UNPKG

eslint-config-galex

Version:
1,311 lines • 52.1 kB
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createRemixEslintPluginReactSettings = exports.createRemixJsImportResolverSettings = exports.createRemixRunOverride = exports.createRemixRoutesOverride = exports.remixRunRoutesOverrideRules = exports.remixRunRoutesOverrideFiles = exports.remixRules = exports.remixRunOverrideFiles = exports.createNextJsPagesOverride = exports.createNextJsRules = exports.createJSXA11yRules = exports.createReactRules = exports.createHookRules = exports.createReactOverride = exports.defaultSettings = exports.defaultParserOptions = exports.parser = exports.files = exports.plugins = void 0;
const array_1 = require("../utils/array");
const overrideType_1 = require("../utils/overrideType");
const prettier_1 = require("../utils/prettier");
const version_1 = require("../utils/version");
exports.plugins = ['jsx-a11y', 'react-hooks', 'react', '@next/next'];
exports.files = ['**/*.?(ts|js)?(x)'];
exports.parser = '@babel/eslint-parser';
exports.defaultParserOptions = {
    requireConfigFile: false,
    sourceType: 'module',
    ecmaFeatures: {
        jsx: true,
    },
};
exports.defaultSettings = {
    react: {
        version: 'detect',
    },
};
const createReactOverride = ({ rules: customRules, files: customFiles, parserOptions: customParserOptions, settings: customSettings, env: customEnv, excludedFiles: customExcludedFiles, extends: customExtends, globals: customGlobals, plugins: customPlugins, overrides: customOverrides, ...dependencies }) => {
    if (!dependencies.react.hasReact) {
        return null;
    }
    // required for `babel-preset-react-app`
    if (dependencies.react.isCreateReactApp && !process.env.NODE_ENV) {
        process.env.NODE_ENV = 'development';
    }
    const rules = {
        ...(0, exports.createReactRules)(dependencies),
        ...(0, exports.createNextJsRules)(dependencies),
        ...prettier_1.prettierReactRules,
        ...(0, exports.createJSXA11yRules)(dependencies),
        ...(0, exports.createHookRules)(dependencies),
        ...customRules,
    };
    const finalFiles = customFiles ?? exports.files;
    const finalOverrides = createOverrides(dependencies, customOverrides);
    const parserOptions = createParserOptions(dependencies, customParserOptions);
    const settings = createSettings(dependencies, customSettings);
    const finalPlugins = determinePlugins(dependencies, customPlugins);
    const finalExtends = customExtends;
    const finalExcludedFiles = customExcludedFiles;
    const finalGlobals = customGlobals;
    const finalEnv = customEnv;
    return {
        extends: finalExtends,
        files: finalFiles,
        parser: exports.parser,
        parserOptions,
        plugins: finalPlugins,
        settings,
        overrides: finalOverrides,
        rules,
        overrideType: overrideType_1.reactOverrideType,
        globals: finalGlobals,
        excludedFiles: finalExcludedFiles,
        env: finalEnv,
    };
};
exports.createReactOverride = createReactOverride;
const createOverrides = (dependencies, customOverrides = []) => {
    const nextJsOverride = (0, exports.createNextJsPagesOverride)(dependencies);
    const remixOverride = (0, exports.createRemixRunOverride)(dependencies);
    return [nextJsOverride, remixOverride, ...customOverrides].filter((dataset) => dataset !== null && typeof dataset === 'object');
};
const createSettings = (dependencies, customSettings) => {
    return {
        ...exports.defaultSettings,
        ...customSettings,
        react: {
            ...exports.defaultSettings.react,
            ...(0, exports.createRemixEslintPluginReactSettings)(dependencies),
            ...customSettings?.react,
        },
        ...(0, exports.createRemixJsImportResolverSettings)(dependencies),
    };
};
const determinePlugins = (dependencies, customPlugins) => {
    const allPlugins = (0, array_1.uniqueArrayEntries)([...exports.plugins, ...(customPlugins ?? [])]);
    if (!dependencies.react.isNext) {
        return allPlugins.filter(plugin => {
            return plugin !== '@next/next';
        });
    }
    return allPlugins;
};
const createParserOptions = (dependencies, customParserOptions) => {
    const presets = (0, array_1.uniqueArrayEntries)([
        dependencies.react.isNext
            ? 'next/babel'
            : dependencies.react.isCreateReactApp
                ? 'react-app'
                : !dependencies.typescript.hasTypeScript && '@babel/preset-react',
        ...(customParserOptions
            ? customParserOptions.babelOptions?.presets ?? []
            : []),
    ]);
    return {
        ...exports.defaultParserOptions,
        ...customParserOptions,
        ecmaFeatures: {
            ...exports.defaultParserOptions.ecmaFeatures,
            ...customParserOptions?.ecmaFeatures,
        },
        babelOptions: {
            presets,
        },
    };
};
/**
 * @see https://github.com/facebook/react/tree/master/packages/eslint-plugin-react-hooks
 */
