carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1// The console's icon set — every piece of interface chrome, one file. This
2// is the server-side twin of Eleven's web/static/icons.js: static, in-code
3// SVG strings in the Lucide idiom (24×24 viewBox, currentColor, stroke, round
4// caps and joins), inlined into the page at render time.
5//
6// Vendored, never a CDN. The console has the same hard constraint as the
7// fleet status page — no build step, no JavaScript framework, and no external
8// request, ever. A <script src> or <link href> at some icon host would be a
9// second origin the console cannot vouch for, cannot cache-control, and
10// cannot serve when it is offline. Inlining the paths is the only option, so
11// the paths live here.
12//
13// Icons are vendored from Lucide — https://lucide.dev — used under the ISC
14// licence:
15//
16// Copyright (c) for portions of Lucide are held by Cole Bemis 2013-2022 as
17// part of Feather (MIT). All other copyright (c) for Lucide are held by
18// Lucide Contributors 2022.
19//
20// Permission to use, copy, modify, and/or distribute this software for any
21// purpose with or without fee is hereby granted, provided that the above
22// copyright notice and this permission notice appear in all copies. THE
23// SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
24// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
25// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
26// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
27// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
28// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
29// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
30//
31// Emoji policy, inherited from Eleven's docs/icons.md: emoji are CONTENT — a
32// mark a person or a model chose, like the footer's factor-X disclosure — and
33// never chrome. Interface furniture uses these icons. Adding one = paste the
34// Lucide SVG's paths in below, keep the (Lucide: <slug>) comment, register it
35// in the icons map, use it as {{icon "<slug>"}}.
36//
37// Each icon carries aria-hidden="true" because every one of them sits beside
38// its own text label — the label is the accessible name, and a second one
39// from the icon would only be read out twice. An icon used as the ONLY label
40// must not use these constants bare: give its button or link an aria-label.
41package console
42
43import "html/template"
44
45// template.HTML is used HERE AND ONLY HERE in the console, and this is why it
46// is safe here and nowhere else: every string in this file is a compile-time
47// constant of our own markup. No user input, no bucket object, no registry
48// row, nothing derived from a request is ever concatenated into one. Anything
49// from those sources must stay a plain string so html/template escapes it —
50// a review in this repo has already flagged template.HTML on bucket-derived
51// text as a Critical finding, and that judgement stands.
52const (
53 iconExternalLink template.HTML = iconOpen + `<path d="M15 3h6v6"/><path d="M10 14 21 3"/><path d="M21 14v5a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5"/></svg>`
54 // iconOpen is the shared opening tag: no width or height, so the icon
55 // sizes from the CSS .icon rule (1em) and tracks the text beside it.
56 iconOpen = `<svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" ` +
57 `stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">`
58
59 // The account switcher's disclosure caret (Lucide: chevron-down).
60 iconChevronDown template.HTML = iconOpen + `<path d="m6 9 6 6 6-6"/></svg>`
61
62 // The switcher menu's mark on the account you are currently in
63 // (Lucide: check).
64 iconCheck template.HTML = iconOpen + `<path d="M20 6 9 17l-5-5"/></svg>`
65
66 // "New account", in the same column the check sits in (Lucide: plus).
67 iconPlus template.HTML = iconOpen + `<path d="M5 12h14"/><path d="M12 5v14"/></svg>`
68
69 // The step between two rungs of the ladder. It points DOWN because the
70 // ladder is drawn the way the spec draws it — canary at the top, stable
71 // at the foot — so the arrow follows the page, not the metaphor
72 // (Lucide: arrow-down).
73 iconArrowDown template.HTML = iconOpen + `<path d="M12 5v14"/><path d="m19 12-7 7-7-7"/></svg>`
74
75 // A route following a canary channel (Lucide: flask-conical).
76 iconFlask template.HTML = iconOpen +
77 `<path d="M14 2v6a2 2 0 0 0 .245.96l5.51 10.08A2 2 0 0 1 18 22H6a2 2 0 0 1-1.755-2.96l5.51-10.08A2 2 0 0 0 10 8V2"/>` +
78 `<path d="M6.453 15h11.094"/><path d="M8.5 2h7"/></svg>`
79
80 // A canary that looks production-wired — the one badge on the app page
81 // that has to stop a reader (Lucide: triangle-alert).
82 iconTriangleAlert template.HTML = iconOpen +
83 `<path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"/>` +
84 `<path d="M12 9v4"/><path d="M12 17h.01"/></svg>`
85
86 // A route's bound environment, beside the rung it is listed under
87 // (Lucide: layers).
88 iconLayers template.HTML = iconOpen +
89 `<path d="m12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83z"/>` +
90 `<path d="m6.08 9.5-3.5 1.6a1 1 0 0 0 0 1.81l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83l-3.5-1.59"/>` +
91 `<path d="m6.08 14.5-3.5 1.6a1 1 0 0 0 0 1.81l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83l-3.5-1.59"/></svg>`
92
93 // A canary/* route whose lease has run out (spec §5 "Canaries expire") —
94 // distinct from iconTriangleAlert's prod-wired warning, because expiry is
95 // a clock running out, not a hazard (Lucide: hourglass).
96 iconHourglass template.HTML = iconOpen +
97 `<path d="M5 22h14"/><path d="M5 2h14"/>` +
98 `<path d="M17 22v-4.172a2 2 0 0 0-.586-1.414L12 12l-4.414 4.414A2 2 0 0 0 7 17.828V22"/>` +
99 `<path d="M7 2v4.172a2 2 0 0 0 .586 1.414L12 12l4.414-4.414A2 2 0 0 0 17 6.172V2"/></svg>`
100
101 // A pointer that arrived by hotfix — the ladder was bypassed, and the
102 // badge is permanent (Lucide: zap).
103 iconZap template.HTML = iconOpen +
104 `<path d="M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z"/></svg>`
105
106 // A pointer whose bake window was waived — fast-tracked, badge equally
107 // permanent (Lucide: fast-forward).
108 iconFastForward template.HTML = iconOpen +
109 `<polygon points="13 19 22 12 13 5 13 19"/>` +
110 `<polygon points="2 19 11 12 2 5 2 19"/></svg>`
111)
112
113// icons maps each Lucide slug to its vendored markup. Slugs are the Lucide
114// names so the mapping back to lucide.dev stays obvious.
115var icons = map[string]template.HTML{
116 "external-link": iconExternalLink,
117 "chevron-down": iconChevronDown,
118 "check": iconCheck,
119 "plus": iconPlus,
120 "arrow-down": iconArrowDown,
121 "flask-conical": iconFlask,
122 "triangle-alert": iconTriangleAlert,
123 "zap": iconZap,
124 "fast-forward": iconFastForward,
125 "layers": iconLayers,
126 "hourglass": iconHourglass,
127}
128
129// icon renders one chrome icon by its Lucide slug: {{icon "chevron-down"}}.
130// An unknown slug renders nothing rather than panicking a page mid-response —
131// a typo must cost a missing caret, not a 500. TestTemplateIconSlugsAllExist
132// is what actually catches the typo, at test time.
133func icon(slug string) template.HTML { return icons[slug] }
134