import js from '@eslint/js'; import ts from 'typescript-eslint'; import stylistic from '@stylistic/eslint-plugin'; import { importX } from 'eslint-plugin-import-x'; import importNewlinesPlugin from 'eslint-plugin-import-newlines'; import reactPlugin from 'eslint-plugin-react'; import reactHooksPlugin from 'eslint-plugin-react-hooks'; import globals from 'globals'; const importResolverSettings = { 'import-x/resolver': { typescript: { project: ['./tsconfig.json'], alwaysTryTypes: true, noWarnOnMultipleProjects: true }, node: { extensions: ['.js', '.jsx', '.ts', '.tsx', '.json'] } }, 'import-x/parsers': { '@typescript-eslint/parser': ['.ts', '.tsx'] }, 'import-x/external-module-folders': ['node_modules', 'node_modules/@types'] }; export default ts.config([ { files: ['**/*.ts', '**/*.tsx'], plugins: { stylistic, 'import-x': importX, 'import-newlines': importNewlinesPlugin }, extends: [ js.configs.recommended, ts.configs.strictTypeChecked, ts.configs.stylisticTypeChecked, importX.flatConfigs.recommended, stylistic.configs.customize({ quotes: 'single', semi: true, indent: 4, jsx: true }) ], languageOptions: { parserOptions: { project: ['./tsconfig.json'], tsconfigRootDir: import.meta.dirname }, globals: { ...globals.node, ...globals.es2021 } }, settings: { ...importResolverSettings }, rules: { 'no-control-regex': 'off', // We intentionally match ANSI escape sequences 'eqeqeq': 'error', 'import-x/order': ['error', { alphabetize: { 'order': 'asc', 'orderImportKind': 'asc', 'caseInsensitive': false }, named: { 'enabled': true, 'types': 'types-last' }, pathGroupsExcludedImportTypes: ["builtin"], groups: [ ['builtin', 'external'], 'internal', 'parent', 'sibling', 'index', 'unknown' ], 'newlines-between': 'always' }], 'import-newlines/enforce': ['error', { items: 1, semi: true }], '@typescript-eslint/no-unused-vars': ['error', { 'args': 'none' }], '@typescript-eslint/no-empty-function': ['error', { 'allow': ['private-constructors'] }], '@typescript-eslint/array-type': 'error', '@typescript-eslint/consistent-type-imports': 'error', '@typescript-eslint/no-inferrable-types': ['error', { 'ignoreProperties': true }], '@typescript-eslint/restrict-template-expressions': 'off', '@stylistic/indent': ['error', 4, { 'ImportDeclaration': 1 }], '@stylistic/key-spacing': 'off', '@stylistic/comma-dangle': ['error', 'never'], '@stylistic/no-multi-spaces': 'off', '@stylistic/brace-style': ['error', '1tbs', { 'allowSingleLine': true }], '@stylistic/max-statements-per-line': ['error', { 'max': 2 }], '@stylistic/operator-linebreak': ['error', 'before'], '@stylistic/padding-line-between-statements': 'error', '@stylistic/implicit-arrow-linebreak': ['error', 'beside'], '@stylistic/no-extra-semi': 'error', '@stylistic/nonblock-statement-body-position': ['error', 'below'], '@stylistic/object-curly-newline': ['error', { 'multiline': true }], '@stylistic/switch-colon-spacing': 'error', '@stylistic/eol-last': ['error', 'always'], '@stylistic/jsx-quotes': ['error', 'prefer-single'], '@stylistic/multiline-ternary': 'off', 'import-x/no-unresolved': ['error'], 'import-x/no-named-as-default': 'off', 'import-x/no-named-as-default-member': 'off', 'import-x/default': 'off' } }, { files: ['**/*.tsx', '**/*.jsx'], plugins: { react: reactPlugin, 'react-hooks': reactHooksPlugin }, settings: { ...importResolverSettings, react: { version: 'detect' } }, rules: { 'react/jsx-uses-react': 'error', 'react/jsx-uses-vars': 'error', 'react/prop-types': 'off', 'react/react-in-jsx-scope': 'off', 'react-hooks/rules-of-hooks': 'error', 'react-hooks/exhaustive-deps': 'warn' } }, { ignores: [ '**/dist/', '**/node_modules/', '**/*.js', '!eslint.config.js' ] } ]);