| 1 | 'use strict';
|
|---|
| 2 |
|
|---|
| 3 | const fromEntries = require('object.fromentries');
|
|---|
| 4 | const entries = require('object.entries');
|
|---|
| 5 |
|
|---|
| 6 | const allRules = require('./lib/rules');
|
|---|
| 7 |
|
|---|
| 8 | function filterRules(rules, predicate) {
|
|---|
| 9 | return fromEntries(entries(rules).filter((entry) => predicate(entry[1])));
|
|---|
| 10 | }
|
|---|
| 11 |
|
|---|
| 12 | /**
|
|---|
| 13 | * @param {object} rules - rules object mapping rule name to rule module
|
|---|
| 14 | * @returns {Record<string, SEVERITY_ERROR | 'error'>}
|
|---|
| 15 | */
|
|---|
| 16 | function configureAsError(rules) {
|
|---|
| 17 | return fromEntries(Object.keys(rules).map((key) => [`react/${key}`, 2]));
|
|---|
| 18 | }
|
|---|
| 19 |
|
|---|
| 20 | /** @type {Partial<typeof allRules>} */
|
|---|
| 21 | const activeRules = filterRules(allRules, (rule) => !rule.meta.deprecated);
|
|---|
| 22 | /** @type {Record<keyof typeof activeRules, 2 | 'error'>} */
|
|---|
| 23 | const activeRulesConfig = configureAsError(activeRules);
|
|---|
| 24 |
|
|---|
| 25 | /** @type {Partial<typeof allRules>} */
|
|---|
| 26 | const deprecatedRules = filterRules(allRules, (rule) => rule.meta.deprecated);
|
|---|
| 27 |
|
|---|
| 28 | /** @type {['react']} */
|
|---|
| 29 | // for legacy config system
|
|---|
| 30 | const plugins = [
|
|---|
| 31 | 'react',
|
|---|
| 32 | ];
|
|---|
| 33 |
|
|---|
| 34 | // TODO: with TS 4.5+, inline this
|
|---|
| 35 | const SEVERITY_ERROR = /** @type {2} */ (2);
|
|---|
| 36 | const SEVERITY_OFF = /** @type {0} */ (0);
|
|---|
| 37 |
|
|---|
| 38 | const configs = {
|
|---|
| 39 | recommended: {
|
|---|
| 40 | plugins,
|
|---|
| 41 | parserOptions: {
|
|---|
| 42 | ecmaFeatures: {
|
|---|
| 43 | jsx: true,
|
|---|
| 44 | },
|
|---|
| 45 | },
|
|---|
| 46 | rules: {
|
|---|
| 47 | 'react/display-name': SEVERITY_ERROR,
|
|---|
| 48 | 'react/jsx-key': SEVERITY_ERROR,
|
|---|
| 49 | 'react/jsx-no-comment-textnodes': SEVERITY_ERROR,
|
|---|
| 50 | 'react/jsx-no-duplicate-props': SEVERITY_ERROR,
|
|---|
| 51 | 'react/jsx-no-target-blank': SEVERITY_ERROR,
|
|---|
| 52 | 'react/jsx-no-undef': SEVERITY_ERROR,
|
|---|
| 53 | 'react/jsx-uses-react': SEVERITY_ERROR,
|
|---|
| 54 | 'react/jsx-uses-vars': SEVERITY_ERROR,
|
|---|
| 55 | 'react/no-children-prop': SEVERITY_ERROR,
|
|---|
| 56 | 'react/no-danger-with-children': SEVERITY_ERROR,
|
|---|
| 57 | 'react/no-deprecated': SEVERITY_ERROR,
|
|---|
| 58 | 'react/no-direct-mutation-state': SEVERITY_ERROR,
|
|---|
| 59 | 'react/no-find-dom-node': SEVERITY_ERROR,
|
|---|
| 60 | 'react/no-is-mounted': SEVERITY_ERROR,
|
|---|
| 61 | 'react/no-render-return-value': SEVERITY_ERROR,
|
|---|
| 62 | 'react/no-string-refs': SEVERITY_ERROR,
|
|---|
| 63 | 'react/no-unescaped-entities': SEVERITY_ERROR,
|
|---|
| 64 | 'react/no-unknown-property': SEVERITY_ERROR,
|
|---|
| 65 | 'react/no-unsafe': SEVERITY_OFF,
|
|---|
| 66 | 'react/prop-types': SEVERITY_ERROR,
|
|---|
| 67 | 'react/react-in-jsx-scope': SEVERITY_ERROR,
|
|---|
| 68 | 'react/require-render-return': SEVERITY_ERROR,
|
|---|
| 69 | },
|
|---|
| 70 | },
|
|---|
| 71 | all: {
|
|---|
| 72 | plugins,
|
|---|
| 73 | parserOptions: {
|
|---|
| 74 | ecmaFeatures: {
|
|---|
| 75 | jsx: true,
|
|---|
| 76 | },
|
|---|
| 77 | },
|
|---|
| 78 | rules: activeRulesConfig,
|
|---|
| 79 | },
|
|---|
| 80 | 'jsx-runtime': {
|
|---|
| 81 | plugins,
|
|---|
| 82 | parserOptions: {
|
|---|
| 83 | ecmaFeatures: {
|
|---|
| 84 | jsx: true,
|
|---|
| 85 | },
|
|---|
| 86 | jsxPragma: null, // for @typescript/eslint-parser
|
|---|
| 87 | },
|
|---|
| 88 | rules: {
|
|---|
| 89 | 'react/react-in-jsx-scope': SEVERITY_OFF,
|
|---|
| 90 | 'react/jsx-uses-react': SEVERITY_OFF,
|
|---|
| 91 | },
|
|---|
| 92 | },
|
|---|
| 93 | flat: /** @type {Record<string, ReactFlatConfig>} */ ({
|
|---|
| 94 | __proto__: null,
|
|---|
| 95 | }),
|
|---|
| 96 | };
|
|---|
| 97 |
|
|---|
| 98 | /** @typedef {{ plugins: { react: typeof plugin }, rules: import('eslint').Linter.RulesRecord, languageOptions: { parserOptions: import('eslint').Linter.ParserOptions } }} ReactFlatConfig */
|
|---|
| 99 |
|
|---|
| 100 | /** @type {{ deprecatedRules: typeof deprecatedRules, rules: typeof allRules, configs: typeof configs & { flat: Record<string, ReactFlatConfig> }}} */
|
|---|
| 101 | const plugin = {
|
|---|
| 102 | deprecatedRules,
|
|---|
| 103 | rules: allRules,
|
|---|
| 104 | configs,
|
|---|
| 105 | };
|
|---|
| 106 |
|
|---|
| 107 | Object.assign(configs.flat, {
|
|---|
| 108 | recommended: {
|
|---|
| 109 | plugins: { react: plugin },
|
|---|
| 110 | rules: configs.recommended.rules,
|
|---|
| 111 | languageOptions: { parserOptions: configs.recommended.parserOptions },
|
|---|
| 112 | },
|
|---|
| 113 | all: {
|
|---|
| 114 | plugins: { react: plugin },
|
|---|
| 115 | rules: configs.all.rules,
|
|---|
| 116 | languageOptions: { parserOptions: configs.all.parserOptions },
|
|---|
| 117 | },
|
|---|
| 118 | 'jsx-runtime': {
|
|---|
| 119 | plugins: { react: plugin },
|
|---|
| 120 | rules: configs['jsx-runtime'].rules,
|
|---|
| 121 | languageOptions: { parserOptions: configs['jsx-runtime'].parserOptions },
|
|---|
| 122 | },
|
|---|
| 123 | });
|
|---|
| 124 |
|
|---|
| 125 | module.exports = plugin;
|
|---|