import { readdirSync, readFileSync } from 'node:fs'; import { join, resolve } from 'node:path'; import { describe, expect, test } from 'vitest'; const sourceRoot = resolve(process.cwd(), 'src'); const generatedDirectories = new Set(['.umi', '.umi-production']); const emojiPattern = /[\u{1F000}-\u{1FAFF}\u{2600}-\u{27BF}]/u; function sourceFiles(directory: string): string[] { return readdirSync(directory, { withFileTypes: true }).flatMap((entry) => { const path = join(directory, entry.name); if (entry.isDirectory()) { return generatedDirectories.has(entry.name) ? [] : sourceFiles(path); } return /\.(?:ts|tsx|less)$/.test(entry.name) ? [path] : []; }); } describe('图标与符号规范', () => { test('业务界面仅使用 Lucide 图标且不包含表情符号', () => { const violations = sourceFiles(sourceRoot).flatMap((path) => { const content = readFileSync(path, 'utf8'); const reasons = [ content.includes('@ant-design/icons') ? '使用了非 Lucide 图标库' : '', emojiPattern.test(content) ? '包含表情符号' : '', ].filter(Boolean); return reasons.map((reason) => `${path}: ${reason}`); }); expect(violations).toEqual([]); }); });