rastrillo / fiesta Public

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

Plain git — no account needed to clone.

Download

Download this file

1package fiesta
2
3import (
4 "embed"
5 "io/fs"
6 "sort"
7 "strings"
8)
9
10// Version is the design system's own version, the one the release
11// build stamps on fiesta.css and the site serves under /<version>/.
12const Version = "1.2.0"
13
14// tree is the design system's files as shipped: the licence, the CSS,
15// the optional scripts, the icons, the examples and the interface
16// strings. go:embed names directories, so a file added under one is
17// embedded without a change here.
18//
19//go:embed LICENSE css js icons examples i18n
20var tree embed.FS
21
22// FS returns the embedded tree. css/tokens.css, js/busy.js,
23// icons/check.svg and LICENSE are paths in it, so a server can mount
24// it as it is and a build can walk it.
25func FS() fs.FS { return tree }
26
27// read returns one file from the tree. Every path passed here is a
28// file this package embeds by name, so a miss is a broken build rather
29// than a condition to report: the panic says which file.
30func read(path string) []byte {
31 b, err := tree.ReadFile(path)
32 if err != nil {
33 panic("fiesta: " + path + " is not embedded: " + err.Error())
34 }
35 return b
36}
37
38// TokensCSS returns css/tokens.css: the structural stylesheet, every
39// component's layout and behaviour, painted with whichever theme sits
40// beside it.
41func TokensCSS() []byte { return read("css/tokens.css") }
42
43// ShellCSS returns css/shell.css: the two application shells' own
44// rules, which a page links only when it uses a shell.
45func ShellCSS() []byte { return read("css/shell.css") }
46
47// License returns LICENSE, the Mozilla Public License 2.0 the design
48// system ships under. The icons carry Lucide's ISC notice as well, at
49// icons/LICENSE-lucide.txt in FS().
50func License() []byte { return read("LICENSE") }
51
52// themeNames lists the shipped themes, day first: it is the default
53// and the reference theme, the one the other themes' token sets are
54// checked against. The slice matches the files in css/themes/ exactly;
55// adding a theme means adding both.
56//
57// day the everyday default: an ordinary blue on white and grey
58// plain the skeleton: greyscale, system type, almost no shape
59// signal graphite and one live cobalt; milled corners, dense shadows
60var themeNames = []string{"day", "plain", "signal"}
61
62// ThemeNames returns the shipped theme names, day first. The returned
63// slice is a copy, so a caller sorting or truncating it cannot reorder
64// the library's own list.
65func ThemeNames() []string { return append([]string(nil), themeNames...) }
66
67// ThemeCSS returns one theme's bytes, the colour, type-family and
68// shape tokens that tokens.css paints its components with, reporting
69// false for a name that is not shipped.
70func ThemeCSS(name string) ([]byte, bool) {
71 b, err := tree.ReadFile("css/themes/" + name + ".css")
72 return b, err == nil
73}
74
75// scriptNames lists the optional scripts in the order a page that
76// wants them all would load them, deferred: fiesta.js first, since it
77// restores a remembered colour scheme and owns the menus every page
78// has, busy and light next, since they touch every button, the shells'
79// navigation after that, then the snippet's Copy button and the
80// controls, and calendar.js last because it is the grid datetime.js
81// asks it for. transition.js is the one script that is not deferred: a
82// page loads it before its stylesheets, since the browser can reject a
83// skipped transition before a deferred script runs. It is listed
84// beside shell.js because it does shell.js's transition work on a page
85// without a shell. The slice matches the files in js/ exactly.
86var scriptNames = []string{"fiesta.js", "busy.js", "light.js", "anchor.js", "shell.js", "transition.js", "copy.js", "select.js", "datetime.js", "calendar.js"}
87
88// ScriptNames returns the optional scripts' file names, in load order.
89// The returned slice is a copy.
90func ScriptNames() []string { return append([]string(nil), scriptNames...) }
91
92// Script returns one optional script's bytes by its file name,
93// reporting false for a name that is not shipped.
94func Script(name string) ([]byte, bool) {
95 b, err := tree.ReadFile("js/" + name)
96 return b, err == nil
97}
98
99// languageNames lists the shipped languages, en first: one
100// i18n/<lang>.json each, holding the strings datetime.js, select.js
101// and copy.js put on screen. The slice matches the files in i18n/
102// exactly; adding a language means adding both. Plain pt is not a
103// language here: it is a test alias for pt-PT
104// (check/testdata/datetime/retagged.json), kept for a page whose lang
105// still says pt.
106var languageNames = []string{"en", "ar", "bn", "es", "ga", "hi", "ja", "pt-PT", "ru", "vi", "yue", "zh-Hans"}
107
108// Languages returns the shipped languages' tags, en first. The
109// returned slice is a copy.
110func Languages() []string { return append([]string(nil), languageNames...) }
111
112// Strings returns one language's table, i18n/<lang>.json: a flat JSON
113// object whose keys are the string attributes' names with data-rst-
114// removed, plus date-words, the parser's vocabulary. It reports false
115// for a tag that is not shipped; a page's tag is matched to a shipped
116// one by the scripts themselves (fiestaPickLang), not here.
117func Strings(lang string) ([]byte, bool) {
118 b, err := tree.ReadFile("i18n/" + lang + ".json")
119 return b, err == nil
120}
121
122// IconSlugs lists every icon Icon answers, sorted. The names are the
123// design system's own vocabulary, which is Lucide's with five renamed
124// (kebab for ellipsis-vertical; check-circle, alert-triangle, x-circle
125// and help-circle for their Lucide v1 names).
126func IconSlugs() []string {
127 entries, err := tree.ReadDir("icons")
128 if err != nil {
129 panic("fiesta: icons/ is not embedded: " + err.Error())
130 }
131 var out []string
132 for _, e := range entries {
133 if name := e.Name(); strings.HasSuffix(name, ".svg") {
134 out = append(out, strings.TrimSuffix(name, ".svg"))
135 }
136 }
137 sort.Strings(out)
138 return out
139}
140
141// Icon returns one icon by its slug, in the inline form: an <svg> with
142// no xmlns, class="icon", a 24x24 viewBox, currentColor strokes and
143// aria-hidden="true", ready to paste into HTML beside its own visible
144// label. It reports false for a slug that is not shipped.
145func Icon(slug string) ([]byte, bool) {
146 b, err := tree.ReadFile("icons/" + slug + ".svg")
147 return b, err == nil
148}
149