aboutsummaryrefslogtreecommitdiff
path: root/scripts/theme-studio/generate.py
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-06-24 14:04:48 -0400
committerCraig Jennings <c@cjennings.net>2026-06-24 14:04:48 -0400
commitc11ad211f5d72b6ee2b48d80f25d16e3e85248eb (patch)
treedd0b3de315e5a84b73e837c964c34020fd26caa4 /scripts/theme-studio/generate.py
parenta9277128cb59372db966b2cc4532bc4573103b38 (diff)
downloaddotemacs-c11ad211f5d72b6ee2b48d80f25d16e3e85248eb.tar.gz
dotemacs-c11ad211f5d72b6ee2b48d80f25d16e3e85248eb.zip
fix(theme-studio): render nerd-icon glyphs in previews instead of tofu
The legend, dashboard, and package previews drew nerd-icon glyphs as empty boxes. The font-family never reached them: PREVIEW_FONT was spliced into inline style="..." attributes with a double-quoted family name, so the inner quote closed the attribute early and the font was silently dropped. Dropping the quotes fixes it. A no-space family name needs none. I embedded the glyph font directly: Symbols Nerd Font Mono, encoded with fontTools (woff2_compress output is rejected by headed Chrome and Firefox), inlined as a data: URI under the unique family name ThemeStudioNerd so it resolves to the embed rather than a system-installed copy of the same name. The page is self-contained and renders on any clone. I added a #fonttest gate that parses previewLines output and asserts the resolved font-family plus glyph coverage, plus a make font target that re-encodes the woff2 with fontTools.
Diffstat (limited to 'scripts/theme-studio/generate.py')
-rw-r--r--scripts/theme-studio/generate.py20
1 files changed, 19 insertions, 1 deletions
diff --git a/scripts/theme-studio/generate.py b/scripts/theme-studio/generate.py
index edfb7e52b..6053aa62f 100644
--- a/scripts/theme-studio/generate.py
+++ b/scripts/theme-studio/generate.py
@@ -1,4 +1,4 @@
-import json, os, re
+import json, os, re, base64
from app_inventory import add_inventory_apps, add_nerd_icons_app, apply_default_face_seeds, apply_package_overrides, face_rows
from default_faces import DefaultFaces
from face_data import *
@@ -68,6 +68,24 @@ COLORMATH_BODY=strip_exports(read_text('colormath.js'))
# template, filled at generate time. app.js carries the data placeholders
# (MAP_J, PALETTE_J, COLORMATH_J, ...); those are filled after it is spliced in.
STYLES=read_text('styles.css')
+# Inline the embedded nerd font as a base64 data: URI. The @font-face in
+# styles.css references the woff2 by a relative path so the source stays editable;
+# here that url is rewritten to a self-contained data: URI at generate time. The
+# payoff is portability — the page renders the glyphs on any clone, with no
+# dependency on a separately-shipped font file or a system-installed copy — and it
+# removes any question about how a file:// font url loads across browsers.
+# (The tofu bug this feature chased was NOT a load failure: the confirmed causes
+# were a double-quoted font-family inside an inline style attribute, which
+# silently dropped the family — see previews.js PREVIEW_FONT — and a woff2 encoded
+# by woff2_compress that headed Chrome/Firefox reject; the woff2 is now encoded by
+# fontTools via `make font`. The data: URI is the durable self-contained form, not
+# the fix for those two bugs.)
+_FONT_WOFF2='SymbolsNerdFontMono-Regular.woff2'
+if os.path.exists(os.path.join(HERE,_FONT_WOFF2)):
+ with open(os.path.join(HERE,_FONT_WOFF2),'rb') as _ff:
+ _FONT_B64=base64.b64encode(_ff.read()).decode('ascii')
+ STYLES=STYLES.replace('url("%s")'%_FONT_WOFF2,
+ 'url("data:font/woff2;base64,%s")'%_FONT_B64)
APP_BODY=read_text('app.js')
# Bespoke per-package preview renderers, spliced into the page <script> via the
# PREVIEWS_J token in app.js. No imports/exports, so read raw.