render.gno
3.37 Kb · 103 lines
1package gnotif
2
3import (
4 "chain"
5 "chain/runtime/unsafe"
6 "strconv"
7 "strings"
8
9 "gno.land/p/nt/markdown/sanitize/v0"
10)
11
12const pageSize = 50
13
14// Render serves "" (the first page), "page/N", "trigger/<id>" and
15// "target/<path>".
16func Render(path string) string {
17 switch {
18 case path == "":
19 return renderPage(1)
20 case strings.HasPrefix(path, "page/"):
21 n, err := strconv.Atoi(strings.TrimPrefix(path, "page/"))
22 if err != nil || n < 1 {
23 return "Not found."
24 }
25 return renderPage(n)
26 case strings.HasPrefix(path, "trigger/"):
27 id := strings.TrimPrefix(path, "trigger/")
28 v := triggers.Get(id)
29 if v == nil {
30 return "Not found."
31 }
32 return renderTrigger(id, decodeRecord(v))
33 case strings.HasPrefix(path, "target/"):
34 target := strings.TrimPrefix(path, "target/")
35 ids := activeOf(target)
36 if len(ids) == 0 {
37 return "Not found."
38 }
39 return renderTarget(target, ids)
40 }
41 return "Not found."
42}
43
44// renderPage lists the triggers newest first, pageSize to a page.
45func renderPage(n int) string {
46 var b strings.Builder
47 b.WriteString("# gnotif triggers\n\n")
48 pages := (triggers.Size() + pageSize - 1) / pageSize
49 if n > pages {
50 b.WriteString("No triggers on this page.\n")
51 return b.String()
52 }
53 triggers.ReverseIterateByOffset((n-1)*pageSize, pageSize, func(id string, v any) bool {
54 writeLine(&b, id, decodeRecord(v))
55 return false
56 })
57 if n < pages {
58 b.WriteString("\n[Next page](" + selfPath + ":page/" + strconv.Itoa(n+1) + ")\n")
59 }
60 return b.String()
61}
62
63// renderTarget lists a realm's triggers, newest first. The cap on them keeps
64// the page to one screen, so it is not paged.
65func renderTarget(target string, ids []string) string {
66 var b strings.Builder
67 b.WriteString("# gnotif triggers for " + sanitize.InlineText(target) + "\n\n")
68 for i := len(ids) - 1; i >= 0; i-- {
69 writeLine(&b, ids[i], decodeRecord(triggers.Get(ids[i])))
70 }
71 b.WriteString("\n[All triggers](" + selfPath + ")\n")
72 return b.String()
73}
74
75func writeLine(b *strings.Builder, id string, r record) {
76 b.WriteString("- [**" + id + "**](" + selfPath + ":trigger/" + id + ") " +
77 sanitize.InlineText(r.Target) + " · " + sanitize.InlineText(r.Name) + " · " + sanitize.InlineText(r.T.Event))
78 if r.T.Param != "" {
79 b.WriteString(" · param " + sanitize.InlineText(r.T.Param))
80 }
81 b.WriteString(" · ✓ verified · by " + chain.PackageAddress(r.Target).String() + "\n")
82}
83
84func renderTrigger(id string, r record) string {
85 var b strings.Builder
86 b.WriteString("# Trigger " + id + "\n\n")
87 b.WriteString("- Target: " + sanitize.InlineText(r.Target) + "\n")
88 b.WriteString("- Name: " + sanitize.InlineText(r.Name) + "\n")
89 b.WriteString("- Event: " + sanitize.InlineText(r.T.Event) + "\n")
90 b.WriteString("- Filter: " + sanitize.InlineText(r.T.Filter) + "\n")
91 b.WriteString("- Param: " + sanitize.InlineText(r.T.Param) + "\n")
92 b.WriteString("- Title: " + sanitize.InlineText(r.T.Title) + "\n")
93 b.WriteString("- Body: " + sanitize.InlineText(r.T.Body) + "\n")
94 b.WriteString("- Link: " + sanitize.InlineText(r.T.Link) + "\n")
95 b.WriteString("- Declarer: " + chain.PackageAddress(r.Target).String() + "\n")
96 b.WriteString("- ✓ verified\n")
97 b.WriteString("\n[All triggers](" + selfPath + ")\n")
98 return b.String()
99}
100
101// selfPath is this realm's path on gnoweb, read at package init: Render is not
102// crossing, so reading it there would give the caller's path.
103var selfPath = strings.TrimPrefix(unsafe.CurrentRealm().PkgPath(), "gno.land")