aboutsummaryrefslogtreecommitdiff
path: root/scripts/theme-studio/previews.js
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-06-23 19:34:01 -0400
committerCraig Jennings <c@cjennings.net>2026-06-23 19:34:01 -0400
commitc5ca8b7d7ac1aa751c1bf79ad35b178f96b3ba77 (patch)
tree06a771c8b21eb9b05ede74dd63fd475bdd4dbd60 /scripts/theme-studio/previews.js
parent558723421f320d00a1d9c7704cae567a00e17310 (diff)
downloaddotemacs-c5ca8b7d7ac1aa751c1bf79ad35b178f96b3ba77.tar.gz
dotemacs-c5ca8b7d7ac1aa751c1bf79ad35b178f96b3ba77.zip
feat(theme-studio): locate preview elements by hover and click
Hovering a data-face preview element shows its section, face, and effective value in the preview-label info line, and the element's title carries the full record: effective fg/bg plus a per-attribute source note (direct, inherited-from-X, default, or cleared-rendering-as-default). Clicking an on-pane element scrolls to and flashes its assignment row. Off-pane and cross-surface elements stay hover-only. A single owner-qualified registry keyed by {owner, face} backs both data-face surfaces, package and UI, so the same face name under two owners never collides. The pure helpers in app-core.js take all state as arguments and return data. The one stateful adapter, previewSpan, lives in previews.js and emits the escaped markup. os() stays a package-owner wrapper over previewSpan, and a unified locateClick dispatcher replaces the per-surface click branches. Covered by test-locate.mjs and four new browser gates. Full harness green.
Diffstat (limited to 'scripts/theme-studio/previews.js')
-rw-r--r--scripts/theme-studio/previews.js22
1 files changed, 21 insertions, 1 deletions
diff --git a/scripts/theme-studio/previews.js b/scripts/theme-studio/previews.js
index bef8b7c12..cb9d5babe 100644
--- a/scripts/theme-studio/previews.js
+++ b/scripts/theme-studio/previews.js
@@ -3,7 +3,27 @@
// they reference shared globals (PKGMAP, MAP, faceCss, effFg, ...) and are
// inlined into the page's single script element via the PREVIEWS_J token in app.js.
function ofs(app,face){const f=PKGMAP[app][face]||{},fg=effFg(pkgEffFg(app,face)),bg=pkgEffBg(app,face);return faceCss(f,fg,bg,{fontSize:(f.height||1),boxBg:bg||MAP['bg']});}
-function os(app,face,txt){return `<span data-face="${face}" style="${ofs(app,face)}">${txt}</span>`;}
+// The CSS for a UI-owned face rendered off any preview surface: effective fg
+// (floored to the default fg) and bg, following the built-in UI inherit chain so
+// the rendered color matches what the registry reports. The @ui counterpart to ofs.
+function ulocateCss(face){const o=UIMAP[face]||{},fg=effFg(resolveUiAttr(face,'fg',UIMAP)),bg=resolveUiAttr(face,'bg',UIMAP)||null;return faceCss(o,fg,bg,{boxBg:bg||MAP['bg']});}
+// previewSpan -- the one stateful locate adapter (preview-locate spec). Reads the
+// live globals (PKGMAP / UIMAP / MAP), dispatches by the owner's surface to the
+// package (ofs / PKGMAP) or @ui (UIMAP) style path, and emits the shared locate
+// attributes: data-owner-app (the internal owner key), data-face, and the
+// locate-onpane class when the owner is the pane currently viewed. TEXT is trusted
+// preview HTML -- callers pre-escape entities, matching the old os() contract, so
+// previewSpan does not re-escape it (that would double-escape &lt; etc.). os
+// delegates here for package owners; an @ui or cross-package owner makes an
+// off-pane, hover-only span.
+function attresc(s){return esc(String(s)).replace(/"/g,'&quot;');}
+function previewSpan(owner,face,text){
+ const style=owner==='@ui'?ulocateCss(face):ofs(owner,face);
+ const cls=isLocateOnPane(owner,curApp())?' class="locate-onpane"':'';
+ const title=attresc(formatLocateTitle(locateFaceMeta(owner,face,LOCATE_REG)));
+ return `<span data-owner-app="${owner}" data-face="${face}"${cls} title="${title}" style="${style}">${text}</span>`;
+}
+function os(app,face,txt){return previewSpan(app,face,txt);}
// Shared wrapper for the line-based package previews: a monospace pre block.
// Each renderer builds its own L array of os(...) lines and returns previewLines(L).
function previewLines(L){return `<div style="padding:12px 16px;font:12pt/1.7 monospace;white-space:pre">${L.join('\n')}</div>`;}