import { readFileSync, readdirSync, statSync } from 'node:fs' import { join, relative } from 'node:path' const root = new URL('..', import.meta.url).pathname const src = join(root, 'src') const requiredFiles = [ 'src/styles/theme.css', 'src/styles/components.css', 'src/styles/element-plus.css' ] const requiredTokens = [ '--color-brand: #2b1f99', '--color-accent: #3ad4d8', '--color-bg:', '--color-surface:', '--color-border:', '--color-text:', '--radius-xs: 4px', '--radius-sm: 6px', '--radius-md: 8px' ] const bannedEmoji = /[๐Ÿ“‹๐Ÿ“Œโšกโณโœ…โŒ๐ŸŽฏ๐Ÿš€๐Ÿ’ก๐Ÿ”ฅ]/ const bannedDecor = /(radial-gradient|gradient orb|bokeh|blur\(60px\)|border-radius:\s*(1[2-9]|[2-9]\d)px)/ const migratedMarkers = [ 'clinical-shell', 'internal-login', 'period-workbench', 'period-status-strip', 'okr-workbench', 'team-okr-workbench', 'review-workbench', 'scoring-worklist', 'result-workbench', 'history-workbench', 'feedback-workbench', 'org-workbench', 'log-workbench', 'dimension-workbench', 'template-workbench' ] function walk(dir) { return readdirSync(dir).flatMap((name) => { const path = join(dir, name) return statSync(path).isDirectory() ? walk(path) : [path] }) } const failures = [] for (const file of requiredFiles) { try { readFileSync(join(root, file), 'utf8') } catch { failures.push(`missing required style file: ${file}`) } } const themePath = join(root, 'src/styles/theme.css') let theme = '' try { theme = readFileSync(themePath, 'utf8') } catch {} for (const token of requiredTokens) { if (!theme.includes(token)) failures.push(`missing theme token: ${token}`) } const main = readFileSync(join(root, 'src/main.js'), 'utf8') for (const file of requiredFiles) { const importPath = './' + file.replace('src/', '') if (!main.includes(importPath)) failures.push(`main.js must import ${importPath}`) } const vueAndCssFiles = walk(src).filter((file) => /\.(vue|css)$/.test(file)) for (const file of vueAndCssFiles) { const text = readFileSync(file, 'utf8') const rel = relative(root, file) const mustFollowMedtechRules = rel.startsWith('src/styles/') || migratedMarkers.some((marker) => text.includes(marker)) if (mustFollowMedtechRules && bannedEmoji.test(text)) failures.push(`banned emoji in ${rel}`) if (mustFollowMedtechRules && bannedDecor.test(text)) failures.push(`banned decorative style in ${rel}`) } if (failures.length) { console.error(failures.join('\n')) process.exit(1) } console.log('medtech theme checks passed')