From b88d7cb0ac5009736aa0998f3ea2933050c55b76 Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Sat, 13 Jun 2026 16:08:13 -0500 Subject: Group numeric color names by stem --- scripts/theme-studio/app-core.js | 2 +- scripts/theme-studio/generate.py | 3 ++- scripts/theme-studio/test-columns.mjs | 8 ++++++++ scripts/theme-studio/test_generate.py | 3 +++ scripts/theme-studio/theme-studio.html | 4 ++-- 5 files changed, 16 insertions(+), 4 deletions(-) (limited to 'scripts') diff --git a/scripts/theme-studio/app-core.js b/scripts/theme-studio/app-core.js index b3542bf7..5a7a14ab 100644 --- a/scripts/theme-studio/app-core.js +++ b/scripts/theme-studio/app-core.js @@ -136,7 +136,7 @@ function lMax(hue,chroma,fgSet,target){ function oklchOf(hex){return oklab2oklch(srgb2oklab(hex));} function nameOfHex(palette,hex){const p=palette.find(p=>p[0].toLowerCase()===hex.toLowerCase());return p?p[1]:null;} -function columnStem(name){name=name||'color';return /^color-\d+$/.test(name)?name:name.replace(/[+-]\d+$/,'');} +function columnStem(name){name=name||'color';if(/^color-\d+$/.test(name))return name;name=name.replace(/[+-]\d+$/,'');return name.replace(/\d+$/,'')||'color';} function columnOffset(name){const m=(name||'').match(/([+-]\d+)$/);return m?parseInt(m[1],10):0;} function columnIdOf(entry){return (entry&&entry[2])||columnStem(entry&&entry[1]);} diff --git a/scripts/theme-studio/generate.py b/scripts/theme-studio/generate.py index 6d1a8eb0..0b74b985 100644 --- a/scripts/theme-studio/generate.py +++ b/scripts/theme-studio/generate.py @@ -51,7 +51,8 @@ def column_id(name): name = name or 'color' if re.fullmatch(r'color-\d+', name): return name - return re.sub(r'[+-]\d+$', '', name) + name = re.sub(r'[+-]\d+$', '', name) + return re.sub(r'\d+$', '', name) or 'color' def normalize_palette(palette): return [[p[0], p[1] if len(p) > 1 else 'color', p[2] if len(p) > 2 else column_id(p[1] if len(p) > 1 else 'color')] diff --git a/scripts/theme-studio/test-columns.mjs b/scripts/theme-studio/test-columns.mjs index 6079966a..ab88cb73 100644 --- a/scripts/theme-studio/test-columns.mjs +++ b/scripts/theme-studio/test-columns.mjs @@ -57,6 +57,14 @@ test('columnsFromPalette: Boundary - explicit color-N column ids are preserved', assert.deepEqual(columns[0].members.map(m => m.name), ['color-22', 'color-23']); }); +test('columnsFromPalette: Boundary - external numeric color names group by text stem', () => { + const pal = [['#0000ee', 'blue1'], ['#0000cd', 'blue2'], ['#bebebe', 'grey80'], ['#c0c0c0', 'grey81'], ['#cd69c9', 'orchid3']]; + const { columns } = columnsFromPalette(pal, { bg: '#000000', fg: '#ffffff' }); + assert.deepEqual(columns.map(f => f.column), ['blue', 'grey', 'orchid']); + assert.deepEqual(columnOf(columns, 'blue1').members.map(m => m.name), ['blue1', 'blue2']); + assert.deepEqual(columnOf(columns, 'grey80').members.map(m => m.name), ['grey80', 'grey81']); +}); + test('columnsFromPalette: Normal - palette order controls column order', () => { const pal = [['#67809c', 'blue'], ['#e8bd30', 'gold'], ['#5d9b86', 'green']]; const { columns } = columnsFromPalette(pal, { bg: '#000000', fg: '#ffffff' }); diff --git a/scripts/theme-studio/test_generate.py b/scripts/theme-studio/test_generate.py index 675d6cae..3b6ad741 100644 --- a/scripts/theme-studio/test_generate.py +++ b/scripts/theme-studio/test_generate.py @@ -170,6 +170,9 @@ class FaceSpecDefaults(unittest.TestCase): self.assertEqual(generate.column_id("color-129"), "color-129") self.assertEqual(generate.column_id("blue-1"), "blue") self.assertEqual(generate.column_id("blue+1"), "blue") + self.assertEqual(generate.column_id("blue1"), "blue") + self.assertEqual(generate.column_id("grey80"), "grey") + self.assertEqual(generate.column_id("orchid3"), "orchid") class DefaultFaceAdapter(unittest.TestCase): diff --git a/scripts/theme-studio/theme-studio.html b/scripts/theme-studio/theme-studio.html index 9ed1ee74..edea254c 100644 --- a/scripts/theme-studio/theme-studio.html +++ b/scripts/theme-studio/theme-studio.html @@ -178,7 +178,7 @@