diff options
Diffstat (limited to 'scripts/theme-studio/generate.py')
| -rw-r--r-- | scripts/theme-studio/generate.py | 36 |
1 files changed, 28 insertions, 8 deletions
diff --git a/scripts/theme-studio/generate.py b/scripts/theme-studio/generate.py index 0b23bc69..29a2ebac 100644 --- a/scripts/theme-studio/generate.py +++ b/scripts/theme-studio/generate.py @@ -2,15 +2,19 @@ import json, os HERE=os.path.dirname(os.path.abspath(__file__)) def strip_exports(src): - """Drop ES-module `export` lines so the body loads as a classic <script>. + """Drop ES-module `export`/`import` lines so the body loads as a classic <script>. - A top-level `export` is a syntax error outside a module, so it must go before - the body is spliced into the page. test-colormath.mjs applies the identical - strip and asserts the page carries the result verbatim (inline-integrity), so - the two copies cannot drift. NOTE: this is line-based — the export statement in - colormath.js must stay on a single line or the continuation lines survive. + A top-level `export` (or `import`) is a syntax error outside a module, so it + must go before the body is spliced into the page. Imports are stripped too so a + pure module may import a peer for its own unit tests (e.g. app-util.js imports + rl from colormath.js) while the inlined copy relies on the peer already being + in the page. The .mjs inline-integrity tests apply the identical strip and + assert the page carries the result verbatim, so the two copies cannot drift. + NOTE: this is line-based — each export/import statement must stay on a single + line or the continuation lines survive. """ - return '\n'.join(l for l in src.splitlines() if not l.startswith('export')).rstrip() + return '\n'.join(l for l in src.splitlines() + if not (l.startswith('export') or l.startswith('import'))).rstrip() # Pure color-math core, inlined verbatim into the page so the browser runs the # same code the Node tests import (one source of truth). @@ -22,6 +26,13 @@ COLORMATH_BODY=strip_exports(open(os.path.join(HERE,'colormath.js')).read()) # (MAP_J, PALETTE_J, COLORMATH_J, ...); those are filled after it is spliced in. STYLES=open(os.path.join(HERE,'styles.css')).read() APP_BODY=open(os.path.join(HERE,'app.js')).read() +# Pure package-model + dropdown logic, inlined into the page (and unit-tested via +# test-app-core.mjs) the same way colormath.js is. +APP_CORE_BODY=strip_exports(open(os.path.join(HERE,'app-core.js')).read()) +# Pure color/UI-boundary helpers (normHex/ratingColor/textOn), unit-tested via +# test-app-util.mjs. Its `import rl` line is stripped on inline (rl is already in +# the page from the colormath core). +APP_UTIL_BODY=strip_exports(open(os.path.join(HERE,'app-util.js')).read()) ns={} src=open(os.path.join(HERE,'samples.py')).read() exec(src[:src.index('cols=')], ns) @@ -77,8 +88,12 @@ if _seed: if _d.get('ui'): for _k,_v in _d['ui'].items(): UIMAP[_k]=_v if 'locks' in _d: LOCKS=_d['locks'] -# link is underlined by default (matches the built-in link face). +# These faces carry a fixed style in Emacs's built-in definitions (verified with +# emacs -Q), independent of any theme: link / lazy-highlight / show-paren-match +# are underlined; error / warning / success are bold. Seed the defaults to match. UIMAP["link"]["underline"]=True +for _f in ("lazy-highlight","show-paren-match"): UIMAP[_f]["underline"]=True +for _f in ("error","warning","success"): UIMAP[_f]["bold"]=True # Tier-3 package faces (Phase 2): complete own-defface sets for org/magit/elfeed, # built from face-name lists + a curated seed-color map. Prominent faces are # seeded; the long tail seeds to the default foreground for the user to tune. @@ -500,8 +515,13 @@ APP_JS</script>""" # Fill the data placeholders. str.replace is literal (no backref interpretation), # so backslashes in the inlined JS survive intact — the escaping-bug class that # the triple-quoted string used to cause is gone now that app.js is a real file. +# Caveat: these tokens are replaced everywhere they appear, including inside code +# comments. Don't write a placeholder name (COLORMATH_J, APP_CORE_J, ...) in +# prose in any inlined file, or that prose gets the body spliced into it too. def fill_data(s): return (s.replace("COLORMATH_J",COLORMATH_BODY) + .replace("APP_CORE_J",APP_CORE_BODY) + .replace("APP_UTIL_J",APP_UTIL_BODY) .replace("SAMPLES_J",json.dumps(SAMPLES)) .replace("PALETTE_J",json.dumps(PALETTE)).replace("CATS_J",json.dumps(CATS)) .replace("UIFACES_J",json.dumps(UI_FACES)).replace("UIMAP_J",json.dumps(UIMAP)).replace("APPS_J",json.dumps(APPS)) |
