@unshared/eslint-config 0.0.14 → 0.0.16

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,867 +1,462 @@
1
- import vueParser from "vue-eslint-parser";
2
- import tslint from "typescript-eslint";
3
- import vueProcessorBlocks from "eslint-processor-vue-blocks";
4
- import vuePlugin from "eslint-plugin-vue";
5
- import { mergeProcessors } from "eslint-merge-processors";
6
- import { cwd } from "node:process";
7
- import perfectionist from "eslint-plugin-perfectionist";
8
- import { toArray } from "@unshared/collection/toArray";
9
- import stylistic from "@stylistic/eslint-plugin";
1
+ import pluginAntfu from "eslint-plugin-antfu";
2
+ import eslintCommentsPlugin from "eslint-plugin-eslint-comments";
3
+ import pluginJsdoc from "eslint-plugin-jsdoc";
4
+ import jsonc from "eslint-plugin-jsonc";
5
+ import nodePlugin from "eslint-plugin-n";
6
+ import pluginSonarjs from "eslint-plugin-sonarjs";
10
7
  import javascript from "@eslint/js";
11
- import vitestPlugin from "eslint-plugin-vitest";
8
+ import stylistic from "@stylistic/eslint-plugin";
9
+ import { toArray } from "@unshared/collection/toArray";
10
+ import perfectionist from "eslint-plugin-perfectionist";
11
+ import { cwd } from "node:process";
12
+ import tslint from "typescript-eslint";
12
13
  import unicornPlugin from "eslint-plugin-unicorn";
