ishou_render/lib.rs
1//! ishou-render — target-specific renderers from `ishou_tokens::TokenSet`.
2//!
3//! Every renderer is a pure function: `TokenSet → String`. Determinism is a
4//! test invariant — same tokens produce byte-identical output.
5//!
6//! Morphism table (identical in spirit to arch-synthesizer's morphism graph):
7//!
8//! | Source | Target | Module |
9//! |----------------|----------------------------------------|--------------|
10//! | `TokenSet` | CSS custom properties + utility classes | `css` |
11//! | `TokenSet` | tailwind.config.js | `tailwind` |
12//! | `TokenSet` | SCSS variables | `scss` |
13//! | `TokenSet` | Rust `pub const` module | `rust` |
14//! | `TokenSet` | W3C Design Tokens JSON | `json` |
15//! | `TokenSet` | GLSL `#define` header | `glsl` |
16//! | `TokenSet` | Ghostty config block | `ghostty` |
17//! | `TokenSet` | TUI ratatui / crossterm Color table | `tui` |
18//! | `TokenSet` | SVG (brand mark + swerve) | `svg` |
19//! | `TokenSet` | stylix base16 YAML | `stylix` |
20//! | `TokenSet` | base16 bat `.tmTheme` (Sublime plist) | `bat` |
21
22pub mod base16_nix;
23pub mod bat;
24pub mod css;
25pub mod fleet_fonts;
26pub mod ghostty;
27pub mod glsl;
28pub mod greys;
29pub mod json;
30pub mod md3;
31pub mod mono;
32pub mod nix;
33pub mod nix_ast;
34pub mod rust;
35pub mod scss;
36pub mod stylix;
37pub mod stylix_fonts;
38pub mod svg;
39pub mod tailwind;
40pub mod tui;
41pub mod vellum;
42
43/// Every renderable target ishou-cli understands. The string here matches the
44/// CLI flag users type (`ishou render --target css`).
45#[derive(Debug, Clone, Copy, PartialEq, Eq)]
46pub enum Target {
47 Css,
48 /// Material Design 3 system colors (`--md-sys-color-*`) mapped from the
49 /// TokenSet — the target Material consumers (`pleme-mui`) bind to so they
50 /// can consume ishou instead of forking a hard-coded MD3 palette.
51 Md3,
52 Tailwind,
53 Scss,
54 Rust,
55 Json,
56 Glsl,
57 Ghostty,
58 Tui,
59 Svg,
60 Stylix,
61 /// base16 bat `.tmTheme` (Sublime-Text XML plist) — the FIRST per-app
62 /// *config-file* target. bat consumes it as a custom theme; this is the
63 /// M0 proof ishou can natively emit a per-app config file (toward ishou
64 /// replacing stylix as the fleet theming engine). Same base16 slot→Nord
65 /// mapping as `Stylix`.
66 Bat,
67 Nix,
68 StylixFonts,
69 /// Fleet-fonts attrset — `{ primary, italic, bold, symbols, emoji,
70 /// fallback_chain }` consumed directly by every pleme-io GPU app
71 /// HM module (mado, blackmatter-ghostty, fumi, kagi, …) to name
72 /// the canonical family AND install the underlying nixpkgs
73 /// package via `home.packages`. Sibling of `StylixFonts` — same
74 /// typed Typography source, different consumer-side shape.
75 FleetFonts,
76 /// Vellum base16 stylix scheme YAML (the prescribed fleet theme).
77 /// Sourced from the BORN `VellumPalette`, not the Nord `TokenSet`.
78 StylixVellum,
79 /// Vellum base16 as a PARSED Nix attrset — the IFD-free form.
80 ///
81 /// Sibling of `StylixVellum` (same palette) and of `StylixFonts` (same
82 /// consumer, same reason). stylix reads a `{ yaml = <drv>; }` via
83 /// `readFile`, which is an import-from-derivation: it forces a build
84 /// during evaluation, and for NixOS consumers that build is a linux
85 /// one — so a Mac cannot evaluate any node. A literal attrset takes
86 /// stylix's already-parsed branch and costs nothing.
87 StylixVellumNix,
88 /// Nord base16 as an already-parsed Nix attrset — the IFD-free shape.
89 StylixNordNix,
90 /// Mono, as an already-parsed Nix attrset.
91 StylixMonoNix,
92 /// Greys, as an already-parsed Nix attrset.
93 StylixGreysNix,
94 /// Vellum base24 stylix scheme YAML — base16 + the real two-tier
95 /// brights (base10–17).
96 StylixVellumBase24,
97 /// Vellum palette preview SVG — one labelled chip per BORN token.
98 SvgVellumPalette,
99 /// Vellum skim/fzf `--color=k:v,…` string, generated from the BORN
100 /// `VellumPalette`. Byte-equal to `skim-tab::VELLUM_COLORS` — the
101 /// SAVED branch, not the live picker theme (skim-tab paints
102 /// `NORD_COLORS`, and has no ishou dependency). See
103 /// `vellum::render_skim` for the full relationship + the destination.
104 SkimVellum,
105 /// Vellum escriba theme `*.lisp` — `(deftheme)` + `(defpalette)` +
106 /// `(defhighlight …)` over escriba's `CANONICAL_GROUPS`, sourced from
107 /// the BORN `VellumPalette`. Mirrors `escriba/configs/vellum.lisp`.
108 EscribaVellum,
109}
110
111impl Target {
112 pub fn from_str(s: &str) -> Option<Self> {
113 Some(match s {
114 "css" => Self::Css,
115 "md3" | "material" | "md-sys-color" => Self::Md3,
116 "tailwind" => Self::Tailwind,
117 "scss" => Self::Scss,
118 "rust" => Self::Rust,
119 "json" => Self::Json,
120 "glsl" => Self::Glsl,
121 "ghostty" => Self::Ghostty,
122 "tui" => Self::Tui,
123 "svg" => Self::Svg,
124 "stylix" | "stylix-base16" => Self::Stylix,
125 "bat" | "bat-tmtheme" => Self::Bat,
126 "stylix-fonts" | "fonts-nix" => Self::StylixFonts,
127 "nix" | "nord-palette-nix" => Self::Nix,
128 "fleet-fonts" | "fleet_fonts" => Self::FleetFonts,
129 "stylix-vellum" | "stylix-base16-vellum" => Self::StylixVellum,
130 "stylix-vellum-nix" | "stylix-base16-vellum-nix" => Self::StylixVellumNix,
131 "stylix-nord-nix" | "stylix-base16-nord-nix" => Self::StylixNordNix,
132 "stylix-mono-nix" => Self::StylixMonoNix,
133 "stylix-greys-nix" => Self::StylixGreysNix,
134 "stylix-vellum-base24" | "stylix-base24-vellum" => Self::StylixVellumBase24,
135 "svg-vellum-palette" | "vellum-palette" => Self::SvgVellumPalette,
136 "skim-vellum" | "skim" => Self::SkimVellum,
137 "escriba-vellum" | "escriba" => Self::EscribaVellum,
138 _ => return None,
139 })
140 }
141
142 pub fn render(&self, tokens: &ishou_tokens::TokenSet) -> String {
143 match self {
144 Self::Css => css::render(tokens),
145 Self::Md3 => md3::render(tokens),
146 Self::Tailwind => tailwind::render(tokens),
147 Self::Scss => scss::render(tokens),
148 Self::Rust => rust::render(tokens),
149 Self::Json => json::render(tokens),
150 Self::Glsl => glsl::render(tokens),
151 Self::Ghostty => ghostty::render(tokens),
152 Self::Tui => tui::render(tokens),
153 Self::Svg => svg::render(tokens),
154 Self::Stylix => stylix::render(tokens),
155 Self::Bat => bat::render(tokens),
156 Self::Nix => nix::render(tokens),
157 Self::StylixFonts => stylix_fonts::render(tokens),
158 Self::StylixVellumNix => vellum::render_base16_nix(),
159 Self::StylixNordNix => stylix::render_nix(tokens),
160 Self::StylixMonoNix => mono::render_base16_nix(),
161 Self::StylixGreysNix => greys::render_base16_nix(),
162 Self::FleetFonts => fleet_fonts::render(tokens),
163 // Vellum targets are their own BORN source — the Nord
164 // `TokenSet` argument is unused.
165 Self::StylixVellum => vellum::render_base16(),
166 Self::StylixVellumBase24 => vellum::render_base24(),
167 Self::SvgVellumPalette => vellum::render_svg_palette(),
168 Self::SkimVellum => vellum::render_skim(),
169 Self::EscribaVellum => vellum::render_escriba_lisp(),
170 }
171 }
172
173 pub fn all() -> [Target; 24] {
174 [
175 Self::Css,
176 Self::Md3,
177 Self::Tailwind,
178 Self::Scss,
179 Self::Rust,
180 Self::Json,
181 Self::Glsl,
182 Self::Ghostty,
183 Self::Tui,
184 Self::Svg,
185 Self::Stylix,
186 Self::Bat,
187 Self::Nix,
188 Self::StylixFonts,
189 Self::FleetFonts,
190 Self::StylixVellum,
191 Self::StylixVellumNix,
192 Self::StylixNordNix,
193 Self::StylixMonoNix,
194 Self::StylixGreysNix,
195 Self::StylixVellumBase24,
196 Self::SvgVellumPalette,
197 Self::SkimVellum,
198 Self::EscribaVellum,
199 ]
200 }
201}