@mrpalmer/eslint-config 1.0.0 → 1.0.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/import.js CHANGED
@@ -11,6 +11,7 @@ module.exports = {
11
11
  'import/ignore': ['node_modules', '.json$', '.(scss|less|css|styl)$'],
12
12
  },
13
13
  rules: {
14
+ 'import/consistent-type-specifier-style': ['error', 'prefer-top-level'],
14
15
  'import/default': 'error',
15
16
  'import/dynamic-import-chunkname': 'off',
16
17
  'import/export': 'error',
@@ -31,6 +32,7 @@ module.exports = {
31
32
  'import/no-deprecated': 'warn',
32
33
  'import/no-duplicates': 'error',
33
34
  'import/no-dynamic-require': 'off',
35
+ 'import/no-empty-named-blocks': 'warn',
34
36
  'import/no-extraneous-dependencies': 'error',
35
37
  'import/no-import-module-exports': 'error',
36
38
  'import/no-internal-modules': 'off',
package/index.js CHANGED
@@ -4,8 +4,8 @@ const path = require('path')
4
4
  const tsConfig = fs.existsSync('tsconfig.json')
5
5
  ? path.resolve('tsconfig.json')
6
6
  : fs.existsSync('types/tsconfig.json')
7
- ? path.resolve('types/tsconfig.json')
8
- : undefined
7
+ ? path.resolve('types/tsconfig.json')
8
+ : undefined
9
9
 
10
10
  module.exports = {
11
11
  env: {
@@ -13,7 +13,7 @@ module.exports = {
13
13
  es6: true,
14
14
  node: true,
15
15
  },
16
- extends: ['prettier', './import.js'],
16
+ extends: ['eslint:recommended', 'prettier', './import.js'],
17
17
  rules: {
18
18
  'accessor-pairs': 'error',
19
19
  'array-callback-return': 'error',
@@ -25,14 +25,12 @@ module.exports = {
25
25
  complexity: ['error', 20],
26
26
  'consistent-return': 'error',
27
27
  'consistent-this': 'off',
28
- 'constructor-super': 'error',
29
28
  curly: ['error', 'multi-line'],
30
29
  'default-case': 'error',
31
30
  'default-case-last': 'error',
32
31
  'default-param-last': 'off',
33
32
  'dot-notation': 'error',
34
33
  eqeqeq: ['error', 'smart'],
35
- 'for-direction': 'error',
36
34
  'func-name-matching': 'error',
37
35
  'func-names': 'error',
38
36
  'func-style': 'off',
@@ -48,7 +46,11 @@ module.exports = {
48
46
  ],
49
47
  'init-declarations': 'off',
50
48
  'line-comment-position': 'off',
51
- 'lines-between-class-members': 'off',
49
+ 'logical-assignment-operators': [
50
+ 'warn',
51
+ 'always',
52
+ { enforceForIfStatements: true },
53
+ ],
52
54
  'max-classes-per-file': 'off',
53
55
  'max-depth': ['error', 4],
54
56
  'max-lines': [
@@ -57,121 +59,75 @@ module.exports = {
57
59
  ],
58
60
  'max-lines-per-function': 'off',
59
61
  'max-nested-callbacks': ['error', 7],
60
- 'max-params': ['error', 7],
62
+ 'max-params': ['error', { max: 7 }],
61
63
  'max-statements': 'off',
62
- 'max-statements-per-line': ['error', { max: 1 }],
63
64
  'multiline-comment-style': 'off',
64
65
  'new-cap': 'error',
65
66
  'no-alert': 'error',
66
67
  'no-array-constructor': 'error',
67
- 'no-async-promise-executor': 'off',
68
68
  'no-await-in-loop': 'error',
69
69
  'no-bitwise': 'error',
70
70
  'no-caller': 'error',
71
- 'no-case-declarations': 'error',
72
- 'no-class-assign': 'error',
73
- 'no-compare-neg-zero': 'error',
74
- 'no-cond-assign': 'error',
75
71
  'no-console': 'off',
76
- 'no-const-assign': 'error',
77
- 'no-constant-condition': 'error',
72
+ 'no-constant-binary-expression': 'error',
78
73
  'no-constructor-return': 'error',
79
74
  'no-continue': 'off',
80
- 'no-control-regex': 'error',
81
- 'no-debugger': 'error',
82
- 'no-delete-var': 'error',
83
75
  'no-div-regex': 'error',
84
- 'no-dupe-args': 'error',
85
- 'no-dupe-class-members': 'error',
86
- 'no-dupe-else-if': 'error',
87
- 'no-dupe-keys': 'error',
88
- 'no-duplicate-case': 'error',
89
- 'no-duplicate-imports': 'error',
76
+ 'no-duplicate-imports': 'off',
90
77
  'no-else-return': 'off',
91
- 'no-empty': 'error',
92
- 'no-empty-character-class': 'error',
93
78
  'no-empty-function': 'off',
94
- 'no-empty-pattern': 'error',
79
+ 'no-empty-static-block': 'warn',
95
80
  'no-eq-null': 'off',
96
81
  'no-eval': 'error',
97
- 'no-ex-assign': 'error',
98
82
  'no-extend-native': 'error',
99
83
  'no-extra-bind': 'error',
100
- 'no-extra-boolean-cast': 'off',
101
84
  'no-extra-label': 'error',
102
- 'no-fallthrough': 'error',
103
- 'no-func-assign': 'error',
104
- 'no-global-assign': 'error',
105
85
  'no-implicit-coercion': 'off',
106
86
  'no-implicit-globals': 'error',
107
87
  'no-implied-eval': 'error',
108
- 'no-import-assign': 'error',
109
88
  'no-inline-comments': 'off',
110
- 'no-inner-declarations': 'error',
111
- 'no-invalid-regexp': 'error',
112
89
  'no-invalid-this': 'error',
113
- 'no-irregular-whitespace': 'error',
114
90
  'no-iterator': 'error',
115
91
  'no-label-var': 'error',
116
92
  'no-labels': 'error',
117
93
  'no-lone-blocks': 'error',
118
94
  'no-lonely-if': 'error',
119
95
  'no-loop-func': 'error',
120
- 'no-loss-of-precision': 'error',
121
96
  'no-magic-numbers': 'off',
122
- 'no-misleading-character-class': 'off',
123
97
  'no-multi-assign': 'error',
124
98
  'no-multi-str': 'error',
125
99
  'no-negated-condition': 'error',
126
100
  'no-nested-ternary': 'off',
127
101
  'no-new': 'error',
128
102
  'no-new-func': 'error',
129
- 'no-new-object': 'error',
130
- 'no-new-symbol': 'error',
103
+ 'no-new-native-nonconstructor': 'error',
131
104
  'no-new-wrappers': 'error',
132
- 'no-nonoctal-decimal-escape': 'error',
133
- 'no-obj-calls': 'error',
134
- 'no-octal': 'error',
105
+ 'no-object-constructor': 'error',
135
106
  'no-octal-escape': 'error',
136
107
  'no-param-reassign': 'off',
137
108
  'no-plusplus': 'off',
138
109
  'no-promise-executor-return': 'off',
139
110
  'no-proto': 'error',
140
- 'no-prototype-builtins': 'off',
141
- 'no-redeclare': 'error',
142
- 'no-regex-spaces': 'error',
143
111
  'no-restricted-exports': 'off',
144
112
  'no-restricted-globals': ['error', 'event', 'fdescribe'],
145
113
  'no-restricted-imports': 'off',
146
114
  'no-restricted-properties': 'off',
147
115
  'no-restricted-syntax': ['error', 'WithStatement'],
148
116
  'no-return-assign': 'error',
149
- 'no-return-await': 'error',
150
117
  'no-script-url': 'error',
151
- 'no-self-assign': 'error',
152
118
  'no-self-compare': 'error',
153
119
  'no-sequences': 'error',
154
- 'no-setter-return': 'error',
155
120
  'no-shadow': 'off',
156
- 'no-shadow-restricted-names': 'error',
157
- 'no-sparse-arrays': 'error',
158
121
  'no-template-curly-in-string': 'error',
159
122
  'no-ternary': 'off',
160
- 'no-this-before-super': 'error',
161
123
  'no-throw-literal': 'error',
162
- 'no-undef': 'error',
163
124
  'no-undef-init': 'error',
164
125
  'no-undefined': 'off',
165
126
  'no-underscore-dangle': 'off',
166
127
  'no-unmodified-loop-condition': 'error',
167
128
  'no-unneeded-ternary': 'error',
168
- 'no-unreachable': 'error',
169
129
  'no-unreachable-loop': 'error',
170
- 'no-unsafe-finally': 'error',
171
- 'no-unsafe-negation': 'error',
172
- 'no-unsafe-optional-chaining': 'error',
173
130
  'no-unused-expressions': 'off',
174
- 'no-unused-labels': 'error',
175
131
  'no-unused-private-class-members': 'error',
176
132
  'no-unused-vars': [
177
133
  'error',
@@ -183,13 +139,10 @@ module.exports = {
183
139
  },
184
140
  ],
185
141
  'no-use-before-define': ['error', 'nofunc'],
186
- 'no-useless-backreference': 'error',
187
142
  'no-useless-call': 'error',
188
- 'no-useless-catch': 'error',
189
143
  'no-useless-computed-key': 'error',
190
144
  'no-useless-concat': 'error',
191
145
  'no-useless-constructor': 'error',
192
- 'no-useless-escape': 'error',
193
146
  'no-useless-rename': 'error',
194
147
  'no-useless-return': 'error',
195
148
  'no-var': 'error',
@@ -198,11 +151,9 @@ module.exports = {
198
151
  'error',
199
152
  { location: 'anywhere', terms: ['fixme'] },
200
153
  ],
201
- 'no-with': 'off',
202
154
  'object-shorthand': ['error', 'properties'],
203
155
  'one-var': ['error', { initialized: 'never', uninitialized: 'always' }],
204
156
  'operator-assignment': 'off',
205
- 'padding-line-between-statements': 'off',
206
157
  'prefer-arrow-callback': [
207
158
  'error',
208
159
  { allowNamedFunctions: true, allowUnboundThis: true },
@@ -223,15 +174,12 @@ module.exports = {
223
174
  'require-atomic-updates': 'off',
224
175
  'require-await': 'off',
225
176
  'require-unicode-regexp': 'off',
226
- 'require-yield': 'error',
227
177
  'sort-imports': 'off',
228
178
  'sort-keys': 'off',
229
179
  'sort-vars': 'off',
230
- 'spaced-comment': 'off',
231
180
  strict: 'error',
232
181
  'symbol-description': 'error',
233
- 'use-isnan': 'error',
234
- 'valid-typeof': 'error',
182
+ 'unicode-bom': ['error', 'never'],
235
183
  'vars-on-top': 'error',
236
184
  yoda: 'error',
237
185
  },
@@ -245,6 +193,10 @@ module.exports = {
245
193
  sourceType: 'module',
246
194
  },
247
195
  plugins: ['@typescript-eslint'],
196
+ extends: [
197
+ 'plugin:@typescript-eslint/strict-type-checked',
198
+ 'plugin:@typescript-eslint/stylistic-type-checked',
199
+ ],
248
200
  rules: {
249
201
  'constructor-super': 'off', // ts(2335) & ts(2377)
250
202
  'getter-return': 'off', // ts(2378)
@@ -262,66 +214,44 @@ module.exports = {
262
214
  'no-unsafe-negation': 'off', // ts(2365) & ts(2360) & ts(2358)
263
215
  'valid-typeof': 'off', // ts(2367)
264
216
 
265
- 'consistent-return': 'off', // in TS this is much less an issue
266
217
  'no-var': 'error', // TS transpiles let/const to var, so no need for vars anymore
267
218
  'prefer-const': 'error', // TS provides better types with const
268
219
  'prefer-rest-params': 'error', // TS provides better types with rest args over arguments
269
220
  'prefer-spread': 'error', // TS transpiles spread to apply, so no need for manual apply
270
221
 
222
+ 'consistent-return': 'off',
223
+ '@typescript-eslint/consistent-return': 'error',
224
+
271
225
  'default-param-last': 'off',
272
226
  '@typescript-eslint/default-param-last': 'off',
273
227
 
274
- 'dot-notation': 'off',
275
- '@typescript-eslint/dot-notation': 'error',
276
-
277
228
  'init-declarations': 'off',
278
229
  '@typescript-eslint/init-declarations': 'off',
279
230
 
280
- 'lines-between-class-members': 'off',
281
- '@typescript-eslint/lines-between-class-members': 'off',
282
-
283
- 'no-array-constructor': 'off',
284
- '@typescript-eslint/no-array-constructor': 'error',
231
+ 'max-params': 'off',
232
+ '@typescript-eslint/max-params': ['error', { max: 7 }],
285
233
 
286
234
  'no-dupe-class-members': 'off',
287
235
  '@typescript-eslint/no-dupe-class-members': 'off', // ts(2393) & ts(2300)
288
236
 
289
- 'no-duplicate-imports': 'off',
290
- '@typescript-eslint/no-duplicate-imports': 'error',
291
-
292
237
  'no-empty-function': 'off',
293
238
  '@typescript-eslint/no-empty-function': 'off',
294
239
 
295
- 'no-implied-eval': 'error',
296
- '@typescript-eslint/no-implied-eval': 'error',
297
-
298
240
  'no-invalid-this': 'off',
299
241
  '@typescript-eslint/no-invalid-this': 'error',
300
242
 
301
243
  'no-loop-func': 'off',
302
244
  '@typescript-eslint/no-loop-func': 'error',
303
245
 
304
- 'no-loss-of-precision': 'off',
305
- '@typescript-eslint/no-loss-of-precision': 'error',
306
-
307
246
  'no-magic-numbers': 'off',
308
247
  '@typescript-eslint/no-magic-numbers': 'off',
309
248
 
310
249
  'no-redeclare': 'off',
311
250
  '@typescript-eslint/no-redeclare': 'off', // ts(2451)
312
251
 
313
- 'no-return-await': 'off',
314
- '@typescript-eslint/return-await': 'error',
315
-
316
252
  'no-shadow': 'off',
317
253
  '@typescript-eslint/no-shadow': 'off',
318
254
 
319
- 'no-throw-literal': 'off',
320
- '@typescript-eslint/no-throw-literal': 'error',
321
-
322
- 'no-use-before-define': 'off',
323
- '@typescript-eslint/no-use-before-define': ['error', 'nofunc'],
324
-
325
255
  'no-unused-expressions': 'off',
326
256
  '@typescript-eslint/no-unused-expressions': 'off',
327
257
 
@@ -336,90 +266,74 @@ module.exports = {
336
266
  },
337
267
  ],
338
268
 
339
- 'no-useless-constructor': 'off',
340
- '@typescript-eslint/no-useless-constructor': 'error',
269
+ 'no-use-before-define': 'off',
270
+ '@typescript-eslint/no-use-before-define': ['error', 'nofunc'],
341
271
 
342
- '@typescript-eslint/adjacent-overload-signatures': 'error',
343
- '@typescript-eslint/array-type': 'off',
344
- '@typescript-eslint/await-thenable': 'error',
345
- '@typescript-eslint/ban-ts-comment': 'error',
346
- '@typescript-eslint/ban-tslint-comment': 'error',
347
- '@typescript-eslint/ban-types': 'off',
348
- '@typescript-eslint/class-literal-property-style': 'off',
349
- '@typescript-eslint/consistent-indexed-object-style': 'off',
350
- '@typescript-eslint/consistent-type-assertions': 'off',
272
+ '@typescript-eslint/array-type': ['error', { default: 'array-simple' }],
273
+ '@typescript-eslint/class-methods-use-this': 'off',
351
274
  '@typescript-eslint/consistent-type-definitions': 'off',
352
- '@typescript-eslint/consistent-type-imports': 'off',
275
+ '@typescript-eslint/consistent-type-exports': [
276
+ 'error',
277
+ { fixMixedExportsWithInlineTypeSpecifier: true },
278
+ ],
279
+ 'import/consistent-type-specifier-style': 'off',
280
+ '@typescript-eslint/consistent-type-imports': [
281
+ 'error',
282
+ { fixStyle: 'inline-type-imports' },
283
+ ],
353
284
  '@typescript-eslint/explicit-function-return-type': 'off',
285
+ '@typescript-eslint/explicit-member-accessibility': 'off',
354
286
  '@typescript-eslint/explicit-module-boundary-types': 'off',
355
- '@typescript-eslint/member-delimiter-style': 'off',
356
287
  '@typescript-eslint/member-ordering': 'off',
357
288
  '@typescript-eslint/method-signature-style': 'off',
358
289
  '@typescript-eslint/naming-convention': 'off',
359
290
  '@typescript-eslint/no-base-to-string': 'warn',
360
- '@typescript-eslint/no-confusing-non-null-assertion': 'off',
361
- '@typescript-eslint/no-confusing-void-expression': 'off',
362
- '@typescript-eslint/no-dynamic-delete': 'error',
363
- '@typescript-eslint/no-empty-interface': 'error',
364
- '@typescript-eslint/no-explicit-any': 'error',
365
- '@typescript-eslint/no-extra-non-null-assertion': 'error',
366
- '@typescript-eslint/no-extraneous-class': 'error',
291
+ '@typescript-eslint/no-confusing-void-expression': [
292
+ 'warn',
293
+ { ignoreArrowShorthand: true, ignoreVoidOperator: true },
294
+ ],
295
+ '@typescript-eslint/no-empty-object-type': 'error',
367
296
  '@typescript-eslint/no-floating-promises': 'warn',
368
- '@typescript-eslint/no-for-in-array': 'error',
369
- '@typescript-eslint/no-implicit-any-catch': 'warn',
297
+ '@typescript-eslint/no-import-type-side-effects': 'error',
370
298
  '@typescript-eslint/no-inferrable-types': 'off',
371
299
  '@typescript-eslint/no-invalid-void-type': 'warn',
372
- '@typescript-eslint/no-misused-new': 'error',
373
300
  '@typescript-eslint/no-misused-promises': [
374
301
  'warn',
375
302
  { checksVoidReturn: false },
376
303
  ],
377
- '@typescript-eslint/no-namespace': 'error',
378
- '@typescript-eslint/no-non-null-asserted-optional-chain': 'error',
379
- '@typescript-eslint/no-non-null-assertion': 'error',
380
- '@typescript-eslint/no-parameter-properties': 'off',
381
304
  '@typescript-eslint/no-require-imports': 'off',
382
- '@typescript-eslint/no-this-alias': 'error',
383
- '@typescript-eslint/no-type-alias': 'off',
305
+ '@typescript-eslint/no-restricted-imports': 'off',
306
+ '@typescript-eslint/no-restricted-types': 'off',
384
307
  '@typescript-eslint/no-unnecessary-boolean-literal-compare': 'warn',
385
- '@typescript-eslint/no-unnecessary-condition': 'error',
308
+ '@typescript-eslint/no-unnecessary-parameter-property-assignment':
309
+ 'warn',
386
310
  '@typescript-eslint/no-unnecessary-qualifier': 'warn',
387
- '@typescript-eslint/no-unnecessary-type-arguments': 'off',
388
- '@typescript-eslint/no-unnecessary-type-assertion': 'error',
389
- '@typescript-eslint/no-unnecessary-type-constraint': 'error',
390
- '@typescript-eslint/no-unsafe-argument': 'error',
311
+ '@typescript-eslint/no-unnecessary-type-arguments': 'warn',
391
312
  '@typescript-eslint/no-unsafe-assignment': 'warn',
392
313
  '@typescript-eslint/no-unsafe-call': 'warn',
393
314
  '@typescript-eslint/no-unsafe-member-access': 'warn',
394
- '@typescript-eslint/no-unsafe-return': 'off',
395
- '@typescript-eslint/no-var-requires': 'error',
396
- '@typescript-eslint/non-nullable-type-assertion-style': 'off',
397
- '@typescript-eslint/prefer-as-const': 'error',
315
+ '@typescript-eslint/no-unsafe-return': 'warn',
316
+ '@typescript-eslint/no-unsafe-unary-minus': 'error',
317
+ '@typescript-eslint/no-useless-empty-export': 'error',
318
+ '@typescript-eslint/parameter-properties': [
319
+ 'error',
320
+ { prefer: 'parameter-property' },
321
+ ],
322
+ '@typescript-eslint/prefer-destructuring': 'off',
398
323
  '@typescript-eslint/prefer-enum-initializers': 'error',
399
- '@typescript-eslint/prefer-for-of': 'off',
400
- '@typescript-eslint/prefer-function-type': 'off',
401
- '@typescript-eslint/prefer-includes': 'error',
402
- '@typescript-eslint/prefer-literal-enum-member': 'error',
403
- '@typescript-eslint/prefer-namespace-keyword': 'error',
404
- '@typescript-eslint/prefer-nullish-coalescing': 'error',
405
- '@typescript-eslint/prefer-optional-chain': 'error',
324
+ '@typescript-eslint/prefer-find': 'warn',
325
+ '@typescript-eslint/prefer-for-of': 'warn',
326
+ '@typescript-eslint/prefer-function-type': 'warn',
406
327
  '@typescript-eslint/prefer-readonly': 'off',
407
328
  '@typescript-eslint/prefer-readonly-parameter-types': 'off',
408
329
  '@typescript-eslint/prefer-reduce-type-parameter': 'warn',
409
330
  '@typescript-eslint/prefer-regexp-exec': 'off',
410
- '@typescript-eslint/prefer-string-starts-ends-with': 'error',
411
- '@typescript-eslint/prefer-ts-expect-error': 'error',
412
331
  '@typescript-eslint/promise-function-async': 'off',
413
332
  '@typescript-eslint/require-array-sort-compare': 'off',
414
- '@typescript-eslint/require-await': 'off',
415
- '@typescript-eslint/restrict-plus-operands': 'error',
416
- '@typescript-eslint/restrict-template-expressions': 'off',
417
- '@typescript-eslint/sort-type-union-intersection-members': 'off',
333
+ '@typescript-eslint/return-await': 'off',
418
334
  '@typescript-eslint/strict-boolean-expressions': 'off',
419
335
  '@typescript-eslint/switch-exhaustiveness-check': 'error',
420
- '@typescript-eslint/triple-slash-reference': 'error',
421
336
  '@typescript-eslint/typedef': 'off',
422
- '@typescript-eslint/unbound-method': 'error',
423
337
  '@typescript-eslint/unified-signatures': 'warn',
424
338
  },
425
339
  },
package/jest.js CHANGED
@@ -1,7 +1,8 @@
1
1
  const readPkgUp = require('read-pkg-up')
2
2
 
3
3
  let hasJestDom = false
4
- let hasTestingLibrary = false
4
+ let hasTestingLibraryDom = false
5
+ let hasTestingLibraryReact = false
5
6
 
6
7
  try {
7
8
  const { packageJson } = readPkgUp.sync({ normalize: true })
@@ -12,107 +13,13 @@ try {
12
13
  })
13
14
 
14
15
  hasJestDom = allDeps.includes('@testing-library/jest-dom')
15
- hasTestingLibrary = ['@testing-library/dom', '@testing-library/react'].some(
16
- (dependency) => allDeps.includes(dependency)
17
- )
16
+ hasTestingLibraryDom = allDeps.includes('@testing-library/dom')
17
+ hasTestingLibraryReact = allDeps.includes('@testing-library/react')
18
18
  } catch (error) {
19
19
  // ignore error
20
20
  }
21
21
 
22
- const rules = {
23
- 'react/display-name': 'off', // we don't need a display name in test files
24
-
25
- 'jest/consistent-test-it': 'off',
26
- 'jest/expect-expect': 'off',
27
- 'jest/max-nested-describe': 'error',
28
- 'jest/no-alias-methods': 'off',
29
- 'jest/no-commented-out-tests': 'warn',
30
- 'jest/no-conditional-expect': 'error',
31
- 'jest/no-deprecated-functions': 'error',
32
- 'jest/no-disabled-tests': 'warn',
33
- 'jest/no-done-callback': 'error',
34
- 'jest/no-duplicate-hooks': 'off',
35
- 'jest/no-export': 'error',
36
- 'jest/no-focused-tests': 'error',
37
- 'jest/no-hooks': 'off',
38
- 'jest/no-identical-title': 'error',
39
- 'jest/no-if': 'error',
40
- 'jest/no-interpolation-in-snapshots': 'error',
41
- 'jest/no-jasmine-globals': 'off',
42
- 'jest/no-jest-import': 'error',
43
- 'jest/no-large-snapshots': ['warn', { maxSize: 300 }],
44
- 'jest/no-mocks-import': 'error',
45
- 'jest/no-restricted-matchers': 'off',
46
- 'jest/no-standalone-expect': 'off',
47
- 'jest/no-test-prefixes': 'error',
48
- 'jest/no-test-return-statement': 'off',
49
- 'jest/prefer-called-with': 'error',
50
- 'jest/prefer-expect-assertions': 'off',
51
- 'jest/prefer-expect-resolves': 'off',
52
- 'jest/prefer-hooks-on-top': 'error',
53
- 'jest/prefer-lowercase-title': 'off',
54
- 'jest/prefer-spy-on': 'off',
55
- 'jest/prefer-strict-equal': 'off',
56
- 'jest/prefer-to-be': 'off',
57
- 'jest/prefer-to-contain': 'warn',
58
- 'jest/prefer-to-have-length': 'warn',
59
- 'jest/prefer-todo': 'warn',
60
- 'jest/require-hook': 'off',
61
- 'jest/require-to-throw-message': 'off',
62
- 'jest/require-top-level-describe': 'off',
63
- 'jest/unbound-method': 'off',
64
- 'jest/valid-describe-callback': 'error',
65
- 'jest/valid-expect': 'error',
66
- 'jest/valid-expect-in-promise': 'error',
67
- 'jest/valid-title': 'warn',
68
-
69
- ...(hasJestDom
70
- ? {
71
- 'jest-dom/prefer-checked': 'error',
72
- 'jest-dom/prefer-empty': 'error',
73
- 'jest-dom/prefer-enabled-disabled': 'error',
74
- 'jest-dom/prefer-focus': 'error',
75
- 'jest-dom/prefer-in-document': 'error',
76
- 'jest-dom/prefer-required': 'error',
77
- 'jest-dom/prefer-to-have-attribute': 'error',
78
- 'jest-dom/prefer-to-have-class': 'error',
79
- 'jest-dom/prefer-to-have-style': 'error',
80
- 'jest-dom/prefer-to-have-text-content': 'error',
81
- 'jest-dom/prefer-to-have-value': 'error',
82
- }
83
- : null),
84
-
85
- ...(hasTestingLibrary
86
- ? {
87
- 'testing-library/await-async-query': 'error',
88
- 'testing-library/await-async-utils': 'error',
89
- 'testing-library/await-fire-event': 'off',
90
- 'testing-library/consistent-data-testid': 'off',
91
- 'testing-library/no-await-sync-events': 'error',
92
- 'testing-library/no-await-sync-query': 'error',
93
- 'testing-library/no-container': 'error',
94
- 'testing-library/no-debugging-utils': 'error',
95
- 'testing-library/no-dom-import': ['error', 'react'],
96
- 'testing-library/no-manual-cleanup': 'error',
97
- 'testing-library/no-node-access': 'error',
98
- 'testing-library/no-promise-in-fire-event': 'error',
99
- 'testing-library/no-render-in-setup': 'error',
100
- 'testing-library/no-unnecessary-act': 'error',
101
- 'testing-library/no-wait-for-empty-callback': 'error',
102
- 'testing-library/no-wait-for-multiple-assertions': 'error',
103
- 'testing-library/no-wait-for-side-effects': 'error',
104
- 'testing-library/no-wait-for-snapshot': 'error',
105
- 'testing-library/prefer-explicit-assert': 'warn',
106
- 'testing-library/prefer-find-by': 'error',
107
- 'testing-library/prefer-presence-queries': 'error',
108
- 'testing-library/prefer-query-by-disappearance': 'error',
109
- 'testing-library/prefer-screen-queries': 'error',
110
- 'testing-library/prefer-user-event': 'error',
111
- 'testing-library/prefer-wait-for': 'error',
112
- 'testing-library/render-result-naming-convention': 'error',
113
- }
114
- : null),
115
- }
22
+ const hasTestingLibrary = hasTestingLibraryDom || hasTestingLibraryReact
116
23
 
117
24
  module.exports = {
118
25
  env: {
@@ -123,14 +30,83 @@ module.exports = {
123
30
  hasJestDom && 'jest-dom',
124
31
  hasTestingLibrary && 'testing-library',
125
32
  ].filter(Boolean),
126
- rules: disableAll(rules),
127
33
  overrides: [
128
34
  {
129
35
  files: [
130
36
  '**/__tests__/**/*.+(js|ts)?(x)',
131
37
  '**/*.{spec,test}.+(js|ts)?(x)',
132
38
  ],
133
- rules,
39
+ extends: [
40
+ 'plugin:jest/recommended',
41
+ 'plugin:jest/style',
42
+ hasJestDom && 'plugin:jest-dom/recommended',
43
+ hasTestingLibraryReact
44
+ ? 'plugin:testing-library/react'
45
+ : hasTestingLibraryDom
46
+ ? 'plugin:testing-library/dom'
47
+ : null,
48
+ ].filter(Boolean),
49
+ rules: {
50
+ 'react/display-name': 'off', // we don't need a display name in test files
51
+
52
+ 'jest/consistent-test-it': 'off',
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-equality-matcher': 'warn',
76
+ 'jest/prefer-expect-assertions': 'off',
77
+ 'jest/prefer-expect-resolves': 'off',
78
+ 'jest/prefer-hooks-in-order': 'error',
79
+ 'jest/prefer-hooks-on-top': 'error',
80
+ 'jest/prefer-importing-jest-globals': 'off',
81
+ 'jest/prefer-jest-mocked': 'warn',
82
+ 'jest/prefer-lowercase-title': 'off',
83
+ 'jest/prefer-mock-promise-shorthand': 'warn',
84
+ 'jest/prefer-snapshot-hint': ['error', 'multi'],
85
+ 'jest/prefer-spy-on': 'off',
86
+ 'jest/prefer-strict-equal': 'off',
87
+ 'jest/prefer-todo': 'warn',
88
+ 'jest/require-hook': 'off',
89
+ 'jest/require-to-throw-message': 'off',
90
+ 'jest/require-top-level-describe': 'off',
91
+ 'jest/unbound-method': 'off',
92
+
93
+ ...(hasTestingLibrary
94
+ ? {
95
+ 'testing-library/consistent-data-testid': 'off',
96
+ 'testing-library/no-container': 'error',
97
+ 'testing-library/no-debugging-utils': 'error',
98
+ 'testing-library/no-dom-import': ['error', 'react'],
99
+ 'testing-library/no-manual-cleanup': 'error',
100
+ 'testing-library/no-render-in-lifecycle': 'error',
101
+ 'testing-library/no-unnecessary-act': 'error',
102
+ 'testing-library/prefer-explicit-assert': 'warn',
103
+ 'testing-library/prefer-implicit-assert': 'off',
104
+ 'testing-library/prefer-query-matchers': 'off',
105
+ 'testing-library/prefer-user-event': 'error',
106
+ 'testing-library/render-result-naming-convention': 'error',
107
+ }
108
+ : null),
109
+ },
134
110
  },
135
111
  {
136
112
  files: ['**/__tests__/**/*.ts?(x)', '**/*.{spec,test}.ts?(x)'],
@@ -141,10 +117,3 @@ module.exports = {
141
117
  },
142
118
  ],
143
119
  }
144
-
145
- function disableAll(obj) {
146
- return Object.keys(obj).reduce((rules, rule) => {
147
- rules[rule] = 'off'
148
- return rules
149
- }, {})
150
- }
package/jsx-a11y.js CHANGED
@@ -8,41 +8,15 @@ module.exports = {
8
8
  },
9
9
  },
10
10
  plugins: ['jsx-a11y'],
11
+ extends: ['plugin:jsx-a11y/recommended'],
11
12
  rules: {
12
- 'jsx-a11y/accessible-emoji': 'error',
13
13
  'jsx-a11y/alt-text': 'warn',
14
- 'jsx-a11y/anchor-has-content': 'error',
15
- 'jsx-a11y/anchor-is-valid': 'error',
16
- 'jsx-a11y/aria-activedescendant-has-tabindex': 'error',
17
- 'jsx-a11y/aria-props': 'error',
18
- 'jsx-a11y/aria-proptypes': 'error',
19
- 'jsx-a11y/aria-role': 'error',
20
- 'jsx-a11y/aria-unsupported-elements': 'error',
21
- 'jsx-a11y/autocomplete-valid': 'error',
22
- 'jsx-a11y/click-events-have-key-events': 'error',
23
- 'jsx-a11y/control-has-associated-label': 'off',
24
- 'jsx-a11y/heading-has-content': 'error',
25
- 'jsx-a11y/html-has-lang': 'error',
26
- 'jsx-a11y/iframe-has-title': 'error',
27
- 'jsx-a11y/img-redundant-alt': 'error',
28
- 'jsx-a11y/interactive-supports-focus': 'warn',
29
- 'jsx-a11y/label-has-associated-control': 'error',
30
14
  'jsx-a11y/lang': 'error',
31
- 'jsx-a11y/media-has-caption': 'warn',
32
- 'jsx-a11y/mouse-events-have-key-events': 'error',
33
- 'jsx-a11y/no-access-key': 'error',
15
+ 'jsx-a11y/no-aria-hidden-on-focusable': 'off',
34
16
  'jsx-a11y/no-autofocus': 'off',
35
- 'jsx-a11y/no-distracting-elements': 'error',
36
- 'jsx-a11y/no-interactive-element-to-noninteractive-role': 'warn',
37
- 'jsx-a11y/no-noninteractive-element-interactions': 'warn',
38
- 'jsx-a11y/no-noninteractive-element-to-interactive-role': 'warn',
39
17
  'jsx-a11y/no-noninteractive-tabindex': 'off',
40
- 'jsx-a11y/no-onchange': 'off',
41
- 'jsx-a11y/no-redundant-roles': 'error',
42
18
  'jsx-a11y/no-static-element-interactions': 'off',
43
- 'jsx-a11y/role-has-required-aria-props': 'error',
44
- 'jsx-a11y/role-supports-aria-props': 'error',
45
- 'jsx-a11y/scope': 'error',
19
+ 'jsx-a11y/prefer-tag-over-role': 'off',
46
20
  'jsx-a11y/tabindex-no-positive': 'warn',
47
21
  },
48
22
  }
package/package.json CHANGED
@@ -1,37 +1,51 @@
1
1
  {
2
2
  "name": "@mrpalmer/eslint-config",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Mike Palmer's personal ESLint rules",
5
5
  "license": "MIT",
6
6
  "main": "index.js",
7
7
  "scripts": {
8
- "find-new-rules": "run-p find-new-rules:*",
9
- "find-new-rules:jest": "eslint-find-rules --unused ./test/jest.js",
10
- "find-new-rules:jsx-a11y": "eslint-find-rules --unused ./test/jsx-a11y.js",
11
- "find-new-rules:main": "eslint-find-rules --unused ./index.js",
12
- "find-new-rules:react": "eslint-find-rules --unused ./test/react.js",
8
+ "check-config": "run-p check-config:*",
9
+ "check-config:jest": "validate-config -f component.test.js ./test/jest.js",
10
+ "check-config:jest-ts": "validate-config -f component.test.ts ./test/jest.js",
11
+ "check-config:js": "validate-config -f index.js ./index.js",
12
+ "check-config:jsx-a11y": "validate-config -f component.jsx ./test/jsx-a11y.js",
13
+ "check-config:react": "validate-config -f component.jsx ./test/react.js",
14
+ "check-config:ts": "validate-config -f index.ts ./index.js",
13
15
  "lint": "eslint --config index.js .",
14
- "validate": "run-p lint find-new-rules"
16
+ "validate": "run-p lint check-config"
15
17
  },
16
18
  "dependencies": {
17
- "@typescript-eslint/eslint-plugin": "^5.9.0",
18
- "@typescript-eslint/parser": "^5.9.0",
19
- "eslint-config-prettier": "^8.3.0",
20
- "eslint-plugin-import": "^2.25.4",
21
- "eslint-plugin-jest": "^25.3.4",
22
- "eslint-plugin-jest-dom": "^4.0.1",
23
- "eslint-plugin-jsx-a11y": "^6.5.1",
24
- "eslint-plugin-react": "^7.28.0",
25
- "eslint-plugin-react-hooks": "^4.3.0",
26
- "eslint-plugin-testing-library": "^5.0.1",
19
+ "@typescript-eslint/eslint-plugin": "^8.1.0",
20
+ "@typescript-eslint/parser": "^8.1.0",
21
+ "eslint-config-prettier": "^9.1.0",
22
+ "eslint-plugin-import": "^2.29.1",
23
+ "eslint-plugin-jest": "^28.8.0",
24
+ "eslint-plugin-jest-dom": "^5.4.0",
25
+ "eslint-plugin-jsx-a11y": "^6.9.0",
26
+ "eslint-plugin-react": "^7.35.0",
27
+ "eslint-plugin-react-hooks": "^4.6.2",
28
+ "eslint-plugin-testing-library": "^6.3.0",
27
29
  "read-pkg-up": "^7.0.1",
28
30
  "semver": "^7.3.2"
29
31
  },
30
32
  "peerDependencies": {
33
+ "@testing-library/dom": "*",
34
+ "@testing-library/jest-dom": "*",
35
+ "@testing-library/react": "*",
31
36
  "eslint": "^8.0.0",
32
- "typescript": "^4.0.0"
37
+ "typescript": "^4.0.0 || ^5.0.0"
33
38
  },
34
39
  "peerDependenciesMeta": {
40
+ "@testing-library/dom": {
41
+ "optional": true
42
+ },
43
+ "@testing-library/jest-dom": {
44
+ "optional": true
45
+ },
46
+ "@testing-library/react": {
47
+ "optional": true
48
+ },
35
49
  "typescript": {
36
50
  "optional": true
37
51
  }
package/react.js CHANGED
@@ -43,6 +43,7 @@ module.exports = {
43
43
  rules: {
44
44
  'react/boolean-prop-naming': 'off',
45
45
  'react/button-has-type': 'off',
46
+ 'react/checked-requires-onchange-or-readonly': 'error',
46
47
  'react/default-props-match-prop-types': hasPropTypes ? 'error' : 'off',
47
48
  'react/destructuring-assignment': 'off',
48
49
  'react/display-name': ['error', { ignoreTranspilerName: false }],
@@ -52,6 +53,8 @@ module.exports = {
52
53
  'react/forbid-foreign-prop-types': hasPropTypes ? 'error' : 'off',
53
54
  'react/forbid-prop-types': 'off',
54
55
  'react/function-component-definition': 'off',
56
+ 'react/hook-use-state': 'off',
57
+ 'react/iframe-missing-sandbox': 'warn',
55
58
  'react/jsx-boolean-value': 'off',
56
59
  'react/jsx-curly-brace-presence': [
57
60
  'warn',
@@ -66,14 +69,15 @@ module.exports = {
66
69
  'react/jsx-no-comment-textnodes': 'error',
67
70
  'react/jsx-no-constructed-context-values': 'off',
68
71
  'react/jsx-no-duplicate-props': 'error',
72
+ 'react/jsx-no-leaked-render': 'off',
69
73
  'react/jsx-no-literals': 'off',
70
74
  'react/jsx-no-script-url': 'error',
71
75
  'react/jsx-no-target-blank': 'error',
72
76
  'react/jsx-no-undef': 'error',
73
77
  'react/jsx-no-useless-fragment': 'warn',
74
78
  'react/jsx-pascal-case': 'error',
79
+ 'react/jsx-props-no-spread-multi': 'warn',
75
80
  'react/jsx-props-no-spreading': 'off',
76
- 'react/jsx-sort-default-props': 'off',
77
81
  'react/jsx-sort-props': 'off',
78
82
  'react/jsx-uses-react': 'error',
79
83
  'react/jsx-uses-vars': 'error',
@@ -93,6 +97,7 @@ module.exports = {
93
97
  'react/no-is-mounted': 'error',
94
98
  'react/no-multi-comp': 'off',
95
99
  'react/no-namespace': 'error',
100
+ 'react/no-object-type-as-default-prop': 'warn',
96
101
  'react/no-redundant-should-component-update': 'error',
97
102
  'react/no-render-return-value': 'error',
98
103
  'react/no-set-state': 'off',
@@ -118,6 +123,7 @@ module.exports = {
118
123
  'react/require-render-return': 'error',
119
124
  'react/self-closing-comp': 'error',
120
125
  'react/sort-comp': 'off',
126
+ 'react/sort-default-props': 'off',
121
127
  'react/sort-prop-types': 'off',
122
128
  'react/state-in-constructor': 'off',
123
129
  'react/static-property-placement': 'off',