Rewrites the web app's comments to rule 32. Task, milestone, rule and spec ids are gone; regression stories are restated as the trap they guard (public auth routes, the menu's stopPropagation, universal loads under adapter-static, metric deltas with their margin). Flutter and Tauri mentions now name the Android app or a native shell, operator quotes and dates are dropped, and one library's counts no longer appear outside test fixtures. Verified with a TypeScript-scanner token comparison (template literals and regex literals re-scanned): only comment text changed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
53 lines
2.3 KiB
JavaScript
53 lines
2.3 KiB
JavaScript
#!/usr/bin/env node
|
|
// Reads ../src/lib/styles/tokens.json and emits tokens.generated.css. Single
|
|
// source of truth for the FabledSword tokens, which the Android app mirrors in
|
|
// FabledSwordTokens.kt. Keep output deterministic — Tailwind reads tokens.json
|
|
// directly, the .css emission is for raw CSS consumers and theme switching.
|
|
import { readFileSync, writeFileSync } from 'node:fs';
|
|
import { fileURLToPath } from 'node:url';
|
|
import { dirname, resolve } from 'node:path';
|
|
|
|
const here = dirname(fileURLToPath(import.meta.url));
|
|
const tokensPath = resolve(here, '../src/lib/styles/tokens.json');
|
|
const outPath = resolve(here, '../src/lib/styles/tokens.generated.css');
|
|
|
|
export function emit(tokens) {
|
|
const lines = ['/* GENERATED — do not edit. Source: tokens.json */', ':root {'];
|
|
for (const [name, value] of Object.entries(tokens.colors.dark)) {
|
|
lines.push(` --fs-${name}: ${value};`);
|
|
}
|
|
for (const [name, value] of Object.entries(tokens.colors.flat)) {
|
|
lines.push(` --fs-${name}: ${value};`);
|
|
}
|
|
// The house -fg tokens: a hue as TEXT on a
|
|
// tint of itself, mixed toward parchment. Parchment inverts in light mode,
|
|
// so one declaration lightens the text on dark surfaces and darkens it on
|
|
// light ones. Declared on :root, the element data-theme is set on, so the
|
|
// var()s resolve against that mode's parchment.
|
|
for (const [name, value] of Object.entries(tokens.colors.fg ?? {})) {
|
|
lines.push(` --fs-${name}: ${value};`);
|
|
}
|
|
for (const [name, value] of Object.entries(tokens.radii)) {
|
|
lines.push(` --fs-radius-${name}: ${value};`);
|
|
}
|
|
lines.push(` --fs-font-display: ${tokens.fontStacks.display};`);
|
|
lines.push(` --fs-font-body: ${tokens.fontStacks.body};`);
|
|
lines.push(` --fs-font-mono: ${tokens.fontStacks.mono};`);
|
|
lines.push('}');
|
|
|
|
lines.push('[data-theme="light"] {');
|
|
for (const [name, value] of Object.entries(tokens.colors.light)) {
|
|
lines.push(` --fs-${name}: ${value};`);
|
|
}
|
|
lines.push('}');
|
|
|
|
lines.push('[data-fs-app="minstrel"] {', ` --fs-accent: ${tokens.colors.flat.accent};`, '}', '');
|
|
return lines.join('\n');
|
|
}
|
|
|
|
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
const tokens = JSON.parse(readFileSync(tokensPath, 'utf8'));
|
|
writeFileSync(outPath, emit(tokens));
|
|
console.log(`wrote ${outPath}`);
|
|
}
|