@unshared/eslint-config 0.0.14 → 0.0.16

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