diff options
| author | Craig Jennings <c@cjennings.net> | 2026-06-09 06:03:40 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-06-09 06:03:40 -0500 |
| commit | 6b85997cdf879e0e5c31c6c2ae5cb277e1d742d8 (patch) | |
| tree | 3619567dcb1f4754a722da6ff3d01025f57e2893 /todo.org | |
| parent | dd90eca92f8ffc60094c9e956c8730b94956eb33 (diff) | |
| download | dotemacs-6b85997cdf879e0e5c31c6c2ae5cb277e1d742d8.tar.gz dotemacs-6b85997cdf879e0e5c31c6c2ae5cb277e1d742d8.zip | |
chore(todo): close theme-studio refactor (Stages 1-7; 6 skipped optional)
Diffstat (limited to 'todo.org')
| -rw-r--r-- | todo.org | 13 |
1 files changed, 7 insertions, 6 deletions
@@ -176,12 +176,13 @@ Phase 1. Palette anchors + OKLCH shade generation (reusing colormath.js), the RO Phase 2. Initial state from seed() plus seedPkgmap for the non-org packages; all-tier reseed button with a scope-named overwrite warning, resetting non-org to their APPS defaults; regenerate dupre-revised.json. Gate: #selftest PASS; default-on-open equals seed(); artifact round-trip (regenerated dupre-revised.json imports back to the same seeded state); Chrome eyeball. *** TODO Seeding-engine test surface :solo:tests: Keep #seedtest, #selftest, the default-on-open check, the dupre-revised round-trip, node --check, and Chrome validation green. -** DOING [#B] theme-studio refactor — extract app from generate.py :feature:theme-studio:refactor: +** DONE [#B] theme-studio refactor — extract app from generate.py :feature:theme-studio:refactor: +CLOSED: [2026-06-09 Tue] Examined 2026-06-09. generate.py is 1378 lines, ~1300 of them a single triple-quoted string holding the whole app (CSS + HTML + ~1000+ lines of JS). That string is the root of every refactor here: the app logic can't be unit-tested (only =colormath.js= is, because it is the one extracted module); backslash-doubling in the string caused real bugs this session (the multi-line export strip, the =#deltatest= regex); and there is no lint, highlight, or brace-check until Chrome runs it. The rest of the directory is healthy: =colormath.js= (pure, 100/96 tested) and =build-theme.el= (13 small functions) are the model. Run the whole set in NO-APPROVALS mode: TDD per stage (characterization hash tests before each behavior-preserving move; node unit tests as extraction makes logic importable), commit + push at each green stage. Tooling committed at c7518d6f before starting. Order: -PROGRESS (2026-06-09): Stages 1-5 DONE + pushed (origin/main tip 89d079fe). The keystone extraction (app.js / styles.css) and all the dedup (dropdowns, table helpers, sort, clear-unlocked + effFg) are landed, with two new permanent characterization gates added along the way: =#locktest= and =#sorttest=. Remaining: Stage 6 (optional, lower priority — works today) and Stage 7 (the test-surface payoff — make app.js importable and node-unit-test the now-extractable logic; this is a distinct effort, best done fresh). +DONE (2026-06-09): Stages 1-5 + 7 landed and pushed (origin/main tip dd90eca9); Stage 6 deliberately skipped (optional, works today). generate.py went 1378→~500 lines; the app now lives in real files (styles.css, app.js, app-core.js) inlined at generate time. The escaping-bug class is gone (str.replace is literal), the dedup is done (unified dropdowns/sort/clear-unlocked, shared crHtml/mkStyleButtons/effFg helpers), and the pure app logic is unit-tested (app-core.js, 18 node tests). Three new permanent gates added along the way: =#locktest=, =#sorttest=, and the app-core integrity + node suite. =make theme-studio-test= = 13 python + 43 node + spliced-check + 8 hash gates, all green. *** 2026-06-09 Tue @ 05:01:11 -0500 Stage 1 — #locktest net + extracted styles.css/app.js Added the =#locktest= browser gate first (commit d04f44dd): it pins, across all three tiers, that mkLockCell disables a row's control (syntax swatch div via data-locked, UI select via .disabled) and that clear-unlocked wipes unlocked rows while skipping locked ones. Proved it goes red when a lock guard is removed. @@ -200,10 +201,10 @@ Verified behavior-preserving by diffing the runtime-rendered DOM (Stage 2 page v Deleted =srt= + =D{}= (the syntax table's own sort); pointed its headers at =srtTable('legbody',col)= so all three tables share =srtTable=/=cellVal=/=applyTableSort= (commit d947944b). Mapping is exact: the legtable color cell is a swatch dropdown whose =data-val= is the hex (what =srt= sorted on via MAP[kind]); elements cell is text; first-click stays ascending. Syntax sorts on click only — it doesn't opt into the cross-rebuild persistence the UI/pkg tables get, preserving its prior behavior. Added a =#sorttest= gate (sort was untested): syntax sorts by color asc, reverses on re-click, sorts by element name; UI + pkg still sort. asc/desc pair is self-validating. *** 2026-06-09 Tue @ 05:20:22 -0500 Stage 5 — parameterized clear-unlocked + added effFg/effBg Collapsed the three clear-unlocked functions into =clearUnlockedRows(items,keyFn,resetFn)= (keyFn returns a row's lock key or null to skip; resetFn does the tier-specific clear) — #locktest already guards clear-unlocked-skips-locked per tier. Replaced the 9x =||MAP['p']= / =||MAP['bg']= effective-fg/bg fallback with =effFg(v)=/=effBg(v)= across syntax/UI/pkg render paths (commit 89d079fe). Behavior-preserving: rendered DOM (script stripped) byte-identical; all gates green. Node-unit-testing the pure pieces (effFg/effBg, clearUnlockedRows) deferred to Stage 7 with the rest of the importable-app-logic suite. -*** TODO Stage 6 — (optional) namespace state + data-file the bespoke faces :solo: -Group free module-level state (MAP/PALETTE/BOLD/ITALIC/UIMAP/PKGMAP/LOCKED/pkMode/pkModel) into a state object; consider moving the large inline org/magit/elfeed face dicts to json data files like =package-inventory.json=. Lower priority; works today. -*** TODO Stage 7 — test surface :solo:tests: -After extraction, add node unit tests for the now-importable app logic (the coverage payoff): dropdown value/format, lock + clear, row builders, sort, effFg. Keep all hash gates + node tests + python templating tests green via =make theme-studio-test=. +*** 2026-06-09 Tue @ 06:03:04 -0500 Stage 6 — skipped (optional, deferred) +Left undone deliberately. Grouping the free module-level state into a state object is churn with no functional gain (works today), and data-filing the inline face dicts is a generate.py size win unrelated to the refactor's goal (testable logic), which Stage 7 already achieved. Can be revived from this entry + the original plan if the generate.py face dicts ever need to become data. Not blocking anything. +*** 2026-06-09 Tue @ 06:03:04 -0500 Stage 7 — extracted app-core.js + unit-tested the app logic +The coverage payoff. Pulled the pure package-face model + dropdown option list into app-core.js (nameToHex, buildPkgmap, packagesForExport, mergePackagesInto, effResolve, optList — every dep a parameter, no DOM/globals), inlined like colormath.js (strip + placeholder + integrity). app.js keeps thin wrappers (pname/seedPkgmap/ddList/pkgEffFg/pkgEffBg) passing live PALETTE/APPS/PKGMAP, so no call site changed and the built DOM is byte-identical. Added test-app-core.mjs: 18 Normal/Boundary/Error tests (name resolution, seed/export/merge round trip, inherit chain incl. a cycle terminating at null, "(gone)" entry) + inline-integrity. Node suite 25→43; python +1 integrity. Commit dd90eca9. GOTCHA found+fixed pre-commit: a code comment that contained the literal token "APP_CORE_J" got inlined by str.replace too (placeholder tokens must not appear in prose that gets templated). ** TODO [#C] theme-studio terminal/ANSI colors :feature:theme-studio: theme-studio represents GUI faces only; terminal colors aren't surfaced at all. Scope decided 2026-06-09: GUI-first faces, NOT full per-face display-class fallback. Two pieces: |
