@whoj/eslint-config 2.5.0 → 7.4.30

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.mjs ADDED
@@ -0,0 +1,2654 @@
1
+ import process from "node:process";
2
+ import fs from "node:fs/promises";
3
+ import { fileURLToPath } from "node:url";
4
+ import fs$1 from "node:fs";
5
+ import path from "node:path";
6
+ import { isPackageExists } from "local-pkg";
7
+ import { FlatConfigComposer } from "eslint-flat-config-utils";
8
+ import { configs } from "eslint-plugin-regexp";
9
+ import pluginNode from "eslint-plugin-n";
10
+ import pluginAntfu from "eslint-plugin-antfu";
11
+ import pluginUnicorn from "eslint-plugin-unicorn";
12
+ import pluginImportLite from "eslint-plugin-import-lite";
13
+ import pluginPerfectionist from "eslint-plugin-perfectionist";
14
+ import pluginUnusedImports from "eslint-plugin-unused-imports";
15
+ import pluginComments from "@eslint-community/eslint-plugin-eslint-comments";
16
+ import { mergeProcessors, processorPassThrough } from "eslint-merge-processors";
17
+ import createCommand from "eslint-plugin-command/config";
18
+ import globals from "globals";
19
+
20
+ //#region node_modules/.pnpm/find-up-simple@1.0.1/node_modules/find-up-simple/index.js
21
+ const toPath = (urlOrPath) => urlOrPath instanceof URL ? fileURLToPath(urlOrPath) : urlOrPath;
22
+ async function findUp(name, { cwd = process.cwd(), type = "file", stopAt } = {}) {
23
+ let directory = path.resolve(toPath(cwd) ?? "");
24
+ const { root } = path.parse(directory);
25
+ stopAt = path.resolve(directory, toPath(stopAt ?? root));
26
+ const isAbsoluteName = path.isAbsolute(name);
27
+ while (directory) {
28
+ const filePath = isAbsoluteName ? name : path.join(directory, name);
29
+ try {
30
+ const stats = await fs.stat(filePath);
31
+ if (type === "file" && stats.isFile() || type === "directory" && stats.isDirectory()) return filePath;
32
+ } catch {}
33
+ if (directory === stopAt || directory === root) break;
34
+ directory = path.dirname(directory);
35
+ }
36
+ }
37
+ function findUpSync(name, { cwd = process.cwd(), type = "file", stopAt } = {}) {
38
+ let directory = path.resolve(toPath(cwd) ?? "");
39
+ const { root } = path.parse(directory);
40
+ stopAt = path.resolve(directory, toPath(stopAt) ?? root);
41
+ const isAbsoluteName = path.isAbsolute(name);
42
+ while (directory) {
43
+ const filePath = isAbsoluteName ? name : path.join(directory, name);
44
+ try {
45
+ const stats = fs$1.statSync(filePath, { throwIfNoEntry: false });
46
+ if (type === "file" && stats?.isFile() || type === "directory" && stats?.isDirectory()) return filePath;
47
+ } catch {}
48
+ if (directory === stopAt || directory === root) break;
49
+ directory = path.dirname(directory);
50
+ }
51
+ }
52
+
53
+ //#endregion
54
+ //#region src/configs/regexp.ts
55
+ async function regexp(options = {}) {
56
+ const config = configs["flat/recommended"];
57
+ const rules = { ...config.rules };
58
+ if (options.level === "warn") {
59
+ for (const key in rules) if (rules[key] === "error") rules[key] = "warn";
60
+ }
61
+ return [{
62
+ ...config,
63
+ name: "whoj/regexp/rules",
64
+ rules: {
65
+ ...rules,
66
+ ...options.overrides
67
+ }
68
+ }];
69
+ }
70
+
71
+ //#endregion
72
+ //#region src/utils.ts
73
+ const scopeUrl = fileURLToPath(new URL(".", import.meta.url));
74
+ const isCwdInScope = isPackageExists("@whoj/eslint-config");
75
+ const parserPlain = {
76
+ meta: { name: "parser-plain" },
77
+ parseForESLint: (code) => ({
78
+ scopeManager: null,
79
+ services: { isPlain: true },
80
+ visitorKeys: { Program: [] },
81
+ ast: {
82
+ body: [],
83
+ tokens: [],
84
+ comments: [],
85
+ type: "Program",
86
+ range: [0, code.length],
87
+ loc: {
88
+ start: 0,
89
+ end: code.length
90
+ }
91
+ }
92
+ })
93
+ };
94
+ /**
95
+ * Combine array and non-array configs into a single array.
96
+ */
97
+ async function combine(...configs$1) {
98
+ return (await Promise.all(configs$1)).flat();
99
+ }
100
+ /**
101
+ * Rename plugin prefixes in a rule object.
102
+ * Accepts a map of prefixes to rename.
103
+ *
104
+ * @example
105
+ * ```ts
106
+ * import { renameRules } from '@whoj/eslint-config'
107
+ *
108
+ * export default [{
109
+ * rules: renameRules(
110
+ * {
111
+ * '@typescript-eslint/indent': 'error'
112
+ * },
113
+ * { '@typescript-eslint': 'ts' }
114
+ * )
115
+ * }]
116
+ * ```
117
+ */
118
+ function renameRules(rules, map) {
119
+ return Object.fromEntries(Object.entries(rules).map(([key, value]) => {
120
+ for (const [from, to] of Object.entries(map)) if (key.startsWith(`${from}/`)) return [to + key.slice(from.length), value];
121
+ return [key, value];
122
+ }));
123
+ }
124
+ /**
125
+ * Rename plugin names a flat configs array
126
+ *
127
+ * @example
128
+ * ```ts
129
+ * import { renamePluginInConfigs } from '@whoj/eslint-config'
130
+ * import someConfigs from './some-configs'
131
+ *
132
+ * export default renamePluginInConfigs(someConfigs, {
133
+ * '@typescript-eslint': 'ts',
134
+ * '@stylistic': 'style',
135
+ * })
136
+ * ```
137
+ */
138
+ function renamePluginInConfigs(configs$1, map) {
139
+ return configs$1.map((i) => {
140
+ const clone = { ...i };
141
+ if (clone.rules) clone.rules = renameRules(clone.rules, map);
142
+ if (clone.plugins) clone.plugins = Object.fromEntries(Object.entries(clone.plugins).map(([key, value]) => {
143
+ if (key in map) return [map[key], value];
144
+ return [key, value];
145
+ }));
146
+ return clone;
147
+ });
148
+ }
149
+ function toArray(value) {
150
+ return Array.isArray(value) ? value : [value];
151
+ }
152
+ async function interopDefault(m) {
153
+ const resolved = await m;
154
+ return resolved.default || resolved;
155
+ }
156
+ function isPackageInScope(name) {
157
+ return isPackageExists(name, { paths: [scopeUrl] });
158
+ }
159
+ async function ensurePackages(packages) {
160
+ if (process.env.CI || process.stdout.isTTY === false || isCwdInScope === false) return;
161
+ const nonExistingPackages = packages.filter((i) => i && !isPackageInScope(i));
162
+ if (nonExistingPackages.length === 0) return;
163
+ if (await (await import("@clack/prompts")).confirm({ message: `${nonExistingPackages.length === 1 ? "Package is" : "Packages are"} required for this config: ${nonExistingPackages.join(", ")}. Do you want to install them?` })) await import("@antfu/install-pkg").then((i) => i.installPackage(nonExistingPackages, { dev: true }));
164
+ }
165
+ function isInEditorEnv() {
166
+ if (process.env.CI) return false;
167
+ if (isInGitHooksOrLintStaged()) return false;
168
+ return !!(process.env.VSCODE_PID || process.env.VSCODE_CWD || process.env.JETBRAINS_IDE || process.env.VIM || process.env.NVIM);
169
+ }
170
+ function isInGitHooksOrLintStaged() {
171
+ return !!(process.env.GIT_PARAMS || process.env.VSCODE_GIT_COMMAND || process.env.npm_lifecycle_script?.startsWith("lint-staged"));
172
+ }
173
+
174
+ //#endregion
175
+ //#region src/configs/stylistic.ts
176
+ const StylisticConfigDefaults = {
177
+ indent: 2,
178
+ jsx: true,
179
+ semi: true,
180
+ quotes: "single",
181
+ experimental: false,
182
+ commaDangle: "never"
183
+ };
184
+ async function stylistic(options = {}) {
185
+ const { jsx: jsx$1, semi, indent, quotes, commaDangle, experimental, overrides = {}, lessOpinionated = false } = {
186
+ ...StylisticConfigDefaults,
187
+ ...options
188
+ };
189
+ const pluginStylistic = await interopDefault(import("@stylistic/eslint-plugin"));
190
+ const config = pluginStylistic.configs.customize({
191
+ jsx: jsx$1,
192
+ semi,
193
+ indent,
194
+ quotes,
195
+ commaDangle,
196
+ pluginName: "style",
197
+ ...experimental != null && { experimental }
198
+ });
199
+ return [{
200
+ name: "whoj/stylistic/rules",
201
+ plugins: {
202
+ whoj: pluginAntfu,
203
+ style: pluginStylistic
204
+ },
205
+ rules: {
206
+ ...config.rules,
207
+ ...experimental ? {} : { "whoj/consistent-list-newline": "error" },
208
+ "whoj/consistent-chaining": "error",
209
+ ...lessOpinionated ? { curly: ["error", "all"] } : {
210
+ "whoj/curly": "error",
211
+ "whoj/if-newline": "error",
212
+ "whoj/top-level-function": "error"
213
+ },
214
+ "style/yield-star-spacing": ["error", {
215
+ after: true,
216
+ before: false
217
+ }],
218
+ "style/generator-star-spacing": ["error", {
219
+ after: true,
220
+ before: false
221
+ }],
222
+ ...overrides
223
+ }
224
+ }];
225
+ }
226
+
227
+ //#endregion
228
+ //#region src/globs.ts
229
+ const GLOB_SRC_EXT = "?([cm])[jt]s?(x)";
230
+ const GLOB_SRC = "**/*.?([cm])[jt]s?(x)";
231
+ const GLOB_JS = "**/*.?([cm])js";
232
+ const GLOB_JSX = "**/*.?([cm])jsx";
233
+ const GLOB_TS = "**/*.?([cm])ts";
234
+ const GLOB_TSX = "**/*.?([cm])tsx";
235
+ const GLOB_STYLE = "**/*.{c,le,sc}ss";
236
+ const GLOB_CSS = "**/*.css";
237
+ const GLOB_POSTCSS = "**/*.{p,post}css";
238
+ const GLOB_LESS = "**/*.less";
239
+ const GLOB_SCSS = "**/*.scss";
240
+ const GLOB_JSON = "**/*.json";
241
+ const GLOB_JSON5 = "**/*.json5";
242
+ const GLOB_JSONC = "**/*.jsonc";
243
+ const GLOB_MARKDOWN = "**/*.md";
244
+ const GLOB_MARKDOWN_IN_MARKDOWN = "**/*.md/*.md";
245
+ const GLOB_SVELTE = "**/*.svelte?(.{js,ts})";
246
+ const GLOB_VUE = "**/*.vue";
247
+ const GLOB_YAML = "**/*.y?(a)ml";
248
+ const GLOB_TOML = "**/*.toml";
249
+ const GLOB_XML = "**/*.xml";
250
+ const GLOB_SVG = "**/*.svg";
251
+ const GLOB_HTML = "**/*.htm?(l)";
252
+ const GLOB_ASTRO = "**/*.astro";
253
+ const GLOB_ASTRO_TS = "**/*.astro/*.ts";
254
+ const GLOB_GRAPHQL = "**/*.{g,graph}ql";
255
+ const GLOB_MARKDOWN_CODE = `${GLOB_MARKDOWN}/${GLOB_SRC}`;
256
+ const GLOB_TESTS = [
257
+ `**/__tests__/**/*.${GLOB_SRC_EXT}`,
258
+ `**/*.spec.${GLOB_SRC_EXT}`,
259
+ `**/*.test.${GLOB_SRC_EXT}`,
260
+ `**/*.bench.${GLOB_SRC_EXT}`,
261
+ `**/*.benchmark.${GLOB_SRC_EXT}`
262
+ ];
263
+ const GLOB_ALL_SRC = [
264
+ GLOB_SRC,
265
+ GLOB_STYLE,
266
+ GLOB_JSON,
267
+ GLOB_JSON5,
268
+ GLOB_MARKDOWN,
269
+ GLOB_SVELTE,
270
+ GLOB_VUE,
271
+ GLOB_YAML,
272
+ GLOB_XML,
273
+ GLOB_HTML
274
+ ];
275
+ const GLOB_EXCLUDE = [
276
+ "**/node_modules",
277
+ "**/dist",
278
+ "**/package-lock.json",
279
+ "**/yarn.lock",
280
+ "**/pnpm-lock.yaml",
281
+ "**/bun.lockb",
282
+ "**/output",
283
+ "**/coverage",
284
+ "**/temp",
285
+ "**/.temp",
286
+ "**/tmp",
287
+ "**/.tmp",
288
+ "**/.history",
289
+ "**/.vitepress/cache",
290
+ "**/.nuxt",
291
+ "**/.next",
292
+ "**/.svelte-kit",
293
+ "**/.vercel",
294
+ "**/.changeset",
295
+ "**/.idea",
296
+ "**/.cache",
297
+ "**/.output",
298
+ "**/.vite-inspect",
299
+ "**/.yarn",
300
+ "**/vite.config.*.timestamp-*",
301
+ "**/CHANGELOG*.md",
302
+ "**/*.min.*",
303
+ "**/LICENSE*",
304
+ "**/__snapshots__",
305
+ "**/auto-import?(s).d.ts",
306
+ "**/components.d.ts"
307
+ ];
308
+
309
+ //#endregion
310
+ //#region src/configs/formatters.ts
311
+ function mergePrettierOptions(options, overrides) {
312
+ return {
313
+ ...options,
314
+ ...overrides,
315
+ plugins: [...overrides.plugins || [], ...options.plugins || []]
316
+ };
317
+ }
318
+ async function formatters(options = {}, stylistic$1 = {}) {
319
+ if (options === true) {
320
+ const isPrettierPluginXmlInScope = isPackageInScope("@prettier/plugin-xml");
321
+ options = {
322
+ css: true,
323
+ html: true,
324
+ graphql: true,
325
+ markdown: true,
326
+ svg: isPrettierPluginXmlInScope,
327
+ xml: isPrettierPluginXmlInScope,
328
+ slidev: isPackageExists("@slidev/cli"),
329
+ astro: isPackageInScope("prettier-plugin-astro")
330
+ };
331
+ }
332
+ await ensurePackages([
333
+ "eslint-plugin-format",
334
+ options.markdown && options.slidev ? "prettier-plugin-slidev" : void 0,
335
+ options.astro ? "prettier-plugin-astro" : void 0,
336
+ options.xml || options.svg ? "@prettier/plugin-xml" : void 0
337
+ ]);
338
+ if (options.slidev && options.markdown !== true && options.markdown !== "prettier") throw new Error("`slidev` option only works when `markdown` is enabled with `prettier`");
339
+ const { semi, indent, quotes } = {
340
+ ...StylisticConfigDefaults,
341
+ ...stylistic$1
342
+ };
343
+ const prettierOptions = Object.assign({
344
+ semi,
345
+ printWidth: 120,
346
+ endOfLine: "auto",
347
+ trailingComma: "none",
348
+ useTabs: indent === "tab",
349
+ singleQuote: quotes === "single",
350
+ tabWidth: typeof indent === "number" ? indent : 2
351
+ }, options.prettierOptions || {});
352
+ const prettierXmlOptions = {
353
+ xmlSelfClosingSpace: true,
354
+ xmlQuoteAttributes: "double",
355
+ xmlSortAttributesByKey: false,
356
+ xmlWhitespaceSensitivity: "ignore"
357
+ };
358
+ const dprintOptions = Object.assign({
359
+ useTabs: indent === "tab",
360
+ indentWidth: typeof indent === "number" ? indent : 2,
361
+ quoteStyle: quotes === "single" ? "preferSingle" : "preferDouble"
362
+ }, options.dprintOptions || {});
363
+ const configs$1 = [{
364
+ name: "whoj/formatter/setup",
365
+ plugins: { format: await interopDefault(import("eslint-plugin-format")) }
366
+ }];
367
+ if (options.css) configs$1.push({
368
+ name: "whoj/formatter/css",
369
+ files: [GLOB_CSS, GLOB_POSTCSS],
370
+ languageOptions: { parser: parserPlain },
371
+ rules: { "format/prettier": ["error", mergePrettierOptions(prettierOptions, { parser: "css" })] }
372
+ }, {
373
+ files: [GLOB_SCSS],
374
+ name: "whoj/formatter/scss",
375
+ languageOptions: { parser: parserPlain },
376
+ rules: { "format/prettier": ["error", mergePrettierOptions(prettierOptions, { parser: "scss" })] }
377
+ }, {
378
+ files: [GLOB_LESS],
379
+ name: "whoj/formatter/less",
380
+ languageOptions: { parser: parserPlain },
381
+ rules: { "format/prettier": ["error", mergePrettierOptions(prettierOptions, { parser: "less" })] }
382
+ });
383
+ if (options.html) configs$1.push({
384
+ files: [GLOB_HTML],
385
+ name: "whoj/formatter/html",
386
+ languageOptions: { parser: parserPlain },
387
+ rules: { "format/prettier": ["error", mergePrettierOptions(prettierOptions, { parser: "html" })] }
388
+ });
389
+ if (options.xml) configs$1.push({
390
+ files: [GLOB_XML],
391
+ name: "whoj/formatter/xml",
392
+ languageOptions: { parser: parserPlain },
393
+ rules: { "format/prettier": ["error", mergePrettierOptions({
394
+ ...prettierXmlOptions,
395
+ ...prettierOptions
396
+ }, {
397
+ parser: "xml",
398
+ plugins: ["@prettier/plugin-xml"]
399
+ })] }
400
+ });
401
+ if (options.svg) configs$1.push({
402
+ files: [GLOB_SVG],
403
+ name: "whoj/formatter/svg",
404
+ languageOptions: { parser: parserPlain },
405
+ rules: { "format/prettier": ["error", mergePrettierOptions({
406
+ ...prettierXmlOptions,
407
+ ...prettierOptions
408
+ }, {
409
+ parser: "xml",
410
+ plugins: ["@prettier/plugin-xml"]
411
+ })] }
412
+ });
413
+ if (options.markdown) {
414
+ const formater = options.markdown === true ? "prettier" : options.markdown;
415
+ const GLOB_SLIDEV = !options.slidev ? [] : options.slidev === true ? ["**/slides.md"] : options.slidev.files;
416
+ configs$1.push({
417
+ ignores: GLOB_SLIDEV,
418
+ files: [GLOB_MARKDOWN],
419
+ name: "whoj/formatter/markdown",
420
+ languageOptions: { parser: parserPlain },
421
+ rules: { [`format/${formater}`]: ["error", formater === "prettier" ? mergePrettierOptions(prettierOptions, {
422
+ parser: "markdown",
423
+ embeddedLanguageFormatting: "off"
424
+ }) : {
425
+ ...dprintOptions,
426
+ language: "markdown"
427
+ }] }
428
+ });
429
+ if (options.slidev) configs$1.push({
430
+ files: GLOB_SLIDEV,
431
+ name: "whoj/formatter/slidev",
432
+ languageOptions: { parser: parserPlain },
433
+ rules: { "format/prettier": ["error", mergePrettierOptions(prettierOptions, {
434
+ parser: "slidev",
435
+ embeddedLanguageFormatting: "off",
436
+ plugins: ["prettier-plugin-slidev"]
437
+ })] }
438
+ });
439
+ }
440
+ if (options.astro) {
441
+ configs$1.push({
442
+ files: [GLOB_ASTRO],
443
+ name: "whoj/formatter/astro",
444
+ languageOptions: { parser: parserPlain },
445
+ rules: { "format/prettier": ["error", mergePrettierOptions(prettierOptions, {
446
+ parser: "astro",
447
+ plugins: ["prettier-plugin-astro"]
448
+ })] }
449
+ });
450
+ configs$1.push({
451
+ files: [GLOB_ASTRO, GLOB_ASTRO_TS],
452
+ name: "whoj/formatter/astro/disables",
453
+ rules: {
454
+ "style/semi": "off",
455
+ "style/indent": "off",
456
+ "style/quotes": "off",
457
+ "style/arrow-parens": "off",
458
+ "style/comma-dangle": "off",
459
+ "style/block-spacing": "off",
460
+ "style/no-multi-spaces": "off"
461
+ }
462
+ });
463
+ }
464
+ if (options.graphql) configs$1.push({
465
+ files: [GLOB_GRAPHQL],
466
+ name: "whoj/formatter/graphql",
467
+ languageOptions: { parser: parserPlain },
468
+ rules: { "format/prettier": ["error", mergePrettierOptions(prettierOptions, { parser: "graphql" })] }
469
+ });
470
+ return configs$1;
471
+ }
472
+
473
+ //#endregion
474
+ //#region src/configs/jsx.ts
475
+ async function jsx(options = {}) {
476
+ const { a11y } = options;
477
+ const baseConfig = {
478
+ rules: {},
479
+ plugins: {},
480
+ name: "whoj/jsx/setup",
481
+ files: [GLOB_JSX, GLOB_TSX],
482
+ languageOptions: { parserOptions: { ecmaFeatures: { jsx: true } } }
483
+ };
484
+ if (!a11y) return [baseConfig];
485
+ await ensurePackages(["eslint-plugin-jsx-a11y"]);
486
+ const jsxA11yPlugin = await interopDefault(import("eslint-plugin-jsx-a11y"));
487
+ const a11yConfig = jsxA11yPlugin.flatConfigs.recommended;
488
+ const a11yRules = {
489
+ ...a11yConfig.rules || {},
490
+ ...typeof a11y === "object" && a11y.overrides ? a11y.overrides : {}
491
+ };
492
+ return [{
493
+ ...baseConfig,
494
+ ...a11yConfig,
495
+ name: baseConfig.name,
496
+ files: baseConfig.files,
497
+ rules: {
498
+ ...baseConfig.rules,
499
+ ...a11yRules
500
+ },
501
+ plugins: {
502
+ ...baseConfig.plugins,
503
+ "jsx-a11y": jsxA11yPlugin
504
+ },
505
+ languageOptions: {
506
+ ...baseConfig.languageOptions,
507
+ ...a11yConfig.languageOptions
508
+ }
509
+ }];
510
+ }
511
+
512
+ //#endregion
513
+ //#region src/configs/vue.ts
514
+ async function vue(options = {}) {
515
+ const { a11y = false, overrides = {}, vueVersion = 3, stylistic: stylistic$1 = true, files = [GLOB_VUE] } = options;
516
+ const sfcBlocks = options.sfcBlocks === true ? {} : options.sfcBlocks ?? {};
517
+ const { indent = 2 } = typeof stylistic$1 === "boolean" ? {} : stylistic$1;
518
+ if (a11y) await ensurePackages(["eslint-plugin-vuejs-accessibility"]);
519
+ const [pluginVue, parserVue, processorVueBlocks, pluginVueA11y] = await Promise.all([
520
+ interopDefault(import("eslint-plugin-vue")),
521
+ interopDefault(import("vue-eslint-parser")),
522
+ interopDefault(import("eslint-processor-vue-blocks")),
523
+ ...a11y ? [interopDefault(import("eslint-plugin-vuejs-accessibility"))] : []
524
+ ]);
525
+ return [{
526
+ name: "whoj/vue/setup",
527
+ plugins: {
528
+ vue: pluginVue,
529
+ ...a11y ? { "vue-a11y": pluginVueA11y } : {}
530
+ },
531
+ languageOptions: { globals: {
532
+ ref: "readonly",
533
+ toRef: "readonly",
534
+ watch: "readonly",
535
+ toRefs: "readonly",
536
+ computed: "readonly",
537
+ reactive: "readonly",
538
+ onMounted: "readonly",
539
+ shallowRef: "readonly",
540
+ defineEmits: "readonly",
541
+ defineProps: "readonly",
542
+ onUnmounted: "readonly",
543
+ watchEffect: "readonly",
544
+ defineExpose: "readonly",
545
+ shallowReactive: "readonly"
546
+ } }
547
+ }, {
548
+ files,
549
+ name: "whoj/vue/rules",
550
+ processor: sfcBlocks === false ? pluginVue.processors[".vue"] : mergeProcessors([pluginVue.processors[".vue"], processorVueBlocks({
551
+ ...sfcBlocks,
552
+ blocks: {
553
+ styles: true,
554
+ ...sfcBlocks.blocks
555
+ }
556
+ })]),
557
+ languageOptions: {
558
+ parser: parserVue,
559
+ parserOptions: {
560
+ sourceType: "module",
561
+ extraFileExtensions: [".vue"],
562
+ ecmaFeatures: { jsx: true },
563
+ parser: options.typescript ? await interopDefault(import("@typescript-eslint/parser")) : null
564
+ }
565
+ },
566
+ rules: {
567
+ ...pluginVue.configs.base.rules,
568
+ ...vueVersion === 2 ? {
569
+ ...pluginVue.configs["vue2-essential"].rules,
570
+ ...pluginVue.configs["vue2-strongly-recommended"].rules,
571
+ ...pluginVue.configs["vue2-recommended"].rules
572
+ } : {
573
+ ...pluginVue.configs["flat/essential"].map((c) => c.rules).reduce((acc, c) => ({
574
+ ...acc,
575
+ ...c
576
+ }), {}),
577
+ ...pluginVue.configs["flat/strongly-recommended"].map((c) => c.rules).reduce((acc, c) => ({
578
+ ...acc,
579
+ ...c
580
+ }), {}),
581
+ ...pluginVue.configs["flat/recommended"].map((c) => c.rules).reduce((acc, c) => ({
582
+ ...acc,
583
+ ...c
584
+ }), {})
585
+ },
586
+ "vue/no-v-html": "off",
587
+ "vue/no-dupe-keys": "off",
588
+ "vue/no-unused-refs": "error",
589
+ "vue/prefer-template": "error",
590
+ "vue/space-infix-ops": "error",
591
+ "vue/no-empty-pattern": "error",
592
+ "vue/no-sparse-arrays": "error",
593
+ "vue/require-prop-types": "off",
594
+ "vue/eqeqeq": ["error", "smart"],
595
+ "vue/no-useless-v-bind": "error",
596
+ "whoj/no-top-level-await": "off",
597
+ "vue/component-tags-order": "off",
598
+ "vue/require-default-prop": "off",
599
+ "node/prefer-global/process": "off",
600
+ "vue/no-loss-of-precision": "error",
601
+ "vue/html-indent": ["error", indent],
602
+ "vue/max-attributes-per-line": "off",
603
+ "vue/html-quotes": ["error", "double"],
604
+ "vue/no-irregular-whitespace": "error",
605
+ "vue/multi-word-component-names": "off",
606
+ "ts/explicit-function-return-type": "off",
607
+ "vue/dot-location": ["error", "property"],
608
+ "vue/no-setup-props-reactivity-loss": "off",
609
+ "vue/prefer-separate-static-class": "error",
610
+ "vue/no-restricted-v-bind": ["error", "/^v-/"],
611
+ "vue/prop-name-casing": ["error", "camelCase"],
612
+ "vue/custom-event-name-casing": ["error", "camelCase"],
613
+ "vue/dot-notation": ["error", { allowKeywords: true }],
614
+ "vue/component-options-name-casing": ["error", "PascalCase"],
615
+ "vue/component-name-in-template-casing": ["error", "PascalCase"],
616
+ "vue/space-unary-ops": ["error", {
617
+ words: true,
618
+ nonwords: false
619
+ }],
620
+ "vue/block-order": ["error", { order: [
621
+ "script",
622
+ "template",
623
+ "style"
624
+ ] }],
625
+ "vue/define-macros-order": ["error", { order: [
626
+ "defineOptions",
627
+ "defineProps",
628
+ "defineEmits",
629
+ "defineSlots"
630
+ ] }],
631
+ "vue/no-restricted-syntax": [
632
+ "error",
633
+ "DebuggerStatement",
634
+ "LabeledStatement",
635
+ "WithStatement"
636
+ ],
637
+ "vue/object-shorthand": [
638
+ "error",
639
+ "always",
640
+ {
641
+ avoidQuotes: true,
642
+ ignoreConstructors: false
643
+ }
644
+ ],
645
+ ...stylistic$1 ? {
646
+ "vue/object-curly-newline": "off",
647
+ "vue/comma-style": ["error", "last"],
648
+ "vue/template-curly-spacing": "error",
649
+ "vue/comma-dangle": ["error", "never"],
650
+ "vue/block-spacing": ["error", "always"],
651
+ "vue/space-in-parens": ["error", "never"],
652
+ "vue/operator-linebreak": ["error", "before"],
653
+ "vue/array-bracket-spacing": ["error", "never"],
654
+ "vue/object-curly-spacing": ["error", "always"],
655
+ "vue/quote-props": ["error", "consistent-as-needed"],
656
+ "vue/padding-line-between-blocks": ["error", "always"],
657
+ "vue/arrow-spacing": ["error", {
658
+ after: true,
659
+ before: true
660
+ }],
661
+ "vue/comma-spacing": ["error", {
662
+ after: true,
663
+ before: false
664
+ }],
665
+ "vue/keyword-spacing": ["error", {
666
+ after: true,
667
+ before: true
668
+ }],
669
+ "vue/brace-style": [
670
+ "error",
671
+ "stroustrup",
672
+ { allowSingleLine: true }
673
+ ],
674
+ "vue/key-spacing": ["error", {
675
+ afterColon: true,
676
+ beforeColon: false
677
+ }],
678
+ "vue/object-property-newline": ["error", { allowAllPropertiesOnSameLine: true }],
679
+ "vue/html-comment-content-spacing": [
680
+ "error",
681
+ "always",
682
+ { exceptions: ["-"] }
683
+ ],
684
+ "vue/block-tag-newline": ["error", {
685
+ multiline: "always",
686
+ singleline: "always"
687
+ }]
688
+ } : {},
689
+ ...a11y ? {
690
+ "vue-a11y/alt-text": "error",
691
+ "vue-a11y/aria-role": "error",
692
+ "vue-a11y/aria-props": "error",
693
+ "vue-a11y/no-autofocus": "warn",
694
+ "vue-a11y/label-has-for": "error",
695
+ "vue-a11y/no-access-key": "error",
696
+ "vue-a11y/iframe-has-title": "error",
697
+ "vue-a11y/media-has-caption": "warn",
698
+ "vue-a11y/anchor-has-content": "error",
699
+ "vue-a11y/no-redundant-roles": "error",
700
+ "vue-a11y/heading-has-content": "error",
701
+ "vue-a11y/tabindex-no-positive": "warn",
702
+ "vue-a11y/form-control-has-label": "error",
703
+ "vue-a11y/no-distracting-elements": "error",
704
+ "vue-a11y/aria-unsupported-elements": "error",
705
+ "vue-a11y/interactive-supports-focus": "error",
706
+ "vue-a11y/no-aria-hidden-on-focusable": "error",
707
+ "vue-a11y/click-events-have-key-events": "error",
708
+ "vue-a11y/mouse-events-have-key-events": "error",
709
+ "vue-a11y/role-has-required-aria-props": "error",
710
+ "vue-a11y/no-static-element-interactions": "error",
711
+ "vue-a11y/no-role-presentation-on-focusable": "error"
712
+ } : {},
713
+ ...overrides
714
+ }
715
+ }];
716
+ }
717
+
718
+ //#endregion
719
+ //#region src/configs/node.ts
720
+ async function node() {
721
+ return [{
722
+ files: [GLOB_SRC],
723
+ name: "whoj/node/rules",
724
+ plugins: { node: pluginNode },
725
+ rules: {
726
+ "node/no-new-require": "error",
727
+ "node/no-path-concat": "error",
728
+ "node/no-deprecated-api": "error",
729
+ "node/no-exports-assign": "error",
730
+ "node/process-exit-as-throw": "error",
731
+ "node/prefer-global/buffer": ["error", "never"],
732
+ "node/prefer-global/process": ["error", "never"],
733
+ "node/handle-callback-err": ["error", "^(err|error)$"]
734
+ }
735
+ }];
736
+ }
737
+
738
+ //#endregion
739
+ //#region src/configs/pnpm.ts
740
+ async function detectCatalogUsage() {
741
+ const workspaceFile = await findUp("pnpm-workspace.yaml");
742
+ if (!workspaceFile) return false;
743
+ const yaml$1 = await fs.readFile(workspaceFile, "utf-8");
744
+ return yaml$1.includes("catalog:") || yaml$1.includes("catalogs:");
745
+ }
746
+ async function pnpm(options) {
747
+ const [pluginPnpm, pluginYaml, yamlParser, jsoncParser] = await Promise.all([
748
+ interopDefault(import("eslint-plugin-pnpm")),
749
+ interopDefault(import("eslint-plugin-yml")),
750
+ interopDefault(import("yaml-eslint-parser")),
751
+ interopDefault(import("jsonc-eslint-parser"))
752
+ ]);
753
+ const { json = true, sort = true, yaml: yaml$1 = true, isInEditor = false, catalogs = await detectCatalogUsage() } = options;
754
+ const configs$1 = [];
755
+ if (json) configs$1.push({
756
+ name: "whoj/pnpm/package-json",
757
+ plugins: { pnpm: pluginPnpm },
758
+ languageOptions: { parser: jsoncParser },
759
+ files: ["package.json", "**/package.json"],
760
+ rules: {
761
+ ...catalogs ? { "pnpm/json-enforce-catalog": ["error", {
762
+ autofix: !isInEditor,
763
+ ignores: ["@types/vscode"]
764
+ }] } : {},
765
+ "pnpm/json-valid-catalog": ["error", { autofix: !isInEditor }],
766
+ "pnpm/json-prefer-workspace-settings": ["error", { autofix: !isInEditor }]
767
+ }
768
+ });
769
+ if (yaml$1) {
770
+ configs$1.push({
771
+ files: ["pnpm-workspace.yaml"],
772
+ name: "whoj/pnpm/pnpm-workspace-yaml",
773
+ plugins: { pnpm: pluginPnpm },
774
+ languageOptions: { parser: yamlParser },
775
+ rules: {
776
+ "pnpm/yaml-no-unused-catalog-item": "error",
777
+ "pnpm/yaml-no-duplicate-catalog-item": "error",
778
+ "pnpm/yaml-enforce-settings": ["error", { settings: {
779
+ shellEmulator: true,
780
+ trustPolicy: "no-downgrade"
781
+ } }]
782
+ }
783
+ });
784
+ if (sort) configs$1.push({
785
+ files: ["pnpm-workspace.yaml"],
786
+ name: "whoj/pnpm/pnpm-workspace-yaml-sort",
787
+ plugins: { yaml: pluginYaml },
788
+ languageOptions: { parser: yamlParser },
789
+ rules: { "yaml/sort-keys": [
790
+ "error",
791
+ {
792
+ pathPattern: "^$",
793
+ order: [
794
+ ...[
795
+ "cacheDir",
796
+ "catalogMode",
797
+ "cleanupUnusedCatalogs",
798
+ "dedupeDirectDeps",
799
+ "deployAllFiles",
800
+ "enablePrePostScripts",
801
+ "engineStrict",
802
+ "extendNodePath",
803
+ "hoist",
804
+ "hoistPattern",
805
+ "hoistWorkspacePackages",
806
+ "ignoreCompatibilityDb",
807
+ "ignoreDepScripts",
808
+ "ignoreScripts",
809
+ "ignoreWorkspaceRootCheck",
810
+ "managePackageManagerVersions",
811
+ "minimumReleaseAge",
812
+ "minimumReleaseAgeExclude",
813
+ "modulesDir",
814
+ "nodeLinker",
815
+ "nodeVersion",
816
+ "optimisticRepeatInstall",
817
+ "packageManagerStrict",
818
+ "packageManagerStrictVersion",
819
+ "preferSymlinkedExecutables",
820
+ "preferWorkspacePackages",
821
+ "publicHoistPattern",
822
+ "registrySupportsTimeField",
823
+ "requiredScripts",
824
+ "resolutionMode",
825
+ "savePrefix",
826
+ "scriptShell",
827
+ "shamefullyHoist",
828
+ "shellEmulator",
829
+ "stateDir",
830
+ "supportedArchitectures",
831
+ "symlink",
832
+ "tag",
833
+ "trustPolicy",
834
+ "trustPolicyExclude",
835
+ "updateNotifier"
836
+ ],
837
+ "packages",
838
+ "overrides",
839
+ "patchedDependencies",
840
+ "catalog",
841
+ "catalogs",
842
+ ...[
843
+ "allowedDeprecatedVersions",
844
+ "allowNonAppliedPatches",
845
+ "configDependencies",
846
+ "ignoredBuiltDependencies",
847
+ "ignoredOptionalDependencies",
848
+ "neverBuiltDependencies",
849
+ "onlyBuiltDependencies",
850
+ "onlyBuiltDependenciesFile",
851
+ "packageExtensions",
852
+ "peerDependencyRules"
853
+ ]
854
+ ]
855
+ },
856
+ {
857
+ pathPattern: ".*",
858
+ order: { type: "asc" }
859
+ }
860
+ ] }
861
+ });
862
+ }
863
+ return configs$1;
864
+ }
865
+
866
+ //#endregion
867
+ //#region src/configs/sort.ts
868
+ /**
869
+ * Sort package.json
870
+ *
871
+ * Requires `jsonc` config
872
+ */
873
+ async function sortPackageJson() {
874
+ return [{
875
+ files: ["**/package.json"],
876
+ name: "whoj/sort/package-json",
877
+ rules: {
878
+ "jsonc/sort-array-values": ["error", {
879
+ order: { type: "asc" },
880
+ pathPattern: "^files$"
881
+ }],
882
+ "jsonc/sort-keys": [
883
+ "error",
884
+ {
885
+ pathPattern: "^$",
886
+ order: [
887
+ "publisher",
888
+ "name",
889
+ "displayName",
890
+ "type",
891
+ "version",
892
+ "private",
893
+ "packageManager",
894
+ "description",
895
+ "author",
896
+ "contributors",
897
+ "license",
898
+ "funding",
899
+ "homepage",
900
+ "repository",
901
+ "bugs",
902
+ "keywords",
903
+ "categories",
904
+ "sideEffects",
905
+ "imports",
906
+ "exports",
907
+ "main",
908
+ "module",
909
+ "unpkg",
910
+ "jsdelivr",
911
+ "types",
912
+ "typesVersions",
913
+ "bin",
914
+ "icon",
915
+ "files",
916
+ "engines",
917
+ "activationEvents",
918
+ "contributes",
919
+ "scripts",
920
+ "peerDependencies",
921
+ "peerDependenciesMeta",
922
+ "dependencies",
923
+ "optionalDependencies",
924
+ "devDependencies",
925
+ "pnpm",
926
+ "overrides",
927
+ "resolutions",
928
+ "husky",
929
+ "simple-git-hooks",
930
+ "lint-staged",
931
+ "eslintConfig"
932
+ ]
933
+ },
934
+ {
935
+ order: { type: "asc" },
936
+ pathPattern: "^(?:dev|peer|optional|bundled)?[Dd]ependencies(Meta)?$"
937
+ },
938
+ {
939
+ order: { type: "asc" },
940
+ pathPattern: "^(?:resolutions|overrides|pnpm.overrides)$"
941
+ },
942
+ {
943
+ order: { type: "asc" },
944
+ pathPattern: "^workspaces\\.catalog$"
945
+ },
946
+ {
947
+ order: { type: "asc" },
948
+ pathPattern: "^workspaces\\.catalogs\\.[^.]+$"
949
+ },
950
+ {
951
+ pathPattern: "^exports.*$",
952
+ order: [
953
+ "types",
954
+ "import",
955
+ "require",
956
+ "default"
957
+ ]
958
+ },
959
+ {
960
+ pathPattern: "^(?:gitHooks|husky|simple-git-hooks)$",
961
+ order: [
962
+ "pre-commit",
963
+ "prepare-commit-msg",
964
+ "commit-msg",
965
+ "post-commit",
966
+ "pre-rebase",
967
+ "post-rewrite",
968
+ "post-checkout",
969
+ "post-merge",
970
+ "pre-push",
971
+ "pre-auto-gc"
972
+ ]
973
+ }
974
+ ]
975
+ }
976
+ }];
977
+ }
978
+ /**
979
+ * Sort tsconfig.json
980
+ *
981
+ * Requires `jsonc` config
982
+ */
983
+ function sortTsconfig() {
984
+ return [{
985
+ name: "whoj/sort/tsconfig-json",
986
+ files: ["**/[jt]sconfig.json", "**/[jt]sconfig.*.json"],
987
+ rules: { "jsonc/sort-keys": [
988
+ "error",
989
+ {
990
+ pathPattern: "^$",
991
+ order: [
992
+ "extends",
993
+ "compilerOptions",
994
+ "references",
995
+ "files",
996
+ "include",
997
+ "exclude"
998
+ ]
999
+ },
1000
+ {
1001
+ pathPattern: "^compilerOptions$",
1002
+ order: [
1003
+ "incremental",
1004
+ "composite",
1005
+ "tsBuildInfoFile",
1006
+ "disableSourceOfProjectReferenceRedirect",
1007
+ "disableSolutionSearching",
1008
+ "disableReferencedProjectLoad",
1009
+ "target",
1010
+ "jsx",
1011
+ "jsxFactory",
1012
+ "jsxFragmentFactory",
1013
+ "jsxImportSource",
1014
+ "lib",
1015
+ "moduleDetection",
1016
+ "noLib",
1017
+ "reactNamespace",
1018
+ "useDefineForClassFields",
1019
+ "emitDecoratorMetadata",
1020
+ "experimentalDecorators",
1021
+ "libReplacement",
1022
+ "baseUrl",
1023
+ "rootDir",
1024
+ "rootDirs",
1025
+ "customConditions",
1026
+ "module",
1027
+ "moduleResolution",
1028
+ "moduleSuffixes",
1029
+ "noResolve",
1030
+ "paths",
1031
+ "resolveJsonModule",
1032
+ "resolvePackageJsonExports",
1033
+ "resolvePackageJsonImports",
1034
+ "typeRoots",
1035
+ "types",
1036
+ "allowArbitraryExtensions",
1037
+ "allowImportingTsExtensions",
1038
+ "allowUmdGlobalAccess",
1039
+ "allowJs",
1040
+ "checkJs",
1041
+ "maxNodeModuleJsDepth",
1042
+ "strict",
1043
+ "strictBindCallApply",
1044
+ "strictFunctionTypes",
1045
+ "strictNullChecks",
1046
+ "strictPropertyInitialization",
1047
+ "allowUnreachableCode",
1048
+ "allowUnusedLabels",
1049
+ "alwaysStrict",
1050
+ "exactOptionalPropertyTypes",
1051
+ "noFallthroughCasesInSwitch",
1052
+ "noImplicitAny",
1053
+ "noImplicitOverride",
1054
+ "noImplicitReturns",
1055
+ "noImplicitThis",
1056
+ "noPropertyAccessFromIndexSignature",
1057
+ "noUncheckedIndexedAccess",
1058
+ "noUnusedLocals",
1059
+ "noUnusedParameters",
1060
+ "useUnknownInCatchVariables",
1061
+ "declaration",
1062
+ "declarationDir",
1063
+ "declarationMap",
1064
+ "downlevelIteration",
1065
+ "emitBOM",
1066
+ "emitDeclarationOnly",
1067
+ "importHelpers",
1068
+ "importsNotUsedAsValues",
1069
+ "inlineSourceMap",
1070
+ "inlineSources",
1071
+ "mapRoot",
1072
+ "newLine",
1073
+ "noEmit",
1074
+ "noEmitHelpers",
1075
+ "noEmitOnError",
1076
+ "outDir",
1077
+ "outFile",
1078
+ "preserveConstEnums",
1079
+ "preserveValueImports",
1080
+ "removeComments",
1081
+ "sourceMap",
1082
+ "sourceRoot",
1083
+ "stripInternal",
1084
+ "allowSyntheticDefaultImports",
1085
+ "esModuleInterop",
1086
+ "forceConsistentCasingInFileNames",
1087
+ "isolatedDeclarations",
1088
+ "isolatedModules",
1089
+ "preserveSymlinks",
1090
+ "verbatimModuleSyntax",
1091
+ "erasableSyntaxOnly",
1092
+ "skipDefaultLibCheck",
1093
+ "skipLibCheck"
1094
+ ]
1095
+ }
1096
+ ] }
1097
+ }];
1098
+ }
1099
+
1100
+ //#endregion
1101
+ //#region src/configs/test.ts
1102
+ let _pluginTest;
1103
+ async function test(options = {}) {
1104
+ const { overrides = {}, files = GLOB_TESTS, isInEditor = false } = options;
1105
+ const [pluginVitest, pluginNoOnlyTests] = await Promise.all([interopDefault(import("@vitest/eslint-plugin")), interopDefault(import("eslint-plugin-no-only-tests"))]);
1106
+ _pluginTest = _pluginTest || {
1107
+ ...pluginVitest,
1108
+ rules: {
1109
+ ...pluginVitest.rules,
1110
+ ...pluginNoOnlyTests.rules
1111
+ }
1112
+ };
1113
+ return [{
1114
+ name: "whoj/test/setup",
1115
+ plugins: { test: _pluginTest }
1116
+ }, {
1117
+ files,
1118
+ name: "whoj/test/rules",
1119
+ rules: {
1120
+ "test/no-identical-title": "error",
1121
+ "test/no-import-node-test": "error",
1122
+ "test/prefer-hooks-in-order": "error",
1123
+ "test/prefer-lowercase-title": "error",
1124
+ "test/no-only-tests": isInEditor ? "warn" : "error",
1125
+ "test/consistent-test-it": ["error", {
1126
+ fn: "it",
1127
+ withinDescribe: "it"
1128
+ }],
1129
+ "no-unused-expressions": "off",
1130
+ "whoj/no-top-level-await": "off",
1131
+ "node/prefer-global/process": "off",
1132
+ "ts/explicit-function-return-type": "off",
1133
+ ...overrides
1134
+ }
1135
+ }];
1136
+ }
1137
+
1138
+ //#endregion
1139
+ //#region src/configs/toml.ts
1140
+ async function toml(options = {}) {
1141
+ const { overrides = {}, stylistic: stylistic$1 = true, files = [GLOB_TOML] } = options;
1142
+ const { indent = 2 } = typeof stylistic$1 === "boolean" ? {} : stylistic$1;
1143
+ const [pluginToml, parserToml] = await Promise.all([interopDefault(import("eslint-plugin-toml")), interopDefault(import("toml-eslint-parser"))]);
1144
+ return [{
1145
+ name: "whoj/toml/setup",
1146
+ plugins: { toml: pluginToml }
1147
+ }, {
1148
+ files,
1149
+ name: "whoj/toml/rules",
1150
+ languageOptions: { parser: parserToml },
1151
+ rules: {
1152
+ "toml/keys-order": "error",
1153
+ "toml/comma-style": "error",
1154
+ "toml/tables-order": "error",
1155
+ "style/spaced-comment": "off",
1156
+ "toml/no-space-dots": "error",
1157
+ "toml/precision-of-integer": "error",
1158
+ "toml/no-unreadable-number-separator": "error",
1159
+ "toml/precision-of-fractional-seconds": "error",
1160
+ "toml/vue-custom-block/no-parsing-error": "error",
1161
+ ...stylistic$1 ? {
1162
+ "toml/key-spacing": "error",
1163
+ "toml/quoted-keys": "error",
1164
+ "toml/spaced-comment": "error",
1165
+ "toml/array-bracket-newline": "error",
1166
+ "toml/array-bracket-spacing": "error",
1167
+ "toml/array-element-newline": "error",
1168
+ "toml/table-bracket-spacing": "error",
1169
+ "toml/inline-table-curly-spacing": "error",
1170
+ "toml/padding-line-between-pairs": "error",
1171
+ "toml/padding-line-between-tables": "error",
1172
+ "toml/indent": ["error", typeof indent === "number" ? indent : indent === "tab" ? "tab" : 2]
1173
+ } : {},
1174
+ ...overrides
1175
+ }
1176
+ }];
1177
+ }
1178
+
1179
+ //#endregion
1180
+ //#region src/configs/yaml.ts
1181
+ async function yaml(options = {}) {
1182
+ const { overrides = {}, stylistic: stylistic$1 = true, files = [GLOB_YAML] } = options;
1183
+ const { indent = 2, quotes = "single" } = typeof stylistic$1 === "boolean" ? {} : stylistic$1;
1184
+ const [pluginYaml, parserYaml] = await Promise.all([interopDefault(import("eslint-plugin-yml")), interopDefault(import("yaml-eslint-parser"))]);
1185
+ return [{
1186
+ name: "whoj/yaml/setup",
1187
+ plugins: { yaml: pluginYaml }
1188
+ }, {
1189
+ files,
1190
+ name: "whoj/yaml/rules",
1191
+ languageOptions: { parser: parserYaml },
1192
+ rules: {
1193
+ "yaml/no-empty-key": "error",
1194
+ "yaml/plain-scalar": "error",
1195
+ "style/spaced-comment": "off",
1196
+ "yaml/block-mapping": "error",
1197
+ "yaml/block-sequence": "error",
1198
+ "yaml/no-empty-sequence-entry": "error",
1199
+ "yaml/no-irregular-whitespace": "error",
1200
+ "yaml/vue-custom-block/no-parsing-error": "error",
1201
+ ...stylistic$1 ? {
1202
+ "yaml/key-spacing": "error",
1203
+ "yaml/no-tab-indent": "error",
1204
+ "yaml/spaced-comment": "error",
1205
+ "yaml/flow-mapping-curly-newline": "error",
1206
+ "yaml/flow-mapping-curly-spacing": "error",
1207
+ "yaml/flow-sequence-bracket-newline": "error",
1208
+ "yaml/flow-sequence-bracket-spacing": "error",
1209
+ "yaml/block-sequence-hyphen-indicator-newline": "error",
1210
+ "yaml/block-mapping-question-indicator-newline": "error",
1211
+ "yaml/indent": ["error", typeof indent === "number" ? indent : 2],
1212
+ "yaml/quotes": ["error", {
1213
+ avoidEscape: true,
1214
+ prefer: quotes === "backtick" ? "single" : quotes
1215
+ }]
1216
+ } : {},
1217
+ ...overrides
1218
+ }
1219
+ }];
1220
+ }
1221
+
1222
+ //#endregion
1223
+ //#region src/configs/astro.ts
1224
+ async function astro(options = {}) {
1225
+ const { overrides = {}, stylistic: stylistic$1 = true, files = [GLOB_ASTRO] } = options;
1226
+ const [pluginAstro, parserAstro, parserTs] = await Promise.all([
1227
+ interopDefault(import("eslint-plugin-astro")),
1228
+ interopDefault(import("astro-eslint-parser")),
1229
+ interopDefault(import("@typescript-eslint/parser"))
1230
+ ]);
1231
+ return [{
1232
+ name: "whoj/astro/setup",
1233
+ plugins: { astro: pluginAstro }
1234
+ }, {
1235
+ files,
1236
+ name: "whoj/astro/rules",
1237
+ processor: "astro/client-side-ts",
1238
+ languageOptions: {
1239
+ parser: parserAstro,
1240
+ sourceType: "module",
1241
+ globals: pluginAstro.environments.astro.globals,
1242
+ parserOptions: {
1243
+ parser: parserTs,
1244
+ extraFileExtensions: [".astro"]
1245
+ }
1246
+ },
1247
+ rules: {
1248
+ "astro/semi": "off",
1249
+ "astro/valid-compile": "error",
1250
+ "whoj/no-top-level-await": "off",
1251
+ "astro/no-set-html-directive": "off",
1252
+ "astro/no-conflict-set-directives": "error",
1253
+ "astro/no-deprecated-astro-resolve": "error",
1254
+ "astro/no-deprecated-getentrybyslug": "error",
1255
+ "astro/no-unused-define-vars-in-style": "error",
1256
+ "astro/no-deprecated-astro-canonicalurl": "error",
1257
+ "astro/no-deprecated-astro-fetchcontent": "error",
1258
+ "astro/missing-client-only-directive-value": "error",
1259
+ ...stylistic$1 ? {
1260
+ "style/indent": "off",
1261
+ "style/no-multiple-empty-lines": "off",
1262
+ "style/jsx-closing-tag-location": "off",
1263
+ "style/jsx-one-expression-per-line": "off"
1264
+ } : {},
1265
+ ...overrides
1266
+ }
1267
+ }];
1268
+ }
1269
+
1270
+ //#endregion
1271
+ //#region src/configs/jsdoc.ts
1272
+ async function jsdoc(options = {}) {
1273
+ const { stylistic: stylistic$1 = true } = options;
1274
+ return [{
1275
+ files: [GLOB_SRC],
1276
+ name: "whoj/jsdoc/rules",
1277
+ plugins: { jsdoc: await interopDefault(import("eslint-plugin-jsdoc")) },
1278
+ rules: {
1279
+ "jsdoc/empty-tags": "warn",
1280
+ "jsdoc/check-types": "warn",
1281
+ "jsdoc/no-defaults": "warn",
1282
+ "jsdoc/check-access": "warn",
1283
+ "jsdoc/require-property": "warn",
1284
+ "jsdoc/check-param-names": "warn",
1285
+ "jsdoc/no-multi-asterisks": "warn",
1286
+ "jsdoc/require-param-name": "warn",
1287
+ "jsdoc/check-property-names": "warn",
1288
+ "jsdoc/require-yields-check": "warn",
1289
+ "jsdoc/implements-on-classes": "warn",
1290
+ "jsdoc/require-property-name": "warn",
1291
+ "jsdoc/require-returns-check": "warn",
1292
+ "jsdoc/require-returns-description": "warn",
1293
+ "jsdoc/require-property-description": "warn",
1294
+ ...stylistic$1 ? {
1295
+ "jsdoc/check-alignment": "warn",
1296
+ "jsdoc/multiline-blocks": "warn"
1297
+ } : {}
1298
+ }
1299
+ }];
1300
+ }
1301
+
1302
+ //#endregion
1303
+ //#region src/configs/jsonc.ts
1304
+ async function jsonc(options = {}) {
1305
+ const { overrides = {}, stylistic: stylistic$1 = true, files = [
1306
+ GLOB_JSON,
1307
+ GLOB_JSON5,
1308
+ GLOB_JSONC
1309
+ ] } = options;
1310
+ const { indent = 2 } = typeof stylistic$1 === "boolean" ? {} : stylistic$1;
1311
+ const [pluginJsonc, parserJsonc] = await Promise.all([interopDefault(import("eslint-plugin-jsonc")), interopDefault(import("jsonc-eslint-parser"))]);
1312
+ return [{
1313
+ name: "whoj/jsonc/setup",
1314
+ plugins: { jsonc: pluginJsonc }
1315
+ }, {
1316
+ files,
1317
+ name: "whoj/jsonc/rules",
1318
+ languageOptions: { parser: parserJsonc },
1319
+ rules: {
1320
+ "jsonc/no-nan": "error",
1321
+ "jsonc/no-octal": "error",
1322
+ "jsonc/no-infinity": "error",
1323
+ "jsonc/no-dupe-keys": "error",
1324
+ "jsonc/no-multi-str": "error",
1325
+ "jsonc/no-plus-sign": "error",
1326
+ "jsonc/no-number-props": "error",
1327
+ "jsonc/no-octal-escape": "error",
1328
+ "jsonc/space-unary-ops": "error",
1329
+ "jsonc/no-parenthesized": "error",
1330
+ "jsonc/no-sparse-arrays": "error",
1331
+ "jsonc/no-useless-escape": "error",
1332
+ "jsonc/valid-json-number": "error",
1333
+ "jsonc/no-bigint-literals": "error",
1334
+ "jsonc/no-regexp-literals": "error",
1335
+ "jsonc/no-undefined-value": "error",
1336
+ "jsonc/no-floating-decimal": "error",
1337
+ "jsonc/no-binary-expression": "error",
1338
+ "jsonc/no-template-literals": "error",
1339
+ "jsonc/no-numeric-separators": "error",
1340
+ "jsonc/no-octal-numeric-literals": "error",
1341
+ "jsonc/no-binary-numeric-literals": "error",
1342
+ "jsonc/no-unicode-codepoint-escapes": "error",
1343
+ "jsonc/no-hexadecimal-numeric-literals": "error",
1344
+ "jsonc/no-escape-sequence-in-identifier": "error",
1345
+ "jsonc/vue-custom-block/no-parsing-error": "error",
1346
+ ...stylistic$1 ? {
1347
+ "jsonc/quotes": "error",
1348
+ "jsonc/quote-props": "error",
1349
+ "jsonc/comma-style": ["error", "last"],
1350
+ "jsonc/comma-dangle": ["error", "never"],
1351
+ "jsonc/array-bracket-spacing": ["error", "never"],
1352
+ "jsonc/object-curly-spacing": ["error", "always"],
1353
+ "jsonc/key-spacing": ["error", {
1354
+ afterColon: true,
1355
+ beforeColon: false
1356
+ }],
1357
+ "jsonc/object-curly-newline": ["error", {
1358
+ multiline: true,
1359
+ consistent: true
1360
+ }],
1361
+ "jsonc/object-property-newline": ["error", { allowAllPropertiesOnSameLine: true }],
1362
+ "jsonc/indent": ["error", typeof indent === "number" ? indent : indent === "tab" ? "tab" : 2]
1363
+ } : {},
1364
+ ...overrides
1365
+ }
1366
+ }];
1367
+ }
1368
+
1369
+ //#endregion
1370
+ //#region src/configs/react.ts
1371
+ const ReactRefreshAllowConstantExportPackages = ["vite"];
1372
+ const RemixPackages = [
1373
+ "@remix-run/node",
1374
+ "@remix-run/react",
1375
+ "@remix-run/serve",
1376
+ "@remix-run/dev"
1377
+ ];
1378
+ const ReactRouterPackages = [
1379
+ "@react-router/node",
1380
+ "@react-router/react",
1381
+ "@react-router/serve",
1382
+ "@react-router/dev"
1383
+ ];
1384
+ const NextJsPackages = ["next"];
1385
+ const ReactCompilerPackages = ["babel-plugin-react-compiler"];
1386
+ async function react(options = {}) {
1387
+ const { files = [GLOB_SRC], filesTypeAware = [GLOB_TS, GLOB_TSX], ignoresTypeAware = [`${GLOB_MARKDOWN}/**`, GLOB_ASTRO_TS], overrides = {}, tsconfigPath, reactCompiler = ReactCompilerPackages.some((i) => isPackageExists(i)) } = options;
1388
+ await ensurePackages([
1389
+ "@eslint-react/eslint-plugin",
1390
+ "eslint-plugin-react-hooks",
1391
+ "eslint-plugin-react-refresh"
1392
+ ]);
1393
+ const isTypeAware = !!tsconfigPath;
1394
+ const typeAwareRules = {
1395
+ "react/no-leaked-conditional-rendering": "warn",
1396
+ "react/no-implicit-key": "error"
1397
+ };
1398
+ const [pluginReact, pluginReactHooks, pluginReactRefresh] = await Promise.all([
1399
+ interopDefault(import("@eslint-react/eslint-plugin")),
1400
+ interopDefault(import("eslint-plugin-react-hooks")),
1401
+ interopDefault(import("eslint-plugin-react-refresh"))
1402
+ ]);
1403
+ const isAllowConstantExport = ReactRefreshAllowConstantExportPackages.some((i) => isPackageExists(i));
1404
+ const isUsingRemix = RemixPackages.some((i) => isPackageExists(i));
1405
+ const isUsingReactRouter = ReactRouterPackages.some((i) => isPackageExists(i));
1406
+ const isUsingNext = NextJsPackages.some((i) => isPackageExists(i));
1407
+ const plugins = pluginReact.configs.all.plugins;
1408
+ return [
1409
+ {
1410
+ name: "whoj/react/setup",
1411
+ plugins: {
1412
+ "react": plugins["@eslint-react"],
1413
+ "react-dom": plugins["@eslint-react/dom"],
1414
+ "react-hooks": pluginReactHooks,
1415
+ "react-hooks-extra": plugins["@eslint-react/hooks-extra"],
1416
+ "react-naming-convention": plugins["@eslint-react/naming-convention"],
1417
+ "react-refresh": pluginReactRefresh,
1418
+ "react-rsc": plugins["@eslint-react/rsc"],
1419
+ "react-web-api": plugins["@eslint-react/web-api"]
1420
+ }
1421
+ },
1422
+ {
1423
+ files,
1424
+ languageOptions: {
1425
+ parserOptions: { ecmaFeatures: { jsx: true } },
1426
+ sourceType: "module"
1427
+ },
1428
+ name: "whoj/react/rules",
1429
+ rules: {
1430
+ "react/jsx-key-before-spread": "warn",
1431
+ "react/jsx-no-comment-textnodes": "warn",
1432
+ "react/jsx-no-duplicate-props": "warn",
1433
+ "react/jsx-uses-react": "warn",
1434
+ "react/jsx-uses-vars": "warn",
1435
+ "react/no-access-state-in-setstate": "error",
1436
+ "react/no-array-index-key": "warn",
1437
+ "react/no-children-count": "warn",
1438
+ "react/no-children-for-each": "warn",
1439
+ "react/no-children-map": "warn",
1440
+ "react/no-children-only": "warn",
1441
+ "react/no-children-to-array": "warn",
1442
+ "react/no-clone-element": "warn",
1443
+ "react/no-component-will-mount": "error",
1444
+ "react/no-component-will-receive-props": "error",
1445
+ "react/no-component-will-update": "error",
1446
+ "react/no-context-provider": "warn",
1447
+ "react/no-create-ref": "error",
1448
+ "react/no-default-props": "error",
1449
+ "react/no-direct-mutation-state": "error",
1450
+ "react/no-forward-ref": "warn",
1451
+ "react/no-missing-key": "error",
1452
+ "react/no-nested-component-definitions": "error",
1453
+ "react/no-nested-lazy-component-declarations": "error",
1454
+ "react/no-prop-types": "error",
1455
+ "react/no-redundant-should-component-update": "error",
1456
+ "react/no-set-state-in-component-did-mount": "warn",
1457
+ "react/no-set-state-in-component-did-update": "warn",
1458
+ "react/no-set-state-in-component-will-update": "warn",
1459
+ "react/no-string-refs": "error",
1460
+ "react/no-unnecessary-use-prefix": "warn",
1461
+ "react/no-unsafe-component-will-mount": "warn",
1462
+ "react/no-unsafe-component-will-receive-props": "warn",
1463
+ "react/no-unsafe-component-will-update": "warn",
1464
+ "react/no-unused-class-component-members": "warn",
1465
+ "react/no-use-context": "warn",
1466
+ "react/no-useless-forward-ref": "warn",
1467
+ "react/prefer-use-state-lazy-initialization": "warn",
1468
+ "react/prefer-namespace-import": "error",
1469
+ "react-rsc/function-definition": "error",
1470
+ "react-dom/no-dangerously-set-innerhtml": "warn",
1471
+ "react-dom/no-dangerously-set-innerhtml-with-children": "error",
1472
+ "react-dom/no-find-dom-node": "error",
1473
+ "react-dom/no-flush-sync": "error",
1474
+ "react-dom/no-hydrate": "error",
1475
+ "react-dom/no-namespace": "error",
1476
+ "react-dom/no-render": "error",
1477
+ "react-dom/no-render-return-value": "error",
1478
+ "react-dom/no-script-url": "warn",
1479
+ "react-dom/no-unsafe-iframe-sandbox": "warn",
1480
+ "react-dom/no-use-form-state": "error",
1481
+ "react-dom/no-void-elements-with-children": "error",
1482
+ "react-hooks-extra/no-direct-set-state-in-use-effect": "warn",
1483
+ "react-naming-convention/context-name": "warn",
1484
+ "react-naming-convention/ref-name": "warn",
1485
+ "react-naming-convention/use-state": "warn",
1486
+ "react-web-api/no-leaked-event-listener": "warn",
1487
+ "react-web-api/no-leaked-interval": "warn",
1488
+ "react-web-api/no-leaked-resize-observer": "warn",
1489
+ "react-web-api/no-leaked-timeout": "warn",
1490
+ "react-hooks/rules-of-hooks": "error",
1491
+ "react-hooks/exhaustive-deps": "warn",
1492
+ ...reactCompiler ? {
1493
+ "react-hooks/config": "error",
1494
+ "react-hooks/error-boundaries": "error",
1495
+ "react-hooks/component-hook-factories": "error",
1496
+ "react-hooks/gating": "error",
1497
+ "react-hooks/globals": "error",
1498
+ "react-hooks/immutability": "error",
1499
+ "react-hooks/preserve-manual-memoization": "error",
1500
+ "react-hooks/purity": "error",
1501
+ "react-hooks/refs": "error",
1502
+ "react-hooks/set-state-in-effect": "error",
1503
+ "react-hooks/set-state-in-render": "error",
1504
+ "react-hooks/static-components": "error",
1505
+ "react-hooks/unsupported-syntax": "warn",
1506
+ "react-hooks/use-memo": "error",
1507
+ "react-hooks/incompatible-library": "warn"
1508
+ } : {},
1509
+ "react-refresh/only-export-components": ["error", {
1510
+ allowConstantExport: isAllowConstantExport,
1511
+ allowExportNames: [...isUsingNext ? [
1512
+ "dynamic",
1513
+ "dynamicParams",
1514
+ "revalidate",
1515
+ "fetchCache",
1516
+ "runtime",
1517
+ "preferredRegion",
1518
+ "maxDuration",
1519
+ "generateStaticParams",
1520
+ "metadata",
1521
+ "generateMetadata",
1522
+ "viewport",
1523
+ "generateViewport",
1524
+ "generateImageMetadata",
1525
+ "generateSitemaps"
1526
+ ] : [], ...isUsingRemix || isUsingReactRouter ? [
1527
+ "meta",
1528
+ "links",
1529
+ "headers",
1530
+ "loader",
1531
+ "action",
1532
+ "clientLoader",
1533
+ "clientAction",
1534
+ "handle",
1535
+ "shouldRevalidate"
1536
+ ] : []]
1537
+ }],
1538
+ ...overrides
1539
+ }
1540
+ },
1541
+ {
1542
+ files: filesTypeAware,
1543
+ name: "whoj/react/typescript",
1544
+ rules: {
1545
+ "react-dom/no-string-style-prop": "off",
1546
+ "react-dom/no-unknown-property": "off",
1547
+ "react/jsx-no-duplicate-props": "off",
1548
+ "react/jsx-no-undef": "off",
1549
+ "react/jsx-uses-react": "off",
1550
+ "react/jsx-uses-vars": "off"
1551
+ }
1552
+ },
1553
+ ...isTypeAware ? [{
1554
+ files: filesTypeAware,
1555
+ ignores: ignoresTypeAware,
1556
+ name: "whoj/react/type-aware-rules",
1557
+ rules: { ...typeAwareRules }
1558
+ }] : []
1559
+ ];
1560
+ }
1561
+
1562
+ //#endregion
1563
+ //#region src/configs/solid.ts
1564
+ async function solid(options = {}) {
1565
+ const { overrides = {}, typescript: typescript$1 = true, files = [GLOB_JSX, GLOB_TSX] } = options;
1566
+ await ensurePackages(["eslint-plugin-solid"]);
1567
+ const tsconfigPath = options?.tsconfigPath ? toArray(options.tsconfigPath) : void 0;
1568
+ const isTypeAware = !!tsconfigPath;
1569
+ const [pluginSolid, parserTs] = await Promise.all([interopDefault(import("eslint-plugin-solid")), interopDefault(import("@typescript-eslint/parser"))]);
1570
+ return [{
1571
+ name: "whoj/solid/setup",
1572
+ plugins: { solid: pluginSolid }
1573
+ }, {
1574
+ files,
1575
+ name: "whoj/solid/rules",
1576
+ languageOptions: {
1577
+ parser: parserTs,
1578
+ sourceType: "module",
1579
+ parserOptions: {
1580
+ ecmaFeatures: { jsx: true },
1581
+ ...isTypeAware ? { project: tsconfigPath } : {}
1582
+ }
1583
+ },
1584
+ rules: {
1585
+ "solid/imports": "error",
1586
+ "solid/reactivity": "warn",
1587
+ "solid/prefer-for": "error",
1588
+ "solid/jsx-no-undef": "error",
1589
+ "solid/jsx-uses-vars": "error",
1590
+ "solid/no-react-deps": "error",
1591
+ "solid/no-destructure": "error",
1592
+ "solid/jsx-no-script-url": "error",
1593
+ "solid/self-closing-comp": "error",
1594
+ "solid/components-return-once": "warn",
1595
+ "solid/no-unknown-namespaces": "error",
1596
+ "solid/jsx-no-duplicate-props": "error",
1597
+ "solid/no-react-specific-props": "error",
1598
+ "solid/no-innerhtml": ["error", { allowStatic: true }],
1599
+ "solid/style-prop": ["error", { styleProps: ["style", "css"] }],
1600
+ "solid/event-handlers": ["error", {
1601
+ ignoreCase: false,
1602
+ warnOnSpread: false
1603
+ }],
1604
+ ...typescript$1 ? {
1605
+ "solid/no-unknown-namespaces": "off",
1606
+ "solid/jsx-no-undef": ["error", { typescriptEnabled: true }]
1607
+ } : {},
1608
+ ...overrides
1609
+ }
1610
+ }];
1611
+ }
1612
+
1613
+ //#endregion
1614
+ //#region src/configs/nextjs.ts
1615
+ function normalizeRules(rules) {
1616
+ return Object.fromEntries(Object.entries(rules).map(([key, value]) => [key, typeof value === "string" ? [value] : value]));
1617
+ }
1618
+ async function nextjs(options = {}) {
1619
+ const { overrides = {}, files = [GLOB_SRC] } = options;
1620
+ await ensurePackages(["@next/eslint-plugin-next"]);
1621
+ const pluginNextJS = await interopDefault(import("@next/eslint-plugin-next"));
1622
+ function getRules$1(name) {
1623
+ const rules = pluginNextJS.configs?.[name]?.rules;
1624
+ if (!rules) throw new Error(`[@whoj/eslint-config] Failed to find config ${name} in @next/eslint-plugin-next`);
1625
+ return normalizeRules(rules);
1626
+ }
1627
+ return [{
1628
+ name: "whoj/nextjs/setup",
1629
+ plugins: { next: pluginNextJS }
1630
+ }, {
1631
+ files,
1632
+ name: "whoj/nextjs/rules",
1633
+ settings: { react: { version: "detect" } },
1634
+ rules: {
1635
+ ...getRules$1("recommended"),
1636
+ ...getRules$1("core-web-vitals"),
1637
+ ...overrides
1638
+ },
1639
+ languageOptions: {
1640
+ sourceType: "module",
1641
+ parserOptions: { ecmaFeatures: { jsx: true } }
1642
+ }
1643
+ }];
1644
+ }
1645
+
1646
+ //#endregion
1647
+ //#region src/configs/svelte.ts
1648
+ async function svelte(options = {}) {
1649
+ const { overrides = {}, stylistic: stylistic$1 = true, files = [GLOB_SVELTE] } = options;
1650
+ const { indent = 2, quotes = "single" } = typeof stylistic$1 === "boolean" ? {} : stylistic$1;
1651
+ await ensurePackages(["eslint-plugin-svelte"]);
1652
+ const [pluginSvelte, parserSvelte] = await Promise.all([interopDefault(import("eslint-plugin-svelte")), interopDefault(import("svelte-eslint-parser"))]);
1653
+ return [{
1654
+ name: "whoj/svelte/setup",
1655
+ plugins: { svelte: pluginSvelte }
1656
+ }, {
1657
+ files,
1658
+ name: "whoj/svelte/rules",
1659
+ processor: pluginSvelte.processors[".svelte"],
1660
+ languageOptions: {
1661
+ parser: parserSvelte,
1662
+ parserOptions: {
1663
+ extraFileExtensions: [".svelte"],
1664
+ parser: options.typescript ? await interopDefault(import("@typescript-eslint/parser")) : null
1665
+ }
1666
+ },
1667
+ rules: {
1668
+ "no-undef": "off",
1669
+ "svelte/system": "error",
1670
+ "svelte/valid-each-key": "error",
1671
+ "svelte/no-at-debug-tags": "warn",
1672
+ "svelte/no-at-html-tags": "error",
1673
+ "svelte/comment-directive": "error",
1674
+ "svelte/no-reactive-literals": "error",
1675
+ "svelte/no-useless-mustaches": "error",
1676
+ "svelte/no-inner-declarations": "error",
1677
+ "svelte/no-reactive-functions": "error",
1678
+ "svelte/no-dupe-else-if-blocks": "error",
1679
+ "svelte/no-dupe-use-directives": "error",
1680
+ "svelte/no-not-function-handler": "error",
1681
+ "svelte/no-unused-svelte-ignore": "error",
1682
+ "svelte/no-dupe-style-properties": "error",
1683
+ "svelte/no-object-in-text-mustaches": "error",
1684
+ "svelte/no-unknown-style-directive-property": "error",
1685
+ "svelte/no-shorthand-style-property-overrides": "error",
1686
+ "svelte/require-store-callbacks-use-set-param": "error",
1687
+ "svelte/no-export-load-in-svelte-module-in-kit-pages": "error",
1688
+ "no-unused-vars": ["error", {
1689
+ vars: "all",
1690
+ args: "none",
1691
+ caughtErrors: "none",
1692
+ ignoreRestSiblings: true,
1693
+ varsIgnorePattern: "^(\\$\\$Props$|\\$\\$Events$|\\$\\$Slots$)"
1694
+ }],
1695
+ "unused-imports/no-unused-vars": ["error", {
1696
+ vars: "all",
1697
+ args: "after-used",
1698
+ argsIgnorePattern: "^_",
1699
+ varsIgnorePattern: "^(_|\\$\\$Props$|\\$\\$Events$|\\$\\$Slots$)"
1700
+ }],
1701
+ ...stylistic$1 ? {
1702
+ "style/indent": "off",
1703
+ "style/no-trailing-spaces": "off",
1704
+ "svelte/mustache-spacing": "error",
1705
+ "svelte/no-trailing-spaces": "error",
1706
+ "svelte/spaced-html-comment": "error",
1707
+ "svelte/html-closing-bracket-spacing": "error",
1708
+ "svelte/derived-has-same-inputs-outputs": "error",
1709
+ "svelte/no-spaces-around-equal-signs-in-attribute": "error",
1710
+ "svelte/html-quotes": ["error", { prefer: quotes === "backtick" ? "double" : quotes }],
1711
+ "svelte/indent": ["error", {
1712
+ alignAttributesVertically: true,
1713
+ indent: typeof indent === "number" ? indent : indent === "tab" ? "tab" : 2
1714
+ }]
1715
+ } : {},
1716
+ ...overrides
1717
+ }
1718
+ }];
1719
+ }
1720
+
1721
+ //#endregion
1722
+ //#region src/configs/unocss.ts
1723
+ async function unocss(options = {}) {
1724
+ const { strict = false, attributify = true } = options;
1725
+ await ensurePackages(["@unocss/eslint-plugin"]);
1726
+ const [pluginUnoCSS] = await Promise.all([interopDefault(import("@unocss/eslint-plugin"))]);
1727
+ return [{
1728
+ name: "whoj/unocss",
1729
+ plugins: { unocss: pluginUnoCSS },
1730
+ rules: {
1731
+ "unocss/order": "warn",
1732
+ ...attributify ? { "unocss/order-attributify": "warn" } : {},
1733
+ ...strict ? { "unocss/blocklist": "error" } : {}
1734
+ }
1735
+ }];
1736
+ }
1737
+
1738
+ //#endregion
1739
+ //#region src/configs/angular.ts
1740
+ async function angular(options = {}) {
1741
+ const { overrides = {} } = options;
1742
+ await ensurePackages([
1743
+ "@angular-eslint/eslint-plugin",
1744
+ "@angular-eslint/eslint-plugin-template",
1745
+ "@angular-eslint/template-parser"
1746
+ ]);
1747
+ const [pluginAngular, pluginAngularTemplate, parserAngularTemplate] = await Promise.all([
1748
+ interopDefault(import("@angular-eslint/eslint-plugin")),
1749
+ interopDefault(import("@angular-eslint/eslint-plugin-template")),
1750
+ interopDefault(import("@angular-eslint/template-parser"))
1751
+ ]);
1752
+ const angularTsRules = {};
1753
+ const angularTemplateRules = {};
1754
+ Object.entries(overrides).forEach(([key, value]) => {
1755
+ if (key.startsWith("angular/")) angularTsRules[key] = value;
1756
+ if (key.startsWith("angular-template/")) angularTemplateRules[key] = value;
1757
+ });
1758
+ return [
1759
+ {
1760
+ name: "whoj/angular/setup",
1761
+ plugins: {
1762
+ "angular": pluginAngular,
1763
+ "angular-template": pluginAngularTemplate
1764
+ }
1765
+ },
1766
+ {
1767
+ files: [GLOB_TS],
1768
+ name: "whoj/angular/rules/ts",
1769
+ processor: pluginAngularTemplate.processors["extract-inline-html"],
1770
+ rules: {
1771
+ "angular/prefer-inject": "error",
1772
+ "angular/no-input-rename": "error",
1773
+ "angular/no-output-native": "error",
1774
+ "angular/no-output-rename": "error",
1775
+ "angular/prefer-standalone": "error",
1776
+ "angular/no-output-on-prefix": "error",
1777
+ "angular/contextual-lifecycle": "error",
1778
+ "angular/use-lifecycle-interface": "error",
1779
+ "angular/no-empty-lifecycle-method": "error",
1780
+ "angular/no-inputs-metadata-property": "error",
1781
+ "angular/no-outputs-metadata-property": "error",
1782
+ "angular/use-pipe-transform-interface": "error",
1783
+ ...angularTsRules
1784
+ }
1785
+ },
1786
+ {
1787
+ files: [GLOB_HTML],
1788
+ name: "whoj/angular/rules/template",
1789
+ languageOptions: { parser: parserAngularTemplate },
1790
+ rules: {
1791
+ "style/indent": "off",
1792
+ "style/no-trailing-spaces": "off",
1793
+ "angular-template/eqeqeq": "error",
1794
+ "angular-template/banana-in-box": "error",
1795
+ "angular-template/no-negated-async": "error",
1796
+ "angular-template/prefer-control-flow": "error",
1797
+ "style/no-multiple-empty-lines": ["error", { max: 1 }],
1798
+ ...angularTemplateRules
1799
+ }
1800
+ }
1801
+ ];
1802
+ }
1803
+
1804
+ //#endregion
1805
+ //#region src/configs/command.ts
1806
+ async function command() {
1807
+ return [{
1808
+ ...createCommand(),
1809
+ name: "whoj/command/rules"
1810
+ }];
1811
+ }
1812
+
1813
+ //#endregion
1814
+ //#region src/configs/ignores.ts
1815
+ async function ignores(userIgnores = [], ignoreTypeScript = false) {
1816
+ let ignores$1 = [...GLOB_EXCLUDE];
1817
+ if (ignoreTypeScript) ignores$1.push(GLOB_TS, GLOB_TSX);
1818
+ if (typeof userIgnores === "function") ignores$1 = userIgnores(ignores$1);
1819
+ else ignores$1 = [...ignores$1, ...userIgnores];
1820
+ return [{
1821
+ ignores: ignores$1,
1822
+ name: "whoj/ignores"
1823
+ }];
1824
+ }
1825
+
1826
+ //#endregion
1827
+ //#region src/configs/imports.ts
1828
+ async function imports(options = {}) {
1829
+ const { overrides = {}, stylistic: stylistic$1 = true } = options;
1830
+ return [{
1831
+ name: "whoj/imports/rules",
1832
+ plugins: {
1833
+ whoj: pluginAntfu,
1834
+ import: pluginImportLite
1835
+ },
1836
+ rules: {
1837
+ "import/first": "error",
1838
+ "whoj/import-dedupe": "error",
1839
+ "whoj/no-import-dist": "error",
1840
+ "import/no-duplicates": "error",
1841
+ "import/no-named-default": "error",
1842
+ "import/no-mutable-exports": "error",
1843
+ "whoj/no-import-node-modules-by-path": "error",
1844
+ "import/consistent-type-specifier-style": ["error", "top-level"],
1845
+ ...stylistic$1 ? { "import/newline-after-import": ["error", { count: 1 }] } : {},
1846
+ ...overrides
1847
+ }
1848
+ }];
1849
+ }
1850
+
1851
+ //#endregion
1852
+ //#region src/configs/unicorn.ts
1853
+ async function unicorn(options = {}) {
1854
+ const { overrides = {}, allRecommended = false } = options;
1855
+ return [{
1856
+ name: "whoj/unicorn/rules",
1857
+ plugins: { unicorn: pluginUnicorn },
1858
+ rules: {
1859
+ ...allRecommended ? pluginUnicorn.configs.recommended.rules : {
1860
+ "unicorn/escape-case": "error",
1861
+ "unicorn/no-new-array": "error",
1862
+ "unicorn/error-message": "error",
1863
+ "unicorn/no-new-buffer": "error",
1864
+ "unicorn/prefer-includes": "error",
1865
+ "unicorn/throw-new-error": "error",
1866
+ "unicorn/new-for-builtins": "error",
1867
+ "unicorn/prefer-type-error": "error",
1868
+ "unicorn/number-literal-case": "error",
1869
+ "unicorn/prefer-node-protocol": "error",
1870
+ "unicorn/no-instanceof-builtins": "error",
1871
+ "unicorn/prefer-number-properties": "error",
1872
+ "unicorn/prefer-dom-node-text-content": "error",
1873
+ "unicorn/consistent-empty-array-spread": "error",
1874
+ "unicorn/prefer-string-starts-ends-with": "error"
1875
+ },
1876
+ ...overrides
1877
+ }
1878
+ }];
1879
+ }
1880
+
1881
+ //#endregion
1882
+ //#region src/configs/comments.ts
1883
+ async function comments() {
1884
+ return [{
1885
+ name: "whoj/eslint-comments/rules",
1886
+ plugins: { "eslint-comments": pluginComments },
1887
+ rules: {
1888
+ "eslint-comments/no-unused-enable": "error",
1889
+ "eslint-comments/no-duplicate-disable": "error",
1890
+ "eslint-comments/no-unlimited-disable": "error",
1891
+ "eslint-comments/no-aggregating-enable": "error"
1892
+ }
1893
+ }];
1894
+ }
1895
+
1896
+ //#endregion
1897
+ //#region src/configs/disables.ts
1898
+ async function disables() {
1899
+ return [
1900
+ {
1901
+ name: "whoj/disables/scripts",
1902
+ files: [`**/scripts/${GLOB_SRC}`],
1903
+ rules: {
1904
+ "no-console": "off",
1905
+ "whoj/no-top-level-await": "off",
1906
+ "ts/explicit-function-return-type": "off"
1907
+ }
1908
+ },
1909
+ {
1910
+ name: "whoj/disables/cli",
1911
+ files: [`**/cli/${GLOB_SRC}`, `**/cli.${GLOB_SRC_EXT}`],
1912
+ rules: {
1913
+ "no-console": "off",
1914
+ "whoj/no-top-level-await": "off"
1915
+ }
1916
+ },
1917
+ {
1918
+ name: "whoj/disables/bin",
1919
+ files: ["**/bin/**/*", `**/bin.${GLOB_SRC_EXT}`],
1920
+ rules: {
1921
+ "whoj/no-import-dist": "off",
1922
+ "whoj/no-import-node-modules-by-path": "off"
1923
+ }
1924
+ },
1925
+ {
1926
+ name: "whoj/disables/dts",
1927
+ files: ["**/*.d.?([cm])ts"],
1928
+ rules: {
1929
+ "no-restricted-syntax": "off",
1930
+ "unused-imports/no-unused-vars": "off",
1931
+ "eslint-comments/no-unlimited-disable": "off"
1932
+ }
1933
+ },
1934
+ {
1935
+ name: "whoj/disables/cjs",
1936
+ files: ["**/*.js", "**/*.cjs"],
1937
+ rules: { "ts/no-require-imports": "off" }
1938
+ },
1939
+ {
1940
+ name: "whoj/disables/config-files",
1941
+ files: [`**/*.config.${GLOB_SRC_EXT}`, `**/*.config.*.${GLOB_SRC_EXT}`],
1942
+ rules: {
1943
+ "no-console": "off",
1944
+ "whoj/no-top-level-await": "off",
1945
+ "ts/explicit-function-return-type": "off"
1946
+ }
1947
+ }
1948
+ ];
1949
+ }
1950
+
1951
+ //#endregion
1952
+ //#region src/configs/markdown.ts
1953
+ async function markdown(options = {}) {
1954
+ const { overrides = {}, componentExts = [], files = [GLOB_MARKDOWN] } = options;
1955
+ const markdown$1 = await interopDefault(import("@eslint/markdown"));
1956
+ return [
1957
+ {
1958
+ name: "whoj/markdown/setup",
1959
+ plugins: { markdown: markdown$1 }
1960
+ },
1961
+ {
1962
+ files,
1963
+ name: "whoj/markdown/processor",
1964
+ ignores: [GLOB_MARKDOWN_IN_MARKDOWN],
1965
+ processor: mergeProcessors([markdown$1.processors.markdown, processorPassThrough])
1966
+ },
1967
+ {
1968
+ files,
1969
+ name: "whoj/markdown/parser",
1970
+ languageOptions: { parser: parserPlain }
1971
+ },
1972
+ {
1973
+ name: "whoj/markdown/disables",
1974
+ files: [GLOB_MARKDOWN_CODE, ...componentExts.map((ext) => `${GLOB_MARKDOWN}/**/*.${ext}`)],
1975
+ languageOptions: { parserOptions: { ecmaFeatures: { impliedStrict: true } } },
1976
+ rules: {
1977
+ "no-alert": "off",
1978
+ "no-undef": "off",
1979
+ "no-labels": "off",
1980
+ "no-console": "off",
1981
+ "unicode-bom": "off",
1982
+ "no-lone-blocks": "off",
1983
+ "no-unused-vars": "off",
1984
+ "style/eol-last": "off",
1985
+ "ts/no-namespace": "off",
1986
+ "ts/no-redeclare": "off",
1987
+ "no-unused-labels": "off",
1988
+ "ts/no-unused-vars": "off",
1989
+ "style/comma-dangle": "off",
1990
+ "no-restricted-syntax": "off",
1991
+ "no-unused-expressions": "off",
1992
+ "ts/no-require-imports": "off",
1993
+ "ts/no-use-before-define": "off",
1994
+ "whoj/no-top-level-await": "off",
1995
+ "ts/no-unused-expressions": "off",
1996
+ "node/prefer-global/process": "off",
1997
+ "ts/consistent-type-imports": "off",
1998
+ "unused-imports/no-unused-vars": "off",
1999
+ "ts/explicit-function-return-type": "off",
2000
+ "unused-imports/no-unused-imports": "off",
2001
+ "style/padding-line-between-statements": "off",
2002
+ ...overrides
2003
+ }
2004
+ }
2005
+ ];
2006
+ }
2007
+
2008
+ //#endregion
2009
+ //#region src/configs/javascript.ts
2010
+ async function javascript(options = {}) {
2011
+ const { overrides = {}, isInEditor = false } = options;
2012
+ return [{
2013
+ name: "whoj/javascript/setup",
2014
+ linterOptions: { reportUnusedDisableDirectives: true },
2015
+ languageOptions: {
2016
+ sourceType: "module",
2017
+ ecmaVersion: "latest",
2018
+ parserOptions: {
2019
+ sourceType: "module",
2020
+ ecmaVersion: "latest",
2021
+ ecmaFeatures: { jsx: true }
2022
+ },
2023
+ globals: {
2024
+ ...globals.browser,
2025
+ ...globals.es2021,
2026
+ ...globals.node,
2027
+ window: "readonly",
2028
+ document: "readonly",
2029
+ navigator: "readonly"
2030
+ }
2031
+ }
2032
+ }, {
2033
+ name: "whoj/javascript/rules",
2034
+ plugins: {
2035
+ "whoj": pluginAntfu,
2036
+ "unused-imports": pluginUnusedImports
2037
+ },
2038
+ rules: {
2039
+ "no-new": "error",
2040
+ "no-var": "error",
2041
+ "no-eval": "error",
2042
+ "no-with": "error",
2043
+ "no-alert": "error",
2044
+ "no-octal": "error",
2045
+ "no-proto": "error",
2046
+ "no-undef": "error",
2047
+ "no-caller": "error",
2048
+ "no-debugger": "error",
2049
+ "no-iterator": "error",
2050
+ "no-new-func": "error",
2051
+ "vars-on-top": "error",
2052
+ "no-dupe-args": "error",
2053
+ "no-dupe-keys": "error",
2054
+ "no-ex-assign": "error",
2055
+ "no-multi-str": "error",
2056
+ "no-obj-calls": "error",
2057
+ "no-sequences": "error",
2058
+ "no-delete-var": "error",
2059
+ "no-extra-bind": "error",
2060
+ "no-undef-init": "error",
2061
+ "prefer-spread": "error",
2062
+ "no-fallthrough": "error",
2063
+ "no-func-assign": "error",
2064
+ "no-lone-blocks": "error",
2065
+ "no-unreachable": "error",
2066
+ "no-class-assign": "error",
2067
+ "no-const-assign": "error",
2068
+ "no-implied-eval": "error",
2069
+ "no-new-wrappers": "error",
2070
+ "no-octal-escape": "error",
2071
+ "no-regex-spaces": "error",
2072
+ "no-self-compare": "error",
2073
+ "no-useless-call": "error",
2074
+ "prefer-template": "error",
2075
+ "yoda": ["error", "never"],
2076
+ "block-scoped-var": "error",
2077
+ "no-control-regex": "error",
2078
+ "no-empty-pattern": "error",
2079
+ "no-extend-native": "error",
2080
+ "no-global-assign": "error",
2081
+ "no-import-assign": "error",
2082
+ "no-sparse-arrays": "error",
2083
+ "no-throw-literal": "error",
2084
+ "no-useless-catch": "error",
2085
+ "constructor-super": "error",
2086
+ "default-case-last": "error",
2087
+ "eqeqeq": ["error", "smart"],
2088
+ "no-duplicate-case": "error",
2089
+ "no-invalid-regexp": "error",
2090
+ "no-unsafe-finally": "error",
2091
+ "no-useless-rename": "error",
2092
+ "no-useless-return": "error",
2093
+ "no-unsafe-negation": "error",
2094
+ "prefer-rest-params": "error",
2095
+ "symbol-description": "error",
2096
+ "no-compare-neg-zero": "error",
2097
+ "no-unreachable-loop": "error",
2098
+ "no-array-constructor": "error",
2099
+ "no-case-declarations": "error",
2100
+ "no-loss-of-precision": "error",
2101
+ "no-this-before-super": "error",
2102
+ "array-callback-return": "error",
2103
+ "no-dupe-class-members": "error",
2104
+ "no-extra-boolean-cast": "error",
2105
+ "no-prototype-builtins": "error",
2106
+ "no-useless-constructor": "error",
2107
+ "unicode-bom": ["error", "never"],
2108
+ "no-irregular-whitespace": "error",
2109
+ "no-unexpected-multiline": "error",
2110
+ "no-useless-computed-key": "error",
2111
+ "whoj/no-top-level-await": "error",
2112
+ "no-empty-character-class": "error",
2113
+ "no-useless-backreference": "error",
2114
+ "no-async-promise-executor": "error",
2115
+ "no-cond-assign": ["error", "always"],
2116
+ "no-shadow-restricted-names": "error",
2117
+ "no-template-curly-in-string": "error",
2118
+ "no-new-native-nonconstructor": "error",
2119
+ "no-unmodified-loop-condition": "error",
2120
+ "prefer-promise-reject-errors": "error",
2121
+ "no-misleading-character-class": "error",
2122
+ "prefer-exponentiation-operator": "error",
2123
+ "no-self-assign": ["error", { props: true }],
2124
+ "one-var": ["error", { initialized: "never" }],
2125
+ "no-empty": ["error", { allowEmptyCatch: true }],
2126
+ "dot-notation": ["error", { allowKeywords: true }],
2127
+ "no-redeclare": ["error", { builtinGlobals: false }],
2128
+ "no-console": ["error", { allow: ["warn", "error"] }],
2129
+ "valid-typeof": ["error", { requireStringLiterals: true }],
2130
+ "no-unneeded-ternary": ["error", { defaultAssignment: false }],
2131
+ "no-labels": ["error", {
2132
+ allowLoop: false,
2133
+ allowSwitch: false
2134
+ }],
2135
+ "unused-imports/no-unused-imports": isInEditor ? "warn" : "error",
2136
+ "prefer-regex-literals": ["error", { disallowRedundantWrapping: true }],
2137
+ "new-cap": ["error", {
2138
+ newIsCap: true,
2139
+ capIsNew: false,
2140
+ properties: true
2141
+ }],
2142
+ "use-isnan": ["error", {
2143
+ enforceForIndexOf: true,
2144
+ enforceForSwitchCase: true
2145
+ }],
2146
+ "accessor-pairs": ["error", {
2147
+ setWithoutGet: true,
2148
+ enforceForClassMembers: true
2149
+ }],
2150
+ "no-use-before-define": ["error", {
2151
+ classes: false,
2152
+ variables: true,
2153
+ functions: false
2154
+ }],
2155
+ "no-restricted-syntax": [
2156
+ "error",
2157
+ "TSEnumDeclaration[const=true]",
2158
+ "TSExportAssignment"
2159
+ ],
2160
+ "no-unused-expressions": ["error", {
2161
+ allowTernary: true,
2162
+ allowShortCircuit: true,
2163
+ allowTaggedTemplates: true
2164
+ }],
2165
+ "no-unused-vars": ["error", {
2166
+ vars: "all",
2167
+ args: "none",
2168
+ caughtErrors: "none",
2169
+ ignoreRestSiblings: true
2170
+ }],
2171
+ "prefer-arrow-callback": ["error", {
2172
+ allowUnboundThis: true,
2173
+ allowNamedFunctions: false
2174
+ }],
2175
+ "object-shorthand": [
2176
+ "error",
2177
+ "always",
2178
+ {
2179
+ avoidQuotes: true,
2180
+ ignoreConstructors: false
2181
+ }
2182
+ ],
2183
+ "prefer-const": [isInEditor ? "warn" : "error", {
2184
+ destructuring: "all",
2185
+ ignoreReadBeforeAssign: true
2186
+ }],
2187
+ "no-restricted-globals": [
2188
+ "error",
2189
+ {
2190
+ name: "global",
2191
+ message: "Use `globalThis` instead."
2192
+ },
2193
+ {
2194
+ name: "self",
2195
+ message: "Use `globalThis` instead."
2196
+ }
2197
+ ],
2198
+ "unused-imports/no-unused-vars": ["error", {
2199
+ vars: "all",
2200
+ args: "after-used",
2201
+ argsIgnorePattern: "^_",
2202
+ varsIgnorePattern: "^_",
2203
+ ignoreRestSiblings: true
2204
+ }],
2205
+ "no-restricted-properties": [
2206
+ "error",
2207
+ {
2208
+ property: "__proto__",
2209
+ message: "Use `Object.getPrototypeOf` or `Object.setPrototypeOf` instead."
2210
+ },
2211
+ {
2212
+ property: "__defineGetter__",
2213
+ message: "Use `Object.defineProperty` instead."
2214
+ },
2215
+ {
2216
+ property: "__defineSetter__",
2217
+ message: "Use `Object.defineProperty` instead."
2218
+ },
2219
+ {
2220
+ property: "__lookupGetter__",
2221
+ message: "Use `Object.getOwnPropertyDescriptor` instead."
2222
+ },
2223
+ {
2224
+ property: "__lookupSetter__",
2225
+ message: "Use `Object.getOwnPropertyDescriptor` instead."
2226
+ }
2227
+ ],
2228
+ ...overrides
2229
+ }
2230
+ }];
2231
+ }
2232
+
2233
+ //#endregion
2234
+ //#region src/configs/typescript.ts
2235
+ async function typescript(options = {}) {
2236
+ const { type = "app", overrides = {}, componentExts = [], parserOptions = {}, erasableOnly = false, overridesTypeAware = {} } = options;
2237
+ const files = options.files ?? [
2238
+ GLOB_TS,
2239
+ GLOB_TSX,
2240
+ ...componentExts.map((ext) => `**/*.${ext}`)
2241
+ ];
2242
+ const filesTypeAware = options.filesTypeAware ?? [GLOB_TS, GLOB_TSX];
2243
+ const ignoresTypeAware = options.ignoresTypeAware ?? [`${GLOB_MARKDOWN}/**`, GLOB_ASTRO_TS];
2244
+ const tsconfigPath = options?.tsconfigPath ? options.tsconfigPath : void 0;
2245
+ const isTypeAware = !!tsconfigPath;
2246
+ const typeAwareRules = {
2247
+ "dot-notation": "off",
2248
+ "no-implied-eval": "off",
2249
+ "ts/await-thenable": "error",
2250
+ "ts/no-unsafe-call": "error",
2251
+ "ts/unbound-method": "error",
2252
+ "ts/no-for-in-array": "error",
2253
+ "ts/no-implied-eval": "error",
2254
+ "ts/no-unsafe-return": "error",
2255
+ "ts/no-unsafe-argument": "error",
2256
+ "ts/no-misused-promises": "error",
2257
+ "ts/no-floating-promises": "error",
2258
+ "ts/no-unsafe-assignment": "error",
2259
+ "ts/promise-function-async": "error",
2260
+ "ts/restrict-plus-operands": "error",
2261
+ "ts/no-unsafe-member-access": "error",
2262
+ "ts/switch-exhaustiveness-check": "error",
2263
+ "ts/no-unnecessary-type-assertion": "error",
2264
+ "ts/restrict-template-expressions": "error",
2265
+ "ts/return-await": ["error", "in-try-catch"],
2266
+ "ts/dot-notation": ["error", { allowKeywords: true }],
2267
+ "ts/strict-boolean-expressions": ["error", {
2268
+ allowNullableObject: true,
2269
+ allowNullableBoolean: true
2270
+ }]
2271
+ };
2272
+ const [pluginTs, parserTs] = await Promise.all([interopDefault(import("@typescript-eslint/eslint-plugin")), interopDefault(import("@typescript-eslint/parser"))]);
2273
+ function makeParser(typeAware, files$1, ignores$1) {
2274
+ return {
2275
+ files: files$1,
2276
+ ...ignores$1 ? { ignores: ignores$1 } : {},
2277
+ name: `whoj/typescript/${typeAware ? "type-aware-parser" : "parser"}`,
2278
+ languageOptions: {
2279
+ parser: parserTs,
2280
+ parserOptions: {
2281
+ sourceType: "module",
2282
+ extraFileExtensions: componentExts.map((ext) => `.${ext}`),
2283
+ ...typeAware ? {
2284
+ tsconfigRootDir: process.cwd(),
2285
+ projectService: {
2286
+ defaultProject: tsconfigPath,
2287
+ allowDefaultProject: ["./*.js"]
2288
+ }
2289
+ } : {},
2290
+ ...parserOptions
2291
+ }
2292
+ }
2293
+ };
2294
+ }
2295
+ return [
2296
+ {
2297
+ name: "whoj/typescript/setup",
2298
+ plugins: {
2299
+ whoj: pluginAntfu,
2300
+ ts: pluginTs
2301
+ }
2302
+ },
2303
+ ...isTypeAware ? [makeParser(false, files), makeParser(true, filesTypeAware, ignoresTypeAware)] : [makeParser(false, files)],
2304
+ {
2305
+ files,
2306
+ name: "whoj/typescript/rules",
2307
+ rules: {
2308
+ ...renameRules(pluginTs.configs["eslint-recommended"].overrides[0].rules, { "@typescript-eslint": "ts" }),
2309
+ ...renameRules(pluginTs.configs.strict.rules, { "@typescript-eslint": "ts" }),
2310
+ "no-redeclare": "off",
2311
+ "ts/no-unused-vars": "off",
2312
+ "ts/no-explicit-any": "off",
2313
+ "no-use-before-define": "off",
2314
+ "ts/no-dynamic-delete": "off",
2315
+ "no-dupe-class-members": "off",
2316
+ "ts/unified-signatures": "off",
2317
+ "no-useless-constructor": "off",
2318
+ "ts/no-extraneous-class": "off",
2319
+ "ts/no-invalid-void-type": "off",
2320
+ "ts/no-require-imports": "error",
2321
+ "ts/no-non-null-assertion": "off",
2322
+ "ts/no-useless-constructor": "off",
2323
+ "ts/triple-slash-reference": "off",
2324
+ "ts/no-dupe-class-members": "error",
2325
+ "ts/no-wrapper-object-types": "error",
2326
+ "ts/no-import-type-side-effects": "error",
2327
+ "ts/method-signature-style": ["error", "property"],
2328
+ "ts/no-redeclare": ["error", { builtinGlobals: false }],
2329
+ "ts/consistent-type-definitions": ["error", "interface"],
2330
+ "ts/no-empty-object-type": ["error", { allowInterfaces: "always" }],
2331
+ "ts/ban-ts-comment": ["error", { "ts-expect-error": "allow-with-description" }],
2332
+ "ts/no-use-before-define": ["error", {
2333
+ classes: false,
2334
+ variables: true,
2335
+ functions: false
2336
+ }],
2337
+ "ts/no-unused-expressions": ["error", {
2338
+ allowTernary: true,
2339
+ allowShortCircuit: true,
2340
+ allowTaggedTemplates: true
2341
+ }],
2342
+ "ts/consistent-type-imports": ["error", {
2343
+ prefer: "type-imports",
2344
+ disallowTypeAnnotations: false,
2345
+ fixStyle: "separate-type-imports"
2346
+ }],
2347
+ ...type === "lib" ? { "ts/explicit-function-return-type": ["error", {
2348
+ allowIIFEs: true,
2349
+ allowExpressions: true,
2350
+ allowHigherOrderFunctions: true
2351
+ }] } : {},
2352
+ ...overrides
2353
+ }
2354
+ },
2355
+ ...isTypeAware ? [{
2356
+ files: filesTypeAware,
2357
+ ignores: ignoresTypeAware,
2358
+ name: "whoj/typescript/rules-type-aware",
2359
+ rules: {
2360
+ ...typeAwareRules,
2361
+ ...overridesTypeAware
2362
+ }
2363
+ }] : [],
2364
+ ...erasableOnly ? [{
2365
+ name: "whoj/typescript/erasable-syntax-only",
2366
+ plugins: { "erasable-syntax-only": await interopDefault(import("./lib-DRA-mDV0.mjs")) },
2367
+ rules: {
2368
+ "erasable-syntax-only/enums": "error",
2369
+ "erasable-syntax-only/namespaces": "error",
2370
+ "erasable-syntax-only/import-aliases": "error",
2371
+ "erasable-syntax-only/parameter-properties": "error"
2372
+ }
2373
+ }] : []
2374
+ ];
2375
+ }
2376
+
2377
+ //#endregion
2378
+ //#region src/configs/perfectionist.ts
2379
+ const LINE_LENGTH_REGEX = /.*(?<!classes|heritage-clauses|intersection-types|interfaces|modules|objects)$/;
2380
+ /**
2381
+ * Perfectionist plugin for props and items sorting.
2382
+ *
2383
+ * @see https://github.com/azat-io/eslint-plugin-perfectionist
2384
+ */
2385
+ async function perfectionist() {
2386
+ return [{
2387
+ name: "whoj/perfectionist/setup",
2388
+ plugins: { perfectionist: pluginPerfectionist },
2389
+ rules: {
2390
+ ...getRules({
2391
+ order: "asc",
2392
+ type: "natural"
2393
+ }),
2394
+ ...getRules({
2395
+ order: "asc",
2396
+ type: "line-length"
2397
+ })
2398
+ }
2399
+ }];
2400
+ }
2401
+ function getRules(options) {
2402
+ return Object.fromEntries(Object.keys({ ...pluginPerfectionist.rules }).filter((ruleName) => options.type === "natural" ? !LINE_LENGTH_REGEX.test(ruleName) && !ruleName.endsWith("sort-modules") : LINE_LENGTH_REGEX.test(ruleName)).map((ruleName) => [`perfectionist/${ruleName}`, ["error", options]]));
2403
+ }
2404
+
2405
+ //#endregion
2406
+ //#region src/factory.ts
2407
+ const flatConfigProps = [
2408
+ "name",
2409
+ "languageOptions",
2410
+ "linterOptions",
2411
+ "processor",
2412
+ "plugins",
2413
+ "rules",
2414
+ "settings"
2415
+ ];
2416
+ const VuePackages = [
2417
+ "vue",
2418
+ "nuxt",
2419
+ "vitepress",
2420
+ "@slidev/cli"
2421
+ ];
2422
+ const defaultPluginRenaming = {
2423
+ "n": "node",
2424
+ "yml": "yaml",
2425
+ "vitest": "test",
2426
+ "@next/next": "next",
2427
+ "@stylistic": "style",
2428
+ "import-lite": "import",
2429
+ "@eslint-react": "react",
2430
+ "@typescript-eslint": "ts",
2431
+ "@eslint-react/dom": "react-dom",
2432
+ "@eslint-react/hooks-extra": "react-hooks-extra",
2433
+ "@eslint-react/naming-convention": "react-naming-convention"
2434
+ };
2435
+ /**
2436
+ * Construct an array of ESLint flat config items.
2437
+ *
2438
+ * @param {OptionsConfig & TypedFlatConfigItem} options
2439
+ * The options for generating the ESLint configurations.
2440
+ * @param {Awaitable<TypedFlatConfigItem | TypedFlatConfigItem[]>[]} userConfigs
2441
+ * The user configurations to be merged with the generated configurations.
2442
+ * @returns {Promise<TypedFlatConfigItem[]>}
2443
+ * The merged ESLint configurations.
2444
+ */
2445
+ function whoj(options = {}, ...userConfigs) {
2446
+ const { componentExts = [], jsx: enableJsx = true, node: enableNode = true, autoRenamePlugins = true, ignores: userIgnores = [], jsdoc: enableJsdoc = true, astro: enableAstro = false, react: enableReact = false, solid: enableSolid = false, regexp: enableRegexp = true, nextjs: enableNextjs = false, svelte: enableSvelte = false, unocss: enableUnoCSS = false, imports: enableImports = true, unicorn: enableUnicorn = true, angular: enableAngular = false, gitignore: enableGitignore = true, pnpm: enableCatalogs = !!findUpSync("pnpm-workspace.yaml"), vue: enableVue = VuePackages.some((i) => isPackageExists(i)), typescript: enableTypeScript = isPackageExists("typescript") } = options;
2447
+ let isInEditor = options.isInEditor;
2448
+ if (isInEditor == null) {
2449
+ isInEditor = isInEditorEnv();
2450
+ if (isInEditor) console.log("[@whoj/eslint-config] Detected running in editor, some rules are disabled.");
2451
+ }
2452
+ const stylisticOptions = options.stylistic === false ? false : typeof options.stylistic === "object" ? options.stylistic : {};
2453
+ if (stylisticOptions && !("jsx" in stylisticOptions)) stylisticOptions.jsx = typeof enableJsx === "object" ? true : enableJsx;
2454
+ const configs$1 = [];
2455
+ if (enableGitignore) if (typeof enableGitignore !== "boolean") configs$1.push(interopDefault(import("eslint-config-flat-gitignore")).then((r) => [r({
2456
+ name: "whoj/gitignore",
2457
+ ...enableGitignore
2458
+ })]));
2459
+ else configs$1.push(interopDefault(import("eslint-config-flat-gitignore")).then((r) => [r({
2460
+ strict: false,
2461
+ name: "whoj/gitignore"
2462
+ })]));
2463
+ const typescriptOptions = resolveSubOptions(options, "typescript");
2464
+ const tsconfigPath = "tsconfigPath" in typescriptOptions ? typescriptOptions.tsconfigPath : void 0;
2465
+ configs$1.push(ignores(userIgnores, !enableTypeScript), javascript({
2466
+ isInEditor,
2467
+ overrides: getOverrides(options, "javascript")
2468
+ }), comments(), command(), perfectionist());
2469
+ if (enableNode) configs$1.push(node());
2470
+ if (enableJsdoc) configs$1.push(jsdoc({ stylistic: stylisticOptions }));
2471
+ if (enableImports) configs$1.push(imports({
2472
+ stylistic: stylisticOptions,
2473
+ ...resolveSubOptions(options, "imports")
2474
+ }));
2475
+ if (enableUnicorn) configs$1.push(unicorn(enableUnicorn === true ? {} : enableUnicorn));
2476
+ if (enableVue) componentExts.push("vue");
2477
+ if (enableJsx) configs$1.push(jsx(enableJsx === true ? {} : enableJsx));
2478
+ if (enableTypeScript) configs$1.push(typescript({
2479
+ ...typescriptOptions,
2480
+ componentExts,
2481
+ type: options.type,
2482
+ overrides: getOverrides(options, "typescript")
2483
+ }));
2484
+ if (stylisticOptions) configs$1.push(stylistic({
2485
+ ...stylisticOptions,
2486
+ lessOpinionated: options.lessOpinionated,
2487
+ overrides: {
2488
+ "style/semi": [2, "always"],
2489
+ "style/spaced-comment": "off",
2490
+ "style/quotes": ["error", "single"],
2491
+ "style/comma-dangle": ["error", "never"],
2492
+ ...getOverrides(options, "stylistic")
2493
+ }
2494
+ }));
2495
+ if (enableRegexp) configs$1.push(regexp(typeof enableRegexp === "boolean" ? {} : enableRegexp));
2496
+ if (options.test ?? true) configs$1.push(test({
2497
+ isInEditor,
2498
+ overrides: getOverrides(options, "test")
2499
+ }));
2500
+ if (enableVue) configs$1.push(vue({
2501
+ ...resolveSubOptions(options, "vue"),
2502
+ stylistic: stylisticOptions,
2503
+ typescript: !!enableTypeScript,
2504
+ overrides: getOverrides(options, "vue")
2505
+ }));
2506
+ if (enableReact) configs$1.push(react({
2507
+ ...typescriptOptions,
2508
+ ...resolveSubOptions(options, "react"),
2509
+ tsconfigPath,
2510
+ overrides: getOverrides(options, "react")
2511
+ }));
2512
+ if (enableNextjs) configs$1.push(nextjs({ overrides: getOverrides(options, "nextjs") }));
2513
+ if (enableSolid) configs$1.push(solid({
2514
+ tsconfigPath,
2515
+ typescript: !!enableTypeScript,
2516
+ overrides: getOverrides(options, "solid")
2517
+ }));
2518
+ if (enableSvelte) configs$1.push(svelte({
2519
+ stylistic: stylisticOptions,
2520
+ typescript: !!enableTypeScript,
2521
+ overrides: getOverrides(options, "svelte")
2522
+ }));
2523
+ if (enableUnoCSS) configs$1.push(unocss({
2524
+ ...resolveSubOptions(options, "unocss"),
2525
+ overrides: getOverrides(options, "unocss")
2526
+ }));
2527
+ if (enableAstro) configs$1.push(astro({
2528
+ stylistic: stylisticOptions,
2529
+ overrides: getOverrides(options, "astro")
2530
+ }));
2531
+ if (enableAngular) configs$1.push(angular({ overrides: getOverrides(options, "angular") }));
2532
+ if (options.jsonc ?? true) configs$1.push(jsonc({
2533
+ stylistic: stylisticOptions,
2534
+ overrides: getOverrides(options, "jsonc")
2535
+ }), sortPackageJson(), sortTsconfig());
2536
+ if (enableCatalogs) {
2537
+ const optionsPnpm = resolveSubOptions(options, "pnpm");
2538
+ configs$1.push(pnpm({
2539
+ isInEditor,
2540
+ yaml: options.yaml !== false,
2541
+ json: options.jsonc !== false,
2542
+ ...optionsPnpm
2543
+ }));
2544
+ }
2545
+ if (options.yaml ?? true) configs$1.push(yaml({
2546
+ stylistic: stylisticOptions,
2547
+ overrides: getOverrides(options, "yaml")
2548
+ }));
2549
+ if (options.toml ?? true) configs$1.push(toml({
2550
+ stylistic: stylisticOptions,
2551
+ overrides: getOverrides(options, "toml")
2552
+ }));
2553
+ if (options.markdown ?? true) configs$1.push(markdown({
2554
+ componentExts,
2555
+ overrides: getOverrides(options, "markdown")
2556
+ }));
2557
+ if (options.formatters) configs$1.push(formatters(options.formatters, typeof stylisticOptions === "boolean" ? {} : stylisticOptions));
2558
+ configs$1.push(disables());
2559
+ configs$1.push([{ rules: {
2560
+ "eqeqeq": "warn",
2561
+ "require-await": "off",
2562
+ "no-useless-escape": "warn"
2563
+ } }]);
2564
+ if ("files" in options) throw new Error("[@whoj/eslint-config] The first argument should not contain the \"files\" property as the options are supposed to be global. Place it in the second or later config instead.");
2565
+ const fusedConfig = flatConfigProps.reduce((acc, key) => {
2566
+ if (key in options) acc[key] = options[key];
2567
+ return acc;
2568
+ }, {});
2569
+ if (Object.keys(fusedConfig).length) configs$1.push([fusedConfig]);
2570
+ let composer = new FlatConfigComposer();
2571
+ composer = composer.append(...configs$1, ...userConfigs);
2572
+ if (autoRenamePlugins) composer = composer.renamePlugins(defaultPluginRenaming);
2573
+ if (isInEditor) composer = composer.disableRulesFix([
2574
+ "unused-imports/no-unused-imports",
2575
+ "test/no-only-tests",
2576
+ "prefer-const"
2577
+ ], { builtinRules: () => import(["eslint", "use-at-your-own-risk"].join("/")).then((r) => r.builtinRules) });
2578
+ return composer;
2579
+ }
2580
+ function resolveSubOptions(options, key) {
2581
+ return typeof options[key] === "boolean" ? {} : options[key] || {};
2582
+ }
2583
+ function getOverrides(options, key) {
2584
+ const sub = resolveSubOptions(options, key);
2585
+ return {
2586
+ ...options.overrides?.[key],
2587
+ ..."overrides" in sub ? sub.overrides : {}
2588
+ };
2589
+ }
2590
+
2591
+ //#endregion
2592
+ //#region src/config-presets.ts
2593
+ const CONFIG_PRESET_FULL_ON = {
2594
+ node: true,
2595
+ pnpm: true,
2596
+ test: true,
2597
+ toml: true,
2598
+ yaml: true,
2599
+ astro: true,
2600
+ jsdoc: true,
2601
+ jsonc: true,
2602
+ solid: true,
2603
+ nextjs: true,
2604
+ regexp: true,
2605
+ svelte: true,
2606
+ unocss: true,
2607
+ angular: true,
2608
+ imports: true,
2609
+ unicorn: true,
2610
+ markdown: true,
2611
+ gitignore: true,
2612
+ formatters: true,
2613
+ jsx: { a11y: true },
2614
+ vue: { a11y: true },
2615
+ react: { reactCompiler: true },
2616
+ stylistic: { experimental: true },
2617
+ typescript: {
2618
+ erasableOnly: true,
2619
+ tsconfigPath: "tsconfig.json"
2620
+ }
2621
+ };
2622
+ const CONFIG_PRESET_FULL_OFF = {
2623
+ jsx: false,
2624
+ vue: false,
2625
+ node: false,
2626
+ pnpm: false,
2627
+ test: false,
2628
+ toml: false,
2629
+ yaml: false,
2630
+ astro: false,
2631
+ jsdoc: false,
2632
+ jsonc: false,
2633
+ react: false,
2634
+ solid: false,
2635
+ nextjs: false,
2636
+ regexp: false,
2637
+ svelte: false,
2638
+ unocss: false,
2639
+ angular: false,
2640
+ imports: false,
2641
+ unicorn: false,
2642
+ markdown: false,
2643
+ gitignore: false,
2644
+ stylistic: false,
2645
+ formatters: false,
2646
+ typescript: false
2647
+ };
2648
+
2649
+ //#endregion
2650
+ //#region src/index.ts
2651
+ var src_default = whoj;
2652
+
2653
+ //#endregion
2654
+ export { CONFIG_PRESET_FULL_OFF, CONFIG_PRESET_FULL_ON, GLOB_ALL_SRC, GLOB_ASTRO, GLOB_ASTRO_TS, GLOB_CSS, GLOB_EXCLUDE, GLOB_GRAPHQL, GLOB_HTML, GLOB_JS, GLOB_JSON, GLOB_JSON5, GLOB_JSONC, GLOB_JSX, GLOB_LESS, GLOB_MARKDOWN, GLOB_MARKDOWN_CODE, GLOB_MARKDOWN_IN_MARKDOWN, GLOB_POSTCSS, GLOB_SCSS, GLOB_SRC, GLOB_SRC_EXT, GLOB_STYLE, GLOB_SVELTE, GLOB_SVG, GLOB_TESTS, GLOB_TOML, GLOB_TS, GLOB_TSX, GLOB_VUE, GLOB_XML, GLOB_YAML, StylisticConfigDefaults, angular, astro, combine, command, comments, src_default as default, defaultPluginRenaming, disables, ensurePackages, formatters, getOverrides, ignores, imports, interopDefault, isInEditorEnv, isInGitHooksOrLintStaged, isPackageInScope, javascript, jsdoc, jsonc, jsx, markdown, nextjs, node, parserPlain, perfectionist, pnpm, react, regexp, renamePluginInConfigs, renameRules, resolveSubOptions, solid, sortPackageJson, sortTsconfig, stylistic, svelte, test, toArray, toml, typescript, unicorn, unocss, vue, whoj, yaml };