|
1 | 1 | import prettier from 'eslint-config-prettier/flat';
|
2 | 2 | import { flatConfigs as importFlatConfigs } from 'eslint-plugin-import';
|
| 3 | +import mochaPlugin from 'eslint-plugin-mocha'; |
| 4 | +import reactCompilerPlugin from 'eslint-plugin-react-compiler'; |
3 | 5 | import { configs as reactHookConfigs } from 'eslint-plugin-react-hooks';
|
| 6 | +import testingLibrary from 'eslint-plugin-testing-library'; |
4 | 7 | import globals from 'globals';
|
5 | 8 | import * as tseslint from 'typescript-eslint';
|
6 | 9 |
|
7 | 10 | import airbnbBase from './airbnb/base.mjs';
|
8 | 11 | import airbnbReact from './airbnb/react.mjs';
|
9 | 12 | import airbnbTs from './airbnb/typescript.mjs';
|
10 | 13 |
|
| 14 | +import { createCoreConfig } from './material-ui/config.mjs'; |
11 | 15 | import muiPlugin from './material-ui/index.mjs';
|
12 |
| -import muiConfig from './material-ui/config.mjs'; |
| 16 | + |
| 17 | +export const specBaseRules = { |
| 18 | + files: ['**/*.spec.*'], |
| 19 | + rules: { |
| 20 | + 'no-alert': 'off', |
| 21 | + 'no-console': 'off', |
| 22 | + 'no-empty-pattern': 'off', |
| 23 | + 'no-lone-blocks': 'off', |
| 24 | + 'no-shadow': 'off', |
| 25 | + |
| 26 | + '@typescript-eslint/no-unused-expressions': 'off', |
| 27 | + '@typescript-eslint/no-unused-vars': 'off', |
| 28 | + '@typescript-eslint/no-use-before-define': 'off', |
| 29 | + |
| 30 | + 'import/prefer-default-export': 'off', |
| 31 | + |
| 32 | + 'jsx-a11y/anchor-has-content': 'off', |
| 33 | + 'jsx-a11y/anchor-is-valid': 'off', |
| 34 | + 'jsx-a11y/tabindex-no-positive': 'off', |
| 35 | + |
| 36 | + 'react/default-props-match-prop-types': 'off', |
| 37 | + 'react/no-access-state-in-setstate': 'off', |
| 38 | + 'react/no-unused-prop-types': 'off', |
| 39 | + 'react/prefer-stateless-function': 'off', |
| 40 | + 'react/prop-types': 'off', |
| 41 | + 'react/require-default-props': 'off', |
| 42 | + 'react/state-in-constructor': 'off', |
| 43 | + 'react/static-property-placement': 'off', |
| 44 | + 'react/function-component-definition': 'off', |
| 45 | + }, |
| 46 | +}; |
13 | 47 |
|
14 | 48 | /**
|
15 |
| - * @type {import('typescript-eslint').ConfigArray} |
| 49 | + * @param {Object} [params] |
| 50 | + * @param {boolean} [params.enableReactCompiler] - Whether the config is for spec files. |
| 51 | + * @returns {import('typescript-eslint').ConfigArray} |
16 | 52 | */
|
17 |
| -export default tseslint.config( |
18 |
| - importFlatConfigs.recommended, |
19 |
| - importFlatConfigs.typescript, |
20 |
| - reactHookConfigs.recommended, |
21 |
| - airbnbBase, |
22 |
| - airbnbReact, |
23 |
| - airbnbTs, |
24 |
| - prettier, |
25 |
| - { |
26 |
| - name: 'typescript-eslint-parser', |
27 |
| - languageOptions: { |
28 |
| - parser: tseslint.parser, |
29 |
| - ecmaVersion: 7, |
30 |
| - globals: { |
31 |
| - ...globals.es2020, |
32 |
| - ...globals.browser, |
33 |
| - ...globals.node, |
| 53 | +export function createBaseConfig({ enableReactCompiler = false } = {}) { |
| 54 | + return tseslint.config( |
| 55 | + importFlatConfigs.recommended, |
| 56 | + importFlatConfigs.typescript, |
| 57 | + reactHookConfigs.recommended, |
| 58 | + enableReactCompiler ? reactCompilerPlugin.configs.recommended : {}, |
| 59 | + airbnbBase, |
| 60 | + airbnbReact, |
| 61 | + airbnbTs, |
| 62 | + prettier, |
| 63 | + { |
| 64 | + name: 'typescript-eslint-parser', |
| 65 | + languageOptions: { |
| 66 | + parser: tseslint.parser, |
| 67 | + ecmaVersion: 7, |
| 68 | + globals: { |
| 69 | + ...globals.es2020, |
| 70 | + ...globals.browser, |
| 71 | + ...globals.node, |
| 72 | + }, |
34 | 73 | },
|
| 74 | + plugins: { |
| 75 | + '@typescript-eslint': tseslint.plugin, |
| 76 | + 'material-ui': muiPlugin, |
| 77 | + }, |
| 78 | + settings: { |
| 79 | + 'import/parsers': { |
| 80 | + '@typescript-eslint/parser': ['.ts', '.tsx'], |
| 81 | + }, |
| 82 | + }, |
| 83 | + extends: createCoreConfig({ reactCompilerEnabled: enableReactCompiler }), |
35 | 84 | },
|
36 |
| - plugins: { |
37 |
| - '@typescript-eslint': tseslint.plugin, |
38 |
| - 'material-ui': muiPlugin, |
39 |
| - }, |
40 |
| - settings: { |
41 |
| - 'import/parsers': { |
42 |
| - '@typescript-eslint/parser': ['.ts', '.tsx'], |
| 85 | + ); |
| 86 | +} |
| 87 | + |
| 88 | +/** |
| 89 | + * @returns {import('typescript-eslint').ConfigArray} |
| 90 | + */ |
| 91 | +export function createTestConfig() { |
| 92 | + return tseslint.config( |
| 93 | + mochaPlugin.configs.recommended, |
| 94 | + testingLibrary.configs['flat/dom'], |
| 95 | + testingLibrary.configs['flat/react'], |
| 96 | + { |
| 97 | + languageOptions: { |
| 98 | + parser: tseslint.parser, |
| 99 | + parserOptions: { |
| 100 | + ecmaVersion: 7, |
| 101 | + }, |
| 102 | + globals: globals.mocha, |
| 103 | + }, |
| 104 | + settings: { |
| 105 | + 'import/resolver': { |
| 106 | + typescript: { |
| 107 | + project: ['tsconfig.node.json', 'apps/*/tsconfig.json', 'packages/*/tsconfig.json'], |
| 108 | + }, |
| 109 | + }, |
| 110 | + }, |
| 111 | + rules: { |
| 112 | + // does not work with wildcard imports. Mistakes will throw at runtime anyway |
| 113 | + 'import/named': 'off', |
| 114 | + 'material-ui/disallow-active-element-as-key-event-target': 'error', |
| 115 | + 'mocha/consistent-spacing-between-blocks': 'off', |
| 116 | + |
| 117 | + // upgraded level from recommended |
| 118 | + 'mocha/no-pending-tests': 'error', |
| 119 | + |
| 120 | + // no rationale provided in /recommended |
| 121 | + 'mocha/no-mocha-arrows': 'off', |
| 122 | + // definitely a useful rule but too many false positives |
| 123 | + // due to `describeConformance` |
| 124 | + // "If you're using dynamically generated tests, you should disable this rule."" |
| 125 | + 'mocha/no-setup-in-describe': 'off', |
| 126 | + // `beforeEach` for a single case is optimized for change |
| 127 | + // when we add a test we don't have to refactor the existing |
| 128 | + // test to `beforeEach`. |
| 129 | + // `beforeEach`+`afterEach` also means that the `beforeEach` |
| 130 | + // is cleaned up in `afterEach` if the test causes a crash |
| 131 | + 'mocha/no-hooks-for-single-case': 'off', |
| 132 | + |
| 133 | + // disable eslint-plugin-jsx-a11y |
| 134 | + // tests are not driven by assistive technology |
| 135 | + // add `jsx-a11y` rules once you encounter them in tests |
| 136 | + 'jsx-a11y/click-events-have-key-events': 'off', |
| 137 | + 'jsx-a11y/control-has-associated-label': 'off', |
| 138 | + 'jsx-a11y/iframe-has-title': 'off', |
| 139 | + 'jsx-a11y/label-has-associated-control': 'off', |
| 140 | + 'jsx-a11y/mouse-events-have-key-events': 'off', |
| 141 | + 'jsx-a11y/no-noninteractive-tabindex': 'off', |
| 142 | + 'jsx-a11y/no-static-element-interactions': 'off', |
| 143 | + 'jsx-a11y/tabindex-no-positive': 'off', |
| 144 | + |
| 145 | + // In tests this is generally intended. |
| 146 | + 'react/button-has-type': 'off', |
| 147 | + // They are accessed to test custom validator implementation with PropTypes.checkPropTypes |
| 148 | + 'react/forbid-foreign-prop-types': 'off', |
| 149 | + // components that are defined in test are isolated enough |
| 150 | + // that they don't need type-checking |
| 151 | + 'react/prop-types': 'off', |
| 152 | + 'react/no-unused-prop-types': 'off', |
43 | 153 | },
|
44 | 154 | },
|
45 |
| - extends: muiConfig, |
46 |
| - }, |
47 |
| -); |
| 155 | + ); |
| 156 | +} |
0 commit comments