render.gno
2.32 Kb · 63 lines
1package toolbox
2
3import (
4 "strings"
5
6 "gno.land/p/g1magld5ptgzaktqcexxq0pgq5lmdf0kz6re8hlv/kit/ui/v0"
7 "gno.land/p/g1magld5ptgzaktqcexxq0pgq5lmdf0kz6re8hlv/md/v0"
8)
9
10// Index renders a catalog as a markdown table: tool, what it does, tags.
11//
12// Every cell that came from a [Tool] is escaped exactly once, with the helper
13// for the slot it lands in. A tool description is written by whoever wrote the
14// entry, which in a hub that accepts runtime registration is not necessarily
15// whoever owns the hub, and a pipe or a backtick in one would otherwise
16// rewrite the table around it.
17//
18// The title link is built by hand rather than with [md.Link], which is the one
19// place the obvious call is wrong: md.Link runs its text through
20// sanitize.InlineText itself, so md.Link(ui.Cell(title), url) escapes twice and
21// a title with an asterisk in it renders as a backslash. The slot here is link
22// text INSIDE a table cell, and the helper for that is [ui.Cell] (InlineText
23// plus the pipe escape InlineText deliberately leaves alone), with the URL
24// escaped once by [md.EscapeURL].
25func Index(tools []Tool) string {
26 t := ui.NewTable("Tool", "What it does", "Tags")
27 for _, tool := range tools {
28 t.Row(
29 "["+ui.Cell(tool.Title)+"]("+md.EscapeURL(tool.URL())+")",
30 ui.Cell(tool.Desc),
31 ui.Cell(strings.Join(tool.Tags, ", ")),
32 )
33 }
34 return t.OrEmpty("No tools yet.")
35}
36
37// Card renders one tool on its own: the title as a link, the description, the
38// package path, and the two ways to reach it.
39func Card(tool Tool) string {
40 var b strings.Builder
41 b.WriteString(md.H2(ui.Inline(tool.Title)))
42 if tool.Desc != "" {
43 b.WriteString("\n" + ui.Inline(tool.Desc) + "\n")
44 }
45 b.WriteString("\n" + md.BulletList([]string{
46 "Open: " + md.Link(tool.URL(), tool.URL()),
47 "Path: " + md.InlineCode(tool.Path),
48 }))
49 if len(tool.Tags) > 0 {
50 b.WriteString("\nTags: " + ui.Inline(strings.Join(tool.Tags, ", ")) + "\n")
51 }
52 return b.String()
53}
54
55// Nav renders the one line every tool page carries above its content: a link
56// back to the hub, then the tool's own title.
57//
58// hubURL is a gnoweb path ("/r/moul/toolbox"), not a package path. A tool
59// cannot import the hub to ask, so it states it, and this is the one place the
60// two have to agree.
61func Nav(hubURL, title string) string {
62 return md.Link("toolbox", hubURL) + " / " + md.Bold(ui.Inline(title)) + "\n"
63}