@lzear/eslint-config 3.0.1 → 4.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/dist/index.d.ts +8 -14
- package/dist/index.js +609 -0
- package/package.json +56 -42
- package/dist/configs/a11y/index.cjs +0 -54
- package/dist/configs/a11y/index.mjs +0 -54
- package/dist/configs/core/index.cjs +0 -88
- package/dist/configs/core/index.mjs +0 -88
- package/dist/configs/node/index.cjs +0 -49
- package/dist/configs/node/index.mjs +0 -31
- package/dist/configs/package-json/index.cjs +0 -33
- package/dist/configs/package-json/index.mjs +0 -16
- package/dist/configs/perfectionist/index.cjs +0 -73
- package/dist/configs/perfectionist/index.mjs +0 -55
- package/dist/configs/react/index.cjs +0 -73
- package/dist/configs/react/index.mjs +0 -55
- package/dist/configs/src/files.cjs +0 -24
- package/dist/configs/src/files.mjs +0 -24
- package/dist/configs/typescript/index.cjs +0 -53
- package/dist/configs/typescript/index.mjs +0 -35
- package/dist/configs/vitest/index.cjs +0 -65
- package/dist/configs/vitest/index.mjs +0 -47
- package/dist/index.cjs +0 -59
- package/dist/index.mjs +0 -59
- package/dist/utils.cjs +0 -21
- package/dist/utils.mjs +0 -21
- package/license.md +0 -20
- package/readme.md +0 -44
package/dist/index.d.ts
CHANGED
|
@@ -1,17 +1,11 @@
|
|
|
1
1
|
import { Linter } from 'eslint';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
type RawConfigOptions = {
|
|
7
|
-
extends?: Linter.Config[] | Linter.Config;
|
|
8
|
-
} & Partial<ConfigOptionFlags>;
|
|
9
|
-
declare const configGenerator: ({ extends: customExtends, ...rawConfig }?: RawConfigOptions) => Promise<Linter.Config[]>;
|
|
10
|
-
export default configGenerator;
|
|
11
|
-
export declare const defaultOptions: {
|
|
12
|
-
perfectionist: boolean;
|
|
2
|
+
|
|
3
|
+
interface ConfigOptions {
|
|
4
|
+
node: boolean;
|
|
5
|
+
react: boolean;
|
|
13
6
|
typescript: boolean;
|
|
14
7
|
vitest: boolean;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
8
|
+
}
|
|
9
|
+
declare const configGenerator: (options?: Partial<ConfigOptions>) => Promise<Linter.Config[]>;
|
|
10
|
+
|
|
11
|
+
export { type ConfigOptions, configGenerator as default };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,609 @@
|
|
|
1
|
+
// configs/a11y.ts
|
|
2
|
+
import jsxA11y from "eslint-plugin-jsx-a11y";
|
|
3
|
+
var a11y = (config) => {
|
|
4
|
+
if (!config.react) {
|
|
5
|
+
return {};
|
|
6
|
+
}
|
|
7
|
+
const files = ["**/*.jsx"];
|
|
8
|
+
if (config.typescript) {
|
|
9
|
+
files.push("**/*.tsx");
|
|
10
|
+
}
|
|
11
|
+
return {
|
|
12
|
+
name: "lzear/a11y",
|
|
13
|
+
files,
|
|
14
|
+
plugins: {
|
|
15
|
+
"jsx-a11y": jsxA11y
|
|
16
|
+
},
|
|
17
|
+
rules: {
|
|
18
|
+
...jsxA11y.flatConfigs.recommended.rules
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
// configs/core.ts
|
|
24
|
+
import js from "@eslint/js";
|
|
25
|
+
import eslintCommentsPlugin from "@eslint-community/eslint-plugin-eslint-comments";
|
|
26
|
+
import deMorganPlugin from "eslint-plugin-de-morgan";
|
|
27
|
+
import importXPlugin from "eslint-plugin-import-x";
|
|
28
|
+
import preferArrowPlugin from "eslint-plugin-prefer-arrow";
|
|
29
|
+
import promisePlugin from "eslint-plugin-promise";
|
|
30
|
+
import regexpPlugin from "eslint-plugin-regexp";
|
|
31
|
+
import sonarjsPlugin from "eslint-plugin-sonarjs";
|
|
32
|
+
import unicornPlugin from "eslint-plugin-unicorn";
|
|
33
|
+
import globals from "globals";
|
|
34
|
+
|
|
35
|
+
// plugin/rules/major-version-only.ts
|
|
36
|
+
var DEP_FIELDS = /* @__PURE__ */ new Set([
|
|
37
|
+
"dependencies",
|
|
38
|
+
"devDependencies",
|
|
39
|
+
"optionalDependencies",
|
|
40
|
+
"peerDependencies"
|
|
41
|
+
]);
|
|
42
|
+
var VERSION_RE = /^([~^])(\d+)\.(\d+)(?:\.\d+)?$/;
|
|
43
|
+
var simplify = (version) => {
|
|
44
|
+
const match = VERSION_RE.exec(version);
|
|
45
|
+
if (!match) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
const [, operator, major, minor] = match;
|
|
49
|
+
if (major === "0" && operator === "^") {
|
|
50
|
+
const target2 = `^0.${minor}`;
|
|
51
|
+
return target2 === version ? null : target2;
|
|
52
|
+
}
|
|
53
|
+
const target = `${operator}${major}`;
|
|
54
|
+
return target === version ? null : target;
|
|
55
|
+
};
|
|
56
|
+
var isIgnored = (pkgName, ignore) => ignore.some(
|
|
57
|
+
(pattern) => pattern instanceof RegExp ? pattern.test(pkgName) : pattern === pkgName
|
|
58
|
+
);
|
|
59
|
+
var majorVersionOnly = {
|
|
60
|
+
meta: {
|
|
61
|
+
type: "suggestion",
|
|
62
|
+
docs: {
|
|
63
|
+
description: "Enforce major-only version specifiers in package.json"
|
|
64
|
+
},
|
|
65
|
+
fixable: "code",
|
|
66
|
+
schema: [
|
|
67
|
+
{
|
|
68
|
+
type: "object",
|
|
69
|
+
properties: {
|
|
70
|
+
ignore: {
|
|
71
|
+
type: "array",
|
|
72
|
+
items: {
|
|
73
|
+
oneOf: [
|
|
74
|
+
{ type: "string" },
|
|
75
|
+
{
|
|
76
|
+
type: "object",
|
|
77
|
+
properties: { regex: { type: "string" } },
|
|
78
|
+
required: ["regex"],
|
|
79
|
+
additionalProperties: false
|
|
80
|
+
}
|
|
81
|
+
]
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
additionalProperties: false
|
|
86
|
+
}
|
|
87
|
+
],
|
|
88
|
+
messages: {
|
|
89
|
+
useMajorOnly: 'Use "{{suggested}}" instead of "{{current}}"'
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
create: (context) => {
|
|
93
|
+
const opts = context.options[0];
|
|
94
|
+
const ignore = (opts?.ignore ?? []).map(
|
|
95
|
+
(item) => typeof item === "string" ? item : new RegExp(item.regex)
|
|
96
|
+
);
|
|
97
|
+
return {
|
|
98
|
+
JSONProperty: (rawNode) => {
|
|
99
|
+
const node2 = rawNode;
|
|
100
|
+
const keyName = node2.key.type === "JSONLiteral" ? String(node2.key.value) : node2.key.name ?? "";
|
|
101
|
+
if (!DEP_FIELDS.has(keyName)) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
const depsNode = node2.value;
|
|
105
|
+
if (depsNode.type !== "JSONObjectExpression") {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
for (const prop of depsNode.properties) {
|
|
109
|
+
const pkgName = prop.key.type === "JSONLiteral" ? String(prop.key.value) : prop.key.name ?? "";
|
|
110
|
+
if (isIgnored(pkgName, ignore)) {
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
const versionNode = prop.value;
|
|
114
|
+
if (versionNode.type !== "JSONLiteral") {
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
const version = versionNode.value;
|
|
118
|
+
if (typeof version !== "string") {
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
const suggested = simplify(version);
|
|
122
|
+
if (!suggested) {
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
context.report({
|
|
126
|
+
node: versionNode,
|
|
127
|
+
messageId: "useMajorOnly",
|
|
128
|
+
data: { current: version, suggested },
|
|
129
|
+
fix: (fixer) => fixer.replaceText(versionNode, JSON.stringify(suggested))
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
// plugin/rules/prefer-relative-imports.ts
|
|
138
|
+
import path from "path";
|
|
139
|
+
|
|
140
|
+
// utils.ts
|
|
141
|
+
var interopDefault = async (m) => {
|
|
142
|
+
const resolved = await m;
|
|
143
|
+
const mod = resolved.default ?? resolved;
|
|
144
|
+
if (mod.__esModule) {
|
|
145
|
+
const inner = mod.default;
|
|
146
|
+
if (inner !== void 0) return inner;
|
|
147
|
+
}
|
|
148
|
+
return mod;
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
// plugin/rules/prefer-relative-imports.ts
|
|
152
|
+
var moduleVisitor = await interopDefault(
|
|
153
|
+
import("eslint-module-utils/moduleVisitor")
|
|
154
|
+
);
|
|
155
|
+
var resolve = await interopDefault(import("eslint-module-utils/resolve"));
|
|
156
|
+
var toRelative = (from, importPath, context) => {
|
|
157
|
+
const resolved = resolve(importPath, context);
|
|
158
|
+
if (!resolved) {
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
let rel = path.relative(path.dirname(from), resolved);
|
|
162
|
+
if (!rel) {
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
if (!rel.startsWith(".")) {
|
|
166
|
+
rel = `./${rel}`;
|
|
167
|
+
}
|
|
168
|
+
if (!path.extname(importPath)) {
|
|
169
|
+
const ext = path.extname(rel);
|
|
170
|
+
if (ext) {
|
|
171
|
+
const withoutExt = rel.slice(0, -ext.length);
|
|
172
|
+
rel = withoutExt.endsWith("/index") ? withoutExt.slice(0, -"/index".length) || "." : withoutExt;
|
|
173
|
+
if (!rel.startsWith(".")) {
|
|
174
|
+
rel = `./${rel}`;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return rel;
|
|
179
|
+
};
|
|
180
|
+
var countParentPrefixes = (p) => {
|
|
181
|
+
const match = /^(?:\.\.\/)+/.exec(p);
|
|
182
|
+
return match ? match[0].length / 3 : 0;
|
|
183
|
+
};
|
|
184
|
+
var preferRelativeImports = {
|
|
185
|
+
meta: {
|
|
186
|
+
type: "suggestion",
|
|
187
|
+
docs: { description: "Prefer relative imports when a shorter path exists" },
|
|
188
|
+
fixable: "code",
|
|
189
|
+
schema: [
|
|
190
|
+
{
|
|
191
|
+
type: "object",
|
|
192
|
+
properties: { maxParentPrefixes: { type: "number", minimum: 0 } },
|
|
193
|
+
additionalProperties: false
|
|
194
|
+
}
|
|
195
|
+
],
|
|
196
|
+
messages: {
|
|
197
|
+
preferRelative: 'Use relative import "{{relative}}" instead of "{{original}}"'
|
|
198
|
+
}
|
|
199
|
+
},
|
|
200
|
+
create: (context) => {
|
|
201
|
+
const opts = context.options[0];
|
|
202
|
+
const maxParentPrefixes = opts?.maxParentPrefixes ?? 1;
|
|
203
|
+
const filename = context.physicalFilename ?? context.filename;
|
|
204
|
+
const check = (source) => {
|
|
205
|
+
const importPath = source.value;
|
|
206
|
+
if (typeof importPath !== "string" || importPath.startsWith(".")) {
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
const relative = toRelative(filename, importPath, context);
|
|
210
|
+
if (!relative || relative.length >= importPath.length) {
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
if (countParentPrefixes(relative) > maxParentPrefixes) {
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
context.report({
|
|
217
|
+
node: source,
|
|
218
|
+
messageId: "preferRelative",
|
|
219
|
+
data: { relative, original: importPath },
|
|
220
|
+
fix: (fixer) => fixer.replaceText(source, JSON.stringify(relative))
|
|
221
|
+
});
|
|
222
|
+
};
|
|
223
|
+
return moduleVisitor(check, { commonjs: false });
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
// plugin/index.ts
|
|
228
|
+
var plugin = {
|
|
229
|
+
meta: {
|
|
230
|
+
name: "lzear",
|
|
231
|
+
version: "1.0.0"
|
|
232
|
+
},
|
|
233
|
+
rules: {
|
|
234
|
+
"major-version-only": majorVersionOnly,
|
|
235
|
+
"prefer-relative-imports": preferRelativeImports
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
// configs/core.ts
|
|
240
|
+
var core = () => {
|
|
241
|
+
const files = [
|
|
242
|
+
"**/*.js",
|
|
243
|
+
"**/*.cjs",
|
|
244
|
+
"**/*.mjs",
|
|
245
|
+
"**/*.ts",
|
|
246
|
+
"**/*.cts",
|
|
247
|
+
"**/*.mts",
|
|
248
|
+
"**/*.jsx",
|
|
249
|
+
"**/*.tsx"
|
|
250
|
+
];
|
|
251
|
+
const sonarRules = (sonarjsPlugin.configs?.recommended).rules;
|
|
252
|
+
const rules = {
|
|
253
|
+
...js.configs.recommended.rules,
|
|
254
|
+
...eslintCommentsPlugin.configs.recommended.rules,
|
|
255
|
+
"@eslint-community/eslint-comments/disable-enable-pair": 0,
|
|
256
|
+
"@eslint-community/eslint-comments/no-unlimited-disable": 0,
|
|
257
|
+
...deMorganPlugin.configs.recommended.rules,
|
|
258
|
+
...importXPlugin.configs.recommended.rules,
|
|
259
|
+
"import-x/no-named-as-default-member": 0,
|
|
260
|
+
"import-x/no-unresolved": 0,
|
|
261
|
+
"import-x/order": [
|
|
262
|
+
2,
|
|
263
|
+
{
|
|
264
|
+
alphabetize: { order: "asc", orderImportKind: "asc" },
|
|
265
|
+
"newlines-between": "never"
|
|
266
|
+
}
|
|
267
|
+
],
|
|
268
|
+
"lzear/prefer-relative-imports": 2,
|
|
269
|
+
"prefer-arrow/prefer-arrow-functions": [
|
|
270
|
+
2,
|
|
271
|
+
{
|
|
272
|
+
classPropertiesAllowed: false,
|
|
273
|
+
disallowPrototype: true,
|
|
274
|
+
singleReturnOnly: false
|
|
275
|
+
}
|
|
276
|
+
],
|
|
277
|
+
...promisePlugin.configs.recommended.rules,
|
|
278
|
+
...regexpPlugin.configs.recommended.rules,
|
|
279
|
+
...sonarRules,
|
|
280
|
+
"sonarjs/fixme-tag": 0,
|
|
281
|
+
"sonarjs/no-os-command-from-path": 0,
|
|
282
|
+
// annoying
|
|
283
|
+
"sonarjs/os-command": 0,
|
|
284
|
+
// annoying
|
|
285
|
+
"sonarjs/prefer-read-only-props": 0,
|
|
286
|
+
// annoying
|
|
287
|
+
"sonarjs/pseudo-random": 0,
|
|
288
|
+
"sonarjs/todo-tag": 0,
|
|
289
|
+
"sonarjs/void-use": 0,
|
|
290
|
+
...unicornPlugin.configs.recommended.rules,
|
|
291
|
+
"unicorn/no-abusive-eslint-disable": 0,
|
|
292
|
+
"unicorn/no-null": 0,
|
|
293
|
+
"unicorn/prevent-abbreviations": 0
|
|
294
|
+
};
|
|
295
|
+
return {
|
|
296
|
+
name: "lzear/core",
|
|
297
|
+
files,
|
|
298
|
+
languageOptions: {
|
|
299
|
+
globals: {
|
|
300
|
+
...globals.browser,
|
|
301
|
+
...globals.es2025,
|
|
302
|
+
...globals.node
|
|
303
|
+
},
|
|
304
|
+
parserOptions: {
|
|
305
|
+
ecmaVersion: "latest",
|
|
306
|
+
sourceType: "module"
|
|
307
|
+
}
|
|
308
|
+
},
|
|
309
|
+
plugins: {
|
|
310
|
+
"@eslint-community/eslint-comments": eslintCommentsPlugin,
|
|
311
|
+
"de-morgan": deMorganPlugin,
|
|
312
|
+
"import-x": importXPlugin,
|
|
313
|
+
lzear: plugin,
|
|
314
|
+
"prefer-arrow": preferArrowPlugin,
|
|
315
|
+
promise: promisePlugin,
|
|
316
|
+
regexp: regexpPlugin,
|
|
317
|
+
sonarjs: sonarjsPlugin,
|
|
318
|
+
unicorn: unicornPlugin
|
|
319
|
+
},
|
|
320
|
+
rules,
|
|
321
|
+
settings: {
|
|
322
|
+
// import-x uses import-x/resolver; eslint-module-utils (used by lzear/prefer-relative-imports) reads import/resolver
|
|
323
|
+
"import-x/resolver": { typescript: true },
|
|
324
|
+
"import/resolver": { typescript: true }
|
|
325
|
+
}
|
|
326
|
+
};
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
// configs/ignores.ts
|
|
330
|
+
var ignores = [
|
|
331
|
+
"**/.eslint-config-inspector/**",
|
|
332
|
+
"**/vite.config.*.timestamp-*",
|
|
333
|
+
"**/.vitepress/cache/**",
|
|
334
|
+
"**/node_modules/**",
|
|
335
|
+
"**/coverage/**",
|
|
336
|
+
"**/.history/**",
|
|
337
|
+
"**/.netlify/**",
|
|
338
|
+
"**/.vercel/**",
|
|
339
|
+
"**/.output/**",
|
|
340
|
+
"**/output/**",
|
|
341
|
+
"**/.cache/**",
|
|
342
|
+
"**/.temp/**",
|
|
343
|
+
"**/build/**",
|
|
344
|
+
"**/.nuxt/**",
|
|
345
|
+
"**/.next/**",
|
|
346
|
+
"**/dist/**",
|
|
347
|
+
"**/temp/**",
|
|
348
|
+
"**/.tmp/**",
|
|
349
|
+
"**/tmp/**"
|
|
350
|
+
];
|
|
351
|
+
|
|
352
|
+
// configs/node.ts
|
|
353
|
+
var node = async (config) => {
|
|
354
|
+
if (!config.node) {
|
|
355
|
+
return {};
|
|
356
|
+
}
|
|
357
|
+
const nodePlugin = await interopDefault(import("eslint-plugin-n"));
|
|
358
|
+
const files = ["**/*.js", "**/*.cjs", "**/*.mjs"];
|
|
359
|
+
if (config.typescript) {
|
|
360
|
+
files.push("**/*.ts", "**/*.cts", "**/*.mts");
|
|
361
|
+
}
|
|
362
|
+
if (config.react) {
|
|
363
|
+
files.push("**/*.jsx");
|
|
364
|
+
if (config.typescript) {
|
|
365
|
+
files.push("**/*.tsx");
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
return {
|
|
369
|
+
name: "lzear/node",
|
|
370
|
+
files,
|
|
371
|
+
plugins: {
|
|
372
|
+
n: nodePlugin
|
|
373
|
+
},
|
|
374
|
+
rules: {
|
|
375
|
+
...nodePlugin.configs["flat/recommended"]?.rules,
|
|
376
|
+
"n/hashbang": 0,
|
|
377
|
+
// n resolver doesn't understand TypeScript imports; TypeScript handles this
|
|
378
|
+
"n/no-extraneous-import": 0,
|
|
379
|
+
"n/no-missing-import": 0,
|
|
380
|
+
"n/no-process-exit": 0
|
|
381
|
+
},
|
|
382
|
+
settings: {
|
|
383
|
+
// Align with the minimum version where import.meta.dirname is stable
|
|
384
|
+
node: { version: ">=22.16.0" }
|
|
385
|
+
}
|
|
386
|
+
};
|
|
387
|
+
};
|
|
388
|
+
|
|
389
|
+
// configs/package-json.ts
|
|
390
|
+
import * as packageJsonPlugin from "eslint-plugin-package-json";
|
|
391
|
+
import * as jsoncParser from "jsonc-eslint-parser";
|
|
392
|
+
var packageJson = () => ({
|
|
393
|
+
name: "lzear/package-json",
|
|
394
|
+
files: ["**/package.json"],
|
|
395
|
+
plugins: {
|
|
396
|
+
lzear: plugin,
|
|
397
|
+
"package-json": packageJsonPlugin
|
|
398
|
+
},
|
|
399
|
+
languageOptions: {
|
|
400
|
+
parser: jsoncParser
|
|
401
|
+
},
|
|
402
|
+
rules: {
|
|
403
|
+
...packageJsonPlugin.configs.recommended.rules,
|
|
404
|
+
"lzear/major-version-only": 2,
|
|
405
|
+
"package-json/repository-shorthand": [2, { form: "shorthand" }]
|
|
406
|
+
}
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
// configs/prettier.ts
|
|
410
|
+
import prettierConfig from "eslint-plugin-prettier/recommended";
|
|
411
|
+
var prettier = {
|
|
412
|
+
...prettierConfig,
|
|
413
|
+
rules: {
|
|
414
|
+
...prettierConfig.rules,
|
|
415
|
+
"prettier/prettier": [
|
|
416
|
+
2,
|
|
417
|
+
{
|
|
418
|
+
semi: false,
|
|
419
|
+
singleQuote: true
|
|
420
|
+
}
|
|
421
|
+
]
|
|
422
|
+
}
|
|
423
|
+
};
|
|
424
|
+
|
|
425
|
+
// configs/react.ts
|
|
426
|
+
var react = async (config) => {
|
|
427
|
+
if (!config.react) {
|
|
428
|
+
return {};
|
|
429
|
+
}
|
|
430
|
+
const [
|
|
431
|
+
reactCompilerPlugin,
|
|
432
|
+
reactHooksPlugin,
|
|
433
|
+
reactPerfPlugin,
|
|
434
|
+
reactPlugin,
|
|
435
|
+
nextPlugin,
|
|
436
|
+
reactXPlugin,
|
|
437
|
+
reactDomPlugin,
|
|
438
|
+
reactWebApiPlugin
|
|
439
|
+
] = await Promise.all([
|
|
440
|
+
interopDefault(import("eslint-plugin-react-compiler")),
|
|
441
|
+
interopDefault(import("eslint-plugin-react-hooks")),
|
|
442
|
+
interopDefault(import("eslint-plugin-react-perf")),
|
|
443
|
+
interopDefault(import("eslint-plugin-react")),
|
|
444
|
+
interopDefault(import("@next/eslint-plugin-next")),
|
|
445
|
+
interopDefault(import("eslint-plugin-react-x")),
|
|
446
|
+
interopDefault(import("eslint-plugin-react-dom")),
|
|
447
|
+
interopDefault(import("eslint-plugin-react-web-api"))
|
|
448
|
+
]);
|
|
449
|
+
const files = ["**/*.jsx"];
|
|
450
|
+
if (config.typescript) {
|
|
451
|
+
files.push("**/*.tsx");
|
|
452
|
+
}
|
|
453
|
+
return {
|
|
454
|
+
name: "lzear/react",
|
|
455
|
+
files,
|
|
456
|
+
plugins: {
|
|
457
|
+
"@next/next": nextPlugin,
|
|
458
|
+
react: reactPlugin,
|
|
459
|
+
"react-compiler": reactCompilerPlugin,
|
|
460
|
+
"react-dom": reactDomPlugin,
|
|
461
|
+
"react-hooks": reactHooksPlugin,
|
|
462
|
+
"react-perf": reactPerfPlugin,
|
|
463
|
+
"react-web-api": reactWebApiPlugin,
|
|
464
|
+
"react-x": reactXPlugin
|
|
465
|
+
},
|
|
466
|
+
rules: {
|
|
467
|
+
"react-compiler/react-compiler": 2,
|
|
468
|
+
...reactHooksPlugin.configs.recommended.rules,
|
|
469
|
+
...reactPerfPlugin.configs.recommended.rules,
|
|
470
|
+
"react-perf/jsx-no-new-function-as-prop": 0,
|
|
471
|
+
"react-perf/jsx-no-new-object-as-prop": 0,
|
|
472
|
+
...reactPlugin.configs.recommended.rules,
|
|
473
|
+
...nextPlugin.configs.recommended.rules,
|
|
474
|
+
...nextPlugin.configs["core-web-vitals"].rules,
|
|
475
|
+
"react/react-in-jsx-scope": 0,
|
|
476
|
+
"react/no-unknown-property": ["error", { ignore: ["jsx", "global"] }],
|
|
477
|
+
...config.typescript ? reactXPlugin.configs["recommended-typescript"].rules : reactXPlugin.configs.recommended.rules,
|
|
478
|
+
...reactDomPlugin.configs.recommended.rules,
|
|
479
|
+
...reactWebApiPlugin.configs.recommended.rules
|
|
480
|
+
},
|
|
481
|
+
settings: {
|
|
482
|
+
react: {
|
|
483
|
+
fragment: "Fragment",
|
|
484
|
+
pragma: "React",
|
|
485
|
+
version: "19.0"
|
|
486
|
+
},
|
|
487
|
+
"react-x": {
|
|
488
|
+
importSource: "react",
|
|
489
|
+
polymorphicPropName: "as",
|
|
490
|
+
version: "19.0"
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
};
|
|
494
|
+
};
|
|
495
|
+
|
|
496
|
+
// configs/typescript.ts
|
|
497
|
+
import eslint from "@eslint/js";
|
|
498
|
+
import { defineConfig } from "eslint/config";
|
|
499
|
+
import tseslint from "typescript-eslint";
|
|
500
|
+
var typescript = async (config) => {
|
|
501
|
+
if (!config.typescript) {
|
|
502
|
+
return [];
|
|
503
|
+
}
|
|
504
|
+
const { parser: typescriptParser } = await interopDefault(
|
|
505
|
+
import("typescript-eslint")
|
|
506
|
+
);
|
|
507
|
+
const files = ["**/*.ts", "**/*.tsx", "**/*.cts", "**/*.mts"];
|
|
508
|
+
return defineConfig({
|
|
509
|
+
name: "lzear/typescript",
|
|
510
|
+
extends: [
|
|
511
|
+
eslint.configs.recommended,
|
|
512
|
+
tseslint.configs.recommendedTypeChecked,
|
|
513
|
+
tseslint.configs.stylisticTypeChecked
|
|
514
|
+
],
|
|
515
|
+
files,
|
|
516
|
+
languageOptions: {
|
|
517
|
+
parser: typescriptParser,
|
|
518
|
+
parserOptions: {
|
|
519
|
+
ecmaFeatures: { jsx: config.react },
|
|
520
|
+
ecmaVersion: "latest",
|
|
521
|
+
projectService: true,
|
|
522
|
+
sourceType: "module",
|
|
523
|
+
tsconfigRootDir: process.cwd()
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
});
|
|
527
|
+
};
|
|
528
|
+
|
|
529
|
+
// configs/vitest.ts
|
|
530
|
+
var vitest = async (config) => {
|
|
531
|
+
if (!config.vitest) {
|
|
532
|
+
return {};
|
|
533
|
+
}
|
|
534
|
+
const vitestPlugin = await interopDefault(import("@vitest/eslint-plugin"));
|
|
535
|
+
const files = [
|
|
536
|
+
"**/test/*.js",
|
|
537
|
+
"**/test/*.cjs",
|
|
538
|
+
"**/test/*.mjs",
|
|
539
|
+
"**/*.test.js",
|
|
540
|
+
"**/*.test.cjs",
|
|
541
|
+
"**/*.test.mjs"
|
|
542
|
+
];
|
|
543
|
+
if (config.typescript) {
|
|
544
|
+
files.push(
|
|
545
|
+
"**/test/*.ts",
|
|
546
|
+
"**/test/*.cts",
|
|
547
|
+
"**/test/*.mts",
|
|
548
|
+
"**/*.test.ts",
|
|
549
|
+
"**/*.test.cts",
|
|
550
|
+
"**/*.test.mts"
|
|
551
|
+
);
|
|
552
|
+
}
|
|
553
|
+
if (config.react) {
|
|
554
|
+
files.push("**/test/*.jsx", "**/*.test.jsx");
|
|
555
|
+
if (config.typescript) {
|
|
556
|
+
files.push("**/test/*.tsx", "**/*.test.tsx");
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
return {
|
|
560
|
+
name: "lzear/vitest",
|
|
561
|
+
files,
|
|
562
|
+
plugins: {
|
|
563
|
+
vitest: vitestPlugin
|
|
564
|
+
},
|
|
565
|
+
rules: {
|
|
566
|
+
...vitestPlugin.configs.recommended.rules,
|
|
567
|
+
"vitest/consistent-test-it": [2, { fn: "it" }],
|
|
568
|
+
// Using Vitest globals mode — explicit imports not required
|
|
569
|
+
"vitest/prefer-importing-vitest-globals": 0
|
|
570
|
+
},
|
|
571
|
+
settings: {
|
|
572
|
+
vitest: {
|
|
573
|
+
typecheck: true
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
};
|
|
577
|
+
};
|
|
578
|
+
|
|
579
|
+
// index.ts
|
|
580
|
+
var configGenerator = async (options = {}) => {
|
|
581
|
+
const config = {
|
|
582
|
+
node: true,
|
|
583
|
+
react: true,
|
|
584
|
+
typescript: true,
|
|
585
|
+
vitest: true,
|
|
586
|
+
...options
|
|
587
|
+
};
|
|
588
|
+
const [reactConfig, nodeConfig, typescriptConfig, vitestConfig] = await Promise.all([
|
|
589
|
+
react(config),
|
|
590
|
+
node(config),
|
|
591
|
+
typescript(config),
|
|
592
|
+
vitest(config)
|
|
593
|
+
]);
|
|
594
|
+
return [
|
|
595
|
+
{ name: "lzear/ignores", ignores },
|
|
596
|
+
core(),
|
|
597
|
+
a11y(config),
|
|
598
|
+
reactConfig,
|
|
599
|
+
nodeConfig,
|
|
600
|
+
typescriptConfig,
|
|
601
|
+
vitestConfig,
|
|
602
|
+
packageJson(),
|
|
603
|
+
prettier
|
|
604
|
+
].flat();
|
|
605
|
+
};
|
|
606
|
+
var index_default = configGenerator;
|
|
607
|
+
export {
|
|
608
|
+
index_default as default
|
|
609
|
+
};
|