@fullstacksjs/eslint-config 11.9.0 → 11.10.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/README.md +28 -6
- package/cjs/modules/imports.js +16 -1
- package/cjs/modules/react.js +10 -4
- package/package.json +14 -14
- package/src/modules/imports.mjs +16 -1
- package/src/modules/react.mjs +10 -5
package/README.md
CHANGED
|
@@ -16,9 +16,11 @@
|
|
|
16
16
|
$ npm install --save-dev @fullstacksjs/eslint-config eslint prettier
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
+
⚡️ That's it, you don't need to install any eslint-plugin! If you already have some plugins installed, please remove them.
|
|
20
|
+
|
|
19
21
|
## Usage
|
|
20
22
|
|
|
21
|
-
To use the configuration, all you need is to export the generated config by the `defineConfig` function.
|
|
23
|
+
To use the configuration, all you need is to export the generated config by the `defineConfig` function. It automatically enables required plugins with **Auto Module Detection**.
|
|
22
24
|
|
|
23
25
|
### ESM
|
|
24
26
|
|
|
@@ -36,7 +38,13 @@ const { defineConfig } = require('@fullstacksjs/eslint-config');
|
|
|
36
38
|
module.exports = defineConfig();
|
|
37
39
|
```
|
|
38
40
|
|
|
39
|
-
##
|
|
41
|
+
## How Module Detection Works
|
|
42
|
+
|
|
43
|
+
Automatic module detection enables ESLint plugins based on the dependencies listed in your `package.json`. It scans your project to identify which tools you're using, and then activates the corresponding ESLint plugins accordingly.
|
|
44
|
+
|
|
45
|
+
For example, if your `package.json` includes `vitest` as a dependency, the configuration will automatically enable `eslint-plugin-vitest` for you. (You don't need to install the plugin itself)
|
|
46
|
+
|
|
47
|
+
### Modules API
|
|
40
48
|
|
|
41
49
|
You can fine-tune module detection by overriding it, the `defineConfig` function accepts options as its first argument to control enabled modules.
|
|
42
50
|
|
|
@@ -69,7 +77,7 @@ interface Options {
|
|
|
69
77
|
}
|
|
70
78
|
```
|
|
71
79
|
|
|
72
|
-
##
|
|
80
|
+
## What if I want to add my one rules
|
|
73
81
|
|
|
74
82
|
You can pass any number of arbitrary custom config overrides to `defineConfig` function:
|
|
75
83
|
|
|
@@ -93,11 +101,25 @@ export default defineConfig(
|
|
|
93
101
|
})
|
|
94
102
|
```
|
|
95
103
|
|
|
96
|
-
##
|
|
104
|
+
## What If I Want to Use a Plugin That Isn't Supported?
|
|
105
|
+
|
|
106
|
+
You can still use any ESLint plugin, even if it's not supported by automatic detection. Simply install the plugin manually and add it to the `defineConfig`. There are no limitations.
|
|
107
|
+
|
|
108
|
+
```js
|
|
109
|
+
import { defineConfig } from '@fullstacksjs/eslint-config';
|
|
110
|
+
import pluginVue from 'eslint-plugin-vue';
|
|
111
|
+
|
|
112
|
+
export default defineConfig(
|
|
113
|
+
{ typescript: true },
|
|
114
|
+
...pluginVue.configs['flat/recommended']
|
|
115
|
+
)
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## I'm Getting a Next.js Warning: Plugin Was Not Detected
|
|
97
119
|
|
|
98
|
-
|
|
120
|
+
This configuration includes built-in support for [Next.js](https://nextjs.org). The warning you're seeing from Next.js is misleading—it simply checks whether the plugin is explicitly listed in your package.json.
|
|
99
121
|
|
|
100
|
-
|
|
122
|
+
You can safely ignore this warning. Alternatively, you can update your lint script from next lint to eslint to avoid it entirely.
|
|
101
123
|
|
|
102
124
|
## Speed Optimization!
|
|
103
125
|
|
package/cjs/modules/imports.js
CHANGED
|
@@ -41,7 +41,22 @@ function imports(options = {}) {
|
|
|
41
41
|
},
|
|
42
42
|
rules: {
|
|
43
43
|
'import/consistent-type-specifier-style': ['warn', 'prefer-top-level'],
|
|
44
|
-
|
|
44
|
+
/*
|
|
45
|
+
* FIXME: This rule is broken!
|
|
46
|
+
const opt = options.esm ? 'always' : 'never';
|
|
47
|
+
'import/extensions': [
|
|
48
|
+
'error',
|
|
49
|
+
opt,
|
|
50
|
+
{
|
|
51
|
+
ignorePackages: true,
|
|
52
|
+
js: opt,
|
|
53
|
+
jsx: opt,
|
|
54
|
+
mjs: opt,
|
|
55
|
+
cjs: opt,
|
|
56
|
+
...(options.typescript && { ts: opt, tsx: opt, mts: opt, cts: opt }),
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
*/
|
|
45
60
|
'import/first': 'error',
|
|
46
61
|
'import/newline-after-import': 'warn',
|
|
47
62
|
'import/no-absolute-path': 'error',
|
package/cjs/modules/react.js
CHANGED
|
@@ -24,17 +24,20 @@ function react() {
|
|
|
24
24
|
},
|
|
25
25
|
rules: {
|
|
26
26
|
'@eslint-react/dom/no-children-in-void-dom-elements': 'warn',
|
|
27
|
-
'@eslint-react/dom/no-dangerously-set-innerhtml': 'off',
|
|
28
27
|
'@eslint-react/dom/no-dangerously-set-innerhtml-with-children': 'error',
|
|
28
|
+
'@eslint-react/dom/no-dangerously-set-innerhtml': 'off',
|
|
29
29
|
'@eslint-react/dom/no-find-dom-node': 'error',
|
|
30
|
+
'@eslint-react/dom/no-flush-sync': 'off',
|
|
31
|
+
'@eslint-react/dom/no-hydrate': 'warn',
|
|
30
32
|
'@eslint-react/dom/no-missing-button-type': 'warn',
|
|
31
33
|
'@eslint-react/dom/no-missing-iframe-sandbox': 'warn',
|
|
32
34
|
'@eslint-react/dom/no-namespace': 'error',
|
|
33
35
|
'@eslint-react/dom/no-render-return-value': 'error',
|
|
36
|
+
'@eslint-react/dom/no-render': 'warn',
|
|
34
37
|
'@eslint-react/dom/no-script-url': 'warn',
|
|
35
38
|
'@eslint-react/dom/no-unsafe-iframe-sandbox': 'warn',
|
|
36
39
|
'@eslint-react/dom/no-unsafe-target-blank': 'warn',
|
|
37
|
-
'@eslint-react/ensure-forward-ref-using-ref': '
|
|
40
|
+
'@eslint-react/ensure-forward-ref-using-ref': 'off',
|
|
38
41
|
'@eslint-react/no-access-state-in-setstate': 'error',
|
|
39
42
|
'@eslint-react/no-array-index-key': 'warn',
|
|
40
43
|
'@eslint-react/no-children-count': 'warn',
|
|
@@ -52,8 +55,9 @@ function react() {
|
|
|
52
55
|
'@eslint-react/no-direct-mutation-state': 'error',
|
|
53
56
|
'@eslint-react/no-duplicate-key': 'error',
|
|
54
57
|
'@eslint-react/no-implicit-key': 'error',
|
|
58
|
+
'@eslint-react/no-missing-context-display-name': 'off',
|
|
55
59
|
'@eslint-react/no-missing-key': 'error',
|
|
56
|
-
'@eslint-react/no-nested-
|
|
60
|
+
'@eslint-react/no-nested-component-definitions': 'warn',
|
|
57
61
|
'@eslint-react/no-redundant-should-component-update': 'error',
|
|
58
62
|
'@eslint-react/no-set-state-in-component-did-mount': 'warn',
|
|
59
63
|
'@eslint-react/no-set-state-in-component-did-update': 'warn',
|
|
@@ -66,6 +70,7 @@ function react() {
|
|
|
66
70
|
'@eslint-react/no-unstable-default-props': 'error',
|
|
67
71
|
'@eslint-react/no-unused-class-component-members': 'warn',
|
|
68
72
|
'@eslint-react/no-unused-state': 'warn',
|
|
73
|
+
'@eslint-react/no-useless-forward-ref': 'warn',
|
|
69
74
|
'@eslint-react/no-useless-fragment': 'warn',
|
|
70
75
|
'@eslint-react/prefer-destructuring-assignment': 'warn',
|
|
71
76
|
'@eslint-react/prefer-shorthand-boolean': 'warn',
|
|
@@ -75,11 +80,12 @@ function react() {
|
|
|
75
80
|
'@eslint-react/hooks-extra/prefer-use-state-lazy-initialization': 'warn',
|
|
76
81
|
'@eslint-react/hooks-extra/no-useless-custom-hooks': 'warn',
|
|
77
82
|
'@eslint-react/naming-convention/component-name': 'warn',
|
|
78
|
-
'@eslint-react/naming-convention/
|
|
83
|
+
'@eslint-react/naming-convention/context-name': 'warn',
|
|
79
84
|
'@eslint-react/naming-convention/filename-extension': ['error', {
|
|
80
85
|
allow: 'always',
|
|
81
86
|
extensions: ['.jsx', '.tsx']
|
|
82
87
|
}],
|
|
88
|
+
'@eslint-react/naming-convention/filename': 'off',
|
|
83
89
|
'@eslint-react/naming-convention/use-state': 'off',
|
|
84
90
|
'react-hooks/exhaustive-deps': 'warn',
|
|
85
91
|
'react-hooks/rules-of-hooks': 'error',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fullstacksjs/eslint-config",
|
|
3
|
-
"version": "11.
|
|
3
|
+
"version": "11.10.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "fullstacks <fullstacksjs@gmail.com>",
|
|
6
6
|
"description": "fullstacks eslint config",
|
|
@@ -34,22 +34,22 @@
|
|
|
34
34
|
}
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@eslint-react/eslint-plugin": "1.
|
|
38
|
-
"@next/eslint-plugin-next": "15.
|
|
39
|
-
"@stylistic/eslint-plugin": "4.
|
|
37
|
+
"@eslint-react/eslint-plugin": "1.37.3",
|
|
38
|
+
"@next/eslint-plugin-next": "15.2.3",
|
|
39
|
+
"@stylistic/eslint-plugin": "4.2.0",
|
|
40
40
|
"deepmerge": "4.3.1",
|
|
41
|
-
"eslint-plugin-cypress": "4.
|
|
42
|
-
"eslint-plugin-import-x": "4.
|
|
41
|
+
"eslint-plugin-cypress": "4.2.0",
|
|
42
|
+
"eslint-plugin-import-x": "4.9.1",
|
|
43
43
|
"eslint-plugin-jest": "28.11.0",
|
|
44
44
|
"eslint-plugin-jest-formatting": "3.1.0",
|
|
45
45
|
"eslint-plugin-jsx-a11y": "6.10.2",
|
|
46
|
-
"eslint-plugin-n": "17.
|
|
47
|
-
"eslint-plugin-perfectionist": "4.
|
|
46
|
+
"eslint-plugin-n": "17.16.2",
|
|
47
|
+
"eslint-plugin-perfectionist": "4.10.1",
|
|
48
48
|
"eslint-plugin-playwright": "2.2.0",
|
|
49
49
|
"eslint-plugin-prettier": "5.2.3",
|
|
50
50
|
"eslint-plugin-promise": "7.2.1",
|
|
51
|
-
"eslint-plugin-react-hooks": "5.
|
|
52
|
-
"eslint-plugin-storybook": "0.11.
|
|
51
|
+
"eslint-plugin-react-hooks": "5.2.0",
|
|
52
|
+
"eslint-plugin-storybook": "0.11.6",
|
|
53
53
|
"eslint-plugin-tailwindcss": "3.18.0",
|
|
54
54
|
"eslint-plugin-vitest": "0.5.4",
|
|
55
55
|
"globals": "16.0.0",
|
|
@@ -57,14 +57,14 @@
|
|
|
57
57
|
"typescript-eslint": "8.27.0"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
|
-
"@eslint/eslintrc": "3.3.
|
|
61
|
-
"@eslint/js": "9.
|
|
60
|
+
"@eslint/eslintrc": "3.3.1",
|
|
61
|
+
"@eslint/js": "9.23.0",
|
|
62
62
|
"@semantic-release/github": "11.0.1",
|
|
63
63
|
"@semantic-release/npm": "12.0.1",
|
|
64
64
|
"@semantic-release/release-notes-generator": "14.0.3",
|
|
65
65
|
"@types/eslint": "9.6.1",
|
|
66
66
|
"cspell": "8.17.5",
|
|
67
|
-
"eslint": "9.
|
|
67
|
+
"eslint": "9.23.0",
|
|
68
68
|
"husky": "9.1.7",
|
|
69
69
|
"jest": "29.7.0",
|
|
70
70
|
"lint-staged": "15.5.0",
|
|
@@ -77,7 +77,7 @@
|
|
|
77
77
|
},
|
|
78
78
|
"peerDependencies": {
|
|
79
79
|
"cypress": ">=8",
|
|
80
|
-
"eslint": "
|
|
80
|
+
"eslint": ">=9.22",
|
|
81
81
|
"prettier": "3",
|
|
82
82
|
"react": ">=16",
|
|
83
83
|
"typescript": ">=4.7"
|
package/src/modules/imports.mjs
CHANGED
|
@@ -32,7 +32,22 @@ function imports(options = {}) {
|
|
|
32
32
|
|
|
33
33
|
rules: {
|
|
34
34
|
'import/consistent-type-specifier-style': ['warn', 'prefer-top-level'],
|
|
35
|
-
|
|
35
|
+
/*
|
|
36
|
+
* FIXME: This rule is broken!
|
|
37
|
+
const opt = options.esm ? 'always' : 'never';
|
|
38
|
+
'import/extensions': [
|
|
39
|
+
'error',
|
|
40
|
+
opt,
|
|
41
|
+
{
|
|
42
|
+
ignorePackages: true,
|
|
43
|
+
js: opt,
|
|
44
|
+
jsx: opt,
|
|
45
|
+
mjs: opt,
|
|
46
|
+
cjs: opt,
|
|
47
|
+
...(options.typescript && { ts: opt, tsx: opt, mts: opt, cts: opt }),
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
*/
|
|
36
51
|
'import/first': 'error',
|
|
37
52
|
'import/newline-after-import': 'warn',
|
|
38
53
|
'import/no-absolute-path': 'error',
|
package/src/modules/react.mjs
CHANGED
|
@@ -18,18 +18,20 @@ function react() {
|
|
|
18
18
|
},
|
|
19
19
|
rules: {
|
|
20
20
|
'@eslint-react/dom/no-children-in-void-dom-elements': 'warn',
|
|
21
|
-
'@eslint-react/dom/no-dangerously-set-innerhtml': 'off',
|
|
22
21
|
'@eslint-react/dom/no-dangerously-set-innerhtml-with-children': 'error',
|
|
22
|
+
'@eslint-react/dom/no-dangerously-set-innerhtml': 'off',
|
|
23
23
|
'@eslint-react/dom/no-find-dom-node': 'error',
|
|
24
|
+
'@eslint-react/dom/no-flush-sync': 'off',
|
|
25
|
+
'@eslint-react/dom/no-hydrate': 'warn',
|
|
24
26
|
'@eslint-react/dom/no-missing-button-type': 'warn',
|
|
25
27
|
'@eslint-react/dom/no-missing-iframe-sandbox': 'warn',
|
|
26
28
|
'@eslint-react/dom/no-namespace': 'error',
|
|
27
29
|
'@eslint-react/dom/no-render-return-value': 'error',
|
|
30
|
+
'@eslint-react/dom/no-render': 'warn',
|
|
28
31
|
'@eslint-react/dom/no-script-url': 'warn',
|
|
29
32
|
'@eslint-react/dom/no-unsafe-iframe-sandbox': 'warn',
|
|
30
33
|
'@eslint-react/dom/no-unsafe-target-blank': 'warn',
|
|
31
|
-
|
|
32
|
-
'@eslint-react/ensure-forward-ref-using-ref': 'warn',
|
|
34
|
+
'@eslint-react/ensure-forward-ref-using-ref': 'off',
|
|
33
35
|
'@eslint-react/no-access-state-in-setstate': 'error',
|
|
34
36
|
'@eslint-react/no-array-index-key': 'warn',
|
|
35
37
|
'@eslint-react/no-children-count': 'warn',
|
|
@@ -47,8 +49,9 @@ function react() {
|
|
|
47
49
|
'@eslint-react/no-direct-mutation-state': 'error',
|
|
48
50
|
'@eslint-react/no-duplicate-key': 'error',
|
|
49
51
|
'@eslint-react/no-implicit-key': 'error',
|
|
52
|
+
'@eslint-react/no-missing-context-display-name': 'off',
|
|
50
53
|
'@eslint-react/no-missing-key': 'error',
|
|
51
|
-
'@eslint-react/no-nested-
|
|
54
|
+
'@eslint-react/no-nested-component-definitions': 'warn',
|
|
52
55
|
'@eslint-react/no-redundant-should-component-update': 'error',
|
|
53
56
|
'@eslint-react/no-set-state-in-component-did-mount': 'warn',
|
|
54
57
|
'@eslint-react/no-set-state-in-component-did-update': 'warn',
|
|
@@ -61,6 +64,7 @@ function react() {
|
|
|
61
64
|
'@eslint-react/no-unstable-default-props': 'error',
|
|
62
65
|
'@eslint-react/no-unused-class-component-members': 'warn',
|
|
63
66
|
'@eslint-react/no-unused-state': 'warn',
|
|
67
|
+
'@eslint-react/no-useless-forward-ref': 'warn',
|
|
64
68
|
'@eslint-react/no-useless-fragment': 'warn',
|
|
65
69
|
'@eslint-react/prefer-destructuring-assignment': 'warn',
|
|
66
70
|
'@eslint-react/prefer-shorthand-boolean': 'warn',
|
|
@@ -72,8 +76,9 @@ function react() {
|
|
|
72
76
|
'@eslint-react/hooks-extra/no-useless-custom-hooks': 'warn',
|
|
73
77
|
|
|
74
78
|
'@eslint-react/naming-convention/component-name': 'warn',
|
|
75
|
-
'@eslint-react/naming-convention/
|
|
79
|
+
'@eslint-react/naming-convention/context-name': 'warn',
|
|
76
80
|
'@eslint-react/naming-convention/filename-extension': ['error', { allow: 'always', extensions: ['.jsx', '.tsx'] }],
|
|
81
|
+
'@eslint-react/naming-convention/filename': 'off',
|
|
77
82
|
'@eslint-react/naming-convention/use-state': 'off',
|
|
78
83
|
|
|
79
84
|
'react-hooks/exhaustive-deps': 'warn',
|