// Fails if any raw Tailwind color utility appears outside src/components/ui/. import { readdirSync, readFileSync } from "node:fs"; import { join, relative } from "node:path"; const root = "src"; const excludeDir = join("src", "components", "ui"); const RAW_COLOR = /(?:text|bg|border|ring|fill|stroke|from|to|via|decoration|outline|divide|placeholder)-(?:(?:neutral|gray|slate|zinc|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-(?:50|100|200|300|400|500|600|700|800|900|950)|white|black)\b/; function walk(dir) { const files = []; for (const entry of readdirSync(dir, { withFileTypes: true })) { const path = join(dir, entry.name); if (entry.isDirectory()) { if (path === excludeDir) continue; files.push(...walk(path)); } else if (entry.name.endsWith(".ts") || entry.name.endsWith(".tsx")) { files.push(path); } } return files; } const files = walk(root); const offenses = []; for (const file of files) { const lines = readFileSync(file, "utf8").split("\n"); for (let i = 0; i < lines.length; i++) { const match = RAW_COLOR.exec(lines[i]); if (match) offenses.push(`${relative(".", file)}:${i + 1}: ${match[0]}`); } } if (offenses.length > 0) { console.error( `raw color utilities found outside components/ui/ (${offenses.length}):`, ); for (const offense of offenses) console.error(` ${offense}`); process.exit(1); } console.log(`no raw color utilities outside components/ui/ (${files.length} files scanned)`);