@coderwyd/eslint-config 2.7.0 → 2.7.2

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.js CHANGED
@@ -1,11 +1,22 @@
1
+ // src/configs/command.ts
2
+ import createCommand from "eslint-plugin-command/config";
3
+ function command() {
4
+ return [
5
+ {
6
+ ...createCommand(),
7
+ name: "coderwyd/command/rules"
8
+ }
9
+ ];
10
+ }
11
+
1
12
  // src/plugins/index.ts
2
- import { default as default2 } from "eslint-plugin-antfu";
3
- import { default as default3 } from "@eslint-community/eslint-plugin-eslint-comments";
13
+ import { default as default2 } from "@eslint-community/eslint-plugin-eslint-comments";
14
+ import { default as default3 } from "eslint-plugin-antfu";
4
15
  import * as pluginImport from "eslint-plugin-import-x";
5
16
  import { default as default4 } from "eslint-plugin-n";
6
- import { default as default5 } from "eslint-plugin-unicorn";
7
- import { default as default6 } from "eslint-plugin-unused-imports";
8
- import { default as default7 } from "eslint-plugin-perfectionist";
17
+ import { default as default5 } from "eslint-plugin-perfectionist";
18
+ import { default as default6 } from "eslint-plugin-unicorn";
19
+ import { default as default7 } from "eslint-plugin-unused-imports";
9
20
 
10
21
  // src/configs/comments.ts
