@foray1010/eslint-config 14.0.1 → 15.0.0
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/CHANGELOG.md +11 -0
- package/README.md +18 -20
- package/bases/base.mjs +78 -79
- package/bases/browser.mjs +11 -23
- package/bases/ignores.mjs +11 -14
- package/bases/node.mjs +8 -10
- package/bases/prettier.mjs +4 -5
- package/bases/react.mjs +10 -18
- package/index.mjs +19 -23
- package/package.json +3 -3
- package/utils/applyConfig.mjs +0 -72
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,17 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [15.0.0](https://github.com/foray1010/common-presets/compare/@foray1010/eslint-config@14.0.1...@foray1010/eslint-config@15.0.0) (2025-03-13)
|
|
7
|
+
|
|
8
|
+
### ⚠ BREAKING CHANGES
|
|
9
|
+
|
|
10
|
+
- drop applyConfig utils
|
|
11
|
+
- require eslint ^9.22.0
|
|
12
|
+
|
|
13
|
+
### Features
|
|
14
|
+
|
|
15
|
+
- migrate to eslint defineConfig utils ([faf0aa7](https://github.com/foray1010/common-presets/commit/faf0aa74048b2536e188a45b8371ebe416dcb851))
|
|
16
|
+
|
|
6
17
|
## [14.0.1](https://github.com/foray1010/common-presets/compare/@foray1010/eslint-config@14.0.0...@foray1010/eslint-config@14.0.1) (2025-03-11)
|
|
7
18
|
|
|
8
19
|
### Bug Fixes
|
package/README.md
CHANGED
|
@@ -29,8 +29,9 @@ Z for looser rules
|
|
|
29
29
|
eslintIgnoresConfig,
|
|
30
30
|
eslintNodeConfig,
|
|
31
31
|
} from '@foray1010/eslint-config'
|
|
32
|
+
import { defineConfig } from 'eslint/config'
|
|
32
33
|
|
|
33
|
-
const config =
|
|
34
|
+
const config = defineConfig(eslintIgnoresConfig, eslintNodeConfig)
|
|
34
35
|
export default config
|
|
35
36
|
```
|
|
36
37
|
|
|
@@ -41,8 +42,9 @@ Z for looser rules
|
|
|
41
42
|
eslintIgnoresConfig,
|
|
42
43
|
eslintBrowserConfig,
|
|
43
44
|
} from '@foray1010/eslint-config'
|
|
45
|
+
import { defineConfig } from 'eslint/config'
|
|
44
46
|
|
|
45
|
-
const config =
|
|
47
|
+
const config = defineConfig(eslintIgnoresConfig, eslintBrowserConfig)
|
|
46
48
|
export default config
|
|
47
49
|
```
|
|
48
50
|
|
|
@@ -53,8 +55,9 @@ Z for looser rules
|
|
|
53
55
|
eslintIgnoresConfig,
|
|
54
56
|
eslintReactConfig,
|
|
55
57
|
} from '@foray1010/eslint-config'
|
|
58
|
+
import { defineConfig } from 'eslint/config'
|
|
56
59
|
|
|
57
|
-
const config =
|
|
60
|
+
const config = defineConfig(eslintIgnoresConfig, eslintReactConfig)
|
|
58
61
|
export default config
|
|
59
62
|
```
|
|
60
63
|
|
|
@@ -62,28 +65,23 @@ Z for looser rules
|
|
|
62
65
|
|
|
63
66
|
```js
|
|
64
67
|
import {
|
|
65
|
-
applyConfig,
|
|
66
68
|
eslintIgnoresConfig,
|
|
67
69
|
eslintNodeConfig,
|
|
68
70
|
eslintReactConfig,
|
|
69
71
|
} from '@foray1010/eslint-config'
|
|
72
|
+
import { defineConfig } from 'eslint/config'
|
|
70
73
|
|
|
71
|
-
const config =
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
filePrefixes: ['src'],
|
|
83
|
-
},
|
|
84
|
-
eslintReactConfig,
|
|
85
|
-
),
|
|
86
|
-
]
|
|
74
|
+
const config = defineConfig(
|
|
75
|
+
eslintIgnoresConfig,
|
|
76
|
+
{
|
|
77
|
+
ignores: ['src/**'],
|
|
78
|
+
extends: [eslintNodeConfig],
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
files: ['src/**'],
|
|
82
|
+
extends: [eslintReactConfig],
|
|
83
|
+
},
|
|
84
|
+
)
|
|
87
85
|
export default config
|
|
88
86
|
```
|
|
89
87
|
|
package/bases/base.mjs
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import js from '@eslint/js'
|
|
2
|
-
|
|
2
|
+
// eslint-disable-next-line import-x/extensions
|
|
3
|
+
import eslintPluginEslintCommentsConfigs from '@eslint-community/eslint-plugin-eslint-comments/configs'
|
|
3
4
|
import { hasDep, isESM } from '@foray1010/common-presets-utils'
|
|
5
|
+
// eslint-disable-next-line import-x/extensions, import-x/no-unresolved
|
|
6
|
+
import { defineConfig } from 'eslint/config'
|
|
4
7
|
import eslintPluginImportX from 'eslint-plugin-import-x'
|
|
5
8
|
import eslintPluginJest from 'eslint-plugin-jest'
|
|
6
9
|
import eslintPluginRegexp from 'eslint-plugin-regexp'
|
|
@@ -14,23 +17,20 @@ import {
|
|
|
14
17
|
typeScriptTestFileGlobs,
|
|
15
18
|
} from '../constants.mjs'
|
|
16
19
|
|
|
17
|
-
/** @typedef {import('../types/internal.d.ts').EslintConfig} EslintConfig */
|
|
18
|
-
|
|
19
|
-
/** @returns {Promise<EslintConfig>} */
|
|
20
20
|
async function generateTypeScriptConfig() {
|
|
21
21
|
// typescript plugins are depended on `typescript` package
|
|
22
|
-
if (!hasDep('typescript')) return
|
|
22
|
+
if (!hasDep('typescript')) return defineConfig({})
|
|
23
23
|
|
|
24
24
|
// eslint-disable-next-line import-x/no-unresolved
|
|
25
25
|
const tseslint = (await import('typescript-eslint')).default
|
|
26
26
|
|
|
27
|
-
return
|
|
28
|
-
|
|
29
|
-
...tseslint.config({
|
|
27
|
+
return defineConfig(
|
|
28
|
+
{
|
|
30
29
|
files: typeScriptFileGlobs,
|
|
31
30
|
extends: [
|
|
32
31
|
tseslint.configs.eslintRecommended,
|
|
33
|
-
|
|
32
|
+
tseslint.configs.recommendedTypeChecked,
|
|
33
|
+
eslintPluginImportX.configs['typescript'],
|
|
34
34
|
esmConfig,
|
|
35
35
|
],
|
|
36
36
|
languageOptions: {
|
|
@@ -42,13 +42,7 @@ async function generateTypeScriptConfig() {
|
|
|
42
42
|
project: ['./tsconfig*.json', './packages/*/tsconfig*.json'],
|
|
43
43
|
},
|
|
44
44
|
},
|
|
45
|
-
settings: {
|
|
46
|
-
'import-x/resolver': {
|
|
47
|
-
typescript: true,
|
|
48
|
-
},
|
|
49
|
-
},
|
|
50
45
|
rules: {
|
|
51
|
-
...eslintPluginImportX.configs['typescript']?.rules,
|
|
52
46
|
// separate type exports which allow certain optimizations within compilers
|
|
53
47
|
'@typescript-eslint/consistent-type-exports': [
|
|
54
48
|
'error',
|
|
@@ -136,8 +130,7 @@ async function generateTypeScriptConfig() {
|
|
|
136
130
|
// It is disabled in recommended config but re-enabled here to enforce a subset of global variables that supported by both node.js and browsers
|
|
137
131
|
'no-undef': 'error',
|
|
138
132
|
},
|
|
139
|
-
}
|
|
140
|
-
// @ts-expect-error As previous item's type is not correct, this item is affected too
|
|
133
|
+
},
|
|
141
134
|
{
|
|
142
135
|
files: typeScriptTestFileGlobs,
|
|
143
136
|
rules: {
|
|
@@ -149,11 +142,10 @@ async function generateTypeScriptConfig() {
|
|
|
149
142
|
'jest/unbound-method': ['error', { ignoreStatic: true }],
|
|
150
143
|
},
|
|
151
144
|
},
|
|
152
|
-
|
|
145
|
+
)
|
|
153
146
|
}
|
|
154
147
|
|
|
155
|
-
|
|
156
|
-
const cjsConfig = {
|
|
148
|
+
const cjsConfig = defineConfig({
|
|
157
149
|
languageOptions: {
|
|
158
150
|
globals: globals.commonjs,
|
|
159
151
|
sourceType: 'script',
|
|
@@ -162,10 +154,9 @@ const cjsConfig = {
|
|
|
162
154
|
// commonjs must use strict mode
|
|
163
155
|
strict: ['error', 'global'],
|
|
164
156
|
},
|
|
165
|
-
}
|
|
157
|
+
})
|
|
166
158
|
|
|
167
|
-
|
|
168
|
-
const esmConfig = {
|
|
159
|
+
const esmConfig = defineConfig({
|
|
169
160
|
languageOptions: {
|
|
170
161
|
sourceType: 'module',
|
|
171
162
|
},
|
|
@@ -178,16 +169,25 @@ const esmConfig = {
|
|
|
178
169
|
// auto sort import statements
|
|
179
170
|
'simple-import-sort/imports': 'error',
|
|
180
171
|
},
|
|
181
|
-
}
|
|
172
|
+
})
|
|
182
173
|
|
|
183
|
-
|
|
184
|
-
const baseConfig = [
|
|
174
|
+
const baseConfig = defineConfig(
|
|
185
175
|
js.configs.recommended,
|
|
186
|
-
eslintPluginRegexp.configs['flat/recommended'],
|
|
187
176
|
{
|
|
188
|
-
|
|
177
|
+
extends: [eslintPluginEslintCommentsConfigs['recommended']],
|
|
178
|
+
rules: {
|
|
179
|
+
// allow disable eslint rules for whole file without re-enable it in the end of the file
|
|
180
|
+
'@eslint-community/eslint-comments/disable-enable-pair': [
|
|
181
|
+
'error',
|
|
182
|
+
{ allowWholeFile: true },
|
|
183
|
+
],
|
|
184
|
+
// make sure every eslint-disable comments are in use
|
|
185
|
+
'@eslint-community/eslint-comments/no-unused-disable': 'error',
|
|
186
|
+
},
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
extends: [eslintPluginImportX.flatConfigs.recommended],
|
|
189
190
|
rules: {
|
|
190
|
-
...eslintPluginImportX.flatConfigs.recommended.rules,
|
|
191
191
|
// this rule doesn't support commonjs, some dependencies are using commonjs
|
|
192
192
|
'import-x/default': 'off',
|
|
193
193
|
// Does not work after upgrading to eslint-plugin-import-x v4, got this error message: `sourceType 'module' is not supported when ecmaVersion < 2015. Consider adding `{ ecmaVersion: 2015 }` to the parser options. (undefined:undefined)`
|
|
@@ -262,27 +262,17 @@ const baseConfig = [
|
|
|
262
262
|
},
|
|
263
263
|
},
|
|
264
264
|
{
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
languageOptions: {
|
|
270
|
-
ecmaVersion: 2023,
|
|
271
|
-
globals: {
|
|
272
|
-
...globals.es2023,
|
|
273
|
-
/* Not using `node` to explicitly import node.js only built-in modules, e.g.
|
|
274
|
-
* import { Buffer } from 'node:buffer'
|
|
275
|
-
* import process from 'node:process'
|
|
276
|
-
*/
|
|
277
|
-
...globals['shared-node-browser'],
|
|
278
|
-
},
|
|
265
|
+
extends: [eslintPluginRegexp.configs['flat/recommended']],
|
|
266
|
+
rules: {
|
|
267
|
+
// enable regexp strict mode (use `v` flag instead when it is widely supported)
|
|
268
|
+
'regexp/require-unicode-regexp': 'error',
|
|
279
269
|
},
|
|
270
|
+
},
|
|
271
|
+
{
|
|
280
272
|
plugins: {
|
|
281
|
-
'@eslint-community/eslint-comments': eslintPluginEslintComments,
|
|
282
273
|
unicorn: eslintPluginUnicorn,
|
|
283
274
|
},
|
|
284
275
|
rules: {
|
|
285
|
-
...eslintPluginEslintComments.configs['recommended']?.rules,
|
|
286
276
|
...Object.fromEntries(
|
|
287
277
|
Object.entries(
|
|
288
278
|
eslintPluginUnicorn.configs['flat/recommended']?.rules ?? {},
|
|
@@ -294,13 +284,40 @@ const baseConfig = [
|
|
|
294
284
|
)
|
|
295
285
|
}),
|
|
296
286
|
),
|
|
297
|
-
//
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
//
|
|
303
|
-
'
|
|
287
|
+
// use with `unicorn/throw-new-error`
|
|
288
|
+
// disallow builtins to be created without `new` operator, to be consistent with es6 class syntax
|
|
289
|
+
'unicorn/new-for-builtins': 'error',
|
|
290
|
+
// some legacy projects still use commonjs
|
|
291
|
+
'unicorn/prefer-module': 'off',
|
|
292
|
+
// `querySelector` is slower than `getElementById`
|
|
293
|
+
'unicorn/prefer-query-selector': 'off',
|
|
294
|
+
// `Array.from(iterable)` is more readable than `[...iterable]`
|
|
295
|
+
'unicorn/prefer-spread': 'off',
|
|
296
|
+
// sometimes it is less readable using ternary expressions
|
|
297
|
+
'unicorn/prefer-ternary': 'off',
|
|
298
|
+
// webpack support on `top level await` is still experimental, and some legacy projects still use commonjs
|
|
299
|
+
'unicorn/prefer-top-level-await': 'off',
|
|
300
|
+
// use with `unicorn/new-for-builtins`
|
|
301
|
+
'unicorn/throw-new-error': 'error',
|
|
302
|
+
},
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
linterOptions: {
|
|
306
|
+
reportUnusedDisableDirectives: 'error',
|
|
307
|
+
reportUnusedInlineConfigs: 'error',
|
|
308
|
+
},
|
|
309
|
+
languageOptions: {
|
|
310
|
+
ecmaVersion: 2023,
|
|
311
|
+
globals: {
|
|
312
|
+
...globals.es2023,
|
|
313
|
+
/* Not using `node` to explicitly import node.js only built-in modules, e.g.
|
|
314
|
+
* import { Buffer } from 'node:buffer'
|
|
315
|
+
* import process from 'node:process'
|
|
316
|
+
*/
|
|
317
|
+
...globals['shared-node-browser'],
|
|
318
|
+
},
|
|
319
|
+
},
|
|
320
|
+
rules: {
|
|
304
321
|
// always use named function for easier to debug via stack trace
|
|
305
322
|
'func-names': ['error', 'as-needed'],
|
|
306
323
|
// prefer explicitly convert type for readability
|
|
@@ -317,49 +334,31 @@ const baseConfig = [
|
|
|
317
334
|
destructuring: 'all',
|
|
318
335
|
},
|
|
319
336
|
],
|
|
320
|
-
// enable regexp strict mode (use `v` flag instead when it is widely supported)
|
|
321
|
-
'regexp/require-unicode-regexp': 'error',
|
|
322
|
-
// use with `unicorn/throw-new-error`
|
|
323
|
-
// disallow builtins to be created without `new` operator, to be consistent with es6 class syntax
|
|
324
|
-
'unicorn/new-for-builtins': 'error',
|
|
325
|
-
// some legacy projects still use commonjs
|
|
326
|
-
'unicorn/prefer-module': 'off',
|
|
327
|
-
// `querySelector` is slower than `getElementById`
|
|
328
|
-
'unicorn/prefer-query-selector': 'off',
|
|
329
|
-
// `Array.from(iterable)` is more readable than `[...iterable]`
|
|
330
|
-
'unicorn/prefer-spread': 'off',
|
|
331
|
-
// sometimes it is less readable using ternary expressions
|
|
332
|
-
'unicorn/prefer-ternary': 'off',
|
|
333
|
-
// webpack support on `top level await` is still experimental, and some legacy projects still use commonjs
|
|
334
|
-
'unicorn/prefer-top-level-await': 'off',
|
|
335
|
-
// use with `unicorn/new-for-builtins`
|
|
336
|
-
'unicorn/throw-new-error': 'error',
|
|
337
337
|
},
|
|
338
338
|
},
|
|
339
339
|
{
|
|
340
340
|
files: ['**/*.js'],
|
|
341
|
-
|
|
341
|
+
extends: [isESM() ? esmConfig : cjsConfig],
|
|
342
342
|
},
|
|
343
343
|
{
|
|
344
344
|
files: ['**/*.cjs'],
|
|
345
|
-
|
|
345
|
+
extends: [cjsConfig],
|
|
346
346
|
},
|
|
347
347
|
{
|
|
348
348
|
files: ['**/*.mjs'],
|
|
349
|
-
|
|
350
|
-
},
|
|
351
|
-
{
|
|
352
|
-
files: testFileGlobs,
|
|
353
|
-
...eslintPluginJest.configs['flat/recommended'],
|
|
354
|
-
...eslintPluginJest.configs['flat/style'],
|
|
349
|
+
extends: [esmConfig],
|
|
355
350
|
},
|
|
356
351
|
{
|
|
357
352
|
files: testFileGlobs,
|
|
353
|
+
extends: [
|
|
354
|
+
eslintPluginJest.configs['flat/recommended'],
|
|
355
|
+
eslintPluginJest.configs['flat/style'],
|
|
356
|
+
],
|
|
358
357
|
rules: {
|
|
359
358
|
// make sure lifecycle hooks on the top for readability
|
|
360
359
|
'jest/prefer-hooks-on-top': 'error',
|
|
361
360
|
},
|
|
362
361
|
},
|
|
363
|
-
|
|
364
|
-
|
|
362
|
+
await generateTypeScriptConfig(),
|
|
363
|
+
)
|
|
365
364
|
export default baseConfig
|
package/bases/browser.mjs
CHANGED
|
@@ -1,30 +1,26 @@
|
|
|
1
1
|
import { hasDep } from '@foray1010/common-presets-utils'
|
|
2
2
|
import restrictedGlobals from 'confusing-browser-globals'
|
|
3
|
+
// eslint-disable-next-line import-x/extensions, import-x/no-unresolved
|
|
4
|
+
import { defineConfig } from 'eslint/config'
|
|
3
5
|
import eslintPluginCompat from 'eslint-plugin-compat'
|
|
4
6
|
import eslintPluginTestingLibrary from 'eslint-plugin-testing-library'
|
|
5
7
|
import globals from 'globals'
|
|
6
8
|
|
|
7
9
|
import { testFileGlobs } from '../constants.mjs'
|
|
8
10
|
|
|
9
|
-
/** @typedef {import('../types/internal.d.ts').EslintConfig} EslintConfig */
|
|
10
|
-
|
|
11
|
-
/** @returns {Promise<EslintConfig>} */
|
|
12
11
|
async function generateJestDomConfig() {
|
|
13
12
|
// `eslint-plugin-jest-dom` depends on `@testing-library/dom` package
|
|
14
|
-
if (!hasDep('@testing-library/dom')) return
|
|
13
|
+
if (!hasDep('@testing-library/dom')) return defineConfig({})
|
|
15
14
|
|
|
16
15
|
const eslintPluginJestDom = (await import('eslint-plugin-jest-dom')).default
|
|
17
16
|
|
|
18
|
-
return
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
},
|
|
23
|
-
]
|
|
17
|
+
return defineConfig({
|
|
18
|
+
files: testFileGlobs,
|
|
19
|
+
extends: [eslintPluginJestDom.configs['flat/recommended']],
|
|
20
|
+
})
|
|
24
21
|
}
|
|
25
22
|
|
|
26
|
-
|
|
27
|
-
const browserConfig = [
|
|
23
|
+
const browserConfig = defineConfig(
|
|
28
24
|
{
|
|
29
25
|
languageOptions: {
|
|
30
26
|
globals: {
|
|
@@ -44,22 +40,14 @@ const browserConfig = [
|
|
|
44
40
|
'no-restricted-globals': ['error', ...restrictedGlobals],
|
|
45
41
|
},
|
|
46
42
|
},
|
|
47
|
-
|
|
48
|
-
{
|
|
49
|
-
files: testFileGlobs,
|
|
50
|
-
plugins: {
|
|
51
|
-
'testing-library': eslintPluginTestingLibrary,
|
|
52
|
-
},
|
|
53
|
-
rules: {
|
|
54
|
-
...eslintPluginTestingLibrary.configs['flat/dom']?.rules,
|
|
55
|
-
},
|
|
56
|
-
},
|
|
43
|
+
await generateJestDomConfig(),
|
|
57
44
|
{
|
|
58
45
|
files: testFileGlobs,
|
|
46
|
+
extends: [eslintPluginTestingLibrary.configs['flat/dom']],
|
|
59
47
|
rules: {
|
|
60
48
|
// allow to use nodejs modules in tests
|
|
61
49
|
'import-x/no-nodejs-modules': 'off',
|
|
62
50
|
},
|
|
63
51
|
},
|
|
64
|
-
|
|
52
|
+
)
|
|
65
53
|
export default browserConfig
|
package/bases/ignores.mjs
CHANGED
|
@@ -1,16 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
// eslint-disable-next-line import-x/extensions, import-x/no-unresolved
|
|
2
|
+
import { defineConfig, globalIgnores } from 'eslint/config'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
'**/node_modules/**',
|
|
13
|
-
],
|
|
14
|
-
},
|
|
15
|
-
]
|
|
4
|
+
const ignoresConfig = defineConfig(
|
|
5
|
+
globalIgnores([
|
|
6
|
+
'**/.yarn/**',
|
|
7
|
+
'**/build/**',
|
|
8
|
+
'**/coverage/**',
|
|
9
|
+
'**/dist/**',
|
|
10
|
+
'**/node_modules/**',
|
|
11
|
+
]),
|
|
12
|
+
)
|
|
16
13
|
export default ignoresConfig
|
package/bases/node.mjs
CHANGED
|
@@ -1,20 +1,18 @@
|
|
|
1
1
|
import { isESM } from '@foray1010/common-presets-utils'
|
|
2
|
+
// eslint-disable-next-line import-x/extensions, import-x/no-unresolved
|
|
3
|
+
import { defineConfig } from 'eslint/config'
|
|
2
4
|
import eslintPluginN from 'eslint-plugin-n'
|
|
3
5
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
/** @type {EslintConfig[number]} */
|
|
7
|
-
const cjsConfig = {
|
|
6
|
+
const cjsConfig = defineConfig({
|
|
8
7
|
languageOptions: {
|
|
9
8
|
globals: {
|
|
10
9
|
__dirname: 'readonly',
|
|
11
10
|
__filename: 'readonly',
|
|
12
11
|
},
|
|
13
12
|
},
|
|
14
|
-
}
|
|
13
|
+
})
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
const nodeConfig = [
|
|
15
|
+
const nodeConfig = defineConfig(
|
|
18
16
|
{
|
|
19
17
|
plugins: {
|
|
20
18
|
n: eslintPluginN,
|
|
@@ -67,12 +65,12 @@ const nodeConfig = [
|
|
|
67
65
|
: [
|
|
68
66
|
{
|
|
69
67
|
files: ['**/*.js'],
|
|
70
|
-
|
|
68
|
+
extends: [cjsConfig],
|
|
71
69
|
},
|
|
72
70
|
]),
|
|
73
71
|
{
|
|
74
72
|
files: ['**/*.{cjs,cts}'],
|
|
75
|
-
|
|
73
|
+
extends: [cjsConfig],
|
|
76
74
|
},
|
|
77
|
-
|
|
75
|
+
)
|
|
78
76
|
export default nodeConfig
|
package/bases/prettier.mjs
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
|
+
// eslint-disable-next-line import-x/extensions, import-x/no-unresolved
|
|
2
|
+
import { defineConfig } from 'eslint/config'
|
|
1
3
|
// eslint-disable-next-line import-x/extensions
|
|
2
4
|
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended'
|
|
3
5
|
|
|
4
|
-
/** @typedef {import('../types/internal.d.ts').EslintConfig} EslintConfig */
|
|
5
|
-
|
|
6
|
-
/** @type {EslintConfig} */
|
|
7
6
|
// should be placed at the end to override other configs
|
|
8
|
-
const prettierConfig =
|
|
7
|
+
const prettierConfig = defineConfig(
|
|
9
8
|
// This includes `eslint-config-prettier` as peer dependency
|
|
10
9
|
eslintPluginPrettierRecommended,
|
|
11
|
-
|
|
10
|
+
)
|
|
12
11
|
export default prettierConfig
|
package/bases/react.mjs
CHANGED
|
@@ -1,26 +1,24 @@
|
|
|
1
|
+
// eslint-disable-next-line import-x/extensions, import-x/no-unresolved
|
|
2
|
+
import { defineConfig } from 'eslint/config'
|
|
1
3
|
import eslintPluginReact from 'eslint-plugin-react'
|
|
2
4
|
import eslintPluginReactHooks from 'eslint-plugin-react-hooks'
|
|
3
5
|
import eslintPluginTestingLibrary from 'eslint-plugin-testing-library'
|
|
4
6
|
|
|
5
7
|
import { testFileGlobs } from '../constants.mjs'
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
/** @type {EslintConfig} */
|
|
10
|
-
const reactConfig = [
|
|
11
|
-
eslintPluginReact.configs.flat.recommended,
|
|
12
|
-
eslintPluginReact.configs.flat['jsx-runtime'],
|
|
9
|
+
const reactConfig = defineConfig(
|
|
13
10
|
{
|
|
14
11
|
settings: {
|
|
15
12
|
react: {
|
|
16
13
|
version: 'detect',
|
|
17
14
|
},
|
|
18
15
|
},
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
16
|
+
extends: [
|
|
17
|
+
eslintPluginReact.configs.flat.recommended,
|
|
18
|
+
eslintPluginReact.configs.flat['jsx-runtime'],
|
|
19
|
+
eslintPluginReactHooks.configs['recommended-latest'],
|
|
20
|
+
],
|
|
22
21
|
rules: {
|
|
23
|
-
...eslintPluginReactHooks.configs['recommended']?.rules,
|
|
24
22
|
// avoid unexpected form submits
|
|
25
23
|
'react/button-has-type': 'error',
|
|
26
24
|
'react/jsx-no-useless-fragment': [
|
|
@@ -61,13 +59,7 @@ const reactConfig = [
|
|
|
61
59
|
},
|
|
62
60
|
{
|
|
63
61
|
files: testFileGlobs,
|
|
64
|
-
|
|
65
|
-
// Do not use flat config directly as eslint v9 does not support duplicated plugins (already defined in browser.mjs)
|
|
66
|
-
...eslintPluginTestingLibrary.configs['flat/react']?.rules,
|
|
67
|
-
},
|
|
68
|
-
},
|
|
69
|
-
{
|
|
70
|
-
files: testFileGlobs,
|
|
62
|
+
extends: [eslintPluginTestingLibrary.configs['flat/react']],
|
|
71
63
|
rules: {
|
|
72
64
|
// avoid using unnecessary `await` as workaround for `not wrapped in act(...)` warnings
|
|
73
65
|
'testing-library/no-await-sync-events': [
|
|
@@ -82,5 +74,5 @@ const reactConfig = [
|
|
|
82
74
|
'testing-library/prefer-user-event': 'error',
|
|
83
75
|
},
|
|
84
76
|
},
|
|
85
|
-
|
|
77
|
+
)
|
|
86
78
|
export default reactConfig
|
package/index.mjs
CHANGED
|
@@ -1,33 +1,29 @@
|
|
|
1
|
+
// eslint-disable-next-line import-x/extensions, import-x/no-unresolved
|
|
2
|
+
import { defineConfig } from 'eslint/config'
|
|
3
|
+
|
|
1
4
|
import baseConfig from './bases/base.mjs'
|
|
2
5
|
import browserConfig from './bases/browser.mjs'
|
|
3
6
|
import nodeConfig from './bases/node.mjs'
|
|
4
7
|
import prettierConfig from './bases/prettier.mjs'
|
|
5
8
|
import reactConfig from './bases/react.mjs'
|
|
6
9
|
|
|
7
|
-
export
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
export const eslintBrowserConfig = [
|
|
13
|
-
...baseConfig,
|
|
14
|
-
...browserConfig,
|
|
15
|
-
...prettierConfig,
|
|
16
|
-
]
|
|
10
|
+
export const eslintBrowserConfig = defineConfig(
|
|
11
|
+
baseConfig,
|
|
12
|
+
browserConfig,
|
|
13
|
+
prettierConfig,
|
|
14
|
+
)
|
|
17
15
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
]
|
|
16
|
+
export const eslintNodeConfig = defineConfig(
|
|
17
|
+
baseConfig,
|
|
18
|
+
nodeConfig,
|
|
19
|
+
prettierConfig,
|
|
20
|
+
)
|
|
24
21
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
]
|
|
22
|
+
export const eslintReactConfig = defineConfig(
|
|
23
|
+
baseConfig,
|
|
24
|
+
browserConfig,
|
|
25
|
+
reactConfig,
|
|
26
|
+
prettierConfig,
|
|
27
|
+
)
|
|
32
28
|
|
|
33
29
|
export { default as eslintIgnoresConfig } from './bases/ignores.mjs'
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package",
|
|
3
3
|
"name": "@foray1010/eslint-config",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "15.0.0",
|
|
5
5
|
"homepage": "https://github.com/foray1010/common-presets/tree/master/packages/eslint-config#readme",
|
|
6
6
|
"bugs": "https://github.com/foray1010/common-presets/issues",
|
|
7
7
|
"repository": {
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
},
|
|
48
48
|
"peerDependencies": {
|
|
49
49
|
"@testing-library/dom": "^10.0.0",
|
|
50
|
-
"eslint": "^9.
|
|
50
|
+
"eslint": "^9.22.0",
|
|
51
51
|
"prettier": "^3.0.0",
|
|
52
52
|
"typescript": "^5.0.2"
|
|
53
53
|
},
|
|
@@ -65,5 +65,5 @@
|
|
|
65
65
|
"publishConfig": {
|
|
66
66
|
"access": "public"
|
|
67
67
|
},
|
|
68
|
-
"gitHead": "
|
|
68
|
+
"gitHead": "321d60ec7b05e7c861bf019fb4c3f7b1410795e9"
|
|
69
69
|
}
|
package/utils/applyConfig.mjs
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import path from 'node:path'
|
|
2
|
-
|
|
3
|
-
import { supportedFilesGlob } from '../constants.mjs'
|
|
4
|
-
|
|
5
|
-
/** @typedef {import('../types/internal.d.ts').EslintConfig} EslintConfig */
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Extend the flat configs with default files and ignores
|
|
9
|
-
* @param {{
|
|
10
|
-
* readonly filePrefixes: string | string[],
|
|
11
|
-
* readonly ignores?: string[] | undefined
|
|
12
|
-
* }} options
|
|
13
|
-
* @param {EslintConfig} eslintConfig
|
|
14
|
-
* @returns {EslintConfig}
|
|
15
|
-
*/
|
|
16
|
-
export function applyConfig(options, eslintConfig) {
|
|
17
|
-
const filePrefixes = [options.filePrefixes].flat()
|
|
18
|
-
if (filePrefixes.length === 0) {
|
|
19
|
-
throw new TypeError('filePrefixes must not be empty')
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// Do not allow string such as "eslint:recommended" because it cannot be overridden by files/ignores
|
|
23
|
-
for (const config of eslintConfig) {
|
|
24
|
-
if (typeof config === 'string') {
|
|
25
|
-
throw new TypeError(
|
|
26
|
-
`Cannot extend ${config} with files/ignores, use \`@eslint/js\` instead`,
|
|
27
|
-
)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
if (Object.keys(config).includes('ignores')) {
|
|
31
|
-
throw new TypeError('Do not use `ignores` in config')
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
return eslintConfig.map((config) => {
|
|
36
|
-
const files = generateCombinations(filePrefixes, config.files)
|
|
37
|
-
return {
|
|
38
|
-
...config,
|
|
39
|
-
...(files ? { files } : {}),
|
|
40
|
-
...(options.ignores ? { ignores: options.ignores } : {}),
|
|
41
|
-
}
|
|
42
|
-
})
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* @param {string[]} prefixes
|
|
47
|
-
* @param {EslintConfig[number]['files']} originalGlobs
|
|
48
|
-
* @returns {string[] | undefined}
|
|
49
|
-
*/
|
|
50
|
-
function generateCombinations(prefixes, originalGlobs) {
|
|
51
|
-
if (!originalGlobs || originalGlobs.length === 0) {
|
|
52
|
-
return prefixes.map((prefix) => path.join(prefix, supportedFilesGlob))
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const verifiedOriginalGlobs = originalGlobs.filter(
|
|
56
|
-
/** @returns {originalGlob is string} */
|
|
57
|
-
(originalGlob) => typeof originalGlob === 'string',
|
|
58
|
-
)
|
|
59
|
-
if (originalGlobs.length !== verifiedOriginalGlobs.length) {
|
|
60
|
-
throw new TypeError(
|
|
61
|
-
`Do not support using non-string value in files/ignores`,
|
|
62
|
-
)
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
return prefixes.flatMap((prefix) => {
|
|
66
|
-
return verifiedOriginalGlobs.flatMap((originalGlob) => {
|
|
67
|
-
const signRegexp = /^!/u
|
|
68
|
-
const sign = originalGlob.match(signRegexp)?.[0] ?? ''
|
|
69
|
-
return sign + path.join(prefix, originalGlob.replace(signRegexp, ''))
|
|
70
|
-
})
|
|
71
|
-
})
|
|
72
|
-
}
|