import { withDefaultOption, type EslintReactRules } from '../types/index.mjs'; export const eslintReactRules = { /** * Disable in favor of prettier * * @link https://github.com/prettier/eslint-config-prettier/blob/main/index.js */ 'react/jsx-child-element-spacing': 'off', 'react/jsx-closing-bracket-location': 'off', 'react/jsx-closing-tag-location': 'off', 'react/jsx-curly-newline': 'off', 'react/jsx-curly-spacing': 'off', 'react/jsx-equals-spacing': 'off', 'react/jsx-first-prop-new-line': 'off', 'react/jsx-indent': 'off', 'react/jsx-indent-props': 'off', 'react/jsx-max-props-per-line': 'off', 'react/jsx-newline': 'off', 'react/jsx-one-expression-per-line': 'off', 'react/jsx-props-no-multi-spaces': 'off', 'react/jsx-tag-spacing': 'off', 'react/jsx-wrap-multilines': 'off', 'react/boolean-prop-naming': withDefaultOption('error'), 'react/button-has-type': withDefaultOption('error'), 'react/default-props-match-prop-types': withDefaultOption('error'), /** Enforce consistent usage of props destructuring. */ 'react/destructuring-assignment': withDefaultOption('error'), 'react/display-name': 'off', // Covered by react-coding-style/display-name 'react/forbid-component-props': ['error', { forbid: ['className'] }], 'react/forbid-dom-props': withDefaultOption('error'), 'react/forbid-elements': withDefaultOption('error'), 'react/forbid-foreign-prop-types': withDefaultOption('error'), 'react/forbid-prop-types': withDefaultOption('error'), 'react/function-component-definition': [ 'error', { unnamedComponents: 'arrow-function', namedComponents: 'arrow-function' }, ], 'react/hook-use-state': 'off', 'react/iframe-missing-sandbox': 'error', 'react/jsx-boolean-value': ['error', 'never'], // Even if props is a string, it is necessary because the display will change, such as whether "\n" will cause a line break. 'react/jsx-curly-brace-presence': ['error', 'always'], /** Enforce consistent file naming */ // Not compatible with ESLint v10: this rule calls `context.getFilename()` // directly, which ESLint v10 removed, so it throws while loading. // It is the only rule in eslint-plugin-react that still does so. 'react/jsx-filename-extension': 'off', 'react/jsx-fragments': withDefaultOption('error'), 'react/jsx-handler-names': 'off', // disabled 'react/jsx-key': withDefaultOption('error'), 'react/jsx-max-depth': 'off', // disabled /** Prohibit inline callback functions in JSX. Fix: Use React.useCallback. */ 'react/jsx-no-bind': withDefaultOption('error'), 'react/jsx-no-comment-textnodes': 'error', 'react/jsx-no-constructed-context-values': 'error', 'react/jsx-no-duplicate-props': withDefaultOption('error'), /** * Avoid writing strings directly in JSX, enforce using `
{"aaa"}
` * format. Benefits: Easier to catch missing `{}` around variables, better * syntax highlighting for readability. */ 'react/jsx-no-literals': withDefaultOption('error'), 'react/jsx-no-script-url': withDefaultOption('error'), 'react/jsx-no-target-blank': withDefaultOption('error'), 'react/jsx-no-undef': withDefaultOption('error'), 'react/jsx-no-useless-fragment': ['error', { allowExpressions: true }], 'react/jsx-pascal-case': withDefaultOption('error'), /** * Avoid `{...props}` spread as it weakens type checking for props * excess/shortage */ 'react/jsx-props-no-spreading': withDefaultOption('error'), 'react/jsx-sort-props': [ 'error', { callbacksLast: true, reservedFirst: true }, ], 'react/jsx-uses-react': 'off', // disabled /** Enforce consistent file naming */ 'react/jsx-uses-vars': 'error', 'react/no-access-state-in-setstate': 'error', 'react/no-adjacent-inline-elements': 'error', 'react/no-array-index-key': 'error', 'react/no-arrow-function-lifecycle': 'error', 'react/no-children-prop': withDefaultOption('error'), 'react/no-danger-with-children': 'error', 'react/no-danger': withDefaultOption('error'), 'react/no-deprecated': 'error', 'react/no-did-mount-set-state': withDefaultOption('error'), 'react/no-did-update-set-state': withDefaultOption('error'), 'react/no-direct-mutation-state': 'error', 'react/no-find-dom-node': 'error', 'react/no-invalid-html-attribute': withDefaultOption('error'), 'react/no-is-mounted': 'error', 'react/no-multi-comp': [ 'error', { ignoreStateless: true, }, ], 'react/no-namespace': 'error', 'react/no-redundant-should-component-update': 'error', 'react/no-render-return-value': 'error', 'react/no-set-state': 'error', 'react/no-string-refs': withDefaultOption('error'), 'react/no-this-in-sfc': 'error', 'react/no-typos': 'error', 'react/no-unescaped-entities': withDefaultOption('error'), // Allow CSS prop for @emotion/react 'react/no-unknown-property': ['error', { ignore: ['css'] }], 'react/no-unsafe': withDefaultOption('error'), 'react/no-object-type-as-default-prop': 'error', 'react/no-unstable-nested-components': withDefaultOption('error'), 'react/no-unused-class-component-methods': 'error', 'react/no-unused-prop-types': withDefaultOption('error'), 'react/no-unused-state': 'error', 'react/no-will-update-set-state': withDefaultOption('error'), 'react/prefer-es6-class': withDefaultOption('error'), 'react/prefer-exact-props': 'error', 'react/prefer-read-only-props': 'error', 'react/prefer-stateless-function': withDefaultOption('error'), /** Not needed with TypeScript */ 'react/prop-types': 'off', 'react/react-in-jsx-scope': 'off', // disabled 'react/require-default-props': withDefaultOption('error'), 'react/require-optimization': withDefaultOption('error'), 'react/require-render-return': 'error', 'react/self-closing-comp': withDefaultOption('error'), 'react/sort-comp': withDefaultOption('error'), 'react/sort-default-props': withDefaultOption('error'), 'react/sort-prop-types': withDefaultOption('error'), 'react/state-in-constructor': withDefaultOption('error'), 'react/static-property-placement': withDefaultOption('error'), 'react/style-prop-object': withDefaultOption('error'), 'react/void-dom-elements-no-children': 'error', 'react/jsx-no-leaked-render': [ 'error', { validStrategies: ['ternary'], }, ], 'react/checked-requires-onchange-or-readonly': withDefaultOption('error'), 'react/jsx-props-no-spread-multi': 'error', // Not compatible with ESLint v10: this rule calls `context.getSourceCode()` // directly, which ESLint v10 removed, so it throws while loading. 'react/forward-ref-uses-ref': 'off', // deprecated 'react/jsx-sort-default-props': 0, 'react/jsx-space-before-closing': 0, } as const satisfies EslintReactRules;