const createHookRules = ({ react: { hasReact, version }, }) => {
    if (!hasReact ||
        !version ||
        !(0, version_1.fulfillsVersionRequirement)({
            given: version,
            expected: '^16.8.0',
        })) {
        return null;
    }
    return {
        /**
         * elevated to error because you either want all deps or you have to explicitly
         * disable the rule anyways
         *
         * @see https://reactjs.org/docs/hooks-rules.html
         */
        'react-hooks/exhaustive-deps': 'error',
        /**
         * prevents invalid hook calls (after early return e.g.)
         *
         * @see https://reactjs.org/docs/hooks-rules.html
         */
        'react-hooks/rules-of-hooks': 'error',
    };
};
exports.createHookRules = createHookRules;
/**
 * @see https://github.com/yannickcr/eslint-plugin-react/tree/master/docs/rules
 */
const createReactRules = ({ react: { isNext, version }, typescript: { hasTypeScript }, }) => {
    if (!version) {
        return null;
    }
    return {
        /**
         * off because it doesnt seem to work anyways
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/boolean-prop-naming.md
         */
        'react/boolean-prop-naming': 'off',
        /**
         * be explicit
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/button-has-type.md
         */
        'react/button-has-type': 'error',
        /**
         * off because use function default arguments or TS instead
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/default-props-match-prop-types.md
         */
        'react/default-props-match-prop-types': 'off',
        /**
         * prefer destructuring when possible. does lead to type limitations with TS,
         * hence its disabled there.
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/destructuring-assignment.md
         */
        'react/destructuring-assignment': hasTypeScript
            ? 'off'
            : ['error', 'always'],
        /**
         * off because anonymous default exports are forbidden
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/display-name.md
         */
        'react/display-name': 'off',
        /**
         * off because most props are perfectly valid
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/forbid-dom-props.md
         */
        'react/forbid-dom-props': 'off',
        /**
         * off because nothing is forbidden to use
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/forbid-elements.md
         */
        'react/forbid-elements': 'off',
        /**
         * avoids using potentially problematic props
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/forbid-component-props.md
         */
        'react/forbid-foreign-prop-types': ['warn', { allowInPropTypes: true }],
        /**
         * off because legacy
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/forbid-prop-types.md
         */
        'react/forbid-prop-types': 'off',
        /**
         * prefer function-declaration; if necessary e.g. React.memo(), use arrow-fn
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/function-component-definition.md
         */
        'react/function-component-definition': [
            'warn',
            {
                namedComponents: 'function-declaration',
                unnamedComponents: 'arrow-function',
            },
        ],
        /**
         * prevents unecessary code
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-boolean-value.md
         */
        'react/jsx-boolean-value': 'error',
        /**
         * off because prettier takes care of it
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-child-element-spacing.md
         */
        'react/jsx-child-element-spacing': 'off',
        /**
         * off because prettier takes care of it
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-closing-bracket-location.md
         */
        'react/jsx-closing-bracket-location': 'off',
        /**
         * off because prettier takes care of it
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-closing-tag-location.md
         */
        'react/jsx-closing-tag-location': 'off',
        /**
         * enforces consistency
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-curly-brace-presence.md
         */
        'react/jsx-curly-brace-presence': [
            'warn',
            {
                children: 'never',
                props: 'never',
            },
        ],
        /**
         * off because prettier takes care of it
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-curly-newline.md
         */
        'react/jsx-curly-newline': 'off',
        /**
         * off because prettier takes care of it
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-curly-spacing.md
         */
        'react/jsx-curly-spacing': 'off',
        /**
         * off because prettier takes care of it
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-equals-spacing.md
         */
        'react/jsx-equals-spacing': 'off',
        /**
         * off because subjective
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-filename-extension.md
         */
        'react/jsx-filename-extension': 'off',
        /**
         * off because why? also prettier takes care of it
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-first-prop-new-line.md
         */
        'react/jsx-first-prop-new-line': 'off',
        /**
         * prefer shorthand function of React.Fragment
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-fragments.md
         */
        'react/jsx-fragments': ['warn', 'syntax'],
        /**
         * prefer naming event handlers `on` or `handle`
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-handler-names.md
         */
        'react/jsx-handler-names': [
            'warn',
            {
                checkLocalVariables: false,
                eventHandlerPrefix: 'handle',
                eventHandlerPropPrefix: 'on',
            },
        ],
        /**
         * off because prettier takes care of it
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-indent.md
         */
        'react/jsx-indent': 'off',
        /**
         * off because prettier takes care of it
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-indent-props.md
         */
        'react/jsx-indent-props': 'off',
        /**
         * prevents mistakes
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-key.md
         */
        'react/jsx-key': [
            'warn',
            {
                checkFragmentShorthand: true,
                /**
                 * only active with new React JSX transform
                 *
                 * @see https://github.com/facebook/react/issues/20031#issuecomment-710346866
                 * @see https://togithub.com/yannickcr/eslint-plugin-react/pull/2835
                 */
                checkKeyMustBeforeSpread: (0, version_1.fulfillsVersionRequirement)({
                    given: version,
                    expected: '^17.0.0',
                }),
            },
        ],
        /**
         * off because arbitrary
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-max-depth.md
         */
        'react/jsx-max-depth': 'off',
        /**
         * off because prettier takes care of it
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-max-props-per-line.md
         */
        'react/jsx-max-props-per-line': 'off',
        /**
         * enforces new line after jsx elements and expressions
         *
         * off because opinionated
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-newline.md
         */
        'react/jsx-newline': 'off',
        /**
         * off because its nonsensical to enforce memoizing every function
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-bind.md
         */
        'react/jsx-no-bind': 'off',
        /**
         * prevents comments from being inserted as text nodes
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-comment-textnodes.md
         */
        'react/jsx-no-comment-textnodes': 'warn',
        /**
         * prevents potential performance issues using React.createContext Provider
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-constructed-context-values.md
         */
        'react/jsx-no-constructed-context-values': 'warn',
        /**
         * prevents duplicate props
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-duplicate-props.md
         */
        'react/jsx-no-duplicate-props': 'error',
        /**
         * off because why
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-literals.md
         */
        'react/jsx-no-literals': 'off',
        /**
         * react warns anyways; once react throws an error, this can probably be
         * turned off
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-script-url.md
         */
        'react/jsx-no-script-url': 'warn',
        /**
         * prevents usage of `target="_blank"` without `rel="noreferrer"`
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-target-blank.md
         */
        'react/jsx-no-target-blank': 'warn',
        /**
         * off simply because I don't get the docs
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-undef.md
         */
        'react/jsx-no-undef': 'off',
        /**
         * prevents unecessary code
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-useless-fragment.md
         */
        'react/jsx-no-useless-fragment': 'warn',
        /**
         * off because prettier takes care of it
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-one-expression-per-line.md
         */
        'react/jsx-one-expression-per-line': 'off',
        /**
         * enforce PascalCase for components
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-pascal-case.md
         */
        'react/jsx-pascal-case': [
            'warn',
            {
                allowAllCaps: true,
                ignore: [],
            },
        ],
        /**
         * off because prettier takes care of it
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-props-no-multi-spaces.md
         */
        'react/jsx-props-no-multi-spaces': 'off',
        /**
         * spreading is love, spreading is life
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-props-no-spreading.md
         */
        'react/jsx-props-no-spreading': 'off',
        /**
         * enforce alphabetical sorting of props
         * off because although its nice in theory, its really impractical sadly
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-sort-props.md
         */
        'react/jsx-sort-props': 'off',
        /**
         * off because prettier takes care of it
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-space-before-closing.md
         */
        'react/jsx-space-before-closing': 'off',
        /**
         * off because prettier takes care of it
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-tag-spacing.md
         */
        'react/jsx-tag-spacing': 'off',
        /**
         * warns about unused react import
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-uses-react.md
         */
        'react/jsx-uses-react': 'warn',
        /**
         * off because TypeScript itself takes care of it
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-uses-vars.md
         */
        'react/jsx-uses-vars': hasTypeScript ? 'off' : 'warn',
        /**
         * off because prettier takes care of it
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-wrap-multilines.md
         */
        'react/jsx-wrap-multilines': 'off',
        /**
         * off because not every state update depends on the previous
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-access-state-in-setstate.md
         */
        'react/no-access-state-in-setstate': 'off',
        /**
         * off because design is not eslint territory
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-adjacent-inline-elements.md
         */
        'react/no-adjacent-inline-elements': 'off',
        /**
         * warns when using array keys as keys - it _might_ lead to issues, situational
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-array-index-key.md
         */
        'react/no-array-index-key': 'warn',
        /**
         * off because function components are preferred anyways and theres little
         * reason to prevent this anyways
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-arrow-function-lifecycle.md
         */
        'react/no-arrow-function-lifecycle': 'off',
        /**
         * use children as intended
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-children-prop.md
         */
        'react/no-children-prop': 'error',
        /**
         * prevents unintended use of dangerouslySetInnerHTML
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-danger.md
         */
        'react/no-danger': 'warn',
        /**
         * prevents using dangerouslySetInnerHTML together with children
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-danger-with-children.md
         */
        'react/no-danger-with-children': 'error',
        /**
         * new code should not contain deprecated. for anything else, disable the rule
         * if necessary
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-deprecated.md
         */
        'react/no-deprecated': 'error',
        /**
         * off because nonsensical, default behaviour of setting state after e.g. fetch
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-did-mount-set-state.md
         */
        'react/no-did-mount-set-state': 'off',
        /**
         * warn because it _probably_ can be solved in other ways
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-did-update-set-state.md
         */
        'react/no-did-update-set-state': 'warn',
        /**
         * prevents direct state mutation
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-direct-mutation-state.md
         */
        'react/no-direct-mutation-state': 'error',
        /**
         * prevents deprecated use of `findDOMNode`
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-find-dom-node.md
         */
        'react/no-find-dom-node': 'error',
        /**
         * disallows improper use of html attributes
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-invalid-html-attribute.md
         */
        'react/no-invalid-html-attribute': hasTypeScript ? 'off' : 'warn',
        /**
         * prevents deprecated use if `isMounted()`
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-is-mounted.md
         */
        'react/no-is-mounted': 'error',
        /**
         * off because nonsensical
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-multi-comp.md
         */
        'react/no-multi-comp': 'off',
        /**
         * forbids usage of namespaces
         *
         * @see https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/no-object-type-as-default-prop.md
         */
        'react/no-namespace': 'warn',
        /**
         * forbids assugning references as default param in fn components
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-namespace.md
         */
        'react/no-object-type-as-default-prop': 'error',
        /**
         * prevents use of `shouldComponentUpdate` in `PureComponent`
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-redundant-should-component-update.md
         */
        'react/no-redundant-should-component-update': 'error',
        /**
         * prevents use of legacy return value of `ReactDOM.render`
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-render-return-value.md
         */
        'react/no-render-return-value': 'off',
        /**
         * off because pointless
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-set-state.md
         */
        'react/no-set-state': 'off',
        /**
         * prevents use of legacy string refs
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-string-refs.md
         */
        'react/no-string-refs': 'error',
        /**
         * prevents use of `this` in stateless functional components
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-this-in-sfc.md
         */
        'react/no-this-in-sfc': 'error',
        /**
         * prevents common typos using class lifecycle methods
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-typos.md
         */
        'react/no-typos': 'error',
        /**
         * off because not needed
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-unescaped-entities.md
         */
        'react/no-unescaped-entities': 'off',
        /**
         * prevents usage of invalid/unknown DOM properties
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-unknown-property.md
         */
        'react/no-unknown-property': 'warn',
        /**
         * prevents use of `UNSAFE_` methods
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-unsafe.md
         */
        'react/no-unsafe': 'error',
        /**
         * hints unused prop types
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-unused-prop-types.md
         */
        'react/no-unused-prop-types': 'warn',
        /**
         * prevents dead code
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-unused-state.md
         */
        'react/no-unused-state': 'warn',
        /**
         * prevents usage of `setState` in `componentWillUpdate`
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-will-update-set-state.md
         */
        'react/no-will-update-set-state': 'warn',
        /**
         * enforce es6/es6 classes for components
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prefer-es6-class.md
         */
        'react/prefer-es6-class': 'error',
        /**
         * off because only works for classes and Flow
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prefer-read-only-props.md
         */
        'react/prefer-read-only-props': 'off',
        /**
         * off because SFC is basically dead
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prefer-stateless-function.md
         */
        'react/prefer-stateless-function': 'off',
        /**
         * off because TypeScript solves this
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prop-types.md
         */
        'react/prop-types': 'off',
        /**
         * neither Next.js nor React >= 17 need React to be in scope
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/react-in-jsx-scope.md
         */
        'react/react-in-jsx-scope': isNext ||
            (0, version_1.fulfillsVersionRequirement)({ given: version, expected: '^17.0.0' })
            ? 'off'
            : 'error',
        /**
         * off because use function default arguments
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/require-default-props.md
         */
        'react/require-default-props': 'off',
        /**
         * off because premature optimization
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/require-optimization.md
         */
        'react/require-optimization': 'off',
        /**
         * hints `return` requirement in `render` of class components
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/require-render-return.md
         */
        'react/require-render-return': 'error',
        /**
         * prevents extra closing tags for components without children
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/self-closing-comp.md
         */
        'react/self-closing-comp': 'warn',
        /**
         * off because not autofixable
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/sort-comp.md
         */
        'react/sort-comp': 'off',
        /**
         * off because `sort-keys-fix` already takes care of it
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/sort-default-props.md
         */
        'react/sort-default-props': 'off',
        /**
         * off because `sort-keys-fix` takes care of it
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/sort-prop-types.md
         */
        'react/sort-prop-types': 'off',
        /**
         * off because state should be properties
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/state-in-constructor.md
         */
        'react/state-in-constructor': 'off',
        /**
         * enforces static properties to be within the class
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/static-property-placement.md
         */
        'react/static-property-placement': ['error', 'static public field'],
        /**
         * enforce style prop to be an object
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/style-prop-object.md
         */
        'react/style-prop-object': 'warn',
        /**
         * prevents passing children to void elements
         *
         * @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/void-dom-elements-no-children.md
         */
        'react/void-dom-elements-no-children': 'error',
    };
};
exports.createReactRules = createReactRules;
/**
 * @see https://github.com/evcohen/eslint-plugin-jsx-a11y/tree/master/docs/rules
 */
