UNPKG

@kununu/eslint-config

Version:
346 lines (308 loc) 11.7 kB
// we need to have the baseRules to have the same on the typescript override // because it has extends the eslint does not take into consideration the ones from the base const baseRules = { 'import/no-extraneous-dependencies': ['error', { devDependencies: [ '**/*.spec.js', '**/*.spec.jsx', '**/*.test.js', '**/*.test.jsx', '**/stories.jsx', '*/test-*/*.js', '*/test-*/*.jsx', 'config/**/*.js', 'jest.setup.js', 'jestsetup.js', 'mockBff/*', 'next.config.js', ], }], 'max-len': 'off', // Sometimes longer lines are more readable (Airbnb rule change) 'no-param-reassign': ['error', {props: false}], 'no-prototype-builtins': 'off', // Objects aren't created that don't extend from Object.prototype (Airbnb rule change) 'object-curly-spacing': 'off', // Disabled in favor of @babel/object-curly-spacing in order to avoid false positives with ECMAScript modules (Airbnb rule change) 'no-use-before-define': 'off', 'sort-destructure-keys/sort-destructure-keys': [2, {'caseSensitive': false}], // https://github.com/yannickcr/eslint-plugin-react/tree/master/docs/rules 'react/no-direct-mutation-state': 'error', // Use .setState() always (Airbnb rule change) // https://github.com/babel/babel/tree/main/eslint/babel-eslint-plugin#rules '@babel/object-curly-spacing': 'error', // No spaces in single-line objects to make nested objects like {a: {b: 'c'}} look more sane (Airbnb rule change) // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/ 'import/order': ['error', { // Make import sort order an error (Airbnb rule change) 'newlines-between': 'always', groups: [ 'builtin', // import fs from 'fs'; 'external', // import chalk from 'chalk'; 'internal', // import foo from 'src/foo'; 'parent', // import qux from '../qux'; 'sibling', // import bar from './bar'; 'index', // import main from './'; ], }], 'import/no-useless-path-segments': ['error', { 'noUselessIndex': true, }], // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/anchor-is-valid.md#rule-details // allow `Link` to have `to` and not the mandatory `href` 'jsx-a11y/anchor-is-valid': ['error', { components: ['Link'], specialLink: ['to'], }], // https://eslint.org/docs/rules/no-confusing-arrow // turn off to prevent conflict with // https://eslint.org/docs/rules/arrow-body-style 'no-confusing-arrow': 'off', // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/label-has-for.md // 'label' tags need 'htmlFor' prop, but nesting is not required 'jsx-a11y/label-has-for': ['error', { 'required': 'id', }], // https://eslint.org/docs/rules/padding-line-between-statements // enforce empty lines after variable declarations 'padding-line-between-statements': ['error', { 'blankLine': 'always', 'prev': ['const', 'let', 'var'], 'next': '*', }, { 'blankLine': 'any', 'prev': ['const', 'let', 'var'], 'next': ['const', 'let', 'var'], }], // https://www.npmjs.com/package/eslint-plugin-react-hooks // enforces the rules of react-hooks (call at top level and only from functional components; checks dependencies) 'react-hooks/rules-of-hooks': 'error', 'react-hooks/exhaustive-deps': 'warn', // https://eslint.org/docs/rules/no-underscore-dangle // no underscores at either the beginning or end of an identifier 'no-underscore-dangle': ['error', {'allow': ['__NEXT_DATA__', '__NEXT_REDUX_STORE__']}], 'no-multiple-empty-lines': ['error', {'max': 1, 'maxEOF': 1}], // https://eslint.org/docs/rules/eol-last // require newline at the end of files 'eol-last': ['error', 'always'], // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/sort-default-props.md // enforce defaultProps declarations alphabetical sorting 'react/sort-default-props': ['error', { 'ignoreCase': true }], // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-sort-props.md // enforce props alphabetical sorting 'react/jsx-sort-props': ['error', { 'ignoreCase': true }], // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/sort-prop-types.md // enforce propTypes declarations alphabetical sorting 'react/sort-prop-types': ['error', { 'ignoreCase': true }], // https://eslint.org/docs/rules/sort-keys // require object keys to be sorted 'sort-keys': ['error', 'asc', {'caseSensitive': false, 'natural': false}], // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/static-property-placement.md // enforces where React component static properties should be positioned 'react/static-property-placement': ['error', 'property assignment'], // https://eslint.org/docs/rules/indent // enforces a consistent 2 spaces indentation style 'indent': ['error', 2, { 'SwitchCase': 1 }], // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/state-in-constructor.md // enforces the state initialization style to be either in a constructor or with a class property 'react/state-in-constructor': 'off', // https://eslint.org/docs/rules/arrow-parens // enforces no braces where they can be omitted 'arrow-parens': ['error', 'as-needed'], // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/extensions.md 'import/extensions': ['error', 'ignorePackages', { 'js': 'never', 'jsx': 'never', 'ts': 'never', 'tsx': 'never', 'scss': 'ignorePackages', 'json': 'always' }], // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-props-no-spreading.md // disallow spread on html tags directly but allows it on React components 'react/jsx-props-no-spreading': ['error', { 'html': 'enforce', 'custom': 'ignore', }], // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/function-component-definition.md 'react/function-component-definition': 'off', 'react/react-in-jsx-scope': 'off', 'prefer-promise-reject-errors': 'off', 'no-restricted-exports': 'off', 'testing-library/prefer-screen-queries': 'off', 'testing-library/render-result-naming-convention': 'off', 'indent': 'off', 'prettier/prettier': [ 'error', { 'arrowParens': 'avoid', 'bracketSpacing': false, 'semi': true, 'singleQuote': true, 'trailingComma': 'all', }, ], 'import/order': [ 'error', { 'groups': [ 'builtin', 'external', 'internal', 'parent', 'sibling', 'index' ], 'newlines-between': 'always', 'alphabetize': { 'order': 'asc', 'caseInsensitive': true }, 'pathGroups': [ { 'pattern': 'react', 'group': 'builtin', 'position': 'before' }, { 'pattern': '@kununu/**', 'group': 'external', 'position': 'after' } ], 'pathGroupsExcludedImportTypes': ['react'] } ], 'lodash/import-scope': [2, 'method'], // https://react.dev/blog/2024/04/25/react-19-upgrade-guide#removed-proptypes-and-defaultprops 'react/require-default-props': 0, 'no-restricted-syntax': ['error', // Target JSX elements specifically { selector: 'ReturnStatement > LogicalExpression[operator="&&"] > JSXElement', message: 'Prefer early returns over logical expressions in return statements. Use if (condition) return value; instead.' }, // Target JSX fragments { selector: 'ReturnStatement > LogicalExpression[operator="&&"] > JSXFragment', message: 'Prefer early returns over logical expressions in return statements. Use if (condition) return value; instead.' }, // Target function calls (which could be component invocations) { selector: 'ReturnStatement > LogicalExpression[operator="&&"] > CallExpression', message: 'Prefer early returns over logical expressions in return statements. Use if (condition) return value; instead.' }, // Target object expressions (which could be props) { selector: 'ReturnStatement > LogicalExpression[operator="&&"] > ObjectExpression', message: 'Prefer early returns over logical expressions in return statements. Use if (condition) return value; instead.' }, // Target array expressions { selector: 'ReturnStatement > LogicalExpression[operator="&&"] > ArrayExpression', message: 'Prefer early returns over logical expressions in return statements. Use if (condition) return value; instead.' }, // Keep the sequence expression rules { selector: 'ReturnStatement > SequenceExpression LogicalExpression[operator="&&"]', message: 'Prefer early returns over logical expressions in return statements. Use if (condition) return value; instead.' }, { selector: 'ReturnStatement > ParenthesizedExpression > SequenceExpression LogicalExpression[operator="&&"]', message: 'Prefer early returns over logical expressions in return statements. Use if (condition) return value; instead.' } ], 'granular-selectors/granular-selectors': ['error', { // Array of patterns to include for selector function detection include: ['use.*Selector.*', 'use.*Store.*'] }] }; module.exports = { extends: [ 'airbnb', // Many strict rules for ECMAScript and React 'airbnb/hooks', 'plugin:import/errors', 'plugin:jest-dom/recommended', 'plugin:prettier/recommended', 'plugin:react-hooks/recommended', ], parser: '@babel/eslint-parser', plugins: [ '@babel', 'lodash', 'sort-destructure-keys', 'granular-selectors' ], env: { browser: true, jest: true, node: true, es6: true, }, rules: baseRules, overrides: [{ files: [ '**/__tests__/**/*.[jt]s?(x)', '**/?(*.)+(spec|test).[jt]s?(x)' ], extends: [ 'plugin:testing-library/react' ], }, { files: [ '**/*.ts', '**/*.tsx', ], extends: [ 'airbnb', // Many strict rules for ECMAScript and React 'airbnb-typescript', 'airbnb/hooks', 'plugin:@typescript-eslint/recommended', 'plugin:@typescript-eslint/stylistic', 'plugin:import/errors', 'plugin:jest-dom/recommended', 'plugin:prettier/recommended', 'plugin:react-hooks/recommended', ], parser: '@typescript-eslint/parser', plugins: [ 'typescript-sort-keys' ], rules: { ...baseRules, '@typescript-eslint/indent': 'off', '@typescript-eslint/no-use-before-define': ['error'], '@typescript-eslint/no-var-requires': 'off', 'react/prop-types': 'off', 'typescript-sort-keys/interface': ['error', 'asc', {'caseSensitive': false, 'natural': false, requiredFirst: true}], 'typescript-sort-keys/string-enum': ['error', 'asc', {'caseSensitive': false, 'natural': false}], 'import/no-extraneous-dependencies': ['error', { devDependencies: [ '**/*.spec.ts', '**/*.spec.tsx', '**/stories.tsx', ], }], }, overrides: [ { files: ['**/stories.tsx', '*.spec.ts', '*.spec.tsx'], rules: { '@typescript-eslint/no-explicit-any': 'off', }, } ], }, { files: ['*.spec.js', '*.spec.jsx', '*.spec.ts', '*.spec.tsx'], rules: { 'global-require': 'off', 'jsx-a11y/anchor-is-valid': 'off', }, }, { files: [ '**/reducers/**/*.js', '**/reducers/**/*.ts' ], rules: { 'default-param-last': 'off' } }], };