@unshared/eslint-config 0.0.20 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,196 +1,103 @@
1
1
  import pluginAntfu from "eslint-plugin-antfu";
2
2
  import eslintCommentsPlugin from "eslint-plugin-eslint-comments";
3
3
  import pluginJsdoc from "eslint-plugin-jsdoc";
4
- import jsonc from "eslint-plugin-jsonc";
4
+ import pluginJsonc from "eslint-plugin-jsonc";
5
5
  import nodePlugin from "eslint-plugin-n";
6
6
  import pluginSonarjs from "eslint-plugin-sonarjs";
7
7
  import javascript from "@eslint/js";
8
8
  import stylistic from "@stylistic/eslint-plugin";
9
9
  import { toArray } from "@unshared/collection/toArray";
10
10
  import perfectionist from "eslint-plugin-perfectionist";
11
- import { cwd } from "node:process";
12
11
  import tslint from "typescript-eslint";
13
12
  import unicornPlugin from "eslint-plugin-unicorn";
14
- import vitestPlugin from "eslint-plugin-vitest";
13
+ import vitestPlugin from "@vitest/eslint-plugin";
15
14
  import { mergeProcessors } from "eslint-merge-processors";
16
15
  import vuePlugin from "eslint-plugin-vue";
17
16
  import vueProcessorBlocks from "eslint-processor-vue-blocks";
18
17
  import vueParser from "vue-eslint-parser";