const createJSXA11yRules = ({ react: { isNext, isCreateReactApp, isRemix }, }) => {
    return {
        /**
         * off because deprecated
         *
         * @see https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/accessible-emoji.md
         */
        'jsx-a11y/accessible-emoji': 'off',
        /**
         * enforces <img alt /> attribute
         *
         * @see https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/alt-text.md
         */
        'jsx-a11y/alt-text': 'error',
        /**
         * prevents unreasonable link descriptions
         *
         * off because extremely limited selection of words and generally questionable
         *
         * @see https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/anchor-ambiguous-text.md
         */
        'jsx-a11y/anchor-ambiguous-text': 'off',
        /**
         * enforces `children` in `a`
         *
         * @see https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/anchor-has-content.md
         * @see https://github.com/remix-run/remix/blob/main/packages/remix-eslint-config/rules/jsx-a11y.js#L8
         */
        'jsx-a11y/anchor-has-content': isRemix
            ? [
                'error',
                {
                    components: ['Link', 'NavLink'],
                },
            ]
            : 'error',
        /**
         * ensures core `a` attributes are valid
         *
         * exclude `noHref` validation for Nextjs because
         *
         * @example
         * ```js
         * <Link passHref href="/foo">
         *  <a>hi</a
         * </Link>
         * ```
         * is valid
         *
         * @see https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/anchor-is-valid.md
         */
        'jsx-a11y/anchor-is-valid': [
            'error',
            {
                aspects: [
                    'invalidHref',
                    isNext ? null : 'noHref',
                    'preferButton',
                ].filter(Boolean),
                components: isNext ? ['Link'] : [],
            },
        ],
        /**
         * ensures using `aria-activedescendant` also has a valid `tabIndex`
         *
         * @see https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/aria-activedescendant-has-tabindex.md
         */
        'jsx-a11y/aria-activedescendant-has-tabindex': 'warn',
        /**
         * disallows invalid `aria-*` attributes
         *
         * @see https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/aria-props.md
         */
        'jsx-a11y/aria-props': 'error',
        /**
         * enforces correct values for `aria-*` values
         *
         * @see https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/aria-proptypes.md
         */
        'jsx-a11y/aria-proptypes': 'error',
        /**
         * enforces use of real `aria-role` values
         *
         * @see https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/aria-role.md
         */
        'jsx-a11y/aria-role': ['warn', { ignoreNonDOM: true }],
        /**
         * enforces using `aria-*` attributes only on elements that support it
         *
         * @see https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/aria-unsupported-elements.md
         */
        'jsx-a11y/aria-unsupported-elements': 'error',
        /**
         * enforces proper use of the `autocomplete` property
         *
         * @see https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/autocomplete-valid.md
         */
        ...(isCreateReactApp ? null : { 'jsx-a11y/autocomplete-valid': 'error' }),
        /**
         * enforces `onClick`s are accompanied by at least one of `onKey*`
         *
         * __EXPERIMENTAL__
         *
         * @see https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/click-events-have-key-events.md
         */
        'jsx-a11y/click-events-have-key-events': 'warn',
        /**
         * enforces use of `aria-label` where needed
         *
         * @see https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/control-has-associated-label.md
         */
        'jsx-a11y/control-has-associated-label': 'warn',
        /**
         * enforces `h1` etc. have content
         *
         * @see https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/heading-has-content.md
         */
        'jsx-a11y/heading-has-content': 'warn',
        /**
         * ensures `html` tag has a `lang` attribute
         *
         * @see https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/html-has-lang.md
         */
        'jsx-a11y/html-has-lang': 'warn',
        /**
         * ensures `iframe` tag has a `title` attribute
         *
         * @see https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/iframe-has-title.md
         */
        'jsx-a11y/iframe-has-title': 'warn',
        /**
         * ensures validity of `img` `alt` attribute
         *
         * @see https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/img-redundant-alt.md
         */
        'jsx-a11y/img-redundant-alt': 'warn',
        /**
         * @see https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/interactive-supports-focus.md
         */
        'jsx-a11y/interactive-supports-focus': 'error',
        /**
         * enforce that a `label` tag has a text label and an associated control
         *
         * @see https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/label-has-associated-control.md
         */
        'jsx-a11y/label-has-associated-control': 'error',
        /**
         * off because deprecated in favor of `jsx-a11y/label-has-associated-control'
         *
         * @see https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/label-has-for.md
         * @see https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/label-has-associated-control.md
         */
        'jsx-a11y/label-has-for': 'off',
        /**
         * ensures `html` tag has a valid `lang` attribute
         *
         * @see https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/lang.md
         */
        'jsx-a11y/lang': 'error',
        /**
         * ensures media elements have captions
         *
         * @see https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/media-has-caption.md
         */
        'jsx-a11y/media-has-caption': 'warn',
        /**
         * enforce `onMouse*` are accompanied by `onFocus`/`onBlur`
         *
         * @see https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/mouse-events-have-key-events.md
         */
        'jsx-a11y/mouse-events-have-key-events': 'error',
        /**
         * enforce no `accessKey` prop on element
         *
         * @see https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/no-access-key.md
         */
        'jsx-a11y/no-access-key': 'warn',
        /**
         * prevent adding `aria-hidden` on focusable elements
         *
         * @see https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/no-aria-hidden-on-focusable.md
         */
        'jsx-a11y/no-aria-hidden-on-focusable': 'error',
        /**
         * enforce that `autoFocus` prop is not used on elements
         *
         * @see https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/no-autofocus.md
         */
        'jsx-a11y/no-autofocus': 'error',
        /**
         * enforces that no distracting elements are used
         *
         * @see https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/no-distracting-elements.md
         */
        'jsx-a11y/no-distracting-elements': 'warn',
        /**
         * use appropriate tags
         *
         * @see https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/no-interactive-element-to-noninteractive-role.md
         */
        'jsx-a11y/no-interactive-element-to-noninteractive-role': 'error',
        /**
         * prevents assigning interactions to non-interactive elements
         *
         * @see https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/no-noninteractive-element-interactions.md
         */
        'jsx-a11y/no-noninteractive-element-interactions': 'error',
        /**
         * prevents assigning interactive roles to non-interactive elements
         *
         * @see https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/no-noninteractive-element-to-interactive-role.md
         */
        'jsx-a11y/no-noninteractive-element-to-interactive-role': [
            'error',
            {
                li: ['menuitem', 'option', 'row', 'tab', 'treeitem'],
                ol: [
                    'listbox',
                    'menu',
                    'menubar',
                    'radiogroup',
                    'tablist',
                    'tree',
                    'treegrid',
                ],
                table: ['grid'],
                td: ['gridcell'],
                ul: [
                    'listbox',
                    'menu',
                    'menubar',
                    'radiogroup',
                    'tablist',
                    'tree',
                    'treegrid',
                ],
            },
        ],
        /**
         * limits tab key navigation to elements that can be interacted with
         *
         * @see https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/no-noninteractive-tabindex.md
         */
        'jsx-a11y/no-noninteractive-tabindex': 'error',
        /**
         * prefer `onBlur` over `onChange`
         *
         * off because deprecated
         *
         * @see https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/no-onchange.md
         */
        'jsx-a11y/no-onchange': 'off',
        /**
         * prevents roles on elements that already have the role implicitly
         *
         * @see https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/no-redundant-roles.md
         */
        'jsx-a11y/no-redundant-roles': 'warn',
        /**
         * prevents assigning interactions to static elements
         *
         * use a role
         *
         * @see https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/no-static-element-interactions.md
         */
        'jsx-a11y/no-static-element-interactions': 'error',
        /**
         * enforces semantic dom elements over `role` property usage
         *
         * @see https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/prefer-tag-over-role.md
         */
        'jsx-a11y/prefer-tag-over-role': 'error',
        /**
         * elements with roles must have all required attributes for that role
         *
         * @see https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/role-has-required-aria-props.md
         */
        'jsx-a11y/role-has-required-aria-props': 'error',
        /**
         * enforce that elements with roles defined contain only `aria-*` properties
         * supported by that role
         *
         * @see https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/role-supports-aria-props.md
         */
        'jsx-a11y/role-supports-aria-props': 'error',
        /**
         * prevents using `scope` prop on anything other than `th`
         *
         * @see https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/scope.md
         */
        'jsx-a11y/scope': 'error',
        /**
         * prevents positive `tabIndex` props to not mess with page flow
         *
         * @see https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/tabindex-no-positive.md
         */
        'jsx-a11y/tabindex-no-positive': 'error',
    };
};
exports.createJSXA11yRules = createJSXA11yRules;
const createNextJsRules = ({ react: { isNext }, typescript: { hasTypeScript }, }) => {
    if (!isNext) {
        return null;
    }
    return {
        /**
         * should be imported directly
         *
         * @see https://github.com/vercel/next.js/blob/canary/packages/eslint-plugin-next/lib/rules/no-css-tags.js
         */
        '@next/next/no-css-tags': 'warn',
        /**
         * sync scripts can impact performance
         *
         * @see https://github.com/vercel/next.js/blob/canary/packages/eslint-plugin-next/lib/rules/no-sync-scripts.js
         */
        '@next/next/no-sync-scripts': 'warn',
        /**
         * disallows regular <a> links
         *
         * @see https://github.com/vercel/next.js/blob/canary/packages/eslint-plugin-next/lib/rules/no-html-link-for-pages.js
         */
        '@next/next/no-html-link-for-pages': 'warn',
        /**
         * prohibit usage of HTML <img> element
         *
         * off because project dependant; incompatible with next export etc.
         *
         * @see https://github.com/vercel/next.js/blob/canary/packages/eslint-plugin-next/lib/rules/no-img-element.js
         */
        '@next/next/no-img-element': 'off',
        /**
         * prohibits usage of HTML <head> element
         *
         * @see https://github.com/vercel/next.js/blob/canary/packages/eslint-plugin-next/lib/rules/no-head-element.js
         */
        '@next/next/no-head-element': 'error',
        /**
         * disallow of polyfill.io in some cases
         *
         * @see https://github.com/vercel/next.js/blob/canary/packages/eslint-plugin-next/lib/rules/no-unwanted-polyfillio.ts
         */
        '@next/next/no-unwanted-polyfillio': 'warn',
        /**
         * recommend adding custom font in a custom document and not in a specific page
         *
         * @see https://github.com/vercel/next.js/blob/canary/packages/eslint-plugin-next/lib/rules/no-page-custom-font.ts
         */
        '@next/next/no-page-custom-font': 'warn',
        /**
         * disallow using <title> with `Head` from `next/document`
         *
         * @see https://github.com/vercel/next.js/blob/canary/packages/eslint-plugin-next/lib/rules/no-title-in-document-head.ts
         */
        '@next/next/no-title-in-document-head': 'warn',
        /**
         * ensure correct font-display property is assigned for Google Fonts
         *
         * @see https://github.com/vercel/next.js/blob/canary/packages/eslint-plugin-next/lib/rules/google-font-display.ts
         */
        '@next/next/google-font-display': 'warn',
        /**
         * ensures preconnect is used with Google Fonts
         *
         * @see https://github.com/vercel/next.js/blob/canary/packages/eslint-plugin-next/lib/rules/google-font-preconnect.ts
         */
        '@next/next/google-font-preconnect': 'error',
        /**
         * disallow importing `next/document` outside of pages/document.js
         *
         * off until https://github.com/vercel/next.js/issues/28169 is resolved
         *
         * @see https://github.com/vercel/next.js/blob/canary/packages/eslint-plugin-next/lib/rules/no-document-import-in-page.ts
         */
        '@next/next/no-document-import-in-page': 'off',
        /**
         * disallow importing `next/head` in pages/document.js
         *
         * @see https://github.com/vercel/next.js/blob/canary/packages/eslint-plugin-next/lib/rules/no-head-import-in-document.ts
         */
        '@next/next/no-head-import-in-document': 'error',
        /**
         * disallow importing `next/script` inside `next/head`
         *
         * @see https://github.com/vercel/next.js/blob/canary/packages/eslint-plugin-next/src/rules/no-script-component-in-head.ts
         */
        '@next/next/no-script-component-in-head': 'error',
        /**
         * tries to correct typos for page-related exports
         *
         * @see https://github.com/vercel/next.js/blob/canary/packages/eslint-plugin-next/lib/rules/no-typos.ts
         */
        '@next/next/no-typos': 'warn',
        /**
         * enforces singular usage of <Head> in _document
         *
         * @see https://github.com/vercel/next.js/blob/canary/packages/eslint-plugin-next/lib/rules/no-duplicate-head.ts
         */
        '@next/next/no-duplicate-head': 'error',
        /**
         * next/script components with inline content must specify an `id` attribute
         *
         * @see https://github.com/vercel/next.js/blob/canary/packages/eslint-plugin-next/lib/rules/inline-script-id.ts
         */
        '@next/next/inline-script-id': 'error',
        /**
         * use next/script component for loading third party scripts
         *
         * @see https://github.com/vercel/next.js/blob/canary/packages/eslint-plugin-next/lib/rules/next-script-for-ga.ts
         */
        '@next/next/next-script-for-ga': 'warn',
        ...(hasTypeScript
            ? null
            : {
                /**
                 * prevents reassigning the variable `module`
                 *
                 * @see https://github.com/vercel/next.js/blob/canary/packages/eslint-plugin-next/lib/rules/no-assign-module-variable.js
                 */
                '@next/next/no-assign-module-variable': 'warn',
            }),
        /**
         * prevents next/script beforeInteractive strategy outside of document
         *
         * @see https://nextjs.org/docs/messages/no-before-interactive-script-outside-document
         */
        '@next/next/no-before-interactive-script-outside-document': 'error',
        /**
         * prevents usages of styled-jsx in document
         *
         * @see https://nextjs.org/docs/messages/no-before-interactive-script-outside-document
         */
        '@next/next/no-styled-jsx-in-document': 'error',
    };
};
exports.createNextJsRules = createNextJsRules;
// files within `pages/` and `/src/pages` require a default export
const nextJsPagesOverrideFiles = [
    'src/pages/**/*.?(t|j)s?(x)',
    'pages/**/*.?(t|j)s?(x)',
];
const nextJsPagesRules = {
    'import/no-default-export': 'off',
};
const createNextJsPagesOverride = dependencies => {
    if (!dependencies.react.isNext) {
        return null;
    }
    return {
        files: nextJsPagesOverrideFiles,
        rules: nextJsPagesRules,
    };
};
exports.createNextJsPagesOverride = createNextJsPagesOverride;
exports.remixRunOverrideFiles = [
    'app/**/*.?(t|j)s?(x)',
];
exports.remixRules = {
    'import/no-default-export': 'off',
};
exports.remixRunRoutesOverrideFiles = [
    '**/routes/**/*.js?(x)',
    '**/routes/**/*.tsx',
];
exports.remixRunRoutesOverrideRules = {
    'react/display-name': 'off',
};
/**
 * @param dependencies see https://github.com/remix-run/remix/blob/main/packages/remix-eslint-config/index.js#L82
 */
