debug.gno

2.84 Kb ยท 92 lines
 1// Package debug provides utilities for logging and displaying debug information
 2// within Gno realms. It supports conditional rendering of logs and metadata,
 3// toggleable via query parameters.
 4//
 5// Key Features:
 6// - Log collection and display using Markdown formatting.
 7// - Metadata display for realm path, address, and height.
 8// - Collapsible debug section for cleaner presentation.
 9// - Query-based debug toggle using `?debug=1`.
10package debug
11
12import (
13	"std"
14	"time"
15
16	"gno.land/p/demo/ufmt"
17	"gno.land/p/moul/md"
18	"gno.land/p/moul/mdtable"
19	"gno.land/p/moul/realmpath"
20)
21
22// Debug encapsulates debug information, including logs and metadata.
23type Debug struct {
24	Logs         []string
25	HideMetadata bool
26}
27
28// Log appends a new line of debug information to the Logs slice.
29func (d *Debug) Log(line string) {
30	d.Logs = append(d.Logs, line)
31}
32
33// Render generates the debug content as a collapsible Markdown section.
34// It conditionally renders logs and metadata if enabled via the `?debug=1` query parameter.
35func (d Debug) Render(path string) string {
36	if realmpath.Parse(path).Query.Get("debug") != "1" {
37		return ""
38	}
39
40	var content string
41
42	if d.Logs != nil {
43		content += md.H3("Logs")
44		content += md.BulletList(d.Logs)
45	}
46
47	if !d.HideMetadata {
48		content += md.H3("Metadata")
49		table := mdtable.Table{
50			Headers: []string{"Key", "Value"},
51		}
52		table.Append([]string{"`std.CurrentRealm().PkgPath()`", string(std.CurrentRealm().PkgPath())})
53		table.Append([]string{"`std.CurrentRealm().Address()`", string(std.CurrentRealm().Address())})
54		table.Append([]string{"`std.PreviousRealm().PkgPath()`", string(std.PreviousRealm().PkgPath())})
55		table.Append([]string{"`std.PreviousRealm().Address()`", string(std.PreviousRealm().Address())})
56		table.Append([]string{"`std.ChainHeight()`", ufmt.Sprintf("%d", std.ChainHeight())})
57		table.Append([]string{"`time.Now().Format(time.RFC3339)`", time.Now().Format(time.RFC3339)})
58		content += table.String()
59	}
60
61	if content == "" {
62		return ""
63	}
64
65	return md.CollapsibleSection("debug", content)
66}
67
68// Render displays metadata about the current realm but does not display logs.
69// This function uses a default Debug struct with metadata enabled and no logs.
70func Render(path string) string {
71	return Debug{}.Render(path)
72}
73
74// IsEnabled checks if the `?debug=1` query parameter is set in the given path.
75// Returns true if debugging is enabled, otherwise false.
76func IsEnabled(path string) bool {
77	req := realmpath.Parse(path)
78	return req.Query.Get("debug") == "1"
79}
80
81// ToggleURL modifies the given path's query string to toggle the `?debug=1` parameter.
82// If debugging is currently enabled, it removes the parameter.
83// If debugging is disabled, it adds the parameter.
84func ToggleURL(path string) string {
85	req := realmpath.Parse(path)
86	if IsEnabled(path) {
87		req.Query.Del("debug")
88	} else {
89		req.Query.Add("debug", "1")
90	}
91	return req.String()
92}