19
- function antfu(options) {
18
+ import pluginYml from "eslint-plugin-yml";
19
+ function antfu() {
20
20
  return [
21
21
  {
22
22
  plugins: {
23
23
  antfu: pluginAntfu
24
24
  },
25
25
  rules: {
26
+ // --- Enforce consistent line breaks for chaining member access.
27
+ "antfu/consistent-chaining": "error",
28
+ // --- Enforce consistent line breaks inside braces of object/array/named imports/exports and function parameters.
26
29
  "antfu/consistent-list-newline": "error",
27
- /**
28
- * Auto-fix import duplication. The TypeScript compiler already detects and removes
29
- * duplicate imports, but this rule can be used to fix the issue automatically in the editor.
30
- *
31
- * @see https://github.com/antfu/eslint-plugin-antfu/blob/main/src/rules/import-dedupe.md
32
- */
30
+ // --- Deduplicate imports.
33
31
  "antfu/import-dedupe": "error",
34
- /**
35
- * Enforce top-level function to be declared using function instead of arrow function. This
36
- * rule helps when you want to add additional overload signatures to a function without
37
- * having to transform the arrow function into a function declaration manually.
38
- *
39
- * On top of that, it mitigates the risk of accidentally using the `this` instance from
40
- * an outer scope.
41
- *
42
- * @see https://github.com/antfu/eslint-plugin-antfu/blob/main/src/rules/top-level-function.md
43
- */
44
- "antfu/top-level-function": "error",
45
- /**
46
- * Enforce consistent line breaks inside braces of object/array/named imports/exports and
47
- * function parameters. Reduces the cognitive load of reasoning about code style.
48
- *
49
- * @see https://github.com/antfu/eslint-plugin-antfu/blob/main/src/rules/consistent-list-newline.md
50
- */
51
- "object-curly-newline": "off",
52
- /** User-defined rules */
53
- ...options.rules
32
+ // --- Avoid importing from 'dist' directories.
33
+ "antfu/no-import-dist": "error",
34
+ // --- Enforce `export default` insteand of `export = {}`.
35
+ "antfu/no-ts-export-equal": "error",
36
+ // --- Enforce `function()` instead of `() => {}` for top-level functions.
37
+ "antfu/top-level-function": "error"
54
38
  }
55
39
  }
56
40
  ];
57
41
  }
58
- function eslintComments(options) {
42
+ function eslintComments() {
59
43
  return [
60
44
  {
61
45
  plugins: {
62
46
  "eslint-comments": eslintCommentsPlugin
63
47
  },
64
48
  rules: {
65
- /**
66
- * Allow multiple rules directive in a single comment. This
67
- * reduces the number of comments in the code.
68
- *
69
- * @see https://mysticatea.github.io/eslint-plugin-eslint-comments/rules/disable-enable-pair
70
- */
49
+ // --- Allow disable without having to enable again.
71
50
  "eslint-comments/disable-enable-pair": "off",
72
- /**
73
- * `eslint-enable` directive-comments can enable rules which are disabled by different
74
- * eslint-disable directive-comments. It can enable a rule unintentionally. This rule
75
- * will report such cases.
76
- *
77
- * @see https://mysticatea.github.io/eslint-plugin-eslint-comments/rules/no-aggregating-enable
78
- */
51
+ // --- Disallow eslint-disable comments without rule names. This ensures that we cannot
79
52
  "eslint-comments/no-aggregating-enable": "error",
80
- /**
81
- * Disallow duplicate eslint-disable comments. This rule will report when there are
82
- * multiple eslint-disable comments for the same rule, either in the same line or enabled
83
- * by different eslint-disable comments.
84
- *
85
- * @see https://mysticatea.github.io/eslint-plugin-eslint-comments/rules/no-duplicate-disable
86
- */
87
- "eslint-comments/no-duplicate-disable": "error",
88
- /**
89
- * Disallow eslint-disable comments without rule names. This ensures that we cannot
90
- * disable all rules in a file using eslint-disable comment.
91
- *
92
- * @see https://mysticatea.github.io/eslint-plugin-eslint-comments/rules/no-unlimited-disable
93
- */
53
+ // --- Disable must specify rule names.
94
54
  "eslint-comments/no-unlimited-disable": "error",
95
- /**
96
- * Errors when an eslint-disable comment has no effect. This is useful
97
- * to prevent unnecessary comments in the code.
98
- *
99
- * @see https://mysticatea.github.io/eslint-plugin-eslint-comments/rules/no-unused-disable
100
- */
55
+ // --- Prevent superfluous eslint comments.
56
+ "eslint-comments/no-duplicate-disable": "error",
101
57
  "eslint-comments/no-unused-disable": "error",
102
- /** User-defined rules */
103
- ...options.rules
58
+ "eslint-comments/no-unused-enable": "error"
104
59
  }
105
60
  }
106
61
  ];
107
62
  }
108
- function jsdoc(options) {
63
+ function jsdoc() {
109
64
  return [
110
- pluginJsdoc.configs["flat/recommended-typescript-flavor-error"],
65
+ pluginJsdoc.configs["flat/recommended-typescript-error"],
111
66
  {
112
67
  files: [
113
68
  "**/*.{ts,mts,cts,tsx,d.ts}",
114
69
  "**/*.{js,mjs,cjs,jsx}",
115
70
  "**/*.vue"
116
71
  ],
72
+ plugins: {
73
+ jsdoc: pluginJsdoc
74
+ },
117
75
  rules: {
118
- /**
119
- * Enforce a consistent padding of the block description.
120
- *
121
- * @see https://github.com/gajus/eslint-plugin-jsdoc/blob/HEAD/docs/rules/check-alignment.md#readme
122
- */
123
- "jsdoc/check-alignment": "error",
124
- /**
125
- * Normalize the indentation in the JSdoc comment to improve readability.
126
- *
127
- * @see https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/check-indentation.md#readme
128
- */
129
- "jsdoc/check-indentation": "error",
130
- /**
131
- * Enforce a strict set of tags for the JSDoc comment. This rule also includes
132
- * some custom tags that are used in our projects.
133
- *
134
- * @see https://github.com/gajus/eslint-plugin-jsdoc/blob/main/.README/rules/check-tag-names.md
135
- */
76
+ // --- Redudant with TypeScript.
136
77
  "jsdoc/require-jsdoc": "off",
137
78
  "jsdoc/require-param-type": "off",
138
- "jsdoc/check-tag-names": ["error", {
139
- definedTags: [
140
- "category"
141
- ]
142
- }],
143
- /**
144
- * Checks for multi-line-style comments which fail to meet the criteria of a jsdoc block,
145
- * namely that it should begin with two and only two asterisks.
146
- *
147
- * @see https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/no-bad-blocks.md
148
- */
79
+ "jsdoc/require-returns-type": "off",
80
+ // --- Reports malformed JSDoc comments.
149
81
  "jsdoc/no-bad-blocks": "error",
150
- /**
151
- * It is common practice to prefix a hyphen to parameters in JSDoc. But this
152
- * is sometimes forgotten and has no real purpose. This rule aims to enforce
153
- * that no hyphen is used.
154
- *
155
- * @see https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-hyphen-before-param-description
156
- */
82
+ "jsdoc/check-alignment": "error",
83
+ "jsdoc/check-indentation": "error",
84
+ // --- Reports invalid block tag names.
85
+ "jsdoc/check-tag-names": ["error", { definedTags: ["category"] }],
86
+ // --- Do not use hyphens before param descriptions.
157
87
  "jsdoc/require-hyphen-before-param-description": ["error", "never"],
158
- /**
159
- * Since we are using TypeScript, we don't need to enforce types in JSDoc.
160
- *
161
- * @see https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-param-type.md
162
- */
163
- "jsdoc/require-returns-type": "off",
164
- /**
165
- * Enforce a new-line between the JSDoc summary and tags. Aims to improve
166
- * readability by separating the summary and tags.
167
- *
168
- * @see https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/tag-lines.md
169
- */
170
- "jsdoc/tag-lines": ["error", "any", { startLines: 1 }],
171
- /** User-defined rules */
172
- ...options.rules
88
+ // --- Newline after description.
89
+ "jsdoc/tag-lines": ["error", "any", { startLines: 1 }]
173
90
  }
174
91
  }
175
92
  ];
176
93
  }
177
- function configJson(options) {
94
+ function json() {
178
95
  return [
179
- ...jsonc.configs["flat/recommended-with-json"],
96
+ ...pluginJsonc.configs["flat/recommended-with-json"],
180
97
  {
181
- files: [
182
- "**/*.json",
183
- "**/*.json5"
184
- ],
185
98
  rules: {
186
- /**
187
- * Automatically apply jsonc rules similar to your configured ESLint core rules to JSON.
188
- *
189
- * @see https://ota-meshi.github.io/eslint-plugin-jsonc/rules/auto.html
190
- */
191
- "jsonc/auto": "error",
192
- /** User-defined rules */
193
- ...options.rules
99
+ // --- Automatically apply jsonc rules similar to your configured ESLint core rules to JSON.
100
+ "jsonc/auto": "error"
194
101
  }
195
102
  }
196
103
  ];
@@ -397,106 +304,89 @@ function jsonTsconfig() {
397
304
  }
398
305
  ];
399
306
  }
400
- function node(options) {
307
+ function node() {
401
308
  return [
309
+ nodePlugin.configs["flat/recommended"],
402
310
  {
403
- plugins: {
404
- n: nodePlugin
311
+ settings: {
312
+ node: {
313
+ version: ">=20.0.0"
314
+ }
405
315
  },
406
316
  rules: {
407
- ...nodePlugin.configs.recommended.rules,
408
- /**
409
- * Disallow the use of extraneous imports. This rule helps prevent the
410
- * use of third-party modules that are not listed in the project's
411
- * dependencies.
412
- *
413
- * @see https://github.com/eslint-community/eslint-plugin-n/blob/HEAD/docs/rules/no-extraneous-import.md
414
- */
415
- "n/no-extraneous-import": "error",
416
- /**
417
- * Disable the no-missing-import as module resolution is already checked
418
- * by other tools and IDEs extensively. This rule is redundant.
419
- *
420
- * @see https://github.com/eslint-community/eslint-plugin-n/blob/HEAD/docs/rules/no-missing-import.md
421
- */
317
+ // --- Redundant with TypeScript module resolution.
422
318
  "n/no-missing-import": "off",
423
319
  "n/no-missing-require": "off",
424
320
  "n/no-unpublished-import": "off",
425
- /**
426
- * Enfore the use of the asyncrounous version of the `fs` and `dns` APIs.
427
- *
428
- * @see https://github.com/eslint-community/eslint-plugin-n/blob/HEAD/docs/rules/no-sync.md
429
- * @see https://github.com/eslint-community/eslint-plugin-n/blob/HEAD/docs/rules/prefer-promises/fs.md
430
- * @see https://github.com/eslint-community/eslint-plugin-n/blob/HEAD/docs/rules/prefer-promises/dns.md
431
- */
432
- "n/no-sync": "off",
433
- "n/prefer-promises/fs": "error",
434
- "n/prefer-promises/dns": "error",
435
- /**
436
- * Allow the use of features up to Node.js version 20. This will allow
437
- * the use of newer ECMAScript features and Node.js APIs.
438
- *
439
- * @see https://github.com/eslint-community/eslint-plugin-n/tree/master/docs/rules
440
- */
321
+ // --- Enforce async functions over synchronous functions.
322
+ "n/no-sync": ["error", { allowAtRootLevel: !0 }],
323
+ // --- Enforce the use of ECMAScript features.
441
324
  "n/no-unsupported-features/es-syntax": "error",
442
325
  "n/no-unsupported-features/es-builtins": "error",
443
- "n/no-unsupported-features/node-builtins": "error",
444
- /**
445
- * Prepend the `node:` prefix to all Node.js core modules. This helps
446
- * identify the module as a Node.js core module and not a third-party
447
- * module.
448
- *
449
- * @see https://github.com/eslint-community/eslint-plugin-n/blob/HEAD/docs/rules/prefer-node-protocol.md
450
- */
326
+ // --- Ignore experimental warnings.
327
+ "n/no-unsupported-features/node-builtins": "off",
328
+ // --- Prefer the use of global objects over built-in modules.
329
+ "n/prefer-global/buffer": "error",
330
+ "n/prefer-global/console": "error",
331
+ "n/prefer-global/process": "error",
332
+ "n/prefer-global/text-decoder": "error",
333
+ "n/prefer-global/text-encoder": "error",
334
+ "n/prefer-global/url": "error",
335
+ "n/prefer-global/url-search-params": "error",
336
+ // --- Prefer the use of the `node:` protocol for built-in modules.
451
337
  "n/prefer-node-protocol": "error",
452
- /** User-defined rules */
453
- ...options.rules
454
- },
455
- settings: {
456
- node: {
457
- version: ">=22.1.0"
458
- }
338
+ // --- Prefer the use of promises over callbacks.
339
+ "n/prefer-promises/fs": "error",
340
+ "n/prefer-promises/dns": "error"
341
+ }
342
+ },
343
+ {
344
+ files: [
345
+ "**/*.test.ts",
346
+ "**/*.spec.ts"
347
+ ],
348
+ rules: {
349
+ // --- Disable the no-sync rule for tests.
350
+ "n/no-sync": "off"
459
351
  }
460
352
  }
461
353
  ];
462
354
  }
463
- function sonarjs(options) {
355
+ function sonarjs() {
464
356
  return [
465
357
  pluginSonarjs.configs.recommended,
466
358
  {
467
359
  rules: {
468
- /**
469
- * Cognitive Complexity is a measure of how hard the control flow of a function
470
- * is to understand. Functions with high Cognitive Complexity will be difficult
471
- * to maintain.
472
- *
473
- * @see https://github.com/SonarSource/eslint-plugin-sonarjs/blob/master/docs/rules/cognitive-complexity.md
474
- */
360
+ // --- Increase the default threshold to 30.
475
361
  "sonarjs/cognitive-complexity": ["error", 30],
476
- /**
477
- * Duplicated string literals make the process of refactoring error-prone,
478
- * since you must be sure to update all occurrences. On the other hand,
479
- * constants can be referenced from many places, but only need to be
480
- * updated in a single place.
481
- *
482
- * @see https://github.com/SonarSource/eslint-plugin-sonarjs/blob/master/docs/rules/no-duplicate-string.md
483
- */
484
- "sonarjs/no-duplicate-string": ["error", {
485
- threshold: 10
486
- }],
487
- /**
488
- * Those rules are crashing ESLint at startup, so they are disabled for now.
489
- */
490
- "sonarjs/no-empty-collection": "off",
491
- "sonarjs/no-extra-arguments": "off",
492
- "sonarjs/no-gratuitous-expressions": "off",
493
- "sonarjs/no-one-iteration-loop": "off",
494
- "sonarjs/no-redundant-jump": "off",
495
- "sonarjs/no-unused-collection": "off",
362
+ // --- Increase the default threshold to 10.
363
+ "sonarjs/no-duplicate-string": ["error", { threshold: 10 }],
364
+ // --- Disable unnecessary rules.
365
+ "sonarjs/use-type-alias": "off",
496
366
  "sonarjs/no-use-of-empty-return-value": "off",
497
- "sonarjs/prefer-immediate-return": "off",
498
- /** User-defined rules */
499
- ...options.rules
367
+ "sonarjs/no-nested-functions": "off",
368
+ // --- Disable rules that are already covered by TypeScript.
369
+ "sonarjs/no-extra-arguments": "off",
370
+ "sonarjs/function-return-type": "off",
371
+ "sonarjs/no-misused-promises": "off",
372
+ "sonarjs/no-invariant-returns": "off",
373
+ "sonarjs/no-unused-expressions": "off",
374
+ "sonarjs/different-types-comparison": "off",
375
+ // --- Allow control characters in regex.
376
+ "sonarjs/sonar-no-control-regex": "off"
377
+ }
378
+ },
379
+ {
380
+ files: [
381
+ "**/*.test.ts",
382
+ "**/*.spec.ts"
383
+ ],
384
+ rules: {
385
+ // --- Disable unnecessary rules for test files.
386
+ "sonarjs/cognitive-complexity": "off",
387
+ "sonarjs/no-duplicate-string": "off",
388
+ "sonarjs/no-useless-constructor": "off",
389
+ "sonarjs/public-static-readonly": "off"
500
390
  }
501
391
  }
502
392
  ];
@@ -508,6 +398,7 @@ function getConfigRules(config) {
508
398
  function typescript(options) {
509
399
  return [
510
400
  javascript.configs.recommended,
401
+ // stylistic.configs['recommended-flat'],
511
402
  {
512
403
  languageOptions: {
513
404
  // @ts-expect-error: ignore
@@ -516,7 +407,7 @@ function typescript(options) {
516
407
  ecmaVersion: "latest",
517
408
  sourceType: "module",
518
409
  project: toArray(options.tsConfigPath ?? "./tsconfig.json"),
519
- tsconfigRootDir: cwd()
410
+ tsconfigRootDir: process.cwd()
520
411
  }
521
412
  },
522
413
  plugins: {
@@ -526,7 +417,8 @@ function typescript(options) {
526
417
  },
527
418
  files: [
528
419
  "**/*.{ts,tsx,cts,mts}",
529
- "**/*.{js,jsx,cjs,mjs}"
420
+ "**/*.{js,jsx,cjs,mjs}",
421
+ "**/*.vue"
530
422
  ],
531
423
  rules: {
532
424
  /**
@@ -535,25 +427,11 @@ function typescript(options) {
535
427
  */
536
428
  ...getConfigRules(tslint.configs.recommendedTypeChecked),
537
429
  ...getConfigRules(tslint.configs.stylisticTypeChecked),
538
- /**
539
- * Age-old debate over how to style braces. This rule aims to reduce the
540
- * cognitive load of reasoning about code by enforcing a consistent style.
541
- *
542
- * @see https://eslint.style/rules/default/brace-style
543
- */
430
+ // --- Enforce stroustrup brace style.
544
431
  "brace-style": "off",
545
432
  "@typescript-eslint/brace-style": "off",
546
- "@stylistic/brace-style": ["error", "stroustrup", {
547
- allowSingleLine: !0
548
- }],
549
- /**
550
- * Enforce an indent of 2 spaces. Aims to reduce visual noise and maintain
551
- * readability of code when viewed on GitHub or GitLab.
552
- *
553
- * @see https://eslint.style/rules/default/no-tabs
554
- * @see https://eslint.style/rules/default/indent
555
- * @see https://eslint.style/rules/default/indent-binary-ops
556
- */
433
+ "@stylistic/brace-style": ["error", "stroustrup", { allowSingleLine: !0 }],
434
+ // --- Enforce 2 spaces for indentation and disallow tabs.
557
435
  "no-tabs": "off",
558
436
  indent: "off",
559
437
  "indent-binary-ops": "off",
@@ -563,67 +441,24 @@ function typescript(options) {
563
441
  "@stylistic/no-tabs": "error",
564
442
  "@stylistic/indent": ["error", 2],
565
443
  "@stylistic/indent-binary-ops": ["error", 2],
566
- /**
567
- * Enforce no semi-colons. This rule aims to maintain consistency around the
568
- * use or omission of trailing semicolons. Helps reduce the visual noise in
569
- * the codebase. Also helps to prevent errors when refactoring and adding
570
- * new lines.
571
- *
572
- * @see https://eslint.style/rules/default/semi
573
- */
444
+ // --- No semicolons.
574
445
  semi: "off",
575
446
  "@typescript-eslint/semi": "off",
576
447
  "@stylistic/semi": ["error", "never"],
577
- /**
578
- * Enforce a consistent linebreak style and ensure no leading line breaks
579
- * and a single trailing line break. This rule aims to maintain consistency
580
- * around the use of line breaks in the codebase and reduce the amount of
581
- * diff churn when making changes.
582
- *
583
- * @see https://eslint.style/rules/default/linebreak-style
584
- */
448
+ // --- Consistent line breaks.
585
449
  "eol-last": "off",
586
450
  "no-multiple-empty-lines": "off",
587
451
  "@stylistic/eol-last": ["error", "always"],
588
- "@stylistic/no-multiple-empty-lines": ["error", {
589
- max: 1,
590
- maxBOF: 0,
591
- maxEOF: 0
592
- }],
593
- /**
594
- * Enforce a trailing comma after the last element or property in a multiline
595
- * list of properties or elements. This rule improves the clarity of diffs
596
- * when an item is added or removed from an object or array.
597
- *
598
- * @see https://eslint.style/rules/default/comma-dangle
599
- * @see https://eslint.style/rules/default/comma-spacing
600
- */
452
+ "@stylistic/no-multiple-empty-lines": ["error", { max: 1, maxBOF: 0, maxEOF: 0 }],
453
+ // --- Enforce dangling commas in multiline object literals.
601
454
  "comma-dangle": "off",
602
455
  "@typescript-eslint/comma-dangle": "off",
603
456
  "@stylistic/comma-dangle": ["error", "always-multiline"],
604
- /**
605
- * This rule requires empty lines before and/or after comments. It is disabled
606
- * however when in an object literal, array, or type literal.
607
- *
608
- * @see https://eslint.style/rules/default/lines-around-comment
609
- */
610
- /**
611
- * Normalize type declaration and definition. This reduces the cognitive load
612
- * of reasoning about code by enforcing a consistent style.
613
- *
614
- * @see https://typescript-eslint.io/rules/consistent-indexed-object-style
615
- */
457
+ // --- Enforce type interfaces over type aliases.
616
458
  "@typescript-eslint/consistent-indexed-object-style": ["error", "record"],
617
459
  "@typescript-eslint/consistent-type-definitions": ["error", "interface"],
618
460
  "@typescript-eslint/array-type": ["error", { default: "array-simple", readonly: "array-simple" }],
619
- /**
620
- * Enforce sequential declarations in the same block. This rule aims to
621
- * enforce a top to bottom ordering of variable and type declarations.
622
- * This reduces the likelihood of a developer skipping over a declaration
623
- * when modifying code.
624
- *
625
- * @see https://typescript-eslint.io/rules/no-use-before-define
626
- */
461
+ // --- Enforce declaration and usage from top to bottom.
627
462
  "no-use-before-define": "off",
628
463
  "@typescript-eslint/no-use-before-define": ["error", {
629
464
  enums: !0,
@@ -633,17 +468,7 @@ function typescript(options) {
633
468
  functions: !1,
634
469
  ignoreTypeReferences: !0
635
470
  }],
636
- /**
637
- * Enforce a consistent spacing around various places where spaces are optional.
638
- * This rule aims to maintain consistency around the use of spaces in the codebase
639
- * and reduce the amount of diff churn when making changes.
640
- *
641
- * @see https://eslint.style/rules/default/key-spacing
642
- * @see https://eslint.style/rules/default/comma-spacing
643
- * @see https://eslint.style/rules/default/block-spacing
644
- * @see https://eslint.style/rules/default/arrow-spacing
645
- * @see https://eslint.style/rules/default/object-curly-spacing
646
- */
471
+ // --- Consistent spacing and line breaks between tokens.
647
472
  "key-spacing": "off",
648
473
  "comma-spacing": "off",
649
474
  "block-spacing": "off",
@@ -713,15 +538,7 @@ function typescript(options) {
713
538
  returnType: { before: !1, after: !0 }
714
539
  }
715
540
  }],
716
- /**
717
- * Enforce the use of `@ts-expect-error` over `@ts-ignore` to silence TypeScript
718
- * errors. This rule aims to ensure that TypeScript errors are never silenced
719
- * without explanation or justification. When an error is fixed, the
720
- * `@ts-expect-error` forces the developer to remove the comment.
721
- *
722
- * @see https://typescript-eslint.io/rules/prefer-ts-expect-error
723
- * @see https://typescript-eslint.io/rules/ban-ts-comment
724
- */
541
+ // --- Enforce `@ts-expect-error` over `@ts-ignore`.
725
542
  "@typescript-eslint/prefer-ts-expect-error": "error",
726
543
  "@typescript-eslint/ban-ts-comment": ["error", {
727
544
  "ts-check": !1,
@@ -886,93 +703,32 @@ function typescript(options) {
886
703
  }
887
704
  ];
888
705
  }
889
- const UNICORN_RECOMMENDED_RULES = unicornPlugin.configs.recommended.rules;
890
- function unicorn(options) {
706
+ function unicorn() {
891
707
  return [
708
+ unicornPlugin.configs["flat/recommended"],
892
709
  {
893
- plugins: {
894
- unicorn: unicornPlugin
895
- },
896
710
  rules: {
897
- ...UNICORN_RECOMMENDED_RULES,
898
- /**
899
- * Improve regexes by making them shorter, consistent, and safer. This rule
900
- * aims to improve readability and consistency of regexes while also
901
- * mitigating regex denial of service attacks by disallowing potentially
902
- * catastrophic backtracking.
903
- *
904
- * @see https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/better-regex.md
905
- */
711
+ // --- Allow any kind of import style.
712
+ "unicorn/import-style": "off",
713
+ // --- Improve regexes by making them shorter, consistent, and safer.
906
714
  "unicorn/better-regex": "error",
907
- /**
908
- * Enforce the catch clause parameter name to be named `error`. This rule
909
- * aims to enforce a consistent parameter name in catch clauses. The name
910
- * `error` is the most commonly used name for the parameter that is passed
911
- * to the catch clause.
912
- *
913
- * @see https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/catch-error-name.md
914
- */
915
- "unicorn/catch-error-name": ["error", {
916
- name: "error"
917
- }],
918
- /**
919
- * Enforce the use of camelCase or PascalCase when naming folders, files and
920
- * variables. This rule aims to enforce a consistent naming convention for
921
- * filenames, directory names, and variable names.
922
- *
923
- * @see https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/filename-case.md
924
- */
715
+ // --- Use destructured variables over properties.
716
+ "unicorn/consistent-destructuring": "error",
717
+ // --- Enforce consistent function scoping except for arrow functions.
718
+ "unicorn/consistent-function-scoping": ["error", { checkArrowFunctions: !1 }],
719
+ // --- Disable switch-case fallthrough.
720
+ "unicorn/prefer-switch": "off",
721
+ // --- Enforce camelCase & PascalCase in filenames. Exepct non TS/JS files.
925
722
  "unicorn/filename-case": ["error", {
926
- cases: {
927
- camelCase: !0,
928
- pascalCase: !0
929
- },
930
- ignore: [
931
- "^[A-Z]+(.md)?$"
932
- ]
723
+ multipleFileExtensions: !1,
724
+ cases: { camelCase: !0, pascalCase: !0 },
725
+ ignore: [/\.json$/, /\.md$/, /\.yml$/, /\.yaml$/]
933
726
  }],
934
- /**
935
- * Disable the recommended import style rules. We want to be able to use both
936
- * named and default imports in our codebase.
937
- *
938
- * @see https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/import-style.md
939
- */
940
- "unicorn/import-style": "off",
941
- /**
942
- * Disallow unsafe regular expressions. Regular expressions can be unsafe
943
- * when they are too complex and can cause catastrophic backtracking. This
944
- * rule disallows regular expressions that can lead to catastrophic
945
- *
946
- * @see https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-unsafe-regex.md
947
- */
948
- "unicorn/no-unsafe-regex": "error",
949
- /**
950
- * Enforces a convention of grouping digits using numeric separators.
951
- * Long numbers can become really hard to read, so cutting it into groups
952
- * of digits, separated with a _, is important to keep your code clear.
953
- *
954
- * @see https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/numeric-separators-style.md
955
- */
727
+ // --- Improve readability by using numeric separators.
956
728
  "unicorn/numeric-separators-style": ["error", {
957
729
  onlyIfContainsSeparator: !0
958
730
  }],
959
- "unicorn/number-literal-case": "error",
960
- "unicorn/consistent-function-scoping": "off",
961
- "unicorn/error-message": "error",
962
- "unicorn/escape-case": "error",
963
- "unicorn/no-array-callback-reference": "off",
964
- "unicorn/no-array-for-each": "off",
965
- "unicorn/no-array-instanceof": "error",
966
- "unicorn/no-new-buffer": "error",
967
- "unicorn/no-static-only-class": "off",
968
- "unicorn/prefer-code-point": "off",
969
- "unicorn/prefer-exponentiation-operator": "error",
970
- "unicorn/prefer-includes": "error",
971
- "unicorn/prefer-module": "off",
972
- "unicorn/prefer-starts-ends-with": "error",
973
- "unicorn/prefer-switch": "off",
974
- "unicorn/prefer-text-content": "error",
975
- "unicorn/prefer-type-error": "error",
731
+ // --- Enforce long variable names when they are meaningful.
976
732
  "unicorn/prevent-abbreviations": ["error", {
977
733
  allowList: {
978
734
  args: !0,
@@ -990,110 +746,50 @@ function unicorn(options) {
990
746
  y: !0,
991
747
  z: !0
992
748
  }
993
- }],
994
- "unicorn/throw-new-error": "error"
995
- },
996
- /** User-defined rules */
997
- ...options.rules
749
+ }]
750
+ }
751
+ },
752
+ {
753
+ files: [
754
+ "**/*.test.ts",
755
+ "**/*.spec.ts"
756
+ ],
757
+ rules: {
758
+ // --- Disable unnecessary rules for test files.
759
+ "unicorn/no-null": "off",
760
+ "unicorn/no-useless-undefined": "off",
761
+ "unicorn/no-static-only-class": "off"
762
+ }
998
763
  }
999
764
  ];
1000
765
  }
1001
- function vitest(options) {
766
+ function vitest() {
1002
767
  return [
768
+ vitestPlugin.configs.recommended,
1003
769
  {
1004
- plugins: {
1005
- vitest: vitestPlugin
1006
- },
1007
- files: [
1008
- "**/*.{ts,mts,cts,tsx,d.ts}",
1009
- "**/*.{js,mjs,cjs,jsx}"
1010
- ],
1011
- settings: {
1012
- vitest: {
1013
- typecheck: !0
1014
- }
1015
- },
1016
- languageOptions: {
1017
- globals: {
1018
- ...vitestPlugin.environments.env.globals,
1019
- expectTypeOf: !0
1020
- }
1021
- },
1022
770
  rules: {
1023
- /**
1024
- * Inject all configuration from eslint-plugin-vitest.
1025
- *
1026
- * @see https://github.com/veritem/eslint-plugin-vitest/tree/main?tab=readme-ov-file#rules
1027
- */
1028
- ...vitestPlugin.configs.all.rules,
1029
- /**
1030
- * This rule aims to enforce having at least one expectation
1031
- * in test body to ensure that the test is actually testing something.
1032
- *
1033
- * @see https://github.com/veritem/eslint-plugin-vitest/blob/main/docs/rules/expect-expect.md
1034
- */
771
+ // --- Add the `expectTypeOf` function to the list of assert functions.
1035
772
  "vitest/expect-expect": ["error", {
1036
- assertFunctionNames: [
1037
- "expect",
1038
- "expectTypeOf"
1039
- ]
773
+ assertFunctionNames: ["expect", "expectTypeOf"]
1040
774
  }],
1041
- /**
1042
- * Disable the conditional test rule as it is prevent's us to use in-source
1043
- * testing when using the `if (import.meta.vitest)` condition. Also disable
1044
- * the rule that prevents the use of if-else statements in tests as we want
1045
- * to use it to test type predicates.
1046
- *
1047
- * @see https://github.com/veritem/eslint-plugin-vitest/blob/main/docs/rules/no-conditional-in-test.md
1048
- */
1049
- "vitest/no-conditional-in-test": "off",
1050
- "vitest/no-conditional-tests": "off",
1051
- /**
1052
- * Since we use in-source testing, we need to disable the rule as it may prevent
1053
- * us from using top level evaluation that are not part of the test suite.
1054
- *
1055
- * @see https://github.com/veritem/eslint-plugin-vitest/blob/main/docs/rules/no-hooks.md
1056
- */
1057
- "vitest/require-hook": "off",
1058
- "vitest/no-hooks": "off",
1059
- /**
1060
- * Disable the rule that enforces the use of `expect.assertions` in tests.
1061
- * As much as this rule enforces a best-practice, it is not always necessary.
1062
- *
1063
- * @see https://github.com/veritem/eslint-plugin-vitest/blob/main/docs/rules/prefer-expect-assertions.md
1064
- */
1065
- "vitest/prefer-expect-assertions": "off",
1066
- /**
1067
- * Some functions may have a single test case, and it is not necessary
1068
- * to wrap them in a describe block.
1069
- *
1070
- * @see https://github.com/veritem/eslint-plugin-vitest/blob/main/docs/rules/require-top-level-describe.md
1071
- */
1072
- "vitest/require-top-level-describe": "off",
1073
- /**
1074
- * Enforce rule titles starts with 'should'. This is a convention
1075
- * to force the developer to write the test in a way that it reads
1076
- * like a sentence.
1077
- *
1078
- * @see https://github.com/veritem/eslint-plugin-vitest/blob/main/docs/rules/valid-title.md
1079
- */
775
+ // --- Enforce a single top-level describe block.
776
+ "vitest/require-top-level-describe": ["error", { maxNumberOfTopLevelDescribes: 1 }],
777
+ // --- Enforce 'should' as the prefix for test titles.
1080
778
  "vitest/valid-title": ["error", {
1081
779
  ignoreTypeOfDescribeName: !0,
1082
- mustMatch: {
1083
- test: ["^should"]
1084
- }
780
+ mustMatch: { test: ["^should"] }
1085
781
  }],
1086
- /**
1087
- * Disable the prefer-truthy/false rule as we want to allow the use of strict equality checks
1088
- * with boolean values.
1089
- *
1090
- * @see https://github.com/veritem/eslint-plugin-vitest/blob/main/docs/rules/prefer-to-be-truthy.md
1091
- * @see https://github.com/veritem/eslint-plugin-vitest/blob/main/docs/rules/prefer-to-be-falsy.md
1092
- */
782
+ // --- Prefer strict equality checks.
1093
783
  "vitest/prefer-to-be-truthy": "off",
1094
784
  "vitest/prefer-to-be-falsy": "off",
1095
- /** User-defined rules */
1096
- ...options.rules
785
+ /// --- Loosen the rules for test files.
786
+ "vitest/no-hooks": "off",
787
+ "vitest/require-hook": "off",
788
+ "vitest/no-conditional-in-test": "off",
789
+ "vitest/no-conditional-tests": "off",
790
+ "vitest/prefer-expect-assertions": "off",
791
+ "vitest/padding-around-all": "off",
792
+ "vitest/padding-around-expect-groups": "off"
1097
793
  }
1098
794
  }
1099
795
  ];
@@ -1101,7 +797,7 @@ function vitest(options) {
1101
797
  function vue(options) {
1102
798
  const TYPESCRIPT_CONFIG = typescript(options).at(1);
1103
799
  return [
1104
- ...vuePlugin.configs?.["flat/base"],
800
+ ...vuePlugin.configs["flat/recommended"],
1105
801
  {
1106
802
  plugins: {
1107
803
  vue: vuePlugin,
@@ -1132,109 +828,48 @@ function vue(options) {
1132
828
  }
1133
829
  },
1134
830
  processor: mergeProcessors([
1135
- // @ts-expect-error: ignore
1136
- vuePlugin.processors[".vue"],
831
+ vuePlugin.processors.vue,
1137
832
  vueProcessorBlocks()
1138
833
  ]),
1139
834
  files: [
1140
- "**/*.vue"
835
+ "**/*.vue",
836
+ "**/*.ts"
1141
837
  ],
1142
838
  rules: {
1143
- ...TYPESCRIPT_CONFIG.rules,
1144
- // @ts-expect-error: ignore
1145
- ...vuePlugin.configs["flat/recommended"].rules,
1146
- // @ts-expect-error: ignore
1147
- ...vuePlugin.configs["flat/strongly-recommended"].rules,
1148
- // @ts-expect-error: ignore
1149
- ...vuePlugin.configs["flat/essential"].rules,
1150
- /**
1151
- * Disable some TypeScript rules that may conflict with the Vue SFC parser.
1152
- */
1153
- "@typescript-eslint/no-unsafe-call": "off",
1154
- "@typescript-eslint/no-unsafe-return": "off",
1155
- "@typescript-eslint/no-misused-promises": "off",
1156
- "@typescript-eslint/no-unsafe-assignment": "off",
1157
- "@typescript-eslint/no-unsafe-member-access": "off",
1158
- /**
1159
- * Enforces consistent usage of type imports. This rule will enforce the use
1160
- * of `type` imports to make it easier for the Vue SFC compiler to analyze
1161
- * the code and infer the dependency graph correctly.
1162
- *
1163
- * @see https://typescript-eslint.io/rules/consistent-type-imports
1164
- * @see https://vuejs.github.io/vetur/guide/FAQ.html#why-does-vetur-show-cannot-find-module-xxx
1165
- */
1166
- // '@typescript-eslint/consistent-type-imports': ['error', {
1167
- // disallowTypeAnnotations: false,
1168
- // fixStyle: 'inline-type-imports',
1169
- // prefer: 'type-imports',
1170
- // }],
1171
- /**
1172
- * Enforce the order of the top-level properties in the component. This rule
1173
- * helps to maintain consistency and readability by enforcing a predictable
1174
- * order of the top-level properties in the component.
1175
- *
1176
- * @see https://eslint.vuejs.org/rules/ordered-component-elements.html
1177
- */
1178
- "vue/block-order": ["error", {
1179
- order: [
1180
- "docs",
1181
- "script",
1182
- "template",
1183
- "style"
1184
- ]
1185
- }],
1186
- /**
1187
- * Enforce use of the Composition API and TypeScript. This rule forbids the
1188
- * use of the Options API and JavaScript in Vue components for better
1189
- * consistency and maintainability.
1190
- *
1191
- * @see https://eslint.vuejs.org/rules/vue/prefer-define-options.html
1192
- * @see https://eslint.vuejs.org/rules/vue/component-api-style.html
1193
- */
839
+ "vue/return-in-computed-property": "off",
840
+ // --- Allow multiple component definitions in a single file.
841
+ "vue/one-component-per-file": "off",
842
+ // --- Enforce Component API style.
1194
843
  "vue/prefer-define-options": "error",
1195
- "vue/component-api-style": ["error", ["script-setup"]],
1196
- /**
1197
- * Enforce the component name casing to be PascalCase. This rules helps identify
1198
- * and distinguish between components and HTML elements. It also helps to avoid
1199
- * conflicts with existing and future HTML elements.
1200
- *
1201
- * @see https://eslint.vuejs.org/rules/component-name-in-template-casing.html
1202
- */
844
+ "vue/component-api-style": ["error", ["script-setup", "composition"]],
845
+ // --- Enforce PascalCase components and allow reserved and single-word names.
846
+ "vue/multi-word-component-names": "off",
847
+ "vue/no-reserved-component-names": "off",
1203
848
  "vue/component-name-in-template-casing": ["error", "PascalCase", {
1204
849
  ignores: [String.raw`/\./`],
1205
850
  registeredComponentsOnly: !1
1206
851
  }],
1207
- /**
1208
- * Enforce consistent spacing between HTML comments and their content.
1209
- *
1210
- * @see https://eslint.vuejs.org/rules/html-comment-content-spacing.html
1211
- * @see https://eslint.vuejs.org/rules/html-comment-content-newline.html
1212
- */
852
+ // --- Consistent spacing around HTML comments.
853
+ "vue/html-comment-indent": ["error", 2],
854
+ "vue/multiline-html-element-content-newline": ["error", {
855
+ allowEmptyLines: !0,
856
+ ignores: [],
857
+ ignoreWhenEmpty: !0
858
+ }],
1213
859
  "vue/html-comment-content-spacing": ["error", "always"],
1214
860
  "vue/html-comment-content-newline": ["error", {
1215
861
  multiline: "always",
1216
862
  singleline: "never"
1217
863
  }],
1218
- /**
1219
- * Enforce consistent spacing between HTML / Component tags. This makes it
1220
- * easier to read and understand the structure of the component.
1221
- *
1222
- * @see https://eslint.vuejs.org/rules/block-spacing.html
1223
- * @see https://eslint.vuejs.org/rules/padding-line-between-blocks.html
1224
- * @see https://eslint.vuejs.org/rules/padding-line-between-tags.html
1225
- */
864
+ // --- Consistent block order in Vue components.
865
+ "vue/block-order": ["error", { order: ["script", "template", "style", "i18n"] }],
866
+ // --- Consistent spacing in and around the block.
1226
867
  "vue/block-spacing": ["error", "always"],
1227
868
  "vue/padding-line-between-blocks": ["error", "always"],
1228
869
  "vue/padding-line-between-tags": ["error", [
1229
870
  { blankLine: "consistent", next: "*", prev: "*" },
1230
871
  { blankLine: "always", next: "*", prev: "comment" }
1231
872
  ]],
1232
- "vue/html-comment-indent": ["error", 2],
1233
- "vue/multiline-html-element-content-newline": ["error", {
1234
- allowEmptyLines: !0,
1235
- ignores: [],
1236
- ignoreWhenEmpty: !0
1237
- }],
1238
873
  /**
1239
874
  * Enforce consistent spacing and newlines in the template. This rule helps
1240
875
  * to maintain consistency and readability by enforcing a predictable
@@ -1263,8 +898,6 @@ function vue(options) {
1263
898
  *
1264
899
  * @see https://eslint.vuejs.org/rules/multi-word-component-names.html
1265
900
  */
1266
- "vue/multi-word-component-names": "off",
1267
- "vue/no-reserved-component-names": "off",
1268
901
  /**
1269
902
  * Reports the destructuring or member expression of props passed to setup
1270
903
  * causing the value to lose reactivity. This rule helps to avoid common
@@ -1336,7 +969,6 @@ function vue(options) {
1336
969
  "vue/block-lang": ["error", {
1337
970
  script: { lang: "ts" }
1338
971
  }],
1339
- "vue/return-in-computed-property": "off",
1340
972
  "vue/no-sparse-arrays": "error",
1341
973
  "vue/no-unused-emit-declarations": "error",
1342
974
  "vue/no-use-v-else-with-v-for": "error",
@@ -1407,34 +1039,89 @@ function vue(options) {
1407
1039
  "vue/space-in-parens": ["error", "never"],
1408
1040
  "vue/space-infix-ops": "error",
1409
1041
  "vue/space-unary-ops": ["error", { nonwords: !1, words: !0 }],
1410
- "vue/template-curly-spacing": "error",
1411
- /** User-defined rules */
1412
- ...options.rules
1042
+ "vue/template-curly-spacing": "error"
1043
+ }
1044
+ },
1045
+ // --- Disable some TypeScript rules that may conflict with the Vue SFC parser.
1046
+ {
1047
+ files: [
1048
+ "**/*.vue"
1049
+ ],
1050
+ rules: {
1051
+ "@typescript-eslint/no-unsafe-call": "off",
1052
+ "@typescript-eslint/no-unsafe-return": "off",
1053
+ "@typescript-eslint/no-unsafe-argument": "off",
1054
+ "@typescript-eslint/no-unsafe-assignment": "off",
1055
+ "@typescript-eslint/no-unsafe-member-access": "off",
1056
+ "@typescript-eslint/no-misused-promises": "off"
1057
+ }
1058
+ },
1059
+ // --- Disable in test files.
1060
+ {
1061
+ files: [
1062
+ "**/*.test.ts",
1063
+ "**/*.spec.ts"
1064
+ ],
1065
+ rules: {
1066
+ "vue/one-component-per-file": "off"
1067
+ }
1068
+ }
1069
+ ];
1070
+ }
1071
+ function yml() {
1072
+ return [
1073
+ ...pluginYml.configs["flat/standard"],
1074
+ ...pluginYml.configs["flat/recommended"],
1075
+ {
1076
+ rules: {
1077
+ // --- Force single quotes.
1078
+ "yml/quotes": ["error", {
1079
+ avoidEscape: !0,
1080
+ prefer: "single"
1081
+ }],
1082
+ // --- Remove trailing zeros in numbers.
1083
+ "yml/no-trailing-zeros": "error",
1084
+ // --- Prevent empty keys.
1085
+ "yml/require-string-key": "error",
1086
+ // --- Prevent empty values or weird newlines in mappings.
1087
+ "yml/block-mapping-colon-indicator-newline": "error",
1088
+ // --- No more than one empty line.
1089
+ "yml/no-multiple-empty-lines": ["error", {
1090
+ max: 1,
1091
+ maxBOF: 0,
1092
+ maxEOF: 0
1093
+ }],
1094
+ // --- Sort environemnt variables alphabetically.
1095
+ "yml/sort-sequence-values": ["error", {
1096
+ pathPattern: "^env$",
1097
+ order: { type: "asc" }
1098
+ }]
1413
1099
  }
1414
1100
  }
1415
1101
  ];
1416
1102
  }
1417
1103
  function all(options = {}) {
1418
1104
  return [
1419
- ...antfu(options),
1420
- ...eslintComments(options),
1421
- ...jsdoc(options),
1422
- ...configJson(options),
1105
+ ...antfu(),
1106
+ ...eslintComments(),
1107
+ ...jsdoc(),
1108
+ ...json(),
1423
1109
  ...jsonPackage(),
1424
1110
  ...jsonTsconfig(),
1425
- ...node(options),
1426
- ...sonarjs(options),
1111
+ ...node(),
1112
+ ...sonarjs(),
1427
1113
  ...typescript(options),
1428
- ...unicorn(options),
1429
- ...vitest(options),
1114
+ ...unicorn(),
1115
+ ...vitest(),
1430
1116
  ...vue(options),
1117
+ ...yml(),
1431
1118
  {
1432
1119
  ignores: [
1433
1120
  "**/dist",
1434
1121
  "**/bin",
1435
1122
  "**/node_modules",
1436
1123
  "**/.nuxt",
1437
- "**/output",
1124
+ "**/.output",
1438
1125
  "**/coverage",
1439
1126
  "**/public",
1440
1127
  "**/__wip__",