@unshared/eslint-config 0.0.14 → 0.0.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.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
  }