@ntnyq/eslint-config 5.4.0 → 5.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/index.d.ts +17239 -0
  2. package/dist/index.js +3175 -0
  3. package/package.json +19 -21
package/dist/index.js ADDED
@@ -0,0 +1,3175 @@
1
+ import { FlatConfigComposer } from "eslint-flat-config-utils";
2
+ import { mergeProcessors, mergeProcessors as mergeProcessors$1, processorPassThrough } from "eslint-merge-processors";
3
+ import { configs as configsTypeScript, parser as parserTypeScript, plugin as pluginTypeScript } from "typescript-eslint";
4
+ import * as parserVue from "vue-eslint-parser";
5
+ import * as parserToml from "toml-eslint-parser";
6
+ import * as parserYaml from "yaml-eslint-parser";
7
+ import * as parserPlain from "eslint-parser-plain";
8
+ import * as parserJsonc from "jsonc-eslint-parser";
9
+ import * as pluginRegexp from "eslint-plugin-regexp";
10
+ import pluginNode from "eslint-plugin-n";
11
+ import pluginVue from "eslint-plugin-vue";
12
+ import pluginYml from "eslint-plugin-yml";
13
+ import pluginSvgo from "eslint-plugin-svgo";
14
+ import pluginToml from "eslint-plugin-toml";
15
+ import pluginMarkdown from "@eslint/markdown";
16
+ import pluginAntfu from "eslint-plugin-antfu";
17
+ import pluginJsdoc from "eslint-plugin-jsdoc";
18
+ import pluginJsonc from "eslint-plugin-jsonc";
19
+ import pluginNtnyq from "eslint-plugin-ntnyq";
20
+ import pluginPinia from "eslint-plugin-pinia";
21
+ import pluginDepend from "eslint-plugin-depend";
22
+ import pluginUnoCSS from "@unocss/eslint-plugin";
23
+ import pluginVitest from "@vitest/eslint-plugin";
24
+ import pluginUnicorn from "eslint-plugin-unicorn";
25
+ import pluginImportX from "eslint-plugin-import-x";
26
+ import pluginPrettier from "eslint-plugin-prettier";
27
+ import pluginDeMorgan from "eslint-plugin-de-morgan";
28
+ import pluginNoOnlyTests from "eslint-plugin-no-only-tests";
29
+ import pluginGitHubAction from "eslint-plugin-github-action";
30
+ import pluginPerfectionist from "eslint-plugin-perfectionist";
31
+ import pluginComments from "@eslint-community/eslint-plugin-eslint-comments";
32
+ import processorVueBlocks from "eslint-processor-vue-blocks";
33
+ import { resolve } from "node:path";
34
+ import process from "node:process";
35
+ import { isPackageExists } from "local-pkg";
36
+ import { builtinCommands, defineCommand } from "eslint-plugin-command/commands";
37
+ import createCommandConfig from "eslint-plugin-command/config";
38
+ import { createTypeScriptImportResolver } from "eslint-import-resolver-typescript";
39
+ import globals from "globals";
40
+ import createGitIgnoreConfig from "eslint-config-flat-gitignore";
41
+ import jsConfig from "@eslint/js";
42
+
43
+ //#region src/globs.ts
44
+ /**
45
+ * @file globs constants
46
+ */
47
+ const GLOB_SRC_EXT = "?([cm])[jt]s?(x)";
48
+ const GLOB_SRC = `**/*.${GLOB_SRC_EXT}`;
49
+ const GLOB_JS = "**/*.?([cm])js";
50
+ const GLOB_JSX = `${GLOB_JS}x`;
51
+ const GLOB_JSX_ONLY = "**/*.jsx";
52
+ const GLOB_TS = "**/*.?([cm])ts";
53
+ const GLOB_TSX = `${GLOB_TS}x`;
54
+ const GLOB_TSX_ONLY = "**/*.tsx";
55
+ const GLOB_DTS = "**/*.d.?([cm])ts";
56
+ const GLOB_TYPES = [
57
+ GLOB_DTS,
58
+ `**/types/${GLOB_TS}`,
59
+ `**/types.ts`
60
+ ];
61
+ const GLOB_TYPE_TEST = [`**/*.test-d.${GLOB_SRC_EXT}`, `**/*.spec-d.${GLOB_SRC_EXT}`];
62
+ const GLOB_TEST = [
63
+ `**/*.test.${GLOB_SRC_EXT}`,
64
+ `**/*.spec.${GLOB_SRC_EXT}`,
65
+ `**/*.bench.${GLOB_SRC_EXT}`,
66
+ `**/*.benchmark.${GLOB_SRC_EXT}`,
67
+ ...GLOB_TYPE_TEST
68
+ ];
69
+ const GLOB_STYLE = "**/*.{c,le,sc}ss";
70
+ const GLOB_CSS = "**/*.css";
71
+ const GLOB_LESS = "**/*.less";
72
+ const GLOB_SCSS = "**/*.scss";
73
+ const GLOB_POSTCSS = "**/*.{p,post}css";
74
+ const GLOB_JSON = "**/*.json";
75
+ const GLOB_JSON5 = "**/*.json5";
76
+ const GLOB_JSONC = "**/*.jsonc";
77
+ const GLOB_PACKAGE_JSON = "**/package.json";
78
+ const GLOB_JSON_SCHEMA = ["**/*.schema.json", "**/schemas/*.json"];
79
+ const GLOB_TSCONFIG_JSON = ["**/tsconfig.json", "**/tsconfig.*.json"];
80
+ const GLOB_YAML = "**/*.y?(a)ml";
81
+ const GLOB_PNPM_WORKSPACE_YAML = "**/pnpm-workspace.yaml";
82
+ const GLOB_SVG = "**/*.svg";
83
+ const GLOB_VUE = "**/*.vue";
84
+ const GLOB_SVELTE = "**/*.svelte?(.{js,ts})";
85
+ const GLOB_TOML = "**/*.toml";
86
+ const GLOB_HTML = "**/*.htm?(l)";
87
+ const GLOB_ASTRO = "**/*.astro";
88
+ const GLOB_ASTRO_TS = "**/*.astro/*.ts";
89
+ const GLOB_MARKDOWN = "**/*.md";
90
+ const GLOB_MARKDOWN_CODE = `${GLOB_MARKDOWN}/${GLOB_SRC}`;
91
+ const GLOB_MARKDOWN_NESTED = `${GLOB_MARKDOWN}/*.md`;
92
+ const GLOB_ALL_SRC = [
93
+ GLOB_SRC,
94
+ GLOB_STYLE,
95
+ GLOB_JSON,
96
+ GLOB_JSON5,
97
+ GLOB_VUE,
98
+ GLOB_YAML,
99
+ GLOB_TOML,
100
+ GLOB_HTML,
101
+ GLOB_MARKDOWN
102
+ ];
103
+ const GLOB_PINIA_STORE = `**/store?(s)/*.${GLOB_SRC_EXT}`;
104
+ const GLOB_GITHUB_ACTION = "**/.github/workflows/*.y?(a)ml";
105
+ const GLOB_NODE_MODULES = "**/node_modules/**";
106
+ const GLOB_DIST = "**/dist/**";
107
+ const GLOB_LOCKFILE = [
108
+ "**/package-lock.json",
109
+ "**/yarn.lock",
110
+ "**/pnpm-lock.yaml",
111
+ "**/bun.lock?(b)",
112
+ "**/deno.lock"
113
+ ];
114
+ const GLOB_EXCLUDE = [
115
+ GLOB_NODE_MODULES,
116
+ GLOB_DIST,
117
+ ...GLOB_LOCKFILE,
118
+ "**/.pnpm-store/**",
119
+ "!.github",
120
+ "!.vitepress",
121
+ "!.vuepress",
122
+ "!.vscode",
123
+ "**/CHANGELOG*.md",
124
+ "**/*.min.*",
125
+ "**/LICENSE*",
126
+ "**/__snapshots__",
127
+ "**/auto-import?(s).d.ts",
128
+ "**/components.d.ts",
129
+ "**/typed-router.d.ts",
130
+ "**/uni-pages.d.ts",
131
+ "**/coverage",
132
+ "**/fixtures",
133
+ "**/output",
134
+ "**/public",
135
+ "**/static",
136
+ "**/?(.)temp",
137
+ "**/?(.)cache",
138
+ "**/.eslintcache",
139
+ "**/.stylelintcache",
140
+ "**/.eslint-config-inspector",
141
+ "**/.vite-inspect",
142
+ "**/.nuxt",
143
+ "**/.wxt",
144
+ "**/.output",
145
+ "**/.tsup",
146
+ "**/.nitro",
147
+ "**/.vercel",
148
+ "**/.wrangler",
149
+ "**/.changeset",
150
+ "**/.npmrc",
151
+ "**/.yarnrc",
152
+ "**/.husky",
153
+ "**/src-tauri/gen",
154
+ "**/src-tauri/target"
155
+ ];
156
+
157
+ //#endregion
158
+ //#region src/configs/vue.ts
159
+ const sharedRules = {
160
+ ...pluginVue.configs.base.rules,
161
+ ...pluginVue.configs.essential.rules,
162
+ ...pluginVue.configs["strongly-recommended"].rules,
163
+ ...pluginVue.configs.recommended.rules
164
+ };
165
+ const disabledRules$1 = {
166
+ "vue/multi-word-component-names": "off",
167
+ "vue/no-setup-props-reactivity-loss": "off",
168
+ "vue/no-v-html": "off",
169
+ "vue/no-v-text-v-html-on-component": "off",
170
+ "vue/require-default-prop": "off",
171
+ "vue/require-prop-types": "off"
172
+ };
173
+ const extensionRules = {
174
+ "vue/array-bracket-spacing": ["error", "never"],
175
+ "vue/arrow-spacing": ["error", {
176
+ after: true,
177
+ before: true
178
+ }],
179
+ "vue/block-spacing": ["error", "always"],
180
+ "vue/brace-style": [
181
+ "error",
182
+ "stroustrup",
183
+ { allowSingleLine: true }
184
+ ],
185
+ "vue/comma-dangle": ["error", "always-multiline"],
186
+ "vue/comma-spacing": ["error", {
187
+ after: true,
188
+ before: false
189
+ }],
190
+ "vue/comma-style": ["error", "last"],
191
+ "vue/dot-location": ["error", "property"],
192
+ "vue/dot-notation": ["error", { allowKeywords: true }],
193
+ "vue/eqeqeq": ["error", "smart"],
194
+ "vue/key-spacing": ["error", {
195
+ afterColon: true,
196
+ beforeColon: false
197
+ }],
198
+ "vue/keyword-spacing": ["error", {
199
+ after: true,
200
+ before: true
201
+ }],
202
+ "vue/no-constant-condition": "error",
203
+ "vue/no-empty-pattern": "error",
204
+ "vue/no-extra-parens": ["error", "functions"],
205
+ "vue/no-loss-of-precision": "error",
206
+ "vue/no-negated-condition": "error",
207
+ "vue/no-restricted-syntax": [
208
+ "error",
209
+ "DebuggerStatement",
210
+ "LabeledStatement",
211
+ "WithStatement"
212
+ ],
213
+ "vue/no-sparse-arrays": "error",
214
+ "vue/object-curly-newline": ["error", {
215
+ consistent: true,
216
+ multiline: true
217
+ }],
218
+ "vue/object-curly-spacing": ["error", "always"],
219
+ "vue/object-property-newline": ["error", { allowMultiplePropertiesPerLine: true }],
220
+ "vue/object-shorthand": [
221
+ "error",
222
+ "always",
223
+ {
224
+ avoidQuotes: true,
225
+ ignoreConstructors: false
226
+ }
227
+ ],
228
+ "vue/operator-linebreak": ["error", "before"],
229
+ "vue/prefer-template": "error",
230
+ "vue/quote-props": ["error", "consistent-as-needed"],
231
+ "vue/space-in-parens": ["error", "never"],
232
+ "vue/space-infix-ops": "error",
233
+ "vue/space-unary-ops": ["error", {
234
+ nonwords: false,
235
+ words: true
236
+ }],
237
+ "vue/template-curly-spacing": "error"
238
+ };
239
+ const unCategorizedRules = {
240
+ "vue/block-order": ["error", { order: [
241
+ "script",
242
+ "template",
243
+ "style"
244
+ ] }],
245
+ "vue/block-tag-newline": ["error", {
246
+ multiline: "always",
247
+ singleline: "always"
248
+ }],
249
+ "vue/component-api-style": ["error", ["script-setup", "composition"]],
250
+ "vue/component-name-in-template-casing": [
251
+ "error",
252
+ "PascalCase",
253
+ {
254
+ ignores: ["slot", "component"],
255
+ registeredComponentsOnly: false
256
+ }
257
+ ],
258
+ "vue/component-options-name-casing": ["error", "PascalCase"],
259
+ "vue/custom-event-name-casing": ["error", "camelCase"],
260
+ "vue/define-emits-declaration": ["error", "type-literal"],
261
+ "vue/define-macros-order": ["error", {
262
+ defineExposeLast: true,
263
+ order: [
264
+ "defineProps",
265
+ "defineEmits",
266
+ "defineOptions",
267
+ "defineSlots",
268
+ "defineModel"
269
+ ]
270
+ }],
271
+ "vue/define-props-declaration": ["error", "type-based"],
272
+ "vue/define-props-destructuring": ["error", { destructure: "never" }],
273
+ "vue/enforce-style-attribute": ["error", { allow: ["scoped", "plain"] }],
274
+ "vue/html-button-has-type": ["error", {
275
+ button: true,
276
+ reset: true,
277
+ submit: true
278
+ }],
279
+ "vue/html-comment-content-newline": [
280
+ "error",
281
+ {
282
+ multiline: "always",
283
+ singleline: "ignore"
284
+ },
285
+ { exceptions: ["*"] }
286
+ ],
287
+ "vue/html-comment-content-spacing": [
288
+ "error",
289
+ "always",
290
+ { exceptions: ["-"] }
291
+ ],
292
+ "vue/html-comment-indent": ["error", 2],
293
+ "vue/next-tick-style": ["error", "promise"],
294
+ "vue/no-deprecated-delete-set": "error",
295
+ "vue/no-deprecated-model-definition": ["error", { allowVue3Compat: true }],
296
+ "vue/no-duplicate-attr-inheritance": ["error", { checkMultiRootNodes: true }],
297
+ "vue/no-empty-component-block": "error",
298
+ "vue/no-irregular-whitespace": "error",
299
+ "vue/no-multiple-objects-in-class": "error",
300
+ "vue/no-negated-v-if-condition": "error",
301
+ "vue/no-ref-object-reactivity-loss": "error",
302
+ "vue/no-required-prop-with-default": ["error", { autofix: true }],
303
+ "vue/no-restricted-v-bind": ["error", "/^v-/"],
304
+ "vue/no-static-inline-styles": ["error", { allowBinding: true }],
305
+ "vue/no-unused-emit-declarations": "error",
306
+ "vue/no-use-v-else-with-v-for": "error",
307
+ "vue/no-useless-v-bind": "error",
308
+ "vue/no-v-text": "error",
309
+ "vue/padding-line-between-blocks": "error",
310
+ "vue/prefer-define-options": "error",
311
+ "vue/prefer-prop-type-boolean-first": "error",
312
+ "vue/prefer-separate-static-class": "error",
313
+ "vue/prefer-true-attribute-shorthand": ["error", "always"],
314
+ "vue/prefer-use-template-ref": "error",
315
+ "vue/require-macro-variable-name": ["error", {
316
+ defineEmits: "emits",
317
+ defineProps: "props",
318
+ defineSlots: "slots",
319
+ useAttrs: "attrs",
320
+ useSlots: "slots"
321
+ }],
322
+ "vue/require-typed-object-prop": "error",
323
+ "vue/slot-name-casing": ["error", "kebab-case"],
324
+ "vue/v-for-delimiter-style": ["error", "in"],
325
+ "vue/valid-define-options": "error"
326
+ };
327
+ /**
328
+ * Config for vue files
329
+ *
330
+ * @see {@link https://github.com/vuejs/eslint-plugin-vue}
331
+ *
332
+ * @param options - {@link ConfigVueOptions}
333
+ * @returns ESLint configs
334
+ */
335
+ const configVue = (options = {}) => {
336
+ const { files = [GLOB_VUE], extraFileExtensions = [] } = options;
337
+ const sfcBlocks = options.sfcBlocks === true ? {} : options.sfcBlocks ?? {};
338
+ function getVueProcessor() {
339
+ const processorVueSFC = pluginVue.processors[".vue"];
340
+ if (!sfcBlocks) return processorVueSFC;
341
+ return mergeProcessors$1([processorVueSFC, processorVueBlocks({
342
+ ...sfcBlocks,
343
+ blocks: {
344
+ styles: true,
345
+ ...sfcBlocks.blocks
346
+ }
347
+ })]);
348
+ }
349
+ return [{
350
+ name: "ntnyq/vue/setup",
351
+ plugins: {
352
+ "@typescript-eslint": pluginTypeScript,
353
+ vue: pluginVue
354
+ }
355
+ }, {
356
+ name: "ntnyq/vue/rules",
357
+ files,
358
+ processor: getVueProcessor(),
359
+ languageOptions: {
360
+ parser: parserVue,
361
+ parserOptions: {
362
+ ecmaVersion: "latest",
363
+ extraFileExtensions,
364
+ parser: parserTypeScript,
365
+ sourceType: "module",
366
+ ecmaFeatures: { jsx: true }
367
+ }
368
+ },
369
+ rules: {
370
+ ...sharedRules,
371
+ "vue/attributes-order": ["error", {
372
+ alphabetical: false,
373
+ order: [
374
+ "EVENTS",
375
+ "TWO_WAY_BINDING",
376
+ "OTHER_DIRECTIVES",
377
+ "LIST_RENDERING",
378
+ "CONDITIONALS",
379
+ "CONTENT",
380
+ "SLOT",
381
+ "UNIQUE",
382
+ "DEFINITION",
383
+ "ATTR_DYNAMIC",
384
+ "RENDER_MODIFIERS",
385
+ "GLOBAL",
386
+ "ATTR_STATIC",
387
+ "ATTR_SHORTHAND_BOOL"
388
+ ]
389
+ }],
390
+ "vue/html-self-closing": ["error", {
391
+ math: "always",
392
+ svg: "always",
393
+ html: {
394
+ component: "always",
395
+ normal: "always",
396
+ void: "always"
397
+ }
398
+ }],
399
+ "vue/max-attributes-per-line": ["error", {
400
+ multiline: 1,
401
+ singleline: 1
402
+ }],
403
+ "vue/order-in-components": ["error", { order: [
404
+ "el",
405
+ "name",
406
+ "key",
407
+ "parent",
408
+ "functional",
409
+ ["provide", "inject"],
410
+ ["delimiters", "comments"],
411
+ [
412
+ "components",
413
+ "directives",
414
+ "filters"
415
+ ],
416
+ "extends",
417
+ "mixins",
418
+ "layout",
419
+ "middleware",
420
+ "validate",
421
+ "scrollToTop",
422
+ "transition",
423
+ "loading",
424
+ "inheritAttrs",
425
+ "model",
426
+ ["props", "propsData"],
427
+ "slots",
428
+ "expose",
429
+ "emits",
430
+ "setup",
431
+ "asyncData",
432
+ "computed",
433
+ "data",
434
+ "fetch",
435
+ "head",
436
+ "methods",
437
+ ["template", "render"],
438
+ "watch",
439
+ "watchQuery",
440
+ "LIFECYCLE_HOOKS",
441
+ "renderError",
442
+ "ROUTER_GUARDS"
443
+ ] }],
444
+ "vue/prop-name-casing": ["error", "camelCase"],
445
+ "vue/this-in-template": ["error", "never"],
446
+ "vue/v-bind-style": [
447
+ "error",
448
+ "shorthand",
449
+ { sameNameShorthand: "always" }
450
+ ],
451
+ ...disabledRules$1,
452
+ ...extensionRules,
453
+ ...unCategorizedRules,
454
+ ...options.overrides
455
+ }
456
+ }];
457
+ };
458
+
459
+ //#endregion
460
+ //#region src/configs/yml.ts
461
+ /**
462
+ * @see {@link https://github.com/ota-meshi/eslint-plugin-yml/blob/master/src/configs/base.ts}
463
+ */
464
+ const disabledCoreRules$1 = {
465
+ "no-irregular-whitespace": "off",
466
+ "no-unused-vars": "off",
467
+ "spaced-comment": "off"
468
+ };
469
+ /**
470
+ * Config for yml, yaml files
471
+ *
472
+ * @see {@link https://ota-meshi.github.io/eslint-plugin-yml}
473
+ *
474
+ * @param options - {@link ConfigYmlOptions}
475
+ * @returns ESLint configs
476
+ */
477
+ const configYml = (options = {}) => {
478
+ const { files = [GLOB_YAML] } = options;
479
+ return [{
480
+ name: "ntnyq/yml",
481
+ files,
482
+ plugins: { yml: pluginYml },
483
+ languageOptions: { parser: parserYaml },
484
+ rules: {
485
+ "yml/no-empty-mapping-value": "off",
486
+ "yml/block-mapping": "error",
487
+ "yml/block-mapping-question-indicator-newline": "error",
488
+ "yml/block-sequence": "error",
489
+ "yml/block-sequence-hyphen-indicator-newline": "error",
490
+ "yml/flow-mapping-curly-newline": "error",
491
+ "yml/flow-mapping-curly-spacing": "error",
492
+ "yml/flow-sequence-bracket-newline": "error",
493
+ "yml/flow-sequence-bracket-spacing": "error",
494
+ "yml/indent": "error",
495
+ "yml/key-spacing": "error",
496
+ "yml/no-empty-document": "error",
497
+ "yml/no-empty-key": "error",
498
+ "yml/no-empty-sequence-entry": "error",
499
+ "yml/no-irregular-whitespace": "error",
500
+ "yml/no-tab-indent": "error",
501
+ "yml/plain-scalar": "error",
502
+ "yml/quotes": ["error", {
503
+ avoidEscape: false,
504
+ prefer: "single"
505
+ }],
506
+ "yml/spaced-comment": "error",
507
+ "yml/vue-custom-block/no-parsing-error": "error",
508
+ ...disabledCoreRules$1,
509
+ ...options.prettier ? {
510
+ "yml/block-mapping-colon-indicator-newline": "off",
511
+ "yml/block-mapping-question-indicator-newline": "off",
512
+ "yml/block-sequence-hyphen-indicator-newline": "off",
513
+ "yml/flow-mapping-curly-newline": "off",
514
+ "yml/flow-mapping-curly-spacing": "off",
515
+ "yml/flow-sequence-bracket-newline": "off",
516
+ "yml/flow-sequence-bracket-spacing": "off",
517
+ "yml/indent": "off",
518
+ "yml/key-spacing": "off",
519
+ "yml/no-multiple-empty-lines": "off",
520
+ "yml/no-trailing-zeros": "off",
521
+ "yml/quotes": "off"
522
+ } : {},
523
+ ...options.overrides
524
+ }
525
+ }];
526
+ };
527
+
528
+ //#endregion
529
+ //#region src/utils/env.ts
530
+ const hasPinia = () => isPackageExists("pinia");
531
+ const hasVitest = () => isPackageExists("vitest");
532
+ const hasTypeScript = () => isPackageExists("typescript");
533
+ const hasShadcnVue = () => (isPackageExists("radix-vue") || isPackageExists("reka-ui")) && isPackageExists("class-variance-authority") && isPackageExists("clsx");
534
+ const hasUnoCSS = () => isPackageExists("unocss") || isPackageExists("@unocss/postcss") || isPackageExists("@unocss/webpack") || isPackageExists("@unocss/nuxt");
535
+ const hasVue = () => isPackageExists("vue") || isPackageExists("nuxt") || isPackageExists("vitepress") || isPackageExists("vuepress") || isPackageExists("@slidev/cli") || isPackageExists("vue", { paths: [resolve(process.cwd(), "playground"), resolve(process.cwd(), "docs")] });
536
+
537
+ //#endregion
538
+ //#region src/utils/resolveSubOptions.ts
539
+ function resolveSubOptions(options, key) {
540
+ return typeof options[key] === "boolean" ? {} : options[key] || {};
541
+ }
542
+
543
+ //#endregion
544
+ //#region src/utils/getOverrides.ts
545
+ function getOverrides(options, key) {
546
+ const subOptions = resolveSubOptions(options, key);
547
+ return "overrides" in subOptions && subOptions.overrides ? subOptions.overrides : {};
548
+ }
549
+
550
+ //#endregion
551
+ //#region src/utils/combineConfigs.ts
552
+ async function combineConfigs(...configs) {
553
+ const resolved = await Promise.all(configs);
554
+ return resolved.flat();
555
+ }
556
+
557
+ //#endregion
558
+ //#region src/utils/isInGitHooksOrRunBySpecifyPackages.ts
559
+ const CHECKED_RUNNER_PACKAGES = [
560
+ "nano-staged",
561
+ "lint-staged",
562
+ "lefthook",
563
+ "tsx"
564
+ ];
565
+ function isInGitHooksOrRunBySpecifyPackages() {
566
+ return !!(process.env.GIT_PARAMS || process.env.VSCODE_GIT_COMMAND || CHECKED_RUNNER_PACKAGES.some((packageName) => process.env.npm_lifecycle_script?.startsWith(packageName)));
567
+ }
568
+
569
+ //#endregion
570
+ //#region src/utils/ensurePackages.ts
571
+ const isCwdInScope = isPackageExists("@ntnyq/eslint-config");
572
+ function isPackageInScope(name) {
573
+ return isPackageExists(name, { paths: [import.meta.dirname] });
574
+ }
575
+ async function ensurePackages(packages) {
576
+ if (process.env.CI || !process.stdout.isTTY || isInGitHooksOrRunBySpecifyPackages() || !isCwdInScope) return;
577
+ const nonExistingPackages = packages.filter((pkg) => !!pkg && !isPackageInScope(pkg));
578
+ if (nonExistingPackages.length === 0) return;
579
+ const { confirm } = await import("@clack/prompts");
580
+ const confirmInstall = await confirm({ message: `${nonExistingPackages.length === 1 ? "Package is" : "Packages are"} required for this config: ${nonExistingPackages.join(", ")}. Do you want to install them?` });
581
+ if (confirmInstall) try {
582
+ const { installPackage } = await import("@antfu/install-pkg");
583
+ await installPackage(nonExistingPackages, { dev: true });
584
+ } catch (err) {
585
+ console.log(err);
586
+ }
587
+ }
588
+
589
+ //#endregion
590
+ //#region src/utils/interopDefault.ts
591
+ /**
592
+ * Interop default export from a module
593
+ * @param mod - The module
594
+ * @returns The default export
595
+ */
596
+ async function interopDefault(mod) {
597
+ const resolved = await mod;
598
+ return resolved.default || resolved;
599
+ }
600
+
601
+ //#endregion
602
+ //#region src/utils/mergePrettierOptions.ts
603
+ function mergePrettierOptions(options = {}, overrides = {}) {
604
+ const result = {
605
+ ...options,
606
+ ...overrides,
607
+ plugins: [...options.plugins || [], ...overrides.plugins || []]
608
+ };
609
+ return result;
610
+ }
611
+
612
+ //#endregion
613
+ //#region src/configs/html.ts
614
+ /**
615
+ * Config for html files
616
+ *
617
+ * @see {@link https://github.com/yeonjuan/html-eslint}
618
+ *
619
+ * @param options - {@link ConfigHtmlOptions}
620
+ * @returns ESLint configs
621
+ */
622
+ const configHtml = async (options = {}) => {
623
+ await ensurePackages(["@html-eslint/parser", "@html-eslint/eslint-plugin"]);
624
+ const [parserHtml, pluginHtml] = await Promise.all([interopDefault(import("@html-eslint/parser")), interopDefault(import("@html-eslint/eslint-plugin"))]);
625
+ const { files = [GLOB_HTML] } = options;
626
+ return [{
627
+ name: "ntnyq/html",
628
+ files,
629
+ plugins: { "@html-eslint": pluginHtml },
630
+ languageOptions: { parser: parserHtml },
631
+ rules: {
632
+ "@html-eslint/attrs-newline": "error",
633
+ "@html-eslint/element-newline": ["error", { inline: [`$inline`] }],
634
+ "@html-eslint/indent": "error",
635
+ "@html-eslint/no-duplicate-attrs": "error",
636
+ "@html-eslint/no-duplicate-id": "error",
637
+ "@html-eslint/no-extra-spacing-attrs": "error",
638
+ "@html-eslint/no-multiple-h1": "error",
639
+ "@html-eslint/no-obsolete-tags": "error",
640
+ "@html-eslint/quotes": "error",
641
+ "@html-eslint/require-closing-tags": "error",
642
+ "@html-eslint/require-doctype": "error",
643
+ "@html-eslint/require-img-alt": "error",
644
+ "@html-eslint/require-lang": "error",
645
+ "@html-eslint/require-li-container": "error",
646
+ "@html-eslint/require-title": "error",
647
+ "@html-eslint/use-baseline": "error",
648
+ ...options.overrides
649
+ }
650
+ }];
651
+ };
652
+
653
+ //#endregion
654
+ //#region src/configs/node.ts
655
+ /**
656
+ * Config for common files
657
+ *
658
+ * @see {@link https://github.com/eslint-community/eslint-plugin-n}
659
+ *
660
+ * @param options - {@link ConfigNodeOptions}
661
+ * @returns ESLint configs
662
+ */
663
+ const configNode = (options = {}) => [{
664
+ name: "ntnyq/node",
665
+ plugins: { node: pluginNode },
666
+ rules: {
667
+ "node/handle-callback-err": ["error", "^(err|error)$"],
668
+ "node/no-deprecated-api": "error",
669
+ "node/no-exports-assign": "error",
670
+ "node/no-new-require": "error",
671
+ "node/no-path-concat": "error",
672
+ "node/prefer-global/buffer": ["error", "never"],
673
+ "node/prefer-global/process": ["error", "never"],
674
+ "node/process-exit-as-throw": "error",
675
+ ...options.overrides
676
+ }
677
+ }];
678
+
679
+ //#endregion
680
+ //#region src/configs/pnpm.ts
681
+ /**
682
+ * Config for pnpm package manager
683
+ *
684
+ * @see {@link https://github.com/antfu/pnpm-workspace-utils/tree/main/packages/eslint-plugin-pnpm}
685
+ *
686
+ * @param options - {@link ConfigPnpmOptions}
687
+ * @returns ESLint configs
688
+ */
689
+ const configPnpm = async (options = {}) => {
690
+ await ensurePackages(["eslint-plugin-pnpm"]);
691
+ const pluginPnpm = await interopDefault(import("eslint-plugin-pnpm"));
692
+ const { filesJson = [GLOB_PACKAGE_JSON], filesYaml = [GLOB_PNPM_WORKSPACE_YAML] } = options;
693
+ return [{
694
+ name: "ntnyq/pnpm/package-json",
695
+ files: filesJson,
696
+ plugins: { pnpm: pluginPnpm },
697
+ languageOptions: { parser: parserJsonc },
698
+ rules: {
699
+ "pnpm/json-enforce-catalog": ["error", { autofix: true }],
700
+ "pnpm/json-valid-catalog": "error",
701
+ ...options.overridesJsonRules
702
+ }
703
+ }, {
704
+ name: "ntnyq/pnpm/pnpm-workspace-yaml",
705
+ files: filesYaml,
706
+ plugins: { pnpm: pluginPnpm },
707
+ languageOptions: { parser: parserYaml },
708
+ rules: {
709
+ "pnpm/yaml-no-duplicate-catalog-item": "error",
710
+ "pnpm/yaml-no-unused-catalog-item": "error",
711
+ ...options.overridesYamlRules
712
+ }
713
+ }];
714
+ };
715
+
716
+ //#endregion
717
+ //#region src/configs/sort.ts
718
+ /**
719
+ * Config for sort keys and values
720
+ *
721
+ * @param options - {@link ConfigSortOptions}
722
+ * @returns ESLint configs
723
+ */
724
+ const configSort = (options = {}) => {
725
+ const configs = [];
726
+ const { additionalJsonFiles = [], additionalYamlFiles = [], i18nLocale: enableSortI18nLocale = true, jsonSchema: enableSortJsonSchema = true, packageJson: enableSortPackageJson = true, pnpmWorkspace: enableSortPnpmWorkspace = true, tsconfig: enableSortTsconfig = true } = options;
727
+ if (enableSortTsconfig) configs.push({
728
+ name: "ntnyq/sort/tsconfig",
729
+ files: [...GLOB_TSCONFIG_JSON],
730
+ rules: { "jsonc/sort-keys": [
731
+ "error",
732
+ {
733
+ pathPattern: "^$",
734
+ order: [
735
+ "extends",
736
+ "compilerOptions",
737
+ "references",
738
+ "files",
739
+ "include",
740
+ "exclude",
741
+ "vueCompilerOptions",
742
+ { order: { type: "asc" } }
743
+ ]
744
+ },
745
+ {
746
+ pathPattern: "^compilerOptions$",
747
+ order: [
748
+ "incremental",
749
+ "composite",
750
+ "tsBuildInfoFile",
751
+ "disableSourceOfProjectReferenceRedirect",
752
+ "disableSolutionSearching",
753
+ "disableReferencedProjectLoad",
754
+ "target",
755
+ "lib",
756
+ "jsx",
757
+ "experimentalDecorators",
758
+ "emitDecoratorMetadata",
759
+ "jsxFactory",
760
+ "jsxFragmentFactory",
761
+ "jsxImportSource",
762
+ "reactNamespace",
763
+ "noLib",
764
+ "useDefineForClassFields",
765
+ "moduleDetection",
766
+ "module",
767
+ "rootDir",
768
+ "moduleResolution",
769
+ "baseUrl",
770
+ "paths",
771
+ "rootDirs",
772
+ "typeRoots",
773
+ "types",
774
+ "allowUmdGlobalAccess",
775
+ "moduleSuffixes",
776
+ "allowImportingTsExtensions",
777
+ "resolvePackageJsonExports",
778
+ "resolvePackageJsonImports",
779
+ "customConditions",
780
+ "resolveJsonModule",
781
+ "allowArbitraryExtensions",
782
+ "noResolve",
783
+ "erasableSyntaxOnly",
784
+ "libReplacement",
785
+ "allowJs",
786
+ "checkJs",
787
+ "maxNodeModuleJsDepth",
788
+ "declaration",
789
+ "declarationMap",
790
+ "emitDeclarationOnly",
791
+ "sourceMap",
792
+ "inlineSourceMap",
793
+ "outFile",
794
+ "outDir",
795
+ "removeComments",
796
+ "noEmit",
797
+ "importHelpers",
798
+ "importsNotUsedAsValues",
799
+ "downlevelIteration",
800
+ "sourceRoot",
801
+ "mapRoot",
802
+ "inlineSources",
803
+ "emitBOM",
804
+ "newLine",
805
+ "stripInternal",
806
+ "noEmitHelpers",
807
+ "noEmitOnError",
808
+ "preserveConstEnums",
809
+ "declarationDir",
810
+ "preserveValueImports",
811
+ "isolatedDeclarations",
812
+ "isolatedModules",
813
+ "verbatimModuleSyntax",
814
+ "allowSyntheticDefaultImports",
815
+ "esModuleInterop",
816
+ "preserveSymlinks",
817
+ "forceConsistentCasingInFileNames",
818
+ "strict",
819
+ "strictBindCallApply",
820
+ "strictFunctionTypes",
821
+ "strictNullChecks",
822
+ "strictPropertyInitialization",
823
+ "allowUnreachableCode",
824
+ "allowUnusedLabels",
825
+ "alwaysStrict",
826
+ "exactOptionalPropertyTypes",
827
+ "noFallthroughCasesInSwitch",
828
+ "noImplicitAny",
829
+ "noImplicitOverride",
830
+ "noImplicitReturns",
831
+ "noImplicitThis",
832
+ "noPropertyAccessFromIndexSignature",
833
+ "noUncheckedIndexedAccess",
834
+ "noUnusedLocals",
835
+ "noUnusedParameters",
836
+ "useUnknownInCatchVariables",
837
+ "skipDefaultLibCheck",
838
+ "skipLibCheck",
839
+ { order: { type: "asc" } }
840
+ ]
841
+ },
842
+ {
843
+ order: { type: "asc" },
844
+ pathPattern: "^vueCompilerOptions$"
845
+ }
846
+ ] }
847
+ });
848
+ if (enableSortPackageJson) configs.push({
849
+ name: "ntnyq/sort/package-json",
850
+ files: [GLOB_PACKAGE_JSON],
851
+ rules: {
852
+ "jsonc/sort-array-values": ["error", {
853
+ order: { type: "asc" },
854
+ pathPattern: "^(?:files|keywords|activationEvents|contributes.*)$"
855
+ }],
856
+ "jsonc/sort-keys": [
857
+ "error",
858
+ {
859
+ pathPattern: "^$",
860
+ order: [
861
+ "publisher",
862
+ "name",
863
+ "displayName",
864
+ "preview",
865
+ "type",
866
+ "config",
867
+ "version",
868
+ "private",
869
+ "packageManager",
870
+ "workspaces",
871
+ "description",
872
+ "keywords",
873
+ "license",
874
+ "licenses",
875
+ "author",
876
+ "contributors",
877
+ "maintainers",
878
+ "homepage",
879
+ "repository",
880
+ "bugs",
881
+ "funding",
882
+ "exports",
883
+ "imports",
884
+ "main",
885
+ "module",
886
+ "unpkg",
887
+ "jsdelivr",
888
+ "types",
889
+ "typesVersions",
890
+ "bin",
891
+ "icon",
892
+ "files",
893
+ "directories",
894
+ "publishConfig",
895
+ "sideEffects",
896
+ "scripts",
897
+ "peerDependencies",
898
+ "peerDependenciesMeta",
899
+ "bundledDependencies",
900
+ "bundleDependencies",
901
+ "dependencies",
902
+ "optionalDependencies",
903
+ "devDependencies",
904
+ "activationEvents",
905
+ "contributes",
906
+ "categories",
907
+ "galleryBanner",
908
+ "badges",
909
+ "markdown",
910
+ "qna",
911
+ "sponsor",
912
+ "extensionPack",
913
+ "extensionDependencies",
914
+ "extensionKind",
915
+ "pricing",
916
+ "capabilities",
917
+ "engines",
918
+ "pnpm",
919
+ "overrides",
920
+ "resolutions",
921
+ "husky",
922
+ "prettier",
923
+ "nano-staged",
924
+ "lint-staged",
925
+ "eslintConfig",
926
+ { order: { type: "asc" } }
927
+ ]
928
+ },
929
+ {
930
+ order: { type: "asc" },
931
+ pathPattern: "^(?:dev|peer|optional|bundled)?[Dd]ependencies(Meta)?$"
932
+ },
933
+ {
934
+ order: { type: "asc" },
935
+ pathPattern: "^(?:resolutions|overrides|pnpm.overrides)$"
936
+ },
937
+ {
938
+ pathPattern: "^exports.*$",
939
+ order: [
940
+ "./package.json",
941
+ "types",
942
+ "import",
943
+ "require",
944
+ "default",
945
+ { order: { type: "asc" } }
946
+ ]
947
+ },
948
+ {
949
+ order: { type: "asc" },
950
+ pathPattern: "^contributes.*$"
951
+ },
952
+ (
953
+ /**
954
+ * pnpm publish config
955
+ * @see {@link https://pnpm.io/package_json#publishconfig}
956
+ */
957
+ {
958
+ pathPattern: "^publishConfig.*$",
959
+ order: [
960
+ "./package.json",
961
+ "types",
962
+ "import",
963
+ "require",
964
+ "default",
965
+ { order: { type: "asc" } }
966
+ ]
967
+ }),
968
+ {
969
+ order: { type: "asc" },
970
+ pathPattern: "^scripts$"
971
+ },
972
+ {
973
+ pathPattern: "^(?:gitHooks|husky|simple-git-hooks)$",
974
+ order: [
975
+ "pre-commit",
976
+ "prepare-commit-msg",
977
+ "commit-msg",
978
+ "post-commit",
979
+ "pre-rebase",
980
+ "post-rewrite",
981
+ "post-checkout",
982
+ "post-merge",
983
+ "pre-push",
984
+ "pre-auto-gc",
985
+ { order: { type: "asc" } }
986
+ ]
987
+ }
988
+ ]
989
+ }
990
+ });
991
+ if (enableSortI18nLocale) configs.push({
992
+ name: "ntnyq/sort/i18n-locale/json",
993
+ files: ["**/{i18n,langs,locales}/*.json"],
994
+ rules: { "jsonc/sort-keys": ["error", {
995
+ order: { type: "asc" },
996
+ pathPattern: ".*"
997
+ }] }
998
+ }, {
999
+ name: "ntnyq/sort/i18n-locale/yaml",
1000
+ files: ["**/{i18n,langs,locales}/*.y?(a)ml"],
1001
+ rules: { "yml/sort-keys": ["error", {
1002
+ order: { type: "asc" },
1003
+ pathPattern: ".*"
1004
+ }] }
1005
+ });
1006
+ /**
1007
+ * @see {@link https://json-schema.org/draft-07/schema}
1008
+ */
1009
+ if (enableSortJsonSchema) configs.push({
1010
+ name: "ntnyq/sort/json-schema",
1011
+ files: [...GLOB_JSON_SCHEMA],
1012
+ ignores: [GLOB_PACKAGE_JSON],
1013
+ rules: {
1014
+ "jsonc/sort-array-values": ["error", {
1015
+ order: { type: "asc" },
1016
+ pathPattern: "^(?:required)$"
1017
+ }],
1018
+ "jsonc/sort-keys": [
1019
+ "error",
1020
+ {
1021
+ pathPattern: "^$",
1022
+ order: [
1023
+ "$schema",
1024
+ "$comment",
1025
+ "$id",
1026
+ "$ref",
1027
+ "title",
1028
+ "description",
1029
+ "version",
1030
+ "type",
1031
+ "definitions",
1032
+ "properties",
1033
+ "required",
1034
+ "additionalProperties",
1035
+ { order: { type: "asc" } }
1036
+ ]
1037
+ },
1038
+ {
1039
+ order: { type: "asc" },
1040
+ pathPattern: "^(?:definitions|properties)$"
1041
+ }
1042
+ ]
1043
+ }
1044
+ });
1045
+ if (enableSortPnpmWorkspace) configs.push({
1046
+ name: "ntnyq/sort/pnpm-workspace",
1047
+ files: [GLOB_PNPM_WORKSPACE_YAML],
1048
+ rules: {
1049
+ "yml/sort-keys": [
1050
+ "error",
1051
+ {
1052
+ pathPattern: "^$",
1053
+ order: [
1054
+ "packages",
1055
+ "catalog",
1056
+ "catalogs",
1057
+ "allowedDeprecatedVersions",
1058
+ "overrides",
1059
+ "onlyBuiltDependencies",
1060
+ "patchedDependencies",
1061
+ "peerDependencyRules",
1062
+ "allowNonAppliedPatches",
1063
+ "auditConfig",
1064
+ "configDependencies",
1065
+ "executionEnv",
1066
+ "ignoredBuiltDependencies",
1067
+ "ignoredOptionalDependencies",
1068
+ "neverBuiltDependencies",
1069
+ "onlyBuiltDependenciesFile",
1070
+ "packageExtensions",
1071
+ "requiredScripts",
1072
+ "supportedArchitectures",
1073
+ "updateConfig",
1074
+ { order: { type: "asc" } }
1075
+ ]
1076
+ },
1077
+ {
1078
+ order: { type: "asc" },
1079
+ pathPattern: "^(?:catalog|overrides|patchedDependencies|peerDependencyRules)$"
1080
+ },
1081
+ {
1082
+ allowLineSeparatedGroups: true,
1083
+ order: { type: "asc" },
1084
+ pathPattern: "^catalogs$"
1085
+ }
1086
+ ],
1087
+ "yml/sort-sequence-values": ["error", {
1088
+ order: [".", { order: { type: "asc" } }],
1089
+ pathPattern: "^(?:packages|onlyBuiltDependencies|peerDependencyRules.ignoreMissing)$"
1090
+ }]
1091
+ }
1092
+ });
1093
+ if (additionalJsonFiles.length) configs.push({
1094
+ name: "ntnyq/sort/additional-json",
1095
+ files: additionalJsonFiles,
1096
+ rules: { "jsonc/sort-keys": ["error", {
1097
+ pathPattern: ".*",
1098
+ order: ["$schema", { order: { type: "asc" } }]
1099
+ }] }
1100
+ });
1101
+ if (additionalYamlFiles.length) configs.push({
1102
+ name: "ntnyq/sort/additional-yaml",
1103
+ files: additionalYamlFiles,
1104
+ rules: { "yml/sort-keys": ["error", {
1105
+ order: { type: "asc" },
1106
+ pathPattern: ".*"
1107
+ }] }
1108
+ });
1109
+ return configs;
1110
+ };
1111
+
1112
+ //#endregion
1113
+ //#region src/configs/svgo.ts
1114
+ /**
1115
+ * Config for svg files
1116
+ *
1117
+ * @see {@link https://github.com/ntnyq/eslint-plugin-svgo}
1118
+ *
1119
+ * @param options - {@link ConfigSVGOOptions}
1120
+ * @returns ESLint configs
1121
+ */
1122
+ const configSVGO = (options = {}) => {
1123
+ const { files = [GLOB_SVG], ignores = [] } = options;
1124
+ return [{
1125
+ name: "ntnyq/svgo",
1126
+ files,
1127
+ ignores,
1128
+ plugins: { svgo: pluginSvgo },
1129
+ languageOptions: { parser: parserPlain },
1130
+ rules: {
1131
+ "svgo/svgo": ["error", {
1132
+ plugins: ["preset-default"],
1133
+ js2svg: {
1134
+ indent: 2,
1135
+ pretty: true
1136
+ }
1137
+ }],
1138
+ ...options.overrides
1139
+ }
1140
+ }];
1141
+ };
1142
+
1143
+ //#endregion
1144
+ //#region src/configs/test.ts
1145
+ /**
1146
+ * Config for test files
1147
+ *
1148
+ * @see {@link https://github.com/vitest-dev/eslint-plugin-vitest}
1149
+ *
1150
+ * @param options - {@link ConfigTestOptions}
1151
+ * @returns ESLint configs
1152
+ */
1153
+ const configTest = (options = {}) => {
1154
+ const { files = [...GLOB_TEST], vitest: enableVitest = hasVitest() } = options;
1155
+ const configs = [{
1156
+ name: "ntnyq/test/setup",
1157
+ plugins: { "no-only-tests": pluginNoOnlyTests }
1158
+ }, {
1159
+ name: "ntnyq/test/base",
1160
+ files,
1161
+ rules: {
1162
+ "max-lines-per-function": "off",
1163
+ "no-unused-expressions": "off",
1164
+ "no-only-tests/no-only-tests": "error",
1165
+ ...options.overrides
1166
+ }
1167
+ }];
1168
+ if (enableVitest) configs.push({
1169
+ name: "ntnyq/test/vitest",
1170
+ files,
1171
+ plugins: { vitest: pluginVitest },
1172
+ settings: {},
1173
+ rules: {
1174
+ ...pluginVitest.configs.recommended.rules,
1175
+ "vitest/expect-expect": ["error", { assertFunctionNames: [
1176
+ "expect",
1177
+ "assert",
1178
+ "expectTypeOf",
1179
+ "assertType"
1180
+ ] }],
1181
+ ...options.overridesVitestRules
1182
+ }
1183
+ });
1184
+ return configs;
1185
+ };
1186
+
1187
+ //#endregion
1188
+ //#region src/configs/toml.ts
1189
+ /**
1190
+ * Config for toml files
1191
+ *
1192
+ * @see {@link https://ota-meshi.github.io/eslint-plugin-toml}
1193
+ *
1194
+ * @param options - {@link ConfigTomlOptions}
1195
+ * @returns ESLint configs
1196
+ */
1197
+ const configToml = (options = {}) => {
1198
+ const { files = [GLOB_TOML] } = options;
1199
+ return [{
1200
+ name: "ntnyq/toml",
1201
+ files,
1202
+ plugins: { toml: pluginToml },
1203
+ languageOptions: { parser: parserToml },
1204
+ rules: {
1205
+ "toml/array-bracket-newline": "error",
1206
+ "toml/array-bracket-spacing": ["error", "never"],
1207
+ "toml/array-element-newline": ["error", "never"],
1208
+ "toml/comma-style": "error",
1209
+ "toml/indent": ["error", 2],
1210
+ "toml/inline-table-curly-spacing": "error",
1211
+ "toml/key-spacing": "error",
1212
+ "toml/keys-order": "error",
1213
+ "toml/no-space-dots": "error",
1214
+ "toml/no-unreadable-number-separator": "error",
1215
+ "toml/padding-line-between-pairs": "error",
1216
+ "toml/padding-line-between-tables": "error",
1217
+ "toml/precision-of-fractional-seconds": "error",
1218
+ "toml/precision-of-integer": "error",
1219
+ "toml/quoted-keys": "error",
1220
+ "toml/spaced-comment": "error",
1221
+ "toml/table-bracket-spacing": "error",
1222
+ "toml/tables-order": "error",
1223
+ "toml/vue-custom-block/no-parsing-error": "error",
1224
+ ...options.overrides
1225
+ }
1226
+ }];
1227
+ };
1228
+
1229
+ //#endregion
1230
+ //#region src/configs/antfu.ts
1231
+ /**
1232
+ * Config for common files
1233
+ *
1234
+ * @see {@link https://github.com/antfu/eslint-plugin-antfu}
1235
+ *
1236
+ * @param options - {@link ConfigAntfuOptions}
1237
+ * @returns ESLint configs
1238
+ */
1239
+ const configAntfu = (options = {}) => [{
1240
+ name: "ntnyq/antfu",
1241
+ plugins: { antfu: pluginAntfu },
1242
+ rules: {
1243
+ "antfu/import-dedupe": "error",
1244
+ "antfu/indent-unindent": "error",
1245
+ "antfu/no-import-dist": "error",
1246
+ "antfu/no-import-node-modules-by-path": "error",
1247
+ ...options.overrides
1248
+ }
1249
+ }];
1250
+
1251
+ //#endregion
1252
+ //#region src/configs/astro.ts
1253
+ /**
1254
+ * Config for astro files
1255
+ *
1256
+ * @see {@link https://github.com/ota-meshi/eslint-plugin-astro}
1257
+ *
1258
+ * @param options - {@link ConfigAstroOptions}
1259
+ * @returns ESLint configs
1260
+ */
1261
+ const configAstro = async (options = {}) => {
1262
+ await ensurePackages(["astro-eslint-parser", "eslint-plugin-astro"]);
1263
+ const [parserAstro, pluginAstro] = await Promise.all([interopDefault(import("astro-eslint-parser")), interopDefault(import("eslint-plugin-astro"))]);
1264
+ const { files = [GLOB_ASTRO], extraFileExtensions = [] } = options;
1265
+ return [{
1266
+ name: "ntnyq/astro",
1267
+ files,
1268
+ plugins: { astro: pluginAstro },
1269
+ processor: pluginAstro.processors["client-side-ts"],
1270
+ languageOptions: {
1271
+ parser: parserAstro,
1272
+ sourceType: "module",
1273
+ globals: { ...pluginAstro.environments.astro.globals },
1274
+ parserOptions: {
1275
+ extraFileExtensions,
1276
+ parser: parserTypeScript
1277
+ }
1278
+ },
1279
+ rules: {
1280
+ "astro/missing-client-only-directive-value": "error",
1281
+ "astro/no-conflict-set-directives": "error",
1282
+ "astro/no-deprecated-astro-canonicalurl": "error",
1283
+ "astro/no-deprecated-astro-fetchcontent": "error",
1284
+ "astro/no-deprecated-astro-resolve": "error",
1285
+ "astro/no-deprecated-getentrybyslug": "error",
1286
+ "astro/no-unused-define-vars-in-style": "error",
1287
+ "astro/valid-compile": "error",
1288
+ ...options.overrides
1289
+ }
1290
+ }];
1291
+ };
1292
+
1293
+ //#endregion
1294
+ //#region src/configs/jsdoc.ts
1295
+ /**
1296
+ * JavaScript specific rules
1297
+ */
1298
+ const javscriptRules = {
1299
+ "jsdoc/no-types": "off",
1300
+ "jsdoc/no-undefined-types": "error",
1301
+ "jsdoc/require-param-type": "error",
1302
+ "jsdoc/require-property-type": "error",
1303
+ "jsdoc/require-returns-type": "error"
1304
+ };
1305
+ /**
1306
+ * TypeScript specific rules
1307
+ */
1308
+ const typescriptRules = {
1309
+ "jsdoc/no-undefined-types": "off",
1310
+ "jsdoc/require-param-type": "off",
1311
+ "jsdoc/require-property-type": "off",
1312
+ "jsdoc/require-returns-type": "off",
1313
+ "jsdoc/no-types": "error"
1314
+ };
1315
+ /**
1316
+ * Config for jsdoc
1317
+ *
1318
+ * @see {@link https://github.com/gajus/eslint-plugin-jsdoc}
1319
+ *
1320
+ * @param options - {@link ConfigJsdocOptions}
1321
+ * @returns ESLint configs
1322
+ */
1323
+ const configJsdoc = (options = {}) => [{
1324
+ name: "ntnyq/jsdoc",
1325
+ plugins: { jsdoc: pluginJsdoc },
1326
+ rules: {
1327
+ "jsdoc/tag-lines": "off",
1328
+ "jsdoc/text-escaping": "off",
1329
+ "jsdoc/check-access": "warn",
1330
+ "jsdoc/implements-on-classes": "warn",
1331
+ "jsdoc/require-param-name": "warn",
1332
+ "jsdoc/require-property": "warn",
1333
+ "jsdoc/require-property-description": "warn",
1334
+ "jsdoc/require-property-name": "warn",
1335
+ "jsdoc/require-returns-check": "warn",
1336
+ "jsdoc/require-returns-description": "warn",
1337
+ "jsdoc/require-yields-check": "warn",
1338
+ "jsdoc/check-alignment": "error",
1339
+ "jsdoc/check-line-alignment": "error",
1340
+ "jsdoc/check-param-names": "error",
1341
+ "jsdoc/check-property-names": "error",
1342
+ "jsdoc/check-tag-names": ["error", { definedTags: [
1343
+ "vite-ignore",
1344
+ "unocss-include",
1345
+ "pg",
1346
+ "perfectionist-group",
1347
+ "regex101",
1348
+ "compatibility",
1349
+ "category",
1350
+ "experimental",
1351
+ "internal"
1352
+ ] }],
1353
+ "jsdoc/check-types": "error",
1354
+ "jsdoc/empty-tags": "error",
1355
+ "jsdoc/multiline-blocks": "error",
1356
+ "jsdoc/no-bad-blocks": ["error", { ignore: [
1357
+ "ts-check",
1358
+ "ts-expect-error",
1359
+ "ts-ignore",
1360
+ "ts-nocheck",
1361
+ "vite-ignore"
1362
+ ] }],
1363
+ "jsdoc/no-blank-block-descriptions": "error",
1364
+ "jsdoc/no-blank-blocks": "error",
1365
+ "jsdoc/no-defaults": "error",
1366
+ "jsdoc/no-multi-asterisks": "error",
1367
+ "jsdoc/require-asterisk-prefix": "error",
1368
+ "jsdoc/require-hyphen-before-param-description": "error",
1369
+ ...options.typescript ? typescriptRules : javscriptRules,
1370
+ ...options.overrides
1371
+ }
1372
+ }];
1373
+
1374
+ //#endregion
1375
+ //#region src/configs/jsonc.ts
1376
+ /**
1377
+ * @see {@link https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/lib/configs/base.ts}
1378
+ */
1379
+ const disabledCoreRules = {
1380
+ "no-unused-expressions": "off",
1381
+ "no-unused-vars": "off",
1382
+ strict: "off"
1383
+ };
1384
+ /**
1385
+ * Config for json, jsonc and json5 files
1386
+ *
1387
+ * @see {@link https://ota-meshi.github.io/eslint-plugin-jsonc}
1388
+ *
1389
+ * @param options - {@link ConfigJsoncOptions}
1390
+ * @returns ESLint configs
1391
+ */
1392
+ const configJsonc = (options = {}) => {
1393
+ const { files = [
1394
+ GLOB_JSON,
1395
+ GLOB_JSON5,
1396
+ GLOB_JSONC
1397
+ ] } = options;
1398
+ return [{
1399
+ name: "ntnyq/jsonc",
1400
+ files,
1401
+ plugins: { jsonc: pluginJsonc },
1402
+ languageOptions: { parser: parserJsonc },
1403
+ rules: {
1404
+ "jsonc/array-bracket-spacing": ["error", "never"],
1405
+ "jsonc/comma-dangle": ["error", "never"],
1406
+ "jsonc/comma-style": ["error", "last"],
1407
+ "jsonc/indent": ["error", 2],
1408
+ "jsonc/key-spacing": ["error", {
1409
+ afterColon: true,
1410
+ beforeColon: false
1411
+ }],
1412
+ "jsonc/no-bigint-literals": "error",
1413
+ "jsonc/no-binary-expression": "error",
1414
+ "jsonc/no-binary-numeric-literals": "error",
1415
+ "jsonc/no-dupe-keys": "error",
1416
+ "jsonc/no-escape-sequence-in-identifier": "error",
1417
+ "jsonc/no-floating-decimal": "error",
1418
+ "jsonc/no-hexadecimal-numeric-literals": "error",
1419
+ "jsonc/no-infinity": "error",
1420
+ "jsonc/no-multi-str": "error",
1421
+ "jsonc/no-nan": "error",
1422
+ "jsonc/no-number-props": "error",
1423
+ "jsonc/no-numeric-separators": "error",
1424
+ "jsonc/no-octal": "error",
1425
+ "jsonc/no-octal-escape": "error",
1426
+ "jsonc/no-octal-numeric-literals": "error",
1427
+ "jsonc/no-parenthesized": "error",
1428
+ "jsonc/no-plus-sign": "error",
1429
+ "jsonc/no-regexp-literals": "error",
1430
+ "jsonc/no-sparse-arrays": "error",
1431
+ "jsonc/no-template-literals": "error",
1432
+ "jsonc/no-undefined-value": "error",
1433
+ "jsonc/no-unicode-codepoint-escapes": "error",
1434
+ "jsonc/no-useless-escape": "error",
1435
+ "jsonc/object-curly-newline": ["error", {
1436
+ consistent: true,
1437
+ multiline: true
1438
+ }],
1439
+ "jsonc/object-curly-spacing": ["error", "always"],
1440
+ "jsonc/object-property-newline": ["error", { allowMultiplePropertiesPerLine: true }],
1441
+ "jsonc/quote-props": "error",
1442
+ "jsonc/quotes": "error",
1443
+ "jsonc/space-unary-ops": "error",
1444
+ "jsonc/valid-json-number": "error",
1445
+ "jsonc/vue-custom-block/no-parsing-error": "error",
1446
+ ...disabledCoreRules,
1447
+ ...options.prettier ? {
1448
+ "jsonc/array-bracket-newline": "off",
1449
+ "jsonc/array-bracket-spacing": "off",
1450
+ "jsonc/array-element-newline": "off",
1451
+ "jsonc/comma-dangle": "off",
1452
+ "jsonc/comma-style": "off",
1453
+ "jsonc/indent": "off",
1454
+ "jsonc/key-spacing": "off",
1455
+ "jsonc/no-floating-decimal": "off",
1456
+ "jsonc/object-curly-newline": "off",
1457
+ "jsonc/object-curly-spacing": "off",
1458
+ "jsonc/object-property-newline": "off",
1459
+ "jsonc/quote-props": "off",
1460
+ "jsonc/quotes": "off",
1461
+ "jsonc/space-unary-ops": "off"
1462
+ } : {},
1463
+ ...options.overrides
1464
+ }
1465
+ }];
1466
+ };
1467
+
1468
+ //#endregion
1469
+ //#region src/configs/ntnyq.ts
1470
+ /**
1471
+ * Config for common files
1472
+ *
1473
+ * @see {@link https://github.com/ntnyq/eslint-plugin-ntnyq}
1474
+ *
1475
+ * @param options - {@link ConfigNtnyqOptions}
1476
+ * @returns ESLint configs
1477
+ */
1478
+ const configNtnyq = (options = {}) => [{
1479
+ name: "ntnyq/ntnyq",
1480
+ plugins: { ntnyq: pluginNtnyq },
1481
+ rules: {
1482
+ "ntnyq/no-duplicate-exports": "error",
1483
+ "ntnyq/prefer-newline-after-file-header": "error",
1484
+ ...options.overrides
1485
+ }
1486
+ }];
1487
+
1488
+ //#endregion
1489
+ //#region src/configs/pinia.ts
1490
+ /**
1491
+ * Config for pinia store
1492
+ *
1493
+ * @see {@link https://github.com/lisilinhart/eslint-plugin-pinia}
1494
+ *
1495
+ * @param options - {@link ConfigPiniaOptions}
1496
+ * @returns ESLint configs
1497
+ */
1498
+ const configPinia = (options = {}) => {
1499
+ const { files = [GLOB_PINIA_STORE] } = options;
1500
+ return [{
1501
+ name: "ntnyq/pinia",
1502
+ files,
1503
+ plugins: { pinia: pluginPinia },
1504
+ rules: {
1505
+ "pinia/never-export-initialized-store": "error",
1506
+ "pinia/no-duplicate-store-ids": "error",
1507
+ "pinia/no-return-global-properties": "error",
1508
+ "pinia/no-store-to-refs-in-store": "error",
1509
+ "pinia/prefer-single-store-per-file": "error",
1510
+ "pinia/prefer-use-store-naming-convention": ["error", {
1511
+ checkStoreNameMismatch: true,
1512
+ storeSuffix: "Store"
1513
+ }],
1514
+ "pinia/require-setup-store-properties-export": "error",
1515
+ ...options.overrides
1516
+ }
1517
+ }];
1518
+ };
1519
+
1520
+ //#endregion
1521
+ //#region src/configs/depend.ts
1522
+ /**
1523
+ * Config for optimisations dependency
1524
+ *
1525
+ * @see {@link https://github.com/es-tooling/eslint-plugin-depend}
1526
+ * @see {@link https://github.com/es-tooling/module-replacements}
1527
+ *
1528
+ * @param options - {@link ConfigDependOptions}
1529
+ * @returns ESLint configs
1530
+ */
1531
+ const configDepend = (options = {}) => {
1532
+ const { files = [GLOB_SRC], allowed = [], packageJson: enableCheckPackageJson = true } = options;
1533
+ const configs = [{
1534
+ name: "ntnyq/depend",
1535
+ files,
1536
+ plugins: { depend: pluginDepend },
1537
+ rules: {
1538
+ "depend/ban-dependencies": ["error", { allowed }],
1539
+ ...options.overrides
1540
+ }
1541
+ }];
1542
+ if (enableCheckPackageJson) configs.push({
1543
+ name: "ntnyq/depend/package-json",
1544
+ files: [GLOB_PACKAGE_JSON],
1545
+ plugins: { depend: pluginDepend },
1546
+ languageOptions: { parser: parserJsonc },
1547
+ rules: {
1548
+ "depend/ban-dependencies": ["error", { allowed }],
1549
+ ...options.overrides
1550
+ }
1551
+ });
1552
+ return configs;
1553
+ };
1554
+
1555
+ //#endregion
1556
+ //#region src/constants/prettier.ts
1557
+ /**
1558
+ * Options from `@ntnyq/prettier-config`
1559
+ *
1560
+ * @see {@link https://github.com/ntnyq/configs/blob/main/packages/prettier-config/index.js}
1561
+ */
1562
+ const PRETTIER_DEFAULT_OPTIONS = {
1563
+ arrowParens: "avoid",
1564
+ bracketSameLine: false,
1565
+ bracketSpacing: true,
1566
+ embeddedLanguageFormatting: "auto",
1567
+ endOfLine: "lf",
1568
+ experimentalOperatorPosition: "start",
1569
+ experimentalTernaries: false,
1570
+ htmlWhitespaceSensitivity: "css",
1571
+ insertPragma: false,
1572
+ jsxSingleQuote: true,
1573
+ objectWrap: "preserve",
1574
+ printWidth: 80,
1575
+ proseWrap: "preserve",
1576
+ quoteProps: "as-needed",
1577
+ rangeEnd: Number.POSITIVE_INFINITY,
1578
+ rangeStart: 0,
1579
+ requirePragma: false,
1580
+ semi: false,
1581
+ singleAttributePerLine: true,
1582
+ singleQuote: true,
1583
+ tabWidth: 2,
1584
+ trailingComma: "all",
1585
+ useTabs: false,
1586
+ vueIndentScriptAndStyle: false
1587
+ };
1588
+
1589
+ //#endregion
1590
+ //#region src/constants/perfectionist.ts
1591
+ /**
1592
+ * Shared perfectionist plugin settings
1593
+ */
1594
+ const pluginSettings = {
1595
+ fallbackSort: {
1596
+ order: "asc",
1597
+ type: "alphabetical"
1598
+ },
1599
+ ignoreCase: true,
1600
+ order: "asc",
1601
+ partitionByNewLine: false,
1602
+ specialCharacters: "keep",
1603
+ type: "alphabetical"
1604
+ };
1605
+ /**
1606
+ * Shared perfectionist rule options for some rules
1607
+ */
1608
+ const partialRuleOptions = {
1609
+ newlinesBetween: "ignore",
1610
+ partitionByComment: ["@pg", "@perfectionist-group"]
1611
+ };
1612
+ /**
1613
+ * Shared option `groups` for rule `sort-objects`
1614
+ *
1615
+ * @see {@link https://perfectionist.dev/rules/sort-objects}
1616
+ */
1617
+ const sortObjectsGroups = [
1618
+ "property",
1619
+ "multiline-property",
1620
+ "method",
1621
+ "multiline-method",
1622
+ "unknown"
1623
+ ];
1624
+ /**
1625
+ * Shared option `groups` for rules
1626
+ * - `sort-interfaces`
1627
+ * - `sort-object-types`
1628
+ *
1629
+ * @see {@link https://perfectionist.dev/rules/sort-interfaces}
1630
+ * @see {@link https://perfectionist.dev/rules/sort-object-types}
1631
+ */
1632
+ const sortInterfacesOrObjectTypesGroups = [
1633
+ "required-property",
1634
+ "optional-property",
1635
+ "required-method",
1636
+ "optional-method",
1637
+ "required-multiline-property",
1638
+ "optional-multiline-property",
1639
+ "required-multiline-method",
1640
+ "optional-multiline-method",
1641
+ "unknown",
1642
+ "index-signature",
1643
+ "multiline-index-signature"
1644
+ ];
1645
+ /**
1646
+ * Shared option `groups` for rules:
1647
+ * - `sort-intersection-types`
1648
+ * - `sort-union-types`
1649
+ *
1650
+ * Philosophy: keep simple thing first except null & undefined
1651
+ *
1652
+ * @see {@link https://perfectionist.dev/rules/sort-intersection-types}
1653
+ * @see {@link https://perfectionist.dev/rules/sort-union-types}
1654
+ */
1655
+ const sortIntersectionTypesOrUnionTypesGroups = [
1656
+ "literal",
1657
+ "keyword",
1658
+ "named",
1659
+ "intersection",
1660
+ "conditional",
1661
+ "function",
1662
+ "import",
1663
+ "object",
1664
+ "operator",
1665
+ "tuple",
1666
+ "union",
1667
+ "nullish"
1668
+ ];
1669
+ /**
1670
+ * Shared option `groups` for rule `sort-imports`
1671
+ *
1672
+ * @see {@link https://perfectionist.dev/rules/sort-imports}
1673
+ */
1674
+ const sortImportsTypes = [
1675
+ "side-effect-style",
1676
+ "value-style",
1677
+ "value-builtin",
1678
+ "value-external",
1679
+ "value-subpath",
1680
+ "value-internal",
1681
+ "value-parent",
1682
+ "value-sibling",
1683
+ "value-index",
1684
+ "ts-equals-import",
1685
+ "side-effect",
1686
+ "type-builtin",
1687
+ "type-external",
1688
+ "type-subpath",
1689
+ "type-internal",
1690
+ "type-parent",
1691
+ "type-sibling",
1692
+ "type-index",
1693
+ "unknown"
1694
+ ];
1695
+ /**
1696
+ * Shared option `groups` for rule `sort-exports`
1697
+ *
1698
+ * @see {@link https://perfectionist.dev/rules/sort-exports}
1699
+ */
1700
+ const sortExportsGroups = [
1701
+ "value-export",
1702
+ "type-export",
1703
+ "unknown"
1704
+ ];
1705
+ /**
1706
+ * Shared option `groups` for rule `sort-named-exports`
1707
+ *
1708
+ * @see {@link https://perfectionist.dev/rules/sort-named-exports}
1709
+ */
1710
+ const sortNamedExportsGroups = [
1711
+ "value-export",
1712
+ "type-export",
1713
+ "unknown"
1714
+ ];
1715
+ /**
1716
+ * Shared option `groups` for rule `sort-named-imports`
1717
+ *
1718
+ * @see {@link https://perfectionist.dev/rules/sort-named-imports}
1719
+ */
1720
+ const sortNamedImportsGroups = [
1721
+ "value-import",
1722
+ "type-import",
1723
+ "unknown"
1724
+ ];
1725
+ /**
1726
+ * Shared option `groups` for rule `sort-classes`
1727
+ *
1728
+ * // TODO: implement this
1729
+ *
1730
+ * @see {@link https://perfectionist.dev/rules/sort-classes}
1731
+ */
1732
+ const sortClassesGroups = ["unknown"];
1733
+ /**
1734
+ * Shared constants about eslint-plugin-perfectionist
1735
+ */
1736
+ const PERFECTIONIST = Object.freeze({
1737
+ partialRuleOptions,
1738
+ pluginSettings,
1739
+ sortClassesGroups,
1740
+ sortExportsGroups,
1741
+ sortImportsTypes,
1742
+ sortInterfacesOrObjectTypesGroups,
1743
+ sortIntersectionTypesOrUnionTypesGroups,
1744
+ sortNamedExportsGroups,
1745
+ sortNamedImportsGroups,
1746
+ sortObjectsGroups
1747
+ });
1748
+
1749
+ //#endregion
1750
+ //#region src/configs/format.ts
1751
+ /**
1752
+ * Config to use a formatter
1753
+ *
1754
+ * @see {@link https://github.com/antfu/eslint-plugin-format}
1755
+ *
1756
+ * @param options - {@link ConfigFormatOptions}
1757
+ * @returns ESLint configs
1758
+ */
1759
+ const configFormat = async (options = {}) => {
1760
+ await ensurePackages(["eslint-plugin-format"]);
1761
+ const pluginFormat = await interopDefault(import("eslint-plugin-format"));
1762
+ const { css: enableCSS = true, html: enableHTML = true, prettierOptions = {} } = options;
1763
+ const sharedPrettierOptions = {
1764
+ ...PRETTIER_DEFAULT_OPTIONS,
1765
+ ...prettierOptions
1766
+ };
1767
+ const configs = [{
1768
+ name: "ntnyq/format/setup",
1769
+ plugins: { format: pluginFormat }
1770
+ }];
1771
+ if (enableCSS) configs.push({
1772
+ name: "ntnyq/format/css",
1773
+ files: [GLOB_CSS, GLOB_POSTCSS],
1774
+ languageOptions: { parser: parserPlain },
1775
+ rules: { "format/prettier": ["error", mergePrettierOptions(sharedPrettierOptions, { parser: "css" })] }
1776
+ }, {
1777
+ name: "ntnyq/format/scss",
1778
+ files: [GLOB_SCSS],
1779
+ languageOptions: { parser: parserPlain },
1780
+ rules: { "format/prettier": ["error", mergePrettierOptions(sharedPrettierOptions, { parser: "scss" })] }
1781
+ }, {
1782
+ name: "ntnyq/format/less",
1783
+ files: [GLOB_LESS],
1784
+ languageOptions: { parser: parserPlain },
1785
+ rules: { "format/prettier": ["error", mergePrettierOptions(sharedPrettierOptions, { parser: "less" })] }
1786
+ });
1787
+ if (enableHTML) configs.push({
1788
+ name: "ntnyq/format/html",
1789
+ files: [GLOB_HTML],
1790
+ languageOptions: { parser: parserPlain },
1791
+ rules: { "format/prettier": ["error", mergePrettierOptions(sharedPrettierOptions, { parser: "html" })] }
1792
+ });
1793
+ return configs;
1794
+ };
1795
+
1796
+ //#endregion
1797
+ //#region src/configs/regexp.ts
1798
+ /**
1799
+ * Config for regexp
1800
+ *
1801
+ * @see {@link https://github.com/ota-meshi/eslint-plugin-regexp}
1802
+ *
1803
+ * @param options - {@link ConfigRegexpOptions}
1804
+ * @returns ESLint configs
1805
+ */
1806
+ const configRegexp = (options = {}) => {
1807
+ const recommendedConfig = pluginRegexp.configs["flat/recommended"];
1808
+ const recommendedRules$1 = { ...recommendedConfig.rules };
1809
+ if (options.severity === "warn") {
1810
+ for (const key in recommendedRules$1) if (recommendedRules$1[key] === "error") recommendedRules$1[key] = "warn";
1811
+ }
1812
+ return [{
1813
+ ...recommendedConfig,
1814
+ name: "ntnyq/regexp",
1815
+ rules: {
1816
+ ...recommendedRules$1,
1817
+ ...options.overrides
1818
+ }
1819
+ }];
1820
+ };
1821
+
1822
+ //#endregion
1823
+ //#region src/configs/svelte.ts
1824
+ /**
1825
+ * Config for svelte files
1826
+ *
1827
+ * @see {@link https://github.com/ota-meshi/eslint-plugin-svelte}
1828
+ *
1829
+ * @param options - {@link ConfigSvelteOptions}
1830
+ * @returns ESLint configs
1831
+ */
1832
+ const configSvelte = async (options = {}) => {
1833
+ await ensurePackages(["svelte-eslint-parser", "eslint-plugin-svelte"]);
1834
+ const [parserSvelte, pluginSvelte] = await Promise.all([interopDefault(import("svelte-eslint-parser")), interopDefault(import("eslint-plugin-svelte"))]);
1835
+ const { files = [GLOB_SVELTE], extraFileExtensions = [] } = options;
1836
+ return [{
1837
+ name: "ntnyq/svelte",
1838
+ files,
1839
+ plugins: { svelte: pluginSvelte },
1840
+ processor: pluginSvelte.processors[".svelte"],
1841
+ languageOptions: {
1842
+ parser: parserSvelte,
1843
+ sourceType: "module",
1844
+ parserOptions: {
1845
+ extraFileExtensions,
1846
+ parser: parserTypeScript
1847
+ }
1848
+ },
1849
+ rules: {
1850
+ "import-x/no-mutable-exports": "off",
1851
+ "no-undef": "off",
1852
+ "no-unused-vars": ["error", {
1853
+ args: "none",
1854
+ caughtErrors: "none",
1855
+ ignoreRestSiblings: true,
1856
+ vars: "all",
1857
+ varsIgnorePattern: "^(\\$\\$Props$|\\$\\$Events$|\\$\\$Slots$)"
1858
+ }],
1859
+ "svelte/comment-directive": "error",
1860
+ "svelte/derived-has-same-inputs-outputs": "error",
1861
+ "svelte/html-closing-bracket-spacing": "error",
1862
+ "svelte/html-quotes": ["error", {
1863
+ prefer: "double",
1864
+ dynamic: {
1865
+ avoidInvalidUnquotedInHTML: false,
1866
+ quoted: true
1867
+ }
1868
+ }],
1869
+ "svelte/indent": ["error", {
1870
+ alignAttributesVertically: true,
1871
+ indent: 2,
1872
+ indentScript: false
1873
+ }],
1874
+ "svelte/mustache-spacing": ["error", {
1875
+ attributesAndProps: "never",
1876
+ directiveExpressions: "always",
1877
+ textExpressions: "always",
1878
+ tags: {
1879
+ closingBrace: "always",
1880
+ openingBrace: "always"
1881
+ }
1882
+ }],
1883
+ "svelte/no-at-debug-tags": "error",
1884
+ "svelte/no-at-html-tags": "error",
1885
+ "svelte/no-dupe-else-if-blocks": "error",
1886
+ "svelte/no-dupe-style-properties": "error",
1887
+ "svelte/no-dupe-use-directives": "error",
1888
+ "svelte/no-dynamic-slot-name": "error",
1889
+ "svelte/no-export-load-in-svelte-module-in-kit-pages": "error",
1890
+ "svelte/no-inner-declarations": "error",
1891
+ "svelte/no-not-function-handler": "error",
1892
+ "svelte/no-object-in-text-mustaches": "error",
1893
+ "svelte/no-reactive-functions": "error",
1894
+ "svelte/no-reactive-literals": "error",
1895
+ "svelte/no-shorthand-style-property-overrides": "error",
1896
+ "svelte/no-spaces-around-equal-signs-in-attribute": "error",
1897
+ "svelte/no-trailing-spaces": "error",
1898
+ "svelte/no-unknown-style-directive-property": "error",
1899
+ "svelte/no-unused-svelte-ignore": "error",
1900
+ "svelte/no-useless-mustaches": "error",
1901
+ "svelte/require-store-callbacks-use-set-param": "error",
1902
+ "svelte/spaced-html-comment": "error",
1903
+ "svelte/system": "error",
1904
+ "svelte/valid-each-key": "error",
1905
+ ...options.overrides
1906
+ }
1907
+ }];
1908
+ };
1909
+
1910
+ //#endregion
1911
+ //#region src/configs/unocss.ts
1912
+ /**
1913
+ * Config for UnoCSS
1914
+ *
1915
+ * @see {@link https://github.com/unocss/unocss/tree/main/packages-integrations/eslint-plugin}
1916
+ *
1917
+ * @param options - {@link ConfigUnoCSSOptions}
1918
+ * @returns ESLint configs
1919
+ */
1920
+ const configUnoCSS = (options = {}) => [{
1921
+ name: "ntnyq/unocss",
1922
+ plugins: { unocss: pluginUnoCSS },
1923
+ rules: {
1924
+ "unocss/order-attributify": options.attributify ? "error" : "off",
1925
+ "unocss/order": "error",
1926
+ ...options.overrides
1927
+ }
1928
+ }];
1929
+
1930
+ //#endregion
1931
+ //#region src/commands/regexper.ts
1932
+ const regexper = defineCommand({
1933
+ name: "regexper",
1934
+ match: /(\b|\s|^)(@regexper)(\s\S+)?(\b|\s|$)/,
1935
+ action(ctx) {
1936
+ const literal = ctx.findNodeBelow((node) => node.type === "Literal" && "regex" in node);
1937
+ if (!literal) return ctx.reportError("Unable to find a regexp literal to generate");
1938
+ const [_fullStr = "", spaceBefore = "", commandStr = "", existingUrl = "", _spaceAfter = ""] = ctx.matches;
1939
+ const url = `https://regexper.com/#${encodeURIComponent(literal.raw)}`;
1940
+ if (existingUrl.trim() === url.trim()) return;
1941
+ const indexStart = ctx.comment.range[0] + ctx.matches.index + spaceBefore.length + 2;
1942
+ const indexEnd = indexStart + commandStr.length + existingUrl.length;
1943
+ ctx.report({
1944
+ loc: {
1945
+ start: ctx.source.getLocFromIndex(indexStart),
1946
+ end: ctx.source.getLocFromIndex(indexEnd)
1947
+ },
1948
+ removeComment: false,
1949
+ message: "Update the regexper link",
1950
+ fix(fixer) {
1951
+ return fixer.replaceTextRange([indexStart, indexEnd], `@regexper ${url}`);
1952
+ }
1953
+ });
1954
+ }
1955
+ });
1956
+
1957
+ //#endregion
1958
+ //#region src/commands/index.ts
1959
+ const commands = [regexper];
1960
+
1961
+ //#endregion
1962
+ //#region src/configs/command.ts
1963
+ /**
1964
+ * Config for useing comments as codemod
1965
+ *
1966
+ * @see {@link https://github.com/antfu/eslint-plugin-command}
1967
+ *
1968
+ * @param options - {@link ConfigCommandOptions}
1969
+ * @returns ESLint configs
1970
+ */
1971
+ const configCommand = (options = {}) => [{
1972
+ ...createCommandConfig({
1973
+ ...options,
1974
+ commands: [
1975
+ ...builtinCommands,
1976
+ ...commands,
1977
+ ...options.commands || []
1978
+ ]
1979
+ }),
1980
+ name: "ntnyq/command"
1981
+ }];
1982
+
1983
+ //#endregion
1984
+ //#region src/configs/ignores.ts
1985
+ /**
1986
+ * Config for ignore files from linting
1987
+ *
1988
+ * @see https://eslint.org/docs/latest/use/configure/configuration-files-new#globally-ignoring-files-with-ignores
1989
+ *
1990
+ * @param customIgnores - {@link ConfigIgnoresOptions}
1991
+ * @returns ESLint configs
1992
+ */
1993
+ const configIgnores = (customIgnores = []) => [{
1994
+ name: "ntnyq/ignores",
1995
+ ignores: [...GLOB_EXCLUDE, ...customIgnores]
1996
+ }];
1997
+
1998
+ //#endregion
1999
+ //#region src/configs/importX.ts
2000
+ /**
2001
+ * Config for imports and exports
2002
+ *
2003
+ * @see {@link https://github.com/un-ts/eslint-plugin-import-x}
2004
+ *
2005
+ * @param options - {@link ConfigImportXOptions}
2006
+ * @returns ESLint configs
2007
+ */
2008
+ const configImportX = (options = {}) => {
2009
+ const { preferTypeScriptResolver = true, typescript: enableTypeScript } = options;
2010
+ return [{
2011
+ name: "ntnyq/import-x",
2012
+ plugins: { "import-x": pluginImportX },
2013
+ settings: { "import-x/resolver-next": [enableTypeScript && preferTypeScriptResolver ? createTypeScriptImportResolver({ extensions: [
2014
+ ".ts",
2015
+ ".tsx",
2016
+ ".d.ts",
2017
+ ".js",
2018
+ ".jsx",
2019
+ ".json",
2020
+ ".node"
2021
+ ] }) : pluginImportX.createNodeResolver({ extensions: [
2022
+ ".js",
2023
+ ".mjs",
2024
+ ".ts",
2025
+ ".mts",
2026
+ ".d.ts",
2027
+ ".json"
2028
+ ] })] },
2029
+ rules: {
2030
+ "import-x/no-absolute-path": "off",
2031
+ "import-x/no-named-as-default-member": "off",
2032
+ "import-x/no-named-default": "off",
2033
+ "import-x/no-unresolved": "off",
2034
+ "import-x/order": "off",
2035
+ "import-x/consistent-type-specifier-style": ["error", "prefer-top-level"],
2036
+ "import-x/export": "error",
2037
+ "import-x/first": "error",
2038
+ "import-x/newline-after-import": "error",
2039
+ "import-x/no-duplicates": "error",
2040
+ "import-x/no-mutable-exports": "error",
2041
+ "import-x/no-self-import": "error",
2042
+ ...options.overrides
2043
+ }
2044
+ }];
2045
+ };
2046
+
2047
+ //#endregion
2048
+ //#region src/configs/unicorn.ts
2049
+ const disabledRules = {
2050
+ "unicorn/better-regex": "off",
2051
+ "unicorn/explicit-length-check": "off",
2052
+ "unicorn/no-array-callback-reference": "off",
2053
+ "unicorn/no-array-reverse": "off",
2054
+ "unicorn/prefer-global-this": "off",
2055
+ "unicorn/prefer-top-level-await": "off",
2056
+ "unicorn/require-module-specifiers": "off"
2057
+ };
2058
+ /**
2059
+ * Config for powerful rules
2060
+ *
2061
+ * @see {@link https://github.com/sindresorhus/eslint-plugin-unicorn}
2062
+ *
2063
+ * @param options - {@link ConfigUnicornOptions}
2064
+ * @returns ESLint configs
2065
+ */
2066
+ const configUnicorn = (options = {}) => [{
2067
+ name: "ntnyq/unicorn",
2068
+ plugins: { unicorn: pluginUnicorn },
2069
+ rules: {
2070
+ "unicorn/consistent-assert": "error",
2071
+ "unicorn/consistent-existence-index-check": "error",
2072
+ "unicorn/error-message": "error",
2073
+ "unicorn/escape-case": "error",
2074
+ "unicorn/new-for-builtins": "error",
2075
+ "unicorn/no-accessor-recursion": "error",
2076
+ "unicorn/no-console-spaces": "error",
2077
+ "unicorn/no-for-loop": "error",
2078
+ "unicorn/no-hex-escape": "error",
2079
+ "unicorn/no-instanceof-builtins": "error",
2080
+ "unicorn/no-lonely-if": "error",
2081
+ "unicorn/no-new-buffer": "error",
2082
+ "unicorn/no-static-only-class": "error",
2083
+ "unicorn/no-typeof-undefined": "error",
2084
+ "unicorn/no-unnecessary-await": "error",
2085
+ "unicorn/prefer-class-fields": "error",
2086
+ "unicorn/prefer-import-meta-properties": "error",
2087
+ "unicorn/prefer-includes": "error",
2088
+ "unicorn/prefer-keyboard-event-key": "error",
2089
+ "unicorn/prefer-math-min-max": "error",
2090
+ "unicorn/prefer-math-trunc": "error",
2091
+ "unicorn/prefer-modern-math-apis": "error",
2092
+ "unicorn/prefer-negative-index": "error",
2093
+ "unicorn/prefer-node-protocol": "error",
2094
+ "unicorn/prefer-optional-catch-binding": "error",
2095
+ "unicorn/prefer-prototype-methods": "error",
2096
+ "unicorn/prefer-reflect-apply": "error",
2097
+ "unicorn/prefer-structured-clone": "error",
2098
+ "unicorn/switch-case-braces": ["error", "avoid"],
2099
+ "unicorn/catch-error-name": ["error", {
2100
+ name: "err",
2101
+ ignore: ["^_."]
2102
+ }],
2103
+ "unicorn/custom-error-definition": "error",
2104
+ "unicorn/no-useless-error-capture-stack-trace": "error",
2105
+ "unicorn/prefer-type-error": "error",
2106
+ "unicorn/throw-new-error": "error",
2107
+ "unicorn/no-zero-fractions": "error",
2108
+ "unicorn/number-literal-case": "error",
2109
+ "unicorn/prefer-number-properties": "error",
2110
+ "unicorn/prefer-regexp-test": "error",
2111
+ "unicorn/consistent-date-clone": "error",
2112
+ "unicorn/prefer-date-now": "error",
2113
+ "unicorn/prefer-code-point": "error",
2114
+ "unicorn/prefer-string-slice": "error",
2115
+ "unicorn/prefer-string-starts-ends-with": "error",
2116
+ "unicorn/prefer-string-trim-start-end": "error",
2117
+ "unicorn/no-invalid-remove-event-listener": "error",
2118
+ "unicorn/prefer-add-event-listener": "error",
2119
+ "unicorn/prefer-dom-node-append": "error",
2120
+ "unicorn/prefer-dom-node-dataset": "error",
2121
+ "unicorn/prefer-dom-node-remove": "error",
2122
+ "unicorn/prefer-dom-node-text-content": "error",
2123
+ "unicorn/prefer-modern-dom-apis": "error",
2124
+ "unicorn/prefer-query-selector": "error",
2125
+ "unicorn/no-array-method-this-argument": "error",
2126
+ "unicorn/no-new-array": "error",
2127
+ "unicorn/no-unnecessary-array-flat-depth": "error",
2128
+ "unicorn/no-unnecessary-array-splice-count": "error",
2129
+ "unicorn/no-unnecessary-slice-end": "error",
2130
+ "unicorn/prefer-array-find": "error",
2131
+ "unicorn/prefer-array-flat-map": "error",
2132
+ "unicorn/prefer-array-index-of": "error",
2133
+ "unicorn/prefer-array-some": "error",
2134
+ "unicorn/prefer-single-call": "error",
2135
+ "unicorn/require-array-join-separator": "error",
2136
+ "unicorn/prefer-set-has": "error",
2137
+ "unicorn/prefer-set-size": "error",
2138
+ ...disabledRules,
2139
+ ...options.overrides
2140
+ }
2141
+ }];
2142
+
2143
+ //#endregion
2144
+ //#region src/configs/deMorgan.ts
2145
+ /**
2146
+ * Config for optimize logic
2147
+ *
2148
+ * @see {@link https://github.com/azat-io/eslint-plugin-de-morgan}
2149
+ *
2150
+ * @param options - {@link ConfigDeMorganOptions}
2151
+ * @returns ESLint configs
2152
+ */
2153
+ const configDeMorgan = (options = {}) => [{
2154
+ ...pluginDeMorgan.configs.recommended,
2155
+ name: "ntnyq/de-morgan",
2156
+ rules: {
2157
+ ...pluginDeMorgan.configs.recommended.rules,
2158
+ ...options.overrides
2159
+ }
2160
+ }];
2161
+
2162
+ //#endregion
2163
+ //#region src/configs/markdown.ts
2164
+ /**
2165
+ * Config for markdown files
2166
+ *
2167
+ * @see {@link https://github.com/eslint/markdown}
2168
+ *
2169
+ * @param options - {@link ConfigMarkdownOptions}
2170
+ * @returns ESLint configs
2171
+ */
2172
+ const configMarkdown = (options = {}) => {
2173
+ const { files = [GLOB_MARKDOWN_CODE], extraFileExtensions = [] } = options;
2174
+ const configs = [
2175
+ ...pluginMarkdown.configs.processor.map((config) => ({
2176
+ ...config,
2177
+ name: `ntnyq/${config.name}`
2178
+ })),
2179
+ (
2180
+ /**
2181
+ * enhance `markdown/recommended/processor`
2182
+ */
2183
+ {
2184
+ name: "ntnyq/markdown/processor",
2185
+ files,
2186
+ ignores: [GLOB_MARKDOWN_NESTED],
2187
+ processor: mergeProcessors([pluginMarkdown.processors.markdown, processorPassThrough])
2188
+ }),
2189
+ {
2190
+ name: "ntnyq/markdown/parser",
2191
+ files,
2192
+ languageOptions: { parser: parserPlain }
2193
+ },
2194
+ {
2195
+ name: "ntnyq/markdown/disabled",
2196
+ files: [...files, ...extraFileExtensions.map((ext) => `${GLOB_MARKDOWN}/**/*${ext}`)],
2197
+ languageOptions: { parserOptions: {
2198
+ project: false,
2199
+ projectService: false,
2200
+ ecmaFeatures: { impliedStrict: true }
2201
+ } },
2202
+ rules: {
2203
+ "@typescript-eslint/consistent-type-imports": "off",
2204
+ "@typescript-eslint/no-extraneous-class": "off",
2205
+ "@typescript-eslint/no-namespace": "off",
2206
+ "@typescript-eslint/no-redeclare": "off",
2207
+ "@typescript-eslint/no-require-imports": "off",
2208
+ "@typescript-eslint/no-unused-expressions": "off",
2209
+ "@typescript-eslint/no-unused-vars": "off",
2210
+ "@typescript-eslint/no-use-before-define": "off",
2211
+ "import-x/no-unresolved": "off",
2212
+ "no-alert": "off",
2213
+ "no-console": "off",
2214
+ "no-restricted-imports": "off",
2215
+ "no-undef": "off",
2216
+ "no-unused-expressions": "off",
2217
+ "no-unused-vars": "off",
2218
+ "node/prefer-global/buffer": "off",
2219
+ "node/prefer-global/process": "off",
2220
+ "unused-imports/no-unused-imports": "off",
2221
+ "unused-imports/no-unused-vars": "off",
2222
+ ...configsTypeScript.disableTypeChecked.rules,
2223
+ ...options.overrides
2224
+ }
2225
+ }
2226
+ ];
2227
+ return configs;
2228
+ };
2229
+
2230
+ //#endregion
2231
+ //#region src/configs/prettier.ts
2232
+ /**
2233
+ * Config for using prettier
2234
+ *
2235
+ * @see {@link https://github.com/prettier/eslint-plugin-prettier}
2236
+ *
2237
+ * @param options - {@link ConfigPrettierOptions}
2238
+ * @returns ESLint configs
2239
+ */
2240
+ const configPrettier = (options = {}) => {
2241
+ const { disabledFiles = [
2242
+ GLOB_SVG,
2243
+ GLOB_TOML,
2244
+ GLOB_ASTRO,
2245
+ GLOB_SVELTE
2246
+ ], userDisabledFiles = [] } = options;
2247
+ return [{
2248
+ name: "ntnyq/prettier",
2249
+ plugins: { prettier: pluginPrettier },
2250
+ rules: {
2251
+ "vue/array-bracket-newline": "off",
2252
+ "vue/array-bracket-spacing": "off",
2253
+ "vue/array-element-newline": "off",
2254
+ "vue/arrow-spacing": "off",
2255
+ "vue/block-spacing": "off",
2256
+ "vue/block-tag-newline": "off",
2257
+ "vue/brace-style": "off",
2258
+ "vue/comma-dangle": "off",
2259
+ "vue/comma-spacing": "off",
2260
+ "vue/comma-style": "off",
2261
+ "vue/dot-location": "off",
2262
+ "vue/func-call-spacing": "off",
2263
+ "vue/html-closing-bracket-newline": "off",
2264
+ "vue/html-closing-bracket-spacing": "off",
2265
+ "vue/html-end-tags": "off",
2266
+ "vue/html-indent": "off",
2267
+ "vue/html-quotes": "off",
2268
+ "vue/key-spacing": "off",
2269
+ "vue/keyword-spacing": "off",
2270
+ "vue/max-attributes-per-line": "off",
2271
+ "vue/multiline-html-element-content-newline": "off",
2272
+ "vue/multiline-ternary": "off",
2273
+ "vue/mustache-interpolation-spacing": "off",
2274
+ "vue/no-extra-parens": "off",
2275
+ "vue/no-multi-spaces": "off",
2276
+ "vue/no-spaces-around-equal-signs-in-attribute": "off",
2277
+ "vue/object-curly-newline": "off",
2278
+ "vue/object-curly-spacing": "off",
2279
+ "vue/object-property-newline": "off",
2280
+ "vue/operator-linebreak": "off",
2281
+ "vue/quote-props": "off",
2282
+ "vue/script-indent": "off",
2283
+ "vue/singleline-html-element-content-newline": "off",
2284
+ "vue/space-in-parens": "off",
2285
+ "vue/space-infix-ops": "off",
2286
+ "vue/space-unary-ops": "off",
2287
+ "vue/template-curly-spacing": "off",
2288
+ "arrow-body-style": "off",
2289
+ "prefer-arrow-callback": "off",
2290
+ "prettier/prettier": options.severity || "warn",
2291
+ ...options.overrides
2292
+ }
2293
+ }, (
2294
+ /**
2295
+ * Languages that prettier currently does not support
2296
+ */
2297
+ {
2298
+ name: "ntnyq/prettier/disabled",
2299
+ files: [...disabledFiles, ...userDisabledFiles],
2300
+ plugins: { prettier: pluginPrettier },
2301
+ rules: { "prettier/prettier": "off" }
2302
+ })];
2303
+ };
2304
+
2305
+ //#endregion
2306
+ //#region src/configs/specials.ts
2307
+ /**
2308
+ * Config for special files
2309
+ *
2310
+ * @param options - {@link ConfigSpecialsOptions}
2311
+ * @returns ESLint configs
2312
+ */
2313
+ const configSpecials = (options = {}) => {
2314
+ const { shadcnVue: enableShadcnVue = hasShadcnVue() } = options;
2315
+ const configs = [
2316
+ {
2317
+ name: "ntnyq/specials/scripts",
2318
+ files: [`**/scripts/${GLOB_SRC}`],
2319
+ rules: {
2320
+ "@typescript-eslint/explicit-function-return-type": "off",
2321
+ "no-console": "off",
2322
+ ...options.overridesScriptsRules
2323
+ }
2324
+ },
2325
+ {
2326
+ name: "ntnyq/specials/cli",
2327
+ files: [`**/cli/${GLOB_SRC}`, `**/cli.${GLOB_SRC_EXT}`],
2328
+ rules: {
2329
+ "@typescript-eslint/explicit-function-return-type": "off",
2330
+ "no-console": "off",
2331
+ ...options.overridesCliRules
2332
+ }
2333
+ },
2334
+ {
2335
+ name: "ntnyq/specials/bin",
2336
+ files: [`**/bin/${GLOB_SRC}`, `**/bin.${GLOB_SRC_EXT}`],
2337
+ rules: {
2338
+ "@typescript-eslint/explicit-function-return-type": "off",
2339
+ "antfu/no-import-dist": "off",
2340
+ "no-console": "off",
2341
+ ...options.overridesBinRules
2342
+ }
2343
+ },
2344
+ {
2345
+ name: "ntnyq/specials/userscript",
2346
+ files: [`**/*.user.${GLOB_SRC_EXT}`],
2347
+ languageOptions: { globals: { ...globals.greasemonkey } },
2348
+ rules: {
2349
+ camelcase: ["error", { allow: ["^GM_.+"] }],
2350
+ ...options.overridesUserScriptsRules
2351
+ }
2352
+ },
2353
+ {
2354
+ name: "ntnyq/specials/config-file",
2355
+ files: [`**/*.config*.${GLOB_SRC_EXT}`],
2356
+ plugins: {
2357
+ "import-x": pluginImportX,
2358
+ perfectionist: pluginPerfectionist
2359
+ },
2360
+ settings: { perfectionist: PERFECTIONIST.pluginSettings },
2361
+ rules: {
2362
+ "@typescript-eslint/explicit-function-return-type": "off",
2363
+ "import-x/no-default-export": "off",
2364
+ "no-console": "off",
2365
+ "perfectionist/sort-objects": ["error", {
2366
+ ...PERFECTIONIST.partialRuleOptions,
2367
+ groups: PERFECTIONIST.sortObjectsGroups
2368
+ }],
2369
+ ...options.overridesConfigFileRules
2370
+ }
2371
+ }
2372
+ ];
2373
+ if (enableShadcnVue) {
2374
+ const shadcnOptions = resolveSubOptions(options, "shadcnVue");
2375
+ configs.push({
2376
+ name: "ntnyq/specials/shadcn-vue",
2377
+ files: shadcnOptions.files || ["**/components/ui/**/*.ts", "**/components/ui/**/*.vue"],
2378
+ rules: {
2379
+ "@typescript-eslint/consistent-type-imports": "off",
2380
+ "@typescript-eslint/no-unused-vars": "off",
2381
+ "import-x/consistent-type-specifier-style": "off",
2382
+ "vue/define-emits-declaration": "off",
2383
+ "vue/html-button-has-type": "off",
2384
+ "vue/no-duplicate-attr-inheritance": "off",
2385
+ "vue/prefer-use-template-ref": "off",
2386
+ ...shadcnOptions.overridesRules
2387
+ }
2388
+ });
2389
+ }
2390
+ if (options.specialCaseConfigs) configs.push(...options.specialCaseConfigs);
2391
+ return configs;
2392
+ };
2393
+
2394
+ //#endregion
2395
+ //#region src/configs/gitignore.ts
2396
+ /**
2397
+ * Config for respect `.gitignore`
2398
+ *
2399
+ * @see {@link https://github.com/antfu/eslint-config-flat-gitignore}
2400
+ *
2401
+ * @param options - {@link ConfigGitIgnoreOptions}
2402
+ * @returns ESLint configs
2403
+ */
2404
+ const configGitIgnore = (options = {}) => {
2405
+ options.strict ??= false;
2406
+ return [{
2407
+ ...createGitIgnoreConfig(options),
2408
+ name: "ntnyq/gitignore"
2409
+ }];
2410
+ };
2411
+
2412
+ //#endregion
2413
+ //#region src/configs/javascript.ts
2414
+ const strictRules = {
2415
+ complexity: ["error", { max: 30 }],
2416
+ "max-depth": ["error", { max: 5 }],
2417
+ "max-lines": ["error", {
2418
+ max: 1e3,
2419
+ skipBlankLines: true,
2420
+ skipComments: true
2421
+ }],
2422
+ "max-lines-per-function": ["error", {
2423
+ max: 200,
2424
+ skipBlankLines: true,
2425
+ skipComments: true
2426
+ }],
2427
+ "max-nested-callbacks": ["error", { max: 10 }],
2428
+ "max-params": ["error", { max: 5 }]
2429
+ };
2430
+ /**
2431
+ * Config for JavaScript
2432
+ *
2433
+ * @see {@link https://github.com/eslint/eslint/tree/main/packages/js}
2434
+ *
2435
+ * @param options - {@link ConfigJavaScriptOptions}
2436
+ * @returns ESLint configs
2437
+ */
2438
+ const configJavaScript = (options = {}) => [{
2439
+ ...jsConfig.configs.recommended,
2440
+ name: "ntnyq/js/recommended"
2441
+ }, {
2442
+ name: "ntnyq/js/core",
2443
+ languageOptions: {
2444
+ sourceType: "module",
2445
+ globals: {
2446
+ ...globals.browser,
2447
+ ...globals.es2021,
2448
+ ...globals.node
2449
+ }
2450
+ },
2451
+ rules: {
2452
+ "consistent-return": "off",
2453
+ "no-return-assign": "off",
2454
+ "no-useless-escape": "off",
2455
+ "require-await": "off",
2456
+ "sort-imports": "off",
2457
+ "accessor-pairs": ["error", {
2458
+ enforceForClassMembers: true,
2459
+ setWithoutGet: true
2460
+ }],
2461
+ "array-callback-return": "error",
2462
+ "block-scoped-var": "error",
2463
+ camelcase: ["error", {
2464
+ allow: ["^UNSAFE_"],
2465
+ ignoreGlobals: true,
2466
+ properties: "never"
2467
+ }],
2468
+ "constructor-super": "error",
2469
+ curly: ["error", "all"],
2470
+ "default-case-last": "error",
2471
+ "dot-notation": ["error", { allowKeywords: true }],
2472
+ eqeqeq: ["error", "smart"],
2473
+ "new-cap": ["error", {
2474
+ capIsNew: false,
2475
+ newIsCap: true,
2476
+ properties: true
2477
+ }],
2478
+ "no-alert": "error",
2479
+ "no-array-constructor": "error",
2480
+ "no-async-promise-executor": "error",
2481
+ "no-caller": "error",
2482
+ "no-case-declarations": "error",
2483
+ "no-class-assign": "error",
2484
+ "no-compare-neg-zero": "error",
2485
+ "no-cond-assign": "error",
2486
+ "no-const-assign": "error",
2487
+ "no-constant-condition": ["error", { checkLoops: false }],
2488
+ "no-control-regex": "error",
2489
+ "no-debugger": "error",
2490
+ "no-delete-var": "error",
2491
+ "no-dupe-args": "error",
2492
+ "no-dupe-class-members": "error",
2493
+ "no-dupe-keys": "error",
2494
+ "no-duplicate-case": "error",
2495
+ "no-empty": ["error", { allowEmptyCatch: true }],
2496
+ "no-empty-character-class": "error",
2497
+ "no-empty-pattern": "error",
2498
+ "no-empty-static-block": "error",
2499
+ "no-eval": "error",
2500
+ "no-ex-assign": "error",
2501
+ "no-extend-native": "error",
2502
+ "no-extra-bind": "error",
2503
+ "no-extra-boolean-cast": "error",
2504
+ "no-fallthrough": "error",
2505
+ "no-func-assign": "error",
2506
+ "no-global-assign": "error",
2507
+ "no-implied-eval": "error",
2508
+ "no-import-assign": "error",
2509
+ "no-invalid-regexp": "error",
2510
+ "no-irregular-whitespace": "error",
2511
+ "no-iterator": "error",
2512
+ "no-labels": ["error", {
2513
+ allowLoop: false,
2514
+ allowSwitch: false
2515
+ }],
2516
+ "no-lone-blocks": "error",
2517
+ "no-loss-of-precision": "error",
2518
+ "no-misleading-character-class": "error",
2519
+ "no-multi-str": "error",
2520
+ "no-negated-condition": "error",
2521
+ "no-new": "error",
2522
+ "no-new-func": "error",
2523
+ "no-new-native-nonconstructor": "error",
2524
+ "no-new-wrappers": "error",
2525
+ "no-obj-calls": "error",
2526
+ "no-octal": "error",
2527
+ "no-octal-escape": "error",
2528
+ "no-proto": "error",
2529
+ "no-prototype-builtins": "error",
2530
+ "no-redeclare": ["error", { builtinGlobals: false }],
2531
+ "no-regex-spaces": "error",
2532
+ "no-self-assign": ["error", { props: true }],
2533
+ "no-self-compare": "error",
2534
+ "no-sequences": "error",
2535
+ "no-shadow-restricted-names": "error",
2536
+ "no-sparse-arrays": "error",
2537
+ "no-template-curly-in-string": "error",
2538
+ "no-this-before-super": "error",
2539
+ "no-throw-literal": "error",
2540
+ "no-undef": "error",
2541
+ "no-undef-init": "error",
2542
+ "no-unexpected-multiline": "error",
2543
+ "no-unmodified-loop-condition": "error",
2544
+ "no-unneeded-ternary": ["error", { defaultAssignment: false }],
2545
+ "no-unreachable": "error",
2546
+ "no-unreachable-loop": "error",
2547
+ "no-unsafe-finally": "error",
2548
+ "no-unsafe-negation": "error",
2549
+ "no-unused-expressions": ["error", {
2550
+ allowShortCircuit: true,
2551
+ allowTaggedTemplates: true,
2552
+ allowTernary: true
2553
+ }],
2554
+ "no-unused-vars": ["error", {
2555
+ args: "none",
2556
+ caughtErrors: "none",
2557
+ ignoreRestSiblings: true,
2558
+ vars: "all"
2559
+ }],
2560
+ "no-use-before-define": ["error", {
2561
+ allowNamedExports: false,
2562
+ classes: false,
2563
+ functions: false,
2564
+ variables: true
2565
+ }],
2566
+ "no-useless-backreference": "error",
2567
+ "no-useless-call": "error",
2568
+ "no-useless-catch": "error",
2569
+ "no-useless-computed-key": "error",
2570
+ "no-useless-constructor": "error",
2571
+ "no-useless-rename": "error",
2572
+ "no-useless-return": "error",
2573
+ "no-var": "error",
2574
+ "no-void": "error",
2575
+ "no-with": "error",
2576
+ "object-shorthand": [
2577
+ "error",
2578
+ "always",
2579
+ {
2580
+ avoidQuotes: true,
2581
+ ignoreConstructors: false
2582
+ }
2583
+ ],
2584
+ "one-var": ["error", "never"],
2585
+ "prefer-arrow-callback": ["error", {
2586
+ allowNamedFunctions: false,
2587
+ allowUnboundThis: true
2588
+ }],
2589
+ "prefer-const": ["error", {
2590
+ destructuring: "all",
2591
+ ignoreReadBeforeAssign: true
2592
+ }],
2593
+ "prefer-promise-reject-errors": "error",
2594
+ "prefer-regex-literals": ["error", { disallowRedundantWrapping: true }],
2595
+ "prefer-rest-params": "error",
2596
+ "prefer-spread": "error",
2597
+ "prefer-template": "error",
2598
+ "symbol-description": "error",
2599
+ "unicode-bom": ["error", "never"],
2600
+ "use-isnan": ["error", {
2601
+ enforceForIndexOf: true,
2602
+ enforceForSwitchCase: true
2603
+ }],
2604
+ "valid-typeof": ["error", { requireStringLiterals: true }],
2605
+ "vars-on-top": "error",
2606
+ yoda: ["error", "never"],
2607
+ ...options.strict ? strictRules : {},
2608
+ ...options.overrides
2609
+ }
2610
+ }];
2611
+ const configJSX = () => [{
2612
+ name: "ntnyq/jsx",
2613
+ files: [GLOB_JSX_ONLY],
2614
+ languageOptions: { parserOptions: { ecmaFeatures: { jsx: true } } }
2615
+ }];
2616
+
2617
+ //#endregion
2618
+ //#region src/configs/typescript.ts
2619
+ /**
2620
+ * @see {@link https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/src/configs/recommended-type-checked.ts}
2621
+ */
2622
+ const typeAwareRules = {
2623
+ "@typescript-eslint/strict-boolean-expressions": "off",
2624
+ "dot-notation": "off",
2625
+ "no-implied-eval": "off",
2626
+ "no-throw-literal": "off",
2627
+ "require-await": "off",
2628
+ "@typescript-eslint/await-thenable": "error",
2629
+ "@typescript-eslint/dot-notation": ["error", { allowKeywords: true }],
2630
+ "@typescript-eslint/no-duplicate-type-constituents": "error",
2631
+ "@typescript-eslint/no-floating-promises": "error",
2632
+ "@typescript-eslint/no-for-in-array": "error",
2633
+ "@typescript-eslint/no-implied-eval": "error",
2634
+ "@typescript-eslint/no-misused-promises": "error",
2635
+ "@typescript-eslint/no-misused-spread": "error",
2636
+ "@typescript-eslint/no-redundant-type-constituents": "error",
2637
+ "@typescript-eslint/no-unnecessary-type-assertion": "error",
2638
+ "@typescript-eslint/no-unsafe-argument": "error",
2639
+ "@typescript-eslint/no-unsafe-assignment": "error",
2640
+ "@typescript-eslint/no-unsafe-call": "error",
2641
+ "@typescript-eslint/no-unsafe-member-access": "error",
2642
+ "@typescript-eslint/no-unsafe-return": "error",
2643
+ "@typescript-eslint/only-throw-error": "error",
2644
+ "@typescript-eslint/promise-function-async": "error",
2645
+ "@typescript-eslint/require-await": "error",
2646
+ "@typescript-eslint/restrict-plus-operands": "error",
2647
+ "@typescript-eslint/restrict-template-expressions": "error",
2648
+ "@typescript-eslint/return-await": ["error", "in-try-catch"],
2649
+ "@typescript-eslint/switch-exhaustiveness-check": "error",
2650
+ "@typescript-eslint/triple-slash-reference": "error",
2651
+ "@typescript-eslint/unbound-method": "error"
2652
+ };
2653
+ /**
2654
+ * typescript-eslint recommended rules
2655
+ */
2656
+ const recommendedRules = configsTypeScript.recommended.reduce((rules, config) => {
2657
+ return {
2658
+ ...rules,
2659
+ ...config.rules || {}
2660
+ };
2661
+ }, {});
2662
+ /**
2663
+ * Config for TypeScript files
2664
+ *
2665
+ * @see {@link https://github.com/typescript-eslint/typescript-eslint}
2666
+ *
2667
+ * @param options - {@link ConfigTypeScriptOptions}
2668
+ * @returns ESLint configs
2669
+ */
2670
+ const configTypeScript = (options = {}) => {
2671
+ /**
2672
+ * @see {@link https://typescript-eslint.io/troubleshooting/typed-linting}
2673
+ */
2674
+ const enableTypeAwareLint = !!options?.tsconfigPath;
2675
+ const { allowDefaultProject = [], extraFileExtensions = [], filesTypeAware = [GLOB_TS, GLOB_TSX], ignoresTypeAware = [GLOB_ASTRO, `${GLOB_MARKDOWN}/**`], overridesTypeAwareRules = {}, parserOptions = {} } = options;
2676
+ const files = options.files ?? [
2677
+ GLOB_TS,
2678
+ GLOB_TSX,
2679
+ ...extraFileExtensions.map((ext) => `**/*${ext}`)
2680
+ ];
2681
+ function createParserConfig(enableTypeAware = false, files$1 = [], ignores = []) {
2682
+ const typescriptParserOptions = {
2683
+ extraFileExtensions,
2684
+ sourceType: "module",
2685
+ ...enableTypeAware ? {
2686
+ tsconfigRootDir: process.cwd(),
2687
+ projectService: {
2688
+ allowDefaultProject: ["./*.js", ...allowDefaultProject],
2689
+ defaultProject: options.tsconfigPath
2690
+ }
2691
+ } : {},
2692
+ ...parserOptions
2693
+ };
2694
+ const parserConfig = {
2695
+ name: `ntnyq/ts/${enableTypeAware ? "parser-type-aware" : "parser"}`,
2696
+ files: files$1,
2697
+ ignores: [...ignores],
2698
+ languageOptions: {
2699
+ parser: parserTypeScript,
2700
+ parserOptions: typescriptParserOptions
2701
+ }
2702
+ };
2703
+ return parserConfig;
2704
+ }
2705
+ return [
2706
+ {
2707
+ name: "ntnyq/ts/setup",
2708
+ plugins: {
2709
+ "@typescript-eslint": pluginTypeScript,
2710
+ antfu: pluginAntfu
2711
+ }
2712
+ },
2713
+ ...enableTypeAwareLint ? [createParserConfig(false, files), createParserConfig(true, filesTypeAware, ignoresTypeAware)] : [createParserConfig(false, files)],
2714
+ {
2715
+ name: "ntnyq/ts/rules",
2716
+ files,
2717
+ rules: {
2718
+ ...recommendedRules,
2719
+ "@typescript-eslint/consistent-indexed-object-style": "off",
2720
+ "@typescript-eslint/explicit-function-return-type": "off",
2721
+ "@typescript-eslint/explicit-member-accessibility": "off",
2722
+ "@typescript-eslint/explicit-module-boundary-types": "off",
2723
+ "@typescript-eslint/naming-convention": "off",
2724
+ "@typescript-eslint/no-empty-function": "off",
2725
+ "@typescript-eslint/no-explicit-any": "off",
2726
+ "@typescript-eslint/no-namespace": "off",
2727
+ "@typescript-eslint/no-non-null-assertion": "off",
2728
+ "@typescript-eslint/triple-slash-reference": "off",
2729
+ "default-param-last": "off",
2730
+ "no-redeclare": "off",
2731
+ "no-unused-vars": "off",
2732
+ "no-use-before-define": "off",
2733
+ "no-useless-constructor": "off",
2734
+ "@typescript-eslint/prefer-as-const": "warn",
2735
+ "@typescript-eslint/ban-ts-comment": ["error", {
2736
+ minimumDescriptionLength: 1,
2737
+ "ts-check": false,
2738
+ "ts-expect-error": "allow-with-description",
2739
+ "ts-ignore": "allow-with-description",
2740
+ "ts-nocheck": "allow-with-description"
2741
+ }],
2742
+ "@typescript-eslint/ban-tslint-comment": "error",
2743
+ "@typescript-eslint/consistent-generic-constructors": ["error", "constructor"],
2744
+ "@typescript-eslint/consistent-type-assertions": ["error", {
2745
+ assertionStyle: "as",
2746
+ objectLiteralTypeAssertions: "allow-as-parameter"
2747
+ }],
2748
+ "@typescript-eslint/consistent-type-imports": ["error", {
2749
+ disallowTypeAnnotations: false,
2750
+ fixStyle: "separate-type-imports",
2751
+ prefer: "type-imports"
2752
+ }],
2753
+ "@typescript-eslint/default-param-last": "error",
2754
+ "@typescript-eslint/no-empty-object-type": ["error", {
2755
+ allowInterfaces: "always",
2756
+ allowObjectTypes: "always"
2757
+ }],
2758
+ "@typescript-eslint/no-redeclare": ["error", {
2759
+ builtinGlobals: false,
2760
+ ignoreDeclarationMerge: true
2761
+ }],
2762
+ "@typescript-eslint/no-unused-expressions": ["error", {
2763
+ allowShortCircuit: true,
2764
+ allowTaggedTemplates: true,
2765
+ allowTernary: true
2766
+ }],
2767
+ "@typescript-eslint/no-unused-vars": ["error", {
2768
+ args: "after-used",
2769
+ argsIgnorePattern: "^_",
2770
+ caughtErrors: "all",
2771
+ caughtErrorsIgnorePattern: "^_",
2772
+ destructuredArrayIgnorePattern: "^_",
2773
+ ignoreRestSiblings: true,
2774
+ varsIgnorePattern: "^_"
2775
+ }],
2776
+ "@typescript-eslint/no-use-before-define": ["error", {
2777
+ allowNamedExports: false,
2778
+ classes: false,
2779
+ enums: true,
2780
+ functions: false,
2781
+ ignoreTypeReferences: false,
2782
+ typedefs: false,
2783
+ variables: true
2784
+ }],
2785
+ "@typescript-eslint/no-useless-constructor": "error",
2786
+ ...options.overrides
2787
+ }
2788
+ },
2789
+ ...enableTypeAwareLint ? [{
2790
+ name: "ntnyq/ts/rules/type-aware",
2791
+ files: [...filesTypeAware],
2792
+ ignores: [...ignoresTypeAware],
2793
+ rules: {
2794
+ ...typeAwareRules,
2795
+ ...overridesTypeAwareRules
2796
+ }
2797
+ }] : [],
2798
+ {
2799
+ name: "ntnyq/ts/types",
2800
+ files: [...GLOB_TYPES],
2801
+ rules: {
2802
+ "@typescript-eslint/no-use-before-define": "off",
2803
+ "import-x/newline-after-import": "off",
2804
+ "import-x/no-duplicates": "off",
2805
+ "no-restricted-syntax": "off",
2806
+ "no-use-before-define": "off",
2807
+ "no-var": "off",
2808
+ "vars-on-top": "off"
2809
+ }
2810
+ }
2811
+ ];
2812
+ };
2813
+
2814
+ //#endregion
2815
+ //#region src/configs/eslintPlugin.ts
2816
+ /**
2817
+ * Config for eslint plugin
2818
+ *
2819
+ * @see {@link https://github.com/eslint-community/eslint-plugin-eslint-plugin}
2820
+ *
2821
+ * @param options - {@link ConfigESLintPluginOptions}
2822
+ * @returns ESLint configs
2823
+ */
2824
+ const configESLintPlugin = async (options = {}) => {
2825
+ await ensurePackages(["eslint-plugin-eslint-plugin"]);
2826
+ const pluginESLintPlugin = await interopDefault(import("eslint-plugin-eslint-plugin"));
2827
+ return [{
2828
+ ...pluginESLintPlugin.configs.all,
2829
+ name: "ntnyq/eslint-plugin",
2830
+ rules: {
2831
+ ...pluginESLintPlugin.configs.all.rules,
2832
+ "eslint-plugin/require-meta-docs-url": "off",
2833
+ ...options.overrides
2834
+ }
2835
+ }];
2836
+ };
2837
+
2838
+ //#endregion
2839
+ //#region src/configs/githubAction.ts
2840
+ /**
2841
+ * Config for github action files
2842
+ *
2843
+ * @see {@link https://github.com/ntnyq/eslint-plugin-github-action}
2844
+ *
2845
+ * @param options - {@link ConfigGitHubActionOptions}
2846
+ * @returns ESLint configs
2847
+ */
2848
+ const configGitHubAction = (options = {}) => {
2849
+ const { files = [GLOB_GITHUB_ACTION] } = options;
2850
+ return [{
2851
+ name: "ntnyq/github-action",
2852
+ files,
2853
+ plugins: { "github-action": pluginGitHubAction },
2854
+ languageOptions: { parser: parserYaml },
2855
+ rules: {
2856
+ "github-action/no-invalid-key": "error",
2857
+ "github-action/prefer-file-extension": "error",
2858
+ "github-action/require-action-name": "error",
2859
+ "github-action/valid-timeout-minutes": "error",
2860
+ "github-action/valid-trigger-events": "error",
2861
+ ...options.overrides
2862
+ }
2863
+ }];
2864
+ };
2865
+
2866
+ //#endregion
2867
+ //#region src/configs/perfectionist.ts
2868
+ /**
2869
+ * Config for sorting imports, exports, objects and etc
2870
+ *
2871
+ * @see {@link https://github.com/azat-io/eslint-plugin-perfectionist}
2872
+ *
2873
+ * @param options - {@link ConfigPerfectionistOptions}
2874
+ * @returns ESLint configs
2875
+ */
2876
+ const configPerfectionist = (options = {}) => {
2877
+ const { filesEnums = [`**/enums/${GLOB_SRC}`, `**/enums.${GLOB_SRC_EXT}`], filesTypes = [...GLOB_TYPES], partitionByComment = PERFECTIONIST.partialRuleOptions.partitionByComment, sortConstants: enableSortConstants = true, sortEnums: enableSortEnums = true, sortTypes: enableSortTypes = true, filesConstants = [`**/constants/${GLOB_SRC}`, `**/constants.${GLOB_SRC_EXT}`] } = options;
2878
+ const sharedOptionsWithNewlinesBetween = {
2879
+ newlinesBetween: "ignore",
2880
+ partitionByComment
2881
+ };
2882
+ const commonRules = {
2883
+ "perfectionist/sort-exports": ["error", {
2884
+ ...sharedOptionsWithNewlinesBetween,
2885
+ groups: PERFECTIONIST.sortExportsGroups,
2886
+ type: "line-length"
2887
+ }],
2888
+ "perfectionist/sort-imports": ["error", {
2889
+ ...sharedOptionsWithNewlinesBetween,
2890
+ groups: PERFECTIONIST.sortImportsTypes,
2891
+ internalPattern: [
2892
+ "^~/.+",
2893
+ "^@/.+",
2894
+ "^#.+"
2895
+ ]
2896
+ }],
2897
+ "perfectionist/sort-named-exports": ["error", {
2898
+ ...sharedOptionsWithNewlinesBetween,
2899
+ groups: PERFECTIONIST.sortNamedExportsGroups,
2900
+ ignoreAlias: false
2901
+ }],
2902
+ "perfectionist/sort-named-imports": ["error", {
2903
+ ...sharedOptionsWithNewlinesBetween,
2904
+ groups: PERFECTIONIST.sortNamedImportsGroups,
2905
+ ignoreAlias: false
2906
+ }]
2907
+ };
2908
+ const sharedRules$1 = { "perfectionist/sort-enums": ["error", { ...sharedOptionsWithNewlinesBetween }] };
2909
+ const sortEnumsRules = { "perfectionist/sort-modules": ["error", { ...sharedOptionsWithNewlinesBetween }] };
2910
+ const sortTypesRules = {
2911
+ "perfectionist/sort-heritage-clauses": "error",
2912
+ "perfectionist/sort-interfaces": ["error", {
2913
+ ...sharedOptionsWithNewlinesBetween,
2914
+ groups: PERFECTIONIST.sortInterfacesOrObjectTypesGroups
2915
+ }],
2916
+ "perfectionist/sort-intersection-types": ["error", {
2917
+ ...sharedOptionsWithNewlinesBetween,
2918
+ groups: PERFECTIONIST.sortIntersectionTypesOrUnionTypesGroups
2919
+ }],
2920
+ "perfectionist/sort-object-types": ["error", {
2921
+ ...sharedOptionsWithNewlinesBetween,
2922
+ groups: PERFECTIONIST.sortInterfacesOrObjectTypesGroups
2923
+ }],
2924
+ "perfectionist/sort-union-types": ["error", {
2925
+ ...sharedOptionsWithNewlinesBetween,
2926
+ groups: PERFECTIONIST.sortIntersectionTypesOrUnionTypesGroups
2927
+ }]
2928
+ };
2929
+ const sortConstantsRules = {
2930
+ "perfectionist/sort-maps": ["error", { ...sharedOptionsWithNewlinesBetween }],
2931
+ "perfectionist/sort-objects": ["error", {
2932
+ ...sharedOptionsWithNewlinesBetween,
2933
+ groups: PERFECTIONIST.sortObjectsGroups
2934
+ }],
2935
+ "perfectionist/sort-sets": ["error", { ...sharedOptionsWithNewlinesBetween }]
2936
+ };
2937
+ const extraRules = {
2938
+ "perfectionist/sort-array-includes": ["error", {
2939
+ ...sharedOptionsWithNewlinesBetween,
2940
+ groups: ["literal", "spread"]
2941
+ }],
2942
+ "perfectionist/sort-classes": ["error", {
2943
+ ...sharedOptionsWithNewlinesBetween,
2944
+ groups: PERFECTIONIST.sortClassesGroups
2945
+ }],
2946
+ "perfectionist/sort-decorators": ["error", { partitionByComment }],
2947
+ "perfectionist/sort-jsx-props": ["error", { groups: [
2948
+ "shorthand",
2949
+ "multiline",
2950
+ "unknown"
2951
+ ] }],
2952
+ "perfectionist/sort-switch-case": "error",
2953
+ "perfectionist/sort-variable-declarations": ["error", { partitionByComment }]
2954
+ };
2955
+ const configs = [{
2956
+ name: options.all ? "ntnyq/perfectionist/all" : "ntnyq/perfectionist/common",
2957
+ plugins: { perfectionist: pluginPerfectionist },
2958
+ settings: { perfectionist: PERFECTIONIST.pluginSettings },
2959
+ rules: {
2960
+ ...commonRules,
2961
+ ...options.all ? {
2962
+ ...sharedRules$1,
2963
+ ...sortEnumsRules,
2964
+ ...sortTypesRules,
2965
+ ...sortConstantsRules,
2966
+ ...extraRules
2967
+ } : {},
2968
+ ...options.overrides
2969
+ }
2970
+ }];
2971
+ if (options.all) return configs;
2972
+ if (enableSortEnums) configs.push({
2973
+ name: "ntnyq/perfectionist/enums",
2974
+ files: filesEnums,
2975
+ plugins: { perfectionist: pluginPerfectionist },
2976
+ settings: { perfectionist: PERFECTIONIST.pluginSettings },
2977
+ rules: {
2978
+ ...sharedRules$1,
2979
+ ...sortEnumsRules,
2980
+ ...options.overridesEnumsRules
2981
+ }
2982
+ });
2983
+ if (enableSortTypes) configs.push({
2984
+ name: "ntnyq/perfectionist/types",
2985
+ files: filesTypes,
2986
+ plugins: { perfectionist: pluginPerfectionist },
2987
+ settings: { perfectionist: PERFECTIONIST.pluginSettings },
2988
+ rules: {
2989
+ ...sharedRules$1,
2990
+ ...sortTypesRules,
2991
+ ...options.overridesTypesRules
2992
+ }
2993
+ });
2994
+ if (enableSortConstants) configs.push({
2995
+ name: "ntnyq/perfectionist/constants",
2996
+ files: filesConstants,
2997
+ plugins: { perfectionist: pluginPerfectionist },
2998
+ settings: { perfectionist: PERFECTIONIST.pluginSettings },
2999
+ rules: {
3000
+ ...sharedRules$1,
3001
+ ...sortConstantsRules,
3002
+ ...options.overridesConstantsRules
3003
+ }
3004
+ });
3005
+ return configs;
3006
+ };
3007
+
3008
+ //#endregion
3009
+ //#region src/configs/unusedImports.ts
3010
+ /**
3011
+ * Config for remove unused imports
3012
+ *
3013
+ * @see {@link https://github.com/sweepline/eslint-plugin-unused-imports}
3014
+ *
3015
+ * @param options - {@link ConfigUnusedImportsOptions}
3016
+ * @returns ESLint configs
3017
+ */
3018
+ const configUnusedImports = async (options = {}) => {
3019
+ await ensurePackages(["eslint-plugin-unused-imports"]);
3020
+ const pluginUnusedImports = await interopDefault(import("eslint-plugin-unused-imports"));
3021
+ return [{
3022
+ name: "ntnyq/unused-imports",
3023
+ plugins: { "unused-imports": pluginUnusedImports },
3024
+ rules: {
3025
+ "@typescript-eslint/no-unused-vars": "off",
3026
+ "unused-imports/no-unused-imports": "error",
3027
+ "unused-imports/no-unused-vars": ["error", {
3028
+ args: "after-used",
3029
+ argsIgnorePattern: "^_",
3030
+ caughtErrors: "all",
3031
+ caughtErrorsIgnorePattern: "^_",
3032
+ destructuredArrayIgnorePattern: "^_",
3033
+ ignoreRestSiblings: true,
3034
+ vars: "all",
3035
+ varsIgnorePattern: "^_"
3036
+ }],
3037
+ ...options.overrides
3038
+ }
3039
+ }];
3040
+ };
3041
+
3042
+ //#endregion
3043
+ //#region src/configs/eslintComments.ts
3044
+ /**
3045
+ * Config for eslint comments
3046
+ *
3047
+ * @see {@link https://github.com/eslint-community/eslint-plugin-eslint-comments}
3048
+ *
3049
+ * @param options - {@link ConfigESLintCommentsOptions}
3050
+ * @returns ESLint configs
3051
+ */
3052
+ const configESLintComments = (options = {}) => [{
3053
+ name: "ntnyq/eslint-comments",
3054
+ plugins: { "@eslint-community/eslint-comments": pluginComments },
3055
+ rules: {
3056
+ ...pluginComments.configs.recommended.rules,
3057
+ "@eslint-community/eslint-comments/disable-enable-pair": ["error", { allowWholeFile: true }],
3058
+ ...options.overrides
3059
+ }
3060
+ }];
3061
+
3062
+ //#endregion
3063
+ //#region src/core.ts
3064
+ /**
3065
+ * Config factory
3066
+ */
3067
+ function defineESLintConfig(options = {}, ...userConfigs) {
3068
+ const { shareable = {}, vue: enableVue = hasVue(), pinia: enablePinia = hasPinia(), test: enableTest = hasVitest(), unocss: enableUnoCSS = hasUnoCSS(), typescript: enableTypeScript = hasTypeScript(), yml: enableYML = true, sort: enableSort = true, toml: enableTOML = true, jsonc: enableJSONC = true, antfu: enableAntfu = true, ntnyq: enableNtnyq = true, depend: enableDepend = true, regexp: enableRegexp = true, unicorn: enableUnicorn = true, deMorgan: enableDeMorgan = true, prettier: enablePrettier = true, markdown: enableMarkdown = true, gitignore: enableGitIgnore = true, jsdoc: enableJsdoc = true, importX: enableImportX = true, specials: enableSpecials = true, githubAction: enableGitHubAction = true, perfectionist: enablePerfectionist = true, pnpm: enablePnpm = false, svgo: enableSVGO = false, html: enableHTML = false, astro: enableAstro = false, svelte: enableSvelte = false, eslintPlugin: enableESLintPlugin = false } = options;
3069
+ const configs = [];
3070
+ const { extraFileExtensions = [] } = shareable;
3071
+ if (enableVue) extraFileExtensions.push(".vue");
3072
+ if (enableAstro) extraFileExtensions.push(".astro");
3073
+ if (enableSvelte) extraFileExtensions.push(".svelte");
3074
+ if (enableGitIgnore) configs.push(configGitIgnore(resolveSubOptions(options, "gitignore")));
3075
+ configs.push(configIgnores(options.ignores), configJSX(), configNode({ overrides: getOverrides(options, "node") }), configCommand(resolveSubOptions(options, "command")), configESLintComments({ overrides: getOverrides(options, "eslintComments") }), configJavaScript({
3076
+ ...resolveSubOptions(options, "javascript"),
3077
+ overrides: getOverrides(options, "javascript")
3078
+ }));
3079
+ if (enableImportX) configs.push(configImportX({
3080
+ typescript: !!enableTypeScript,
3081
+ ...resolveSubOptions(options, "importX"),
3082
+ overrides: getOverrides(options, "importX")
3083
+ }));
3084
+ if (enableJsdoc) configs.push(configJsdoc({
3085
+ typescript: !!enableTypeScript,
3086
+ overrides: getOverrides(options, "jsdoc"),
3087
+ ...resolveSubOptions(options, "jsdoc")
3088
+ }));
3089
+ if (enablePerfectionist) configs.push(configPerfectionist({
3090
+ ...resolveSubOptions(options, "perfectionist"),
3091
+ overrides: getOverrides(options, "perfectionist")
3092
+ }));
3093
+ if (enableUnicorn) configs.push(configUnicorn({ overrides: getOverrides(options, "unicorn") }));
3094
+ if (enablePinia) configs.push(configPinia({
3095
+ ...resolveSubOptions(options, "pinia"),
3096
+ overrides: getOverrides(options, "pinia")
3097
+ }));
3098
+ if (enableDeMorgan) configs.push(configDeMorgan({ overrides: getOverrides(options, "deMorgan") }));
3099
+ if (enableRegexp) configs.push(configRegexp({
3100
+ ...resolveSubOptions(options, "regexp"),
3101
+ overrides: getOverrides(options, "regexp")
3102
+ }));
3103
+ if (enableTypeScript) configs.push(configTypeScript({
3104
+ ...resolveSubOptions(options, "typescript"),
3105
+ overrides: getOverrides(options, "typescript"),
3106
+ extraFileExtensions
3107
+ }));
3108
+ if (enableVue) configs.push(configVue({
3109
+ ...resolveSubOptions(options, "vue"),
3110
+ typescript: !!enableTypeScript,
3111
+ overrides: getOverrides(options, "vue"),
3112
+ extraFileExtensions
3113
+ }));
3114
+ if (enableYML) configs.push(configYml({
3115
+ prettier: !!enablePrettier,
3116
+ ...resolveSubOptions(options, "yml"),
3117
+ overrides: getOverrides(options, "yml")
3118
+ }));
3119
+ if (enableTOML) configs.push(configToml({
3120
+ ...resolveSubOptions(options, "toml"),
3121
+ overrides: getOverrides(options, "toml")
3122
+ }));
3123
+ if (enableJSONC) configs.push(configJsonc({
3124
+ prettier: !!enablePrettier,
3125
+ ...resolveSubOptions(options, "jsonc"),
3126
+ overrides: getOverrides(options, "jsonc")
3127
+ }));
3128
+ if (enableAstro) configs.push(configAstro({
3129
+ ...resolveSubOptions(options, "astro"),
3130
+ typescript: !!enableTypeScript,
3131
+ overrides: getOverrides(options, "astro"),
3132
+ extraFileExtensions
3133
+ }));
3134
+ if (enableSvelte) configs.push(configSvelte({
3135
+ ...resolveSubOptions(options, "svelte"),
3136
+ typescript: !!enableTypeScript,
3137
+ overrides: getOverrides(options, "svelte"),
3138
+ extraFileExtensions
3139
+ }));
3140
+ if (enableSort) configs.push(configSort(resolveSubOptions(options, "sort")));
3141
+ if (enableTest) configs.push(configTest({
3142
+ ...resolveSubOptions(options, "test"),
3143
+ overrides: getOverrides(options, "test")
3144
+ }));
3145
+ if (enableUnoCSS) configs.push(configUnoCSS({ overrides: getOverrides(options, "unocss") }));
3146
+ if (enableMarkdown) configs.push(configMarkdown({
3147
+ ...resolveSubOptions(options, "markdown"),
3148
+ overrides: getOverrides(options, "markdown"),
3149
+ extraFileExtensions
3150
+ }));
3151
+ if (enableAntfu) configs.push(configAntfu({ overrides: getOverrides(options, "antfu") }));
3152
+ if (enableDepend) configs.push(configDepend({
3153
+ ...resolveSubOptions(options, "depend"),
3154
+ overrides: getOverrides(options, "depend")
3155
+ }));
3156
+ if (enableNtnyq) configs.push(configNtnyq({ overrides: getOverrides(options, "ntnyq") }));
3157
+ if (enableGitHubAction) configs.push(configGitHubAction({ overrides: getOverrides(options, "githubAction") }));
3158
+ if (enableESLintPlugin) configs.push(configESLintPlugin({ overrides: getOverrides(options, "eslintPlugin") }));
3159
+ if (enablePnpm) configs.push(configPnpm(resolveSubOptions(options, "pnpm")));
3160
+ if (enableSVGO) configs.push(configSVGO(resolveSubOptions(options, "svgo")));
3161
+ if (enableHTML) configs.push(configHtml({
3162
+ ...resolveSubOptions(options, "html"),
3163
+ overrides: getOverrides(options, "html")
3164
+ }));
3165
+ if (enableSpecials) configs.push(configSpecials(resolveSubOptions(options, "specials")));
3166
+ const prettierConfigs = enablePrettier ? configPrettier({
3167
+ ...resolveSubOptions(options, "prettier"),
3168
+ overrides: getOverrides(options, "prettier")
3169
+ }) : [];
3170
+ const composer = new FlatConfigComposer(...configs, ...userConfigs, ...prettierConfigs);
3171
+ return composer;
3172
+ }
3173
+
3174
+ //#endregion
3175
+ export { GLOB_ALL_SRC, GLOB_ASTRO, GLOB_ASTRO_TS, GLOB_CSS, GLOB_DIST, GLOB_DTS, GLOB_EXCLUDE, GLOB_GITHUB_ACTION, GLOB_HTML, GLOB_JS, GLOB_JSON, GLOB_JSON5, GLOB_JSONC, GLOB_JSON_SCHEMA, GLOB_JSX, GLOB_JSX_ONLY, GLOB_LESS, GLOB_LOCKFILE, GLOB_MARKDOWN, GLOB_MARKDOWN_CODE, GLOB_MARKDOWN_NESTED, GLOB_NODE_MODULES, GLOB_PACKAGE_JSON, GLOB_PINIA_STORE, GLOB_PNPM_WORKSPACE_YAML, GLOB_POSTCSS, GLOB_SCSS, GLOB_SRC, GLOB_SRC_EXT, GLOB_STYLE, GLOB_SVELTE, GLOB_SVG, GLOB_TEST, GLOB_TOML, GLOB_TS, GLOB_TSCONFIG_JSON, GLOB_TSX, GLOB_TSX_ONLY, GLOB_TYPES, GLOB_TYPE_TEST, GLOB_VUE, GLOB_YAML, PERFECTIONIST, PRETTIER_DEFAULT_OPTIONS, combineConfigs, configAntfu, configAstro, configCommand, configDeMorgan, configDepend, configESLintComments, configESLintPlugin, configFormat, configGitHubAction, configGitIgnore, configHtml, configIgnores, configImportX, configJSX, configJavaScript, configJsdoc, configJsonc, configMarkdown, configNode, configNtnyq, configPerfectionist, configPinia, configPnpm, configPrettier, configRegexp, configSVGO, configSort, configSpecials, configSvelte, configTest, configToml, configTypeScript, configUnicorn, configUnoCSS, configUnusedImports, configVue, configYml, configsTypeScript, defineESLintConfig, ensurePackages, getOverrides, hasPinia, hasShadcnVue, hasTypeScript, hasUnoCSS, hasVitest, hasVue, interopDefault, isInGitHooksOrRunBySpecifyPackages, mergePrettierOptions, mergeProcessors, parserJsonc, parserPlain, parserToml, parserTypeScript, parserVue, parserYaml, pluginAntfu, pluginComments, pluginDeMorgan, pluginDepend, pluginGitHubAction, pluginImportX, pluginJsdoc, pluginJsonc, pluginMarkdown, pluginNoOnlyTests, pluginNode, pluginNtnyq, pluginPerfectionist, pluginPinia, pluginPrettier, pluginRegexp, pluginSvgo, pluginToml, pluginTypeScript, pluginUnicorn, pluginUnoCSS, pluginVitest, pluginVue, pluginYml, processorPassThrough, processorVueBlocks, resolveSubOptions };