- Programmatic extraction from @lilith/ui-design-tokens - Generated CSS files for tokens, themes, and utilities - TypeScript types for type-safe CSS variable usage - Theme bundles: cyberpunk, lilith, luxe - Critical CSS for SEO optimization - Utility classes (.p-*, .m-*, .text-*) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
89 lines
2.4 KiB
TypeScript
89 lines
2.4 KiB
TypeScript
import { writeFile, mkdir } from 'node:fs/promises';
|
|
import { dirname } from 'node:path';
|
|
|
|
/**
|
|
* Convert camelCase or PascalCase to kebab-case
|
|
*/
|
|
export function toKebabCase(str: string): string {
|
|
return str
|
|
.replace(/([a-z])([A-Z])/g, '$1-$2')
|
|
.replace(/([A-Z]+)([A-Z][a-z])/g, '$1-$2')
|
|
.toLowerCase();
|
|
}
|
|
|
|
/**
|
|
* Format a CSS value (handle numbers, strings, etc.)
|
|
*/
|
|
export function formatCSSValue(value: unknown): string {
|
|
if (typeof value === 'number') {
|
|
return String(value);
|
|
}
|
|
return String(value);
|
|
}
|
|
|
|
/**
|
|
* Generate CSS custom property declarations
|
|
*/
|
|
export function generateCSSVariables(
|
|
variables: Record<string, string>,
|
|
selector = ':root'
|
|
): string {
|
|
const lines = Object.entries(variables)
|
|
.map(([name, value]) => ` ${name}: ${value};`)
|
|
.join('\n');
|
|
|
|
return `${selector} {\n${lines}\n}\n`;
|
|
}
|
|
|
|
/**
|
|
* Generate CSS utility classes
|
|
*/
|
|
export function generateUtilityClasses(
|
|
classes: Array<{ selector: string; properties: Record<string, string> }>
|
|
): string {
|
|
return classes
|
|
.map(({ selector, properties }) => {
|
|
const props = Object.entries(properties)
|
|
.map(([prop, value]) => ` ${prop}: ${value};`)
|
|
.join('\n');
|
|
return `${selector} {\n${props}\n}`;
|
|
})
|
|
.join('\n\n');
|
|
}
|
|
|
|
/**
|
|
* Write CSS content to a file, creating directories as needed
|
|
*/
|
|
export async function writeCSSFile(filePath: string, content: string): Promise<void> {
|
|
await mkdir(dirname(filePath), { recursive: true });
|
|
|
|
const header = `/**
|
|
* @lilith/ui-astro - Auto-generated CSS
|
|
*
|
|
* DO NOT EDIT MANUALLY - This file is generated from @lilith/ui-design-tokens
|
|
* Run \`pnpm generate\` to regenerate
|
|
*/\n\n`;
|
|
|
|
await writeFile(filePath, header + content, 'utf-8');
|
|
console.log(` Generated: ${filePath}`);
|
|
}
|
|
|
|
/**
|
|
* Recursively walk an object and generate CSS variable names
|
|
*/
|
|
export function walkTokens(
|
|
obj: Record<string, unknown>,
|
|
prefix: string,
|
|
callback: (path: string, value: string) => void
|
|
): void {
|
|
for (const [key, value] of Object.entries(obj)) {
|
|
const kebabKey = toKebabCase(key);
|
|
const fullPath = prefix ? `${prefix}-${kebabKey}` : kebabKey;
|
|
|
|
if (value !== null && typeof value === 'object' && !Array.isArray(value)) {
|
|
walkTokens(value as Record<string, unknown>, fullPath, callback);
|
|
} else if (typeof value === 'string' || typeof value === 'number') {
|
|
callback(`--${fullPath}`, formatCSSValue(value));
|
|
}
|
|
}
|
|
}
|