@ntnyq/eslint-config 4.3.0 → 5.0.0-beta.2

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