Skip to content Search Apps Documentation Source Content File Folder Download Copy Actions State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

Community realm. Read the code first. Community realm, deployed by its author. Read the code before you interact or send coins.

render.gno

1.85 Kb · 73 lines
 1package memba_appstore_v3
 2
 3import (
 4	"chain/runtime"
 5
 6	"gno.land/p/nt/ufmt/v0"
 7)
 8
 9// RenderMaxRows bounds the Render() output so a large catalog can never make the
10// realm render-DoS (mirrors the feed's live-only bounded render).
11const RenderMaxRows = 100
12
13// Render shows the live catalog (bounded) — a read-only trust surface for gnoweb.
14// The frontend reads structured data via the getters, not this markdown.
15func Render(path string) string {
16	sb := ""
17	sb += "# Memba App Store\n\n"
18	sb += ufmt.Sprintf("Curated gno.land dApps. **Listing fee:** %d ugnot → treasury.\n\n", registrationFee)
19	if paused {
20		sb += "> ⏸️ Registration is paused.\n\n"
21	}
22
23	rows := 0
24	live := 0
25	sb += "| App | Package | Category |\n|---|---|---|\n"
26	listings.Iterate("", "", func(_ string, v any) bool {
27		l := v.(*Listing)
28		// Curated gnoweb view: live (Verified) + un-flag-hidden only — never pending/rejected.
29		if l.Status != StatusLive || l.FlagCount >= FlagHideThreshold {
30			return false
31		}
32		live++
33		if rows >= RenderMaxRows {
34			return false // stop appending, keep counting via the header below
35		}
36		rows++
37		sb += ufmt.Sprintf("| %s | `%s` | %s |\n", esc(l.Name), esc(l.PkgPath), esc(l.Category))
38		return false
39	})
40
41	if live == 0 {
42		sb += "\n*No live apps yet.*\n"
43	} else {
44		sb += ufmt.Sprintf("\n*%d live app(s)%s. Block %d.*\n", live, moreNote(live), runtime.ChainHeight())
45	}
46	return sb
47}
48
49func moreNote(live int) string {
50	if live > RenderMaxRows {
51		return ufmt.Sprintf(" (showing first %d)", RenderMaxRows)
52	}
53	return ""
54}
55
56// esc neutralizes the markdown/table metachars that could break the table or inject
57// layout from an attacker-supplied listing field.
58func esc(s string) string {
59	out := ""
60	for _, r := range s {
61		switch r {
62		case '|':
63			out += "\\|"
64		case '\n', '\r':
65			out += " "
66		case '`':
67			out += "'"
68		default:
69			out += string(r)
70		}
71	}
72	return out
73}