aboutsummaryrefslogtreecommitdiff
path: root/scripts/theme-studio/app.js
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-06-09 05:16:00 -0500
committerCraig Jennings <c@cjennings.net>2026-06-09 05:16:00 -0500
commitd947944bbe358f1a50c58b97a129642e68b7e7c5 (patch)
tree1be76039a0738778a2287101fc26b4e84e0068a0 /scripts/theme-studio/app.js
parent947d146a9692c8b17aca92b3e66772611ac3b598 (diff)
downloaddotemacs-d947944bbe358f1a50c58b97a129642e68b7e7c5.tar.gz
dotemacs-d947944bbe358f1a50c58b97a129642e68b7e7c5.zip
refactor(theme-studio): unify the syntax table onto the shared sort
The syntax table had its own sort (srt + a D{} direction map) that read state directly — MAP[kind] for the color column, cell text for elements. The UI and package tables used a separate, more general system (srtTable / cellVal / applyTableSort) that reads the rendered cells. Pointed the syntax headers at srtTable('legbody', col) and deleted srt, so all three tables share one sort. The mapping is exact: the legtable color cell is a swatch dropdown whose data-val is the hex, which cellVal reads — same key srt sorted on — and the elements cell is text. First-click direction stays ascending. The syntax table sorts on click only; it doesn't opt into the cross-rebuild persistence the UI and package tables get from applyTableSort, which preserves its prior behavior. Added a #sorttest gate: sort was previously untested, and this collapses two systems into one. It checks the syntax table sorts by color ascending, reverses on a second click, sorts by element name, and that the UI and package tables still sort. The asc/desc pair is self-validating — a no-op sort can't pass both.
Diffstat (limited to 'scripts/theme-studio/app.js')
-rw-r--r--scripts/theme-studio/app.js30
1 files changed, 21 insertions, 9 deletions
diff --git a/scripts/theme-studio/app.js b/scripts/theme-studio/app.js
index be70f0ed..c4ff36fb 100644
--- a/scripts/theme-studio/app.js
+++ b/scripts/theme-studio/app.js
@@ -705,15 +705,11 @@ function buildUITable(){
}
applyTableSort('uibody');
}
-let D={};
-function srt(c){const tb=document.getElementById('legbody');const r=[...tb.rows];D[c]=!D[c];
- r.sort((a,b)=>{const x=(c===0?(MAP[a.dataset.kind]||''):a.cells[0].innerText).toLowerCase(),
- y=(c===0?(MAP[b.dataset.kind]||''):b.cells[0].innerText).toLowerCase();
- return (x<y?-1:x>y?1:0)*(D[c]?1:-1);});r.forEach(x=>tb.appendChild(x));}
-// Generic header-click sort for the package and UI tables. Reads a select
-// value, a numeric input, or cell text (numeric when the text leads with a
-// number, e.g. contrast or size). The sort is remembered per table and
-// re-applied after a rebuild so editing a face does not reset it.
+// Generic header-click sort, shared by all three tables. Reads a swatch
+// dropdown's value, a select value, a numeric input, or cell text (numeric when
+// the text leads with a number, e.g. contrast or size). The UI and package
+// tables remember the sort (applyTableSort runs on rebuild) so editing a row
+// does not reset it; the syntax table sorts on click only.
let tableSort={};
function cellVal(td){if(!td)return '';const dd=td.querySelector('.cdd');if(dd)return (dd.dataset.val||'').toLowerCase();const s=td.querySelector('select');if(s)return s.value.toLowerCase();const i=td.querySelector('input');if(i)return parseFloat(i.value)||0;const t=td.innerText.trim();const n=parseFloat(t);return (!isNaN(n)&&/^[-\d.]/.test(t))?n:t.toLowerCase();}
function srtTable(tbId,col){tableSort[tbId]={col,asc:!(tableSort[tbId]&&tableSort[tbId].col===col&&tableSort[tbId].asc)};applyTableSort(tbId);}
@@ -771,6 +767,22 @@ if(location.hash==='#locktest'){let ok=true;const notes=[];const A=(c,n)=>{if(!c
A(PKGMAP[app][p1].fg==='#111111','pkg-clear-keeps-locked');A(PKGMAP[app][p2].fg===null,'pkg-clear-wipes-unlocked');}
document.title='LOCKTEST '+(ok?'PASS':'FAIL');
const d=document.createElement('div');d.id='locktest';d.textContent='LOCKTEST '+(ok?'PASS':'FAIL')+(notes.length?' | '+notes.join(' ; '):'');document.body.appendChild(d);}
+// Sort gate (open with #sorttest): all three tables now share srtTable/cellVal.
+// Verifies the syntax table (which used to have its own srt) sorts by color
+// value and by element name, that a repeat click reverses, and that the UI and
+// package tables still sort. Guards the unified sort for the later stages.
+if(location.hash==='#sorttest'){let ok=true;const notes=[];const A=(c,n)=>{if(!c){ok=false;notes.push(n);}};
+ const ddVals=tb=>[...document.querySelectorAll('#'+tb+' tr')].map(tr=>{const dd=tr.cells[2].querySelector('.cdd');return dd?(dd.dataset.val||''):'';});
+ const txtVals=tb=>[...document.querySelectorAll('#'+tb+' tr')].map(tr=>tr.cells[0].innerText.trim().toLowerCase());
+ const asc=a=>a.every((v,i)=>i===0||a[i-1]<=v),desc=a=>a.every((v,i)=>i===0||a[i-1]>=v);
+ buildTable();
+ srtTable('legbody',2);A(asc(ddVals('legbody')),'legbody-color-asc');
+ srtTable('legbody',2);A(desc(ddVals('legbody')),'legbody-color-desc');
+ srtTable('legbody',0);A(asc(txtVals('legbody')),'legbody-elements-asc');
+ buildUITable();srtTable('uibody',0);A(asc(txtVals('uibody')),'uibody-face-asc');
+ buildPkgTable();srtTable('pkgbody',2);A(asc(ddVals('pkgbody')),'pkgbody-fg-asc');
+ document.title='SORTTEST '+(ok?'PASS':'FAIL');
+ const d=document.createElement('div');d.id='sorttest';d.textContent='SORTTEST '+(ok?'PASS':'FAIL')+(notes.length?' | '+notes.join(' ; '):'');document.body.appendChild(d);}
if(location.hash.startsWith('#pick')){openPicker();const m=location.hash.slice(5);if(m){const b=document.querySelector('.pmode button[data-m="'+m+'"]');if(b)b.click();}}
if(location.hash==='#cursortest'){document.getElementById('newhexstr').value='#67809c';openPicker();const sc=document.getElementById('svcur'),hc=document.getElementById('huecur');const L=parseFloat(sc.style.left||'0'),T=parseFloat(sc.style.top||'0'),H=parseFloat(hc.style.top||'0');const ok=L>1&&T>1&&H>1;document.title='CURSORTEST '+(ok?'PASS':'FAIL');const d=document.createElement('div');d.id='cursortest';d.textContent='CURSORTEST '+(ok?'PASS':'FAIL')+' left='+sc.style.left+' top='+sc.style.top+' hue='+hc.style.top;document.body.appendChild(d);}
if(location.hash.startsWith('#app')){const ap=location.hash.slice(4),s=document.getElementById('appsel');if(s&&ap){s.value=ap;pkgChanged();}}