From 67a609dd5e98df4df9a3fb40104817e0c25e5582 Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Thu, 2 Jul 2026 13:10:54 -0400 Subject: feat(theme-studio): screenshot harness + ecosystem coverage policy Two speedrun-enabling pieces. A #preview=&theme= hash handler plus screenshot-previews.sh shoot any app's face table and live preview headlessly under a real theme (WIP.json by default), so preview work can be verified without a human clicking through the studio. The README gains the coverage policy: the studio themes popular packages even when uninstalled, pinning their faces rather than dropping them, and unloaded packages' previews matter more, not less. --- scripts/theme-studio/app.js | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'scripts/theme-studio/app.js') diff --git a/scripts/theme-studio/app.js b/scripts/theme-studio/app.js index 7f846e6c..24fd120d 100644 --- a/scripts/theme-studio/app.js +++ b/scripts/theme-studio/app.js @@ -727,4 +727,27 @@ function initApp(){ } initApp(); addEventListener('resize',()=>{syncPaneHeight('uitable','mockframe');syncPaneHeight('pkgtable','pkgpreview');}); +// #preview=[&theme=]: select that app on load and hide the +// topbar + palette so its face table + live preview render from the top of the +// page (headless screenshots can't scroll reliably). An optional theme URL is +// fetched and imported first, so shots show a real theme instead of untitled +// (fresh headless profiles have no localStorage; Chrome needs +// --allow-file-access-from-files for a file:// fetch). Drives the screenshot +// harness (screenshot-previews.sh), same hash-URL pattern as the browser gates. +// The title flip lets the harness confirm the selection landed. +if(location.hash.startsWith('#preview=')){ + const q=location.hash.slice(9).split('&theme='); + const k=decodeURIComponent(q[0]); + const showApp=()=>{ + if(!APPS[k])return; + const s=document.getElementById('viewsel'); + if(!s)return; + s.value=k;onViewChange();document.title='PREVIEW '+k; + document.querySelectorAll('.topbar, body > section') + .forEach(e=>{e.style.display='none';});}; + if(q[1])fetch(decodeURIComponent(q[1])).then(r=>r.text()) + .then(t=>{applyImported(t);showApp();}) + .catch(()=>{document.title='PREVIEW THEME-LOAD-FAILED';showApp();}); + else showApp(); +} BROWSER_GATES_J -- cgit v1.2.3