From 5e72000497732e7d20c179d2562e4bfacc1e3fbe Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Wed, 24 Jun 2026 05:46:43 -0400 Subject: feat(theme-studio): bespoke nerd-icons filetype-legend preview (phase 2) Register nerd-icons as a bespoke app whenever its captured legend is valid: the 34 color faces stay editable rows, and the legend rides APPS['nerd-icons'].legend. A new renderNerdIconsPreview draws each curated filetype's glyph in its mapped face's effective color, read through the same registry the other previews use, so recoloring a face repaints every row mapped to it. When the legend is absent the generic inventory app stands in. The #nerdiconstest browser gate covers the wiring, the dir-row owner, and the recolor-repaint. Claude-Session: https://claude.ai/code/session_01BqrdWUo9GcznYX2pZr76gZ --- scripts/theme-studio/browser-gates.js | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'scripts/theme-studio/browser-gates.js') diff --git a/scripts/theme-studio/browser-gates.js b/scripts/theme-studio/browser-gates.js index 3b909c424..e428ae58c 100644 --- a/scripts/theme-studio/browser-gates.js +++ b/scripts/theme-studio/browser-gates.js @@ -810,6 +810,33 @@ if(location.hash==='#gnustest')gate('gnustest',A=>{ assertPreviewFaces(A, renderGnusPreview(), APPS['gnus']&&APPS['gnus'].faces, 20, 'gnus', ['gnus-header-name','gnus-header-from','gnus-header-subject','gnus-cite-1','gnus-cite-attribution','gnus-signature','gnus-button','gnus-emphasis-highlight-words']); }); +// nerd-icons legend gate (open with #nerdiconstest): nerd-icons is a bespoke +// filetype-legend app; every glyph span is a real nerd-icons face, the dir row +// models nerd-icons-yellow, and recoloring a face repaints every row mapped to it. +if(location.hash==='#nerdiconstest')gate('nerdiconstest',A=>{ + A(!!APPS['nerd-icons'],'nerd-icons is a registered app'); + A(APPS['nerd-icons']&&APPS['nerd-icons'].preview==='nerdicons','nerd-icons uses the nerdicons preview renderer'); + A(!!PACKAGE_PREVIEWS['nerdicons'],'nerdicons renderer registered'); + const legend=(APPS['nerd-icons']&&APPS['nerd-icons'].legend)||[]; + A(Array.isArray(legend)&&legend.length>=10,'legend has the curated rows ('+legend.length+')'); + const dir=legend.find(r=>r.key==='dir'); + A(dir&&dir.face==='nerd-icons-yellow','dir row models nerd-icons-yellow'); + if(PACKAGE_PREVIEWS['nerdicons']&&APPS['nerd-icons']){ + assertPreviewFaces(A, renderNerdIconsPreview(), APPS['nerd-icons'].faces, 10, 'nerd-icons', + ['nerd-icons-purple','nerd-icons-yellow','nerd-icons-blue','nerd-icons-dblue']); + // Recoloring a face repaints every legend row mapped to it (os reads the live registry). + withSavedState(['PKGMAP'],()=>{ + const target='nerd-icons-purple',mapped=legend.filter(r=>r.face===target); + A(mapped.length>=1,'at least one row maps to '+target); + PKGMAP['nerd-icons']=PKGMAP['nerd-icons']||{}; + PKGMAP['nerd-icons'][target]={fg:'#abcdef',bg:null,weight:null,slant:null,inherit:null,height:1,source:'user'}; + const box=document.createElement('div');box.innerHTML=renderNerdIconsPreview(); + const els=[...box.querySelectorAll('[data-face="'+target+'"]')]; + A(els.length===mapped.length,'every '+target+' row rendered ('+els.length+'/'+mapped.length+')'); + A(els.length>0&&els.every(e=>/#abcdef/i.test(e.getAttribute('style')||'')),'recolor repaints the mapped rows'); + }); + } + }); // picker-distinct gate (open with #pickertest): the color picker panel must stand // out from the page background. It carries a highlighted gold accent border, and its // background is meaningfully lighter than the body so the two are easy to tell apart. -- cgit v1.2.3