@activatus/code-standards 2.0.0 → 3.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/README.md +12 -14
- package/docs/Guides/_category_.json +2 -2
- package/docs/Guides/migrating.md +50 -25
- package/docs/Guides/setup.md +52 -17
- package/docs/Standards/_category_.json +2 -2
- package/docs/Standards/agent-skills.md +29 -29
- package/docs/Standards/agent-specs.md +17 -32
- package/docs/Standards/direnv.mdx +8 -8
- package/docs/Standards/documentation.md +5 -2
- package/docs/Standards/editorconfig.md +23 -21
- package/docs/Standards/eslint.md +593 -402
- package/docs/Standards/human-readable-names.md +62 -22
- package/docs/Standards/lint-errors.md +3 -7
- package/docs/Standards/prettier.md +35 -26
- package/docs/Standards/readable-code.md +30 -0
- package/docs/Standards/stylelint.md +26 -11
- package/docs/Standards/styling.md +9 -3
- package/docs/Standards/tech-stack.md +3 -2
- package/docs/Structure/_category_.json +2 -2
- package/docs/Structure/component-organization.md +9 -2
- package/docs/Structure/folder-structure.md +26 -13
- package/docs/Structure/naming-conventions.md +0 -2
- package/docs/intro.md +1 -3
- package/docs/ontology.md +21 -26
- package/docs/templates.mdx +12 -49
- package/docs/version-history.md +143 -10
- package/package.json +6 -2
- package/scripts/renameSymbol.mjs +230 -0
- package/static/templates/.editorconfig +8 -11
- package/static/templates/AGENTS.md +16 -13
- package/static/templates/docs/development/coding-standards.md +4 -0
- package/static/templates/docsSite/docusaurus.config.mjs +144 -0
- package/static/templates/docsSite/sidebars.mjs +7 -0
- package/static/templates/docsSite/src/css/custom.css +6 -0
- package/static/templates/docsSite/tsconfig.json +5 -5
- package/static/templates/eslint/base/eslint.config.mjs +95 -70
- package/static/templates/eslint/nextjs/eslint.config.mjs +170 -126
- package/static/templates/eslint/react/eslint.config.mjs +160 -125
- package/static/templates/eslint/typescript/eslint.config.mjs +143 -115
- package/static/templates/globals.css +9 -9
- package/static/templates/next.config.mjs +13 -10
- package/static/templates/prettier.config.mjs +26 -0
- package/static/templates/stylelint/css/stylelint.config.mjs +37 -25
- package/static/templates/stylelint/scss/stylelint.config.mjs +10 -7
- package/docs/Standards/branch-naming.md +0 -66
- package/docs/Standards/conventional-commits.md +0 -189
- package/static/templates/.commitlintrc.json +0 -3
- package/static/templates/docsSite/docusaurus.config.ts +0 -119
- package/static/templates/docsSite/sidebars.ts +0 -8
- package/static/templates/husky/commit-msg +0 -1
- package/static/templates/husky/pre-commit +0 -1
- package/static/templates/prettier.config.js +0 -17
package/docs/Standards/eslint.md
CHANGED
|
@@ -18,6 +18,22 @@ Each config builds on the one above it — React adds to TypeScript, which adds
|
|
|
18
18
|
|
|
19
19
|
## Installation
|
|
20
20
|
|
|
21
|
+
:::warning[ESLint 10.4 or later]
|
|
22
|
+
|
|
23
|
+
**The config needs ESLint 10.4 or later.** `eslint-plugin-unicorn` 78, which provides the naming rules, requires it. A project on ESLint 9 must upgrade first:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
pnpm add -D eslint@latest @eslint/js@latest
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
:::
|
|
30
|
+
|
|
31
|
+
:::note[eslint-plugin-react on ESLint 10]
|
|
32
|
+
|
|
33
|
+
`eslint-plugin-react` 7.37 officially supports ESLint only up to 9.7, and on ESLint 10 it crashes when it tries to detect the React version by itself. The React and Next.js configs below avoid this by setting the version: `settings: { react: { version: "19.0" } }`. **Keep that setting** and update the number when the project upgrades React. pnpm warns about the unmet peer dependency on install; that warning is expected.
|
|
34
|
+
|
|
35
|
+
:::
|
|
36
|
+
|
|
21
37
|
```bash
|
|
22
38
|
pnpm add -D eslint @eslint/js globals \
|
|
23
39
|
@eslint-community/eslint-plugin-eslint-comments \
|
|
@@ -65,90 +81,101 @@ import unicorn from "eslint-plugin-unicorn";
|
|
|
65
81
|
import globals from "globals";
|
|
66
82
|
|
|
67
83
|
export default [
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
84
|
+
{ ignores: ["dist/", "build/", "coverage/", "**/vendor/**"] },
|
|
85
|
+
js.configs.recommended,
|
|
86
|
+
comments.recommended,
|
|
87
|
+
importX.recommended,
|
|
88
|
+
unicorn.configs.recommended,
|
|
89
|
+
{
|
|
90
|
+
languageOptions: { globals: { ...globals.node } },
|
|
91
|
+
rules: {
|
|
92
|
+
"@eslint-community/eslint-comments/require-description":
|
|
93
|
+
"error",
|
|
94
|
+
"func-style": ["error", "expression"],
|
|
95
|
+
"max-depth": ["error", 3],
|
|
96
|
+
"max-lines": [
|
|
97
|
+
"error",
|
|
98
|
+
{ max: 300, skipBlankLines: true, skipComments: true },
|
|
99
|
+
],
|
|
100
|
+
"no-nested-ternary": "error",
|
|
101
|
+
"no-var": "error",
|
|
102
|
+
"prefer-arrow-callback": "error",
|
|
103
|
+
"prefer-const": "error",
|
|
104
|
+
"no-magic-numbers": [
|
|
105
|
+
"error",
|
|
106
|
+
{
|
|
107
|
+
ignore: [-1, 0, 1],
|
|
108
|
+
ignoreArrayIndexes: true,
|
|
109
|
+
ignoreDefaultValues: true,
|
|
110
|
+
enforceConst: true,
|
|
111
|
+
},
|
|
112
|
+
],
|
|
113
|
+
"no-restricted-syntax": [
|
|
114
|
+
"error",
|
|
115
|
+
{
|
|
116
|
+
selector: "ClassDeclaration",
|
|
117
|
+
message: "Use functions, not classes.",
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
selector: "ClassExpression",
|
|
121
|
+
message: "Use functions, not classes.",
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
selector: "VariableDeclarator > FunctionExpression",
|
|
125
|
+
message: "Use an arrow function.",
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
selector: "VariableDeclaration[kind='let']",
|
|
129
|
+
message:
|
|
130
|
+
"Use const. If this value really must be reassigned, disable this rule on this line with a comment saying why.",
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
selector: "FunctionDeclaration[params.length>1]",
|
|
134
|
+
message:
|
|
135
|
+
"Use a single object parameter when a function needs more than one value.",
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
selector:
|
|
139
|
+
"VariableDeclarator > :matches(ArrowFunctionExpression, FunctionExpression)[params.length>1]",
|
|
140
|
+
message:
|
|
141
|
+
"Use a single object parameter when a function needs more than one value.",
|
|
142
|
+
},
|
|
143
|
+
],
|
|
144
|
+
"import-x/no-cycle": "error",
|
|
145
|
+
"import-x/no-default-export": "error",
|
|
146
|
+
"no-use-before-define": "error",
|
|
147
|
+
"unicorn/default-export-style": "off",
|
|
148
|
+
"unicorn/filename-case": [
|
|
149
|
+
"error",
|
|
150
|
+
{ cases: { camelCase: true, pascalCase: true } },
|
|
151
|
+
],
|
|
152
|
+
"unicorn/name-replacements": [
|
|
153
|
+
"error",
|
|
154
|
+
{
|
|
155
|
+
// Dictionary words: see "Dictionary" in the Human-Readable Names standard.
|
|
156
|
+
replacements: {
|
|
157
|
+
docs: false,
|
|
158
|
+
lib: false,
|
|
159
|
+
props: false,
|
|
160
|
+
ref: false,
|
|
161
|
+
repo: false,
|
|
162
|
+
utils: false,
|
|
163
|
+
},
|
|
164
|
+
// Third-party names, allowed only exactly as they are.
|
|
165
|
+
allowList: { params: true, searchParams: true },
|
|
166
|
+
},
|
|
167
|
+
],
|
|
168
|
+
},
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
files: ["**/*.test.{js,mjs}"],
|
|
172
|
+
rules: { "max-lines": "off", "no-magic-numbers": "off" },
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
files: ["**/*.config.{js,mjs}"],
|
|
176
|
+
rules: { "import-x/no-default-export": "off" },
|
|
177
|
+
},
|
|
178
|
+
prettier,
|
|
152
179
|
];
|
|
153
180
|
```
|
|
154
181
|
|
|
@@ -165,138 +192,149 @@ import globals from "globals";
|
|
|
165
192
|
import { configs as typescript } from "typescript-eslint";
|
|
166
193
|
|
|
167
194
|
export default [
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
195
|
+
{ ignores: ["dist/", "build/", "coverage/", "**/vendor/**"] },
|
|
196
|
+
js.configs.recommended,
|
|
197
|
+
comments.recommended,
|
|
198
|
+
importX.recommended,
|
|
199
|
+
importX.typescript,
|
|
200
|
+
unicorn.configs.recommended,
|
|
201
|
+
...typescript.recommended,
|
|
202
|
+
{
|
|
203
|
+
languageOptions: { globals: { ...globals.node } },
|
|
204
|
+
settings: {
|
|
205
|
+
"import-x/resolver-next": [createTypeScriptImportResolver()],
|
|
206
|
+
},
|
|
207
|
+
rules: {
|
|
208
|
+
"@eslint-community/eslint-comments/require-description":
|
|
209
|
+
"error",
|
|
210
|
+
"func-style": ["error", "expression"],
|
|
211
|
+
"max-depth": ["error", 3],
|
|
212
|
+
"max-lines": [
|
|
213
|
+
"error",
|
|
214
|
+
{ max: 300, skipBlankLines: true, skipComments: true },
|
|
215
|
+
],
|
|
216
|
+
"no-nested-ternary": "error",
|
|
217
|
+
"no-var": "error",
|
|
218
|
+
"prefer-arrow-callback": "error",
|
|
219
|
+
"prefer-const": "error",
|
|
220
|
+
"no-magic-numbers": [
|
|
221
|
+
"error",
|
|
222
|
+
{
|
|
223
|
+
ignore: [-1, 0, 1],
|
|
224
|
+
ignoreArrayIndexes: true,
|
|
225
|
+
ignoreDefaultValues: true,
|
|
226
|
+
enforceConst: true,
|
|
227
|
+
},
|
|
228
|
+
],
|
|
229
|
+
"no-restricted-syntax": [
|
|
230
|
+
"error",
|
|
231
|
+
{
|
|
232
|
+
selector: "ClassDeclaration",
|
|
233
|
+
message: "Use functions, not classes.",
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
selector: "ClassExpression",
|
|
237
|
+
message: "Use functions, not classes.",
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
selector: "VariableDeclarator > FunctionExpression",
|
|
241
|
+
message: "Use an arrow function.",
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
selector: "VariableDeclaration[kind='let']",
|
|
245
|
+
message:
|
|
246
|
+
"Use const. If this value really must be reassigned, disable this rule on this line with a comment saying why.",
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
selector: "FunctionDeclaration[params.length>1]",
|
|
250
|
+
message:
|
|
251
|
+
"Use a single object parameter when a function needs more than one value.",
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
selector:
|
|
255
|
+
"VariableDeclarator > :matches(ArrowFunctionExpression, FunctionExpression)[params.length>1]",
|
|
256
|
+
message:
|
|
257
|
+
"Use a single object parameter when a function needs more than one value.",
|
|
258
|
+
},
|
|
259
|
+
],
|
|
260
|
+
"import-x/no-cycle": "error",
|
|
261
|
+
"import-x/no-default-export": "error",
|
|
262
|
+
"no-use-before-define": "error",
|
|
263
|
+
"unicorn/default-export-style": "off",
|
|
264
|
+
"unicorn/filename-case": [
|
|
265
|
+
"error",
|
|
266
|
+
{ cases: { camelCase: true, pascalCase: true } },
|
|
267
|
+
],
|
|
268
|
+
"unicorn/name-replacements": [
|
|
269
|
+
"error",
|
|
270
|
+
{
|
|
271
|
+
// Dictionary words: see "Dictionary" in the Human-Readable Names standard.
|
|
272
|
+
replacements: {
|
|
273
|
+
docs: false,
|
|
274
|
+
lib: false,
|
|
275
|
+
props: false,
|
|
276
|
+
ref: false,
|
|
277
|
+
repo: false,
|
|
278
|
+
utils: false,
|
|
279
|
+
},
|
|
280
|
+
// Third-party names, allowed only exactly as they are.
|
|
281
|
+
allowList: { params: true, searchParams: true },
|
|
282
|
+
},
|
|
283
|
+
],
|
|
284
|
+
},
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
files: ["**/*.{ts,tsx}"],
|
|
288
|
+
rules: {
|
|
289
|
+
"no-undef": "off",
|
|
290
|
+
"no-magic-numbers": "off",
|
|
291
|
+
"no-use-before-define": "off",
|
|
292
|
+
"@typescript-eslint/consistent-type-assertions": [
|
|
293
|
+
"error",
|
|
294
|
+
{ assertionStyle: "never" },
|
|
295
|
+
],
|
|
296
|
+
"@typescript-eslint/consistent-type-imports": "error",
|
|
297
|
+
"@typescript-eslint/naming-convention": [
|
|
298
|
+
"error",
|
|
299
|
+
{
|
|
300
|
+
selector: ["typeAlias", "interface"],
|
|
301
|
+
format: ["PascalCase"],
|
|
302
|
+
custom: { regex: "(Props|Type)$", match: true },
|
|
303
|
+
},
|
|
304
|
+
],
|
|
305
|
+
"@typescript-eslint/no-explicit-any": "error",
|
|
306
|
+
"@typescript-eslint/no-magic-numbers": [
|
|
307
|
+
"error",
|
|
308
|
+
{
|
|
309
|
+
ignore: [-1, 0, 1],
|
|
310
|
+
ignoreArrayIndexes: true,
|
|
311
|
+
ignoreDefaultValues: true,
|
|
312
|
+
enforceConst: true,
|
|
313
|
+
ignoreEnums: true,
|
|
314
|
+
ignoreNumericLiteralTypes: true,
|
|
315
|
+
},
|
|
316
|
+
],
|
|
317
|
+
"@typescript-eslint/no-non-null-assertion": "error",
|
|
318
|
+
"@typescript-eslint/no-use-before-define": "error",
|
|
319
|
+
},
|
|
320
|
+
},
|
|
321
|
+
{
|
|
322
|
+
files: ["**/*.test.{ts,tsx}"],
|
|
323
|
+
rules: {
|
|
324
|
+
"max-lines": "off",
|
|
325
|
+
"no-magic-numbers": "off",
|
|
326
|
+
"@typescript-eslint/no-magic-numbers": "off",
|
|
327
|
+
},
|
|
328
|
+
},
|
|
329
|
+
{
|
|
330
|
+
files: ["**/*.config.{js,mjs,ts}", "**/*.stories.tsx"],
|
|
331
|
+
rules: { "import-x/no-default-export": "off" },
|
|
332
|
+
},
|
|
333
|
+
{
|
|
334
|
+
files: ["**/*.config.{js,mjs,ts}"],
|
|
335
|
+
rules: { "unicorn/no-top-level-side-effects": "off" },
|
|
336
|
+
},
|
|
337
|
+
prettier,
|
|
300
338
|
];
|
|
301
339
|
```
|
|
302
340
|
|
|
@@ -307,40 +345,178 @@ TypeScript files are checked by the compiler, so `no-undef` is off for them. The
|
|
|
307
345
|
Start from the [TypeScript](#typescript) config and make five changes:
|
|
308
346
|
|
|
309
347
|
```js title="eslint.config.mjs"
|
|
310
|
-
|
|
348
|
+
import js from "@eslint/js";
|
|
349
|
+
import comments from "@eslint-community/eslint-plugin-eslint-comments/configs";
|
|
350
|
+
import prettier from "eslint-config-prettier";
|
|
351
|
+
import { createTypeScriptImportResolver } from "eslint-import-resolver-typescript";
|
|
352
|
+
import { flatConfigs as importX } from "eslint-plugin-import-x";
|
|
311
353
|
import react from "eslint-plugin-react";
|
|
312
354
|
import reactHooks from "eslint-plugin-react-hooks";
|
|
355
|
+
import unicorn from "eslint-plugin-unicorn";
|
|
356
|
+
import globals from "globals";
|
|
357
|
+
import { configs as typescript } from "typescript-eslint";
|
|
313
358
|
|
|
314
359
|
export default [
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
360
|
+
{ ignores: ["dist/", "build/", "coverage/", "**/vendor/**"] },
|
|
361
|
+
js.configs.recommended,
|
|
362
|
+
comments.recommended,
|
|
363
|
+
importX.recommended,
|
|
364
|
+
importX.typescript,
|
|
365
|
+
unicorn.configs.recommended,
|
|
366
|
+
...typescript.recommended,
|
|
367
|
+
react.configs.flat.recommended,
|
|
368
|
+
react.configs.flat["jsx-runtime"],
|
|
369
|
+
reactHooks.configs.flat.recommended,
|
|
370
|
+
{
|
|
371
|
+
languageOptions: {
|
|
372
|
+
globals: { ...globals.browser, ...globals.node },
|
|
373
|
+
},
|
|
374
|
+
settings: {
|
|
375
|
+
// Keep this. eslint-plugin-react crashes on ESLint 10 if it has to detect the version itself.
|
|
376
|
+
// Update the number when the project upgrades React.
|
|
377
|
+
react: { version: "19.0" },
|
|
378
|
+
"import-x/resolver-next": [createTypeScriptImportResolver()],
|
|
379
|
+
},
|
|
380
|
+
rules: {
|
|
381
|
+
"@eslint-community/eslint-comments/require-description":
|
|
382
|
+
"error",
|
|
383
|
+
"func-style": ["error", "expression"],
|
|
384
|
+
"max-depth": ["error", 3],
|
|
385
|
+
"max-lines": [
|
|
386
|
+
"error",
|
|
387
|
+
{ max: 300, skipBlankLines: true, skipComments: true },
|
|
388
|
+
],
|
|
389
|
+
"no-nested-ternary": "error",
|
|
390
|
+
"no-var": "error",
|
|
391
|
+
"prefer-arrow-callback": "error",
|
|
392
|
+
"prefer-const": "error",
|
|
393
|
+
"no-magic-numbers": [
|
|
394
|
+
"error",
|
|
395
|
+
{
|
|
396
|
+
ignore: [-1, 0, 1],
|
|
397
|
+
ignoreArrayIndexes: true,
|
|
398
|
+
ignoreDefaultValues: true,
|
|
399
|
+
enforceConst: true,
|
|
400
|
+
},
|
|
401
|
+
],
|
|
402
|
+
"no-restricted-syntax": [
|
|
403
|
+
"error",
|
|
404
|
+
{
|
|
405
|
+
selector: "ClassDeclaration",
|
|
406
|
+
message: "Use functions, not classes.",
|
|
407
|
+
},
|
|
408
|
+
{
|
|
409
|
+
selector: "ClassExpression",
|
|
410
|
+
message: "Use functions, not classes.",
|
|
411
|
+
},
|
|
412
|
+
{
|
|
413
|
+
selector: "VariableDeclarator > FunctionExpression",
|
|
414
|
+
message: "Use an arrow function.",
|
|
415
|
+
},
|
|
416
|
+
{
|
|
417
|
+
selector: "VariableDeclaration[kind='let']",
|
|
418
|
+
message:
|
|
419
|
+
"Use const. If this value really must be reassigned, disable this rule on this line with a comment saying why.",
|
|
420
|
+
},
|
|
421
|
+
{
|
|
422
|
+
selector: "FunctionDeclaration[params.length>1]",
|
|
423
|
+
message:
|
|
424
|
+
"Use a single object parameter when a function needs more than one value.",
|
|
425
|
+
},
|
|
426
|
+
{
|
|
427
|
+
selector:
|
|
428
|
+
"VariableDeclarator > :matches(ArrowFunctionExpression, FunctionExpression)[params.length>1]",
|
|
429
|
+
message:
|
|
430
|
+
"Use a single object parameter when a function needs more than one value.",
|
|
431
|
+
},
|
|
432
|
+
],
|
|
433
|
+
"import-x/no-cycle": "error",
|
|
434
|
+
"import-x/no-default-export": "error",
|
|
435
|
+
"no-use-before-define": "error",
|
|
436
|
+
"unicorn/default-export-style": "off",
|
|
437
|
+
"unicorn/filename-case": [
|
|
438
|
+
"error",
|
|
439
|
+
{ cases: { camelCase: true, pascalCase: true } },
|
|
440
|
+
],
|
|
441
|
+
"unicorn/name-replacements": [
|
|
442
|
+
"error",
|
|
443
|
+
{
|
|
444
|
+
// Dictionary words: see "Dictionary" in the Human-Readable Names standard.
|
|
445
|
+
replacements: {
|
|
446
|
+
docs: false,
|
|
447
|
+
lib: false,
|
|
448
|
+
props: false,
|
|
449
|
+
ref: false,
|
|
450
|
+
repo: false,
|
|
451
|
+
utils: false,
|
|
452
|
+
},
|
|
453
|
+
// Third-party names, allowed only exactly as they are.
|
|
454
|
+
allowList: { params: true, searchParams: true },
|
|
455
|
+
},
|
|
456
|
+
],
|
|
457
|
+
"react/function-component-definition": [
|
|
458
|
+
"error",
|
|
459
|
+
{
|
|
460
|
+
namedComponents: "arrow-function",
|
|
461
|
+
unnamedComponents: "arrow-function",
|
|
462
|
+
},
|
|
463
|
+
],
|
|
464
|
+
"react/jsx-no-bind": "error",
|
|
465
|
+
"react/no-multi-comp": "error",
|
|
466
|
+
},
|
|
467
|
+
},
|
|
468
|
+
{
|
|
469
|
+
files: ["**/*.{ts,tsx}"],
|
|
470
|
+
rules: {
|
|
471
|
+
"no-undef": "off",
|
|
472
|
+
"no-magic-numbers": "off",
|
|
473
|
+
"no-use-before-define": "off",
|
|
474
|
+
"@typescript-eslint/consistent-type-assertions": [
|
|
475
|
+
"error",
|
|
476
|
+
{ assertionStyle: "never" },
|
|
477
|
+
],
|
|
478
|
+
"@typescript-eslint/consistent-type-imports": "error",
|
|
479
|
+
"@typescript-eslint/naming-convention": [
|
|
480
|
+
"error",
|
|
481
|
+
{
|
|
482
|
+
selector: ["typeAlias", "interface"],
|
|
483
|
+
format: ["PascalCase"],
|
|
484
|
+
custom: { regex: "(Props|Type)$", match: true },
|
|
485
|
+
},
|
|
486
|
+
],
|
|
487
|
+
"@typescript-eslint/no-explicit-any": "error",
|
|
488
|
+
"@typescript-eslint/no-magic-numbers": [
|
|
489
|
+
"error",
|
|
490
|
+
{
|
|
491
|
+
ignore: [-1, 0, 1],
|
|
492
|
+
ignoreArrayIndexes: true,
|
|
493
|
+
ignoreDefaultValues: true,
|
|
494
|
+
enforceConst: true,
|
|
495
|
+
ignoreEnums: true,
|
|
496
|
+
ignoreNumericLiteralTypes: true,
|
|
497
|
+
},
|
|
498
|
+
],
|
|
499
|
+
"@typescript-eslint/no-non-null-assertion": "error",
|
|
500
|
+
"@typescript-eslint/no-use-before-define": "error",
|
|
501
|
+
},
|
|
502
|
+
},
|
|
503
|
+
{
|
|
504
|
+
files: ["**/*.test.{ts,tsx}"],
|
|
505
|
+
rules: {
|
|
506
|
+
"max-lines": "off",
|
|
507
|
+
"no-magic-numbers": "off",
|
|
508
|
+
"@typescript-eslint/no-magic-numbers": "off",
|
|
509
|
+
},
|
|
510
|
+
},
|
|
511
|
+
{
|
|
512
|
+
files: ["**/*.config.{js,mjs,ts}", "**/*.stories.tsx"],
|
|
513
|
+
rules: { "import-x/no-default-export": "off" },
|
|
514
|
+
},
|
|
515
|
+
{
|
|
516
|
+
files: ["**/*.config.{js,mjs,ts}"],
|
|
517
|
+
rules: { "unicorn/no-top-level-side-effects": "off" },
|
|
518
|
+
},
|
|
519
|
+
prettier,
|
|
344
520
|
];
|
|
345
521
|
```
|
|
346
522
|
|
|
@@ -365,161 +541,176 @@ import unicorn from "eslint-plugin-unicorn";
|
|
|
365
541
|
import globals from "globals";
|
|
366
542
|
|
|
367
543
|
export default [
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
544
|
+
{
|
|
545
|
+
ignores: [
|
|
546
|
+
".next/",
|
|
547
|
+
"out/",
|
|
548
|
+
"build/",
|
|
549
|
+
"coverage/",
|
|
550
|
+
"next-env.d.ts",
|
|
551
|
+
"**/vendor/**",
|
|
552
|
+
],
|
|
553
|
+
},
|
|
554
|
+
...nextVitals,
|
|
555
|
+
...nextTypescript,
|
|
556
|
+
comments.recommended,
|
|
557
|
+
importX.recommended,
|
|
558
|
+
importX.typescript,
|
|
559
|
+
unicorn.configs.recommended,
|
|
560
|
+
{
|
|
561
|
+
languageOptions: {
|
|
562
|
+
globals: { ...globals.browser, ...globals.node },
|
|
563
|
+
},
|
|
564
|
+
settings: {
|
|
565
|
+
// Keep this. eslint-plugin-react crashes on ESLint 10 if it has to detect the version itself.
|
|
566
|
+
// Update the number when the project upgrades React.
|
|
567
|
+
react: { version: "19.0" },
|
|
568
|
+
"import-x/resolver-next": [createTypeScriptImportResolver()],
|
|
569
|
+
},
|
|
570
|
+
rules: {
|
|
571
|
+
"@eslint-community/eslint-comments/require-description":
|
|
572
|
+
"error",
|
|
573
|
+
"func-style": ["error", "expression"],
|
|
574
|
+
"max-depth": ["error", 3],
|
|
575
|
+
"max-lines": [
|
|
576
|
+
"error",
|
|
577
|
+
{ max: 300, skipBlankLines: true, skipComments: true },
|
|
578
|
+
],
|
|
579
|
+
"no-nested-ternary": "error",
|
|
580
|
+
"no-var": "error",
|
|
581
|
+
"prefer-arrow-callback": "error",
|
|
582
|
+
"prefer-const": "error",
|
|
583
|
+
"no-magic-numbers": [
|
|
584
|
+
"error",
|
|
585
|
+
{
|
|
586
|
+
ignore: [-1, 0, 1],
|
|
587
|
+
ignoreArrayIndexes: true,
|
|
588
|
+
ignoreDefaultValues: true,
|
|
589
|
+
enforceConst: true,
|
|
590
|
+
},
|
|
591
|
+
],
|
|
592
|
+
"no-restricted-syntax": [
|
|
593
|
+
"error",
|
|
594
|
+
{
|
|
595
|
+
selector: "ClassDeclaration",
|
|
596
|
+
message: "Use functions, not classes.",
|
|
597
|
+
},
|
|
598
|
+
{
|
|
599
|
+
selector: "ClassExpression",
|
|
600
|
+
message: "Use functions, not classes.",
|
|
601
|
+
},
|
|
602
|
+
{
|
|
603
|
+
selector: "VariableDeclarator > FunctionExpression",
|
|
604
|
+
message: "Use an arrow function.",
|
|
605
|
+
},
|
|
606
|
+
{
|
|
607
|
+
selector: "VariableDeclaration[kind='let']",
|
|
608
|
+
message:
|
|
609
|
+
"Use const. If this value really must be reassigned, disable this rule on this line with a comment saying why.",
|
|
610
|
+
},
|
|
611
|
+
{
|
|
612
|
+
selector: "FunctionDeclaration[params.length>1]",
|
|
613
|
+
message:
|
|
614
|
+
"Use a single object parameter when a function needs more than one value.",
|
|
615
|
+
},
|
|
616
|
+
{
|
|
617
|
+
selector:
|
|
618
|
+
"VariableDeclarator > :matches(ArrowFunctionExpression, FunctionExpression)[params.length>1]",
|
|
619
|
+
message:
|
|
620
|
+
"Use a single object parameter when a function needs more than one value.",
|
|
621
|
+
},
|
|
622
|
+
],
|
|
623
|
+
"import-x/no-cycle": "error",
|
|
624
|
+
"import-x/no-default-export": "error",
|
|
625
|
+
"no-use-before-define": "error",
|
|
626
|
+
"unicorn/default-export-style": "off",
|
|
627
|
+
"unicorn/filename-case": [
|
|
628
|
+
"error",
|
|
629
|
+
{ cases: { camelCase: true, pascalCase: true } },
|
|
630
|
+
],
|
|
631
|
+
"unicorn/name-replacements": [
|
|
632
|
+
"error",
|
|
633
|
+
{
|
|
634
|
+
// Dictionary words: see "Dictionary" in the Human-Readable Names standard.
|
|
635
|
+
replacements: {
|
|
636
|
+
docs: false,
|
|
637
|
+
lib: false,
|
|
638
|
+
props: false,
|
|
639
|
+
ref: false,
|
|
640
|
+
repo: false,
|
|
641
|
+
utils: false,
|
|
642
|
+
},
|
|
643
|
+
// Third-party names, allowed only exactly as they are.
|
|
644
|
+
allowList: { params: true, searchParams: true },
|
|
645
|
+
},
|
|
646
|
+
],
|
|
647
|
+
"react/function-component-definition": [
|
|
648
|
+
"error",
|
|
649
|
+
{
|
|
650
|
+
namedComponents: "arrow-function",
|
|
651
|
+
unnamedComponents: "arrow-function",
|
|
652
|
+
},
|
|
653
|
+
],
|
|
654
|
+
"react/jsx-no-bind": "error",
|
|
655
|
+
"react/no-multi-comp": "error",
|
|
656
|
+
},
|
|
657
|
+
},
|
|
658
|
+
{
|
|
659
|
+
files: ["**/*.{ts,tsx}"],
|
|
660
|
+
rules: {
|
|
661
|
+
"no-undef": "off",
|
|
662
|
+
"no-magic-numbers": "off",
|
|
663
|
+
"no-use-before-define": "off",
|
|
664
|
+
"@typescript-eslint/consistent-type-assertions": [
|
|
665
|
+
"error",
|
|
666
|
+
{ assertionStyle: "never" },
|
|
667
|
+
],
|
|
668
|
+
"@typescript-eslint/consistent-type-imports": "error",
|
|
669
|
+
"@typescript-eslint/naming-convention": [
|
|
670
|
+
"error",
|
|
671
|
+
{
|
|
672
|
+
selector: ["typeAlias", "interface"],
|
|
673
|
+
format: ["PascalCase"],
|
|
674
|
+
custom: { regex: "(Props|Type)$", match: true },
|
|
675
|
+
},
|
|
676
|
+
],
|
|
677
|
+
"@typescript-eslint/no-explicit-any": "error",
|
|
678
|
+
"@typescript-eslint/no-magic-numbers": [
|
|
679
|
+
"error",
|
|
680
|
+
{
|
|
681
|
+
ignore: [-1, 0, 1],
|
|
682
|
+
ignoreArrayIndexes: true,
|
|
683
|
+
ignoreDefaultValues: true,
|
|
684
|
+
enforceConst: true,
|
|
685
|
+
ignoreEnums: true,
|
|
686
|
+
ignoreNumericLiteralTypes: true,
|
|
687
|
+
},
|
|
688
|
+
],
|
|
689
|
+
"@typescript-eslint/no-non-null-assertion": "error",
|
|
690
|
+
"@typescript-eslint/no-use-before-define": "error",
|
|
691
|
+
},
|
|
692
|
+
},
|
|
693
|
+
{
|
|
694
|
+
files: ["**/*.test.{ts,tsx}"],
|
|
695
|
+
rules: {
|
|
696
|
+
"max-lines": "off",
|
|
697
|
+
"no-magic-numbers": "off",
|
|
698
|
+
"@typescript-eslint/no-magic-numbers": "off",
|
|
699
|
+
},
|
|
700
|
+
},
|
|
701
|
+
{
|
|
702
|
+
files: [
|
|
703
|
+
"**/*.config.{js,mjs,ts}",
|
|
704
|
+
"**/*.stories.tsx",
|
|
705
|
+
"app/**/{page,layout,template,default,loading,error,global-error,not-found}.tsx",
|
|
706
|
+
],
|
|
707
|
+
rules: { "import-x/no-default-export": "off" },
|
|
708
|
+
},
|
|
709
|
+
{
|
|
710
|
+
files: ["**/*.config.{js,mjs,ts}"],
|
|
711
|
+
rules: { "unicorn/no-top-level-side-effects": "off" },
|
|
712
|
+
},
|
|
713
|
+
prettier,
|
|
523
714
|
];
|
|
524
715
|
```
|
|
525
716
|
|
|
@@ -673,7 +864,7 @@ The plugin's default is kebab-case, which contradicts our [naming conventions](/
|
|
|
673
864
|
|
|
674
865
|
### `unicorn/name-replacements: error`
|
|
675
866
|
|
|
676
|
-
Names are full English words: `btn` must be `button`, `e` must be `error` or `event`, `acc` must be `accumulator`. `docs`, `props` and `utils` are allowed because they are on the [dictionary](/Standards/human-readable-names#dictionary) list. Only three names owned by React and Next.js are allowed exactly as they are — `ref`, `params` and `searchParams` — and our own names built from them are still flagged (`inputRef` must be `inputReference`). See [Human-Readable Names](/Standards/human-readable-names). (Before `eslint-plugin-unicorn` 77 this rule was called `unicorn/prevent-abbreviations`.)
|
|
867
|
+
Names are full English words: `btn` must be `button`, `e` must be `error` or `event`, `acc` must be `accumulator`. `docs`, `lib`, `props`, `ref`, `repo` and `utils` are allowed because they are on the [dictionary](/Standards/human-readable-names#dictionary) list. Only three names owned by React and Next.js are allowed exactly as they are — `ref`, `params` and `searchParams` — and our own names built from them are still flagged (`inputRef` must be `inputReference`). See [Human-Readable Names](/Standards/human-readable-names). (Before `eslint-plugin-unicorn` 77 this rule was called `unicorn/prevent-abbreviations`.)
|
|
677
868
|
|
|
678
869
|
### `@typescript-eslint/no-explicit-any: error`
|
|
679
870
|
|