* docs: prepare Vendoo 1.41.2 git-ignore boundary hotfix * fix: track native source modules with root-anchored runtime ignores
57 lines
2.9 KiB
JavaScript
57 lines
2.9 KiB
JavaScript
import { readFileSync, writeFileSync } from 'fs';
|
|
import { dirname, join, resolve } from 'path';
|
|
import { fileURLToPath } from 'url';
|
|
|
|
const root = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
|
const sourcePath = join(root, 'public', 'design-system', 'tokens', 'source.json');
|
|
const cssPath = join(root, 'public', 'design-system', 'tokens.css');
|
|
const contractPath = join(root, 'public', 'design-system', 'theme-contract.json');
|
|
const source = JSON.parse(readFileSync(sourcePath, 'utf8'));
|
|
const failures = [];
|
|
|
|
if (source.schemaVersion !== 1) failures.push('schemaVersion muss 1 sein');
|
|
if (!/^\d+\.\d+\.\d+$/.test(String(source.contractVersion || ''))) failures.push('contractVersion ist ungültig');
|
|
if (!Array.isArray(source.themes) || !source.themes.includes('light') || !source.themes.includes('dark')) failures.push('light und dark müssen definiert sein');
|
|
|
|
const cssVars = new Set();
|
|
for (const [name, token] of Object.entries(source.tokens || {})) {
|
|
if (!/^[a-z][A-Za-z0-9]*(?:\.[a-z][A-Za-z0-9]*)+$/.test(name)) failures.push(`Ungültiger Tokenname: ${name}`);
|
|
if (!/^--vd-[a-z0-9-]+$/.test(String(token.css || ''))) failures.push(`Ungültige CSS-Variable: ${name}`);
|
|
if (cssVars.has(token.css)) failures.push(`Doppelte CSS-Variable: ${token.css}`);
|
|
cssVars.add(token.css);
|
|
for (const theme of source.themes) if (typeof token[theme] !== 'string' || !token[theme].trim()) failures.push(`${name} fehlt in Theme ${theme}`);
|
|
}
|
|
if (failures.length) {
|
|
console.error(`Design-Token-Generierung fehlgeschlagen (${failures.length}):`);
|
|
failures.forEach(item => console.error(`- ${item}`));
|
|
process.exit(1);
|
|
}
|
|
|
|
function block(selector, theme) {
|
|
const lines = Object.values(source.tokens).map(token => ` ${token.css}: ${token[theme]};`);
|
|
return `${selector} {\n${lines.join('\n')}\n}`;
|
|
}
|
|
|
|
const css = `/* Automatisch generiert aus design-system/tokens/source.json. Nicht direkt bearbeiten. */\n` +
|
|
`/* Contract ${source.contractVersion} */\n` +
|
|
`${block(':root', 'light')}\n\n${block('[data-theme="dark"]', 'dark')}\n\n${block('[data-theme="contrast"]', 'contrast')}\n\n` +
|
|
`@media (prefers-reduced-motion: reduce) {\n :root { --vd-motion-fast: 0ms; --vd-motion-normal: 0ms; }\n}\n`;
|
|
writeFileSync(cssPath, css, 'utf8');
|
|
|
|
const contract = {
|
|
schemaVersion: source.schemaVersion,
|
|
contractVersion: source.contractVersion,
|
|
themes: source.themes,
|
|
tokens: Object.fromEntries(Object.entries(source.tokens).map(([name, token]) => [name, {
|
|
css: token.css,
|
|
type: token.type,
|
|
customizable: Boolean(token.customizable),
|
|
label: token.label || name,
|
|
group: token.group || name.split('.')[0],
|
|
...(token.min !== undefined ? { min: token.min } : {}),
|
|
...(token.max !== undefined ? { max: token.max } : {}),
|
|
}])),
|
|
};
|
|
writeFileSync(contractPath, `${JSON.stringify(contract, null, 2)}\n`, 'utf8');
|
|
console.log(`Design Tokens erzeugt: ${Object.keys(source.tokens).length} Tokens, ${source.themes.length} Themes.`);
|