71 lines
2.0 KiB
JavaScript
71 lines
2.0 KiB
JavaScript
/**
|
||
* 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'],
|
||
},
|
||
);
|