|
|
@@ -0,0 +1,74 @@
|
|
|
+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)/
|
|
|
+
|
|
|
+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)
|
|
|
+ if (bannedEmoji.test(text)) failures.push(`banned emoji in ${rel}`)
|
|
|
+ if (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')
|