@mrpalmer/eslint-config 2.3.1 → 2.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/configs/base.js CHANGED
@@ -3,238 +3,245 @@ import mrpalmerPlugin from '@mrpalmer/eslint-plugin'
3
3
  import { defineConfig } from 'eslint/config'
4
4
  import pluginImport from 'eslint-plugin-import-x'
5
5
 
6
- export default defineConfig(
7
- {
8
- name: 'eslint/recommended',
9
- ...eslint.configs.recommended,
6
+ export default defineConfig({
7
+ extends: [
8
+ {
9
+ name: 'eslint/recommended',
10
+ ...eslint.configs.recommended,
11
+ },
12
+ mrpalmerPlugin.configs.recommended,
13
+ pluginImport.flatConfigs.recommended,
14
+ ],
15
+ files: [
16
+ '**/*.js',
17
+ '**/*.cjs',
18
+ '**/*.mjs',
19
+ '**/*.jsx',
20
+ '**/*.ts',
21
+ '**/*.mts',
22
+ '**/*.tsx',
23
+ ],
24
+ name: 'mrpalmer/base',
25
+
26
+ linterOptions: {
27
+ reportUnusedDisableDirectives: 'error',
10
28
  },
11
- mrpalmerPlugin.configs.recommended,
12
- {
13
- name: 'mrpalmer/base',
29
+ rules: {
30
+ 'accessor-pairs': 'error',
31
+ 'array-callback-return': 'error',
32
+ 'arrow-body-style': 'off',
33
+ 'block-scoped-var': 'error',
34
+ camelcase: 'off',
35
+ 'capitalized-comments': 'off',
36
+ 'class-methods-use-this': 'off',
37
+ complexity: ['error', 20],
38
+ 'consistent-return': 'error',
39
+ 'consistent-this': 'off',
40
+ curly: ['error', 'multi-line'],
41
+ 'default-case': 'error',
42
+ 'default-case-last': 'error',
43
+ 'default-param-last': 'off',
44
+ 'dot-notation': 'error',
45
+ eqeqeq: ['error', 'smart'],
46
+ 'func-name-matching': 'error',
47
+ 'func-names': 'error',
48
+ 'func-style': 'off',
49
+ 'grouped-accessor-pairs': 'off',
50
+ 'guard-for-in': 'error',
51
+ 'id-denylist': 'error',
52
+ 'id-length': 'off',
53
+ 'id-match': [
54
+ 'error',
55
+ // camelCase, PascalCase, __filename, CONST_VALUE, stream$, $el
56
+ '^\\$?(__)?(([A-Z]|[a-z]|[0-9]+)|([A-Z_]))*\\$?$',
57
+ ],
58
+ 'init-declarations': 'off',
59
+ 'logical-assignment-operators': [
60
+ 'warn',
61
+ 'always',
62
+ { enforceForIfStatements: true },
63
+ ],
64
+ 'max-classes-per-file': 'off',
65
+ 'max-depth': ['error', 4],
66
+ 'max-lines': [
67
+ 'error',
68
+ { max: 2500, skipBlankLines: false, skipComments: false },
69
+ ],
70
+ 'max-lines-per-function': 'off',
71
+ 'max-nested-callbacks': ['error', 7],
72
+ 'max-params': ['error', { max: 7 }],
73
+ 'max-statements': 'off',
74
+ 'new-cap': 'error',
75
+ 'no-alert': 'error',
76
+ 'no-array-constructor': 'error',
77
+ 'no-await-in-loop': 'error',
78
+ 'no-bitwise': 'error',
79
+ 'no-caller': 'error',
80
+ 'no-console': 'off',
81
+ 'no-constant-binary-expression': 'error',
82
+ 'no-constructor-return': 'error',
83
+ 'no-continue': 'off',
84
+ 'no-div-regex': 'error',
85
+ 'no-duplicate-imports': 'off',
86
+ 'no-else-return': 'off',
87
+ 'no-empty-function': 'off',
88
+ 'no-empty-static-block': 'warn',
89
+ 'no-eq-null': 'off',
90
+ 'no-eval': 'error',
91
+ 'no-extend-native': 'error',
92
+ 'no-extra-bind': 'error',
93
+ 'no-extra-label': 'error',
94
+ 'no-implicit-coercion': 'off',
95
+ 'no-implicit-globals': 'error',
96
+ 'no-implied-eval': 'error',
97
+ 'no-inline-comments': 'off',
98
+ 'no-inner-declarations': 'error',
99
+ 'no-invalid-this': 'error',
100
+ 'no-iterator': 'error',
101
+ 'no-label-var': 'error',
102
+ 'no-labels': 'error',
103
+ 'no-lone-blocks': 'error',
104
+ 'no-lonely-if': 'error',
105
+ 'no-loop-func': 'error',
106
+ 'no-magic-numbers': 'off',
107
+ 'no-multi-assign': 'error',
108
+ 'no-multi-str': 'error',
109
+ 'no-negated-condition': 'error',
110
+ 'no-nested-ternary': 'off',
111
+ 'no-new': 'error',
112
+ 'no-new-func': 'error',
113
+ 'no-new-native-nonconstructor': 'error',
114
+ 'no-new-wrappers': 'error',
115
+ 'no-object-constructor': 'error',
116
+ 'no-octal-escape': 'error',
117
+ 'no-param-reassign': 'off',
118
+ 'no-plusplus': 'off',
119
+ 'no-promise-executor-return': 'off',
120
+ 'no-proto': 'error',
121
+ 'no-restricted-exports': 'off',
122
+ 'no-restricted-globals': ['error', 'event', 'fdescribe'],
123
+ 'no-restricted-imports': 'off',
124
+ 'no-restricted-properties': 'off',
125
+ 'no-restricted-syntax': ['error', 'WithStatement'],
126
+ 'no-return-assign': 'error',
127
+ 'no-script-url': 'error',
128
+ 'no-self-compare': 'error',
129
+ 'no-sequences': 'error',
130
+ 'no-shadow': 'off',
131
+ 'no-template-curly-in-string': 'error',
132
+ 'no-ternary': 'off',
133
+ 'no-throw-literal': 'error',
134
+ 'no-unassigned-vars': 'error',
135
+ 'no-undef-init': 'error',
136
+ 'no-undefined': 'off',
137
+ 'no-underscore-dangle': 'off',
138
+ 'no-unmodified-loop-condition': 'error',
139
+ 'no-unneeded-ternary': 'error',
140
+ 'no-unreachable-loop': 'error',
141
+ 'no-unused-expressions': 'off',
142
+ 'no-unused-private-class-members': 'error',
143
+ 'no-unused-vars': [
144
+ 'error',
145
+ {
146
+ args: 'after-used',
147
+ argsIgnorePattern: '^_',
148
+ ignoreRestSiblings: true,
149
+ varsIgnorePattern: '^ignored',
150
+ },
151
+ ],
152
+ 'no-use-before-define': ['error', 'nofunc'],
153
+ 'no-useless-assignment': 'warn',
154
+ 'no-useless-call': 'error',
155
+ 'no-useless-computed-key': 'error',
156
+ 'no-useless-concat': 'error',
157
+ 'no-useless-constructor': 'error',
158
+ 'no-useless-rename': 'error',
159
+ 'no-useless-return': 'error',
160
+ 'no-var': 'error',
161
+ 'no-void': 'off',
162
+ 'no-warning-comments': [
163
+ 'error',
164
+ { location: 'anywhere', terms: ['fixme'] },
165
+ ],
166
+ 'object-shorthand': ['error', 'properties'],
167
+ 'one-var': ['error', { initialized: 'never', uninitialized: 'always' }],
168
+ 'operator-assignment': 'off',
169
+ 'prefer-arrow-callback': [
170
+ 'error',
171
+ { allowNamedFunctions: true, allowUnboundThis: true },
172
+ ],
173
+ 'prefer-const': 'error',
174
+ 'prefer-destructuring': 'off',
175
+ 'prefer-exponentiation-operator': 'warn',
176
+ 'prefer-named-capture-group': 'off',
177
+ 'prefer-numeric-literals': 'error',
178
+ 'prefer-object-has-own': 'error',
179
+ 'prefer-object-spread': 'warn',
180
+ 'prefer-promise-reject-errors': 'off',
181
+ 'prefer-regex-literals': 'off',
182
+ 'prefer-rest-params': 'error',
183
+ 'prefer-spread': 'error',
184
+ 'prefer-template': 'error',
185
+ 'preserve-caught-error': 'warn',
186
+ radix: 'error',
187
+ 'require-atomic-updates': 'off',
188
+ 'require-await': 'off',
189
+ 'require-unicode-regexp': 'off',
190
+ 'sort-imports': 'off',
191
+ 'sort-keys': 'off',
192
+ 'sort-vars': 'off',
193
+ strict: 'error',
194
+ 'symbol-description': 'error',
195
+ 'unicode-bom': ['error', 'never'],
196
+ 'vars-on-top': 'error',
197
+ yoda: 'error',
14
198
 
15
- linterOptions: {
16
- reportUnusedDisableDirectives: 'error',
17
- },
18
- rules: {
19
- 'accessor-pairs': 'error',
20
- 'array-callback-return': 'error',
21
- 'arrow-body-style': 'off',
22
- 'block-scoped-var': 'error',
23
- camelcase: 'off',
24
- 'capitalized-comments': 'off',
25
- 'class-methods-use-this': 'off',
26
- complexity: ['error', 20],
27
- 'consistent-return': 'error',
28
- 'consistent-this': 'off',
29
- curly: ['error', 'multi-line'],
30
- 'default-case': 'error',
31
- 'default-case-last': 'error',
32
- 'default-param-last': 'off',
33
- 'dot-notation': 'error',
34
- eqeqeq: ['error', 'smart'],
35
- 'func-name-matching': 'error',
36
- 'func-names': 'error',
37
- 'func-style': 'off',
38
- 'grouped-accessor-pairs': 'off',
39
- 'guard-for-in': 'error',
40
- 'id-denylist': 'error',
41
- 'id-length': 'off',
42
- 'id-match': [
43
- 'error',
44
- // camelCase, PascalCase, __filename, CONST_VALUE, stream$, $el
45
- '^\\$?(__)?(([A-Z]|[a-z]|[0-9]+)|([A-Z_]))*\\$?$',
46
- ],
47
- 'init-declarations': 'off',
48
- 'logical-assignment-operators': [
49
- 'warn',
50
- 'always',
51
- { enforceForIfStatements: true },
52
- ],
53
- 'max-classes-per-file': 'off',
54
- 'max-depth': ['error', 4],
55
- 'max-lines': [
56
- 'error',
57
- { max: 2500, skipBlankLines: false, skipComments: false },
58
- ],
59
- 'max-lines-per-function': 'off',
60
- 'max-nested-callbacks': ['error', 7],
61
- 'max-params': ['error', { max: 7 }],
62
- 'max-statements': 'off',
63
- 'new-cap': 'error',
64
- 'no-alert': 'error',
65
- 'no-array-constructor': 'error',
66
- 'no-await-in-loop': 'error',
67
- 'no-bitwise': 'error',
68
- 'no-caller': 'error',
69
- 'no-console': 'off',
70
- 'no-constant-binary-expression': 'error',
71
- 'no-constructor-return': 'error',
72
- 'no-continue': 'off',
73
- 'no-div-regex': 'error',
74
- 'no-duplicate-imports': 'off',
75
- 'no-else-return': 'off',
76
- 'no-empty-function': 'off',
77
- 'no-empty-static-block': 'warn',
78
- 'no-eq-null': 'off',
79
- 'no-eval': 'error',
80
- 'no-extend-native': 'error',
81
- 'no-extra-bind': 'error',
82
- 'no-extra-label': 'error',
83
- 'no-implicit-coercion': 'off',
84
- 'no-implicit-globals': 'error',
85
- 'no-implied-eval': 'error',
86
- 'no-inline-comments': 'off',
87
- 'no-inner-declarations': 'error',
88
- 'no-invalid-this': 'error',
89
- 'no-iterator': 'error',
90
- 'no-label-var': 'error',
91
- 'no-labels': 'error',
92
- 'no-lone-blocks': 'error',
93
- 'no-lonely-if': 'error',
94
- 'no-loop-func': 'error',
95
- 'no-magic-numbers': 'off',
96
- 'no-multi-assign': 'error',
97
- 'no-multi-str': 'error',
98
- 'no-negated-condition': 'error',
99
- 'no-nested-ternary': 'off',
100
- 'no-new': 'error',
101
- 'no-new-func': 'error',
102
- 'no-new-native-nonconstructor': 'error',
103
- 'no-new-wrappers': 'error',
104
- 'no-object-constructor': 'error',
105
- 'no-octal-escape': 'error',
106
- 'no-param-reassign': 'off',
107
- 'no-plusplus': 'off',
108
- 'no-promise-executor-return': 'off',
109
- 'no-proto': 'error',
110
- 'no-restricted-exports': 'off',
111
- 'no-restricted-globals': ['error', 'event', 'fdescribe'],
112
- 'no-restricted-imports': 'off',
113
- 'no-restricted-properties': 'off',
114
- 'no-restricted-syntax': ['error', 'WithStatement'],
115
- 'no-return-assign': 'error',
116
- 'no-script-url': 'error',
117
- 'no-self-compare': 'error',
118
- 'no-sequences': 'error',
119
- 'no-shadow': 'off',
120
- 'no-template-curly-in-string': 'error',
121
- 'no-ternary': 'off',
122
- 'no-throw-literal': 'error',
123
- 'no-unassigned-vars': 'error',
124
- 'no-undef-init': 'error',
125
- 'no-undefined': 'off',
126
- 'no-underscore-dangle': 'off',
127
- 'no-unmodified-loop-condition': 'error',
128
- 'no-unneeded-ternary': 'error',
129
- 'no-unreachable-loop': 'error',
130
- 'no-unused-expressions': 'off',
131
- 'no-unused-private-class-members': 'error',
132
- 'no-unused-vars': [
133
- 'error',
134
- {
135
- args: 'after-used',
136
- argsIgnorePattern: '^_',
137
- ignoreRestSiblings: true,
138
- varsIgnorePattern: '^ignored',
139
- },
140
- ],
141
- 'no-use-before-define': ['error', 'nofunc'],
142
- 'no-useless-assignment': 'warn',
143
- 'no-useless-call': 'error',
144
- 'no-useless-computed-key': 'error',
145
- 'no-useless-concat': 'error',
146
- 'no-useless-constructor': 'error',
147
- 'no-useless-rename': 'error',
148
- 'no-useless-return': 'error',
149
- 'no-var': 'error',
150
- 'no-void': 'off',
151
- 'no-warning-comments': [
152
- 'error',
153
- { location: 'anywhere', terms: ['fixme'] },
154
- ],
155
- 'object-shorthand': ['error', 'properties'],
156
- 'one-var': ['error', { initialized: 'never', uninitialized: 'always' }],
157
- 'operator-assignment': 'off',
158
- 'prefer-arrow-callback': [
159
- 'error',
160
- { allowNamedFunctions: true, allowUnboundThis: true },
161
- ],
162
- 'prefer-const': 'error',
163
- 'prefer-destructuring': 'off',
164
- 'prefer-exponentiation-operator': 'warn',
165
- 'prefer-named-capture-group': 'off',
166
- 'prefer-numeric-literals': 'error',
167
- 'prefer-object-has-own': 'error',
168
- 'prefer-object-spread': 'warn',
169
- 'prefer-promise-reject-errors': 'off',
170
- 'prefer-regex-literals': 'off',
171
- 'prefer-rest-params': 'error',
172
- 'prefer-spread': 'error',
173
- 'prefer-template': 'error',
174
- 'preserve-caught-error': 'warn',
175
- radix: 'error',
176
- 'require-atomic-updates': 'off',
177
- 'require-await': 'off',
178
- 'require-unicode-regexp': 'off',
179
- 'sort-imports': 'off',
180
- 'sort-keys': 'off',
181
- 'sort-vars': 'off',
182
- strict: 'error',
183
- 'symbol-description': 'error',
184
- 'unicode-bom': ['error', 'never'],
185
- 'vars-on-top': 'error',
186
- yoda: 'error',
187
- },
199
+ 'import-x/consistent-type-specifier-style': ['error', 'prefer-inline'],
200
+ 'import-x/dynamic-import-chunkname': 'off',
201
+ 'import-x/exports-last': 'off',
202
+ 'import-x/extensions': 'off',
203
+ 'import-x/first': 'error',
204
+ 'import-x/group-exports': 'off',
205
+ 'import-x/max-dependencies': 'off',
206
+ 'import-x/newline-after-import': 'off',
207
+ 'import-x/no-absolute-path': 'error',
208
+ 'import-x/no-amd': 'error',
209
+ 'import-x/no-anonymous-default-export': [
210
+ 'error',
211
+ { allowArray: true, allowObject: true },
212
+ ],
213
+ 'import-x/no-commonjs': 'off',
214
+ 'import-x/no-cycle': 'off',
215
+ 'import-x/no-default-export': 'off',
216
+ 'import-x/no-deprecated': 'warn',
217
+ 'import-x/no-dynamic-require': 'off',
218
+ 'import-x/no-empty-named-blocks': 'warn',
219
+ 'import-x/no-extraneous-dependencies': 'error',
220
+ 'import-x/no-import-module-exports': 'error',
221
+ 'import-x/no-internal-modules': 'off',
222
+ 'import-x/no-mutable-exports': 'error',
223
+ 'import-x/no-named-default': 'error',
224
+ 'import-x/no-named-export': 'off',
225
+ 'import-x/no-namespace': 'off',
226
+ 'import-x/no-nodejs-modules': 'off',
227
+ 'import-x/no-relative-packages': 'warn',
228
+ 'import-x/no-relative-parent-imports': 'off',
229
+ 'import-x/no-rename-default': 'off',
230
+ 'import-x/no-restricted-paths': 'off',
231
+ 'import-x/no-self-import': 'error',
232
+ 'import-x/no-unassigned-import': 'off',
233
+ 'import-x/no-unused-modules': 'off',
234
+ 'import-x/no-useless-path-segments': 'error',
235
+ 'import-x/no-webpack-loader-syntax': 'error',
236
+ 'import-x/order': 'off',
237
+ 'import-x/prefer-default-export': 'off',
238
+ 'import-x/prefer-namespace-import': 'off',
239
+ 'import-x/unambiguous': 'off',
240
+
241
+ 'mrpalmer/require-package-scope': 'off',
188
242
  },
189
- pluginImport.flatConfigs.recommended,
190
- {
191
- name: 'mrpalmer/import',
192
- rules: {
193
- 'import-x/consistent-type-specifier-style': ['error', 'prefer-inline'],
194
- 'import-x/dynamic-import-chunkname': 'off',
195
- 'import-x/exports-last': 'off',
196
- 'import-x/extensions': 'off',
197
- 'import-x/first': 'error',
198
- 'import-x/group-exports': 'off',
199
- 'import-x/max-dependencies': 'off',
200
- 'import-x/newline-after-import': 'off',
201
- 'import-x/no-absolute-path': 'error',
202
- 'import-x/no-amd': 'error',
203
- 'import-x/no-anonymous-default-export': [
204
- 'error',
205
- { allowArray: true, allowObject: true },
206
- ],
207
- 'import-x/no-commonjs': 'off',
208
- 'import-x/no-cycle': 'off',
209
- 'import-x/no-default-export': 'off',
210
- 'import-x/no-deprecated': 'warn',
211
- 'import-x/no-dynamic-require': 'off',
212
- 'import-x/no-empty-named-blocks': 'warn',
213
- 'import-x/no-extraneous-dependencies': 'error',
214
- 'import-x/no-import-module-exports': 'error',
215
- 'import-x/no-internal-modules': 'off',
216
- 'import-x/no-mutable-exports': 'error',
217
- 'import-x/no-named-default': 'error',
218
- 'import-x/no-named-export': 'off',
219
- 'import-x/no-namespace': 'off',
220
- 'import-x/no-nodejs-modules': 'off',
221
- 'import-x/no-relative-packages': 'warn',
222
- 'import-x/no-relative-parent-imports': 'off',
223
- 'import-x/no-rename-default': 'off',
224
- 'import-x/no-restricted-paths': 'off',
225
- 'import-x/no-self-import': 'error',
226
- 'import-x/no-unassigned-import': 'off',
227
- 'import-x/no-unused-modules': 'off',
228
- 'import-x/no-useless-path-segments': 'error',
229
- 'import-x/no-webpack-loader-syntax': 'error',
230
- 'import-x/order': 'off',
231
- 'import-x/prefer-default-export': 'off',
232
- 'import-x/prefer-namespace-import': 'off',
233
- 'import-x/unambiguous': 'off',
234
- },
235
- settings: {
236
- 'import-x/ignore': ['node_modules', '.json$', '.(scss|less|css|styl)$'],
237
- 'import-x/resolver-x': [pluginImport.createNodeResolver()],
238
- },
239
- }
240
- )
243
+ settings: {
244
+ 'import-x/ignore': ['node_modules', '.json$', '.(scss|less|css|styl)$'],
245
+ 'import-x/resolver-x': [pluginImport.createNodeResolver()],
246
+ },
247
+ })
package/configs/react.js CHANGED
@@ -57,6 +57,7 @@ export default defineConfig(
57
57
  'jsx-a11y/prefer-tag-over-role': 'off',
58
58
  'jsx-a11y/tabindex-no-positive': 'warn',
59
59
 
60
+ '@eslint-react/jsx-dollar': 'warn',
60
61
  '@eslint-react/jsx-key-before-spread': 'warn',
61
62
  '@eslint-react/jsx-no-iife': 'warn',
62
63
  '@eslint-react/jsx-no-undef': 'error',
@@ -64,7 +65,6 @@ export default defineConfig(
64
65
  '@eslint-react/jsx-shorthand-fragment': 'warn',
65
66
  '@eslint-react/no-children-prop': 'warn',
66
67
  '@eslint-react/no-class-component': 'warn',
67
- '@eslint-react/no-forbidden-props': 'off',
68
68
  '@eslint-react/no-leaked-conditional-rendering': 'off', // will be enabled for typescript files below
69
69
  '@eslint-react/no-missing-component-display-name': 'warn',
70
70
  '@eslint-react/no-missing-context-display-name': 'warn',
@@ -0,0 +1,200 @@
1
+ import pluginVitest from '@vitest/eslint-plugin'
2
+ import { defineConfig } from 'eslint/config'
3
+ import pluginJest from 'eslint-plugin-jest'
4
+ import pluginJestDom from 'eslint-plugin-jest-dom'
5
+ import pluginTestingLibrary from 'eslint-plugin-testing-library'
6
+ import { getAllDependencies } from '../utils/packageJson.js'
7
+
8
+ const allDeps = new Set(Object.keys(getAllDependencies()))
9
+
10
+ const hasJest = allDeps.has('jest')
11
+ const hasVitest = allDeps.has('vitest')
12
+ const hasJestDom = allDeps.has('@testing-library/jest-dom')
13
+ const hasTestingLibraryDom = allDeps.has('@testing-library/dom')
14
+ const hasTestingLibraryReact = allDeps.has('@testing-library/react')
15
+ const hasTestingLibrary = hasTestingLibraryDom || hasTestingLibraryReact
16
+
17
+ export default defineConfig(
18
+ {
19
+ extends: [
20
+ hasJest && {
21
+ name: 'jest/recommended',
22
+ ...pluginJest.configs['flat/recommended'],
23
+ },
24
+ hasJest && { name: 'jest/style', ...pluginJest.configs['flat/style'] },
25
+ hasVitest && pluginVitest.configs.recommended,
26
+ hasJestDom && {
27
+ name: 'jest-dom/recommended',
28
+ ...pluginJestDom.configs['flat/recommended'],
29
+ },
30
+ hasTestingLibraryReact
31
+ ? {
32
+ name: 'testing-library/react',
33
+ ...pluginTestingLibrary.configs['flat/react'],
34
+ }
35
+ : hasTestingLibraryDom
36
+ ? {
37
+ name: 'testing-library/dom',
38
+ ...pluginTestingLibrary.configs['flat/dom'],
39
+ }
40
+ : null,
41
+ ].filter(Boolean),
42
+ files: ['**/__tests__/**/*.+(js|ts)?(x)', '**/*.{spec,test}.+(js|ts)?(x)'],
43
+ name: 'mrpalmer/jest',
44
+
45
+ rules: {
46
+ // we don't need a display name in test files
47
+ '@eslint-react/no-missing-component-display-name': 'off',
48
+ '@eslint-react/no-missing-context-display-name': 'off',
49
+
50
+ ...(hasJest
51
+ ? {
52
+ 'jest/consistent-test-it': 'warn',
53
+ 'jest/max-expects': 'off',
54
+ 'jest/max-nested-describe': 'error',
55
+ 'jest/no-conditional-in-test': 'error',
56
+ 'jest/no-confusing-set-timeout': 'error',
57
+ 'jest/no-duplicate-hooks': 'off',
58
+ 'jest/no-hooks': 'off',
59
+ 'jest/no-large-snapshots': ['warn', { maxSize: 300 }],
60
+ 'jest/no-restricted-jest-methods': 'off',
61
+ 'jest/no-restricted-matchers': 'off',
62
+ 'jest/no-test-return-statement': 'off',
63
+ 'jest/no-untyped-mock-factory': 'error',
64
+ 'jest/padding-around-after-all-blocks': 'off',
65
+ 'jest/padding-around-after-each-blocks': 'off',
66
+ 'jest/padding-around-all': 'off',
67
+ 'jest/padding-around-before-all-blocks': 'off',
68
+ 'jest/padding-around-before-each-blocks': 'off',
69
+ 'jest/padding-around-describe-blocks': 'off',
70
+ 'jest/padding-around-expect-groups': 'off',
71
+ 'jest/padding-around-test-blocks': 'off',
72
+ 'jest/prefer-called-with': 'error',
73
+ 'jest/prefer-comparison-matcher': 'warn',
74
+ 'jest/prefer-each': 'warn',
75
+ 'jest/prefer-ending-with-an-expect': 'warn',
76
+ 'jest/prefer-equality-matcher': 'warn',
77
+ 'jest/prefer-expect-assertions': 'off',
78
+ 'jest/prefer-expect-resolves': 'off',
79
+ 'jest/prefer-hooks-in-order': 'error',
80
+ 'jest/prefer-hooks-on-top': 'error',
81
+ 'jest/prefer-importing-jest-globals': 'off',
82
+ 'jest/prefer-jest-mocked': 'warn',
83
+ 'jest/prefer-lowercase-title': 'off',
84
+ 'jest/prefer-mock-promise-shorthand': 'warn',
85
+ 'jest/prefer-snapshot-hint': ['error', 'multi'],
86
+ 'jest/prefer-spy-on': 'warn',
87
+ 'jest/prefer-strict-equal': 'off',
88
+ 'jest/prefer-todo': 'warn',
89
+ 'jest/require-hook': 'off',
90
+ 'jest/require-to-throw-message': 'off',
91
+ 'jest/require-top-level-describe': 'off',
92
+ 'jest/unbound-method': 'off',
93
+ 'jest/valid-mock-module-path': 'warn',
94
+ }
95
+ : {}),
96
+
97
+ ...(hasVitest
98
+ ? {
99
+ 'vitest/consistent-test-filename': 'off',
100
+ 'vitest/consistent-test-it': 'warn',
101
+ 'vitest/consistent-vitest-vi': 'warn',
102
+ 'vitest/hoisted-apis-on-top': 'error',
103
+ 'vitest/max-expects': 'off',
104
+ 'vitest/max-nested-describe': 'error',
105
+ 'vitest/no-alias-methods': 'off',
106
+ 'vitest/no-conditional-expect': 'error',
107
+ 'vitest/no-conditional-in-test': 'error',
108
+ 'vitest/no-conditional-tests': 'error',
109
+ 'vitest/no-disabled-tests': 'warn',
110
+ 'vitest/no-duplicate-hooks': 'off',
111
+ 'vitest/no-focused-tests': 'error',
112
+ 'vitest/no-hooks': 'off',
113
+ 'vitest/no-importing-vitest-globals': 'off',
114
+ 'vitest/no-interpolation-in-snapshots': 'warn',
115
+ 'vitest/no-large-snapshots': ['warn', { maxSize: 300 }],
116
+ 'vitest/no-mocks-import': 'error',
117
+ 'vitest/no-restricted-matchers': 'off',
118
+ 'vitest/no-restricted-vi-methods': 'off',
119
+ 'vitest/no-standalone-expect': 'error',
120
+ 'vitest/no-test-prefixes': 'off',
121
+ 'vitest/no-test-return-statement': 'error',
122
+ 'vitest/prefer-called-once': 'warn',
123
+ 'vitest/prefer-called-times': 'off',
124
+ 'vitest/prefer-called-with': 'error',
125
+ 'vitest/prefer-comparison-matcher': 'warn',
126
+ 'vitest/prefer-describe-function-title': 'warn',
127
+ 'vitest/prefer-each': 'warn',
128
+ 'vitest/prefer-equality-matcher': 'warn',
129
+ 'vitest/prefer-expect-assertions': 'off',
130
+ 'vitest/prefer-expect-resolves': 'off',
131
+ 'vitest/prefer-expect-type-of': 'warn',
132
+ 'vitest/prefer-hooks-in-order': 'error',
133
+ 'vitest/prefer-hooks-on-top': 'error',
134
+ 'vitest/prefer-import-in-mock': 'warn',
135
+ 'vitest/prefer-importing-vitest-globals': 'off',
136
+ 'vitest/prefer-lowercase-title': 'off',
137
+ 'vitest/prefer-mock-promise-shorthand': 'warn',
138
+ 'vitest/prefer-snapshot-hint': ['error', 'multi'],
139
+ 'vitest/prefer-spy-on': 'warn',
140
+ 'vitest/prefer-strict-boolean-matchers': 'off',
141
+ 'vitest/prefer-strict-equal': 'off',
142
+ 'vitest/prefer-to-be': 'warn',
143
+ 'vitest/prefer-to-be-falsy': 'off',
144
+ 'vitest/prefer-to-be-object': 'warn',
145
+ 'vitest/prefer-to-be-truthy': 'off',
146
+ 'vitest/prefer-to-contain': 'warn',
147
+ 'vitest/prefer-to-have-length': 'warn',
148
+ 'vitest/prefer-todo': 'warn',
149
+ 'vitest/prefer-vi-mocked': 'warn',
150
+ 'vitest/require-awaited-expect-poll': 'error',
151
+ 'vitest/require-hook': 'off',
152
+ 'vitest/require-mock-type-parameters': 'off',
153
+ 'vitest/require-to-throw-message': 'off',
154
+ 'vitest/require-top-level-describe': 'off',
155
+ 'vitest/valid-expect-in-promise': 'error',
156
+ 'vitest/warn-todo': 'warn',
157
+
158
+ // disable style rules
159
+ 'vitest/padding-around-after-all-blocks': 'off',
160
+ 'vitest/padding-around-after-each-blocks': 'off',
161
+ 'vitest/padding-around-all': 'off',
162
+ 'vitest/padding-around-before-all-blocks': 'off',
163
+ 'vitest/padding-around-before-each-blocks': 'off',
164
+ 'vitest/padding-around-describe-blocks': 'off',
165
+ 'vitest/padding-around-expect-groups': 'off',
166
+ 'vitest/padding-around-test-blocks': 'off',
167
+ }
168
+ : {}),
169
+
170
+ ...(hasTestingLibrary
171
+ ? {
172
+ 'testing-library/consistent-data-testid': 'off',
173
+ 'testing-library/no-test-id-queries': 'warn',
174
+ 'testing-library/prefer-explicit-assert': 'warn',
175
+ 'testing-library/prefer-implicit-assert': 'off',
176
+ 'testing-library/prefer-query-matchers': 'off',
177
+ 'testing-library/prefer-user-event': 'error',
178
+ }
179
+ : null),
180
+ },
181
+ },
182
+ {
183
+ files: ['**/__tests__/**/*.ts?(x)', '**/*.{spec,test}.ts?(x)'],
184
+ name: 'mrpalmer/jest/typescript',
185
+ rules: {
186
+ '@typescript-eslint/unbound-method': 'off',
187
+
188
+ ...(hasJest
189
+ ? {
190
+ 'jest/unbound-method': 'error',
191
+ }
192
+ : hasVitest
193
+ ? {
194
+ // feature is planned but not supported yet
195
+ // 'vitest/unbound-method': 'error',
196
+ }
197
+ : {}),
198
+ },
199
+ }
200
+ )
@@ -133,6 +133,7 @@ export default defineConfig({
133
133
  '@typescript-eslint/no-unnecessary-type-arguments': 'warn',
134
134
  '@typescript-eslint/no-unnecessary-type-conversion': 'warn',
135
135
  '@typescript-eslint/no-unsafe-type-assertion': 'error',
136
+ '@typescript-eslint/no-unused-private-class-members': 'error',
136
137
  '@typescript-eslint/no-useless-empty-export': 'error',
137
138
  '@typescript-eslint/parameter-properties': [
138
139
  'error',
package/index.js CHANGED
@@ -1,14 +1,14 @@
1
1
  import globals from 'globals'
2
2
  import base from './configs/base.js'
3
- import jest from './configs/jest.js'
4
3
  import react from './configs/react.js'
4
+ import tests from './configs/tests.js'
5
5
  import typescript from './configs/typescript.js'
6
6
 
7
7
  const configs = {
8
- all: [...base, ...typescript, ...react, ...jest],
8
+ all: [...base, ...typescript, ...react, ...tests],
9
9
  base,
10
- jest,
11
10
  react,
11
+ tests,
12
12
  typescript,
13
13
  }
14
14
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrpalmer/eslint-config",
3
- "version": "2.3.1",
3
+ "version": "2.4.1",
4
4
  "description": "Mike Palmer's personal ESLint rules",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -23,28 +23,30 @@
23
23
  "prebuild": "rm -rf types",
24
24
  "build": "tsc",
25
25
  "check-config": "run-p check-config:*",
26
- "check-config:jest": "cd test && validate-config -f component.test.js",
27
- "check-config:jest-ts": "cd test && validate-config -f component.test.ts",
28
26
  "check-config:js": "cd test && validate-config -f index.js",
27
+ "check-config:tests": "cd test && validate-config -f component.test.js",
28
+ "check-config:tests-ts": "cd test && validate-config -f component.test.ts",
29
29
  "check-config:ts": "cd test && validate-config -f index.ts",
30
30
  "dev": "cd test && eslint-config-inspector",
31
31
  "validate": "npm run check-config"
32
32
  },
33
33
  "dependencies": {
34
- "@eslint-react/eslint-plugin": "^2.2.2",
35
- "@eslint/js": "^9.31.0",
36
- "@mrpalmer/eslint-plugin": "^1.0.3",
34
+ "@eslint-react/eslint-plugin": "^2.3.7",
35
+ "@eslint/js": "^9.39.1",
36
+ "@eslint/json": "^0.14.0",
37
+ "@mrpalmer/eslint-plugin": "^1.1.0",
38
+ "@vitest/eslint-plugin": "^1.4.3",
37
39
  "eslint-import-resolver-typescript": "^4.4.4",
38
40
  "eslint-plugin-import-x": "^4.16.1",
39
- "eslint-plugin-jest": "^29.0.1",
41
+ "eslint-plugin-jest": "^29.2.0",
40
42
  "eslint-plugin-jest-dom": "^5.5.0",
41
43
  "eslint-plugin-jsx-a11y": "^6.10.2",
42
- "eslint-plugin-react-hooks": "^7.0.0",
43
- "eslint-plugin-testing-library": "^7.13.3",
44
+ "eslint-plugin-react-hooks": "^7.0.1",
45
+ "eslint-plugin-testing-library": "^7.13.5",
44
46
  "globals": "^16.4.0",
45
47
  "read-package-up": "^11.0.0",
46
48
  "semver": "^7.7.3",
47
- "typescript-eslint": "^8.46.1"
49
+ "typescript-eslint": "^8.47.0"
48
50
  },
49
51
  "peerDependencies": {
50
52
  "@testing-library/dom": "*",
@@ -1,2 +1,2 @@
1
- declare const _default: import("@eslint/core", { with: { "resolution-mode": "require" } }).ConfigObject<import("@eslint/core", { with: { "resolution-mode": "require" } }).RulesConfig>[];
1
+ declare const _default: import("eslint/config").Config[];
2
2
  export default _default;
@@ -1,2 +1,2 @@
1
- declare const _default: import("@eslint/core", { with: { "resolution-mode": "require" } }).ConfigObject<import("@eslint/core", { with: { "resolution-mode": "require" } }).RulesConfig>[];
1
+ declare const _default: import("eslint/config").Config[];
2
2
  export default _default;
@@ -0,0 +1,2 @@
1
+ declare const _default: import("eslint/config").Config[];
2
+ export default _default;
@@ -1,2 +1,2 @@
1
- declare const _default: import("@eslint/core", { with: { "resolution-mode": "require" } }).ConfigObject<import("@eslint/core", { with: { "resolution-mode": "require" } }).RulesConfig>[];
1
+ declare const _default: import("eslint/config").Config[];
2
2
  export default _default;
package/types/index.d.ts CHANGED
@@ -4,15 +4,15 @@ declare namespace _default {
4
4
  }
5
5
  export default _default;
6
6
  export namespace configs {
7
- export let all: import("@eslint/core", { with: { "resolution-mode": "require" } }).ConfigObject<import("@eslint/core", { with: { "resolution-mode": "require" } }).RulesConfig>[];
7
+ export let all: import("eslint/config").Config[];
8
8
  export { base };
9
- export { jest };
10
9
  export { react };
10
+ export { tests };
11
11
  export { typescript };
12
12
  }
13
13
  import globals from 'globals';
14
14
  import base from './configs/base.js';
15
- import jest from './configs/jest.js';
16
15
  import react from './configs/react.js';
16
+ import tests from './configs/tests.js';
17
17
  import typescript from './configs/typescript.js';
18
18
  export { globals };
package/configs/jest.js DELETED
@@ -1,105 +0,0 @@
1
- import { defineConfig } from 'eslint/config'
2
- import pluginJest from 'eslint-plugin-jest'
3
- import pluginJestDom from 'eslint-plugin-jest-dom'
4
- import pluginTestingLibrary from 'eslint-plugin-testing-library'
5
- import { getAllDependencies } from '../utils/packageJson.js'
6
-
7
- const allDeps = new Set(Object.keys(getAllDependencies()))
8
-
9
- const hasJestDom = allDeps.has('@testing-library/jest-dom')
10
- const hasTestingLibraryDom = allDeps.has('@testing-library/dom')
11
- const hasTestingLibraryReact = allDeps.has('@testing-library/react')
12
- const hasTestingLibrary = hasTestingLibraryDom || hasTestingLibraryReact
13
-
14
- export default defineConfig(
15
- {
16
- extends: [
17
- { name: 'jest/recommended', ...pluginJest.configs['flat/recommended'] },
18
- { name: 'jest/style', ...pluginJest.configs['flat/style'] },
19
- hasJestDom && {
20
- name: 'jest-dom/recommended',
21
- ...pluginJestDom.configs['flat/recommended'],
22
- },
23
- hasTestingLibraryReact
24
- ? {
25
- name: 'testing-library/react',
26
- ...pluginTestingLibrary.configs['flat/react'],
27
- }
28
- : hasTestingLibraryDom
29
- ? {
30
- name: 'testing-library/dom',
31
- ...pluginTestingLibrary.configs['flat/dom'],
32
- }
33
- : null,
34
- ].filter(Boolean),
35
- files: ['**/__tests__/**/*.+(js|ts)?(x)', '**/*.{spec,test}.+(js|ts)?(x)'],
36
- name: 'mrpalmer/jest',
37
-
38
- rules: {
39
- // we don't need a display name in test files
40
- '@eslint-react/no-missing-component-display-name': 'off',
41
- '@eslint-react/no-missing-context-display-name': 'off',
42
-
43
- 'jest/consistent-test-it': 'off',
44
- 'jest/max-expects': 'off',
45
- 'jest/max-nested-describe': 'error',
46
- 'jest/no-conditional-in-test': 'error',
47
- 'jest/no-confusing-set-timeout': 'error',
48
- 'jest/no-duplicate-hooks': 'off',
49
- 'jest/no-hooks': 'off',
50
- 'jest/no-large-snapshots': ['warn', { maxSize: 300 }],
51
- 'jest/no-restricted-jest-methods': 'off',
52
- 'jest/no-restricted-matchers': 'off',
53
- 'jest/no-test-return-statement': 'off',
54
- 'jest/no-untyped-mock-factory': 'error',
55
- 'jest/padding-around-after-all-blocks': 'off',
56
- 'jest/padding-around-after-each-blocks': 'off',
57
- 'jest/padding-around-all': 'off',
58
- 'jest/padding-around-before-all-blocks': 'off',
59
- 'jest/padding-around-before-each-blocks': 'off',
60
- 'jest/padding-around-describe-blocks': 'off',
61
- 'jest/padding-around-expect-groups': 'off',
62
- 'jest/padding-around-test-blocks': 'off',
63
- 'jest/prefer-called-with': 'error',
64
- 'jest/prefer-comparison-matcher': 'warn',
65
- 'jest/prefer-each': 'warn',
66
- 'jest/prefer-ending-with-an-expect': 'warn',
67
- 'jest/prefer-equality-matcher': 'warn',
68
- 'jest/prefer-expect-assertions': 'off',
69
- 'jest/prefer-expect-resolves': 'off',
70
- 'jest/prefer-hooks-in-order': 'error',
71
- 'jest/prefer-hooks-on-top': 'error',
72
- 'jest/prefer-importing-jest-globals': 'off',
73
- 'jest/prefer-jest-mocked': 'warn',
74
- 'jest/prefer-lowercase-title': 'off',
75
- 'jest/prefer-mock-promise-shorthand': 'warn',
76
- 'jest/prefer-snapshot-hint': ['error', 'multi'],
77
- 'jest/prefer-spy-on': 'off',
78
- 'jest/prefer-strict-equal': 'off',
79
- 'jest/prefer-todo': 'warn',
80
- 'jest/require-hook': 'off',
81
- 'jest/require-to-throw-message': 'off',
82
- 'jest/require-top-level-describe': 'off',
83
- 'jest/unbound-method': 'off',
84
-
85
- ...(hasTestingLibrary
86
- ? {
87
- 'testing-library/consistent-data-testid': 'off',
88
- 'testing-library/no-test-id-queries': 'warn',
89
- 'testing-library/prefer-explicit-assert': 'warn',
90
- 'testing-library/prefer-implicit-assert': 'off',
91
- 'testing-library/prefer-query-matchers': 'off',
92
- 'testing-library/prefer-user-event': 'error',
93
- }
94
- : null),
95
- },
96
- },
97
- {
98
- files: ['**/__tests__/**/*.ts?(x)', '**/*.{spec,test}.ts?(x)'],
99
- name: 'mrpalmer/jest/typescript',
100
- rules: {
101
- '@typescript-eslint/unbound-method': 'off',
102
- 'jest/unbound-method': 'error',
103
- },
104
- }
105
- )
@@ -1,2 +0,0 @@
1
- declare const _default: import("@eslint/core", { with: { "resolution-mode": "require" } }).ConfigObject<import("@eslint/core", { with: { "resolution-mode": "require" } }).RulesConfig>[];
2
- export default _default;