Skip to content

Commit 8900ea7

Browse files
Merge pull request #315 from codeslash-dev/claude/loving-galileo-0197q7
fix(configurator): draggable pane widths, font-family classifier, overflow fix, build-time version injection
2 parents c2c920c + e4491d4 commit 8900ea7

10 files changed

Lines changed: 42 additions & 48 deletions

File tree

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ jobs:
186186
run: |
187187
git config user.name "github-actions[bot]"
188188
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
189-
git add package.json package-lock.json docs/roadmap.md CHANGELOG.md configurator/src/data/api-index.generated.json
189+
git add package.json package-lock.json docs/roadmap.md CHANGELOG.md
190190
if git diff --cached --quiet; then
191191
echo "Nothing to commit — version artifacts on main already match ${{ steps.ver.outputs.tag }}."
192192
else

configurator/scripts/sync-api.mjs

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -45,21 +45,6 @@ const ANNOTATIONS_FILE = path.join(FRAMEWORK_ROOT, 'docs', 'token-annotations.js
4545
const OUT_DIR = path.join(CONFIGURATOR_ROOT, 'src', 'data');
4646
const OUT = path.join(OUT_DIR, 'api-index.generated.json');
4747

48-
/**
49-
* Read the framework's package version, used only as a display/sync stamp.
50-
* Falls back to an empty string when the file is unavailable.
51-
* @returns {string}
52-
*/
53-
function readFrameworkVersion() {
54-
try {
55-
const pkg = JSON.parse(
56-
fs.readFileSync(path.join(FRAMEWORK_ROOT, 'package.json'), 'utf8')
57-
);
58-
return typeof pkg.version === 'string' ? pkg.version : '';
59-
} catch {
60-
return '';
61-
}
62-
}
6348

6449
/**
6550
* Read the optional token-annotations.json overlay. Returns null if the file
@@ -180,7 +165,10 @@ function main() {
180165
_sync: {
181166
generatedBy: 'configurator/scripts/sync-api.mjs',
182167
source: path.relative(FRAMEWORK_ROOT, SOURCE).split(path.sep).join('/'),
183-
frameworkVersion: readFrameworkVersion(),
168+
// frameworkVersion is intentionally NOT stored here. It is injected at
169+
// Vite build time (vite.config.js `define.__SLASHED_VERSION__`) from the
170+
// root package.json, so it always matches the build and never needs a
171+
// separate sync step.
184172
// Content hash of the projected catalogue. Unlike a wall-clock stamp it
185173
// only changes when the tokens themselves change, so re-running the sync
186174
// produces no diff unless the framework API actually moved.
@@ -206,8 +194,7 @@ function main() {
206194

207195
console.log(
208196
`[configurator:sync] ${path.relative(FRAMEWORK_ROOT, OUT)} ← ` +
209-
`${out._sync.source} (${tokens.length} tokens, framework ` +
210-
`${out._sync.frameworkVersion || 'unknown'})`
197+
`${out._sync.source} (${tokens.length} tokens)`
211198
);
212199
}
213200

configurator/src/components/Header.svelte

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* Below ~760px the labels collapse to icons but every control stays
1414
* reachable. Keyboard shortcut: `/` focuses the search box.
1515
*/
16-
import { sync, allTokens } from '../lib/model.js';
16+
import { sync, allTokens, frameworkVersion } from '../lib/model.js';
1717
import { ui, overrides, overrideCount, history, undo, redo, openOutputDrawer } from '../lib/store.svelte.js';
1818
1919
const totalTokens = allTokens.length;
@@ -30,9 +30,9 @@
3030
<p class="hdr__sub">Edit every framework token. Generate override CSS.</p>
3131
</div>
3232
<div class="hdr__pills">
33-
{#if sync.frameworkVersion}
33+
{#if frameworkVersion}
3434
<span class="hdr__pill" title="Synced from {sync.source} (catalogue {sync.tokensHash})">
35-
v{sync.frameworkVersion}
35+
v{frameworkVersion}
3636
</span>
3737
{/if}
3838
<span class="hdr__pill hdr__pill--muted" title="{totalTokens} tokens in the live catalogue">

configurator/src/components/OutputPanel.svelte

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
* customised" pill keeps the user oriented even with the body hidden.
1212
*/
1313
import { overrides, ui, storage, replaceOverrides, clearAll } from '../lib/store.svelte.js';
14-
import { sync, defaultsByName, tokenByName } from '../lib/model.js';
14+
import { sync, defaultsByName, tokenByName, frameworkVersion } from '../lib/model.js';
1515
import { generateCSS, parseCSS } from '../lib/css.js';
1616
import { copyText, COPY_FEEDBACK_MS } from '../lib/clipboard.js';
1717
@@ -211,7 +211,7 @@
211211

212212
<footer class="out__foot">
213213
Synced from <code>{sync.source}</code> · framework
214-
<code>{sync.frameworkVersion || 'unknown'}</code> ·
214+
<code>{frameworkVersion || 'unknown'}</code> ·
215215
{sync.counts?.tokens ?? 0} tokens in catalogue
216216
</footer>
217217
{/if}

configurator/src/data/api-index.generated.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
"_sync": {
33
"generatedBy": "configurator/scripts/sync-api.mjs",
44
"source": "docs/api-index.json",
5-
"frameworkVersion": "0.5.36",
65
"tokensHash": "64c1ee7ddc47",
76
"bundles": [
87
"essential",

configurator/src/lib/css.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* the cascade, so these win without `!important`). A bare `:root { … }` mode is
88
* also offered for consumers who don't use cascade layers.
99
*/
10-
import { sync } from './model.js';
10+
import { frameworkVersion } from './model.js';
1111

1212
/**
1313
* Sanitize a single declaration value so it cannot break out of its CSS
@@ -51,7 +51,7 @@ export function generateCSS(overrides, opts = {}) {
5151

5252
let out = '';
5353
if (banner) {
54-
const v = sync.frameworkVersion ? ` v${sync.frameworkVersion}` : '';
54+
const v = frameworkVersion ? ` v${frameworkVersion}` : '';
5555
out +=
5656
`/* SLASHED override tokens${v} — generated by the SLASHED configurator.\n` +
5757
` Load this AFTER the SLASHED stylesheet. ${names.length} token${

configurator/src/lib/model.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,17 @@
99
import data from '../data/api-index.generated.json' with { type: 'json' };
1010
import { domainOf } from './domains.js';
1111

12-
/** Sync metadata (framework version, generated timestamp, counts). */
12+
/** Sync metadata (catalogue hash, counts — NOT frameworkVersion, which is injected at build time). */
1313
export const sync = data._sync ?? {};
1414

15+
/**
16+
* Framework version, injected at Vite build time from the root package.json.
17+
* Declared as `string` via vite.config.js `define`, guaranteed to match
18+
* whatever package.json version was current when `vite build` ran.
19+
*/
20+
// eslint-disable-next-line no-undef
21+
export const frameworkVersion = typeof __SLASHED_VERSION__ !== 'undefined' ? __SLASHED_VERSION__ : (sync.frameworkVersion ?? '');
22+
1523
/** Every token row from the synced catalogue. */
1624
export const allTokens = Array.isArray(data.tokens) ? data.tokens : [];
1725

configurator/vite.config.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
1+
import { readFileSync } from 'node:fs';
2+
import { resolve } from 'node:path';
13
import { defineConfig } from 'vite';
24
import { svelte } from '@sveltejs/vite-plugin-svelte';
35

6+
// Read the framework's package.json for the version stamp. Using the file
7+
// directly (rather than package.json imports) keeps this compatible with both
8+
// ESM and CJS Vite configs, and avoids assert{type:'json'} compat issues.
9+
const pkg = JSON.parse(
10+
readFileSync(resolve(import.meta.dirname, '../package.json'), 'utf8')
11+
);
12+
413
/**
514
* Build config for the standalone SLASHED configurator.
615
*
@@ -12,10 +21,17 @@ import { svelte } from '@sveltejs/vite-plugin-svelte';
1221
* `base: './'` keeps every asset reference relative so the built site in
1322
* dist/ can be hosted from any sub-path (GitHub Pages project site, a CDN
1423
* folder, file://, etc.) without reconfiguration.
24+
*
25+
* `__SLASHED_VERSION__` is injected at build time from the root package.json
26+
* so the version pill in the header is always exactly the version that was
27+
* built — no separate sync step needed, no off-by-one after releases.
1528
*/
1629
export default defineConfig({
1730
base: './',
1831
plugins: [svelte()],
32+
define: {
33+
__SLASHED_VERSION__: JSON.stringify(pkg.version),
34+
},
1935
build: {
2036
target: 'es2022',
2137
sourcemap: true,

scripts/check-version-sync.js

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
// 1. package-lock.json version (root and packages[""]) === package.json
88
// 2. docs/roadmap.md "Current version" === package.json
99
//
10+
// Note: configurator/src/data/api-index.generated.json no longer stores a
11+
// frameworkVersion field — the version is injected at Vite build time from the
12+
// root package.json (vite.config.js define.__SLASHED_VERSION__), so it is
13+
// always exactly the version that was built and never needs a sync step.
1014
// Run locally with: node scripts/check-version-sync.js
1115
// Wired into CI (.github/workflows/ci.yml).
1216

@@ -46,15 +50,6 @@ if (!m) {
4650
);
4751
}
4852

49-
// 3. configurator generated index frameworkVersion must match package.json.
50-
const genIndex = JSON.parse(read('configurator/src/data/api-index.generated.json'));
51-
const genVersion = genIndex?._sync?.frameworkVersion;
52-
if (genVersion !== version) {
53-
errors.push(
54-
`configurator/src/data/api-index.generated.json frameworkVersion "${genVersion}" != package.json "${version}" — run \`npm run configurator:sync\``,
55-
);
56-
}
57-
5853
if (errors.length) {
5954
console.error('version-sync check FAILED:');
6055
for (const e of errors) console.error(` - ${e}`);

scripts/version-sync.js

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -55,17 +55,6 @@ changed += sync(
5555
`roadmap version = ${version}`
5656
) ? 1 : 0;
5757

58-
// ── configurator/src/data/api-index.generated.json ──────────────────────────
59-
// A release bumps package.json but doesn't rebuild the configurator, so without
60-
// this the panel keeps showing the PREVIOUS version every release. Bump the
61-
// stamp here too (guarded by check-version-sync.js).
62-
changed += sync(
63-
'configurator/src/data/api-index.generated.json',
64-
new RegExp(`("frameworkVersion":\\s*")${SEMVER_RE.source}(")`),
65-
`$1${version}$2`,
66-
`configurator api-index frameworkVersion = ${version}`
67-
) ? 1 : 0;
68-
6958
// ── Summary ─────────────────────────────────────────────────────────────────
7059
if (changed === 0) {
7160
console.log('\nAll version references are already up to date.\n');

0 commit comments

Comments
 (0)