@codfish/eslint-config 0.0.0-PR-155--2a9a213 → 0.0.0-PR-132--1df6820
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/README.md +9 -70
- package/dist/utils.d.ts +0 -5
- package/dist/utils.d.ts.map +1 -1
- package/index.js +48 -15
- package/package.json +23 -25
- package/rules/react.js +35 -56
- package/rules/tests.js +2 -6
- package/utils.js +0 -11
- package/dist/rules/typescript.d.ts +0 -38
- package/dist/rules/typescript.d.ts.map +0 -1
- package/dist/tests/integration/eslint-execution.spec.d.ts +0 -2
- package/dist/tests/integration/eslint-execution.spec.d.ts.map +0 -1
- package/dist/tests/integration/react-integration.spec.d.ts +0 -2
- package/dist/tests/integration/react-integration.spec.d.ts.map +0 -1
- package/dist/tests/integration/rule-application.spec.d.ts +0 -2
- package/dist/tests/integration/rule-application.spec.d.ts.map +0 -1
- package/dist/tests/scenarios/edge-cases.spec.d.ts +0 -2
- package/dist/tests/scenarios/edge-cases.spec.d.ts.map +0 -1
- package/dist/tests/unit/config-loading.spec.d.ts +0 -2
- package/dist/tests/unit/config-loading.spec.d.ts.map +0 -1
- package/dist/tests/unit/dynamic-detection.spec.d.ts +0 -2
- package/dist/tests/unit/dynamic-detection.spec.d.ts.map +0 -1
- package/dist/tests/unit/utils.spec.d.ts +0 -2
- package/dist/tests/unit/utils.spec.d.ts.map +0 -1
- package/rules/typescript.js +0 -56
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# @codfish/eslint-config
|
|
2
2
|
|
|
3
3
|
> Modern ESLint configuration with TypeScript, React/Next.js, YAML, Testing Library, and testing framework support using
|
|
4
|
-
> ESLint
|
|
4
|
+
> ESLint v9+ flat config format.
|
|
5
5
|
|
|
6
6
|
[](http://npm.im/@codfish/eslint-config)
|
|
7
7
|
[](http://npm-stat.com/charts.html?package=@codfish/eslint-config&from=2015-08-01)
|
|
@@ -24,10 +24,6 @@
|
|
|
24
24
|
- [Use in combination with prettier-plugin-tailwindcss](#use-in-combination-with-prettier-plugin-tailwindcss)
|
|
25
25
|
- [Example scripts](#example-scripts)
|
|
26
26
|
- [Commitlint Configuration](#commitlint-configuration)
|
|
27
|
-
- [Upgrading to ESLint 10](#upgrading-to-eslint-10)
|
|
28
|
-
- [Breaking Changes in ESLint 10](#breaking-changes-in-eslint-10)
|
|
29
|
-
- [Migration Steps](#migration-steps)
|
|
30
|
-
- [What Changed](#what-changed)
|
|
31
27
|
- [Migration from Legacy Config](#migration-from-legacy-config)
|
|
32
28
|
|
|
33
29
|
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
|
@@ -35,7 +31,7 @@
|
|
|
35
31
|
|
|
36
32
|
## Features
|
|
37
33
|
|
|
38
|
-
- **Modern ESLint
|
|
34
|
+
- **Modern ESLint v9+ flat config**: Uses the new flat configuration format
|
|
39
35
|
- **Dynamic feature detection**: Automatically configures based on your project's dependencies
|
|
40
36
|
- **TypeScript support**: Full TypeScript linting with modern typescript-eslint parser and rules
|
|
41
37
|
- **React ecosystem**: React, React Hooks, and JSX accessibility rules when React is detected
|
|
@@ -53,7 +49,7 @@
|
|
|
53
49
|
Install the package and required peer dependencies:
|
|
54
50
|
|
|
55
51
|
```sh
|
|
56
|
-
npm i -D eslint@
|
|
52
|
+
npm i -D eslint@9 @codfish/eslint-config
|
|
57
53
|
|
|
58
54
|
# Optionally, you can uninstall plugins or presets you don't need to manage anymore,
|
|
59
55
|
# @codfish/eslint-config includes them all.
|
|
@@ -307,10 +303,14 @@ Add these settings to your `.vscode/settings.json` or user settings:
|
|
|
307
303
|
"javascriptreact",
|
|
308
304
|
"typescript",
|
|
309
305
|
"typescriptreact",
|
|
306
|
+
"vue",
|
|
310
307
|
"markdown",
|
|
311
308
|
"json",
|
|
312
309
|
"jsonc",
|
|
310
|
+
"github-actions-workflow",
|
|
313
311
|
"html",
|
|
312
|
+
"mdx",
|
|
313
|
+
"css",
|
|
314
314
|
"yml",
|
|
315
315
|
"yaml"
|
|
316
316
|
]
|
|
@@ -383,7 +383,7 @@ export default {
|
|
|
383
383
|
### Use in combination with prettier-plugin-tailwindcss
|
|
384
384
|
|
|
385
385
|
```sh
|
|
386
|
-
npm i -D eslint@
|
|
386
|
+
npm i -D eslint@9 @codfish/eslint-config prettier-plugin-tailwindcss
|
|
387
387
|
```
|
|
388
388
|
|
|
389
389
|
```js
|
|
@@ -505,72 +505,11 @@ jobs:
|
|
|
505
505
|
--verbose
|
|
506
506
|
```
|
|
507
507
|
|
|
508
|
-
## Upgrading to ESLint 10
|
|
509
|
-
|
|
510
|
-
This package now requires **ESLint 10.0.0 or higher** and **Node.js v20.19.0 or higher**.
|
|
511
|
-
|
|
512
|
-
### Breaking Changes in ESLint 10
|
|
513
|
-
|
|
514
|
-
- **ESLint 10 Required**: Minimum ESLint version is now 10.0.0
|
|
515
|
-
- **Node.js v20.19.0+**: Minimum Node.js version increased from v20.0.0 to v20.19.0
|
|
516
|
-
- **Legacy eslintrc removed**: ESLint 10 completely removes the deprecated eslintrc config system (this package already
|
|
517
|
-
uses flat config)
|
|
518
|
-
- **Improved JSX tracking**: ESLint 10 properly tracks JSX references in scope analysis, which may surface previously
|
|
519
|
-
hidden unused import warnings in React files
|
|
520
|
-
- **New recommended rules**: Three new rules enabled in `eslint:recommended`:
|
|
521
|
-
- `no-unassigned-vars` - Disallow variables that are assigned but never used
|
|
522
|
-
- `no-useless-assignment` - Disallow assignments that don't change the value
|
|
523
|
-
- `preserve-caught-error` - Enforce that caught errors are not reassigned
|
|
524
|
-
|
|
525
|
-
### Migration Steps
|
|
526
|
-
|
|
527
|
-
1. **Update Node.js** (if needed):
|
|
528
|
-
|
|
529
|
-
```sh
|
|
530
|
-
node --version # Ensure you're on v20.19.0+ or v22.13.0+
|
|
531
|
-
```
|
|
532
|
-
|
|
533
|
-
2. **Update ESLint and this config**:
|
|
534
|
-
|
|
535
|
-
```sh
|
|
536
|
-
npm install --save-dev eslint@10 @codfish/eslint-config@latest
|
|
537
|
-
```
|
|
538
|
-
|
|
539
|
-
3. **Install dependencies with legacy peer deps** (required until all plugins update):
|
|
540
|
-
|
|
541
|
-
```sh
|
|
542
|
-
npm install --legacy-peer-deps
|
|
543
|
-
```
|
|
544
|
-
|
|
545
|
-
This is necessary because some ESLint plugins haven't updated their `peerDependencies` to include ESLint 10 yet. The
|
|
546
|
-
plugins still work correctly with ESLint 10.
|
|
547
|
-
|
|
548
|
-
4. **Run linting** and check for new violations:
|
|
549
|
-
|
|
550
|
-
```sh
|
|
551
|
-
npm run lint
|
|
552
|
-
```
|
|
553
|
-
|
|
554
|
-
5. **Review React files** for newly reported unused imports. ESLint 10's improved JSX tracking may flag imports that
|
|
555
|
-
were previously ignored but are actually used in JSX.
|
|
556
|
-
|
|
557
|
-
### What Changed
|
|
558
|
-
|
|
559
|
-
Since this package already uses ESLint's flat config format (the biggest change in ESLint 9), the upgrade to ESLint 10
|
|
560
|
-
is relatively smooth. The main changes are:
|
|
561
|
-
|
|
562
|
-
- ✅ Flat config format (already implemented)
|
|
563
|
-
- ✅ Plugin configurations updated to ESLint 10-compatible versions
|
|
564
|
-
- ✅ All tests passing with ESLint 10
|
|
565
|
-
- ⚠️ Some plugins show peer dependency warnings but work correctly (ecosystem is catching up)
|
|
566
|
-
|
|
567
|
-
For more details, see the [ESLint 10 Migration Guide](https://eslint.org/docs/latest/use/migrate-to-10.0.0).
|
|
568
|
-
|
|
569
508
|
## Migration from Legacy Config
|
|
570
509
|
|
|
571
510
|
If you're upgrading from an older version that used Airbnb presets:
|
|
572
511
|
|
|
573
|
-
1. **Update to ESLint
|
|
512
|
+
1. **Update to ESLint v9+**: `npm install --save-dev eslint@9`
|
|
574
513
|
2. **Switch to flat config**: Replace `.eslintrc.js` with `eslint.config.js`
|
|
575
514
|
3. **Use import syntax**: Change from `require()` to `import` statements
|
|
576
515
|
4. **Remove explicit React config**: React support is now automatically detected
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Get the version of a dependency from the consumer's package.json.
|
|
3
|
-
* Returns the major version as a string (e.g. '18', '19'), or null if not found.
|
|
4
|
-
*/
|
|
5
|
-
export function getDepVersion(dep: any): string | null;
|
|
6
1
|
export function hasLocalConfig(moduleName: any, searchOptions?: {}): boolean;
|
|
7
2
|
export function hasDep(props: any): boolean;
|
|
8
3
|
export function hasDevDep(props: any): boolean;
|
package/dist/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../utils.js"],"names":[],"mappings":"AAyBA
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../utils.js"],"names":[],"mappings":"AAyBA,6EAKC;AAfgC,4CAA+D;AAA/D,+CAA+D;AAA/D,gDAA+D;AAMzF,8CAA8E;AAE9E,yDAAmE"}
|
package/index.js
CHANGED
|
@@ -4,17 +4,18 @@ import markdown from '@eslint/markdown';
|
|
|
4
4
|
import html from '@html-eslint/eslint-plugin';
|
|
5
5
|
import htmlParser from '@html-eslint/parser';
|
|
6
6
|
import { defineConfig } from 'eslint/config';
|
|
7
|
-
import
|
|
7
|
+
import prettierPlugin from 'eslint-plugin-prettier';
|
|
8
8
|
import simpleImportSortPlugin from 'eslint-plugin-simple-import-sort';
|
|
9
9
|
import ymlPlugin from 'eslint-plugin-yml';
|
|
10
10
|
import globals from 'globals';
|
|
11
|
+
import tseslint from 'typescript-eslint';
|
|
11
12
|
|
|
12
13
|
import prettierBuiltInConfig from './prettier.js';
|
|
13
14
|
import configFilesConfig from './rules/config-files.js';
|
|
14
15
|
import reactConfig from './rules/react.js';
|
|
15
16
|
import testConfig from './rules/tests.js';
|
|
16
|
-
import tseslintConfig, { rules as tsRules } from './rules/typescript.js';
|
|
17
17
|
import { hasLocalConfig, ifAnyDep } from './utils.js';
|
|
18
|
+
|
|
18
19
|
const useBuiltinPrettierConfig = !hasLocalConfig('prettier');
|
|
19
20
|
|
|
20
21
|
/**
|
|
@@ -33,7 +34,7 @@ export default defineConfig([
|
|
|
33
34
|
|
|
34
35
|
files: ['**/*.{js,mjs,cjs,jsx,ts,mts,cts,tsx}'],
|
|
35
36
|
|
|
36
|
-
extends: [js.configs.recommended,
|
|
37
|
+
extends: [js.configs.recommended, tseslint.configs.recommended],
|
|
37
38
|
|
|
38
39
|
plugins: {
|
|
39
40
|
'simple-import-sort': simpleImportSortPlugin,
|
|
@@ -42,9 +43,6 @@ export default defineConfig([
|
|
|
42
43
|
languageOptions: {
|
|
43
44
|
ecmaVersion: 'latest',
|
|
44
45
|
sourceType: 'module',
|
|
45
|
-
parserOptions: {
|
|
46
|
-
ecmaFeatures: { jsx: true },
|
|
47
|
-
},
|
|
48
46
|
globals: {
|
|
49
47
|
...globals.browser,
|
|
50
48
|
...globals.node,
|
|
@@ -56,10 +54,8 @@ export default defineConfig([
|
|
|
56
54
|
// Error handling rules to enforce using the Error object
|
|
57
55
|
'no-throw-literal': 'error',
|
|
58
56
|
'prefer-promise-reject-errors': 'error',
|
|
59
|
-
'no-unused-vars': ['error', { ignoreRestSiblings: true }],
|
|
60
|
-
'no-empty-function': 'off',
|
|
61
57
|
|
|
62
|
-
// Asynchronous functions that don
|
|
58
|
+
// Asynchronous functions that don’t use await might not need to be asynchronous functions
|
|
63
59
|
// Usually result of refactoring, leads to misunderstanding/misusage
|
|
64
60
|
'require-await': 'error',
|
|
65
61
|
|
|
@@ -89,6 +85,44 @@ export default defineConfig([
|
|
|
89
85
|
'simple-import-sort/exports': 'error',
|
|
90
86
|
'sort-imports': 'off',
|
|
91
87
|
|
|
88
|
+
// Allows destructuring of rest properties even if they are unused
|
|
89
|
+
'@typescript-eslint/no-unused-vars': ['error', { ignoreRestSiblings: true }],
|
|
90
|
+
'@typescript-eslint/no-empty-function': 'off',
|
|
91
|
+
'@typescript-eslint/naming-convention': [
|
|
92
|
+
'error',
|
|
93
|
+
{
|
|
94
|
+
selector: ['interface', 'typeAlias'],
|
|
95
|
+
format: ['PascalCase'],
|
|
96
|
+
custom: {
|
|
97
|
+
regex: '^I[A-Z]', // prevent prefixing interfaces and type alias declarations with "I"
|
|
98
|
+
match: false,
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
],
|
|
102
|
+
'@typescript-eslint/ban-ts-comment': [
|
|
103
|
+
'error',
|
|
104
|
+
{
|
|
105
|
+
// If you need to use a ts comment, make sure you have a description.
|
|
106
|
+
'ts-ignore': 'allow-with-description',
|
|
107
|
+
'ts-expect-error': 'allow-with-description',
|
|
108
|
+
'ts-nocheck': 'allow-with-description',
|
|
109
|
+
},
|
|
110
|
+
],
|
|
111
|
+
|
|
112
|
+
'@typescript-eslint/no-restricted-types': [
|
|
113
|
+
'error',
|
|
114
|
+
{
|
|
115
|
+
types: {
|
|
116
|
+
'React.FC': {
|
|
117
|
+
message: 'Useless and has some drawbacks, see https://github.com/facebook/create-react-app/pull/8177',
|
|
118
|
+
},
|
|
119
|
+
'React.FunctionComponent': {
|
|
120
|
+
message: 'Useless and has some drawbacks, see https://github.com/facebook/create-react-app/pull/8177',
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
],
|
|
125
|
+
|
|
92
126
|
// 1. Encouraging `lodash-es` imports per file
|
|
93
127
|
// lodash imports should use `lodash-es` package and should be imported per file.
|
|
94
128
|
// E.G: `import get from "lodash-es/get"`
|
|
@@ -136,9 +170,6 @@ export default defineConfig([
|
|
|
136
170
|
],
|
|
137
171
|
},
|
|
138
172
|
],
|
|
139
|
-
|
|
140
|
-
// TypeScript rules (empty object when typescript is not installed)
|
|
141
|
-
...tsRules,
|
|
142
173
|
},
|
|
143
174
|
},
|
|
144
175
|
|
|
@@ -263,7 +294,7 @@ export default defineConfig([
|
|
|
263
294
|
// Allow GitHub-style alerts and checkbox syntax (task lists)
|
|
264
295
|
'markdown/no-missing-label-refs': [
|
|
265
296
|
'error',
|
|
266
|
-
{ allowLabels: ['!NOTE', '!WARNING', '!IMPORTANT', '!TIP', '
|
|
297
|
+
{ allowLabels: ['!NOTE', '!WARNING', '!IMPORTANT', '!TIP', '', 'x', 'X'] },
|
|
267
298
|
],
|
|
268
299
|
},
|
|
269
300
|
},
|
|
@@ -280,9 +311,11 @@ export default defineConfig([
|
|
|
280
311
|
// rule and turning off ESLint rules that might conflict.
|
|
281
312
|
// IMPORTANT: KEEP THIS LAST TO OVERRIDE ESLINT!
|
|
282
313
|
{
|
|
283
|
-
files: ['**/*.{js,ts,jsx,tsx,md,yml,yaml,html,json,jsonc
|
|
314
|
+
files: ['**/*.{js,ts,jsx,tsx,md,yml,yaml,html,json,jsonc}'],
|
|
284
315
|
|
|
285
|
-
|
|
316
|
+
plugins: {
|
|
317
|
+
prettier: prettierPlugin,
|
|
318
|
+
},
|
|
286
319
|
|
|
287
320
|
rules: {
|
|
288
321
|
// Reset prettier rule passing in custom prettier config.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codfish/eslint-config",
|
|
3
|
-
"version": "0.0.0-PR-
|
|
3
|
+
"version": "0.0.0-PR-132--1df6820",
|
|
4
4
|
"description": "Modern ESLint configuration with TypeScript, React, and testing framework support.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"scripts": {
|
|
46
46
|
"build": "tsc --emitDeclarationOnly",
|
|
47
47
|
"dev": "tsc --watch",
|
|
48
|
-
"
|
|
48
|
+
"type-check": "tsc --noEmit",
|
|
49
49
|
"lint": "eslint",
|
|
50
50
|
"format": "eslint --fix",
|
|
51
51
|
"test": "vitest",
|
|
@@ -54,45 +54,43 @@
|
|
|
54
54
|
"prepare": "husky"
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
|
-
"@commitlint/cli": "^20.4.
|
|
58
|
-
"@commitlint/config-conventional": "^20.4.
|
|
59
|
-
"@eslint/js": "^
|
|
60
|
-
"@eslint/json": "^1.0.
|
|
61
|
-
"@eslint/markdown": "^
|
|
62
|
-
"@html-eslint/eslint-plugin": "^0.
|
|
63
|
-
"@html-eslint/parser": "^0.
|
|
57
|
+
"@commitlint/cli": "^20.4.0",
|
|
58
|
+
"@commitlint/config-conventional": "^20.4.0",
|
|
59
|
+
"@eslint/js": "^9.35.0",
|
|
60
|
+
"@eslint/json": "^1.0.0",
|
|
61
|
+
"@eslint/markdown": "^7.5.1",
|
|
62
|
+
"@html-eslint/eslint-plugin": "^0.54.2",
|
|
63
|
+
"@html-eslint/parser": "^0.54.0",
|
|
64
64
|
"@next/eslint-plugin-next": "^16.1.6",
|
|
65
65
|
"@tanstack/eslint-plugin-query": "^5.91.4",
|
|
66
|
-
"@vitest/eslint-plugin": "^1.
|
|
66
|
+
"@vitest/eslint-plugin": "^1.3.10",
|
|
67
67
|
"cosmiconfig": "^9.0.0",
|
|
68
68
|
"eslint-config-prettier": "^10.1.8",
|
|
69
|
-
"eslint-plugin-jest": "^29.
|
|
69
|
+
"eslint-plugin-jest": "^29.0.1",
|
|
70
70
|
"eslint-plugin-jsx-a11y": "^6.10.2",
|
|
71
|
-
"eslint-plugin-prettier": "^5.5.
|
|
71
|
+
"eslint-plugin-prettier": "^5.5.4",
|
|
72
72
|
"eslint-plugin-react": "^7.37.5",
|
|
73
73
|
"eslint-plugin-react-hooks": "^7.0.1",
|
|
74
|
-
"eslint-plugin-react-refresh": "^0.5.
|
|
74
|
+
"eslint-plugin-react-refresh": "^0.5.0",
|
|
75
75
|
"eslint-plugin-simple-import-sort": "^12.1.1",
|
|
76
|
-
"eslint-plugin-testing-library": "^7.
|
|
77
|
-
"eslint-plugin-yml": "^3.
|
|
76
|
+
"eslint-plugin-testing-library": "^7.1.0",
|
|
77
|
+
"eslint-plugin-yml": "^3.0.0",
|
|
78
78
|
"globals": "^17.3.0",
|
|
79
79
|
"lodash.has": "^4.5.2",
|
|
80
80
|
"prettier": ">= 3",
|
|
81
81
|
"read-package-up": "^12.0.0",
|
|
82
|
-
"typescript-eslint": "^8.
|
|
82
|
+
"typescript-eslint": "^8.44.0"
|
|
83
83
|
},
|
|
84
84
|
"devDependencies": {
|
|
85
|
-
"
|
|
86
|
-
"
|
|
87
|
-
"doctoc": "^2.3.0",
|
|
88
|
-
"eslint": "^10.0.2",
|
|
85
|
+
"doctoc": "^2.2.1",
|
|
86
|
+
"eslint": "^9.35.0",
|
|
89
87
|
"husky": "^9.1.7",
|
|
90
|
-
"lint-staged": "^
|
|
91
|
-
"typescript": "^
|
|
88
|
+
"lint-staged": "^16.1.6",
|
|
89
|
+
"typescript": "^5.9.2",
|
|
92
90
|
"vitest": "^4.0.18"
|
|
93
91
|
},
|
|
94
92
|
"engines": {
|
|
95
|
-
"node": ">=20.
|
|
93
|
+
"node": ">=20.0.0"
|
|
96
94
|
},
|
|
97
95
|
"files": [
|
|
98
96
|
"dist",
|
|
@@ -105,7 +103,7 @@
|
|
|
105
103
|
"commitlint.js"
|
|
106
104
|
],
|
|
107
105
|
"peerDependencies": {
|
|
108
|
-
"eslint": ">=
|
|
106
|
+
"eslint": ">= 9",
|
|
109
107
|
"prettier": ">= 3"
|
|
110
108
|
},
|
|
111
109
|
"peerDependenciesMeta": {
|
|
@@ -128,6 +126,6 @@
|
|
|
128
126
|
]
|
|
129
127
|
},
|
|
130
128
|
"volta": {
|
|
131
|
-
"node": "24.
|
|
129
|
+
"node": "24.8.0"
|
|
132
130
|
}
|
|
133
131
|
}
|
package/rules/react.js
CHANGED
|
@@ -7,7 +7,7 @@ import reactHooks from 'eslint-plugin-react-hooks';
|
|
|
7
7
|
import reactRefresh from 'eslint-plugin-react-refresh';
|
|
8
8
|
import globals from 'globals';
|
|
9
9
|
|
|
10
|
-
import {
|
|
10
|
+
import { ifAnyDep } from '../utils.js';
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* React ESLint configuration. Includes React, React Hooks, and JSX accessibility rules.
|
|
@@ -16,71 +16,50 @@ import { getDepVersion, ifAnyDep } from '../utils.js';
|
|
|
16
16
|
* - https://github.com/facebook/react/tree/main/packages/eslint-plugin-react-hooks
|
|
17
17
|
* - https://github.com/jsx-eslint/eslint-plugin-jsx-a11y
|
|
18
18
|
*/
|
|
19
|
-
export default defineConfig(
|
|
20
|
-
|
|
21
|
-
name: 'codfish/react',
|
|
19
|
+
export default defineConfig({
|
|
20
|
+
name: 'codfish/react',
|
|
22
21
|
|
|
23
|
-
|
|
22
|
+
files: ['**/*.jsx', '**/*.tsx', '**/*.mjsx', '**/*.mtsx'],
|
|
24
23
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
24
|
+
extends: [
|
|
25
|
+
react.configs.flat.recommended,
|
|
26
|
+
reactHooks.configs.flat['recommended-latest'],
|
|
27
|
+
reactRefresh.configs.recommended,
|
|
28
|
+
jsxA11y.flatConfigs.recommended,
|
|
29
|
+
ifAnyDep('@tanstack/react-query', tanstackQuery.configs['flat/recommended']),
|
|
30
|
+
ifAnyDep('next', nextPlugin.configs.recommended),
|
|
31
|
+
ifAnyDep('next', nextPlugin.configs['core-web-vitals']),
|
|
32
|
+
].filter(Boolean),
|
|
34
33
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
},
|
|
34
|
+
languageOptions: {
|
|
35
|
+
globals: {
|
|
36
|
+
...globals.serviceworker,
|
|
37
|
+
...globals.browser,
|
|
40
38
|
},
|
|
39
|
+
},
|
|
41
40
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
// Read the major version from the consumer's package.json instead.
|
|
46
|
-
version: getDepVersion('react') || 'detect',
|
|
47
|
-
},
|
|
41
|
+
settings: {
|
|
42
|
+
react: {
|
|
43
|
+
version: 'detect',
|
|
48
44
|
},
|
|
45
|
+
},
|
|
49
46
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
// TypeScript provides type checking, no need for PropTypes
|
|
56
|
-
'react/prop-types': 'off',
|
|
47
|
+
rules: {
|
|
48
|
+
// React 17+ uses automatic JSX runtime, no need to import React
|
|
49
|
+
'react/react-in-jsx-scope': 'off',
|
|
50
|
+
'react/jsx-uses-react': 'off',
|
|
57
51
|
|
|
58
|
-
|
|
59
|
-
|
|
52
|
+
// TypeScript provides type checking, no need for PropTypes
|
|
53
|
+
'react/prop-types': 'off',
|
|
60
54
|
|
|
61
|
-
|
|
62
|
-
|
|
55
|
+
// this rule is too noisey and doesn"t account for certain valid use cases
|
|
56
|
+
'react-hooks/exhaustive-deps': 'off',
|
|
63
57
|
|
|
64
|
-
|
|
58
|
+
// sometimes autoFocus is needed for better UX. @todo - revisit later?
|
|
59
|
+
'jsx-a11y/no-autofocus': 'off',
|
|
65
60
|
|
|
66
|
-
|
|
61
|
+
'react-refresh/only-export-components': ['warn', { allowConstantExport: true }],
|
|
67
62
|
|
|
68
|
-
|
|
69
|
-
'next',
|
|
70
|
-
{
|
|
71
|
-
// annoying cause this is common in Next.js, i.e. generateMetadata()
|
|
72
|
-
'react-refresh/only-export-components': ['off'],
|
|
73
|
-
},
|
|
74
|
-
{},
|
|
75
|
-
),
|
|
76
|
-
},
|
|
77
|
-
},
|
|
78
|
-
|
|
79
|
-
{
|
|
80
|
-
name: 'codfish/react-next-config',
|
|
81
|
-
files: ['next.config.js', 'next.config.ts'],
|
|
82
|
-
rules: {
|
|
83
|
-
'require-await': 'off',
|
|
84
|
-
},
|
|
63
|
+
...ifAnyDep('@tanstack/react-query', { '@tanstack/query/exhaustive-deps': 'error' }, {}),
|
|
85
64
|
},
|
|
86
|
-
|
|
65
|
+
});
|
package/rules/tests.js
CHANGED
|
@@ -30,12 +30,8 @@ export default defineConfig({
|
|
|
30
30
|
extends: [
|
|
31
31
|
ifAnyDep('jest', jest.configs['flat/recommended'], false),
|
|
32
32
|
ifAnyDep('vitest', vitest.configs.recommended, false),
|
|
33
|
-
ifAnyDep('
|
|
34
|
-
ifAnyDep('
|
|
35
|
-
ifAnyDep('@testing-library/vue', testingLibrary.configs['flat/vue'], false),
|
|
36
|
-
ifAnyDep('@testing-library/svelte', testingLibrary.configs['flat/svelte'], false),
|
|
37
|
-
ifAnyDep('@testing-library/angular', testingLibrary.configs['flat/angular'], false),
|
|
38
|
-
ifAnyDep('@testing-library/marko', testingLibrary.configs['flat/marko'], false),
|
|
33
|
+
ifAnyDep('react-testing-library', testingLibrary.configs['flat/react'], false),
|
|
34
|
+
ifAnyDep('vue-testing-library', testingLibrary.configs['flat/vue'], false),
|
|
39
35
|
].filter(Boolean),
|
|
40
36
|
|
|
41
37
|
languageOptions: {
|
package/utils.js
CHANGED
|
@@ -23,17 +23,6 @@ export const hasAnyDep = args => [hasDep, hasDevDep, hasPeerDep].some(fn => fn(a
|
|
|
23
23
|
|
|
24
24
|
export const ifAnyDep = (deps, t, f) => (hasAnyDep([deps].flat()) ? t : f);
|
|
25
25
|
|
|
26
|
-
/**
|
|
27
|
-
* Get the version of a dependency from the consumer's package.json.
|
|
28
|
-
* Returns the major version as a string (e.g. '18', '19'), or null if not found.
|
|
29
|
-
*/
|
|
30
|
-
export function getDepVersion(dep) {
|
|
31
|
-
const spec = pkg?.dependencies?.[dep] || pkg?.devDependencies?.[dep] || pkg?.peerDependencies?.[dep];
|
|
32
|
-
if (!spec) return null;
|
|
33
|
-
const match = spec.match(/\d+/);
|
|
34
|
-
return match ? match[0] : null;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
26
|
export function hasLocalConfig(moduleName, searchOptions = {}) {
|
|
38
27
|
const explorerSync = cosmiconfigSync(moduleName, searchOptions);
|
|
39
28
|
const result = explorerSync.search(pkgPath || './');
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
export default tseslintConfig;
|
|
2
|
-
export const rules: {
|
|
3
|
-
'@typescript-eslint/no-unused-vars': (string | {
|
|
4
|
-
ignoreRestSiblings: boolean;
|
|
5
|
-
})[];
|
|
6
|
-
'@typescript-eslint/no-empty-function': string;
|
|
7
|
-
'@typescript-eslint/naming-convention': (string | {
|
|
8
|
-
selector: string[];
|
|
9
|
-
format: string[];
|
|
10
|
-
custom: {
|
|
11
|
-
regex: string;
|
|
12
|
-
match: boolean;
|
|
13
|
-
};
|
|
14
|
-
})[];
|
|
15
|
-
'@typescript-eslint/ban-ts-comment': (string | {
|
|
16
|
-
'ts-ignore': string;
|
|
17
|
-
'ts-expect-error': string;
|
|
18
|
-
'ts-nocheck': string;
|
|
19
|
-
})[];
|
|
20
|
-
'@typescript-eslint/no-restricted-types': (string | {
|
|
21
|
-
types: {
|
|
22
|
-
'React.FC': {
|
|
23
|
-
message: string;
|
|
24
|
-
};
|
|
25
|
-
'React.FunctionComponent': {
|
|
26
|
-
message: string;
|
|
27
|
-
};
|
|
28
|
-
};
|
|
29
|
-
})[];
|
|
30
|
-
} | {
|
|
31
|
-
'@typescript-eslint/no-unused-vars'?: never;
|
|
32
|
-
'@typescript-eslint/no-empty-function'?: never;
|
|
33
|
-
'@typescript-eslint/naming-convention'?: never;
|
|
34
|
-
'@typescript-eslint/ban-ts-comment'?: never;
|
|
35
|
-
'@typescript-eslint/no-restricted-types'?: never;
|
|
36
|
-
};
|
|
37
|
-
declare const tseslintConfig: import("eslint").Linter.Config[];
|
|
38
|
-
//# sourceMappingURL=typescript.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"typescript.d.ts","sourceRoot":"","sources":["../../rules/typescript.js"],"names":[],"mappings":";AAeA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAwCO;AA9CP,8BACa,OAAO,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,CACsC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"eslint-execution.spec.d.ts","sourceRoot":"","sources":["../../../tests/integration/eslint-execution.spec.js"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"react-integration.spec.d.ts","sourceRoot":"","sources":["../../../tests/integration/react-integration.spec.js"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"rule-application.spec.d.ts","sourceRoot":"","sources":["../../../tests/integration/rule-application.spec.js"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"edge-cases.spec.d.ts","sourceRoot":"","sources":["../../../tests/scenarios/edge-cases.spec.js"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"config-loading.spec.d.ts","sourceRoot":"","sources":["../../../tests/unit/config-loading.spec.js"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dynamic-detection.spec.d.ts","sourceRoot":"","sources":["../../../tests/unit/dynamic-detection.spec.js"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"utils.spec.d.ts","sourceRoot":"","sources":["../../../tests/unit/utils.spec.js"],"names":[],"mappings":""}
|
package/rules/typescript.js
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { hasAnyDep } from '../utils.js';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* TypeScript ESLint configuration. Dynamically loads typescript-eslint
|
|
5
|
-
* only when typescript is installed in the consuming project.
|
|
6
|
-
*
|
|
7
|
-
* - https://typescript-eslint.io/
|
|
8
|
-
*/
|
|
9
|
-
const hasTypeScript = hasAnyDep('typescript');
|
|
10
|
-
const tseslintConfig =
|
|
11
|
-
/** @type {import('eslint').Linter.Config[]} */
|
|
12
|
-
(hasTypeScript ? [(await import('typescript-eslint')).configs.recommended] : []);
|
|
13
|
-
|
|
14
|
-
export default tseslintConfig;
|
|
15
|
-
|
|
16
|
-
export const rules = hasTypeScript
|
|
17
|
-
? {
|
|
18
|
-
// Allows destructuring of rest properties even if they are unused
|
|
19
|
-
'@typescript-eslint/no-unused-vars': ['error', { ignoreRestSiblings: true }],
|
|
20
|
-
'@typescript-eslint/no-empty-function': 'off',
|
|
21
|
-
'@typescript-eslint/naming-convention': [
|
|
22
|
-
'error',
|
|
23
|
-
{
|
|
24
|
-
selector: ['interface', 'typeAlias'],
|
|
25
|
-
format: ['PascalCase'],
|
|
26
|
-
custom: {
|
|
27
|
-
regex: '^I[A-Z]', // prevent prefixing interfaces and type alias declarations with "I"
|
|
28
|
-
match: false,
|
|
29
|
-
},
|
|
30
|
-
},
|
|
31
|
-
],
|
|
32
|
-
'@typescript-eslint/ban-ts-comment': [
|
|
33
|
-
'error',
|
|
34
|
-
{
|
|
35
|
-
// If you need to use a ts comment, make sure you have a description.
|
|
36
|
-
'ts-ignore': 'allow-with-description',
|
|
37
|
-
'ts-expect-error': 'allow-with-description',
|
|
38
|
-
'ts-nocheck': 'allow-with-description',
|
|
39
|
-
},
|
|
40
|
-
],
|
|
41
|
-
|
|
42
|
-
'@typescript-eslint/no-restricted-types': [
|
|
43
|
-
'error',
|
|
44
|
-
{
|
|
45
|
-
types: {
|
|
46
|
-
'React.FC': {
|
|
47
|
-
message: 'Useless and has some drawbacks, see https://github.com/facebook/create-react-app/pull/8177',
|
|
48
|
-
},
|
|
49
|
-
'React.FunctionComponent': {
|
|
50
|
-
message: 'Useless and has some drawbacks, see https://github.com/facebook/create-react-app/pull/8177',
|
|
51
|
-
},
|
|
52
|
-
},
|
|
53
|
-
},
|
|
54
|
-
],
|
|
55
|
-
}
|
|
56
|
-
: {};
|