aboutsummaryrefslogtreecommitdiff
path: root/scripts/theme-studio/test-app-core.mjs
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-06-19 00:40:30 -0500
committerCraig Jennings <c@cjennings.net>2026-06-19 00:40:30 -0500
commit4c8702587a7c1f1d0dbff5fc71a82c5e912d3e76 (patch)
tree9b4c63c8cd6e7b75105dfb44af1fa31d7cf2a20f /scripts/theme-studio/test-app-core.mjs
parent1d521c7723aa96ca6d6dd5894619704cb4e08119 (diff)
downloaddotemacs-4c8702587a7c1f1d0dbff5fc71a82c5e912d3e76.tar.gz
dotemacs-4c8702587a7c1f1d0dbff5fc71a82c5e912d3e76.zip
refactor(theme-studio): polish the expander (underline inside, dynamic colspan, nd flag)
Three cleanups to the per-row expander from 3B-2. The underline control moves from the in-row style cell into the expander, next to overline. The row keeps weight, slant, and strike inline, so the style cell drops from three wrapped rows to two and the table reads flatter. mkExpander no longer hardcodes each table's colspan. tableColCount reads the column count from the table's header, so a detail row spans correctly even if a column is added later. A collapsed expander now flags itself when it hides an attribute that differs from the face's default, so a non-default value is never invisible. overflowNonDefault (app-core.js, unit-tested) compares the expander's attributes against the default. The toggle re-checks after every edit and gets the gold marker when any differ. faceBoxNonDefaults drops underline from the in-row style box in the same move, since underline is now the expander's concern. The #expandtest gate covers the underline control in its new home, its wavy write, and the flag appearing then clearing. Full suite green: Python 59, Node 201, ERT 41, plus the browser hash gates.
Diffstat (limited to 'scripts/theme-studio/test-app-core.mjs')
-rw-r--r--scripts/theme-studio/test-app-core.mjs31
1 files changed, 28 insertions, 3 deletions
diff --git a/scripts/theme-studio/test-app-core.mjs b/scripts/theme-studio/test-app-core.mjs
index d5f015d93..457f04d17 100644
--- a/scripts/theme-studio/test-app-core.mjs
+++ b/scripts/theme-studio/test-app-core.mjs
@@ -9,7 +9,7 @@ import { fileURLToPath } from 'node:url';
import {
nameToHex, migrateLegacyFace, normalizePkgFace, buildPkgmap, packagesForExport, mergePackagesInto, effResolve, resolveSyntaxFg, resolveUiAttr, dropdownRowTextColor, paletteOptionList, spanNeighborHex, slugify,
clearPalettePlan, deletePaletteColumnPlan, groundColumnMembersFromPalette, areAllLocked, lockToggleLabel, toggleLockSet,
- galleryModel, appViewKeysSorted, faceBoxNonDefaults, stepViewIndex,
+ galleryModel, appViewKeysSorted, faceBoxNonDefaults, overflowNonDefault, stepViewIndex,
} from './app-core.js';
import { planPaletteGenerator, entriesForGeneratedColumn } from './palette-generator-core.js';
import { oklch2hex, deltaE } from './colormath.js';
@@ -957,12 +957,37 @@ test('faceBoxNonDefaults: a set fg over an empty default flags fg', () => {
assert.equal(faceBoxNonDefaults({ fg: '#8ea85e' }, {}).fg, true);
assert.equal(faceBoxNonDefaults({}, {}).fg, false);
});
-test('faceBoxNonDefaults: any style attr differing flags the style box once', () => {
+test('faceBoxNonDefaults: an in-row style attr differing flags the style box once', () => {
assert.equal(faceBoxNonDefaults({ weight: 'bold' }, { weight: null }).style, true);
assert.equal(faceBoxNonDefaults({ slant: 'italic' }, {}).style, true);
- assert.equal(faceBoxNonDefaults({ underline: { style: 'line', color: null } }, {}).style, true);
+ assert.equal(faceBoxNonDefaults({ strike: { color: null } }, {}).style, true);
+ // underline lives in the expander now, so it does not flag the in-row style box
+ assert.equal(faceBoxNonDefaults({ underline: { style: 'line', color: null } }, {}).style, false);
assert.equal(faceBoxNonDefaults({ weight: 'bold' }, { weight: 'bold' }).style, false);
});
+
+test('overflowNonDefault: Normal — flags an expander attr that differs from default', () => {
+ assert.equal(overflowNonDefault({ family: 'Iosevka' }, {}, false), true);
+ assert.equal(overflowNonDefault({ underline: { style: 'wave', color: null } }, {}, false), true);
+ assert.equal(overflowNonDefault({ inverse: true }, {}, false), true);
+ assert.equal(overflowNonDefault({ 'distant-fg': '#222222' }, {}, false), true);
+});
+
+test('overflowNonDefault: Boundary — matching attrs and in-row attrs do not flag', () => {
+ // identical overflow attrs -> no flag
+ const f = { family: 'Iosevka', overline: { color: '#abc' }, inverse: true };
+ assert.equal(overflowNonDefault(f, f, false), false);
+ // weight/slant/strike are in-row, not the expander's concern
+ assert.equal(overflowNonDefault({ weight: 'bold', slant: 'italic', strike: { color: null } }, {}, false), false);
+});
+
+test('overflowNonDefault: Boundary — inherit/height only count when shown in the expander', () => {
+ // packages keep inherit/height inline (showInheritHeight false) -> not flagged here
+ assert.equal(overflowNonDefault({ inherit: 'shadow', height: 1.4 }, {}, false), false);
+ // ui/syntax expose them in the expander (showInheritHeight true) -> flagged
+ assert.equal(overflowNonDefault({ inherit: 'shadow' }, {}, true), true);
+ assert.equal(overflowNonDefault({ height: 1.4 }, {}, true), true);
+});
test('faceBoxNonDefaults: inherit and box differences are flagged', () => {
assert.equal(faceBoxNonDefaults({ inherit: 'bold' }, { inherit: null }).inherit, true);
assert.equal(faceBoxNonDefaults({ box: { style: 'line' } }, { box: null }).box, true);