import type {Gen} from '@fuzdev/gro'; import {readFileSync} from 'node:fs'; const theme_css_path = 'src/lib/theme_highlight.css'; /** @nodocs */ export const gen: Gen = { dependencies: {files: [theme_css_path]}, generate: ({origin_path}) => { // Read the theme_highlight.css file let css_content = readFileSync(theme_css_path, 'utf-8'); // Strip CSS comments to avoid false positives css_content = css_content.replace(/\/\*[\s\S]*?\*\//g, ''); // Extract ::highlight() rules by CSS rule blocks const highlight_priorities: Record = {}; let priority = 1; // Split CSS into rule blocks (roughly by closing braces) const rule_blocks = css_content.split('}'); for (const block of rule_blocks) { // Find all ::highlight(token_name) declarations in this block const highlight_regex = /::highlight\(([^)]+)\)/g; const tokens_in_block: Array = []; let match; while ((match = highlight_regex.exec(block)) !== null) { const token_name = match[1]!; if (!tokens_in_block.includes(token_name)) { tokens_in_block.push(token_name); } } // Assign the same priority to all tokens in this block if (tokens_in_block.length > 0) { for (const token_name of tokens_in_block) { if (!Object.hasOwn(highlight_priorities, token_name)) { highlight_priorities[token_name] = priority; } } priority++; } } const banner = `// generated by ${origin_path} - DO NOT EDIT OR RISK LOST DATA`; // Generate priority entries const priority_entries = Object.entries(highlight_priorities) .map(([token, priority]) => `\t${token}: ${priority}`) .join(',\n'); // Generate the type const token_names = Object.keys(highlight_priorities) .map((name) => `'${name}'`) .join(' | '); return ` ${banner} export type HighlightTokenName = ${token_names}; export const highlight_priorities: Record = { ${priority_entries}, } as const; ${banner} `; }, };