/** * student-portal ESLint 配置(ai14) * * 强制约束(project_rules §3.10): * - no-restricted-syntax:禁止 #hex 颜色字面量 * - design-tokens/no-hardcoded-fonts:禁止 'Inter'/'Fraunces' 字面量 * - 白名单:primitive.css(原始令牌定义) */ const js = require('@eslint/js'); const tseslint = require('typescript-eslint'); const jsxAlly = require('eslint-plugin-jsx-a11y'); module.exports = tseslint.config( js.configs.recommended, ...tseslint.configs.recommended, { files: ['src/**/*.{ts,tsx}'], languageOptions: { ecmaVersion: 2022, sourceType: 'module', parserOptions: { ecmaFeatures: { jsx: true }, project: true, }, }, plugins: { 'jsx-a11y': jsxAlly, }, rules: { // 禁止 any(project_rules §3.4) '@typescript-eslint/no-explicit-any': 'error', // 禁止 as 断言(除非从 unknown 转换) '@typescript-eslint/no-unsafe-assignment': 'warn', // 函数返回值必须显式标注 '@typescript-eslint/explicit-function-return-type': [ 'warn', { allowExpressions: true, allowTypedFunctionExpressions: true }, ], // import type 强制 '@typescript-eslint/no-unused-vars': [ 'error', { argsIgnorePattern: '^_' }, ], // A11y 基础规则 'jsx-a11y/alt-text': 'error', 'jsx-a11y/aria-role': 'error', 'jsx-a11y/tabindex-no-positive': 'error', // 禁止硬编码颜色(#hex)— 白名单:primitive.css 'no-restricted-syntax': [ 'error', { selector: "Literal[value=/^#[0-9a-fA-F]{3,8}$/]", message: '禁止硬编码 #hex 颜色,使用语义令牌 var(--color-*) 或 Tailwind bg-*/text-*', }, ], }, }, { // 白名单:primitive.css 允许定义原始令牌 files: ['src/styles/primitive.css'], rules: { 'no-restricted-syntax': 'off', }, }, { ignores: ['node_modules/', '.next/', 'build/', 'dist/', 'src/**/*.css'], }, );