11
22
  function comments() {
@@ -13,7 +24,7 @@ function comments() {
13
24
  {
14
25
  name: "coderwyd/eslint-comments/rules",
15
26
  plugins: {
16
- "eslint-comments": default3
27
+ "eslint-comments": default2
17
28
  },
18
29
  rules: {
19
30
  "eslint-comments/no-aggregating-enable": "error",
@@ -89,107 +100,413 @@ var GLOB_EXCLUDE = [
89
100
  "**/components.d.ts"
90
101
  ];
91
102
 
92
- // src/configs/ignores.ts
93
- function ignores(userIgnores = []) {
103
+ // src/configs/disables.ts
104
+ function disables() {
94
105
  return [
95
106
  {
96
- ignores: [
97
- ...GLOB_EXCLUDE,
98
- ...userIgnores
99
- ],
100
- name: "coderwyd/ignores"
101
- }
102
- ];
103
- }
104
-
105
- // src/configs/imports.ts
106
- function imports(options = {}) {
107
- const { stylistic: stylistic2 = true } = options;
108
- return [
107
+ files: [`scripts/${GLOB_SRC}`],
108
+ name: "coderwyd/disables/scripts",
109
+ rules: {
110
+ "no-console": "off",
111
+ "ts/explicit-function-return-type": "off"
112
+ }
113
+ },
109
114
  {
110
- name: "coderwyd/imports/rules",
111
- plugins: {
112
- antfu: default2,
113
- import: pluginImport
114
- },
115
+ files: [`cli/${GLOB_SRC}`, `cli.${GLOB_SRC_EXT}`],
116
+ name: "coderwyd/disables/cli",
115
117
  rules: {
116
- "antfu/import-dedupe": "error",
117
- "antfu/no-import-dist": "error",
118
- "antfu/no-import-node-modules-by-path": "error",
119
- "import/first": "error",
120
- "import/no-duplicates": "error",
121
- "import/no-mutable-exports": "error",
122
- "import/no-named-default": "error",
123
- "import/no-self-import": "error",
124
- "import/no-webpack-loader-syntax": "error",
125
- ...stylistic2 ? {
126
- "import/newline-after-import": ["error", { count: 1 }]
127
- } : {}
118
+ "no-console": "off"
128
119
  }
129
120
  },
130
121
  {
131
122
  files: ["**/bin/**/*", `**/bin.${GLOB_SRC_EXT}`],
132
- name: "coderwyd/imports/disables/bin",
123
+ name: "coderwyd/disables/bin",
133
124
  rules: {
134
125
  "antfu/no-import-dist": "off",
135
126
  "antfu/no-import-node-modules-by-path": "off"
136
127
  }
128
+ },
129
+ {
130
+ files: [GLOB_DTS],
131
+ name: "coderwyd/disables/dts",
132
+ rules: {
133
+ "eslint-comments/no-unlimited-disable": "off",
134
+ "import/no-duplicates": "off",
135
+ "no-restricted-syntax": "off",
136
+ "unused-imports/no-unused-vars": "off"
137
+ }
138
+ },
139
+ {
140
+ files: ["**/*.{test,spec}.([tj])s?(x)"],
141
+ name: "coderwyd/disables/test",
142
+ rules: {
143
+ "no-unused-expressions": "off"
144
+ }
145
+ },
146
+ {
147
+ files: ["**/*.js", "**/*.cjs"],
148
+ name: "coderwyd/disables/cjs",
149
+ rules: {
150
+ "ts/no-require-imports": "off"
151
+ }
137
152
  }
138
153
  ];
139
154
  }
140
155
 
141
- // src/configs/javascript.ts
142
- import globals from "globals";
143
- function javascript(options = {}) {
144
- const { isInEditor: isInEditor2 = false, overrides = {} } = options;
145
- return [
146
- {
147
- languageOptions: {
148
- ecmaVersion: 2022,
149
- globals: {
150
- ...globals.browser,
151
- ...globals.es2021,
152
- ...globals.node,
153
- document: "readonly",
154
- navigator: "readonly",
155
- window: "readonly"
156
- },
157
- parserOptions: {
158
- ecmaFeatures: {
159
- jsx: true
160
- },
161
- ecmaVersion: 2022,
162
- sourceType: "module"
163
- },
164
- sourceType: "module"
165
- },
166
- linterOptions: {
167
- reportUnusedDisableDirectives: true
168
- },
169
- name: "coderwyd/javascript/setup"
156
+ // src/shared/index.ts
157
+ import process from "node:process";
158
+ import { fileURLToPath } from "node:url";
159
+ import { getPackageInfoSync, isPackageExists } from "local-pkg";
160
+ var scopeUrl = fileURLToPath(new URL(".", import.meta.url));
161
+ var isCwdInScope = isPackageExists("@coderwyd/eslint-config");
162
+ var parserPlain = {
163
+ meta: {
164
+ name: "parser-plain"
165
+ },
166
+ parseForESLint: (code) => ({
167
+ ast: {
168
+ body: [],
169
+ comments: [],
170
+ loc: { end: code.length, start: 0 },
171
+ range: [0, code.length],
172
+ tokens: [],
173
+ type: "Program"
170
174
  },
175
+ scopeManager: null,
176
+ services: { isPlain: true },
177
+ visitorKeys: {
178
+ Program: []
179
+ }
180
+ })
181
+ };
182
+ async function combine(...configs2) {
183
+ const resolved = await Promise.all(configs2);
184
+ return resolved.flat();
185
+ }
186
+ function renameRules(rules, map) {
187
+ return Object.fromEntries(
188
+ Object.entries(rules).map(([key, value]) => {
189
+ for (const [from, to] of Object.entries(map)) {
190
+ if (key.startsWith(`${from}/`))
191
+ return [to + key.slice(from.length), value];
192
+ }
193
+ return [key, value];
194
+ })
195
+ );
196
+ }
197
+ function renamePluginInConfigs(configs2, map) {
198
+ return configs2.map((i) => {
199
+ const clone = { ...i };
200
+ if (clone.rules)
201
+ clone.rules = renameRules(clone.rules, map);
202
+ if (clone.plugins) {
203
+ clone.plugins = Object.fromEntries(
204
+ Object.entries(clone.plugins).map(([key, value]) => {
205
+ if (key in map)
206
+ return [map[key], value];
207
+ return [key, value];
208
+ })
209
+ );
210
+ }
211
+ return clone;
212
+ });
213
+ }
214
+ function getVueVersion() {
215
+ const pkg = getPackageInfoSync("vue", { paths: [process.cwd()] });
216
+ if (pkg && typeof pkg.version === "string" && !Number.isNaN(+pkg.version[0]))
217
+ return +pkg.version[0];
218
+ return 3;
219
+ }
220
+ function toArray(value) {
221
+ return Array.isArray(value) ? value : [value];
222
+ }
223
+ async function interopDefault(m) {
224
+ const resolved = await m;
225
+ return resolved.default || resolved;
226
+ }
227
+ function isPackageInScope(name) {
228
+ return isPackageExists(name, { paths: [scopeUrl] });
229
+ }
230
+ async function ensurePackages(packages) {
231
+ if (process.env.CI || process.stdout.isTTY === false || isCwdInScope === false)
232
+ return;
233
+ const nonExistingPackages = packages.filter((i) => !isPackageInScope(i));
234
+ if (nonExistingPackages.length === 0)
235
+ return;
236
+ const { default: prompts } = await import("prompts");
237
+ const { result } = await prompts([
171
238
  {
172
- name: "coderwyd/javascript/rules",
239
+ message: `${nonExistingPackages.length === 1 ? "Package is" : "Packages are"} required for this config: ${nonExistingPackages.join(", ")}. Do you want to install them?`,
240
+ name: "result",
241
+ type: "confirm"
242
+ }
243
+ ]);
244
+ if (result) {
245
+ await import("@antfu/install-pkg").then(
246
+ (i) => i.installPackage(nonExistingPackages, { dev: true })
247
+ );
248
+ }
249
+ }
250
+ function resolveSubOptions(options, key) {
251
+ return typeof options[key] === "boolean" ? {} : options[key] || {};
252
+ }
253
+ function getOverrides(options, key) {
254
+ const sub = resolveSubOptions(options, key);
255
+ return {
256
+ ..."overrides" in sub ? sub.overrides || {} : {}
257
+ };
258
+ }
259
+ function isInEditorEnv() {
260
+ if (process.env.CI)
261
+ return false;
262
+ if (isInGitHooksOrLintStaged())
263
+ return false;
264
+ return !!(process.env.VSCODE_PID || process.env.VSCODE_CWD || process.env.JETBRAINS_IDE || process.env.VIM || process.env.NVIM || false);
265
+ }
266
+ function isInGitHooksOrLintStaged() {
267
+ return !!(process.env.GIT_PARAMS || process.env.VSCODE_GIT_COMMAND || process.env.npm_lifecycle_script?.startsWith("lint-staged") || process.env.npm_lifecycle_script?.startsWith("nano-staged") || false);
268
+ }
269
+
270
+ // src/configs/stylistic.ts
271
+ var StylisticConfigDefaults = {
272
+ indent: 2,
273
+ jsx: true,
274
+ quotes: "single",
275
+ semi: false
276
+ };
277
+ async function stylistic(options = {}) {
278
+ const {
279
+ indent,
280
+ jsx: jsx2,
281
+ overrides = {},
282
+ quotes,
283
+ semi
284
+ } = {
285
+ ...StylisticConfigDefaults,
286
+ ...options
287
+ };
288
+ const pluginStylistic = await interopDefault(
289
+ import("@stylistic/eslint-plugin")
290
+ );
291
+ const config = pluginStylistic.configs.customize({
292
+ flat: true,
293
+ indent,
294
+ jsx: jsx2,
295
+ pluginName: "style",
296
+ quotes,
297
+ semi
298
+ });
299
+ return [
300
+ {
301
+ name: "coderwyd/stylistic/rules",
173
302
  plugins: {
174
- "unused-imports": default6
303
+ antfu: default3,
304
+ style: pluginStylistic
175
305
  },
176
306
  rules: {
177
- "accessor-pairs": [
178
- "error",
179
- { enforceForClassMembers: true, setWithoutGet: true }
180
- ],
181
- "array-callback-return": "error",
182
- "block-scoped-var": "error",
183
- "constructor-super": "error",
184
- "default-case-last": "error",
185
- "dot-notation": ["error", { allowKeywords: true }],
186
- "eqeqeq": ["error", "smart"],
187
- "for-direction": "error",
188
- "getter-return": "error",
189
- "new-cap": [
190
- "error",
191
- { capIsNew: false, newIsCap: true, properties: true }
192
- ],
307
+ ...config.rules,
308
+ "antfu/consistent-chaining": "error",
309
+ "antfu/consistent-list-newline": "error",
310
+ "antfu/curly": "error",
311
+ "antfu/if-newline": "warn",
312
+ "antfu/top-level-function": "warn",
313
+ ...overrides
314
+ }
315
+ }
316
+ ];
317
+ }
318
+
319
+ // src/configs/formatter.ts
320
+ async function formatter(options = {}, stylistic2 = {}) {
321
+ const { css, graphql, html, markdown, toml, yaml } = options === true ? {
322
+ css: true,
323
+ graphql: true,
324
+ html: true,
325
+ markdown: true,
326
+ toml: true,
327
+ yaml: true
328
+ } : options;
329
+ const { indent, quotes, semi } = {
330
+ ...StylisticConfigDefaults,
331
+ ...stylistic2
332
+ };
333
+ const prettierOptions = Object.assign(
334
+ {
335
+ endOfLine: "auto",
336
+ printWidth: 80,
337
+ semi,
338
+ singleQuote: quotes === "single",
339
+ tabWidth: typeof indent === "number" ? indent : 2,
340
+ trailingComma: "all",
341
+ useTabs: indent === "tab"
342
+ },
343
+ typeof options === "boolean" ? {} : options.prettierOptions || {}
344
+ );
345
+ await ensurePackages(["eslint-plugin-format"]);
346
+ const pluginFormat = await interopDefault(import("eslint-plugin-format"));
347
+ function createPrettierFormatter(files, parser, plugins) {
348
+ const rules = {
349
+ ...prettierOptions,
350
+ parser
351
+ };
352
+ const markdownRules = {
353
+ printWidth: 120,
354
+ ...rules,
355
+ embeddedLanguageFormatting: "off"
356
+ };
357
+ if (plugins?.length)
358
+ rules.plugins = [...rules.plugins || [], ...plugins];
359
+ const config = {
360
+ files,
361
+ languageOptions: {
362
+ parser: parserPlain
363
+ },
364
+ name: `coderwyd/formatter/${parser}`,
365
+ plugins: {
366
+ format: pluginFormat
367
+ },
368
+ rules: {
369
+ "format/prettier": [
370
+ "warn",
371
+ parser === "markdown" ? markdownRules : rules
372
+ ]
373
+ }
374
+ };
375
+ return config;
376
+ }
377
+ const configs2 = [
378
+ {
379
+ name: "coderwyd/formatter/setup",
380
+ plugins: {
381
+ format: pluginFormat
382
+ }
383
+ }
384
+ ];
385
+ if (html) {
386
+ const htmlConfig = createPrettierFormatter([GLOB_HTML], "html");
387
+ configs2.push(htmlConfig);
388
+ }
389
+ if (css) {
390
+ const cssConfig = createPrettierFormatter([GLOB_CSS, GLOB_POSTCSS], "css");
391
+ const scssConfig = createPrettierFormatter([GLOB_SCSS], "scss");
392
+ const lessConfig = createPrettierFormatter([GLOB_LESS], "less");
393
+ configs2.push(cssConfig, scssConfig, lessConfig);
394
+ }
395
+ if (markdown) {
396
+ const markdownConfig = createPrettierFormatter([GLOB_MARKDOWN], "markdown");
397
+ configs2.push(markdownConfig);
398
+ }
399
+ if (graphql) {
400
+ const graphqlConfig = createPrettierFormatter([GLOB_GRAPHQL], "graphql");
401
+ configs2.push(graphqlConfig);
402
+ }
403
+ if (yaml) {
404
+ const yamlConfig = createPrettierFormatter([GLOB_YAML], "yaml");
405
+ configs2.push(yamlConfig);
406
+ }
407
+ if (toml) {
408
+ await ensurePackages(["@toml-tools/parser", "prettier-plugin-toml"]);
409
+ const tomlConfig = createPrettierFormatter([GLOB_TOML], "toml", [
410
+ "prettier-plugin-toml"
411
+ ]);
412
+ configs2.push(tomlConfig);
413
+ }
414
+ return configs2;
415
+ }
416
+
417
+ // src/configs/ignores.ts
418
+ function ignores(userIgnores = []) {
419
+ return [
420
+ {
421
+ ignores: [
422
+ ...GLOB_EXCLUDE,
423
+ ...userIgnores
424
+ ],
425
+ name: "coderwyd/ignores"
426
+ }
427
+ ];
428
+ }
429
+
430
+ // src/configs/imports.ts
431
+ function imports(options = {}) {
432
+ const { stylistic: stylistic2 = true } = options;
433
+ return [
434
+ {
435
+ name: "coderwyd/imports/rules",
436
+ plugins: {
437
+ antfu: default3,
438
+ import: pluginImport
439
+ },
440
+ rules: {
441
+ "antfu/import-dedupe": "error",
442
+ "antfu/no-import-dist": "error",
443
+ "antfu/no-import-node-modules-by-path": "error",
444
+ "import/first": "error",
445
+ "import/no-duplicates": "error",
446
+ "import/no-mutable-exports": "error",
447
+ "import/no-named-default": "error",
448
+ "import/no-self-import": "error",
449
+ "import/no-webpack-loader-syntax": "error",
450
+ ...stylistic2 ? {
451
+ "import/newline-after-import": ["error", { count: 1 }]
452
+ } : {}
453
+ }
454
+ }
455
+ ];
456
+ }
457
+
458
+ // src/configs/javascript.ts
459
+ import globals from "globals";
460
+ function javascript(options = {}) {
461
+ const { isInEditor: isInEditor2 = false, overrides = {} } = options;
462
+ return [
463
+ {
464
+ languageOptions: {
465
+ ecmaVersion: 2022,
466
+ globals: {
467
+ ...globals.browser,
468
+ ...globals.es2021,
469
+ ...globals.node,
470
+ document: "readonly",
471
+ navigator: "readonly",
472
+ window: "readonly"
473
+ },
474
+ parserOptions: {
475
+ ecmaFeatures: {
476
+ jsx: true
477
+ },
478
+ ecmaVersion: 2022,
479
+ sourceType: "module"
480
+ },
481
+ sourceType: "module"
482
+ },
483
+ linterOptions: {
484
+ reportUnusedDisableDirectives: true
485
+ },
486
+ name: "coderwyd/javascript/setup"
487
+ },
488
+ {
489
+ name: "coderwyd/javascript/rules",
490
+ plugins: {
491
+ "unused-imports": default7
492
+ },
493
+ rules: {
494
+ "accessor-pairs": [
495
+ "error",
496
+ { enforceForClassMembers: true, setWithoutGet: true }
497
+ ],
498
+ "array-callback-return": "error",
499
+ "block-scoped-var": "error",
500
+ "constructor-super": "error",
501
+ "default-case-last": "error",
502
+ "dot-notation": ["error", { allowKeywords: true }],
503
+ "eqeqeq": ["error", "smart"],
504
+ "for-direction": "error",
505
+ "getter-return": "error",
506
+ "new-cap": [
507
+ "error",
508
+ { capIsNew: false, newIsCap: true, properties: true }
509
+ ],
193
510
  "no-alert": "error",
194
511
  "no-array-constructor": "error",
195
512
  "no-async-promise-executor": "error",
@@ -367,167 +684,39 @@ function javascript(options = {}) {
367
684
  "yoda": ["error", "never"],
368
685
  ...overrides
369
686
  }
370
- },
371
- {
372
- files: [`scripts/${GLOB_SRC}`, `cli.${GLOB_SRC_EXT}`],
373
- name: "coderwyd/javascript/disables/cli",
374
- rules: {
375
- "no-console": "off"
376
- }
377
- },
687
+ }
688
+ ];
689
+ }
690
+
691
+ // src/configs/jsdoc.ts
692
+ async function jsdoc(options = {}) {
693
+ const { stylistic: stylistic2 = true } = options;
694
+ return [
378
695
  {
379
- files: ["**/*.{test,spec}.js?(x)"],
380
- name: "coderwyd/javascript/disables/test",
696
+ name: "coderwyd/jsdoc/rules",
697
+ plugins: {
698
+ jsdoc: await interopDefault(import("eslint-plugin-jsdoc"))
699
+ },
381
700
  rules: {
382
- "no-unused-expressions": "off"
383
- }
384
- }
385
- ];
386
- }
387
-
388
- // src/shared/index.ts
389
- import process from "node:process";
390
- import { fileURLToPath } from "node:url";
391
- import { getPackageInfoSync, isPackageExists } from "local-pkg";
392
- var scopeUrl = fileURLToPath(new URL(".", import.meta.url));
393
- var isCwdInScope = isPackageExists("@coderwyd/eslint-config");
394
- var parserPlain = {
395
- meta: {
396
- name: "parser-plain"
397
- },
398
- parseForESLint: (code) => ({
399
- ast: {
400
- body: [],
401
- comments: [],
402
- loc: { end: code.length, start: 0 },
403
- range: [0, code.length],
404
- tokens: [],
405
- type: "Program"
406
- },
407
- scopeManager: null,
408
- services: { isPlain: true },
409
- visitorKeys: {
410
- Program: []
411
- }
412
- })
413
- };
414
- async function combine(...configs2) {
415
- const resolved = await Promise.all(configs2);
416
- return resolved.flat();
417
- }
418
- function renameRules(rules, map) {
419
- return Object.fromEntries(
420
- Object.entries(rules).map(([key, value]) => {
421
- for (const [from, to] of Object.entries(map)) {
422
- if (key.startsWith(`${from}/`))
423
- return [to + key.slice(from.length), value];
424
- }
425
- return [key, value];
426
- })
427
- );
428
- }
429
- function renamePluginInConfigs(configs2, map) {
430
- return configs2.map((i) => {
431
- const clone = { ...i };
432
- if (clone.rules)
433
- clone.rules = renameRules(clone.rules, map);
434
- if (clone.plugins) {
435
- clone.plugins = Object.fromEntries(
436
- Object.entries(clone.plugins).map(([key, value]) => {
437
- if (key in map)
438
- return [map[key], value];
439
- return [key, value];
440
- })
441
- );
442
- }
443
- return clone;
444
- });
445
- }
446
- function getVueVersion() {
447
- const pkg = getPackageInfoSync("vue", { paths: [process.cwd()] });
448
- if (pkg && typeof pkg.version === "string" && !Number.isNaN(+pkg.version[0]))
449
- return +pkg.version[0];
450
- return 3;
451
- }
452
- function toArray(value) {
453
- return Array.isArray(value) ? value : [value];
454
- }
455
- async function interopDefault(m) {
456
- const resolved = await m;
457
- return resolved.default || resolved;
458
- }
459
- function isPackageInScope(name) {
460
- return isPackageExists(name, { paths: [scopeUrl] });
461
- }
462
- async function ensurePackages(packages) {
463
- if (process.env.CI || process.stdout.isTTY === false || isCwdInScope === false)
464
- return;
465
- const nonExistingPackages = packages.filter((i) => !isPackageInScope(i));
466
- if (nonExistingPackages.length === 0)
467
- return;
468
- const { default: prompts } = await import("prompts");
469
- const { result } = await prompts([
470
- {
471
- message: `${nonExistingPackages.length === 1 ? "Package is" : "Packages are"} required for this config: ${nonExistingPackages.join(", ")}. Do you want to install them?`,
472
- name: "result",
473
- type: "confirm"
474
- }
475
- ]);
476
- if (result) {
477
- await import("@antfu/install-pkg").then(
478
- (i) => i.installPackage(nonExistingPackages, { dev: true })
479
- );
480
- }
481
- }
482
- function resolveSubOptions(options, key) {
483
- return typeof options[key] === "boolean" ? {} : options[key] || {};
484
- }
485
- function getOverrides(options, key) {
486
- const sub = resolveSubOptions(options, key);
487
- return {
488
- ..."overrides" in sub ? sub.overrides || {} : {}
489
- };
490
- }
491
- function isInEditorEnv() {
492
- if (process.env.CI)
493
- return false;
494
- if (isInGitHooksOrLintStaged())
495
- return false;
496
- return !!(process.env.VSCODE_PID || process.env.VSCODE_CWD || process.env.JETBRAINS_IDE || process.env.VIM || process.env.NVIM || false);
497
- }
498
- function isInGitHooksOrLintStaged() {
499
- return !!(process.env.GIT_PARAMS || process.env.VSCODE_GIT_COMMAND || process.env.npm_lifecycle_script?.startsWith("lint-staged") || process.env.npm_lifecycle_script?.startsWith("nano-staged") || false);
500
- }
501
-
502
- // src/configs/jsdoc.ts
503
- async function jsdoc(options = {}) {
504
- const { stylistic: stylistic2 = true } = options;
505
- return [
506
- {
507
- name: "coderwyd/jsdoc/rules",
508
- plugins: {
509
- jsdoc: await interopDefault(import("eslint-plugin-jsdoc"))
510
- },
511
- rules: {
512
- "jsdoc/check-access": "warn",
513
- "jsdoc/check-param-names": "warn",
514
- "jsdoc/check-property-names": "warn",
515
- "jsdoc/check-types": "warn",
516
- "jsdoc/empty-tags": "warn",
517
- "jsdoc/implements-on-classes": "warn",
518
- "jsdoc/no-defaults": "warn",
519
- "jsdoc/no-multi-asterisks": "warn",
520
- "jsdoc/require-param-name": "warn",
521
- "jsdoc/require-property": "warn",
522
- "jsdoc/require-property-description": "warn",
523
- "jsdoc/require-property-name": "warn",
524
- "jsdoc/require-returns-check": "warn",
525
- "jsdoc/require-returns-description": "warn",
526
- "jsdoc/require-yields-check": "warn",
527
- ...stylistic2 ? {
528
- "jsdoc/check-alignment": "warn",
529
- "jsdoc/multiline-blocks": "warn"
530
- } : {}
701
+ "jsdoc/check-access": "warn",
702
+ "jsdoc/check-param-names": "warn",
703
+ "jsdoc/check-property-names": "warn",
704
+ "jsdoc/check-types": "warn",
705
+ "jsdoc/empty-tags": "warn",
706
+ "jsdoc/implements-on-classes": "warn",
707
+ "jsdoc/no-defaults": "warn",
708
+ "jsdoc/no-multi-asterisks": "warn",
709
+ "jsdoc/require-param-name": "warn",
710
+ "jsdoc/require-property": "warn",
711
+ "jsdoc/require-property-description": "warn",
712
+ "jsdoc/require-property-name": "warn",
713
+ "jsdoc/require-returns-check": "warn",
714
+ "jsdoc/require-returns-description": "warn",
715
+ "jsdoc/require-yields-check": "warn",
716
+ ...stylistic2 ? {
717
+ "jsdoc/check-alignment": "warn",
718
+ "jsdoc/multiline-blocks": "warn"
719
+ } : {}
531
720
  }
532
721
  }
533
722
  ];
@@ -614,6 +803,23 @@ async function jsonc(options = {}) {
614
803
  ];
615
804
  }
616
805
 
806
+ // src/configs/jsx.ts
807
+ function jsx() {
808
+ return [
809
+ {
810
+ files: [GLOB_JSX, GLOB_TSX],
811
+ languageOptions: {
812
+ parserOptions: {
813
+ ecmaFeatures: {
814
+ jsx: true
815
+ }
816
+ }
817
+ },
818
+ name: "coderwyd/jsx/setup"
819
+ }
820
+ ];
821
+ }
822
+
617
823
  // src/configs/node.ts
618
824
  function node() {
619
825
  return [
@@ -637,1303 +843,1101 @@ function node() {
637
843
  ];
638
844
  }
639
845
 
640
- // src/configs/sort.ts
641
- function sortPackageJson() {
846
+ // src/configs/perfectionist.ts
847
+ function perfectionist() {
642
848
  return [
643
849
  {
644
- files: ["**/package.json"],
645
- name: "coderwyd/sort/package-json",
850
+ name: "coderwyd/perfectionist/rules",
851
+ plugins: {
852
+ perfectionist: default5
853
+ },
646
854
  rules: {
647
- "jsonc/sort-array-values": [
648
- "error",
649
- {
650
- order: { type: "asc" },
651
- pathPattern: "^files$"
652
- }
653
- ],
654
- "jsonc/sort-keys": [
655
- "error",
855
+ "perfectionist/sort-exports": ["error", { order: "asc", type: "natural" }],
856
+ "perfectionist/sort-imports": [
857
+ "warn",
656
858
  {
657
- order: [
658
- "publisher",
659
- "name",
660
- "displayName",
859
+ groups: [
860
+ "builtin",
861
+ "external",
661
862
  "type",
662
- "version",
663
- "private",
664
- "packageManager",
665
- "description",
666
- "author",
667
- "license",
668
- "funding",
669
- "homepage",
670
- "repository",
671
- "bugs",
672
- "keywords",
673
- "categories",
674
- "sideEffects",
675
- "exports",
676
- "main",
677
- "module",
678
- "unpkg",
679
- "jsdelivr",
680
- "types",
681
- "typesVersions",
682
- "bin",
683
- "icon",
684
- "files",
685
- "engines",
686
- "activationEvents",
687
- "contributes",
688
- "scripts",
689
- "peerDependencies",
690
- "peerDependenciesMeta",
691
- "dependencies",
692
- "optionalDependencies",
693
- "devDependencies",
694
- "pnpm",
695
- "overrides",
696
- "resolutions",
697
- "husky",
698
- "simple-git-hooks",
699
- "lint-staged",
700
- "eslintConfig"
701
- ],
702
- pathPattern: "^$"
703
- },
704
- {
705
- order: { type: "asc" },
706
- pathPattern: "^(?:dev|peer|optional|bundled)?[Dd]ependencies(Meta)?$"
707
- },
708
- {
709
- order: { type: "asc" },
710
- pathPattern: "^(?:resolutions|overrides|pnpm.overrides)$"
711
- },
712
- {
713
- order: ["types", "import", "require", "default"],
714
- pathPattern: "^exports.*$"
715
- },
716
- {
717
- order: [
718
- // client hooks only
719
- "pre-commit",
720
- "prepare-commit-msg",
721
- "commit-msg",
722
- "post-commit",
723
- "pre-rebase",
724
- "post-rewrite",
725
- "post-checkout",
726
- "post-merge",
727
- "pre-push",
728
- "pre-auto-gc"
863
+ ["internal", "internal-type"],
864
+ ["parent", "sibling", "index"],
865
+ ["parent-type", "sibling-type", "index-type"],
866
+ "object",
867
+ "side-effect",
868
+ "side-effect-style",
869
+ "style",
870
+ "unknown"
729
871
  ],
730
- pathPattern: "^(?:gitHooks|husky|simple-git-hooks)$"
731
- }
732
- ]
733
- }
734
- }
735
- ];
736
- }
737
- function sortTsconfig() {
738
- return [
739
- {
740
- files: ["**/tsconfig.json", "**/tsconfig.*.json"],
741
- name: "coderwyd/sort/tsconfig-json",
742
- rules: {
743
- "jsonc/sort-keys": [
744
- "error",
745
- {
746
- order: [
747
- "extends",
748
- "compilerOptions",
749
- "references",
750
- "files",
751
- "include",
752
- "exclude"
753
- ],
754
- pathPattern: "^$"
755
- },
756
- {
757
- order: [
758
- /* Projects */
759
- "incremental",
760
- "composite",
761
- "tsBuildInfoFile",
762
- "disableSourceOfProjectReferenceRedirect",
763
- "disableSolutionSearching",
764
- "disableReferencedProjectLoad",
765
- /* Language and Environment */
766
- "target",
767
- "jsx",
768
- "jsxFactory",
769
- "jsxFragmentFactory",
770
- "jsxImportSource",
771
- "lib",
772
- "moduleDetection",
773
- "noLib",
774
- "reactNamespace",
775
- "useDefineForClassFields",
776
- "emitDecoratorMetadata",
777
- "experimentalDecorators",
778
- /* Modules */
779
- "baseUrl",
780
- "rootDir",
781
- "rootDirs",
782
- "customConditions",
783
- "module",
784
- "moduleResolution",
785
- "moduleSuffixes",
786
- "noResolve",
787
- "paths",
788
- "resolveJsonModule",
789
- "resolvePackageJsonExports",
790
- "resolvePackageJsonImports",
791
- "typeRoots",
792
- "types",
793
- "allowArbitraryExtensions",
794
- "allowImportingTsExtensions",
795
- "allowUmdGlobalAccess",
796
- /* JavaScript Support */
797
- "allowJs",
798
- "checkJs",
799
- "maxNodeModuleJsDepth",
800
- /* Type Checking */
801
- "strict",
802
- "strictBindCallApply",
803
- "strictFunctionTypes",
804
- "strictNullChecks",
805
- "strictPropertyInitialization",
806
- "allowUnreachableCode",
807
- "allowUnusedLabels",
808
- "alwaysStrict",
809
- "exactOptionalPropertyTypes",
810
- "noFallthroughCasesInSwitch",
811
- "noImplicitAny",
812
- "noImplicitOverride",
813
- "noImplicitReturns",
814
- "noImplicitThis",
815
- "noPropertyAccessFromIndexSignature",
816
- "noUncheckedIndexedAccess",
817
- "noUnusedLocals",
818
- "noUnusedParameters",
819
- "useUnknownInCatchVariables",
820
- /* Emit */
821
- "declaration",
822
- "declarationDir",
823
- "declarationMap",
824
- "downlevelIteration",
825
- "emitBOM",
826
- "emitDeclarationOnly",
827
- "importHelpers",
828
- "importsNotUsedAsValues",
829
- "inlineSourceMap",
830
- "inlineSources",
831
- "mapRoot",
832
- "newLine",
833
- "noEmit",
834
- "noEmitHelpers",
835
- "noEmitOnError",
836
- "outDir",
837
- "outFile",
838
- "preserveConstEnums",
839
- "preserveValueImports",
840
- "removeComments",
841
- "sourceMap",
842
- "sourceRoot",
843
- "stripInternal",
844
- /* Interop Constraints */
845
- "allowSyntheticDefaultImports",
846
- "esModuleInterop",
847
- "forceConsistentCasingInFileNames",
848
- "isolatedDeclarations",
849
- "isolatedModules",
850
- "preserveSymlinks",
851
- "verbatimModuleSyntax",
852
- /* Completeness */
853
- "skipDefaultLibCheck",
854
- "skipLibCheck"
855
- ],
856
- pathPattern: "^compilerOptions$"
872
+ internalPattern: ["~/**", "@/**", "#**"],
873
+ newlinesBetween: "ignore",
874
+ order: "asc",
875
+ type: "natural"
857
876
  }
877
+ ],
878
+ "perfectionist/sort-named-exports": [
879
+ "warn",
880
+ { groupKind: "values-first", order: "asc", type: "natural" }
881
+ ],
882
+ "perfectionist/sort-named-imports": [
883
+ "warn",
884
+ { groupKind: "values-first", order: "asc", type: "natural" }
858
885
  ]
859
886
  }
860
887
  }
861
888
  ];
862
889
  }
863
890
 
864
- // src/configs/stylistic.ts
865
- var StylisticConfigDefaults = {
866
- indent: 2,
867
- jsx: true,
868
- quotes: "single",
869
- semi: false
870
- };
871
- async function stylistic(options = {}) {
872
- const {
873
- indent,
874
- jsx: jsx2,
875
- overrides = {},
876
- quotes,
877
- semi
878
- } = {
879
- ...StylisticConfigDefaults,
880
- ...options
881
- };
882
- const pluginStylistic = await interopDefault(
883
- import("@stylistic/eslint-plugin")
884
- );
885
- const config = pluginStylistic.configs.customize({
886
- flat: true,
887
- indent,
888
- jsx: jsx2,
889
- pluginName: "style",
890
- quotes,
891
- semi
892
- });
893
- return [
894
- {
895
- name: "coderwyd/stylistic/rules",
896
- plugins: {
897
- antfu: default2,
898
- style: pluginStylistic
899
- },
900
- rules: {
901
- ...config.rules,
902
- "antfu/consistent-list-newline": "error",
903
- "antfu/curly": "error",
904
- "antfu/if-newline": "warn",
905
- "antfu/top-level-function": "warn",
906
- ...overrides
907
- }
908
- }
909
- ];
910
- }
911
-
912
- // src/configs/typescript.ts
913
- import process2 from "node:process";
914
- async function typescript(options = {}) {
915
- const { componentExts = [], overrides = {}, overridesTypeAware = {}, parserOptions = {} } = options;
916
- const files = options.files ?? [
917
- GLOB_TS,
918
- GLOB_TSX,
919
- ...componentExts.map((ext) => `**/*.${ext}`)
920
- ];
921
- const filesTypeAware = options.filesTypeAware ?? [GLOB_TS, GLOB_TSX];
922
- const ignoresTypeAware = options.ignoresTypeAware ?? [
923
- `${GLOB_MARKDOWN}/**`,
924
- GLOB_ASTRO_TS
925
- ];
926
- const tsconfigPath = options.tsconfigPath;
927
- const isTypeAware = !!tsconfigPath;
928
- const typeAwareRules = {
929
- "dot-notation": "off",
930
- "no-implied-eval": "off",
931
- "ts/await-thenable": "error",
932
- "ts/dot-notation": ["error", { allowKeywords: true }],
933
- "ts/no-floating-promises": "error",
934
- "ts/no-for-in-array": "error",
935
- "ts/no-implied-eval": "error",
936
- "ts/no-misused-promises": "error",
937
- "ts/no-unnecessary-type-assertion": "error",
938
- "ts/no-unsafe-argument": "error",
939
- "ts/no-unsafe-assignment": "error",
940
- "ts/no-unsafe-call": "error",
941
- "ts/no-unsafe-member-access": "error",
942
- "ts/no-unsafe-return": "error",
943
- "ts/promise-function-async": "error",
944
- "ts/restrict-plus-operands": "error",
945
- "ts/restrict-template-expressions": "error",
946
- "ts/return-await": "error",
947
- "ts/strict-boolean-expressions": "error",
948
- "ts/switch-exhaustiveness-check": "error",
949
- "ts/unbound-method": "error"
950
- };
951
- const [pluginTs, parserTs] = await Promise.all([
952
- interopDefault(import("@typescript-eslint/eslint-plugin")),
953
- interopDefault(import("@typescript-eslint/parser"))
954
- ]);
955
- function makeParser(typeAware, files2, ignores2) {
956
- return {
957
- files: files2,
958
- ...ignores2 ? { ignores: ignores2 } : {},
959
- languageOptions: {
960
- parser: parserTs,
961
- parserOptions: {
962
- extraFileExtensions: componentExts.map((ext) => `.${ext}`),
963
- sourceType: "module",
964
- ...typeAware ? {
965
- projectService: {
966
- allowDefaultProject: ["./*.js"],
967
- defaultProject: tsconfigPath
968
- },
969
- tsconfigRootDir: process2.cwd()
970
- } : {},
971
- ...parserOptions
972
- }
973
- },
974
- name: `coderwyd/typescript/${typeAware ? "type-aware-parser" : "parser"}`
975
- };
976
- }
977
- return [
978
- {
979
- // Install the plugins without globs, so they can be configured separately.
980
- name: "coderwyd/typescript/setup",
981
- plugins: {
982
- antfu: default2,
983
- ts: pluginTs
984
- }
985
- },
986
- // assign type-aware parser for type-aware files and type-unaware parser for the rest
987
- ...isTypeAware ? [
988
- makeParser(false, files),
989
- makeParser(true, filesTypeAware, ignoresTypeAware)
990
- ] : [makeParser(false, files)],
991
- {
992
- files,
993
- name: "coderwyd/typescript/rules",
994
- rules: {
995
- ...renameRules(
996
- pluginTs.configs["eslint-recommended"].overrides[0].rules,
997
- { "@typescript-eslint": "ts" }
998
- ),
999
- ...renameRules(pluginTs.configs.strict.rules, {
1000
- "@typescript-eslint": "ts"
1001
- }),
1002
- "no-dupe-class-members": "off",
1003
- "no-loss-of-precision": "off",
1004
- "no-redeclare": "off",
1005
- "no-use-before-define": "off",
1006
- "no-useless-constructor": "off",
1007
- "ts/ban-ts-comment": [
1008
- "error",
1009
- { "ts-expect-error": "allow-with-description" }
1010
- ],
1011
- "ts/consistent-type-definitions": ["error", "interface"],
1012
- "ts/consistent-type-imports": [
1013
- "error",
1014
- { disallowTypeAnnotations: false, prefer: "type-imports" }
1015
- ],
1016
- "ts/method-signature-style": ["error", "property"],
1017
- // https://www.totaltypescript.com/method-shorthand-syntax-considered-harmful
1018
- "ts/no-dupe-class-members": "error",
1019
- "ts/no-dynamic-delete": "off",
1020
- "ts/no-empty-object-type": [
1021
- "error",
1022
- {
1023
- allowInterfaces: "with-single-extends",
1024
- // interface Derived extends Base {}
1025
- allowObjectTypes: "never",
1026
- allowWithName: "Props$"
1027
- }
1028
- ],
1029
- "ts/no-explicit-any": "off",
1030
- "ts/no-extraneous-class": "off",
1031
- "ts/no-import-type-side-effects": "error",
1032
- "ts/no-invalid-void-type": "off",
1033
- // this is deprecated
1034
- "ts/no-loss-of-precision": "off",
1035
- "ts/no-non-null-assertion": "off",
1036
- "ts/no-redeclare": "error",
1037
- "ts/no-require-imports": "error",
1038
- "ts/no-unused-vars": "off",
1039
- "ts/no-use-before-define": [
1040
- "error",
1041
- { classes: false, functions: false, variables: true }
1042
- ],
1043
- "ts/no-useless-constructor": "off",
1044
- "ts/no-wrapper-object-types": "error",
1045
- "ts/triple-slash-reference": "off",
1046
- "ts/unified-signatures": "off",
1047
- ...overrides
1048
- }
1049
- },
1050
- ...isTypeAware ? [
1051
- {
1052
- files: filesTypeAware,
1053
- ignores: ignoresTypeAware,
1054
- name: "coderwyd/typescript/rules-type-aware",
1055
- rules: {
1056
- ...typeAwareRules,
1057
- ...overridesTypeAware
1058
- }
1059
- }
1060
- ] : [],
1061
- {
1062
- files: [GLOB_DTS],
1063
- name: "coderwyd/typescript/disables/dts",
1064
- rules: {
1065
- "eslint-comments/no-unlimited-disable": "off",
1066
- "import/no-duplicates": "off",
1067
- "no-restricted-syntax": "off",
1068
- "unused-imports/no-unused-vars": "off"
1069
- }
1070
- },
1071
- {
1072
- files: ["**/*.{test,spec}.ts?(x)"],
1073
- name: "coderwyd/typescript/disables/test",
1074
- rules: {
1075
- "no-unused-expressions": "off"
1076
- }
1077
- },
1078
- {
1079
- files: ["**/*.js", "**/*.cjs"],
1080
- name: "coderwyd/typescript/disables/cjs",
1081
- rules: {
1082
- "ts/no-require-imports": "off",
1083
- "ts/no-var-requires": "off"
1084
- }
1085
- }
1086
- ];
1087
- }
891
+ // src/configs/react.ts
892
+ import { isPackageExists as isPackageExists3 } from "local-pkg";
1088
893
 
1089
- // src/configs/unicorn.ts
1090
- function unicorn() {
1091
- return [
1092
- {
1093
- name: "coderwyd/unicorn/rules",
1094
- plugins: {
1095
- unicorn: default5
1096
- },
1097
- rules: {
1098
- // 'unicorn/better-regex': 'error',
1099
- "unicorn/catch-error-name": "error",
1100
- "unicorn/consistent-empty-array-spread": "error",
1101
- "unicorn/custom-error-definition": "error",
1102
- "unicorn/error-message": "error",
1103
- // 'unicorn/explicit-length-check': 'error',
1104
- // 'unicorn/filename-case': [
1105
- // 'error',
1106
- // {
1107
- // cases: { kebabCase: true, pascalCase: true },
1108
- // ignore: [/^[A-Z]+\..*$/],
1109
- // },
1110
- "unicorn/escape-case": "error",
1111
- // ],
1112
- "unicorn/new-for-builtins": "error",
1113
- // 'unicorn/no-array-callback-reference': 'error',
1114
- "unicorn/no-array-method-this-argument": "error",
1115
- "unicorn/no-array-push-push": "error",
1116
- "unicorn/no-await-in-promise-methods": "error",
1117
- "unicorn/no-console-spaces": "error",
1118
- "unicorn/no-for-loop": "error",
1119
- "unicorn/no-hex-escape": "error",
1120
- "unicorn/no-instanceof-array": "error",
1121
- "unicorn/no-invalid-remove-event-listener": "error",
1122
- "unicorn/no-length-as-slice-end": "error",
1123
- "unicorn/no-lonely-if": "error",
1124
- "unicorn/no-new-array": "error",
1125
- "unicorn/no-new-buffer": "error",
1126
- "unicorn/no-single-promise-in-promise-methods": "error",
1127
- "unicorn/no-static-only-class": "error",
1128
- "unicorn/no-unnecessary-await": "error",
1129
- "unicorn/no-zero-fractions": `error`,
1130
- "unicorn/prefer-add-event-listener": "error",
1131
- "unicorn/prefer-array-find": "error",
1132
- "unicorn/prefer-array-flat-map": "error",
1133
- "unicorn/prefer-array-index-of": "error",
1134
- "unicorn/prefer-array-some": "error",
1135
- "unicorn/prefer-at": "error",
1136
- "unicorn/prefer-blob-reading-methods": "error",
1137
- "unicorn/prefer-date-now": "error",
1138
- "unicorn/prefer-dom-node-append": "error",
1139
- "unicorn/prefer-dom-node-dataset": "error",
1140
- "unicorn/prefer-dom-node-remove": "error",
1141
- "unicorn/prefer-dom-node-text-content": "error",
1142
- "unicorn/prefer-includes": "error",
1143
- "unicorn/prefer-keyboard-event-key": "error",
1144
- "unicorn/prefer-math-trunc": "error",
1145
- "unicorn/prefer-modern-dom-apis": "error",
1146
- "unicorn/prefer-modern-math-apis": "error",
1147
- "unicorn/prefer-negative-index": "error",
1148
- "unicorn/prefer-node-protocol": "error",
1149
- "unicorn/prefer-number-properties": "error",
1150
- "unicorn/prefer-optional-catch-binding": "error",
1151
- "unicorn/prefer-prototype-methods": "error",
1152
- "unicorn/prefer-query-selector": "error",
1153
- "unicorn/prefer-reflect-apply": "error",
1154
- // 'unicorn/prefer-regexp-test': 'error',
1155
- "unicorn/prefer-string-replace-all": "error",
1156
- "unicorn/prefer-string-slice": "error",
1157
- "unicorn/prefer-string-starts-ends-with": "error",
1158
- "unicorn/prefer-string-trim-start-end": "error",
1159
- // top level await is not supported in all environments
1160
- // 'unicorn/prefer-top-level-await': 'error',
1161
- "unicorn/prefer-type-error": "error",
1162
- "unicorn/throw-new-error": "error"
1163
- }
1164
- }
1165
- ];
894
+ // src/env.ts
895
+ import process2 from "node:process";
896
+ import { isPackageExists as isPackageExists2 } from "local-pkg";
897
+ var isInEditor = !!((process2.env.VSCODE_PID || process2.env.VSCODE_CWD || process2.env.JETBRAINS_IDE || process2.env.VIM || process2.env.NVIM) && !process2.env.CI);
898
+ var hasTypeScript = isPackageExists2("typescript");
899
+ var VueJsPackages = [
900
+ "vue",
901
+ "nuxt",
902
+ "vitepress",
903
+ "@slidev/cli"
904
+ ];
905
+ var hasVue = hasPackages(VueJsPackages);
906
+ var RemixPackages = [
907
+ "@remix-run/node",
908
+ "@remix-run/react",
909
+ "@remix-run/serve",
910
+ "@remix-run/dev"
911
+ ];
912
+ var NextJsPackages = ["next"];
913
+ var isUsingRemix = hasPackages(RemixPackages);
914
+ var isUsingNext = hasPackages(NextJsPackages);
915
+ function hasPackages(packages) {
916
+ return packages.some((name) => isPackageExists2(name));
1166
917
  }
1167
918
 
1168
- // src/configs/vue.ts
1169
- import { mergeProcessors } from "eslint-merge-processors";
1170
- async function vue(options = {}) {
1171
- const { files = [GLOB_VUE], overrides = {}, stylistic: stylistic2 = true } = options;
1172
- const sfcBlocks = options.sfcBlocks === true ? {} : options.sfcBlocks ?? {};
1173
- const { indent = 2 } = typeof stylistic2 === "boolean" ? {} : stylistic2;
1174
- const [pluginVue, parserVue, processorVueBlocks] = await Promise.all([
1175
- interopDefault(import("eslint-plugin-vue")),
1176
- interopDefault(import("vue-eslint-parser")),
1177
- interopDefault(import("eslint-processor-vue-blocks"))
919
+ // src/configs/react.ts
920
+ var ReactRefreshAllowConstantExportPackages = ["vite"];
921
+ async function react(options = {}) {
922
+ const { files = [GLOB_SRC], overrides = {} } = options;
923
+ await ensurePackages([
924
+ "@eslint-react/eslint-plugin",
925
+ "eslint-plugin-react-hooks",
926
+ "eslint-plugin-react-refresh"
1178
927
  ]);
1179
- const isVue3 = getVueVersion() === 3;
1180
- const configKeys = isVue3 ? ["vue3-essential", "vue3-strongly-recommended", "vue3-recommended"] : ["essential", "strongly-recommended", "recommended"];
1181
- const vueRules = configKeys.reduce((preRules, key) => {
1182
- const config = pluginVue.configs[key];
1183
- return {
1184
- ...preRules,
1185
- ...config.rules
1186
- };
1187
- }, {});
928
+ const tsconfigPath = options?.tsconfigPath ? toArray(options.tsconfigPath) : void 0;
929
+ const isTypeAware = !!tsconfigPath;
930
+ const [pluginReact, pluginReactHooks, pluginReactRefresh, parserTs] = await Promise.all([
931
+ interopDefault(import("@eslint-react/eslint-plugin")),
932
+ interopDefault(import("eslint-plugin-react-hooks")),
933
+ interopDefault(import("eslint-plugin-react-refresh")),
934
+ interopDefault(import("@typescript-eslint/parser"))
935
+ ]);
936
+ const isAllowConstantExport = ReactRefreshAllowConstantExportPackages.some(
937
+ (i) => isPackageExists3(i)
938
+ );
939
+ const plugins = pluginReact.configs.all.plugins;
1188
940
  return [
1189
941
  {
1190
- // This allows Vue plugin to work with auto imports
1191
- // https://github.com/vuejs/eslint-plugin-vue/pull/2422
1192
- languageOptions: {
1193
- globals: {
1194
- computed: "readonly",
1195
- defineEmits: "readonly",
1196
- defineExpose: "readonly",
1197
- defineProps: "readonly",
1198
- onMounted: "readonly",
1199
- onUnmounted: "readonly",
1200
- reactive: "readonly",
1201
- ref: "readonly",
1202
- shallowReactive: "readonly",
1203
- shallowRef: "readonly",
1204
- toRef: "readonly",
1205
- toRefs: "readonly",
1206
- watch: "readonly",
1207
- watchEffect: "readonly"
1208
- }
1209
- },
1210
- name: "coderwyd/vue/setup",
942
+ name: "coderwyd/react/setup",
1211
943
  plugins: {
1212
- vue: pluginVue
944
+ "react": plugins["@eslint-react"],
945
+ "react-dom": plugins["@eslint-react/dom"],
946
+ "react-hooks": pluginReactHooks,
947
+ "react-hooks-extra": plugins["@eslint-react/hooks-extra"],
948
+ "react-naming-convention": plugins["@eslint-react/naming-convention"],
949
+ "react-refresh": pluginReactRefresh
1213
950
  }
1214
951
  },
1215
952
  {
1216
953
  files,
1217
954
  languageOptions: {
1218
- parser: parserVue,
955
+ parser: parserTs,
1219
956
  parserOptions: {
1220
957
  ecmaFeatures: {
1221
958
  jsx: true
1222
959
  },
1223
- extraFileExtensions: [".vue"],
1224
- parser: options.typescript ? await interopDefault(
1225
- import("@typescript-eslint/parser")
1226
- ) : null,
1227
- sourceType: "module"
1228
- }
960
+ ...isTypeAware ? { project: tsconfigPath } : {}
961
+ },
962
+ sourceType: "module"
1229
963
  },
1230
- name: "coderwyd/vue/rules",
1231
- processor: sfcBlocks === false ? pluginVue.processors[".vue"] : mergeProcessors([
1232
- pluginVue.processors[".vue"],
1233
- processorVueBlocks({
1234
- ...sfcBlocks,
1235
- blocks: {
1236
- styles: true,
1237
- ...sfcBlocks.blocks
1238
- }
1239
- })
1240
- ]),
1241
- rules: {
1242
- ...pluginVue.configs.base.rules,
1243
- ...vueRules,
1244
- "node/prefer-global/process": "off",
1245
- "vue/block-order": [
1246
- "error",
1247
- {
1248
- order: isVue3 ? ["script", "template", "style"] : ["template", "script", "style"]
1249
- }
1250
- ],
1251
- // 'vue/component-api-style': ['warn', ['script-setup', 'composition']],
1252
- "vue/component-name-in-template-casing": ["error", "PascalCase"],
1253
- "vue/component-options-name-casing": ["error", "PascalCase"],
1254
- // this is deprecated
1255
- "vue/component-tags-order": "off",
1256
- "vue/custom-event-name-casing": ["error", "camelCase"],
1257
- // 'vue/define-emits-declaration': ['warn', 'type-based'],
1258
- "vue/define-macros-order": [
1259
- "error",
1260
- {
1261
- order: [
1262
- "defineOptions",
1263
- "defineProps",
1264
- "defineEmits",
1265
- "defineSlots"
1266
- ]
1267
- }
1268
- ],
1269
- // 'vue/define-props-declaration': ['warn', 'type-based'],
1270
- "vue/dot-location": ["error", "property"],
1271
- "vue/dot-notation": ["error", { allowKeywords: true }],
1272
- "vue/eqeqeq": ["error", "smart"],
1273
- "vue/html-indent": ["error", indent],
1274
- "vue/html-quotes": ["error", "double"],
1275
- "vue/html-self-closing": [
1276
- "error",
1277
- {
1278
- html: {
1279
- component: "always",
1280
- normal: "always",
1281
- void: "any"
1282
- },
1283
- math: "always",
1284
- svg: "always"
1285
- }
1286
- ],
1287
- "vue/max-attributes-per-line": "off",
1288
- "vue/multi-word-component-names": "off",
1289
- // 'vue/next-tick-style': ['warn', 'promise'],
1290
- "vue/no-constant-condition": "warn",
1291
- "vue/no-dupe-keys": "off",
1292
- "vue/no-duplicate-attr-inheritance": "warn",
1293
- "vue/no-empty-pattern": "error",
1294
- "vue/no-extra-parens": ["error", "functions"],
1295
- "vue/no-irregular-whitespace": "error",
1296
- "vue/no-loss-of-precision": "error",
1297
- "vue/no-required-prop-with-default": "warn",
1298
- "vue/no-restricted-syntax": [
1299
- "error",
1300
- "DebuggerStatement",
1301
- "LabeledStatement",
1302
- "WithStatement"
1303
- ],
1304
- "vue/no-restricted-v-bind": ["error", "/^v-/"],
1305
- "vue/no-setup-props-reactivity-loss": "off",
1306
- "vue/no-sparse-arrays": "error",
1307
- "vue/no-unsupported-features": "warn",
1308
- "vue/no-unused-emit-declarations": "warn",
1309
- "vue/no-unused-refs": "error",
1310
- "vue/no-use-v-else-with-v-for": "error",
1311
- "vue/no-useless-mustaches": "warn",
1312
- "vue/no-useless-v-bind": "error",
1313
- "vue/no-v-html": "off",
1314
- "vue/no-v-text": "warn",
1315
- "vue/object-shorthand": [
1316
- "error",
1317
- "always",
1318
- {
1319
- avoidQuotes: true,
1320
- ignoreConstructors: false
1321
- }
1322
- ],
1323
- "vue/prefer-define-options": "warn",
1324
- "vue/prefer-separate-static-class": "error",
1325
- "vue/prefer-template": "error",
1326
- "vue/prop-name-casing": ["error", "camelCase"],
1327
- "vue/require-default-prop": "off",
1328
- "vue/require-macro-variable-name": [
1329
- "warn",
1330
- {
1331
- defineEmits: "emit",
1332
- defineProps: "props",
1333
- defineSlots: "slots",
1334
- useAttrs: "attrs",
1335
- useSlots: "slots"
1336
- }
1337
- ],
1338
- "vue/require-prop-types": "off",
1339
- // 'vue/singleline-html-element-content-newline': 'off',
1340
- "vue/space-infix-ops": "error",
1341
- "vue/space-unary-ops": ["error", { nonwords: false, words: true }],
1342
- "vue/valid-define-options": "warn",
1343
- ...stylistic2 ? {
1344
- "vue/array-bracket-spacing": ["error", "never"],
1345
- "vue/arrow-spacing": ["error", { after: true, before: true }],
1346
- "vue/block-spacing": ["error", "always"],
1347
- "vue/block-tag-newline": [
1348
- "error",
1349
- {
1350
- multiline: "always",
1351
- singleline: "always"
1352
- }
1353
- ],
1354
- "vue/brace-style": [
1355
- "error",
1356
- "stroustrup",
1357
- { allowSingleLine: true }
1358
- ],
1359
- "vue/comma-dangle": ["error", "always-multiline"],
1360
- "vue/comma-spacing": ["error", { after: true, before: false }],
1361
- "vue/comma-style": ["error", "last"],
1362
- "vue/html-comment-content-newline": "warn",
1363
- "vue/html-comment-content-spacing": [
1364
- "error",
1365
- "always",
1366
- {
1367
- exceptions: ["-"]
1368
- }
1369
- ],
1370
- "vue/key-spacing": [
1371
- "error",
1372
- { afterColon: true, beforeColon: false }
1373
- ],
1374
- "vue/keyword-spacing": ["error", { after: true, before: true }],
1375
- "vue/object-curly-newline": "off",
1376
- "vue/object-curly-spacing": ["error", "always"],
1377
- "vue/object-property-newline": [
1378
- "error",
1379
- { allowMultiplePropertiesPerLine: true }
1380
- ],
1381
- "vue/operator-linebreak": ["error", "before"],
1382
- "vue/padding-line-between-blocks": ["error", "always"],
1383
- "vue/quote-props": ["error", "consistent-as-needed"],
1384
- "vue/space-in-parens": ["error", "never"],
1385
- "vue/template-curly-spacing": "error"
964
+ name: "coderwyd/react/rules",
965
+ rules: {
966
+ // recommended rules from @eslint-react/dom
967
+ "react-dom/no-children-in-void-dom-elements": "warn",
968
+ "react-dom/no-dangerously-set-innerhtml": "warn",
969
+ "react-dom/no-dangerously-set-innerhtml-with-children": "error",
970
+ "react-dom/no-find-dom-node": "error",
971
+ "react-dom/no-missing-button-type": "warn",
972
+ "react-dom/no-missing-iframe-sandbox": "warn",
973
+ "react-dom/no-namespace": "error",
974
+ "react-dom/no-render-return-value": "error",
975
+ "react-dom/no-script-url": "warn",
976
+ "react-dom/no-unsafe-iframe-sandbox": "warn",
977
+ "react-dom/no-unsafe-target-blank": "warn",
978
+ // recommended rules react-hooks
979
+ "react-hooks/exhaustive-deps": "warn",
980
+ "react-hooks/rules-of-hooks": "error",
981
+ // react refresh
982
+ "react-refresh/only-export-components": [
983
+ "warn",
984
+ {
985
+ allowConstantExport: isAllowConstantExport,
986
+ allowExportNames: [
987
+ ...isUsingNext ? [
988
+ "config",
989
+ "generateStaticParams",
990
+ "metadata",
991
+ "generateMetadata",
992
+ "viewport",
993
+ "generateViewport"
994
+ ] : [],
995
+ ...isUsingRemix ? ["meta", "links", "headers", "loader", "action"] : []
996
+ ]
997
+ }
998
+ ],
999
+ // recommended rules from @eslint-react
1000
+ "react/ensure-forward-ref-using-ref": "warn",
1001
+ "react/no-access-state-in-setstate": "error",
1002
+ "react/no-array-index-key": "warn",
1003
+ "react/no-children-count": "warn",
1004
+ "react/no-children-for-each": "warn",
1005
+ "react/no-children-map": "warn",
1006
+ "react/no-children-only": "warn",
1007
+ "react/no-children-prop": "warn",
1008
+ "react/no-children-to-array": "warn",
1009
+ "react/no-clone-element": "warn",
1010
+ "react/no-comment-textnodes": "warn",
1011
+ "react/no-component-will-mount": "error",
1012
+ "react/no-component-will-receive-props": "error",
1013
+ "react/no-component-will-update": "error",
1014
+ "react/no-create-ref": "error",
1015
+ "react/no-direct-mutation-state": "error",
1016
+ "react/no-duplicate-key": "error",
1017
+ "react/no-implicit-key": "error",
1018
+ "react/no-missing-key": "error",
1019
+ "react/no-nested-components": "warn",
1020
+ "react/no-redundant-should-component-update": "error",
1021
+ "react/no-set-state-in-component-did-mount": "warn",
1022
+ "react/no-set-state-in-component-did-update": "warn",
1023
+ "react/no-set-state-in-component-will-update": "warn",
1024
+ "react/no-string-refs": "error",
1025
+ "react/no-unsafe-component-will-mount": "warn",
1026
+ "react/no-unsafe-component-will-receive-props": "warn",
1027
+ "react/no-unsafe-component-will-update": "warn",
1028
+ "react/no-unstable-context-value": "error",
1029
+ "react/no-unstable-default-props": "error",
1030
+ "react/no-unused-class-component-members": "warn",
1031
+ "react/no-unused-state": "warn",
1032
+ "react/no-useless-fragment": "warn",
1033
+ "react/prefer-destructuring-assignment": "warn",
1034
+ "react/prefer-shorthand-boolean": "warn",
1035
+ "react/prefer-shorthand-fragment": "warn",
1036
+ ...isTypeAware ? {
1037
+ "react/no-leaked-conditional-rendering": "warn"
1386
1038
  } : {},
1039
+ // overrides
1387
1040
  ...overrides
1388
1041
  }
1389
1042
  }
1390
1043
  ];
1391
1044
  }
1392
1045
 
1393
- // src/configs/test.ts
1394
- var _pluginTest;
1395
- async function test(options = {}) {
1396
- const { files = GLOB_TESTS, isInEditor: isInEditor2 = false, overrides = {} } = options;
1397
- const [pluginVitest, pluginNoOnlyTests] = await Promise.all([
1398
- interopDefault(import("@vitest/eslint-plugin")),
1399
- // @ts-expect-error missing types
1400
- interopDefault(import("eslint-plugin-no-only-tests"))
1401
- ]);
1402
- _pluginTest = _pluginTest || {
1403
- ...pluginVitest,
1404
- rules: {
1405
- ...pluginVitest.rules,
1406
- // extend `test/no-only-tests` rule
1407
- ...pluginNoOnlyTests.rules
1408
- }
1046
+ // src/configs/regexp.ts
1047
+ import { configs } from "eslint-plugin-regexp";
1048
+ function regexp(options = {}) {
1049
+ const config = configs["flat/recommended"];
1050
+ const rules = {
1051
+ ...config.rules
1409
1052
  };
1053
+ if (options.level === "warn") {
1054
+ Object.keys(rules).forEach((key) => {
1055
+ if (rules[key] === "error")
1056
+ rules[key] = "warn";
1057
+ });
1058
+ }
1410
1059
  return [
1411
1060
  {
1412
- name: "coderwyd/test/setup",
1413
- plugins: {
1414
- test: _pluginTest
1061
+ ...config,
1062
+ name: "coderwyd/regexp/rules",
1063
+ rules: {
1064
+ ...rules,
1065
+ ...options.overrides
1415
1066
  }
1416
- },
1067
+ }
1068
+ ];
1069
+ }
1070
+
1071
+ // src/configs/sort.ts
1072
+ function sortPackageJson() {
1073
+ return [
1417
1074
  {
1418
- files,
1419
- name: "coderwyd/test/rules",
1075
+ files: ["**/package.json"],
1076
+ name: "coderwyd/sort/package-json",
1420
1077
  rules: {
1421
- "node/prefer-global/process": "off",
1422
- "test/consistent-test-it": [
1078
+ "jsonc/sort-array-values": [
1423
1079
  "error",
1424
- { fn: "it", withinDescribe: "it" }
1080
+ {
1081
+ order: { type: "asc" },
1082
+ pathPattern: "^files$"
1083
+ }
1425
1084
  ],
1426
- "test/no-identical-title": "error",
1427
- "test/no-import-node-test": "error",
1428
- "test/no-only-tests": isInEditor2 ? "off" : "error",
1429
- "test/prefer-hooks-in-order": "error",
1430
- "test/prefer-lowercase-title": "error",
1431
- "ts/explicit-function-return-type": "off",
1432
- ...overrides
1085
+ "jsonc/sort-keys": [
1086
+ "error",
1087
+ {
1088
+ order: [
1089
+ "publisher",
1090
+ "name",
1091
+ "displayName",
1092
+ "type",
1093
+ "version",
1094
+ "private",
1095
+ "packageManager",
1096
+ "description",
1097
+ "author",
1098
+ "license",
1099
+ "funding",
1100
+ "homepage",
1101
+ "repository",
1102
+ "bugs",
1103
+ "keywords",
1104
+ "categories",
1105
+ "sideEffects",
1106
+ "exports",
1107
+ "main",
1108
+ "module",
1109
+ "unpkg",
1110
+ "jsdelivr",
1111
+ "types",
1112
+ "typesVersions",
1113
+ "bin",
1114
+ "icon",
1115
+ "files",
1116
+ "engines",
1117
+ "activationEvents",
1118
+ "contributes",
1119
+ "scripts",
1120
+ "peerDependencies",
1121
+ "peerDependenciesMeta",
1122
+ "dependencies",
1123
+ "optionalDependencies",
1124
+ "devDependencies",
1125
+ "pnpm",
1126
+ "overrides",
1127
+ "resolutions",
1128
+ "husky",
1129
+ "simple-git-hooks",
1130
+ "lint-staged",
1131
+ "eslintConfig"
1132
+ ],
1133
+ pathPattern: "^$"
1134
+ },
1135
+ {
1136
+ order: { type: "asc" },
1137
+ pathPattern: "^(?:dev|peer|optional|bundled)?[Dd]ependencies(Meta)?$"
1138
+ },
1139
+ {
1140
+ order: { type: "asc" },
1141
+ pathPattern: "^(?:resolutions|overrides|pnpm.overrides)$"
1142
+ },
1143
+ {
1144
+ order: ["types", "import", "require", "default"],
1145
+ pathPattern: "^exports.*$"
1146
+ },
1147
+ {
1148
+ order: [
1149
+ // client hooks only
1150
+ "pre-commit",
1151
+ "prepare-commit-msg",
1152
+ "commit-msg",
1153
+ "post-commit",
1154
+ "pre-rebase",
1155
+ "post-rewrite",
1156
+ "post-checkout",
1157
+ "post-merge",
1158
+ "pre-push",
1159
+ "pre-auto-gc"
1160
+ ],
1161
+ pathPattern: "^(?:gitHooks|husky|simple-git-hooks)$"
1162
+ }
1163
+ ]
1433
1164
  }
1434
1165
  }
1435
1166
  ];
1436
1167
  }
1437
-
1438
- // src/configs/perfectionist.ts
1439
- function perfectionist() {
1168
+ function sortTsconfig() {
1440
1169
  return [
1441
1170
  {
1442
- name: "coderwyd/perfectionist/rules",
1443
- plugins: {
1444
- perfectionist: default7
1445
- },
1171
+ files: ["**/tsconfig.json", "**/tsconfig.*.json"],
1172
+ name: "coderwyd/sort/tsconfig-json",
1446
1173
  rules: {
1447
- "perfectionist/sort-imports": [
1448
- "warn",
1174
+ "jsonc/sort-keys": [
1175
+ "error",
1449
1176
  {
1450
- groups: [
1451
- "builtin",
1452
- "external",
1453
- "internal",
1454
- "internal-type",
1455
- "parent",
1456
- "parent-type",
1457
- "sibling",
1458
- "sibling-type",
1459
- "index",
1460
- "index-type",
1461
- "object",
1462
- "type",
1463
- "side-effect",
1464
- "side-effect-style"
1177
+ order: [
1178
+ "extends",
1179
+ "compilerOptions",
1180
+ "references",
1181
+ "files",
1182
+ "include",
1183
+ "exclude"
1184
+ ],
1185
+ pathPattern: "^$"
1186
+ },
1187
+ {
1188
+ order: [
1189
+ /* Projects */
1190
+ "incremental",
1191
+ "composite",
1192
+ "tsBuildInfoFile",
1193
+ "disableSourceOfProjectReferenceRedirect",
1194
+ "disableSolutionSearching",
1195
+ "disableReferencedProjectLoad",
1196
+ /* Language and Environment */
1197
+ "target",
1198
+ "jsx",
1199
+ "jsxFactory",
1200
+ "jsxFragmentFactory",
1201
+ "jsxImportSource",
1202
+ "lib",
1203
+ "moduleDetection",
1204
+ "noLib",
1205
+ "reactNamespace",
1206
+ "useDefineForClassFields",
1207
+ "emitDecoratorMetadata",
1208
+ "experimentalDecorators",
1209
+ /* Modules */
1210
+ "baseUrl",
1211
+ "rootDir",
1212
+ "rootDirs",
1213
+ "customConditions",
1214
+ "module",
1215
+ "moduleResolution",
1216
+ "moduleSuffixes",
1217
+ "noResolve",
1218
+ "paths",
1219
+ "resolveJsonModule",
1220
+ "resolvePackageJsonExports",
1221
+ "resolvePackageJsonImports",
1222
+ "typeRoots",
1223
+ "types",
1224
+ "allowArbitraryExtensions",
1225
+ "allowImportingTsExtensions",
1226
+ "allowUmdGlobalAccess",
1227
+ /* JavaScript Support */
1228
+ "allowJs",
1229
+ "checkJs",
1230
+ "maxNodeModuleJsDepth",
1231
+ /* Type Checking */
1232
+ "strict",
1233
+ "strictBindCallApply",
1234
+ "strictFunctionTypes",
1235
+ "strictNullChecks",
1236
+ "strictPropertyInitialization",
1237
+ "allowUnreachableCode",
1238
+ "allowUnusedLabels",
1239
+ "alwaysStrict",
1240
+ "exactOptionalPropertyTypes",
1241
+ "noFallthroughCasesInSwitch",
1242
+ "noImplicitAny",
1243
+ "noImplicitOverride",
1244
+ "noImplicitReturns",
1245
+ "noImplicitThis",
1246
+ "noPropertyAccessFromIndexSignature",
1247
+ "noUncheckedIndexedAccess",
1248
+ "noUnusedLocals",
1249
+ "noUnusedParameters",
1250
+ "useUnknownInCatchVariables",
1251
+ /* Emit */
1252
+ "declaration",
1253
+ "declarationDir",
1254
+ "declarationMap",
1255
+ "downlevelIteration",
1256
+ "emitBOM",
1257
+ "emitDeclarationOnly",
1258
+ "importHelpers",
1259
+ "importsNotUsedAsValues",
1260
+ "inlineSourceMap",
1261
+ "inlineSources",
1262
+ "mapRoot",
1263
+ "newLine",
1264
+ "noEmit",
1265
+ "noEmitHelpers",
1266
+ "noEmitOnError",
1267
+ "outDir",
1268
+ "outFile",
1269
+ "preserveConstEnums",
1270
+ "preserveValueImports",
1271
+ "removeComments",
1272
+ "sourceMap",
1273
+ "sourceRoot",
1274
+ "stripInternal",
1275
+ /* Interop Constraints */
1276
+ "allowSyntheticDefaultImports",
1277
+ "esModuleInterop",
1278
+ "forceConsistentCasingInFileNames",
1279
+ "isolatedDeclarations",
1280
+ "isolatedModules",
1281
+ "preserveSymlinks",
1282
+ "verbatimModuleSyntax",
1283
+ /* Completeness */
1284
+ "skipDefaultLibCheck",
1285
+ "skipLibCheck"
1465
1286
  ],
1466
- internalPattern: ["~/**", "@/**", "#**"],
1467
- newlinesBetween: "ignore"
1287
+ pathPattern: "^compilerOptions$"
1468
1288
  }
1469
- ],
1470
- "perfectionist/sort-named-exports": [
1471
- "warn",
1472
- { groupKind: "values-first" }
1473
- ],
1474
- "perfectionist/sort-named-imports": [
1475
- "warn",
1476
- { groupKind: "values-first" }
1477
1289
  ]
1478
1290
  }
1479
1291
  }
1480
1292
  ];
1481
1293
  }
1482
1294
 
1483
- // src/configs/react.ts
1484
- import { isPackageExists as isPackageExists3 } from "local-pkg";
1485
-
1486
- // src/env.ts
1487
- import process3 from "node:process";
1488
- import { isPackageExists as isPackageExists2 } from "local-pkg";
1489
- var isInEditor = !!((process3.env.VSCODE_PID || process3.env.VSCODE_CWD || process3.env.JETBRAINS_IDE || process3.env.VIM || process3.env.NVIM) && !process3.env.CI);
1490
- var hasTypeScript = isPackageExists2("typescript");
1491
- var VueJsPackages = [
1492
- "vue",
1493
- "nuxt",
1494
- "vitepress",
1495
- "@slidev/cli"
1496
- ];
1497
- var hasVue = hasPackages(VueJsPackages);
1498
- var RemixPackages = [
1499
- "@remix-run/node",
1500
- "@remix-run/react",
1501
- "@remix-run/serve",
1502
- "@remix-run/dev"
1503
- ];
1504
- var NextJsPackages = ["next"];
1505
- var isUsingRemix = hasPackages(RemixPackages);
1506
- var isUsingNext = hasPackages(NextJsPackages);
1507
- function hasPackages(packages) {
1508
- return packages.some((name) => isPackageExists2(name));
1509
- }
1510
-
1511
- // src/configs/react.ts
1512
- var ReactRefreshAllowConstantExportPackages = ["vite"];
1513
- async function react(options = {}) {
1514
- const { files = [GLOB_SRC], overrides = {} } = options;
1515
- await ensurePackages([
1516
- "@eslint-react/eslint-plugin",
1517
- "eslint-plugin-react-hooks",
1518
- "eslint-plugin-react-refresh"
1519
- ]);
1520
- const tsconfigPath = options?.tsconfigPath ? toArray(options.tsconfigPath) : void 0;
1521
- const isTypeAware = !!tsconfigPath;
1522
- const [pluginReact, pluginReactHooks, pluginReactRefresh, parserTs] = await Promise.all([
1523
- interopDefault(import("@eslint-react/eslint-plugin")),
1524
- interopDefault(import("eslint-plugin-react-hooks")),
1525
- interopDefault(import("eslint-plugin-react-refresh")),
1526
- interopDefault(import("@typescript-eslint/parser"))
1295
+ // src/configs/svelte.ts
1296
+ async function svelte(options = {}) {
1297
+ const { files = [GLOB_SVELTE], overrides = {}, stylistic: stylistic2 = true } = options;
1298
+ const {
1299
+ indent = 2,
1300
+ quotes = "single"
1301
+ } = typeof stylistic2 === "boolean" ? {} : stylistic2;
1302
+ await ensurePackages(["eslint-plugin-svelte"]);
1303
+ const [pluginSvelte, parserSvelte] = await Promise.all([
1304
+ interopDefault(import("eslint-plugin-svelte")),
1305
+ interopDefault(import("svelte-eslint-parser"))
1527
1306
  ]);
1528
- const isAllowConstantExport = ReactRefreshAllowConstantExportPackages.some(
1529
- (i) => isPackageExists3(i)
1530
- );
1531
- const plugins = pluginReact.configs.all.plugins;
1532
1307
  return [
1533
1308
  {
1534
- name: "coderwyd/react/setup",
1309
+ name: "coderwyd/svelte/setup",
1535
1310
  plugins: {
1536
- "react": plugins["@eslint-react"],
1537
- "react-dom": plugins["@eslint-react/dom"],
1538
- "react-hooks": pluginReactHooks,
1539
- "react-hooks-extra": plugins["@eslint-react/hooks-extra"],
1540
- "react-naming-convention": plugins["@eslint-react/naming-convention"],
1541
- "react-refresh": pluginReactRefresh
1311
+ svelte: pluginSvelte
1542
1312
  }
1543
1313
  },
1544
1314
  {
1545
1315
  files,
1546
1316
  languageOptions: {
1547
- parser: parserTs,
1317
+ parser: parserSvelte,
1548
1318
  parserOptions: {
1549
- ecmaFeatures: {
1550
- jsx: true
1551
- },
1552
- ...isTypeAware ? { project: tsconfigPath } : {}
1553
- },
1554
- sourceType: "module"
1319
+ extraFileExtensions: [".svelte"],
1320
+ parser: options.typescript ? await interopDefault(
1321
+ import("@typescript-eslint/parser")
1322
+ ) : null
1323
+ }
1555
1324
  },
1556
- name: "coderwyd/react/rules",
1325
+ name: "coderwyd/svelte/rules",
1326
+ processor: pluginSvelte.processors[".svelte"],
1557
1327
  rules: {
1558
- // recommended rules from @eslint-react/dom
1559
- "react-dom/no-children-in-void-dom-elements": "warn",
1560
- "react-dom/no-dangerously-set-innerhtml": "warn",
1561
- "react-dom/no-dangerously-set-innerhtml-with-children": "error",
1562
- "react-dom/no-find-dom-node": "error",
1563
- "react-dom/no-missing-button-type": "warn",
1564
- "react-dom/no-missing-iframe-sandbox": "warn",
1565
- "react-dom/no-namespace": "error",
1566
- "react-dom/no-render-return-value": "error",
1567
- "react-dom/no-script-url": "warn",
1568
- "react-dom/no-unsafe-iframe-sandbox": "warn",
1569
- "react-dom/no-unsafe-target-blank": "warn",
1570
- // recommended rules react-hooks
1571
- "react-hooks/exhaustive-deps": "warn",
1572
- "react-hooks/rules-of-hooks": "error",
1573
- // react refresh
1574
- "react-refresh/only-export-components": [
1575
- "warn",
1576
- {
1577
- allowConstantExport: isAllowConstantExport,
1578
- allowExportNames: [
1579
- ...isUsingNext ? [
1580
- "config",
1581
- "generateStaticParams",
1582
- "metadata",
1583
- "generateMetadata",
1584
- "viewport",
1585
- "generateViewport"
1586
- ] : [],
1587
- ...isUsingRemix ? ["meta", "links", "headers", "loader", "action"] : []
1588
- ]
1589
- }
1590
- ],
1591
- // recommended rules from @eslint-react
1592
- "react/ensure-forward-ref-using-ref": "warn",
1593
- "react/no-access-state-in-setstate": "error",
1594
- "react/no-array-index-key": "warn",
1595
- "react/no-children-count": "warn",
1596
- "react/no-children-for-each": "warn",
1597
- "react/no-children-map": "warn",
1598
- "react/no-children-only": "warn",
1599
- "react/no-children-prop": "warn",
1600
- "react/no-children-to-array": "warn",
1601
- "react/no-clone-element": "warn",
1602
- "react/no-comment-textnodes": "warn",
1603
- "react/no-component-will-mount": "error",
1604
- "react/no-component-will-receive-props": "error",
1605
- "react/no-component-will-update": "error",
1606
- "react/no-create-ref": "error",
1607
- "react/no-direct-mutation-state": "error",
1608
- "react/no-duplicate-key": "error",
1609
- "react/no-implicit-key": "error",
1610
- "react/no-missing-key": "error",
1611
- "react/no-nested-components": "warn",
1612
- "react/no-redundant-should-component-update": "error",
1613
- "react/no-set-state-in-component-did-mount": "warn",
1614
- "react/no-set-state-in-component-did-update": "warn",
1615
- "react/no-set-state-in-component-will-update": "warn",
1616
- "react/no-string-refs": "error",
1617
- "react/no-unsafe-component-will-mount": "warn",
1618
- "react/no-unsafe-component-will-receive-props": "warn",
1619
- "react/no-unsafe-component-will-update": "warn",
1620
- "react/no-unstable-context-value": "error",
1621
- "react/no-unstable-default-props": "error",
1622
- "react/no-unused-class-component-members": "warn",
1623
- "react/no-unused-state": "warn",
1624
- "react/no-useless-fragment": "warn",
1625
- "react/prefer-destructuring-assignment": "warn",
1626
- "react/prefer-shorthand-boolean": "warn",
1627
- "react/prefer-shorthand-fragment": "warn",
1628
- ...isTypeAware ? {
1629
- "react/no-leaked-conditional-rendering": "warn"
1328
+ "import/no-mutable-exports": "off",
1329
+ "no-undef": "off",
1330
+ // incompatible with most recent (attribute-form) generic types RFC
1331
+ "no-unused-vars": [
1332
+ "error",
1333
+ {
1334
+ args: "none",
1335
+ caughtErrors: "none",
1336
+ ignoreRestSiblings: true,
1337
+ vars: "all",
1338
+ varsIgnorePattern: "^(\\$\\$Props$|\\$\\$Events$|\\$\\$Slots$)"
1339
+ }
1340
+ ],
1341
+ "svelte/comment-directive": "error",
1342
+ "svelte/no-at-debug-tags": "warn",
1343
+ "svelte/no-at-html-tags": "error",
1344
+ "svelte/no-dupe-else-if-blocks": "error",
1345
+ "svelte/no-dupe-style-properties": "error",
1346
+ "svelte/no-dupe-use-directives": "error",
1347
+ "svelte/no-dynamic-slot-name": "error",
1348
+ "svelte/no-export-load-in-svelte-module-in-kit-pages": "error",
1349
+ "svelte/no-inner-declarations": "error",
1350
+ "svelte/no-not-function-handler": "error",
1351
+ "svelte/no-object-in-text-mustaches": "error",
1352
+ "svelte/no-reactive-functions": "error",
1353
+ "svelte/no-reactive-literals": "error",
1354
+ "svelte/no-shorthand-style-property-overrides": "error",
1355
+ "svelte/no-unknown-style-directive-property": "error",
1356
+ "svelte/no-unused-svelte-ignore": "error",
1357
+ "svelte/no-useless-mustaches": "error",
1358
+ "svelte/require-store-callbacks-use-set-param": "error",
1359
+ "svelte/system": "error",
1360
+ "svelte/valid-each-key": "error",
1361
+ "unused-imports/no-unused-vars": [
1362
+ "error",
1363
+ {
1364
+ args: "after-used",
1365
+ argsIgnorePattern: "^_",
1366
+ vars: "all",
1367
+ varsIgnorePattern: "^(_|\\$\\$Props$|\\$\\$Events$|\\$\\$Slots$)"
1368
+ }
1369
+ ],
1370
+ ...stylistic2 ? {
1371
+ "style/indent": "off",
1372
+ // superseded by svelte/indent
1373
+ "style/no-trailing-spaces": "off",
1374
+ // superseded by svelte/no-trailing-spaces
1375
+ "svelte/derived-has-same-inputs-outputs": "error",
1376
+ "svelte/html-closing-bracket-spacing": "error",
1377
+ "svelte/html-quotes": ["error", { prefer: quotes }],
1378
+ "svelte/indent": [
1379
+ "error",
1380
+ { alignAttributesVertically: true, indent }
1381
+ ],
1382
+ "svelte/mustache-spacing": "error",
1383
+ "svelte/no-spaces-around-equal-signs-in-attribute": "error",
1384
+ "svelte/no-trailing-spaces": "error",
1385
+ "svelte/spaced-html-comment": "error"
1630
1386
  } : {},
1631
- // overrides
1632
1387
  ...overrides
1633
1388
  }
1634
1389
  }
1635
1390
  ];
1636
1391
  }
1637
1392
 
1638
- // src/configs/unocss.ts
1639
- async function unocss(options = {}) {
1640
- const { attributify = true, strict = false } = options;
1641
- await ensurePackages(["@unocss/eslint-plugin"]);
1642
- const [pluginUnoCSS] = await Promise.all([
1643
- interopDefault(import("@unocss/eslint-plugin"))
1644
- ]);
1393
+ // src/configs/tailwindcss.ts
1394
+ async function tailwindcss(options = {}) {
1395
+ const { overrides } = options;
1396
+ await ensurePackages(["eslint-plugin-tailwindcss"]);
1397
+ const pluginTailwindcss = await interopDefault(
1398
+ import("eslint-plugin-tailwindcss")
1399
+ );
1645
1400
  return [
1646
1401
  {
1647
- name: "coderwyd/unocss/rules",
1402
+ name: "coderwyd/tailwindcss/rules",
1648
1403
  plugins: {
1649
- unocss: pluginUnoCSS
1404
+ tailwindcss: pluginTailwindcss
1650
1405
  },
1651
1406
  rules: {
1652
- "unocss/order": "warn",
1653
- ...attributify ? {
1654
- "unocss/order-attributify": "warn"
1655
- } : {},
1656
- ...strict ? {
1657
- "unocss/blocklist": "error"
1658
- } : {}
1407
+ "tailwindcss/classnames-order": "warn",
1408
+ "tailwindcss/enforces-negative-arbitrary-values": "warn",
1409
+ "tailwindcss/enforces-shorthand": "warn",
1410
+ "tailwindcss/migration-from-tailwind-2": "warn",
1411
+ "tailwindcss/no-arbitrary-value": "off",
1412
+ "tailwindcss/no-contradicting-classname": "warn",
1413
+ "tailwindcss/no-custom-classname": "off",
1414
+ "tailwindcss/no-unnecessary-arbitrary-value": "warn",
1415
+ ...overrides
1659
1416
  }
1660
1417
  }
1661
1418
  ];
1662
1419
  }
1663
1420
 
1664
- // src/configs/formatter.ts
1665
- async function formatter(options = {}, stylistic2 = {}) {
1666
- const { css, graphql, html, markdown, toml, yaml } = options === true ? {
1667
- css: true,
1668
- graphql: true,
1669
- html: true,
1670
- markdown: true,
1671
- toml: true,
1672
- yaml: true
1673
- } : options;
1674
- const { indent, quotes, semi } = {
1675
- ...StylisticConfigDefaults,
1676
- ...stylistic2
1421
+ // src/configs/test.ts
1422
+ var _pluginTest;
1423
+ async function test(options = {}) {
1424
+ const { files = GLOB_TESTS, isInEditor: isInEditor2 = false, overrides = {} } = options;
1425
+ const [pluginVitest, pluginNoOnlyTests] = await Promise.all([
1426
+ interopDefault(import("@vitest/eslint-plugin")),
1427
+ // @ts-expect-error missing types
1428
+ interopDefault(import("eslint-plugin-no-only-tests"))
1429
+ ]);
1430
+ _pluginTest = _pluginTest || {
1431
+ ...pluginVitest,
1432
+ rules: {
1433
+ ...pluginVitest.rules,
1434
+ // extend `test/no-only-tests` rule
1435
+ ...pluginNoOnlyTests.rules
1436
+ }
1677
1437
  };
1678
- const prettierOptions = Object.assign(
1438
+ return [
1679
1439
  {
1680
- endOfLine: "auto",
1681
- printWidth: 80,
1682
- semi,
1683
- singleQuote: quotes === "single",
1684
- tabWidth: typeof indent === "number" ? indent : 2,
1685
- trailingComma: "all",
1686
- useTabs: indent === "tab"
1687
- },
1688
- typeof options === "boolean" ? {} : options.prettierOptions || {}
1689
- );
1690
- await ensurePackages(["eslint-plugin-format"]);
1691
- const pluginFormat = await interopDefault(import("eslint-plugin-format"));
1692
- function createPrettierFormatter(files, parser, plugins) {
1693
- const rules = {
1694
- ...prettierOptions,
1695
- parser
1696
- };
1697
- const markdownRules = {
1698
- printWidth: 120,
1699
- ...rules,
1700
- embeddedLanguageFormatting: "off"
1701
- };
1702
- if (plugins?.length)
1703
- rules.plugins = [...rules.plugins || [], ...plugins];
1704
- const config = {
1705
- files,
1706
- languageOptions: {
1707
- parser: parserPlain
1708
- },
1709
- name: `coderwyd/formatter/${parser}`,
1440
+ name: "coderwyd/test/setup",
1710
1441
  plugins: {
1711
- format: pluginFormat
1712
- },
1713
- rules: {
1714
- "format/prettier": [
1715
- "warn",
1716
- parser === "markdown" ? markdownRules : rules
1717
- ]
1442
+ test: _pluginTest
1718
1443
  }
1719
- };
1720
- return config;
1721
- }
1722
- const configs2 = [
1444
+ },
1723
1445
  {
1724
- name: "coderwyd/formatter/setup",
1725
- plugins: {
1726
- format: pluginFormat
1446
+ files,
1447
+ name: "coderwyd/test/rules",
1448
+ rules: {
1449
+ "node/prefer-global/process": "off",
1450
+ "test/consistent-test-it": [
1451
+ "error",
1452
+ { fn: "it", withinDescribe: "it" }
1453
+ ],
1454
+ "test/no-identical-title": "error",
1455
+ "test/no-import-node-test": "error",
1456
+ "test/no-only-tests": isInEditor2 ? "off" : "error",
1457
+ "test/prefer-hooks-in-order": "error",
1458
+ "test/prefer-lowercase-title": "error",
1459
+ "ts/explicit-function-return-type": "off",
1460
+ ...overrides
1727
1461
  }
1728
1462
  }
1729
1463
  ];
1730
- if (html) {
1731
- const htmlConfig = createPrettierFormatter([GLOB_HTML], "html");
1732
- configs2.push(htmlConfig);
1733
- }
1734
- if (css) {
1735
- const cssConfig = createPrettierFormatter([GLOB_CSS, GLOB_POSTCSS], "css");
1736
- const scssConfig = createPrettierFormatter([GLOB_SCSS], "scss");
1737
- const lessConfig = createPrettierFormatter([GLOB_LESS], "less");
1738
- configs2.push(cssConfig, scssConfig, lessConfig);
1739
- }
1740
- if (markdown) {
1741
- const markdownConfig = createPrettierFormatter([GLOB_MARKDOWN], "markdown");
1742
- configs2.push(markdownConfig);
1743
- }
1744
- if (graphql) {
1745
- const graphqlConfig = createPrettierFormatter([GLOB_GRAPHQL], "graphql");
1746
- configs2.push(graphqlConfig);
1747
- }
1748
- if (yaml) {
1749
- const yamlConfig = createPrettierFormatter([GLOB_YAML], "yaml");
1750
- configs2.push(yamlConfig);
1751
- }
1752
- if (toml) {
1753
- await ensurePackages(["@toml-tools/parser", "prettier-plugin-toml"]);
1754
- const tomlConfig = createPrettierFormatter([GLOB_TOML], "toml", [
1755
- "prettier-plugin-toml"
1756
- ]);
1757
- configs2.push(tomlConfig);
1758
- }
1759
- return configs2;
1760
1464
  }
1761
1465
 
1762
- // src/configs/svelte.ts
1763
- async function svelte(options = {}) {
1764
- const { files = [GLOB_SVELTE], overrides = {}, stylistic: stylistic2 = true } = options;
1765
- const {
1766
- indent = 2,
1767
- quotes = "single"
1768
- } = typeof stylistic2 === "boolean" ? {} : stylistic2;
1769
- await ensurePackages(["eslint-plugin-svelte"]);
1770
- const [pluginSvelte, parserSvelte] = await Promise.all([
1771
- interopDefault(import("eslint-plugin-svelte")),
1772
- interopDefault(import("svelte-eslint-parser"))
1466
+ // src/configs/typescript.ts
1467
+ import process3 from "node:process";
1468
+ async function typescript(options = {}) {
1469
+ const { componentExts = [], overrides = {}, overridesTypeAware = {}, parserOptions = {} } = options;
1470
+ const files = options.files ?? [
1471
+ GLOB_TS,
1472
+ GLOB_TSX,
1473
+ ...componentExts.map((ext) => `**/*.${ext}`)
1474
+ ];
1475
+ const filesTypeAware = options.filesTypeAware ?? [GLOB_TS, GLOB_TSX];
1476
+ const ignoresTypeAware = options.ignoresTypeAware ?? [
1477
+ `${GLOB_MARKDOWN}/**`,
1478
+ GLOB_ASTRO_TS
1479
+ ];
1480
+ const tsconfigPath = options.tsconfigPath;
1481
+ const isTypeAware = !!tsconfigPath;
1482
+ const typeAwareRules = {
1483
+ "dot-notation": "off",
1484
+ "no-implied-eval": "off",
1485
+ "ts/await-thenable": "error",
1486
+ "ts/dot-notation": ["error", { allowKeywords: true }],
1487
+ "ts/no-floating-promises": "error",
1488
+ "ts/no-for-in-array": "error",
1489
+ "ts/no-implied-eval": "error",
1490
+ "ts/no-misused-promises": "error",
1491
+ "ts/no-unnecessary-type-assertion": "error",
1492
+ "ts/no-unsafe-argument": "error",
1493
+ "ts/no-unsafe-assignment": "error",
1494
+ "ts/no-unsafe-call": "error",
1495
+ "ts/no-unsafe-member-access": "error",
1496
+ "ts/no-unsafe-return": "error",
1497
+ "ts/promise-function-async": "error",
1498
+ "ts/restrict-plus-operands": "error",
1499
+ "ts/restrict-template-expressions": "error",
1500
+ "ts/return-await": "error",
1501
+ "ts/strict-boolean-expressions": "error",
1502
+ "ts/switch-exhaustiveness-check": "error",
1503
+ "ts/unbound-method": "error"
1504
+ };
1505
+ const [pluginTs, parserTs] = await Promise.all([
1506
+ interopDefault(import("@typescript-eslint/eslint-plugin")),
1507
+ interopDefault(import("@typescript-eslint/parser"))
1773
1508
  ]);
1509
+ function makeParser(typeAware, files2, ignores2) {
1510
+ return {
1511
+ files: files2,
1512
+ ...ignores2 ? { ignores: ignores2 } : {},
1513
+ languageOptions: {
1514
+ parser: parserTs,
1515
+ parserOptions: {
1516
+ extraFileExtensions: componentExts.map((ext) => `.${ext}`),
1517
+ sourceType: "module",
1518
+ ...typeAware ? {
1519
+ projectService: {
1520
+ allowDefaultProject: ["./*.js"],
1521
+ defaultProject: tsconfigPath
1522
+ },
1523
+ tsconfigRootDir: process3.cwd()
1524
+ } : {},
1525
+ ...parserOptions
1526
+ }
1527
+ },
1528
+ name: `coderwyd/typescript/${typeAware ? "type-aware-parser" : "parser"}`
1529
+ };
1530
+ }
1774
1531
  return [
1775
1532
  {
1776
- name: "coderwyd/svelte/setup",
1533
+ // Install the plugins without globs, so they can be configured separately.
1534
+ name: "coderwyd/typescript/setup",
1777
1535
  plugins: {
1778
- svelte: pluginSvelte
1536
+ antfu: default3,
1537
+ ts: pluginTs
1779
1538
  }
1780
1539
  },
1540
+ // assign type-aware parser for type-aware files and type-unaware parser for the rest
1541
+ ...isTypeAware ? [
1542
+ makeParser(false, files),
1543
+ makeParser(true, filesTypeAware, ignoresTypeAware)
1544
+ ] : [makeParser(false, files)],
1781
1545
  {
1782
1546
  files,
1783
- languageOptions: {
1784
- parser: parserSvelte,
1785
- parserOptions: {
1786
- extraFileExtensions: [".svelte"],
1787
- parser: options.typescript ? await interopDefault(
1788
- import("@typescript-eslint/parser")
1789
- ) : null
1790
- }
1791
- },
1792
- name: "coderwyd/svelte/rules",
1793
- processor: pluginSvelte.processors[".svelte"],
1547
+ name: "coderwyd/typescript/rules",
1794
1548
  rules: {
1795
- "import/no-mutable-exports": "off",
1796
- "no-undef": "off",
1797
- // incompatible with most recent (attribute-form) generic types RFC
1798
- "no-unused-vars": [
1549
+ ...renameRules(
1550
+ pluginTs.configs["eslint-recommended"].overrides[0].rules,
1551
+ { "@typescript-eslint": "ts" }
1552
+ ),
1553
+ ...renameRules(pluginTs.configs.strict.rules, {
1554
+ "@typescript-eslint": "ts"
1555
+ }),
1556
+ "no-dupe-class-members": "off",
1557
+ "no-redeclare": "off",
1558
+ "no-use-before-define": "off",
1559
+ "no-useless-constructor": "off",
1560
+ "ts/ban-ts-comment": [
1799
1561
  "error",
1800
- {
1801
- args: "none",
1802
- caughtErrors: "none",
1803
- ignoreRestSiblings: true,
1804
- vars: "all",
1805
- varsIgnorePattern: "^(\\$\\$Props$|\\$\\$Events$|\\$\\$Slots$)"
1806
- }
1562
+ { "ts-expect-error": "allow-with-description" }
1807
1563
  ],
1808
- "svelte/comment-directive": "error",
1809
- "svelte/no-at-debug-tags": "warn",
1810
- "svelte/no-at-html-tags": "error",
1811
- "svelte/no-dupe-else-if-blocks": "error",
1812
- "svelte/no-dupe-style-properties": "error",
1813
- "svelte/no-dupe-use-directives": "error",
1814
- "svelte/no-dynamic-slot-name": "error",
1815
- "svelte/no-export-load-in-svelte-module-in-kit-pages": "error",
1816
- "svelte/no-inner-declarations": "error",
1817
- "svelte/no-not-function-handler": "error",
1818
- "svelte/no-object-in-text-mustaches": "error",
1819
- "svelte/no-reactive-functions": "error",
1820
- "svelte/no-reactive-literals": "error",
1821
- "svelte/no-shorthand-style-property-overrides": "error",
1822
- "svelte/no-unknown-style-directive-property": "error",
1823
- "svelte/no-unused-svelte-ignore": "error",
1824
- "svelte/no-useless-mustaches": "error",
1825
- "svelte/require-store-callbacks-use-set-param": "error",
1826
- "svelte/system": "error",
1827
- "svelte/valid-each-key": "error",
1828
- "unused-imports/no-unused-vars": [
1564
+ "ts/consistent-type-definitions": ["error", "interface"],
1565
+ "ts/consistent-type-imports": [
1566
+ "error",
1567
+ { disallowTypeAnnotations: false, prefer: "type-imports" }
1568
+ ],
1569
+ "ts/method-signature-style": ["error", "property"],
1570
+ // https://www.totaltypescript.com/method-shorthand-syntax-considered-harmful
1571
+ "ts/no-dupe-class-members": "error",
1572
+ "ts/no-dynamic-delete": "off",
1573
+ "ts/no-empty-object-type": [
1829
1574
  "error",
1830
1575
  {
1831
- args: "after-used",
1832
- argsIgnorePattern: "^_",
1833
- vars: "all",
1834
- varsIgnorePattern: "^(_|\\$\\$Props$|\\$\\$Events$|\\$\\$Slots$)"
1576
+ allowInterfaces: "with-single-extends",
1577
+ // interface Derived extends Base {}
1578
+ allowObjectTypes: "never",
1579
+ allowWithName: "Props$"
1835
1580
  }
1836
1581
  ],
1837
- ...stylistic2 ? {
1838
- "style/indent": "off",
1839
- // superseded by svelte/indent
1840
- "style/no-trailing-spaces": "off",
1841
- // superseded by svelte/no-trailing-spaces
1842
- "svelte/derived-has-same-inputs-outputs": "error",
1843
- "svelte/html-closing-bracket-spacing": "error",
1844
- "svelte/html-quotes": ["error", { prefer: quotes }],
1845
- "svelte/indent": [
1846
- "error",
1847
- { alignAttributesVertically: true, indent }
1848
- ],
1849
- "svelte/mustache-spacing": "error",
1850
- "svelte/no-spaces-around-equal-signs-in-attribute": "error",
1851
- "svelte/no-trailing-spaces": "error",
1852
- "svelte/spaced-html-comment": "error"
1853
- } : {},
1582
+ "ts/no-explicit-any": "off",
1583
+ "ts/no-extraneous-class": "off",
1584
+ "ts/no-import-type-side-effects": "error",
1585
+ "ts/no-invalid-void-type": "off",
1586
+ "ts/no-non-null-assertion": "off",
1587
+ "ts/no-redeclare": "error",
1588
+ "ts/no-require-imports": "error",
1589
+ "ts/no-unused-vars": "off",
1590
+ "ts/no-use-before-define": [
1591
+ "error",
1592
+ { classes: false, functions: false, variables: true }
1593
+ ],
1594
+ "ts/no-useless-constructor": "off",
1595
+ "ts/no-wrapper-object-types": "error",
1596
+ "ts/triple-slash-reference": "off",
1597
+ "ts/unified-signatures": "off",
1854
1598
  ...overrides
1855
1599
  }
1856
- }
1600
+ },
1601
+ ...isTypeAware ? [
1602
+ {
1603
+ files: filesTypeAware,
1604
+ ignores: ignoresTypeAware,
1605
+ name: "coderwyd/typescript/rules-type-aware",
1606
+ rules: {
1607
+ ...typeAwareRules,
1608
+ ...overridesTypeAware
1609
+ }
1610
+ }
1611
+ ] : []
1857
1612
  ];
1858
1613
  }
1859
1614
 
1860
- // src/configs/tailwindcss.ts
1861
- async function tailwindcss(options = {}) {
1862
- const { overrides } = options;
1863
- await ensurePackages(["eslint-plugin-tailwindcss"]);
1864
- const pluginTailwindcss = await interopDefault(
1865
- import("eslint-plugin-tailwindcss")
1866
- );
1615
+ // src/configs/unicorn.ts
1616
+ function unicorn() {
1867
1617
  return [
1868
1618
  {
1869
- name: "coderwyd/tailwindcss/rules",
1619
+ name: "coderwyd/unicorn/rules",
1870
1620
  plugins: {
1871
- tailwindcss: pluginTailwindcss
1621
+ unicorn: default6
1872
1622
  },
1873
1623
  rules: {
1874
- "tailwindcss/classnames-order": "warn",
1875
- "tailwindcss/enforces-negative-arbitrary-values": "warn",
1876
- "tailwindcss/enforces-shorthand": "warn",
1877
- "tailwindcss/migration-from-tailwind-2": "warn",
1878
- "tailwindcss/no-arbitrary-value": "off",
1879
- "tailwindcss/no-contradicting-classname": "warn",
1880
- "tailwindcss/no-custom-classname": "off",
1881
- "tailwindcss/no-unnecessary-arbitrary-value": "warn",
1882
- ...overrides
1883
- }
1884
- }
1885
- ];
1886
- }
1887
-
1888
- // src/configs/command.ts
1889
- import createCommand from "eslint-plugin-command/config";
1890
- function command() {
1891
- return [
1892
- {
1893
- ...createCommand(),
1894
- name: "coderwyd/command/rules"
1624
+ // 'unicorn/better-regex': 'error',
1625
+ "unicorn/catch-error-name": "error",
1626
+ "unicorn/consistent-empty-array-spread": "error",
1627
+ "unicorn/custom-error-definition": "error",
1628
+ "unicorn/error-message": "error",
1629
+ // 'unicorn/explicit-length-check': 'error',
1630
+ // 'unicorn/filename-case': [
1631
+ // 'error',
1632
+ // {
1633
+ // cases: { kebabCase: true, pascalCase: true },
1634
+ // ignore: [/^[A-Z]+\..*$/],
1635
+ // },
1636
+ "unicorn/escape-case": "error",
1637
+ // ],
1638
+ "unicorn/new-for-builtins": "error",
1639
+ // 'unicorn/no-array-callback-reference': 'error',
1640
+ "unicorn/no-array-method-this-argument": "error",
1641
+ "unicorn/no-array-push-push": "error",
1642
+ "unicorn/no-await-in-promise-methods": "error",
1643
+ "unicorn/no-console-spaces": "error",
1644
+ "unicorn/no-for-loop": "error",
1645
+ "unicorn/no-hex-escape": "error",
1646
+ "unicorn/no-instanceof-array": "error",
1647
+ "unicorn/no-invalid-remove-event-listener": "error",
1648
+ "unicorn/no-length-as-slice-end": "error",
1649
+ "unicorn/no-lonely-if": "error",
1650
+ "unicorn/no-new-array": "error",
1651
+ "unicorn/no-new-buffer": "error",
1652
+ "unicorn/no-single-promise-in-promise-methods": "error",
1653
+ "unicorn/no-static-only-class": "error",
1654
+ "unicorn/no-unnecessary-await": "error",
1655
+ "unicorn/no-zero-fractions": `error`,
1656
+ "unicorn/prefer-add-event-listener": "error",
1657
+ "unicorn/prefer-array-find": "error",
1658
+ "unicorn/prefer-array-flat-map": "error",
1659
+ "unicorn/prefer-array-index-of": "error",
1660
+ "unicorn/prefer-array-some": "error",
1661
+ "unicorn/prefer-at": "error",
1662
+ "unicorn/prefer-blob-reading-methods": "error",
1663
+ "unicorn/prefer-date-now": "error",
1664
+ "unicorn/prefer-dom-node-append": "error",
1665
+ "unicorn/prefer-dom-node-dataset": "error",
1666
+ "unicorn/prefer-dom-node-remove": "error",
1667
+ "unicorn/prefer-dom-node-text-content": "error",
1668
+ "unicorn/prefer-includes": "error",
1669
+ "unicorn/prefer-keyboard-event-key": "error",
1670
+ "unicorn/prefer-math-trunc": "error",
1671
+ "unicorn/prefer-modern-dom-apis": "error",
1672
+ "unicorn/prefer-modern-math-apis": "error",
1673
+ "unicorn/prefer-negative-index": "error",
1674
+ "unicorn/prefer-node-protocol": "error",
1675
+ "unicorn/prefer-number-properties": "error",
1676
+ "unicorn/prefer-optional-catch-binding": "error",
1677
+ "unicorn/prefer-prototype-methods": "error",
1678
+ "unicorn/prefer-query-selector": "error",
1679
+ "unicorn/prefer-reflect-apply": "error",
1680
+ // 'unicorn/prefer-regexp-test': 'error',
1681
+ "unicorn/prefer-string-replace-all": "error",
1682
+ "unicorn/prefer-string-slice": "error",
1683
+ "unicorn/prefer-string-starts-ends-with": "error",
1684
+ "unicorn/prefer-string-trim-start-end": "error",
1685
+ // top level await is not supported in all environments
1686
+ // 'unicorn/prefer-top-level-await': 'error',
1687
+ "unicorn/prefer-type-error": "error",
1688
+ "unicorn/throw-new-error": "error"
1689
+ }
1895
1690
  }
1896
1691
  ];
1897
1692
  }
1898
1693
 
1899
- // src/configs/regexp.ts
1900
- import { configs } from "eslint-plugin-regexp";
1901
- function regexp(options = {}) {
1902
- const config = configs["flat/recommended"];
1903
- const rules = {
1904
- ...config.rules
1905
- };
1906
- if (options.level === "warn") {
1907
- Object.keys(rules).forEach((key) => {
1908
- if (rules[key] === "error")
1909
- rules[key] = "warn";
1910
- });
1911
- }
1694
+ // src/configs/unocss.ts
1695
+ async function unocss(options = {}) {
1696
+ const { attributify = true, strict = false } = options;
1697
+ await ensurePackages(["@unocss/eslint-plugin"]);
1698
+ const [pluginUnoCSS] = await Promise.all([
1699
+ interopDefault(import("@unocss/eslint-plugin"))
1700
+ ]);
1912
1701
  return [
1913
1702
  {
1914
- ...config,
1915
- name: "coderwyd/regexp/rules",
1703
+ name: "coderwyd/unocss/rules",
1704
+ plugins: {
1705
+ unocss: pluginUnoCSS
1706
+ },
1916
1707
  rules: {
1917
- ...rules,
1918
- ...options.overrides
1708
+ "unocss/order": "warn",
1709
+ ...attributify ? {
1710
+ "unocss/order-attributify": "warn"
1711
+ } : {},
1712
+ ...strict ? {
1713
+ "unocss/blocklist": "error"
1714
+ } : {}
1919
1715
  }
1920
1716
  }
1921
1717
  ];
1922
1718
  }
1923
1719
 
1924
- // src/configs/jsx.ts
1925
- function jsx() {
1720
+ // src/configs/vue.ts
1721
+ import { mergeProcessors } from "eslint-merge-processors";
1722
+ async function vue(options = {}) {
1723
+ const { files = [GLOB_VUE], overrides = {}, stylistic: stylistic2 = true } = options;
1724
+ const sfcBlocks = options.sfcBlocks === true ? {} : options.sfcBlocks ?? {};
1725
+ const { indent = 2 } = typeof stylistic2 === "boolean" ? {} : stylistic2;
1726
+ const [pluginVue, parserVue, processorVueBlocks] = await Promise.all([
1727
+ interopDefault(import("eslint-plugin-vue")),
1728
+ interopDefault(import("vue-eslint-parser")),
1729
+ interopDefault(import("eslint-processor-vue-blocks"))
1730
+ ]);
1731
+ const isVue3 = getVueVersion() === 3;
1732
+ const configKeys = isVue3 ? ["vue3-essential", "vue3-strongly-recommended", "vue3-recommended"] : ["essential", "strongly-recommended", "recommended"];
1733
+ const vueRules = configKeys.reduce((preRules, key) => {
1734
+ const config = pluginVue.configs[key];
1735
+ return {
1736
+ ...preRules,
1737
+ ...config.rules
1738
+ };
1739
+ }, {});
1926
1740
  return [
1927
1741
  {
1928
- files: [GLOB_JSX, GLOB_TSX],
1742
+ // This allows Vue plugin to work with auto imports
1743
+ // https://github.com/vuejs/eslint-plugin-vue/pull/2422
1744
+ languageOptions: {
1745
+ globals: {
1746
+ computed: "readonly",
1747
+ defineEmits: "readonly",
1748
+ defineExpose: "readonly",
1749
+ defineProps: "readonly",
1750
+ onMounted: "readonly",
1751
+ onUnmounted: "readonly",
1752
+ reactive: "readonly",
1753
+ ref: "readonly",
1754
+ shallowReactive: "readonly",
1755
+ shallowRef: "readonly",
1756
+ toRef: "readonly",
1757
+ toRefs: "readonly",
1758
+ watch: "readonly",
1759
+ watchEffect: "readonly"
1760
+ }
1761
+ },
1762
+ name: "coderwyd/vue/setup",
1763
+ plugins: {
1764
+ vue: pluginVue
1765
+ }
1766
+ },
1767
+ {
1768
+ files,
1929
1769
  languageOptions: {
1770
+ parser: parserVue,
1930
1771
  parserOptions: {
1931
1772
  ecmaFeatures: {
1932
1773
  jsx: true
1933
- }
1774
+ },
1775
+ extraFileExtensions: [".vue"],
1776
+ parser: options.typescript ? await interopDefault(
1777
+ import("@typescript-eslint/parser")
1778
+ ) : null,
1779
+ sourceType: "module"
1934
1780
  }
1935
1781
  },
1936
- name: "coderwyd/jsx/setup"
1782
+ name: "coderwyd/vue/rules",
1783
+ processor: sfcBlocks === false ? pluginVue.processors[".vue"] : mergeProcessors([
1784
+ pluginVue.processors[".vue"],
1785
+ processorVueBlocks({
1786
+ ...sfcBlocks,
1787
+ blocks: {
1788
+ styles: true,
1789
+ ...sfcBlocks.blocks
1790
+ }
1791
+ })
1792
+ ]),
1793
+ rules: {
1794
+ ...pluginVue.configs.base.rules,
1795
+ ...vueRules,
1796
+ "node/prefer-global/process": "off",
1797
+ "vue/block-order": [
1798
+ "error",
1799
+ {
1800
+ order: isVue3 ? ["script", "template", "style"] : ["template", "script", "style"]
1801
+ }
1802
+ ],
1803
+ // 'vue/component-api-style': ['warn', ['script-setup', 'composition']],
1804
+ "vue/component-name-in-template-casing": ["error", "PascalCase"],
1805
+ "vue/component-options-name-casing": ["error", "PascalCase"],
1806
+ // this is deprecated
1807
+ "vue/component-tags-order": "off",
1808
+ "vue/custom-event-name-casing": ["error", "camelCase"],
1809
+ // 'vue/define-emits-declaration': ['warn', 'type-based'],
1810
+ "vue/define-macros-order": [
1811
+ "error",
1812
+ {
1813
+ order: [
1814
+ "defineOptions",
1815
+ "defineProps",
1816
+ "defineEmits",
1817
+ "defineSlots"
1818
+ ]
1819
+ }
1820
+ ],
1821
+ // 'vue/define-props-declaration': ['warn', 'type-based'],
1822
+ "vue/dot-location": ["error", "property"],
1823
+ "vue/dot-notation": ["error", { allowKeywords: true }],
1824
+ "vue/eqeqeq": ["error", "smart"],
1825
+ "vue/html-indent": ["error", indent],
1826
+ "vue/html-quotes": ["error", "double"],
1827
+ "vue/html-self-closing": [
1828
+ "error",
1829
+ {
1830
+ html: {
1831
+ component: "always",
1832
+ normal: "always",
1833
+ void: "any"
1834
+ },
1835
+ math: "always",
1836
+ svg: "always"
1837
+ }
1838
+ ],
1839
+ "vue/max-attributes-per-line": "off",
1840
+ "vue/multi-word-component-names": "off",
1841
+ // 'vue/next-tick-style': ['warn', 'promise'],
1842
+ "vue/no-constant-condition": "warn",
1843
+ "vue/no-dupe-keys": "off",
1844
+ "vue/no-duplicate-attr-inheritance": "warn",
1845
+ "vue/no-empty-pattern": "error",
1846
+ "vue/no-extra-parens": ["error", "functions"],
1847
+ "vue/no-irregular-whitespace": "error",
1848
+ "vue/no-loss-of-precision": "error",
1849
+ "vue/no-required-prop-with-default": "warn",
1850
+ "vue/no-restricted-syntax": [
1851
+ "error",
1852
+ "DebuggerStatement",
1853
+ "LabeledStatement",
1854
+ "WithStatement"
1855
+ ],
1856
+ "vue/no-restricted-v-bind": ["error", "/^v-/"],
1857
+ "vue/no-setup-props-reactivity-loss": "off",
1858
+ "vue/no-sparse-arrays": "error",
1859
+ "vue/no-unsupported-features": "warn",
1860
+ "vue/no-unused-emit-declarations": "warn",
1861
+ "vue/no-unused-refs": "error",
1862
+ "vue/no-use-v-else-with-v-for": "error",
1863
+ "vue/no-useless-mustaches": "warn",
1864
+ "vue/no-useless-v-bind": "error",
1865
+ "vue/no-v-html": "off",
1866
+ "vue/no-v-text": "warn",
1867
+ "vue/object-shorthand": [
1868
+ "error",
1869
+ "always",
1870
+ {
1871
+ avoidQuotes: true,
1872
+ ignoreConstructors: false
1873
+ }
1874
+ ],
1875
+ "vue/prefer-define-options": "warn",
1876
+ "vue/prefer-separate-static-class": "error",
1877
+ "vue/prefer-template": "error",
1878
+ "vue/prop-name-casing": ["error", "camelCase"],
1879
+ "vue/require-default-prop": "off",
1880
+ "vue/require-macro-variable-name": [
1881
+ "warn",
1882
+ {
1883
+ defineEmits: "emit",
1884
+ defineProps: "props",
1885
+ defineSlots: "slots",
1886
+ useAttrs: "attrs",
1887
+ useSlots: "slots"
1888
+ }
1889
+ ],
1890
+ "vue/require-prop-types": "off",
1891
+ // 'vue/singleline-html-element-content-newline': 'off',
1892
+ "vue/space-infix-ops": "error",
1893
+ "vue/space-unary-ops": ["error", { nonwords: false, words: true }],
1894
+ "vue/valid-define-options": "warn",
1895
+ ...stylistic2 ? {
1896
+ "vue/array-bracket-spacing": ["error", "never"],
1897
+ "vue/arrow-spacing": ["error", { after: true, before: true }],
1898
+ "vue/block-spacing": ["error", "always"],
1899
+ "vue/block-tag-newline": [
1900
+ "error",
1901
+ {
1902
+ multiline: "always",
1903
+ singleline: "always"
1904
+ }
1905
+ ],
1906
+ "vue/brace-style": [
1907
+ "error",
1908
+ "stroustrup",
1909
+ { allowSingleLine: true }
1910
+ ],
1911
+ "vue/comma-dangle": ["error", "always-multiline"],
1912
+ "vue/comma-spacing": ["error", { after: true, before: false }],
1913
+ "vue/comma-style": ["error", "last"],
1914
+ "vue/html-comment-content-newline": "warn",
1915
+ "vue/html-comment-content-spacing": [
1916
+ "error",
1917
+ "always",
1918
+ {
1919
+ exceptions: ["-"]
1920
+ }
1921
+ ],
1922
+ "vue/key-spacing": [
1923
+ "error",
1924
+ { afterColon: true, beforeColon: false }
1925
+ ],
1926
+ "vue/keyword-spacing": ["error", { after: true, before: true }],
1927
+ "vue/object-curly-newline": "off",
1928
+ "vue/object-curly-spacing": ["error", "always"],
1929
+ "vue/object-property-newline": [
1930
+ "error",
1931
+ { allowMultiplePropertiesPerLine: true }
1932
+ ],
1933
+ "vue/operator-linebreak": ["error", "before"],
1934
+ "vue/padding-line-between-blocks": ["error", "always"],
1935
+ "vue/quote-props": ["error", "consistent-as-needed"],
1936
+ "vue/space-in-parens": ["error", "never"],
1937
+ "vue/template-curly-spacing": "error"
1938
+ } : {},
1939
+ ...overrides
1940
+ }
1937
1941
  }
1938
1942
  ];
1939
1943
  }
@@ -2116,6 +2120,7 @@ async function defineConfig(options = {}, ...userConfigs) {
2116
2120
  )
2117
2121
  );
2118
2122
  }
2123
+ configs2.push(disables());
2119
2124
  if ("files" in options) {
2120
2125
  throw new Error('[@coderwyd/eslint-config] The first argument should not contain the "files" property as the options are supposed to be global. Place it in the second or later config instead.');
2121
2126
  }