aboutsummaryrefslogtreecommitdiff
path: root/scripts/theme-studio/app.js
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-06-18 21:42:40 -0500
committerCraig Jennings <c@cjennings.net>2026-06-18 21:42:40 -0500
commit64153c8d995f1603986f3b44ccbdf9ddb21dfd55 (patch)
treeaf836bca12798b2fe8f71cfcd22df3341421d9f0 /scripts/theme-studio/app.js
parentfe196a307877ea69fe4922e49bafa684939d6173 (diff)
downloaddotemacs-64153c8d995f1603986f3b44ccbdf9ddb21dfd55.tar.gz
dotemacs-64153c8d995f1603986f3b44ccbdf9ddb21dfd55.zip
feat(theme-studio): widen the face model with the additive attributes
This is Phase 2 of the face-attribute expansion. The model now carries distant-fg, family, overline, inverse, and extend in final shape across all three tiers, and inherit and height are no longer package-only (a ui or syntax face can set them too). I kept bold/italic/underline/strike as the legacy booleans for now. The cutover to weight/slant and the underline/strike object forms lands in the next phase with the editor widgets that force it, so the representation and the controls that drive it move together. face_specs.py holds the canonical defaults. In app-core.js, normalizePkgFace and packagesForExport carry and emit the new attrs: distant-fg resolves through the palette like fg/bg, and each attr exports only when set, so existing presets re-export unchanged. app.js syntaxBlank, uiFaceBlank, and seedFace match the shape. Nothing changed shape, so dupre, distinguished, sterling, now, theme, and WIP all emit byte-identical themes. make check green: Python 58, Node 193, ERT 40.
Diffstat (limited to 'scripts/theme-studio/app.js')
-rw-r--r--scripts/theme-studio/app.js6
1 files changed, 3 insertions, 3 deletions
diff --git a/scripts/theme-studio/app.js b/scripts/theme-studio/app.js
index 3949268d0..82dccc111 100644
--- a/scripts/theme-studio/app.js
+++ b/scripts/theme-studio/app.js
@@ -4,7 +4,7 @@ let MAP=MAP_J, PALETTE=PALETTE_J, SYNTAX=SYNTAX_J, UIMAP=UIMAP_J;
let LOCKED=new Set(LOCKS_J); // rows whose choice is decided (controls disabled, skipped by erase/reset batch actions)
const DELTAE_MIN=0.02; // OKLab ΔE below this = colors too close to tell apart (perceptual-metrics spec)
const DEFAULT_UIMAP=JSON.parse(JSON.stringify(UIMAP));
-function syntaxBlank(k){return {fg:MAP[k]||null,bg:null,bold:false,italic:false,underline:false,strike:false,box:null};}
+function syntaxBlank(k){return {fg:MAP[k]||null,bg:null,'distant-fg':null,family:null,bold:false,italic:false,underline:false,strike:false,overline:null,box:null,inverse:false,extend:false,inherit:null,height:null};}
function syncSyntaxCache(k){const s=SYNTAX[k]||syntaxBlank(k);MAP[k]=s.fg||'';}
function syncAllSyntaxCache(){CATS.forEach(c=>syncSyntaxCache(c[0]));}
function syncSyntaxFromCache(){CATS.forEach(c=>{const k=c[0];syntaxFace(k).fg=MAP[k]||null;});}
@@ -514,8 +514,8 @@ function buildMockFrame(){
function uiSelect(face,attr){const cur=UIMAP[face][attr]||'';
return mkColorDropdown(ddList(cur),cur,h=>{UIMAP[face][attr]=h||null;paintUI(face);buildMockFrame();},{compact:true,defaultHex:attr==='fg'?effFg(null):effBg(null)});}
const BASE_INHERITS=['fixed-pitch','variable-pitch','default','link','bold','italic','shadow'];
-function uiFaceBlank(){return {fg:null,bg:null,bold:false,italic:false,underline:false,strike:false};}
-function seedFace(d){return normalizePkgFace({fg:pname(d.fg),bg:pname(d.bg),bold:d.bold,italic:d.italic,underline:d.underline,strike:d.strike,inherit:d.inherit,height:d.height,box:d.box},'default');}
+function uiFaceBlank(){return {fg:null,bg:null,'distant-fg':null,family:null,bold:false,italic:false,underline:false,strike:false,overline:null,box:null,inverse:false,extend:false,inherit:null,height:null};}
+function seedFace(d){return normalizePkgFace({fg:pname(d.fg),bg:pname(d.bg),'distant-fg':pname(d['distant-fg']),family:d.family,bold:d.bold,italic:d.italic,underline:d.underline,strike:d.strike,overline:d.overline,inherit:d.inherit,height:d.height,box:d.box,inverse:d.inverse,extend:d.extend},'default');}
function curApp(){const s=document.getElementById('viewsel');const v=s&&s.value;return (v&&v[0]!=='@')?v:Object.keys(APPS)[0];}
function pkgEffFg(app,face,seen){return effResolve(PKGMAP,app,face,'fg',seen);}
function pkgEffBg(app,face,seen){return effResolve(PKGMAP,app,face,'bg',seen);}