rastrillo / fiesta Public

Clone
git clone https://amadan.net/rastrillo/fiesta

Plain git — no account needed to clone.

Download

Download this file

1package gallery
2
3import (
4 "fmt"
5 "html/template"
6 "strings"
7)
8
9// The Icons page: one chip per icon, drawn the way a component draws
10// it, with its slug, the file to copy and where the glyph comes from.
11// Nothing in this file names an icon or counts them: the chips are
12// s.icons, read off icons/*.svg, and both numbers in the sentence
13// under the grid are counted from the set. The one list here is the
14// names Fiesta gives glyphs that Lucide names otherwise.
15
16// lucideHome is the one address in this tree that is not in this tree:
17// where the glyphs come from, and where a reader goes to see the rest
18// of the set. outboundLinks is the gate's side of the same decision.
19const lucideHome = "https://lucide.dev"
20
21// lucideNames is Fiesta's slug to the name lucide.dev publishes, for
22// the slugs where the two differ; every other slug is Lucide's own
23// name. Each was checked at lucide.dev/icons/<name> on 2026-10-29.
24// help-circle's published name is circle-question-mark: the address
25// lucide.dev/icons/circle-help now lands on that page.
26var lucideNames = map[string]string{
27 "kebab": "ellipsis-vertical",
28 "alert-triangle": "triangle-alert",
29 "check-circle": "circle-check",
30 "help-circle": "circle-question-mark",
31 "x-circle": "circle-x",
32}
33
34// outboundLinks is the whole list of addresses the tree may point at
35// that are not in it, each with the reason it is there. The table is
36// exact strings, not prefixes, and every entry has to be linked by some
37// page; TestEveryOutboundLinkIsAllowedAndUsed holds both halves, so it
38// cannot become a licence for the next link somebody feels like adding.
39var outboundLinks = map[string]string{
40 lucideHome: "where the glyphs come from: the set the icons are copied from, under the ISC licence, and the only place a reader can see the rest of it",
41}
42
43// lucideName is what lucide.dev calls the icon Fiesta calls slug.
44func lucideName(slug string) string {
45 if name, ok := lucideNames[slug]; ok {
46 return name
47 }
48 return slug
49}
50
51// iconView is one chip: its anchor, its slug, the glyph, and its
52// provenance, an address rather than a sentence (lucide.dev/icons/…)
53// so it needs no translation and a reader can type it.
54type iconView struct {
55 ID, Slug, Provenance string
56 Markup template.HTML
57}
58
59// iconsView is the page's data. Total and Renamed are counted from
60// the set rather than written into the sentence, so the sentence
61// cannot be wrong about the set it describes. Lucide is the line that
62// links the set, with the link in it.
63type iconsView struct {
64 List []iconView
65 Total, Renamed string
66 Lucide template.HTML
67}
68
69// buildIcons reads the set for one locale's page.
70func (s *site) buildIcons(locale string) iconsView {
71 out := iconsView{Total: fmt.Sprint(len(s.icons))}
72 renamed := 0
73 for _, ic := range s.icons {
74 name := lucideName(ic.Slug)
75 if name != ic.Slug {
76 renamed++
77 }
78 out.List = append(out.List, iconView{
79 ID: anchorID("icon", ic.Slug),
80 Slug: ic.Slug,
81 Provenance: "lucide.dev/icons/" + name,
82 Markup: ic.Markup,
83 })
84 }
85 out.Renamed = fmt.Sprint(renamed)
86 link := `<a href="` + lucideHome + `" target="_blank" rel="noopener">lucide.dev<span class="rst-sr-only"> (` +
87 template.HTMLEscapeString(s.say(locale, "gallery.newtab")) + `)</span></a>`
88 out.Lucide = template.HTML(strings.Replace(template.HTMLEscapeString(s.say(locale, "gallery.icons.lucide")), "{link}", link, 1))
89 return out
90}
91
92// iconsBody is every slug, drawn at the size tokens.css gives .icon,
93// each with its file and its lucide.dev address; then the names that
94// are Fiesta's own, with the count; then where the glyphs come from,
95// with the one link that leaves the tree.
96const iconsBody = `{{define "ds-body-icons"}}<p class="ds-lead">{{say "gallery.icons.lead" "total" .Icons.Total}}</p>
97<ul class="ds-toks ds-icons">{{range .Icons.List}}
98<li class="ds-tok" id="{{.ID}}" data-ds-anchor><span class="ds-chip ds-chip--icon">{{.Markup}}</span><span class="ds-tok__text rst-mono"><span class="ds-tok__name">{{.Slug}}</span><span class="ds-tok__value">icons/{{.Slug}}.svg</span><span class="ds-tok__value">{{.Provenance}}</span></span></li>{{end}}
99</ul>
100
101<h2 class="ds-sub">{{say "gallery.icons.names.heading"}}</h2>
102<p class="ds-lead">{{say "gallery.icons.names.body" "renamed" .Icons.Renamed "total" .Icons.Total}}</p>
103<p class="ds-note">{{say "gallery.icons.kebab"}}</p>
104
105<h2 class="ds-sub">{{say "gallery.icons.source"}}</h2>
106<p class="ds-lead">{{say "gallery.icons.source.body"}}</p>
107<p class="ds-note">{{.Icons.Lucide}}</p>
108{{end}}`
109
110// iconsBody renders the Icons page's body for p.
111func (s *site) iconsBody(p page) (template.HTML, error) {
112 return s.body(p.Locale, "ds-body-icons", struct {
113 page
114 Icons iconsView
115 }{p, s.buildIcons(p.Locale)})
116}
117
118// iconMarkup is one of Fiesta's icons, inline, for the gallery's own
119// furniture; the icon template func.
120func (s *site) iconMarkup(slug string) template.HTML {
121 for _, ic := range s.icons {
122 if ic.Slug == slug {
123 return ic.Markup
124 }
125 }
126 return ""
127}
128
129func init() { registerTemplate(iconsBody) }
130