1// Package importdemo shows a realm importing and composing packages from2// ANOTHER namespace — the whole point of the demo.3//4// v2 imported gno.land/p/archive/dom, which is published on no chain we target5// (absent on both sapphire and pearl), so it type-checked locally but could6// never be deployed: `addpkg` failed with7// `could not import gno.land/p/archive/dom (unknown import path)`. v2 is8// archived (`ignore = true`); this version rebuilds the same thread-of-posts9// idea on foreign packages that are actually on chain — `p/nt/avl/v0` for10// ordered storage and `p/nt/ufmt/v0` for formatting.11//12// Deliberately keeps no realm state: Render builds the thread on each call, so13// output depends only on the code and the demo is reproducible.14package importdemo1516import (17 "strconv"18 "strings"1920 "gno.land/p/nt/avl/v0"21 "gno.land/p/nt/ufmt/v0"22)2324// thread is a titled list of posts, kept in an avl.Tree so iteration is ordered25// by key rather than by insertion — the same guarantee the realm needs for a26// stable Render.27type thread struct {28 name string29 posts *avl.Tree // zero-padded index -> *post30 n int31}3233type post struct {34 title string35 body string36}3738func newThread(name string) *thread {39 return &thread{name: name, posts: avl.NewTree()}40}4142// addPost appends a post. The key is zero-padded so avl's lexicographic order43// matches insertion order past 9 entries ("10" would otherwise sort before "9").44func (t *thread) addPost(title, body string) {45 t.posts.Set(padIdx(t.n), &post{title: title, body: body})46 t.n++47}4849// padIdx renders i as a fixed-width, zero-padded key.50//51// Done by hand on purpose: gno's ufmt supports NO width or padding flags, so52// ufmt.Sprintf("%03d", 7) yields "7", not "007" — silently, with no error. Keys53// built that way sort as "0","1","10","11","2", which quietly reorders every54// thread past nine posts (TestOrderSurvivesPastNinePosts covers exactly this).55func padIdx(i int) string {56 s := strconv.Itoa(i)57 for len(s) < 3 {58 s = "0" + s59 }60 return s61}6263// String renders the thread as Markdown.64func (t *thread) String() string {65 var b strings.Builder66 b.WriteString(ufmt.Sprintf("# [thread] %s\n\n", t.name))67 t.posts.Iterate("", "", func(_ string, v any) bool {68 p := v.(*post)69 b.WriteString(ufmt.Sprintf("## %s\n%s\n", p.title, p.body))70 return false71 })72 return b.String()73}7475// Render renders the demo thread for gnoweb.76func Render(path string) string {77 t := newThread("Hello!")78 t.addPost("Foo", "foo foo foo")79 t.addPost("Bar", "bar bar bar")80 return t.String()81}82Render(path string) string
Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.
vm/qrender output, sanitized (docs/render-security.md) and displayed in an empty-sandbox iframe — scripts, forms and popups cannot run. Links stay inert in-preview; right-click to open.