git-ents.gitmain
⌘K
foforge
assets.rs135 lines · 5.5 KB · rusthistorycomment on this file
1//! Static assets embedded at compile time so the built binary stays
2//! self-contained -- no runtime fetch, no separate asset bundle to ship
3//! alongside `git-ents`. `ents.css` is the hand-rolled workbench
4//! stylesheet, keyed to the design handoff's tokens and component specs;
5//! its `@font-face` rules load the [`FONTS`] IBM Plex faces this crate
6//! serves itself (`GET /fonts/{name}`) rather than fetching them from
7//! Google Fonts, so the design's exact type ships without a network
8//! dependency. `ents.js` is new to this crate
9//! (pre-redo had no client-side script at all): a vanilla,
10//! dependency-free progressive enhancement over `crate::pages::files`'s
11//! raw-source blob view -- click-to-select a line or range and an inline
12//! comment composer -- served alongside `ents.css` the same way, via
13//! `crate::router`'s own `GET /ents.js` route.
14//!
15//! The icon functions below are vendored Octicons (`.gitvendors`, MIT; see
16//! `assets/icons/LICENSE`), re-homed here from
17//! `pre-redo:crates/git-ents-server/src/web/icons/` for
18//! [`crate::pages::files`]'s directory listing and breadcrumbs -- the same
19//! `include_str!`-and-tag pattern
20//! `pre-redo:crates/git-ents-server/src/web/icons.rs` used. The workbench
21//! shell's own chrome (the `.rail` page-family icons, the `.palette`
22//! search glass, the `.branch` pill, the `.editor-open` pill's `↗` mark)
23//! draws from [`sprite`] instead: one hand-rolled `<symbol>` sprite
24//! embedded per page by `crate::pages::layout`, each use site a tiny
25//! [`icon_use`] reference rather than a repeated inline SVG. Every sprite
26//! symbol is an original drawing in the design handoff's 24×24 stroke style
27//! (`stroke-width: 1.7`, round caps), never a vendored asset, so no
28//! third-party icon license applies to the sprite; the Octicons under
29//! `assets/icons/` remain this module's only third-party assets.
30
31use std::sync::LazyLock;
32
33use maud::{Markup, PreEscaped};
34
35pub(crate) const OVERRIDES: &str = include_str!("assets/ents.css");
36
37/// The client-side line-selection/comment-composer script
38/// [`crate::router`]'s `GET /ents.js` serves -- see this module's own doc.
39pub(crate) const SCRIPT: &str = include_str!("assets/ents.js");
40
41/// The self-hosted IBM Plex webfonts the workbench renders in
42/// (`assets/fonts/`, SIL OFL, see `assets/fonts/LICENSE`), embedded so the
43/// design's exact type is served without a runtime Google Fonts fetch --
44/// the same "self-contained binary, no network dependency" rule
45/// [`OVERRIDES`] and the vendored Octicons already hold. `ents.css`'s
46/// `@font-face` rules name each by its `GET /fonts/{name}` URL; [`font`]
47/// resolves that name back to these bytes.
48pub(crate) const FONTS: &[(&str, &[u8])] = &[
49 (
50 "plex-sans-400.woff2",
51 include_bytes!("assets/fonts/plex-sans-400.woff2"),
52 ),
53 (
54 "plex-sans-500.woff2",
55 include_bytes!("assets/fonts/plex-sans-500.woff2"),
56 ),
57 (
58 "plex-sans-600.woff2",
59 include_bytes!("assets/fonts/plex-sans-600.woff2"),
60 ),
61 (
62 "plex-sans-700.woff2",
63 include_bytes!("assets/fonts/plex-sans-700.woff2"),
64 ),
65 (
66 "plex-mono-400.woff2",
67 include_bytes!("assets/fonts/plex-mono-400.woff2"),
68 ),
69 (
70 "plex-mono-500.woff2",
71 include_bytes!("assets/fonts/plex-mono-500.woff2"),
72 ),
73 (
74 "plex-mono-600.woff2",
75 include_bytes!("assets/fonts/plex-mono-600.woff2"),
76 ),
77];
78
79/// The embedded woff2 bytes for `name`, or `None` for a name no
80/// `@font-face` rule references -- [`crate::router`]'s `GET /fonts/{name}`
81/// handler serves the hit and 404s the miss, so an unknown path can never
82/// read outside this fixed table.
83pub(crate) fn font(name: &str) -> Option<&'static [u8]> {
84 FONTS
85 .iter()
86 .find(|(file, _)| *file == name)
87 .map(|(_, bytes)| *bytes)
88}
89
90/// Adapt a vendored Octicon to this UI: tag it with the `.icon` class the
91/// stylesheet targets and mark it decorative for assistive tech. Every
92/// vendored file opens with a bare `<svg …>` element, so a single prefix
93/// swap suffices (mirrors
94/// `pre-redo:crates/git-ents-server/src/web/icons.rs`'s own `inline`).
95fn inline(svg: &str) -> String {
96 svg.replacen("<svg ", "<svg class=\"icon\" aria-hidden=\"true\" ", 1)
97}
98
99/// Define an icon accessor per vendored Octicon file. Each prepares its
100/// inline markup once and hands out a cheap clone on use.
101macro_rules! icons {
102 ($($name:ident => $file:literal),* $(,)?) => {
103 $(
104 pub(crate) fn $name() -> Markup {
105 static HTML: LazyLock<String> =
106 LazyLock::new(|| inline(include_str!(concat!("assets/icons/", $file, ".svg"))));
107 PreEscaped(HTML.clone())
108 }
109 )*
110 };
111}
112
113icons! {
114 icon_folder => "file-directory-fill",
115 icon_file => "file",
116 icon_chevron => "chevron-right",
117}
118
119/// The workbench shell's inline `<symbol>` sprite (see this module's own
120/// doc) -- embedded once per page, right after `<body>`, so every
121/// [`icon_use`] reference on the page resolves against it.
122pub(crate) fn sprite() -> Markup {
123 PreEscaped(include_str!("assets/sprite.svg").to_owned())
124}
125
126/// An `.icon`-classed, decorative `<use>` reference into [`sprite`] --
127/// `id` names one of its `<symbol>`s (`i-home`, `i-files`, ...). Sized
128/// entirely by the use site's own CSS rule (`.rail a .icon`,
129/// `.palette .icon`, `.branch .icon`), since a symbol carries only a
130/// viewBox.
131pub(crate) fn icon_use(id: &str) -> Markup {
132 PreEscaped(format!(
133 "<svg class=\"icon\" aria-hidden=\"true\"><use href=\"#{id}\"/></svg>"
134 ))
135}