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