@coderwyd/eslint-config 2.6.4 → 2.7.1

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