Files
Hydro/framework/eslint-config/base.mjs
T
2025-03-21 09:39:11 +08:00

483 lines
16 KiB
JavaScript

import { FlatCompat } from '@eslint/eslintrc';
import eslintReact from '@eslint-react/eslint-plugin';
import stylistic from '@stylistic/eslint-plugin';
import typescriptEslint from '@typescript-eslint/eslint-plugin';
import tsParser from '@typescript-eslint/parser';
import { defineConfig, globalIgnores } from 'eslint/config';
import deMorgan from 'eslint-plugin-de-morgan';
import github from 'eslint-plugin-github';
import jsxA11Y from 'eslint-plugin-jsx-a11y';
import reactRefresh from 'eslint-plugin-react-refresh';
import simpleImportSort from 'eslint-plugin-simple-import-sort';
const compat = new FlatCompat({});
export default defineConfig([
globalIgnores([
'**/*.d.ts',
'**/node_modules',
'**/.git',
]),
{
extends: [
compat.extends('airbnb-base'),
compat.extends('airbnb/hooks'),
github.getFlatConfigs().react,
deMorgan.configs.recommended,
eslintReact.configs['recommended-typescript'],
],
settings: {
'import/parsers': {
'@typescript-eslint/parser': ['.ts', '.tsx', '.d.ts'],
},
'import/resolver': {
node: {
extensions: ['.mjs', '.js', '.json', '.ts', '.d.ts'],
},
},
'import/extensions': ['.js', '.mjs', '.jsx', '.ts', '.tsx', '.d.ts'],
'import/external-module-folders': ['node_modules', 'node_modules/@types'],
},
plugins: {
'@typescript-eslint': typescriptEslint,
'simple-import-sort': simpleImportSort,
// import: fixupPluginRules(_import),
'react-refresh': reactRefresh,
'jsx-a11y': jsxA11Y,
'@stylistic': stylistic,
},
languageOptions: {
globals: {
Atomics: 'readonly',
SharedArrayBuffer: 'readonly',
BigInt: 'readonly',
},
parser: tsParser,
},
rules: {
'brace-style': 'off',
'@stylistic/brace-style': ['error', '1tbs', {
allowSingleLine: true,
}],
camelcase: 'off',
'comma-dangle': 'off',
'@stylistic/comma-dangle': ['error', {
arrays: 'always-multiline',
objects: 'always-multiline',
imports: 'always-multiline',
exports: 'always-multiline',
functions: 'always-multiline',
enums: 'always-multiline',
generics: 'always-multiline',
tuples: 'always-multiline',
}],
'comma-spacing': 'off',
'@stylistic/comma-spacing': ['error', {
before: false,
after: true,
}],
'default-param-last': 'off',
'func-call-spacing': 'off',
'@stylistic/func-call-spacing': ['error', 'never'],
indent: 'off',
'@stylistic/indent': ['warn', 4, {
SwitchCase: 1,
VariableDeclarator: 1,
outerIIFEBody: 1,
FunctionDeclaration: {
parameters: 1,
body: 1,
},
FunctionExpression: {
parameters: 1,
body: 1,
},
CallExpression: {
arguments: 1,
},
ArrayExpression: 1,
ObjectExpression: 1,
ImportDeclaration: 1,
flatTernaryExpressions: false,
ignoredNodes: [
'JSXElement',
'JSXElement > *',
'JSXAttribute',
'JSXIdentifier',
'JSXNamespacedName',
'JSXMemberExpression',
'JSXSpreadAttribute',
'JSXExpressionContainer',
'JSXOpeningElement',
'JSXClosingElement',
'JSXFragment',
'JSXOpeningFragment',
'JSXClosingFragment',
'JSXText',
'JSXEmptyExpression',
'JSXSpreadChild',
],
ignoreComments: false,
}],
'keyword-spacing': 'off',
'@stylistic/keyword-spacing': ['error', {
before: true,
after: true,
overrides: {
return: {
after: true,
},
throw: {
after: true,
},
case: {
after: true,
},
},
}],
'lines-between-class-members': 'off',
'@stylistic/lines-between-class-members': ['error', 'always', {
exceptAfterSingleLine: true,
}],
'no-array-constructor': 'off',
'@typescript-eslint/no-array-constructor': 'error',
'no-dupe-class-members': 'off',
'@typescript-eslint/no-dupe-class-members': 'error',
'no-empty-function': 'off',
'@typescript-eslint/no-empty-function': ['error', {
allow: ['arrowFunctions', 'functions', 'methods'],
}],
'no-extra-parens': 'off',
'@typescript-eslint/no-extra-parens': ['off', 'all', {
conditionalAssign: true,
nestedBinaryExpressions: false,
returnAssign: false,
ignoreJSX: 'all',
enforceForArrowConditionals: false,
}],
'no-extra-semi': 'off',
'@stylistic/no-extra-semi': 'error',
'no-new-func': 'off',
'no-loss-of-precision': 'off',
'@typescript-eslint/no-loss-of-precision': 'error',
'no-loop-func': 'off',
'@typescript-eslint/no-loop-func': 'error',
'no-magic-numbers': 'off',
'@typescript-eslint/no-magic-numbers': ['off', {
ignore: [],
ignoreArrayIndexes: true,
enforceConst: true,
detectObjects: false,
}],
'no-redeclare': 'off',
'@typescript-eslint/no-redeclare': 'error',
'no-shadow': 'off',
'@typescript-eslint/no-shadow': 'error',
'space-before-blocks': 'off',
'@stylistic/space-before-blocks': 'error',
'no-unused-expressions': 'off',
'@typescript-eslint/no-unused-expressions': ['error', {
allowShortCircuit: false,
allowTernary: false,
allowTaggedTemplates: false,
}],
'no-unused-vars': 'off',
'@typescript-eslint/no-unused-vars': ['error', {
vars: 'all',
args: 'after-used',
ignoreRestSiblings: true,
caughtErrorsIgnorePattern: '^_|e',
argsIgnorePattern: '^_',
}],
'no-use-before-define': 'off',
'@typescript-eslint/no-use-before-define': ['error', {
functions: true,
classes: true,
variables: true,
}],
'no-useless-constructor': 'off',
'@typescript-eslint/no-useless-constructor': 'error',
quotes: 'off',
'@stylistic/quotes': ['warn', 'single', {
avoidEscape: true,
}],
semi: 'off',
'@stylistic/semi': ['error', 'always'],
'space-before-function-paren': 'off',
'@stylistic/space-before-function-paren': ['error', {
anonymous: 'always',
named: 'never',
asyncArrow: 'always',
}],
'require-await': 'off',
'@typescript-eslint/require-await': 'off',
'space-infix-ops': 'off',
'@stylistic/space-infix-ops': 'error',
'object-curly-spacing': 'off',
'@stylistic/object-curly-spacing': ['error', 'always'],
'function-call-argument-newline': 0,
'no-implicit-coercion': ['warn', {
allow: ['!!', '+'],
}],
'no-extra-boolean-cast': ['warn', {
enforceForLogicalOperands: true,
}],
'no-empty-pattern': 0,
'no-multi-str': 0,
'dot-notation': 0,
'@typescript-eslint/naming-convention': [
'warn',
{
selector: 'default',
format: ['camelCase'],
leadingUnderscore: 'allowSingleOrDouble',
}, {
selector: 'default',
filter: {
regex: '^([A-Z]|_+id|__call__)$',
match: true,
},
format: null,
}, {
selector: 'variable',
modifiers: ['destructured'],
format: null,
}, {
selector: 'import',
format: null,
}, {
selector: 'variable',
format: ['camelCase', 'PascalCase', 'UPPER_CASE'],
modifiers: ['const'],
leadingUnderscore: 'allowSingleOrDouble',
}, {
selector: 'property',
format: ['camelCase', 'PascalCase', 'UPPER_CASE', 'snake_case'],
leadingUnderscore: 'allowSingleOrDouble',
}, {
selector: ['function', 'parameter', 'parameterProperty', 'objectLiteralMethod'],
filter: {
regex: '__call__',
match: false,
},
format: ['camelCase', 'PascalCase'],
leadingUnderscore: 'allowSingleOrDouble',
}, {
selector: ['objectLiteralProperty'],
filter: {
regex: '^[\\d]+$',
match: true,
},
format: null,
}, {
selector: ['typeProperty', 'typeMethod', 'objectLiteralProperty'],
modifiers: ['requiresQuotes'],
format: null,
}, {
selector: ['typeMethod'],
format: ['camelCase', 'PascalCase'],
}, {
selector: ['enum', 'class', 'interface'],
format: ['PascalCase'],
}, {
selector: ['typeAlias', 'enumMember', 'typeParameter'],
format: ['PascalCase', 'camelCase', 'UPPER_CASE'],
},
],
'@typescript-eslint/no-invalid-this': 0,
'class-methods-use-this': 0,
'global-require': 0,
'guard-for-in': 0,
'implicit-arrow-linebreak': 0,
'import/extensions': 0,
'import/order': 0,
'consistent-return': 1,
'func-names': 0,
'import/newline-after-import': 0,
'import/no-cycle': 0,
'import/no-extraneous-dependencies': 0,
'import/no-named-as-default': 0,
'import/prefer-default-export': 0,
'logical-assignment-operators': ['warn', 'always', {
enforceForIfStatements: true,
}],
'max-classes-per-file': 0,
'max-len': ['warn', 150],
'newline-per-chained-call': 0,
'no-bitwise': 0,
'no-console': 0,
'no-continue': 0,
'no-extend-native': 0,
'no-empty': ['warn', {
allowEmptyCatch: true,
}],
'no-await-in-loop': 1,
'no-multi-assign': 0,
'no-return-await': 0,
'no-nested-ternary': 0,
'no-param-reassign': 0,
'no-plusplus': 0,
'no-underscore-dangle': 0,
'no-unmodified-loop-condition': 1,
'prefer-destructuring': 0,
'function-paren-newline': 0,
'simple-import-sort/exports': 0,
'no-restricted-syntax': [
'error', {
selector: 'LabeledStatement',
message: 'Labels are a form of GOTO; using them makes code confusing and hard to maintain and understand.',
}, {
selector: 'WithStatement',
message: '`with` is disallowed in strict mode because it makes code impossible to predict and optimize.',
},
],
'generator-star-spacing': 0,
'github/array-foreach': 1,
'github/a11y-svg-has-accessible-name': 0,
'quote-props': 0,
'@stylistic/quote-props': [0, 'as-needed'],
'simple-import-sort/imports': ['warn', {
groups: [
['^\\u0000'],
[
// eslint-disable-next-line max-len
'^(node:)?(assert|buffer|child_process|cluster|console|constants|crypto|dgram|dns|domain|events|fs|http|https|module|net|os|path|punycode|querystring|readline|repl|stream|string_decoder|sys|timers|tls|tty|url|util|vm|zlib|freelist|v8|process|async_hooks|http2|perf_hooks)(/.*|$)',
'^',
'^\\.',
],
],
}],
// ui-default is currently on react 18
'@eslint-react/no-prop-types': 0,
'@eslint-react/no-string-refs': 0,
// to allow `javascript:;`
'@eslint-react/dom/no-script-url': 0,
'@eslint-react/no-array-index-key': 0,
'@eslint-react/dom/no-missing-button-type': 0,
'@eslint-react/dom/no-dangerously-set-innerhtml': 0,
'@eslint-react/hooks-extra/no-direct-set-state-in-use-effect': 0,
'@eslint-react/hooks-extra/no-unnecessary-use-prefix': 0,
'react-hooks/exhaustive-deps': 0,
// 'react/prefer-stateless-function': 0,
// 'react/function-component-definition': 0,
// 'react/static-property-placement': 0,
// 'react/self-closing-comp': 0,
// 'react/prop-types': 0,
// 'react/jsx-filename-extension': 0,
// 'react/jsx-one-expression-per-line': 0,
// 'react/jsx-props-no-spreading': 0,
// 'react/no-string-refs': 0,
// 'react/require-default-props': 0,
// 'react/react-in-jsx-scope': 0,
// 'react/destructuring-assignment': 0,
// 'react/button-has-type': 0,
// 'react/forbid-prop-types': 0,
'jsx-a11y/no-static-element-interactions': 0,
'jsx-a11y/anchor-is-valid': 0,
'jsx-a11y/click-events-have-key-events': 0,
'jsx-a11y/label-has-associated-control': 0,
'react-refresh/only-export-components': ['warn', {
allowConstantExport: true,
}],
},
},
{
files: ['**/*.ts', '**/*.tsx'],
// Hand over to tsc
rules: {
'constructor-super': 'off',
'getter-return': 'off',
'no-const-assign': 'off',
'no-dupe-args': 'off',
'no-dupe-class-members': 'off',
'no-dupe-keys': 'off',
'no-func-assign': 'off',
'no-import-assign': 'off',
'no-new-symbol': 'off',
'no-obj-calls': 'off',
'no-redeclare': 'off',
'no-setter-return': 'off',
'no-this-before-super': 'off',
'no-undef': 'off',
'no-unreachable': 'off',
'no-unsafe-negation': 'off',
'valid-typeof': 'off',
'import/named': 'off',
'import/no-named-as-default-member': 'off',
'import/no-unresolved': 'off',
},
},
]);