13
- import pluginSonarjs from "eslint-plugin-sonarjs";
14
- import nodePlugin from "eslint-plugin-n";
15
- import jsonc from "eslint-plugin-jsonc";
16
- import pluginJsdoc from "eslint-plugin-jsdoc";
17
- import eslintCommentsPlugin from "eslint-plugin-eslint-comments";
18
- import pluginAntfu from "eslint-plugin-antfu";
19
- function getConfigRules(config) {
20
- const rules = toArray(config).flat().map((x) => x.rules);
21
- return Object.assign({}, ...rules);
22
- }
23
- function typescript(options) {
14
+ import vitestPlugin from "eslint-plugin-vitest";
15
+ import { mergeProcessors } from "eslint-merge-processors";
16
+ import vuePlugin from "eslint-plugin-vue";
17
+ import vueProcessorBlocks from "eslint-processor-vue-blocks";
18
+ import vueParser from "vue-eslint-parser";
19
+ function antfu(options) {
24
20
  return [
25
- javascript.configs.recommended,
26
21
  {
27
- languageOptions: {
28
- // @ts-expect-error: ignore
29
- parser: tslint.parser,
30
- parserOptions: {
31
- ecmaVersion: "latest",
32
- sourceType: "module",
33
- project: toArray(options.tsConfigPath ?? "./tsconfig.json"),
34
- tsconfigRootDir: cwd()
35
- }
36
- },
37
22
  plugins: {
38
- "@typescript-eslint": tslint.plugin,
39
- "@stylistic": stylistic,
40
- perfectionist
23
+ antfu: pluginAntfu
41
24
  },
42
- files: [
43
- "**/*.{ts,tsx,cts,mts}",
44
- "**/*.{js,jsx,cjs,mjs}"
45
- ],
46
25
  rules: {
26
+ "antfu/consistent-list-newline": "error",
47
27
  /**
48
- * Inherit all recommended rules from the `@eslint/js` plugin. This is the base
49
- * configuration for JavaScript files.
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
50
32
  */
51
- ...getConfigRules(tslint.configs.recommendedTypeChecked),
52
- ...getConfigRules(tslint.configs.stylisticTypeChecked),
33
+ "antfu/import-dedupe": "error",
53
34
  /**
54
- * Age-old debate over how to style braces. This rule aims to reduce the
55
- * cognitive load of reasoning about code by enforcing a consistent style.
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.
56
38
  *
57
- * @see https://eslint.style/rules/default/brace-style
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
58
43
  */
59
- "brace-style": "off",
60
- "@typescript-eslint/brace-style": "off",
61
- "@stylistic/brace-style": ["error", "stroustrup", {
62
- allowSingleLine: !0
63
- }],
44
+ "antfu/top-level-function": "error",
64
45
  /**
65
- * Enforce an indent of 2 spaces. Aims to reduce visual noise and maintain
66
- * readability of code when viewed on GitHub or GitLab.
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.
67
48
  *
68
- * @see https://eslint.style/rules/default/no-tabs
69
- * @see https://eslint.style/rules/default/indent
70
- * @see https://eslint.style/rules/default/indent-binary-ops
49
+ * @see https://github.com/antfu/eslint-plugin-antfu/blob/main/src/rules/consistent-list-newline.md
71
50
  */
72
- "no-tabs": "off",
73
- indent: "off",
74
- "indent-binary-ops": "off",
75
- "@typescript-eslint/no-tabs": "off",
76
- "@typescript-eslint/indent": "off",
77
- "@typescript-eslint/indent-binary-ops": "off",
78
- "@stylistic/no-tabs": "error",
79
- "@stylistic/indent": ["error", 2],
80
- "@stylistic/indent-binary-ops": ["error", 2],
51
+ "object-curly-newline": "off",
52
+ /** User-defined rules */
53
+ ...options.rules
54
+ }
55
+ }
56
+ ];
57
+ }
58
+ function eslintComments(options) {
59
+ return [
60
+ {
61
+ plugins: {
62
+ "eslint-comments": eslintCommentsPlugin
63
+ },
64
+ rules: {
81
65
  /**
82
- * Enforce no semi-colons. This rule aims to maintain consistency around the
83
- * use or omission of trailing semicolons. Helps reduce the visual noise in
84
- * the codebase. Also helps to prevent errors when refactoring and adding
85
- * new lines.
66
+ * Allow multiple rules directive in a single comment. This
67
+ * reduces the number of comments in the code.
86
68
  *
87
- * @see https://eslint.style/rules/default/semi
69
+ * @see https://mysticatea.github.io/eslint-plugin-eslint-comments/rules/disable-enable-pair
88
70
  */
89
- semi: "off",
90
- "@typescript-eslint/semi": "off",
91
- "@stylistic/semi": ["error", "never"],
71
+ "eslint-comments/disable-enable-pair": "off",
92
72
  /**
93
- * Enforce a consistent linebreak style and ensure no leading line breaks
94
- * and a single trailing line break. This rule aims to maintain consistency
95
- * around the use of line breaks in the codebase and reduce the amount of
96
- * diff churn when making changes.
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.
97
76
  *
98
- * @see https://eslint.style/rules/default/linebreak-style
77
+ * @see https://mysticatea.github.io/eslint-plugin-eslint-comments/rules/no-aggregating-enable
99
78
  */
100
- "eol-last": "off",
101
- "no-multiple-empty-lines": "off",
102
- "@stylistic/eol-last": ["error", "always"],
103
- "@stylistic/no-multiple-empty-lines": ["error", {
104
- max: 1,
105
- maxBOF: 0,
106
- maxEOF: 0
107
- }],
79
+ "eslint-comments/no-aggregating-enable": "error",
108
80
  /**
109
- * Enforce a trailing comma after the last element or property in a multiline
110
- * list of properties or elements. This rule improves the clarity of diffs
111
- * when an item is added or removed from an object or array.
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.
112
84
  *
113
- * @see https://eslint.style/rules/default/comma-dangle
114
- * @see https://eslint.style/rules/default/comma-spacing
85
+ * @see https://mysticatea.github.io/eslint-plugin-eslint-comments/rules/no-duplicate-disable
115
86
  */
116
- "comma-dangle": "off",
117
- "@typescript-eslint/comma-dangle": "off",
118
- "@stylistic/comma-dangle": ["error", "always-multiline"],
87
+ "eslint-comments/no-duplicate-disable": "error",
119
88
  /**
120
- * This rule requires empty lines before and/or after comments. It is disabled
121
- * however when in an object literal, array, or type literal.
89
+ * Disallow eslint-disable comments without rule names. This ensures that we cannot
90
+ * disable all rules in a file using eslint-disable comment.
122
91
  *
123
- * @see https://eslint.style/rules/default/lines-around-comment
92
+ * @see https://mysticatea.github.io/eslint-plugin-eslint-comments/rules/no-unlimited-disable
124
93
  */
94
+ "eslint-comments/no-unlimited-disable": "error",
125
95
  /**
126
- * Normalize type declaration and definition. This reduces the cognitive load
127
- * of reasoning about code by enforcing a consistent style.
96
+ * Errors when an eslint-disable comment has no effect. This is useful
97
+ * to prevent unnecessary comments in the code.
128
98
  *
129
- * @see https://typescript-eslint.io/rules/consistent-indexed-object-style
99
+ * @see https://mysticatea.github.io/eslint-plugin-eslint-comments/rules/no-unused-disable
130
100
  */
131
- "@typescript-eslint/consistent-indexed-object-style": ["error", "record"],
132
- "@typescript-eslint/consistent-type-definitions": ["error", "interface"],
133
- "@typescript-eslint/member-delimiter-style": ["error", { multiline: { delimiter: "none" } }],
134
- "@typescript-eslint/array-type": ["error", { default: "array-simple", readonly: "array-simple" }],
101
+ "eslint-comments/no-unused-disable": "error",
102
+ /** User-defined rules */
103
+ ...options.rules
104
+ }
105
+ }
106
+ ];
107
+ }
108
+ function jsdoc(options) {
109
+ return [
110
+ pluginJsdoc.configs["flat/recommended-typescript-flavor-error"],
111
+ {
112
+ files: [
113
+ "**/*.{ts,mts,cts,tsx,d.ts}",
114
+ "**/*.{js,mjs,cjs,jsx}",
115
+ "**/*.vue"
116
+ ],
117
+ rules: {
135
118
  /**
136
- * Enforce sequential declarations in the same block. This rule aims to
137
- * enforce a top to bottom ordering of variable and type declarations.
138
- * This reduces the likelihood of a developer skipping over a declaration
139
- * when modifying code.
119
+ * Enforce a consistent padding of the block description.
140
120
  *
141
- * @see https://typescript-eslint.io/rules/no-use-before-define
121
+ * @see https://github.com/gajus/eslint-plugin-jsdoc/blob/HEAD/docs/rules/check-alignment.md#readme
142
122
  */
143
- "no-use-before-define": "off",
144
- "@typescript-eslint/no-use-before-define": ["error", {
145
- enums: !0,
146
- classes: !1,
147
- typedefs: !0,
148
- variables: !0,
149
- functions: !1,
150
- ignoreTypeReferences: !0
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
+ */
136
+ "jsdoc/require-jsdoc": "off",
137
+ "jsdoc/require-param-type": "off",
138
+ "jsdoc/check-tag-names": ["error", {
139
+ definedTags: [
140
+ "category"
141
+ ]
151
142
  }],
152
143
  /**
153
- * Enforce a consistent spacing around various places where spaces are optional.
154
- * This rule aims to maintain consistency around the use of spaces in the codebase
155
- * and reduce the amount of diff churn when making changes.
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.
156
146
  *
157
- * @see https://eslint.style/rules/default/key-spacing
158
- * @see https://eslint.style/rules/default/comma-spacing
159
- * @see https://eslint.style/rules/default/block-spacing
160
- * @see https://eslint.style/rules/default/arrow-spacing
161
- * @see https://eslint.style/rules/default/object-curly-spacing
147
+ * @see https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/no-bad-blocks.md
162
148
  */
163
- "key-spacing": "off",
164
- "comma-spacing": "off",
165
- "block-spacing": "off",
166
- "arrow-spacing": "off",
167
- "spaced-comment": "off",
168
- "no-multi-spaces": "off",
169
- "space-before-blocks": "off",
170
- "lines-around-comment": "off",
171
- "object-curly-spacing": "off",
172
- "array-bracket-spacing": "off",
173
- "array-bracket-newline": "off",
174
- "function-call-spacing": "off",
175
- "generator-star-spacing": "off",
176
- "template-curly-spacing": "off",
177
- "object-property-newline ": "off",
178
- "newline-per-chained-call": "off",
179
- "computed-property-spacing": "off",
180
- "lines-between-class-members": "off",
181
- "@typescript-eslint/comma-spacing": "off",
182
- "@typescript-eslint/object-curly-spacing": "off",
183
- "@typescript-eslint/type-annotation-spacing": "off",
184
- "@typescript-eslint/lines-around-comment": "off",
185
- "@stylistic/key-spacing": ["error", { afterColon: !0, beforeColon: !1 }],
186
- "@stylistic/comma-spacing": ["error", { after: !0, before: !1 }],
187
- "@stylistic/arrow-spacing": ["error", { before: !0, after: !0 }],
188
- "@stylistic/type-generic-spacing": "error",
189
- "@stylistic/type-named-tuple-spacing": "error",
190
- "@stylistic/block-spacing": ["error", "always"],
191
- "@stylistic/no-multi-spaces": "error",
192
- "@stylistic/keyword-spacing": ["error", { before: !0, after: !0 }],
193
- "@stylistic/space-before-blocks": ["error", "always"],
194
- "@stylistic/object-curly-spacing": ["error", "always"],
195
- "@stylistic/array-bracket-spacing": ["error", "never"],
196
- "@stylistic/array-bracket-newline": ["error", "consistent"],
197
- "@stylistic/function-call-spacing": ["error", "never"],
198
- "@stylistic/template-curly-spacing": ["error", "never"],
199
- "@stylistic/object-property-newline": ["error", { allowAllPropertiesOnSameLine: !0 }],
200
- "@stylistic/generator-star-spacing": ["error", { before: !0, after: !0 }],
201
- "@stylistic/computed-property-spacing": ["error", "never"],
202
- "@stylistic/multiline-ternary": ["error", "always-multiline"],
203
- "@stylistic/lines-around-comment": ["error", {
204
- beforeBlockComment: !0,
205
- beforeLineComment: !0,
206
- ignorePattern: String.raw`^(?! ?---|\*)`,
207
- applyDefaultIgnorePatterns: !0,
208
- afterHashbangComment: !0
209
- }],
210
- "@stylistic/spaced-comment": ["error", "always", {
211
- block: { markers: ["!"], exceptions: ["*"], balanced: !0 },
212
- line: { markers: ["/"], exceptions: ["/", "#"] }
213
- }],
214
- "@stylistic/lines-between-class-members": ["error", {
215
- enforce: [{ blankLine: "always", prev: "method", next: "*" }]
216
- }, {
217
- exceptAfterSingleLine: !0
218
- }],
219
- "@stylistic/type-annotation-spacing": ["error", {
220
- before: !1,
221
- after: !0,
222
- overrides: {
223
- arrow: { before: !0, after: !0 },
224
- colon: { before: !1, after: !0 },
225
- variable: { before: !1, after: !0 },
226
- property: { before: !1, after: !0 },
227
- parameter: { before: !1, after: !0 },
228
- returnType: { before: !1, after: !0 }
229
- }
230
- }],
231
- /**
232
- * Enforce the use of `@ts-expect-error` over `@ts-ignore` to silence TypeScript
233
- * errors. This rule aims to ensure that TypeScript errors are never silenced
234
- * without explanation or justification. When an error is fixed, the
235
- * `@ts-expect-error` forces the developer to remove the comment.
236
- *
237
- * @see https://typescript-eslint.io/rules/prefer-ts-expect-error
238
- * @see https://typescript-eslint.io/rules/ban-ts-comment
239
- */
240
- "@typescript-eslint/prefer-ts-expect-error": "error",
241
- "@typescript-eslint/ban-ts-comment": ["error", {
242
- "ts-check": !1,
243
- "ts-expect-error": "allow-with-description",
244
- "ts-ignore": !1,
245
- "ts-nocheck": !1
246
- }],
149
+ "jsdoc/no-bad-blocks": "error",
247
150
  /**
248
- * Disallow dangling expressions and promises. This rule aims to prevent
249
- * dangling promises and expressions that are not assigned to a variable.
250
- * This can lead to bugs and unexpected behavior in the codebase.
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.
251
154
  *
252
- * @see https://eslint.org/docs/rules/no-void
253
- * @see https://typescript-eslint.io/rules/no-floating-promises
155
+ * @see https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-hyphen-before-param-description
254
156
  */
255
- "no-void": "off",
256
- "no-unused-expressions": "off",
257
- "@typescript-eslint/no-unused-expressions": "error",
258
- "@typescript-eslint/no-floating-promises": ["error", {
259
- ignoreVoid: !0,
260
- ignoreIIFE: !0
261
- }],
157
+ "jsdoc/require-hyphen-before-param-description": ["error", "never"],
262
158
  /**
263
- * Sort imports alphabetically and group them without newlines. This rule
264
- * aims to maintain consistency around the order of imports in JavaScript
265
- * files. Helps reduce the visual noise in the codebase.
159
+ * Since we are using TypeScript, we don't need to enforce types in JSDoc.
266
160
  *
267
- * @see https://eslint-plugin-perfectionist.azat.io/rules/sort-imports
161
+ * @see https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-param-type.md
268
162
  */
269
- "sort-imports": "off",
270
- "@typescript-eslint/sort-type-constituents": "off",
271
- "@typescript-eslint/consistent-type-imports": ["error", {
272
- disallowTypeAnnotations: !1,
273
- prefer: "no-type-imports"
274
- }],
275
- "perfectionist/sort-exports": ["error", {
276
- type: "alphabetical",
277
- "ignore-case": !1
278
- }],
279
- "perfectionist/sort-named-imports": ["error", { type: "natural" }],
280
- "perfectionist/sort-imports": ["error", {
281
- "newlines-between": "never",
282
- order: "desc"
283
- }],
163
+ "jsdoc/require-returns-type": "off",
284
164
  /**
285
- * Enforce no unused variables. Helps keep the codebase clean and reduces
286
- * the chance of bugs from side-effects.
165
+ * Enforce a new-line between the JSDoc summary and tags. Aims to improve
166
+ * readability by separating the summary and tags.
287
167
  *
288
- * @see https://typescript-eslint.io/rules/@typescript-eslint/no-unused-vars
168
+ * @see https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/tag-lines.md
289
169
  */
290
- "no-redeclare": "off",
291
- "no-unused-vars": "off",
292
- "@typescript-eslint/no-redeclare": "error",
293
- "@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_" }],
294
- //////////////////////////////////////////////////////////////////////////////////////////
295
- "perfectionist/sort-intersection-types": ["error", { type: "natural" }],
296
- "perfectionist/sort-union-types": ["error", {
297
- type: "natural",
298
- "nullable-last": !0
299
- }],
300
- "no-useless-constructor": "off",
301
- "@typescript-eslint/ban-types": "off",
302
- "@typescript-eslint/camelcase": "off",
303
- "@typescript-eslint/explicit-function-return-type": "off",
304
- "@typescript-eslint/explicit-member-accessibility": "off",
305
- "@typescript-eslint/explicit-module-boundary-types": "off",
306
- "@typescript-eslint/no-empty-function": "off",
307
- "@typescript-eslint/no-empty-interface": "off",
308
- "@typescript-eslint/no-explicit-any": "off",
309
- "@typescript-eslint/no-namespace": "off",
310
- "@typescript-eslint/no-non-null-assertion": "off",
311
- "@typescript-eslint/no-parameter-properties": "off",
312
- "array-callback-return": "error",
313
- "arrow-body-style": ["error", "as-needed"],
314
- "arrow-parens": ["error", "as-needed", { requireForBlockBody: !0 }],
315
- "block-scoped-var": "error",
316
- camelcase: "off",
317
- "comma-style": ["error", "last"],
318
- complexity: ["off", 11],
319
- "consistent-return": "off",
320
- curly: ["error", "multi-or-nest", "consistent"],
321
- eqeqeq: ["error", "smart"],
322
- "no-alert": "error",
323
- "no-case-declarations": "error",
324
- "no-cond-assign": ["error", "always"],
325
- "no-confusing-arrow": "error",
326
- "no-console": ["warn", { allow: ["warn", "error"] }],
327
- "no-constant-condition": "error",
328
- "no-debugger": "error",
329
- "no-eval": "error",
330
- "no-implied-eval": "error",
331
- "no-multi-str": "error",
332
- "no-param-reassign": "off",
333
- "no-restricted-syntax": ["error", "DebuggerStatement", "LabeledStatement", "WithStatement"],
334
- "no-return-assign": "off",
335
- "no-return-await": "off",
336
- "no-trailing-spaces": "error",
337
- "no-useless-escape": "off",
338
- "no-var": "error",
339
- "no-with": "error",
340
- "object-shorthand": ["error", "always", { avoidQuotes: !0, ignoreConstructors: !1 }],
341
- "one-var-declaration-per-line": "error",
342
- "operator-linebreak": ["error", "before"],
343
- "prefer-arrow-callback": ["error", { allowNamedFunctions: !1, allowUnboundThis: !0 }],
344
- "prefer-const": ["error", { destructuring: "any", ignoreReadBeforeAssign: !0 }],
345
- "prefer-rest-params": "error",
346
- "prefer-spread": "error",
347
- "prefer-template": "error",
348
- "quote-props": ["error", "consistent-as-needed"],
349
- quotes: ["error", "single"],
350
- "require-await": "off",
351
- "space-before-function-paren": ["error", "never"],
352
- "vars-on-top": "error"
353
- }
354
- },
355
- /**
356
- * Ignore duplicate imports in declaration files as they are often used to re-export
357
- * types from other packages into multiple namespaces. This is a common pattern
358
- * in TypeScript declaration files.
359
- */
360
- {
361
- files: ["*.d.ts"],
362
- rules: {
363
- "@typescript-eslint/no-use-before-define": "off",
364
- "import/no-duplicates": "off"
365
- }
366
- },
367
- /**
368
- * Allow console statements in scripts and CLI files since they are not part of the
369
- * library / production code and are useful for debugging, logging, and testing.
370
- */
371
- {
372
- files: ["**/scripts/**/*", "cli.*"],
373
- rules: {
374
- "no-console": "off"
170
+ "jsdoc/tag-lines": ["error", "any", { startLines: 1 }],
171
+ /** User-defined rules */
172
+ ...options.rules
375
173
  }
376
174
  }
377
175
  ];
378
176
  }
379
- function vue(options) {
380
- const TYPESCRIPT_CONFIG = typescript(options).at(1);
177
+ function configJson(options) {
381
178
  return [
382
- ...vuePlugin.configs?.["flat/base"],
179
+ ...jsonc.configs["flat/recommended-with-json"],
383
180
  {
384
- plugins: {
385
- vue: vuePlugin,
386
- ...TYPESCRIPT_CONFIG.plugins
387
- },
388
- languageOptions: {
389
- globals: {
390
- computed: "readonly",
391
- defineEmits: "readonly",
392
- defineExpose: "readonly",
393
- defineProps: "readonly",
394
- onMounted: "readonly",
395
- onUnmounted: "readonly",
396
- reactive: "readonly",
397
- ref: "readonly",
398
- shallowReactive: "readonly",
399
- shallowRef: "readonly",
400
- toRef: "readonly",
401
- toRefs: "readonly",
402
- watch: "readonly",
403
- watchEffect: "readonly"
404
- },
405
- parser: vueParser,
406
- parserOptions: {
407
- parser: tslint.parser,
408
- extraFileExtensions: [".vue"],
409
- ...TYPESCRIPT_CONFIG.languageOptions.parserOptions
410
- }
411
- },
412
- processor: mergeProcessors([
413
- // @ts-expect-error: ignore
414
- vuePlugin.processors[".vue"],
415
- vueProcessorBlocks()
416
- ]),
417
181
  files: [
418
- "**/*.vue"
182
+ "**/*.json",
183
+ "**/*.json5"
419
184
  ],
420
185
  rules: {
421
- ...TYPESCRIPT_CONFIG.rules,
422
- // @ts-expect-error: ignore
423
- ...vuePlugin.configs["flat/recommended"].rules,
424
- // @ts-expect-error: ignore
425
- ...vuePlugin.configs["flat/strongly-recommended"].rules,
426
- // @ts-expect-error: ignore
427
- ...vuePlugin.configs["flat/essential"].rules,
428
- /**
429
- * Disable some TypeScript rules that may conflict with the Vue SFC parser.
430
- */
431
- "@typescript-eslint/no-unsafe-call": "off",
432
- "@typescript-eslint/no-unsafe-return": "off",
433
- "@typescript-eslint/no-misused-promises": "off",
434
- "@typescript-eslint/no-unsafe-assignment": "off",
435
- "@typescript-eslint/no-unsafe-member-access": "off",
436
186
  /**
437
- * Enforces consistent usage of type imports. This rule will enforce the use
438
- * of `type` imports to make it easier for the Vue SFC compiler to analyze
439
- * the code and infer the dependency graph correctly.
187
+ * Automatically apply jsonc rules similar to your configured ESLint core rules to JSON.
440
188
  *
441
- * @see https://typescript-eslint.io/rules/consistent-type-imports
442
- * @see https://vuejs.github.io/vetur/guide/FAQ.html#why-does-vetur-show-cannot-find-module-xxx
189
+ * @see https://ota-meshi.github.io/eslint-plugin-jsonc/rules/auto.html
443
190
  */
444
- // '@typescript-eslint/consistent-type-imports': ['error', {
445
- // disallowTypeAnnotations: false,
446
- // fixStyle: 'inline-type-imports',
447
- // prefer: 'type-imports',
448
- // }],
449
- /**
450
- * Enforce the order of the top-level properties in the component. This rule
451
- * helps to maintain consistency and readability by enforcing a predictable
452
- * order of the top-level properties in the component.
453
- *
454
- * @see https://eslint.vuejs.org/rules/ordered-component-elements.html
455
- */
456
- "vue/block-order": ["error", {
457
- order: [
458
- "docs",
459
- "script",
460
- "template",
461
- "style"
462
- ]
463
- }],
464
- /**
465
- * Enforce use of the Composition API and TypeScript. This rule forbids the
466
- * use of the Options API and JavaScript in Vue components for better
467
- * consistency and maintainability.
468
- *
469
- * @see https://eslint.vuejs.org/rules/vue/prefer-define-options.html
470
- * @see https://eslint.vuejs.org/rules/vue/component-api-style.html
471
- */
472
- "vue/prefer-define-options": "error",
473
- "vue/component-api-style": ["error", ["script-setup"]],
474
- /**
475
- * Enforce the component name casing to be PascalCase. This rules helps identify
476
- * and distinguish between components and HTML elements. It also helps to avoid
477
- * conflicts with existing and future HTML elements.
478
- *
479
- * @see https://eslint.vuejs.org/rules/component-name-in-template-casing.html
480
- */
481
- "vue/component-name-in-template-casing": ["error", "PascalCase", {
482
- ignores: [String.raw`/\./`],
483
- registeredComponentsOnly: !1
484
- }],
485
- /**
486
- * Enforce consistent spacing between HTML comments and their content.
487
- *
488
- * @see https://eslint.vuejs.org/rules/html-comment-content-spacing.html
489
- * @see https://eslint.vuejs.org/rules/html-comment-content-newline.html
490
- */
491
- "vue/html-comment-content-spacing": ["error", "always"],
492
- "vue/html-comment-content-newline": ["error", {
493
- multiline: "always",
494
- singleline: "never"
495
- }],
496
- /**
497
- * Enforce consistent spacing between HTML / Component tags. This makes it
498
- * easier to read and understand the structure of the component.
499
- *
500
- * @see https://eslint.vuejs.org/rules/padding-line-between-blocks.html
501
- * @see https://eslint.vuejs.org/rules/padding-line-between-tags.html
502
- */
503
- "vue/padding-line-between-blocks": ["error", "always"],
504
- "vue/padding-line-between-tags": ["error", [
505
- { blankLine: "consistent", next: "*", prev: "*" },
506
- { blankLine: "always", next: "*", prev: "comment" }
507
- ]],
508
- "vue/html-comment-indent": ["error", 2],
509
- "vue/multiline-html-element-content-newline": ["error", {
510
- allowEmptyLines: !0,
511
- ignores: [],
512
- ignoreWhenEmpty: !0
513
- }],
514
- /**
515
- * Enforce consistent spacing and newlines in the template. This rule helps
516
- * to maintain consistency and readability by enforcing a predictable
517
- *
518
- * @see https://eslint.vuejs.org/rules/html-indent.html
519
- * @see https://eslint.vuejs.org/rules/max-attributes-per-line.html
520
- * @see https://eslint.vuejs.org/rules/html-closing-bracket-newline.html
521
- */
522
- "vue/html-indent": ["error", 2, {
523
- alignAttributesVertically: !0,
524
- attribute: 1,
525
- baseIndent: 1,
526
- closeBracket: 0,
527
- ignores: []
528
- }],
529
- // 'vue/func-call-spacing': ['off', 'never'],
530
- "vue/key-spacing": ["error", { afterColon: !0, beforeColon: !1 }],
531
- "vue/keyword-spacing": ["error", { after: !0, before: !0 }],
532
- "vue/max-attributes-per-line": ["error", {
533
- multiline: { max: 1 },
534
- singleline: { max: 5 }
535
- }],
536
- /**
537
- * Allow single-word component names. This rule is disabled because we use
538
- * pascal-casing to distinguish between components and HTML elements.
539
- *
540
- * @see https://eslint.vuejs.org/rules/multi-word-component-names.html
541
- */
542
- "vue/multi-word-component-names": "off",
543
- "vue/no-reserved-component-names": "off",
544
- /**
545
- * Reports the destructuring or member expression of props passed to setup
546
- * causing the value to lose reactivity. This rule helps to avoid common
547
- * pitfalls when using the Composition API.
548
- *
549
- * @see https://eslint.vuejs.org/rules/no-setup-props-reactivity-loss.html
550
- */
551
- "vue/no-setup-props-reactivity-loss": "error",
552
- /**
553
- * Disallow v-if in v-for. This rule helps to avoid common pitfalls when
554
- * using v-if and v-for together in the same element.
555
- *
556
- * @see https://eslint.vuejs.org/rules/no-use-v-if-with-v-for.html
557
- */
558
- "vue/no-use-v-if-with-v-for": "error",
559
- /**
560
- * Enforce the declaration of emits in the setup function and warn on unused
561
- * emits declarations. This rule helps reduce the risk stale code.
562
- *
563
- * @see https://eslint.vuejs.org/rules/require-explicit-emits.html
564
- * @see https://eslint.vuejs.org/rules/no-unused-emit-declarations.html
565
- */
566
- "vue/require-explicit-emits": "error",
567
- /**
568
- * Enforce the `@` shorthand over `v-on:` and only allow inline callbacks.
569
- * This rule helps to maintain consistency and readability by enforcing a
570
- * predictable order of the event handlers in the component.
571
- *
572
- * @see https://eslint.vuejs.org/rules/v-on-style.html
573
- * @see https://eslint.vuejs.org/rules/v-on-handler-style.html
574
- */
575
- "vue/v-on-style": ["error", "shorthand"],
576
- "vue/v-on-handler-style": ["error", "inline-function"],
577
- "vue/return-in-computed-property": "off",
578
- "vue/no-sparse-arrays": "error",
579
- "vue/no-unused-emit-declarations": "error",
580
- "vue/no-use-v-else-with-v-for": "error",
581
- "vue/no-useless-v-bind": "error",
582
- "vue/no-v-html": "off",
583
- "vue/no-v-text-v-html-on-component": "error",
584
- "vue/object-curly-newline": ["error", { consistent: !0, multiline: !0 }],
585
- "vue/object-curly-spacing": ["error", "always"],
586
- "vue/object-shorthand": [
587
- "error",
588
- "always",
589
- {
590
- avoidQuotes: !0,
591
- ignoreConstructors: !1
592
- }
593
- ],
594
- "vue/operator-linebreak": ["error", "before"],
595
- "vue/prefer-import-from-vue": "off",
596
- "vue/prefer-separate-static-class": "error",
597
- "vue/prefer-template": "error",
598
- "vue/quote-props": ["error", "consistent-as-needed"],
599
- "vue/require-default-prop": "off",
600
- // reactivity transform
601
- "vue/block-tag-newline": ["error", {
602
- multiline: "always",
603
- singleline: "always"
604
- }],
605
- // extensions
606
- "vue/array-bracket-spacing": ["error", "never"],
607
- "vue/arrow-spacing": ["error", { after: !0, before: !0 }],
608
- "vue/block-lang": ["error", { script: { lang: "ts" } }],
609
- "vue/block-spacing": ["error", "always"],
610
- "vue/brace-style": ["error", "stroustrup", { allowSingleLine: !0 }],
611
- "vue/comma-dangle": ["error", "always-multiline"],
612
- "vue/comma-spacing": ["error", { after: !0, before: !1 }],
613
- "vue/comma-style": ["error", "last"],
614
- "vue/component-options-name-casing": ["error", "PascalCase"],
615
- "vue/custom-event-name-casing": ["error", "camelCase"],
616
- "vue/define-macros-order": ["error", {
617
- order: ["defineProps", "defineEmits"]
618
- }],
619
- "vue/dot-location": ["error", "property"],
620
- "vue/dot-notation": ["error", { allowKeywords: !0 }],
621
- "vue/eqeqeq": ["error", "smart"],
622
- "vue/first-attribute-linebreak": ["error", {
623
- multiline: "below",
624
- singleline: "beside"
625
- }],
626
- "vue/html-closing-bracket-newline": ["error", {
627
- multiline: "never",
628
- selfClosingTag: {
629
- multiline: "always",
630
- singleline: "never"
631
- },
632
- singleline: "never"
633
- }],
634
- "vue/no-constant-condition": "warn",
635
- "vue/no-empty-pattern": "error",
636
- "vue/no-extra-parens": ["error", "functions"],
637
- "vue/no-irregular-whitespace": "error",
638
- "vue/no-loss-of-precision": "error",
639
- "vue/no-restricted-syntax": [
640
- "error",
641
- "DebuggerStatement",
642
- "LabeledStatement",
643
- "WithStatement"
644
- ],
645
- "vue/no-restricted-v-bind": ["error", "/^v-/"],
646
- "vue/require-prop-types": "off",
647
- "vue/space-in-parens": ["error", "never"],
648
- "vue/space-infix-ops": "error",
649
- "vue/space-unary-ops": ["error", { nonwords: !1, words: !0 }],
650
- "vue/template-curly-spacing": "error",
191
+ "jsonc/auto": "error",
651
192
  /** User-defined rules */
652
193
  ...options.rules
653
194
  }
654
195
  }
655
196
  ];
656
197
  }
657
- function vitest(options) {
198
+ function jsonPackage() {
658
199
  return [
659
200
  {
660
- plugins: {
661
- vitest: vitestPlugin
662
- },
663
201
  files: [
664
- "**/*.{ts,mts,cts,tsx,d.ts}",
665
- "**/*.{js,mjs,cjs,jsx}"
202
+ "**/package.json"
666
203
  ],
667
- settings: {
668
- vitest: {
669
- typecheck: !0
670
- }
671
- },
672
- languageOptions: {
673
- globals: {
674
- ...vitestPlugin.environments.env.globals,
675
- expectTypeOf: !0
676
- }
677
- },
678
204
  rules: {
679
- /**
680
- * Inject all configuration from eslint-plugin-vitest.
681
- *
682
- * @see https://github.com/veritem/eslint-plugin-vitest/tree/main?tab=readme-ov-file#rules
683
- */
684
- ...vitestPlugin.configs.all.rules,
685
- /**
686
- * This rule aims to enforce having at least one expectation
687
- * in test body to ensure that the test is actually testing something.
688
- *
689
- * @see https://github.com/veritem/eslint-plugin-vitest/blob/main/docs/rules/expect-expect.md
690
- */
691
- "vitest/expect-expect": ["error", {
692
- assertFunctionNames: [
693
- "expect",
694
- "expectTypeOf"
695
- ]
696
- }],
697
- /**
698
- * Disable the conditional test rule as it is prevent's us to use in-source
699
- * testing when using the `if (import.meta.vitest)` condition. Also disable
700
- * the rule that prevents the use of if-else statements in tests as we want
701
- * to use it to test type predicates.
702
- *
703
- * @see https://github.com/veritem/eslint-plugin-vitest/blob/main/docs/rules/no-conditional-in-test.md
704
- */
705
- "vitest/no-conditional-in-test": "off",
706
- "vitest/no-conditional-tests": "off",
707
- /**
708
- * Since we use in-source testing, we need to disable the rule as it may prevent
709
- * us from using top level evaluation that are not part of the test suite.
710
- *
711
- * @see https://github.com/veritem/eslint-plugin-vitest/blob/main/docs/rules/no-hooks.md
712
- */
713
- "vitest/require-hook": "off",
714
- "vitest/no-hooks": "off",
715
- /**
716
- * Disable the rule that enforces the use of `expect.assertions` in tests.
717
- * As much as this rule enforces a best-practice, it is not always necessary.
718
- *
719
- * @see https://github.com/veritem/eslint-plugin-vitest/blob/main/docs/rules/prefer-expect-assertions.md
720
- */
721
- "vitest/prefer-expect-assertions": "off",
722
- /**
723
- * Some functions may have a single test case, and it is not necessary
724
- * to wrap them in a describe block.
725
- *
726
- * @see https://github.com/veritem/eslint-plugin-vitest/blob/main/docs/rules/require-top-level-describe.md
727
- */
728
- "vitest/require-top-level-describe": "off",
729
- /**
730
- * Enforce rule titles starts with 'should'. This is a convention
731
- * to force the developer to write the test in a way that it reads
732
- * like a sentence.
733
- *
734
- * @see https://github.com/veritem/eslint-plugin-vitest/blob/main/docs/rules/valid-title.md
735
- */
736
- "vitest/valid-title": ["error", {
737
- ignoreTypeOfDescribeName: !0,
738
- mustMatch: {
739
- test: ["^should"]
205
+ "jsonc/sort-keys": [
206
+ "error",
207
+ {
208
+ order: [
209
+ "name",
210
+ "type",
211
+ "version",
212
+ "license",
213
+ "private",
214
+ "sideEffects",
215
+ // --- Publishing
216
+ "description",
217
+ "author",
218
+ "keywords",
219
+ "bugs",
220
+ "funding",
221
+ "homepage",
222
+ "repository",
223
+ // --- Distribution
224
+ "bin",
225
+ "main",
226
+ "module",
227
+ "types",
228
+ "typings",
229
+ "browser",
230
+ "exports",
231
+ "files",
232
+ // --- Package Manager
233
+ "packageManager",
234
+ "pnpm",
235
+ // --- Scripts
236
+ "scripts",
237
+ // --- Dependencies
238
+ "peerDependencies",
239
+ "peerDependenciesMeta",
240
+ "optionalDependencies",
241
+ "dependencies",
242
+ "devDependencies",
243
+ "bundledDependencies",
244
+ "bundleDependencies",
245
+ // --- Config
246
+ "tsup",
247
+ "husky",
248
+ "lint-staged",
249
+ "eslintConfig"
250
+ ],
251
+ pathPattern: "^$"
252
+ },
253
+ {
254
+ order: { type: "asc" },
255
+ pathPattern: "^(?:dev|peer|optional|bundled)?[Dd]ependencies$"
740
256
  }
741
- }],
742
- /**
743
- * Disable the prefer-truthy/false rule as we want to allow the use of strict equality checks
744
- * with boolean values.
745
- *
746
- * @see https://github.com/veritem/eslint-plugin-vitest/blob/main/docs/rules/prefer-to-be-truthy.md
747
- * @see https://github.com/veritem/eslint-plugin-vitest/blob/main/docs/rules/prefer-to-be-falsy.md
748
- */
749
- "vitest/prefer-to-be-truthy": "off",
750
- "vitest/prefer-to-be-falsy": "off",
751
- /** User-defined rules */
752
- ...options.rules
257
+ ]
753
258
  }
754
259
  }
755
260
  ];
756
261
  }
757
- const UNICORN_RECOMMENDED_RULES = unicornPlugin.configs.recommended.rules;
758
- function unicorn(options) {
262
+ function jsonTsconfig() {
263
+ return [
264
+ {
265
+ files: [
266
+ "**/tsconfig.json",
267
+ "**/tsconfig.*.json"
268
+ ],
269
+ rules: {
270
+ "jsonc/sort-array-values": [
271
+ "error",
272
+ {
273
+ order: { type: "asc" },
274
+ pathPattern: "^(includes|excludes)$"
275
+ }
276
+ ],
277
+ "jsonc/sort-keys": [
278
+ "error",
279
+ {
280
+ order: [
281
+ "extends",
282
+ "compilerOptions",
283
+ "references",
284
+ "files",
285
+ "include",
286
+ "exclude"
287
+ ],
288
+ pathPattern: "^$"
289
+ },
290
+ {
291
+ order: [
292
+ // --- Project Structure
293
+ "incremental",
294
+ "composite",
295
+ "tsBuildInfoFile",
296
+ "disableSourceOfProjectReferenceRedirect",
297
+ "disableSolutionSearching",
298
+ "disableReferencedProjectLoad",
299
+ // --- Language and Environment
300
+ "target",
301
+ "jsx",
302
+ "jsxFactory",
303
+ "jsxFragmentFactory",
304
+ "jsxImportSource",
305
+ "lib",
306
+ "moduleDetection",
307
+ "noLib",
308
+ "reactNamespace",
309
+ "useDefineForClassFields",
310
+ "emitDecoratorMetadata",
311
+ "experimentalDecorators",
312
+ // --- Module Resolution
313
+ "baseUrl",
314
+ "rootDir",
315
+ "rootDirs",
316
+ "customConditions",
317
+ "module",
318
+ "moduleResolution",
319
+ "moduleSuffixes",
320
+ "noResolve",
321
+ "paths",
322
+ "resolveJsonModule",
323
+ "resolvePackageJsonExports",
324
+ "resolvePackageJsonImports",
325
+ "typeRoots",
326
+ "types",
327
+ "allowArbitraryExtensions",
328
+ "allowImportingTsExtensions",
329
+ "allowUmdGlobalAccess",
330
+ // --- JavaScript Support
331
+ "allowJs",
332
+ "checkJs",
333
+ "maxNodeModuleJsDepth",
334
+ // --- Type Checking
335
+ "strict",
336
+ "strictBindCallApply",
337
+ "strictFunctionTypes",
338
+ "strictNullChecks",
339
+ "strictPropertyInitialization",
340
+ "allowUnreachableCode",
341
+ "allowUnusedLabels",
342
+ "alwaysStrict",
343
+ "exactOptionalPropertyTypes",
344
+ "noFallthroughCasesInSwitch",
345
+ "noImplicitAny",
346
+ "noImplicitOverride",
347
+ "noImplicitReturns",
348
+ "noImplicitThis",
349
+ "noPropertyAccessFromIndexSignature",
350
+ "noUncheckedIndexedAccess",
351
+ "noUnusedLocals",
352
+ "noUnusedParameters",
353
+ "useUnknownInCatchVariables",
354
+ // --- Emitting
355
+ "declaration",
356
+ "declarationDir",
357
+ "declarationMap",
358
+ "downlevelIteration",
359
+ "emitBOM",
360
+ "emitDeclarationOnly",
361
+ "importHelpers",
362
+ "importsNotUsedAsValues",
363
+ "inlineSourceMap",
364
+ "inlineSources",
365
+ "mapRoot",
366
+ "newLine",
367
+ "noEmit",
368
+ "noEmitHelpers",
369
+ "noEmitOnError",
370
+ "outDir",
371
+ "outFile",
372
+ "preserveConstEnums",
373
+ "preserveValueImports",
374
+ "removeComments",
375
+ "sourceMap",
376
+ "sourceRoot",
377
+ "stripInternal",
378
+ // --- Interop Constraints
379
+ "allowSyntheticDefaultImports",
380
+ "esModuleInterop",
381
+ "forceConsistentCasingInFileNames",
382
+ "isolatedModules",
383
+ "preserveSymlinks",
384
+ "verbatimModuleSyntax",
385
+ // --- Completeness
386
+ "skipDefaultLibCheck",
387
+ "skipLibCheck"
388
+ ],
389
+ pathPattern: "^compilerOptions$"
390
+ },
391
+ {
392
+ order: { type: "asc" },
393
+ pathPattern: String.raw`^compilerOptions\.paths$`
394
+ }
395
+ ]
396
+ }
397
+ }
398
+ ];
399
+ }
400
+ function node(options) {
759
401
  return [
760
402
  {
761
403
  plugins: {
762
- unicorn: unicornPlugin
404
+ n: nodePlugin
763
405
  },
764
406
  rules: {
765
- ...UNICORN_RECOMMENDED_RULES,
407
+ ...nodePlugin.configs.recommended.rules,
766
408
  /**
767
- * Improve regexes by making them shorter, consistent, and safer. This rule
768
- * aims to improve readability and consistency of regexes while also
769
- * mitigating regex denial of service attacks by disallowing potentially
770
- * catastrophic backtracking.
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.
771
412
  *
772
- * @see https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/better-regex.md
413
+ * @see https://github.com/eslint-community/eslint-plugin-n/blob/HEAD/docs/rules/no-extraneous-import.md
773
414
  */
774
- "unicorn/better-regex": "error",
415
+ "n/no-extraneous-import": "error",
775
416
  /**
776
- * Enforce the catch clause parameter name to be named `error`. This rule
777
- * aims to enforce a consistent parameter name in catch clauses. The name
778
- * `error` is the most commonly used name for the parameter that is passed
779
- * to the catch clause.
417
+ * Disable the no-missing-import as module resolution is already checked
418
+ * by other tools and IDEs extensively. This rule is redundant.
780
419
  *
781
- * @see https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/catch-error-name.md
420
+ * @see https://github.com/eslint-community/eslint-plugin-n/blob/HEAD/docs/rules/no-missing-import.md
782
421
  */
783
- "unicorn/catch-error-name": ["error", {
784
- name: "error"
785
- }],
786
- /**
787
- * Enforce the use of camelCase or PascalCase when naming folders, files and
788
- * variables. This rule aims to enforce a consistent naming convention for
789
- * filenames, directory names, and variable names.
790
- *
791
- * @see https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/filename-case.md
792
- */
793
- "unicorn/filename-case": ["error", {
794
- cases: {
795
- camelCase: !0,
796
- pascalCase: !0
797
- },
798
- ignore: [
799
- "^[A-Z]+(.md)?$"
800
- ]
801
- }],
422
+ "n/no-missing-import": "off",
423
+ "n/no-missing-require": "off",
424
+ "n/no-unpublished-import": "off",
802
425
  /**
803
- * Disable the recommended import style rules. We want to be able to use both
804
- * named and default imports in our codebase.
426
+ * Enfore the use of the asyncrounous version of the `fs` and `dns` APIs.
805
427
  *
806
- * @see https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/import-style.md
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
807
431
  */
808
- "unicorn/import-style": "off",
432
+ "n/no-sync": "off",
433
+ "n/prefer-promises/fs": "error",
434
+ "n/prefer-promises/dns": "error",
809
435
  /**
810
- * Disallow unsafe regular expressions. Regular expressions can be unsafe
811
- * when they are too complex and can cause catastrophic backtracking. This
812
- * rule disallows regular expressions that can lead to catastrophic
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.
813
438
  *
814
- * @see https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-unsafe-regex.md
439
+ * @see https://github.com/eslint-community/eslint-plugin-n/tree/master/docs/rules
815
440
  */
816
- "unicorn/no-unsafe-regex": "error",
441
+ "n/no-unsupported-features/es-syntax": "error",
442
+ "n/no-unsupported-features/es-builtins": "error",
443
+ "n/no-unsupported-features/node-builtins": "error",
817
444
  /**
818
- * Enforces a convention of grouping digits using numeric separators.
819
- * Long numbers can become really hard to read, so cutting it into groups
820
- * of digits, separated with a _, is important to keep your code clear.
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.
821
448
  *
822
- * @see https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/numeric-separators-style.md
449
+ * @see https://github.com/eslint-community/eslint-plugin-n/blob/HEAD/docs/rules/prefer-node-protocol.md
823
450
  */
824
- "unicorn/numeric-separators-style": ["error", {
825
- onlyIfContainsSeparator: !0
826
- }],
827
- "unicorn/number-literal-case": "error",
828
- "unicorn/consistent-function-scoping": "off",
829
- "unicorn/error-message": "error",
830
- "unicorn/escape-case": "error",
831
- "unicorn/no-array-callback-reference": "off",
832
- "unicorn/no-array-for-each": "off",
833
- "unicorn/no-array-instanceof": "error",
834
- "unicorn/no-new-buffer": "error",
835
- "unicorn/no-static-only-class": "off",
836
- "unicorn/prefer-code-point": "off",
837
- "unicorn/prefer-exponentiation-operator": "error",
838
- "unicorn/prefer-includes": "error",
839
- "unicorn/prefer-module": "off",
840
- "unicorn/prefer-starts-ends-with": "error",
841
- "unicorn/prefer-switch": "off",
842
- "unicorn/prefer-text-content": "error",
843
- "unicorn/prefer-type-error": "error",
844
- "unicorn/prevent-abbreviations": ["error", {
845
- allowList: {
846
- args: !0,
847
- dir: !0,
848
- fn: !0,
849
- i: !0,
850
- j: !0,
851
- k: !0,
852
- props: !0,
853
- Props: !0,
854
- ref: !0,
855
- v: !0,
856
- x: !0,
857
- y: !0,
858
- z: !0
859
- }
860
- }],
861
- "unicorn/throw-new-error": "error"
451
+ "n/prefer-node-protocol": "error",
452
+ /** User-defined rules */
453
+ ...options.rules
862
454
  },
863
- /** User-defined rules */
864
- ...options.rules
455
+ settings: {
456
+ node: {
457
+ version: ">=22.1.0"
458
+ }
459
+ }
865
460
  }
866
461
  ];
867
462
  }
@@ -906,444 +501,913 @@ function sonarjs(options) {
906
501
  }
907
502
  ];
908
503
  }
909
- function node(options) {
504
+ function getConfigRules(config) {
505
+ const rules = toArray(config).flat().map((x) => x.rules);
506
+ return Object.assign({}, ...rules);
507
+ }
508
+ function typescript(options) {
910
509
  return [
510
+ javascript.configs.recommended,
911
511
  {
512
+ languageOptions: {
513
+ // @ts-expect-error: ignore
514
+ parser: tslint.parser,
515
+ parserOptions: {
516
+ ecmaVersion: "latest",
517
+ sourceType: "module",
518
+ project: toArray(options.tsConfigPath ?? "./tsconfig.json"),
519
+ tsconfigRootDir: cwd()
520
+ }
521
+ },
912
522
  plugins: {
913
- n: nodePlugin
523
+ "@typescript-eslint": tslint.plugin,
524
+ "@stylistic": stylistic,
525
+ perfectionist
914
526
  },
527
+ files: [
528
+ "**/*.{ts,tsx,cts,mts}",
529
+ "**/*.{js,jsx,cjs,mjs}"
530
+ ],
915
531
  rules: {
916
- ...nodePlugin.configs.recommended.rules,
917
532
  /**
918
- * Disallow the use of extraneous imports. This rule helps prevent the
919
- * use of third-party modules that are not listed in the project's
920
- * dependencies.
533
+ * Inherit all recommended rules from the `@eslint/js` plugin. This is the base
534
+ * configuration for JavaScript files.
535
+ */
536
+ ...getConfigRules(tslint.configs.recommendedTypeChecked),
537
+ ...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.
921
541
  *
922
- * @see https://github.com/eslint-community/eslint-plugin-n/blob/HEAD/docs/rules/no-extraneous-import.md
542
+ * @see https://eslint.style/rules/default/brace-style
923
543
  */
924
- "n/no-extraneous-import": "error",
544
+ "brace-style": "off",
545
+ "@typescript-eslint/brace-style": "off",
546
+ "@stylistic/brace-style": ["error", "stroustrup", {
547
+ allowSingleLine: !0
548
+ }],
925
549
  /**
926
- * Disable the no-missing-import as module resolution is already checked
927
- * by other tools and IDEs extensively. This rule is redundant.
550
+ * Enforce an indent of 2 spaces. Aims to reduce visual noise and maintain
551
+ * readability of code when viewed on GitHub or GitLab.
928
552
  *
929
- * @see https://github.com/eslint-community/eslint-plugin-n/blob/HEAD/docs/rules/no-missing-import.md
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
930
556
  */
931
- "n/no-missing-import": "off",
932
- "n/no-missing-require": "off",
933
- "n/no-unpublished-import": "off",
557
+ "no-tabs": "off",
558
+ indent: "off",
559
+ "indent-binary-ops": "off",
560
+ "@typescript-eslint/no-tabs": "off",
561
+ "@typescript-eslint/indent": "off",
562
+ "@typescript-eslint/indent-binary-ops": "off",
563
+ "@stylistic/no-tabs": "error",
564
+ "@stylistic/indent": ["error", 2],
565
+ "@stylistic/indent-binary-ops": ["error", 2],
934
566
  /**
935
- * Enfore the use of the asyncrounous version of the `fs` and `dns` APIs.
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.
936
571
  *
937
- * @see https://github.com/eslint-community/eslint-plugin-n/blob/HEAD/docs/rules/no-sync.md
938
- * @see https://github.com/eslint-community/eslint-plugin-n/blob/HEAD/docs/rules/prefer-promises/fs.md
939
- * @see https://github.com/eslint-community/eslint-plugin-n/blob/HEAD/docs/rules/prefer-promises/dns.md
572
+ * @see https://eslint.style/rules/default/semi
940
573
  */
941
- "n/no-sync": "off",
942
- "n/prefer-promises/fs": "error",
943
- "n/prefer-promises/dns": "error",
574
+ semi: "off",
575
+ "@typescript-eslint/semi": "off",
576
+ "@stylistic/semi": ["error", "never"],
944
577
  /**
945
- * Allow the use of features up to Node.js version 20. This will allow
946
- * the use of newer ECMAScript features and Node.js APIs.
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.
947
582
  *
948
- * @see https://github.com/eslint-community/eslint-plugin-n/tree/master/docs/rules
583
+ * @see https://eslint.style/rules/default/linebreak-style
949
584
  */
950
- "n/no-unsupported-features/es-syntax": "error",
951
- "n/no-unsupported-features/es-builtins": "error",
952
- "n/no-unsupported-features/node-builtins": "error",
585
+ "eol-last": "off",
586
+ "no-multiple-empty-lines": "off",
587
+ "@stylistic/eol-last": ["error", "always"],
588
+ "@stylistic/no-multiple-empty-lines": ["error", {
589
+ max: 1,
590
+ maxBOF: 0,
591
+ maxEOF: 0
592
+ }],
953
593
  /**
954
- * Prepend the `node:` prefix to all Node.js core modules. This helps
955
- * identify the module as a Node.js core module and not a third-party
956
- * module.
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.
957
597
  *
958
- * @see https://github.com/eslint-community/eslint-plugin-n/blob/HEAD/docs/rules/prefer-node-protocol.md
598
+ * @see https://eslint.style/rules/default/comma-dangle
599
+ * @see https://eslint.style/rules/default/comma-spacing
959
600
  */
960
- "n/prefer-node-protocol": "error",
961
- /** User-defined rules */
962
- ...options.rules
963
- },
964
- settings: {
965
- node: {
966
- version: ">=22.1.0"
967
- }
968
- }
969
- }
970
- ];
971
- }
972
- function jsonTsconfig() {
973
- return [
974
- {
975
- files: [
976
- "**/tsconfig.json",
977
- "**/tsconfig.*.json"
978
- ],
979
- rules: {
980
- "jsonc/sort-array-values": [
981
- "error",
982
- {
983
- order: { type: "asc" },
984
- pathPattern: "^(includes|excludes)$"
985
- }
986
- ],
987
- "jsonc/sort-keys": [
988
- "error",
989
- {
990
- order: [
991
- "extends",
992
- "compilerOptions",
993
- "references",
994
- "files",
995
- "include",
996
- "exclude"
997
- ],
998
- pathPattern: "^$"
999
- },
1000
- {
1001
- order: [
1002
- // --- Project Structure
1003
- "incremental",
1004
- "composite",
1005
- "tsBuildInfoFile",
1006
- "disableSourceOfProjectReferenceRedirect",
1007
- "disableSolutionSearching",
1008
- "disableReferencedProjectLoad",
1009
- // --- Language and Environment
1010
- "target",
1011
- "jsx",
1012
- "jsxFactory",
1013
- "jsxFragmentFactory",
1014
- "jsxImportSource",
1015
- "lib",
1016
- "moduleDetection",
1017
- "noLib",
1018
- "reactNamespace",
1019
- "useDefineForClassFields",
1020
- "emitDecoratorMetadata",
1021
- "experimentalDecorators",
1022
- // --- Module Resolution
1023
- "baseUrl",
1024
- "rootDir",
1025
- "rootDirs",
1026
- "customConditions",
1027
- "module",
1028
- "moduleResolution",
1029
- "moduleSuffixes",
1030
- "noResolve",
1031
- "paths",
1032
- "resolveJsonModule",
1033
- "resolvePackageJsonExports",
1034
- "resolvePackageJsonImports",
1035
- "typeRoots",
1036
- "types",
1037
- "allowArbitraryExtensions",
1038
- "allowImportingTsExtensions",
1039
- "allowUmdGlobalAccess",
1040
- // --- JavaScript Support
1041
- "allowJs",
1042
- "checkJs",
1043
- "maxNodeModuleJsDepth",
1044
- // --- Type Checking
1045
- "strict",
1046
- "strictBindCallApply",
1047
- "strictFunctionTypes",
1048
- "strictNullChecks",
1049
- "strictPropertyInitialization",
1050
- "allowUnreachableCode",
1051
- "allowUnusedLabels",
1052
- "alwaysStrict",
1053
- "exactOptionalPropertyTypes",
1054
- "noFallthroughCasesInSwitch",
1055
- "noImplicitAny",
1056
- "noImplicitOverride",
1057
- "noImplicitReturns",
1058
- "noImplicitThis",
1059
- "noPropertyAccessFromIndexSignature",
1060
- "noUncheckedIndexedAccess",
1061
- "noUnusedLocals",
1062
- "noUnusedParameters",
1063
- "useUnknownInCatchVariables",
1064
- // --- Emitting
1065
- "declaration",
1066
- "declarationDir",
1067
- "declarationMap",
1068
- "downlevelIteration",
1069
- "emitBOM",
1070
- "emitDeclarationOnly",
1071
- "importHelpers",
1072
- "importsNotUsedAsValues",
1073
- "inlineSourceMap",
1074
- "inlineSources",
1075
- "mapRoot",
1076
- "newLine",
1077
- "noEmit",
1078
- "noEmitHelpers",
1079
- "noEmitOnError",
1080
- "outDir",
1081
- "outFile",
1082
- "preserveConstEnums",
1083
- "preserveValueImports",
1084
- "removeComments",
1085
- "sourceMap",
1086
- "sourceRoot",
1087
- "stripInternal",
1088
- // --- Interop Constraints
1089
- "allowSyntheticDefaultImports",
1090
- "esModuleInterop",
1091
- "forceConsistentCasingInFileNames",
1092
- "isolatedModules",
1093
- "preserveSymlinks",
1094
- "verbatimModuleSyntax",
1095
- // --- Completeness
1096
- "skipDefaultLibCheck",
1097
- "skipLibCheck"
1098
- ],
1099
- pathPattern: "^compilerOptions$"
1100
- },
1101
- {
1102
- order: { type: "asc" },
1103
- pathPattern: String.raw`^compilerOptions\.paths$`
601
+ "comma-dangle": "off",
602
+ "@typescript-eslint/comma-dangle": "off",
603
+ "@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
+ */
616
+ "@typescript-eslint/consistent-indexed-object-style": ["error", "record"],
617
+ "@typescript-eslint/consistent-type-definitions": ["error", "interface"],
618
+ "@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
+ */
627
+ "no-use-before-define": "off",
628
+ "@typescript-eslint/no-use-before-define": ["error", {
629
+ enums: !0,
630
+ classes: !1,
631
+ typedefs: !0,
632
+ variables: !0,
633
+ functions: !1,
634
+ ignoreTypeReferences: !0
635
+ }],
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
+ */
647
+ "key-spacing": "off",
648
+ "comma-spacing": "off",
649
+ "block-spacing": "off",
650
+ "arrow-spacing": "off",
651
+ "spaced-comment": "off",
652
+ "no-multi-spaces": "off",
653
+ "space-before-blocks": "off",
654
+ "lines-around-comment": "off",
655
+ "object-curly-spacing": "off",
656
+ "array-bracket-spacing": "off",
657
+ "array-bracket-newline": "off",
658
+ "function-call-spacing": "off",
659
+ "generator-star-spacing": "off",
660
+ "template-curly-spacing": "off",
661
+ "object-property-newline ": "off",
662
+ "newline-per-chained-call": "off",
663
+ "computed-property-spacing": "off",
664
+ "lines-between-class-members": "off",
665
+ "@typescript-eslint/comma-spacing": "off",
666
+ "@typescript-eslint/object-curly-spacing": "off",
667
+ "@typescript-eslint/type-annotation-spacing": "off",
668
+ "@typescript-eslint/lines-around-comment": "off",
669
+ "@stylistic/key-spacing": ["error", { afterColon: !0, beforeColon: !1 }],
670
+ "@stylistic/comma-spacing": ["error", { after: !0, before: !1 }],
671
+ "@stylistic/arrow-spacing": ["error", { before: !0, after: !0 }],
672
+ "@stylistic/type-generic-spacing": "error",
673
+ "@stylistic/type-named-tuple-spacing": "error",
674
+ "@stylistic/block-spacing": ["error", "always"],
675
+ "@stylistic/no-multi-spaces": "error",
676
+ "@stylistic/keyword-spacing": ["error", { before: !0, after: !0 }],
677
+ "@stylistic/space-before-blocks": ["error", "always"],
678
+ "@stylistic/object-curly-spacing": ["error", "always"],
679
+ "@stylistic/array-bracket-spacing": ["error", "never"],
680
+ "@stylistic/array-bracket-newline": ["error", "consistent"],
681
+ "@stylistic/function-call-spacing": ["error", "never"],
682
+ "@stylistic/template-curly-spacing": ["error", "never"],
683
+ "@stylistic/member-delimiter-style": ["error", { multiline: { delimiter: "none" } }],
684
+ "@stylistic/object-property-newline": ["error", { allowAllPropertiesOnSameLine: !0 }],
685
+ "@stylistic/generator-star-spacing": ["error", { before: !0, after: !0 }],
686
+ "@stylistic/computed-property-spacing": ["error", "never"],
687
+ "@stylistic/multiline-ternary": ["error", "always-multiline"],
688
+ "@stylistic/lines-around-comment": ["error", {
689
+ beforeBlockComment: !0,
690
+ beforeLineComment: !0,
691
+ ignorePattern: String.raw`^(?! ?---|\*)`,
692
+ applyDefaultIgnorePatterns: !0,
693
+ afterHashbangComment: !0
694
+ }],
695
+ "@stylistic/spaced-comment": ["error", "always", {
696
+ block: { markers: ["!"], exceptions: ["*"], balanced: !0 },
697
+ line: { markers: ["/"], exceptions: ["/", "#"] }
698
+ }],
699
+ "@stylistic/lines-between-class-members": ["error", {
700
+ enforce: [{ blankLine: "always", prev: "method", next: "*" }]
701
+ }, {
702
+ exceptAfterSingleLine: !0
703
+ }],
704
+ "@stylistic/type-annotation-spacing": ["error", {
705
+ before: !1,
706
+ after: !0,
707
+ overrides: {
708
+ arrow: { before: !0, after: !0 },
709
+ colon: { before: !1, after: !0 },
710
+ variable: { before: !1, after: !0 },
711
+ property: { before: !1, after: !0 },
712
+ parameter: { before: !1, after: !0 },
713
+ returnType: { before: !1, after: !0 }
1104
714
  }
1105
- ]
715
+ }],
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
+ */
725
+ "@typescript-eslint/prefer-ts-expect-error": "error",
726
+ "@typescript-eslint/ban-ts-comment": ["error", {
727
+ "ts-check": !1,
728
+ "ts-expect-error": "allow-with-description",
729
+ "ts-ignore": !1,
730
+ "ts-nocheck": !1
731
+ }],
732
+ /**
733
+ * Disallow dangling expressions and promises. This rule aims to prevent
734
+ * dangling promises and expressions that are not assigned to a variable.
735
+ * This can lead to bugs and unexpected behavior in the codebase.
736
+ *
737
+ * @see https://eslint.org/docs/rules/no-void
738
+ * @see https://typescript-eslint.io/rules/no-floating-promises
739
+ */
740
+ "no-void": "off",
741
+ "no-unused-expressions": "off",
742
+ "@typescript-eslint/no-unused-expressions": "error",
743
+ "@typescript-eslint/no-floating-promises": ["error", {
744
+ ignoreVoid: !0,
745
+ ignoreIIFE: !0
746
+ }],
747
+ /**
748
+ * Sort imports alphabetically and group them without newlines. This rule
749
+ * aims to maintain consistency around the order of imports in JavaScript
750
+ * files. Helps reduce the visual noise in the codebase.
751
+ *
752
+ * @see https://typescript-eslint.io/rules/consistent-type-imports
753
+ * @see https://eslint-plugin-perfectionist.azat.io/rules/sort-imports
754
+ */
755
+ "sort-imports": "off",
756
+ "@typescript-eslint/consistent-type-imports": ["error", {
757
+ disallowTypeAnnotations: !1,
758
+ prefer: "type-imports",
759
+ fixStyle: "separate-type-imports"
760
+ }],
761
+ "perfectionist/sort-exports": ["error", {
762
+ type: "alphabetical",
763
+ ignoreCase: !0
764
+ }],
765
+ "perfectionist/sort-named-imports": ["error", {
766
+ type: "alphabetical",
767
+ ignoreCase: !0
768
+ }],
769
+ "perfectionist/sort-imports": ["error", {
770
+ newlinesBetween: "never",
771
+ order: "asc",
772
+ ignoreCase: !0,
773
+ groups: [
774
+ "type",
775
+ "internal-type",
776
+ ["parent-type", "sibling-type", "index-type"],
777
+ ["builtin", "external"],
778
+ "internal",
779
+ ["parent", "sibling", "index"],
780
+ "object",
781
+ "unknown"
782
+ ]
783
+ }],
784
+ /**
785
+ * Sort types and union types alphabetically. This rule aims to maintain
786
+ * consistency around the order of types in TypeScript files. Helps reduce
787
+ * the visual noise in the codebase.
788
+ *
789
+ * @see https://perfectionist.dev/rules/sort-union-types
790
+ */
791
+ "@typescript-eslint/sort-type-constituents": "off",
792
+ "perfectionist/sort-intersection-types": ["error", {
793
+ type: "natural"
794
+ }],
795
+ "perfectionist/sort-union-types": ["error", {
796
+ type: "natural",
797
+ ignoreCase: !1
798
+ }],
799
+ /**
800
+ * Enforce no unused variables. Helps keep the codebase clean and reduces
801
+ * the chance of bugs from side-effects.
802
+ *
803
+ * @see https://typescript-eslint.io/rules/@typescript-eslint/no-unused-vars
804
+ */
805
+ "no-redeclare": "off",
806
+ "no-unused-vars": "off",
807
+ "@typescript-eslint/no-redeclare": "error",
808
+ "@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_" }],
809
+ //////////////////////////////////////////////////////////////////////////////////////////
810
+ "no-useless-constructor": "off",
811
+ "@typescript-eslint/ban-types": "off",
812
+ "@typescript-eslint/camelcase": "off",
813
+ "@typescript-eslint/explicit-function-return-type": "off",
814
+ "@typescript-eslint/explicit-member-accessibility": "off",
815
+ "@typescript-eslint/explicit-module-boundary-types": "off",
816
+ "@typescript-eslint/no-empty-function": "off",
817
+ "@typescript-eslint/no-empty-interface": "off",
818
+ "@typescript-eslint/no-explicit-any": "off",
819
+ "@typescript-eslint/no-namespace": "off",
820
+ "@typescript-eslint/no-non-null-assertion": "off",
821
+ "@typescript-eslint/no-parameter-properties": "off",
822
+ "array-callback-return": "error",
823
+ "arrow-body-style": ["error", "as-needed"],
824
+ "arrow-parens": ["error", "as-needed", { requireForBlockBody: !0 }],
825
+ "block-scoped-var": "error",
826
+ camelcase: "off",
827
+ "comma-style": ["error", "last"],
828
+ complexity: ["off", 11],
829
+ "consistent-return": "off",
830
+ curly: ["error", "multi-or-nest", "consistent"],
831
+ eqeqeq: ["error", "smart"],
832
+ "no-alert": "error",
833
+ "no-case-declarations": "error",
834
+ "no-cond-assign": ["error", "always"],
835
+ "no-confusing-arrow": "error",
836
+ "no-console": ["warn", { allow: ["warn", "error"] }],
837
+ "no-constant-condition": "error",
838
+ "no-debugger": "error",
839
+ "no-eval": "error",
840
+ "no-implied-eval": "error",
841
+ "no-multi-str": "error",
842
+ "no-param-reassign": "off",
843
+ "no-restricted-syntax": ["error", "DebuggerStatement", "LabeledStatement", "WithStatement"],
844
+ "no-return-assign": "off",
845
+ "no-return-await": "off",
846
+ "no-trailing-spaces": "error",
847
+ "no-useless-escape": "off",
848
+ "no-var": "error",
849
+ "no-with": "error",
850
+ "object-shorthand": ["error", "always", { avoidQuotes: !0, ignoreConstructors: !1 }],
851
+ "one-var-declaration-per-line": "error",
852
+ "operator-linebreak": ["error", "before"],
853
+ "prefer-arrow-callback": ["error", { allowNamedFunctions: !1, allowUnboundThis: !0 }],
854
+ "prefer-const": ["error", { destructuring: "any", ignoreReadBeforeAssign: !0 }],
855
+ "prefer-rest-params": "error",
856
+ "prefer-spread": "error",
857
+ "prefer-template": "error",
858
+ "quote-props": ["error", "consistent-as-needed"],
859
+ quotes: ["error", "single"],
860
+ "require-await": "off",
861
+ "space-before-function-paren": ["error", "never"],
862
+ "vars-on-top": "error"
863
+ }
864
+ },
865
+ /**
866
+ * Ignore duplicate imports in declaration files as they are often used to re-export
867
+ * types from other packages into multiple namespaces. This is a common pattern
868
+ * in TypeScript declaration files.
869
+ */
870
+ {
871
+ files: ["*.d.ts"],
872
+ rules: {
873
+ "@typescript-eslint/no-use-before-define": "off",
874
+ "import/no-duplicates": "off"
875
+ }
876
+ },
877
+ /**
878
+ * Allow console statements in scripts and CLI files since they are not part of the
879
+ * library / production code and are useful for debugging, logging, and testing.
880
+ */
881
+ {
882
+ files: ["**/scripts/**/*", "cli.*"],
883
+ rules: {
884
+ "no-console": "off"
1106
885
  }
1107
886
  }
1108
887
  ];
1109
888
  }
1110
- function jsonPackage() {
889
+ const UNICORN_RECOMMENDED_RULES = unicornPlugin.configs.recommended.rules;
890
+ function unicorn(options) {
1111
891
  return [
1112
892
  {
1113
- files: [
1114
- "**/package.json"
1115
- ],
893
+ plugins: {
894
+ unicorn: unicornPlugin
895
+ },
1116
896
  rules: {
1117
- "jsonc/sort-keys": [
1118
- "error",
1119
- {
1120
- order: [
1121
- "name",
1122
- "type",
1123
- "version",
1124
- "license",
1125
- "private",
1126
- "sideEffects",
1127
- // --- Publishing
1128
- "description",
1129
- "author",
1130
- "keywords",
1131
- "bugs",
1132
- "funding",
1133
- "homepage",
1134
- "repository",
1135
- // --- Distribution
1136
- "bin",
1137
- "main",
1138
- "module",
1139
- "types",
1140
- "typings",
1141
- "browser",
1142
- "exports",
1143
- "files",
1144
- // --- Package Manager
1145
- "packageManager",
1146
- "pnpm",
1147
- // --- Scripts
1148
- "scripts",
1149
- // --- Dependencies
1150
- "peerDependencies",
1151
- "peerDependenciesMeta",
1152
- "optionalDependencies",
1153
- "dependencies",
1154
- "devDependencies",
1155
- "bundledDependencies",
1156
- "bundleDependencies",
1157
- // --- Config
1158
- "tsup",
1159
- "husky",
1160
- "lint-staged",
1161
- "eslintConfig"
1162
- ],
1163
- pathPattern: "^$"
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
+ */
906
+ "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
+ */
925
+ "unicorn/filename-case": ["error", {
926
+ cases: {
927
+ camelCase: !0,
928
+ pascalCase: !0
1164
929
  },
1165
- {
1166
- order: { type: "asc" },
1167
- pathPattern: "^(?:dev|peer|optional|bundled)?[Dd]ependencies$"
930
+ ignore: [
931
+ "^[A-Z]+(.md)?$"
932
+ ]
933
+ }],
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
+ */
956
+ "unicorn/numeric-separators-style": ["error", {
957
+ onlyIfContainsSeparator: !0
958
+ }],
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",
976
+ "unicorn/prevent-abbreviations": ["error", {
977
+ allowList: {
978
+ args: !0,
979
+ dir: !0,
980
+ fn: !0,
981
+ i: !0,
982
+ j: !0,
983
+ k: !0,
984
+ ref: !0,
985
+ Ref: !0,
986
+ props: !0,
987
+ Props: !0,
988
+ v: !0,
989
+ x: !0,
990
+ y: !0,
991
+ z: !0
1168
992
  }
1169
- ]
1170
- }
993
+ }],
994
+ "unicorn/throw-new-error": "error"
995
+ },
996
+ /** User-defined rules */
997
+ ...options.rules
1171
998
  }
1172
999
  ];
1173
1000
  }
1174
- function configJson(options) {
1001
+ function vitest(options) {
1175
1002
  return [
1176
- ...jsonc.configs["flat/recommended-with-json"],
1177
1003
  {
1004
+ plugins: {
1005
+ vitest: vitestPlugin
1006
+ },
1178
1007
  files: [
1179
- "**/*.json",
1180
- "**/*.json5"
1008
+ "**/*.{ts,mts,cts,tsx,d.ts}",
1009
+ "**/*.{js,mjs,cjs,jsx}"
1181
1010
  ],
1011
+ settings: {
1012
+ vitest: {
1013
+ typecheck: !0
1014
+ }
1015
+ },
1016
+ languageOptions: {
1017
+ globals: {
1018
+ ...vitestPlugin.environments.env.globals,
1019
+ expectTypeOf: !0
1020
+ }
1021
+ },
1182
1022
  rules: {
1183
1023
  /**
1184
- * Automatically apply jsonc rules similar to your configured ESLint core rules to JSON.
1024
+ * Inject all configuration from eslint-plugin-vitest.
1185
1025
  *
1186
- * @see https://ota-meshi.github.io/eslint-plugin-jsonc/rules/auto.html
1026
+ * @see https://github.com/veritem/eslint-plugin-vitest/tree/main?tab=readme-ov-file#rules
1187
1027
  */
1188
- "jsonc/auto": "error",
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
+ */
1035
+ "vitest/expect-expect": ["error", {
1036
+ assertFunctionNames: [
1037
+ "expect",
1038
+ "expectTypeOf"
1039
+ ]
1040
+ }],
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
+ */
1080
+ "vitest/valid-title": ["error", {
1081
+ ignoreTypeOfDescribeName: !0,
1082
+ mustMatch: {
1083
+ test: ["^should"]
1084
+ }
1085
+ }],
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
+ */
1093
+ "vitest/prefer-to-be-truthy": "off",
1094
+ "vitest/prefer-to-be-falsy": "off",
1189
1095
  /** User-defined rules */
1190
1096
  ...options.rules
1191
1097
  }
1192
1098
  }
1193
1099
  ];
1194
1100
  }
1195
- function jsdoc(options) {
1101
+ function vue(options) {
1102
+ const TYPESCRIPT_CONFIG = typescript(options).at(1);
1196
1103
  return [
1197
- pluginJsdoc.configs["flat/recommended-typescript-flavor-error"],
1104
+ ...vuePlugin.configs?.["flat/base"],
1198
1105
  {
1106
+ plugins: {
1107
+ vue: vuePlugin,
1108
+ ...TYPESCRIPT_CONFIG.plugins
1109
+ },
1110
+ languageOptions: {
1111
+ globals: {
1112
+ computed: "readonly",
1113
+ defineEmits: "readonly",
1114
+ defineExpose: "readonly",
1115
+ defineProps: "readonly",
1116
+ onMounted: "readonly",
1117
+ onUnmounted: "readonly",
1118
+ reactive: "readonly",
1119
+ ref: "readonly",
1120
+ shallowReactive: "readonly",
1121
+ shallowRef: "readonly",
1122
+ toRef: "readonly",
1123
+ toRefs: "readonly",
1124
+ watch: "readonly",
1125
+ watchEffect: "readonly"
1126
+ },
1127
+ parser: vueParser,
1128
+ parserOptions: {
1129
+ parser: tslint.parser,
1130
+ extraFileExtensions: [".vue"],
1131
+ ...TYPESCRIPT_CONFIG.languageOptions.parserOptions
1132
+ }
1133
+ },
1134
+ processor: mergeProcessors([
1135
+ // @ts-expect-error: ignore
1136
+ vuePlugin.processors[".vue"],
1137
+ vueProcessorBlocks()
1138
+ ]),
1199
1139
  files: [
1200
- "**/*.{ts,mts,cts,tsx,d.ts}",
1201
- "**/*.{js,mjs,cjs,jsx}",
1202
1140
  "**/*.vue"
1203
1141
  ],
1204
1142
  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,
1205
1150
  /**
1206
- * Enforce a consistent padding of the block description.
1207
- *
1208
- * @see https://github.com/gajus/eslint-plugin-jsdoc/blob/HEAD/docs/rules/check-alignment.md#readme
1151
+ * Disable some TypeScript rules that may conflict with the Vue SFC parser.
1209
1152
  */
1210
- "jsdoc/check-alignment": "error",
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",
1211
1158
  /**
1212
- * Normalize the indentation in the JSdoc comment to improve readability.
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.
1213
1162
  *
1214
- * @see https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/check-indentation.md#readme
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
1215
1165
  */
1216
- "jsdoc/check-indentation": "error",
1166
+ // '@typescript-eslint/consistent-type-imports': ['error', {
1167
+ // disallowTypeAnnotations: false,
1168
+ // fixStyle: 'inline-type-imports',
1169
+ // prefer: 'type-imports',
1170
+ // }],
1217
1171
  /**
1218
- * Enforce a strict set of tags for the JSDoc comment. This rule also includes
1219
- * some custom tags that are used in our projects.
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.
1220
1175
  *
1221
- * @see https://github.com/gajus/eslint-plugin-jsdoc/blob/main/.README/rules/check-tag-names.md
1176
+ * @see https://eslint.vuejs.org/rules/ordered-component-elements.html
1222
1177
  */
1223
- "jsdoc/require-jsdoc": "off",
1224
- "jsdoc/require-param-type": "off",
1225
- "jsdoc/check-tag-names": ["error", {
1226
- definedTags: [
1227
- "category"
1178
+ "vue/block-order": ["error", {
1179
+ order: [
1180
+ "docs",
1181
+ "script",
1182
+ "template",
1183
+ "style"
1228
1184
  ]
1229
1185
  }],
1230
1186
  /**
1231
- * Checks for multi-line-style comments which fail to meet the criteria of a jsdoc block,
1232
- * namely that it should begin with two and only two asterisks.
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.
1233
1190
  *
1234
- * @see https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/no-bad-blocks.md
1191
+ * @see https://eslint.vuejs.org/rules/vue/prefer-define-options.html
1192
+ * @see https://eslint.vuejs.org/rules/vue/component-api-style.html
1235
1193
  */
1236
- "jsdoc/no-bad-blocks": "error",
1194
+ "vue/prefer-define-options": "error",
1195
+ "vue/component-api-style": ["error", ["script-setup"]],
1237
1196
  /**
1238
- * It is common practice to prefix a hyphen to parameters in JSDoc. But this
1239
- * is sometimes forgotten and has no real purpose. This rule aims to enforce
1240
- * that no hyphen is used.
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.
1241
1200
  *
1242
- * @see https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-hyphen-before-param-description
1201
+ * @see https://eslint.vuejs.org/rules/component-name-in-template-casing.html
1243
1202
  */
1244
- "jsdoc/require-hyphen-before-param-description": ["error", "never"],
1203
+ "vue/component-name-in-template-casing": ["error", "PascalCase", {
1204
+ ignores: [String.raw`/\./`],
1205
+ registeredComponentsOnly: !1
1206
+ }],
1245
1207
  /**
1246
- * Since we are using TypeScript, we don't need to enforce types in JSDoc.
1208
+ * Enforce consistent spacing between HTML comments and their content.
1247
1209
  *
1248
- * @see https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-param-type.md
1210
+ * @see https://eslint.vuejs.org/rules/html-comment-content-spacing.html
1211
+ * @see https://eslint.vuejs.org/rules/html-comment-content-newline.html
1249
1212
  */
1250
- "jsdoc/require-returns-type": "off",
1213
+ "vue/html-comment-content-spacing": ["error", "always"],
1214
+ "vue/html-comment-content-newline": ["error", {
1215
+ multiline: "always",
1216
+ singleline: "never"
1217
+ }],
1251
1218
  /**
1252
- * Enforce a new-line between the JSDoc summary and tags. Aims to improve
1253
- * readability by separating the summary and tags.
1219
+ * Enforce consistent spacing between HTML / Component tags. This makes it
1220
+ * easier to read and understand the structure of the component.
1254
1221
  *
1255
- * @see https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/tag-lines.md
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
1256
1225
  */
1257
- "jsdoc/tag-lines": ["error", "any", { startLines: 1 }],
1258
- /** User-defined rules */
1259
- ...options.rules
1260
- }
1261
- }
1262
- ];
1263
- }
1264
- function eslintComments(options) {
1265
- return [
1266
- {
1267
- plugins: {
1268
- "eslint-comments": eslintCommentsPlugin
1269
- },
1270
- rules: {
1226
+ "vue/block-spacing": ["error", "always"],
1227
+ "vue/padding-line-between-blocks": ["error", "always"],
1228
+ "vue/padding-line-between-tags": ["error", [
1229
+ { blankLine: "consistent", next: "*", prev: "*" },
1230
+ { blankLine: "always", next: "*", prev: "comment" }
1231
+ ]],
1232
+ "vue/html-comment-indent": ["error", 2],
1233
+ "vue/multiline-html-element-content-newline": ["error", {
1234
+ allowEmptyLines: !0,
1235
+ ignores: [],
1236
+ ignoreWhenEmpty: !0
1237
+ }],
1271
1238
  /**
1272
- * Allow multiple rules directive in a single comment. This
1273
- * reduces the number of comments in the code.
1239
+ * Enforce consistent spacing and newlines in the template. This rule helps
1240
+ * to maintain consistency and readability by enforcing a predictable
1274
1241
  *
1275
- * @see https://mysticatea.github.io/eslint-plugin-eslint-comments/rules/disable-enable-pair
1242
+ * @see https://eslint.vuejs.org/rules/html-indent.html
1243
+ * @see https://eslint.vuejs.org/rules/max-attributes-per-line.html
1244
+ * @see https://eslint.vuejs.org/rules/html-closing-bracket-newline.html
1276
1245
  */
1277
- "eslint-comments/disable-enable-pair": "off",
1246
+ "vue/html-indent": ["error", 2, {
1247
+ alignAttributesVertically: !0,
1248
+ attribute: 1,
1249
+ baseIndent: 1,
1250
+ closeBracket: 0,
1251
+ ignores: []
1252
+ }],
1253
+ // 'vue/func-call-spacing': ['off', 'never'],
1254
+ "vue/key-spacing": ["error", { afterColon: !0, beforeColon: !1 }],
1255
+ "vue/keyword-spacing": ["error", { after: !0, before: !0 }],
1256
+ "vue/max-attributes-per-line": ["error", {
1257
+ multiline: { max: 1 },
1258
+ singleline: { max: 5 }
1259
+ }],
1278
1260
  /**
1279
- * `eslint-enable` directive-comments can enable rules which are disabled by different
1280
- * eslint-disable directive-comments. It can enable a rule unintentionally. This rule
1281
- * will report such cases.
1261
+ * Allow single-word component names. This rule is disabled because we use
1262
+ * pascal-casing to distinguish between components and HTML elements.
1282
1263
  *
1283
- * @see https://mysticatea.github.io/eslint-plugin-eslint-comments/rules/no-aggregating-enable
1264
+ * @see https://eslint.vuejs.org/rules/multi-word-component-names.html
1284
1265
  */
1285
- "eslint-comments/no-aggregating-enable": "error",
1266
+ "vue/multi-word-component-names": "off",
1267
+ "vue/no-reserved-component-names": "off",
1286
1268
  /**
1287
- * Disallow duplicate eslint-disable comments. This rule will report when there are
1288
- * multiple eslint-disable comments for the same rule, either in the same line or enabled
1289
- * by different eslint-disable comments.
1269
+ * Reports the destructuring or member expression of props passed to setup
1270
+ * causing the value to lose reactivity. This rule helps to avoid common
1271
+ * pitfalls when using the Composition API.
1290
1272
  *
1291
- * @see https://mysticatea.github.io/eslint-plugin-eslint-comments/rules/no-duplicate-disable
1273
+ * @see https://eslint.vuejs.org/rules/no-setup-props-reactivity-loss.html
1292
1274
  */
1293
- "eslint-comments/no-duplicate-disable": "error",
1275
+ "vue/no-setup-props-reactivity-loss": "error",
1294
1276
  /**
1295
- * Disallow eslint-disable comments without rule names. This ensures that we cannot
1296
- * disable all rules in a file using eslint-disable comment.
1277
+ * Disallow v-if in v-for. This rule helps to avoid common pitfalls when
1278
+ * using v-if and v-for together in the same element.
1297
1279
  *
1298
- * @see https://mysticatea.github.io/eslint-plugin-eslint-comments/rules/no-unlimited-disable
1280
+ * @see https://eslint.vuejs.org/rules/no-use-v-if-with-v-for.html
1299
1281
  */
1300
- "eslint-comments/no-unlimited-disable": "error",
1282
+ "vue/no-use-v-if-with-v-for": "error",
1301
1283
  /**
1302
- * Errors when an eslint-disable comment has no effect. This is useful
1303
- * to prevent unnecessary comments in the code.
1284
+ * Enforce the declaration of emits in the setup function and warn on unused
1285
+ * emits declarations. This rule helps reduce the risk stale code.
1304
1286
  *
1305
- * @see https://mysticatea.github.io/eslint-plugin-eslint-comments/rules/no-unused-disable
1287
+ * @see https://eslint.vuejs.org/rules/require-explicit-emits.html
1288
+ * @see https://eslint.vuejs.org/rules/no-unused-emit-declarations.html
1306
1289
  */
1307
- "eslint-comments/no-unused-disable": "error",
1308
- /** User-defined rules */
1309
- ...options.rules
1310
- }
1311
- }
1312
- ];
1313
- }
1314
- function antfu(options) {
1315
- return [
1316
- {
1317
- plugins: {
1318
- antfu: pluginAntfu
1319
- },
1320
- rules: {
1321
- "antfu/consistent-list-newline": "error",
1290
+ "vue/require-explicit-emits": "error",
1322
1291
  /**
1323
- * Auto-fix import duplication. The TypeScript compiler already detects and removes
1324
- * duplicate imports, but this rule can be used to fix the issue automatically in the editor.
1292
+ * Enforce the `@` shorthand over `v-on:` and only allow inline callbacks.
1293
+ * This rule helps to maintain consistency and readability by enforcing a
1294
+ * predictable order of the event handlers in the component.
1325
1295
  *
1326
- * @see https://github.com/antfu/eslint-plugin-antfu/blob/main/src/rules/import-dedupe.md
1296
+ * @see https://eslint.vuejs.org/rules/v-on-style.html
1297
+ * @see https://eslint.vuejs.org/rules/v-on-handler-style.html
1327
1298
  */
1328
- "antfu/import-dedupe": "error",
1299
+ "vue/v-on-style": ["error", "shorthand"],
1300
+ "vue/v-on-handler-style": ["error", "inline-function"],
1329
1301
  /**
1330
- * Enforce top-level function to be declared using function instead of arrow function. This
1331
- * rule helps when you want to add additional overload signatures to a function without
1332
- * having to transform the arrow function into a function declaration manually.
1333
- *
1334
- * On top of that, it mitigates the risk of accidentally using the `this` instance from
1335
- * an outer scope.
1302
+ * Sort the vue attributes in a consistent order. This rule helps to maintain
1303
+ * consistency and readability by enforcing a predictable order of the
1304
+ * attributes in the component.
1336
1305
  *
1337
- * @see https://github.com/antfu/eslint-plugin-antfu/blob/main/src/rules/top-level-function.md
1306
+ * @see https://eslint.vuejs.org/rules/attributes-order.html
1338
1307
  */
1339
- "antfu/top-level-function": "error",
1308
+ "vue/attributes-order": ["error", {
1309
+ order: [
1310
+ "DEFINITION",
1311
+ "LIST_RENDERING",
1312
+ "CONDITIONALS",
1313
+ "RENDER_MODIFIERS",
1314
+ "GLOBAL",
1315
+ ["UNIQUE", "SLOT"],
1316
+ "TWO_WAY_BINDING",
1317
+ "OTHER_DIRECTIVES",
1318
+ "OTHER_ATTR",
1319
+ "EVENTS",
1320
+ "CONTENT"
1321
+ ],
1322
+ alphabetical: !1
1323
+ }],
1340
1324
  /**
1341
- * Enforce consistent line breaks inside braces of object/array/named imports/exports and
1342
- * function parameters. Reduces the cognitive load of reasoning about code style.
1325
+ * Enforce consistent spacing around attribute assignments. This ensures that
1326
+ * the code is easier to read and maintain.
1343
1327
  *
1344
- * @see https://github.com/antfu/eslint-plugin-antfu/blob/main/src/rules/consistent-list-newline.md
1328
+ * @see https://eslint.vuejs.org/rules/no-spaces-around-equal-signs-in-attribute.html
1345
1329
  */
1346
- "object-curly-newline": "off",
1330
+ "vue/no-spaces-around-equal-signs-in-attribute": "error",
1331
+ "vue/no-multi-spaces": "error",
1332
+ /**
1333
+ * Enforce the use of the `ts` lang attribute in the script block. This rule
1334
+ * explicitly dissallows the use of the `js` lang attribute in the script.
1335
+ */
1336
+ "vue/block-lang": ["error", {
1337
+ script: { lang: "ts" }
1338
+ }],
1339
+ "vue/return-in-computed-property": "off",
1340
+ "vue/no-sparse-arrays": "error",
1341
+ "vue/no-unused-emit-declarations": "error",
1342
+ "vue/no-use-v-else-with-v-for": "error",
1343
+ "vue/no-useless-v-bind": "error",
1344
+ "vue/no-v-html": "off",
1345
+ "vue/no-v-text-v-html-on-component": "error",
1346
+ "vue/object-curly-newline": ["error", { consistent: !0, multiline: !0 }],
1347
+ "vue/object-curly-spacing": ["error", "always"],
1348
+ "vue/object-shorthand": [
1349
+ "error",
1350
+ "always",
1351
+ {
1352
+ avoidQuotes: !0,
1353
+ ignoreConstructors: !1
1354
+ }
1355
+ ],
1356
+ "vue/operator-linebreak": ["error", "before"],
1357
+ "vue/prefer-import-from-vue": "off",
1358
+ "vue/prefer-separate-static-class": "error",
1359
+ "vue/prefer-template": "error",
1360
+ "vue/quote-props": ["error", "consistent-as-needed"],
1361
+ "vue/require-default-prop": "off",
1362
+ // reactivity transform
1363
+ "vue/block-tag-newline": ["error", {
1364
+ multiline: "always",
1365
+ singleline: "always"
1366
+ }],
1367
+ // extensions
1368
+ "vue/array-bracket-spacing": ["error", "never"],
1369
+ "vue/arrow-spacing": ["error", { after: !0, before: !0 }],
1370
+ "vue/brace-style": ["error", "stroustrup", { allowSingleLine: !0 }],
1371
+ "vue/comma-dangle": ["error", "always-multiline"],
1372
+ "vue/comma-spacing": ["error", { after: !0, before: !1 }],
1373
+ "vue/comma-style": ["error", "last"],
1374
+ "vue/component-options-name-casing": ["error", "PascalCase"],
1375
+ "vue/custom-event-name-casing": ["error", "camelCase"],
1376
+ "vue/define-macros-order": ["error", {
1377
+ order: ["defineProps", "defineEmits"]
1378
+ }],
1379
+ "vue/dot-location": ["error", "property"],
1380
+ "vue/dot-notation": ["error", { allowKeywords: !0 }],
1381
+ "vue/eqeqeq": ["error", "smart"],
1382
+ "vue/first-attribute-linebreak": ["error", {
1383
+ multiline: "below",
1384
+ singleline: "beside"
1385
+ }],
1386
+ "vue/html-closing-bracket-newline": ["error", {
1387
+ multiline: "never",
1388
+ selfClosingTag: {
1389
+ multiline: "always",
1390
+ singleline: "never"
1391
+ },
1392
+ singleline: "never"
1393
+ }],
1394
+ "vue/no-constant-condition": "warn",
1395
+ "vue/no-empty-pattern": "error",
1396
+ "vue/no-extra-parens": ["error", "functions"],
1397
+ "vue/no-irregular-whitespace": "error",
1398
+ "vue/no-loss-of-precision": "error",
1399
+ "vue/no-restricted-syntax": [
1400
+ "error",
1401
+ "DebuggerStatement",
1402
+ "LabeledStatement",
1403
+ "WithStatement"
1404
+ ],
1405
+ "vue/no-restricted-v-bind": ["error", "/^v-/"],
1406
+ "vue/require-prop-types": "off",
1407
+ "vue/space-in-parens": ["error", "never"],
1408
+ "vue/space-infix-ops": "error",
1409
+ "vue/space-unary-ops": ["error", { nonwords: !1, words: !0 }],
1410
+ "vue/template-curly-spacing": "error",
1347
1411
  /** User-defined rules */
1348
1412
  ...options.rules
1349
1413
  }