const createRemixRoutesOverride = dependencies => {
    if (!dependencies.react.isRemix) {
        return null;
    }
    return {
        files: exports.remixRunRoutesOverrideFiles,
        rules: exports.remixRunRoutesOverrideRules,
    };
};
exports.createRemixRoutesOverride = createRemixRoutesOverride;
const createRemixRunOverride = dependencies => {
    if (!dependencies.react.isRemix) {
        return null;
    }
    return {
        files: exports.remixRunOverrideFiles,
        rules: exports.remixRules,
        overrides: [(0, exports.createRemixRoutesOverride)(dependencies)].filter((override) => override !== null),
    };
};
exports.createRemixRunOverride = createRemixRunOverride;
const createRemixJsImportResolverSettings = (dependencies) => {
    if (!dependencies.react.isRemix) {
        return null;
    }
    return {
        // see https://github.com/remix-run/remix/blob/main/packages/remix-eslint-config/settings/import.js
        'import/ignore': ['node_modules', '\\.(css|md|svg|json)$'],
        ...(dependencies.typescript.hasTypeScript
            ? {
                'import/parsers': {
                    '@typescript-eslint/parser': ['.ts', '.tsx', '.d.ts'],
                },
            }
            : null),
        'import/resolver': {
            ...(dependencies.typescript.hasTypeScript
                ? {
                    typescript: {
                        alwaysTryTypes: true,
                    },
                }
                : {
                    jsconfig: {
                        config: 'jsconfig.json',
                    },
                }),
            node: {
                extensions: [
                    '.js',
                    '.jsx',
                    ...(dependencies.typescript.hasTypeScript ? ['.ts', '.tsx'] : []),
                ],
            },
        },
    };
};
exports.createRemixJsImportResolverSettings = createRemixJsImportResolverSettings;
/**
 * @see https://github.com/remix-run/remix/blob/main/packages/remix-eslint-config/settings/react.js#L4
 */
const createRemixEslintPluginReactSettings = (dependendencies) => {
    if (!dependendencies.react.isRemix) {
        return null;
    }
    return {
        // detect is already covered in default settings
        formComponents: ['Form'],
        linkComponents: [
            {
                name: 'Link',
                linkAttribute: 'to',
            },
            {
                name: 'NavLink',
                linkAttribute: 'to',
            },
        ],
    };
};
exports.createRemixEslintPluginReactSettings = createRemixEslintPluginReactSettings;