#!/usr/bin/env node // Reads ../src/lib/styles/tokens.json and emits tokens.generated.css. // Single source of truth for FabledSword tokens shared with the Flutter // client. 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};`); } 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}`); }