@unshared/eslint-config 0.0.14 → 0.0.16

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