@whoj/eslint-config 7.5.2 → 9.2.0

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 CHANGED
@@ -1,22 +1,22 @@
1
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";
2
+ import fs from "node:fs";
5
3
  import path from "node:path";
4
+ import fsp from "node:fs/promises";
5
+ import { fileURLToPath } from "node:url";
6
6
  import { isPackageExists } from "local-pkg";
7
7
  import { FlatConfigComposer } from "eslint-flat-config-utils";
8
- import { configs } from "eslint-plugin-regexp";
9
8
  import pluginNode from "eslint-plugin-n";
9
+ import pluginE18e from "@e18e/eslint-plugin";
10
10
  import pluginAntfu from "eslint-plugin-antfu";
11
11
  import pluginUnicorn from "eslint-plugin-unicorn";
12
12
  import pluginImportLite from "eslint-plugin-import-lite";
13
13
  import pluginPerfectionist from "eslint-plugin-perfectionist";
14
14
  import pluginUnusedImports from "eslint-plugin-unused-imports";
15
15
  import pluginComments from "@eslint-community/eslint-plugin-eslint-comments";
16
+ import { configs } from "eslint-plugin-regexp";
16
17
  import { mergeProcessors, processorPassThrough } from "eslint-merge-processors";
17
18
  import createCommand from "eslint-plugin-command/config";
18
19
  import globals from "globals";
19
-
20
20
  //#region node_modules/.pnpm/find-up-simple@1.0.1/node_modules/find-up-simple/index.js
21
21
  const toPath = (urlOrPath) => urlOrPath instanceof URL ? fileURLToPath(urlOrPath) : urlOrPath;
22
22
  async function findUp(name, { cwd = process.cwd(), type = "file", stopAt } = {}) {
@@ -27,7 +27,7 @@ async function findUp(name, { cwd = process.cwd(), type = "file", stopAt } = {})
27
27
  while (directory) {
28
28
  const filePath = isAbsoluteName ? name : path.join(directory, name);
29
29
  try {
30
- const stats = await fs.stat(filePath);
30
+ const stats = await fsp.stat(filePath);
31
31
  if (type === "file" && stats.isFile() || type === "directory" && stats.isDirectory()) return filePath;
32
32
  } catch {}
33
33
  if (directory === stopAt || directory === root) break;
@@ -42,14 +42,121 @@ function findUpSync(name, { cwd = process.cwd(), type = "file", stopAt } = {}) {
42
42
  while (directory) {
43
43
  const filePath = isAbsoluteName ? name : path.join(directory, name);
44
44
  try {
45
- const stats = fs$1.statSync(filePath, { throwIfNoEntry: false });
45
+ const stats = fs.statSync(filePath, { throwIfNoEntry: false });
46
46
  if (type === "file" && stats?.isFile() || type === "directory" && stats?.isDirectory()) return filePath;
47
47
  } catch {}
48
48
  if (directory === stopAt || directory === root) break;
49
49
  directory = path.dirname(directory);
50
50
  }
51
51
  }
52
-
52
+ //#endregion
53
+ //#region src/configs/e18e.ts
54
+ async function e18e(options = {}) {
55
+ const { type = "app", overrides = {}, isInEditor = false, modernization = true, performanceImprovements = true, moduleReplacements = type === "lib" && isInEditor } = options;
56
+ const configs = pluginE18e.configs;
57
+ return [{
58
+ name: "whoj/e18e/rules",
59
+ plugins: { e18e: pluginE18e },
60
+ rules: {
61
+ ...modernization ? configs.modernization.rules : {},
62
+ ...moduleReplacements ? configs.moduleReplacements.rules : {},
63
+ ...performanceImprovements ? configs.performanceImprovements.rules : {},
64
+ ...type === "lib" ? {} : { "e18e/prefer-static-regex": "off" },
65
+ "e18e/prefer-array-at": "off",
66
+ "e18e/prefer-spread-syntax": "off",
67
+ "e18e/prefer-array-from-map": "off",
68
+ "e18e/prefer-array-to-sorted": "off",
69
+ "e18e/prefer-array-to-spliced": "off",
70
+ "e18e/prefer-array-to-reversed": "off",
71
+ ...overrides
72
+ }
73
+ }];
74
+ }
75
+ //#endregion
76
+ //#region src/globs.ts
77
+ const GLOB_SRC_EXT = "?([cm])[jt]s?(x)";
78
+ const GLOB_SRC = "**/*.?([cm])[jt]s?(x)";
79
+ const GLOB_JS = "**/*.?([cm])js";
80
+ const GLOB_JSX = "**/*.?([cm])jsx";
81
+ const GLOB_TS = "**/*.?([cm])ts";
82
+ const GLOB_TSX = "**/*.?([cm])tsx";
83
+ const GLOB_STYLE = "**/*.{c,le,sc}ss";
84
+ const GLOB_CSS = "**/*.css";
85
+ const GLOB_POSTCSS = "**/*.{p,post}css";
86
+ const GLOB_LESS = "**/*.less";
87
+ const GLOB_SCSS = "**/*.scss";
88
+ const GLOB_JSON = "**/*.json";
89
+ const GLOB_JSON5 = "**/*.json5";
90
+ const GLOB_JSONC = "**/*.jsonc";
91
+ const GLOB_MARKDOWN = "**/*.md";
92
+ const GLOB_MARKDOWN_IN_MARKDOWN = "**/*.md/*.md";
93
+ const GLOB_SVELTE = "**/*.svelte?(.{js,ts})";
94
+ const GLOB_VUE = "**/*.vue";
95
+ const GLOB_YAML = "**/*.y?(a)ml";
96
+ const GLOB_TOML = "**/*.toml";
97
+ const GLOB_XML = "**/*.xml";
98
+ const GLOB_SVG = "**/*.svg";
99
+ const GLOB_HTML = "**/*.htm?(l)";
100
+ const GLOB_ASTRO = "**/*.astro";
101
+ const GLOB_ASTRO_TS = "**/*.astro/*.ts";
102
+ const GLOB_GRAPHQL = "**/*.{g,graph}ql";
103
+ const GLOB_MARKDOWN_CODE = `${GLOB_MARKDOWN}/${GLOB_SRC}`;
104
+ const GLOB_TESTS = [
105
+ `**/__tests__/**/*.${GLOB_SRC_EXT}`,
106
+ `**/*.spec.${GLOB_SRC_EXT}`,
107
+ `**/*.test.${GLOB_SRC_EXT}`,
108
+ `**/*.bench.${GLOB_SRC_EXT}`,
109
+ `**/*.benchmark.${GLOB_SRC_EXT}`
110
+ ];
111
+ const GLOB_ALL_SRC = [
112
+ GLOB_SRC,
113
+ GLOB_STYLE,
114
+ GLOB_JSON,
115
+ GLOB_JSON5,
116
+ GLOB_MARKDOWN,
117
+ GLOB_SVELTE,
118
+ GLOB_VUE,
119
+ GLOB_YAML,
120
+ GLOB_XML,
121
+ GLOB_HTML
122
+ ];
123
+ const GLOB_EXCLUDE = [
124
+ "**/node_modules",
125
+ "**/dist",
126
+ "**/package-lock.json",
127
+ "**/yarn.lock",
128
+ "**/pnpm-lock.yaml",
129
+ "**/bun.lockb",
130
+ "**/output",
131
+ "**/coverage",
132
+ "**/temp",
133
+ "**/.temp",
134
+ "**/tmp",
135
+ "**/.tmp",
136
+ "**/.history",
137
+ "**/.vitepress/cache",
138
+ "**/.nuxt",
139
+ "**/.next",
140
+ "**/.svelte-kit",
141
+ "**/.vercel",
142
+ "**/.changeset",
143
+ "**/.idea",
144
+ "**/.cache",
145
+ "**/.output",
146
+ "**/.vite-inspect",
147
+ "**/.yarn",
148
+ "**/CHANGELOG*.md",
149
+ "**/LICENSE*",
150
+ "**/*.min.*",
151
+ "**/__snapshots__",
152
+ "**/vite.config.*.timestamp-*",
153
+ "**/auto-import?(s).d.ts",
154
+ "**/components.d.ts",
155
+ "**/.context",
156
+ "**/.claude",
157
+ "**/.agents",
158
+ "**/.*/skills"
159
+ ];
53
160
  //#endregion
54
161
  //#region src/configs/regexp.ts
55
162
  async function regexp(options = {}) {
@@ -67,7 +174,6 @@ async function regexp(options = {}) {
67
174
  }
68
175
  }];
69
176
  }
70
-
71
177
  //#endregion
72
178
  //#region src/utils.ts
73
179
  const scopeUrl = fileURLToPath(new URL(".", import.meta.url));
@@ -94,8 +200,8 @@ const parserPlain = {
94
200
  /**
95
201
  * Combine array and non-array configs into a single array.
96
202
  */
97
- async function combine(...configs$1) {
98
- return (await Promise.all(configs$1)).flat();
203
+ async function combine(...configs) {
204
+ return (await Promise.all(configs)).flat();
99
205
  }
100
206
  /**
101
207
  * Rename plugin prefixes in a rule object.
@@ -135,8 +241,8 @@ function renameRules(rules, map) {
135
241
  * })
136
242
  * ```
137
243
  */
138
- function renamePluginInConfigs(configs$1, map) {
139
- return configs$1.map((i) => {
244
+ function renamePluginInConfigs(configs, map) {
245
+ return configs.map((i) => {
140
246
  const clone = { ...i };
141
247
  if (clone.rules) clone.rules = renameRules(clone.rules, map);
142
248
  if (clone.plugins) clone.plugins = Object.fromEntries(Object.entries(clone.plugins).map(([key, value]) => {
@@ -165,12 +271,11 @@ async function ensurePackages(packages) {
165
271
  function isInEditorEnv() {
166
272
  if (process.env.CI) return false;
167
273
  if (isInGitHooksOrLintStaged()) return false;
168
- return !!(process.env.VSCODE_PID || process.env.VSCODE_CWD || process.env.JETBRAINS_IDE || process.env.VIM || process.env.NVIM);
274
+ return !!(process.env.VSCODE_PID || process.env.VSCODE_CWD || process.env.JETBRAINS_IDE || process.env.VIM || process.env.NVIM || process.env.ZED_ENVIRONMENT && !process.env.ZED_TERM);
169
275
  }
170
276
  function isInGitHooksOrLintStaged() {
171
277
  return !!(process.env.GIT_PARAMS || process.env.VSCODE_GIT_COMMAND || process.env.npm_lifecycle_script?.startsWith("lint-staged"));
172
278
  }
173
-
174
279
  //#endregion
175
280
  //#region src/configs/stylistic.ts
176
281
  const StylisticConfigDefaults = {
@@ -179,19 +284,21 @@ const StylisticConfigDefaults = {
179
284
  semi: true,
180
285
  quotes: "single",
181
286
  experimental: false,
182
- commaDangle: "never"
287
+ commaDangle: "never",
288
+ braceStyle: "stroustrup"
183
289
  };
184
290
  async function stylistic(options = {}) {
185
- const { jsx: jsx$1, semi, indent, quotes, commaDangle, experimental, overrides = {}, lessOpinionated = false } = {
291
+ const { jsx, semi, indent, quotes, braceStyle, commaDangle, experimental, overrides = {}, lessOpinionated = false } = {
186
292
  ...StylisticConfigDefaults,
187
293
  ...options
188
294
  };
189
295
  const pluginStylistic = await interopDefault(import("@stylistic/eslint-plugin"));
190
296
  const config = pluginStylistic.configs.customize({
191
- jsx: jsx$1,
297
+ jsx,
192
298
  semi,
193
299
  indent,
194
300
  quotes,
301
+ braceStyle,
195
302
  commaDangle,
196
303
  pluginName: "style",
197
304
  ...experimental != null && { experimental }
@@ -223,89 +330,6 @@ async function stylistic(options = {}) {
223
330
  }
224
331
  }];
225
332
  }
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
333
  //#endregion
310
334
  //#region src/configs/formatters.ts
311
335
  function mergePrettierOptions(options, overrides) {
@@ -315,7 +339,7 @@ function mergePrettierOptions(options, overrides) {
315
339
  plugins: [...overrides.plugins || [], ...options.plugins || []]
316
340
  };
317
341
  }
318
- async function formatters(options = {}, stylistic$1 = {}) {
342
+ async function formatters(options = {}, stylistic = {}) {
319
343
  if (options === true) {
320
344
  const isPrettierPluginXmlInScope = isPackageInScope("@prettier/plugin-xml");
321
345
  options = {
@@ -331,14 +355,14 @@ async function formatters(options = {}, stylistic$1 = {}) {
331
355
  }
332
356
  await ensurePackages([
333
357
  "eslint-plugin-format",
334
- options.markdown && options.slidev ? "prettier-plugin-slidev" : void 0,
335
358
  options.astro ? "prettier-plugin-astro" : void 0,
336
- options.xml || options.svg ? "@prettier/plugin-xml" : void 0
359
+ options.xml || options.svg ? "@prettier/plugin-xml" : void 0,
360
+ options.markdown && options.slidev ? "prettier-plugin-slidev" : void 0
337
361
  ]);
338
362
  if (options.slidev && options.markdown !== true && options.markdown !== "prettier") throw new Error("`slidev` option only works when `markdown` is enabled with `prettier`");
339
363
  const { semi, indent, quotes } = {
340
364
  ...StylisticConfigDefaults,
341
- ...stylistic$1
365
+ ...stylistic
342
366
  };
343
367
  const prettierOptions = Object.assign({
344
368
  semi,
@@ -355,16 +379,17 @@ async function formatters(options = {}, stylistic$1 = {}) {
355
379
  xmlSortAttributesByKey: false,
356
380
  xmlWhitespaceSensitivity: "ignore"
357
381
  };
358
- const dprintOptions = Object.assign({
382
+ const dprintOptions = {
359
383
  useTabs: indent === "tab",
360
384
  indentWidth: typeof indent === "number" ? indent : 2,
361
- quoteStyle: quotes === "single" ? "preferSingle" : "preferDouble"
362
- }, options.dprintOptions || {});
363
- const configs$1 = [{
385
+ quoteStyle: quotes === "single" ? "preferSingle" : "preferDouble",
386
+ ...options.dprintOptions || {}
387
+ };
388
+ const configs = [{
364
389
  name: "whoj/formatter/setup",
365
390
  plugins: { format: await interopDefault(import("eslint-plugin-format")) }
366
391
  }];
367
- if (options.css) configs$1.push({
392
+ if (options.css) configs.push({
368
393
  name: "whoj/formatter/css",
369
394
  files: [GLOB_CSS, GLOB_POSTCSS],
370
395
  languageOptions: { parser: parserPlain },
@@ -380,13 +405,13 @@ async function formatters(options = {}, stylistic$1 = {}) {
380
405
  languageOptions: { parser: parserPlain },
381
406
  rules: { "format/prettier": ["error", mergePrettierOptions(prettierOptions, { parser: "less" })] }
382
407
  });
383
- if (options.html) configs$1.push({
408
+ if (options.html) configs.push({
384
409
  files: [GLOB_HTML],
385
410
  name: "whoj/formatter/html",
386
411
  languageOptions: { parser: parserPlain },
387
412
  rules: { "format/prettier": ["error", mergePrettierOptions(prettierOptions, { parser: "html" })] }
388
413
  });
389
- if (options.xml) configs$1.push({
414
+ if (options.xml) configs.push({
390
415
  files: [GLOB_XML],
391
416
  name: "whoj/formatter/xml",
392
417
  languageOptions: { parser: parserPlain },
@@ -398,7 +423,7 @@ async function formatters(options = {}, stylistic$1 = {}) {
398
423
  plugins: ["@prettier/plugin-xml"]
399
424
  })] }
400
425
  });
401
- if (options.svg) configs$1.push({
426
+ if (options.svg) configs.push({
402
427
  files: [GLOB_SVG],
403
428
  name: "whoj/formatter/svg",
404
429
  languageOptions: { parser: parserPlain },
@@ -413,7 +438,7 @@ async function formatters(options = {}, stylistic$1 = {}) {
413
438
  if (options.markdown) {
414
439
  const formater = options.markdown === true ? "prettier" : options.markdown;
415
440
  const GLOB_SLIDEV = !options.slidev ? [] : options.slidev === true ? ["**/slides.md"] : options.slidev.files;
416
- configs$1.push({
441
+ configs.push({
417
442
  ignores: GLOB_SLIDEV,
418
443
  files: [GLOB_MARKDOWN],
419
444
  name: "whoj/formatter/markdown",
@@ -426,7 +451,7 @@ async function formatters(options = {}, stylistic$1 = {}) {
426
451
  language: "markdown"
427
452
  }] }
428
453
  });
429
- if (options.slidev) configs$1.push({
454
+ if (options.slidev) configs.push({
430
455
  files: GLOB_SLIDEV,
431
456
  name: "whoj/formatter/slidev",
432
457
  languageOptions: { parser: parserPlain },
@@ -438,7 +463,7 @@ async function formatters(options = {}, stylistic$1 = {}) {
438
463
  });
439
464
  }
440
465
  if (options.astro) {
441
- configs$1.push({
466
+ configs.push({
442
467
  files: [GLOB_ASTRO],
443
468
  name: "whoj/formatter/astro",
444
469
  languageOptions: { parser: parserPlain },
@@ -447,7 +472,7 @@ async function formatters(options = {}, stylistic$1 = {}) {
447
472
  plugins: ["prettier-plugin-astro"]
448
473
  })] }
449
474
  });
450
- configs$1.push({
475
+ configs.push({
451
476
  files: [GLOB_ASTRO, GLOB_ASTRO_TS],
452
477
  name: "whoj/formatter/astro/disables",
453
478
  rules: {
@@ -461,15 +486,14 @@ async function formatters(options = {}, stylistic$1 = {}) {
461
486
  }
462
487
  });
463
488
  }
464
- if (options.graphql) configs$1.push({
489
+ if (options.graphql) configs.push({
465
490
  files: [GLOB_GRAPHQL],
466
491
  name: "whoj/formatter/graphql",
467
492
  languageOptions: { parser: parserPlain },
468
493
  rules: { "format/prettier": ["error", mergePrettierOptions(prettierOptions, { parser: "graphql" })] }
469
494
  });
470
- return configs$1;
495
+ return configs;
471
496
  }
472
-
473
497
  //#endregion
474
498
  //#region src/configs/jsx.ts
475
499
  async function jsx(options = {}) {
@@ -508,13 +532,12 @@ async function jsx(options = {}) {
508
532
  }
509
533
  }];
510
534
  }
511
-
512
535
  //#endregion
513
536
  //#region src/configs/vue.ts
514
537
  async function vue(options = {}) {
515
- const { a11y = false, overrides = {}, vueVersion = 3, stylistic: stylistic$1 = true, files = [GLOB_VUE] } = options;
538
+ const { a11y = false, overrides = {}, vueVersion = 3, stylistic = true, files = [GLOB_VUE] } = options;
516
539
  const sfcBlocks = options.sfcBlocks === true ? {} : options.sfcBlocks ?? {};
517
- const { indent = 2 } = typeof stylistic$1 === "boolean" ? {} : stylistic$1;
540
+ const { indent = 2, braceStyle = "stroustrup" } = typeof stylistic === "boolean" ? {} : stylistic;
518
541
  if (a11y) await ensurePackages(["eslint-plugin-vuejs-accessibility"]);
519
542
  const [pluginVue, parserVue, processorVueBlocks, pluginVueA11y] = await Promise.all([
520
543
  interopDefault(import("eslint-plugin-vue")),
@@ -618,21 +641,21 @@ async function vue(options = {}) {
618
641
  nonwords: false
619
642
  }],
620
643
  "vue/block-order": ["error", { order: [
644
+ "style",
621
645
  "script",
622
- "template",
623
- "style"
646
+ "template"
624
647
  ] }],
625
648
  "vue/define-macros-order": ["error", { order: [
626
- "defineOptions",
627
649
  "defineProps",
628
650
  "defineEmits",
629
- "defineSlots"
651
+ "defineSlots",
652
+ "defineOptions"
630
653
  ] }],
631
654
  "vue/no-restricted-syntax": [
632
655
  "error",
633
- "DebuggerStatement",
656
+ "WithStatement",
634
657
  "LabeledStatement",
635
- "WithStatement"
658
+ "DebuggerStatement"
636
659
  ],
637
660
  "vue/object-shorthand": [
638
661
  "error",
@@ -642,7 +665,7 @@ async function vue(options = {}) {
642
665
  ignoreConstructors: false
643
666
  }
644
667
  ],
645
- ...stylistic$1 ? {
668
+ ...stylistic ? {
646
669
  "vue/object-curly-newline": "off",
647
670
  "vue/comma-style": ["error", "last"],
648
671
  "vue/template-curly-spacing": "error",
@@ -668,7 +691,7 @@ async function vue(options = {}) {
668
691
  }],
669
692
  "vue/brace-style": [
670
693
  "error",
671
- "stroustrup",
694
+ braceStyle,
672
695
  { allowSingleLine: true }
673
696
  ],
674
697
  "vue/key-spacing": ["error", {
@@ -714,14 +737,15 @@ async function vue(options = {}) {
714
737
  }
715
738
  }];
716
739
  }
717
-
718
740
  //#endregion
719
741
  //#region src/configs/node.ts
720
742
  async function node() {
721
743
  return [{
744
+ name: "whoj/node/setup",
745
+ plugins: { node: pluginNode }
746
+ }, {
722
747
  files: [GLOB_SRC],
723
748
  name: "whoj/node/rules",
724
- plugins: { node: pluginNode },
725
749
  rules: {
726
750
  "node/no-new-require": "error",
727
751
  "node/no-path-concat": "error",
@@ -734,28 +758,26 @@ async function node() {
734
758
  }
735
759
  }];
736
760
  }
737
-
738
761
  //#endregion
739
762
  //#region src/configs/pnpm.ts
740
763
  async function detectCatalogUsage() {
741
764
  const workspaceFile = await findUp("pnpm-workspace.yaml");
742
765
  if (!workspaceFile) return false;
743
- const yaml$1 = await fs.readFile(workspaceFile, "utf-8");
744
- return yaml$1.includes("catalog:") || yaml$1.includes("catalogs:");
766
+ const yaml = await fsp.readFile(workspaceFile, "utf-8");
767
+ return yaml.includes("catalog:") || yaml.includes("catalogs:");
745
768
  }
746
769
  async function pnpm(options) {
747
- const [pluginPnpm, pluginYaml, yamlParser, jsoncParser] = await Promise.all([
770
+ const [pluginPnpm, pluginYaml, yamlParser] = await Promise.all([
748
771
  interopDefault(import("eslint-plugin-pnpm")),
749
772
  interopDefault(import("eslint-plugin-yml")),
750
- interopDefault(import("yaml-eslint-parser")),
751
- interopDefault(import("jsonc-eslint-parser"))
773
+ interopDefault(import("yaml-eslint-parser"))
752
774
  ]);
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({
775
+ const { json = true, sort = true, yaml = true, isInEditor = false, catalogs = await detectCatalogUsage() } = options;
776
+ const configs = [];
777
+ if (json) configs.push({
778
+ language: "jsonc/x",
756
779
  name: "whoj/pnpm/package-json",
757
780
  plugins: { pnpm: pluginPnpm },
758
- languageOptions: { parser: jsoncParser },
759
781
  files: ["package.json", "**/package.json"],
760
782
  rules: {
761
783
  ...catalogs ? { "pnpm/json-enforce-catalog": ["error", {
@@ -766,8 +788,8 @@ async function pnpm(options) {
766
788
  "pnpm/json-prefer-workspace-settings": ["error", { autofix: !isInEditor }]
767
789
  }
768
790
  });
769
- if (yaml$1) {
770
- configs$1.push({
791
+ if (yaml) {
792
+ configs.push({
771
793
  files: ["pnpm-workspace.yaml"],
772
794
  name: "whoj/pnpm/pnpm-workspace-yaml",
773
795
  plugins: { pnpm: pluginPnpm },
@@ -781,13 +803,17 @@ async function pnpm(options) {
781
803
  } }]
782
804
  }
783
805
  });
784
- if (sort) configs$1.push({
806
+ if (sort) configs.push({
785
807
  files: ["pnpm-workspace.yaml"],
786
808
  name: "whoj/pnpm/pnpm-workspace-yaml-sort",
787
809
  plugins: { yaml: pluginYaml },
788
810
  languageOptions: { parser: yamlParser },
789
811
  rules: { "yaml/sort-keys": [
790
812
  "error",
813
+ {
814
+ pathPattern: ".*",
815
+ order: { type: "asc" }
816
+ },
791
817
  {
792
818
  pathPattern: "^$",
793
819
  order: [
@@ -834,11 +860,11 @@ async function pnpm(options) {
834
860
  "trustPolicyExclude",
835
861
  "updateNotifier"
836
862
  ],
863
+ "catalog",
837
864
  "packages",
865
+ "catalogs",
838
866
  "overrides",
839
867
  "patchedDependencies",
840
- "catalog",
841
- "catalogs",
842
868
  ...[
843
869
  "allowedDeprecatedVersions",
844
870
  "allowNonAppliedPatches",
@@ -852,17 +878,12 @@ async function pnpm(options) {
852
878
  "peerDependencyRules"
853
879
  ]
854
880
  ]
855
- },
856
- {
857
- pathPattern: ".*",
858
- order: { type: "asc" }
859
881
  }
860
882
  ] }
861
883
  });
862
884
  }
863
- return configs$1;
885
+ return configs;
864
886
  }
865
-
866
887
  //#endregion
867
888
  //#region src/configs/sort.ts
868
889
  /**
@@ -1096,7 +1117,6 @@ function sortTsconfig() {
1096
1117
  ] }
1097
1118
  }];
1098
1119
  }
1099
-
1100
1120
  //#endregion
1101
1121
  //#region src/configs/test.ts
1102
1122
  let _pluginTest;
@@ -1128,18 +1148,18 @@ async function test(options = {}) {
1128
1148
  }],
1129
1149
  "no-unused-expressions": "off",
1130
1150
  "whoj/no-top-level-await": "off",
1151
+ "e18e/prefer-static-regex": "off",
1131
1152
  "node/prefer-global/process": "off",
1132
1153
  "ts/explicit-function-return-type": "off",
1133
1154
  ...overrides
1134
1155
  }
1135
1156
  }];
1136
1157
  }
1137
-
1138
1158
  //#endregion
1139
1159
  //#region src/configs/toml.ts
1140
1160
  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;
1161
+ const { overrides = {}, stylistic = true, files = [GLOB_TOML] } = options;
1162
+ const { indent = 2 } = typeof stylistic === "boolean" ? {} : stylistic;
1143
1163
  const [pluginToml, parserToml] = await Promise.all([interopDefault(import("eslint-plugin-toml")), interopDefault(import("toml-eslint-parser"))]);
1144
1164
  return [{
1145
1165
  name: "whoj/toml/setup",
@@ -1158,7 +1178,7 @@ async function toml(options = {}) {
1158
1178
  "toml/no-unreadable-number-separator": "error",
1159
1179
  "toml/precision-of-fractional-seconds": "error",
1160
1180
  "toml/vue-custom-block/no-parsing-error": "error",
1161
- ...stylistic$1 ? {
1181
+ ...stylistic ? {
1162
1182
  "toml/key-spacing": "error",
1163
1183
  "toml/quoted-keys": "error",
1164
1184
  "toml/spaced-comment": "error",
@@ -1175,12 +1195,11 @@ async function toml(options = {}) {
1175
1195
  }
1176
1196
  }];
1177
1197
  }
1178
-
1179
1198
  //#endregion
1180
1199
  //#region src/configs/yaml.ts
1181
1200
  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;
1201
+ const { overrides = {}, stylistic = true, files = [GLOB_YAML] } = options;
1202
+ const { indent = 2, quotes = "single" } = typeof stylistic === "boolean" ? {} : stylistic;
1184
1203
  const [pluginYaml, parserYaml] = await Promise.all([interopDefault(import("eslint-plugin-yml")), interopDefault(import("yaml-eslint-parser"))]);
1185
1204
  return [{
1186
1205
  name: "whoj/yaml/setup",
@@ -1198,7 +1217,7 @@ async function yaml(options = {}) {
1198
1217
  "yaml/no-empty-sequence-entry": "error",
1199
1218
  "yaml/no-irregular-whitespace": "error",
1200
1219
  "yaml/vue-custom-block/no-parsing-error": "error",
1201
- ...stylistic$1 ? {
1220
+ ...stylistic ? {
1202
1221
  "yaml/key-spacing": "error",
1203
1222
  "yaml/no-tab-indent": "error",
1204
1223
  "yaml/spaced-comment": "error",
@@ -1218,11 +1237,10 @@ async function yaml(options = {}) {
1218
1237
  }
1219
1238
  }];
1220
1239
  }
1221
-
1222
1240
  //#endregion
1223
1241
  //#region src/configs/astro.ts
1224
1242
  async function astro(options = {}) {
1225
- const { overrides = {}, stylistic: stylistic$1 = true, files = [GLOB_ASTRO] } = options;
1243
+ const { overrides = {}, stylistic = true, files = [GLOB_ASTRO] } = options;
1226
1244
  const [pluginAstro, parserAstro, parserTs] = await Promise.all([
1227
1245
  interopDefault(import("eslint-plugin-astro")),
1228
1246
  interopDefault(import("astro-eslint-parser")),
@@ -1256,7 +1274,7 @@ async function astro(options = {}) {
1256
1274
  "astro/no-deprecated-astro-canonicalurl": "error",
1257
1275
  "astro/no-deprecated-astro-fetchcontent": "error",
1258
1276
  "astro/missing-client-only-directive-value": "error",
1259
- ...stylistic$1 ? {
1277
+ ...stylistic ? {
1260
1278
  "style/indent": "off",
1261
1279
  "style/no-multiple-empty-lines": "off",
1262
1280
  "style/jsx-closing-tag-location": "off",
@@ -1266,15 +1284,16 @@ async function astro(options = {}) {
1266
1284
  }
1267
1285
  }];
1268
1286
  }
1269
-
1270
1287
  //#endregion
1271
1288
  //#region src/configs/jsdoc.ts
1272
1289
  async function jsdoc(options = {}) {
1273
- const { stylistic: stylistic$1 = true } = options;
1290
+ const { stylistic = true } = options;
1274
1291
  return [{
1292
+ name: "whoj/jsdoc/setup",
1293
+ plugins: { jsdoc: await interopDefault(import("eslint-plugin-jsdoc")) }
1294
+ }, {
1275
1295
  files: [GLOB_SRC],
1276
1296
  name: "whoj/jsdoc/rules",
1277
- plugins: { jsdoc: await interopDefault(import("eslint-plugin-jsdoc")) },
1278
1297
  rules: {
1279
1298
  "jsdoc/empty-tags": "warn",
1280
1299
  "jsdoc/check-types": "warn",
@@ -1291,31 +1310,29 @@ async function jsdoc(options = {}) {
1291
1310
  "jsdoc/require-returns-check": "warn",
1292
1311
  "jsdoc/require-returns-description": "warn",
1293
1312
  "jsdoc/require-property-description": "warn",
1294
- ...stylistic$1 ? {
1313
+ ...stylistic ? {
1295
1314
  "jsdoc/check-alignment": "warn",
1296
1315
  "jsdoc/multiline-blocks": "warn"
1297
1316
  } : {}
1298
1317
  }
1299
1318
  }];
1300
1319
  }
1301
-
1302
1320
  //#endregion
1303
1321
  //#region src/configs/jsonc.ts
1304
1322
  async function jsonc(options = {}) {
1305
- const { overrides = {}, stylistic: stylistic$1 = true, files = [
1323
+ const { overrides = {}, stylistic = true, files = [
1306
1324
  GLOB_JSON,
1307
1325
  GLOB_JSON5,
1308
1326
  GLOB_JSONC
1309
1327
  ] } = 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"))]);
1328
+ const { indent = 2 } = typeof stylistic === "boolean" ? {} : stylistic;
1312
1329
  return [{
1313
1330
  name: "whoj/jsonc/setup",
1314
- plugins: { jsonc: pluginJsonc }
1331
+ plugins: { jsonc: await interopDefault(import("eslint-plugin-jsonc")) }
1315
1332
  }, {
1316
1333
  files,
1334
+ language: "jsonc/x",
1317
1335
  name: "whoj/jsonc/rules",
1318
- languageOptions: { parser: parserJsonc },
1319
1336
  rules: {
1320
1337
  "jsonc/no-nan": "error",
1321
1338
  "jsonc/no-octal": "error",
@@ -1343,7 +1360,7 @@ async function jsonc(options = {}) {
1343
1360
  "jsonc/no-hexadecimal-numeric-literals": "error",
1344
1361
  "jsonc/no-escape-sequence-in-identifier": "error",
1345
1362
  "jsonc/vue-custom-block/no-parsing-error": "error",
1346
- ...stylistic$1 ? {
1363
+ ...stylistic ? {
1347
1364
  "jsonc/quotes": "error",
1348
1365
  "jsonc/quote-props": "error",
1349
1366
  "jsonc/comma-style": ["error", "last"],
@@ -1365,191 +1382,89 @@ async function jsonc(options = {}) {
1365
1382
  }
1366
1383
  }];
1367
1384
  }
1368
-
1369
1385
  //#endregion
1370
1386
  //#region src/configs/react.ts
1371
1387
  const ReactRefreshAllowConstantExportPackages = ["vite"];
1372
1388
  const RemixPackages = [
1389
+ "@remix-run/dev",
1373
1390
  "@remix-run/node",
1374
1391
  "@remix-run/react",
1375
- "@remix-run/serve",
1376
- "@remix-run/dev"
1392
+ "@remix-run/serve"
1377
1393
  ];
1378
1394
  const ReactRouterPackages = [
1395
+ "@react-router/dev",
1379
1396
  "@react-router/node",
1380
1397
  "@react-router/react",
1381
- "@react-router/serve",
1382
- "@react-router/dev"
1398
+ "@react-router/serve"
1383
1399
  ];
1384
1400
  const NextJsPackages = ["next"];
1385
- const ReactCompilerPackages = ["babel-plugin-react-compiler"];
1386
1401
  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
- ]);
1402
+ const { tsconfigPath, overrides = {}, files = [GLOB_SRC], filesTypeAware = [GLOB_TS, GLOB_TSX], ignoresTypeAware = [GLOB_ASTRO_TS, `${GLOB_MARKDOWN}/**`] } = options;
1403
+ await ensurePackages(["@eslint-react/eslint-plugin", "eslint-plugin-react-refresh"]);
1393
1404
  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
- ]);
1405
+ const typeAwareRules = { "react/no-leaked-conditional-rendering": "error" };
1406
+ const [pluginReact, pluginReactRefresh] = await Promise.all([interopDefault(import("@eslint-react/eslint-plugin")), interopDefault(import("eslint-plugin-react-refresh"))]);
1403
1407
  const isAllowConstantExport = ReactRefreshAllowConstantExportPackages.some((i) => isPackageExists(i));
1404
1408
  const isUsingRemix = RemixPackages.some((i) => isPackageExists(i));
1405
1409
  const isUsingReactRouter = ReactRouterPackages.some((i) => isPackageExists(i));
1406
1410
  const isUsingNext = NextJsPackages.some((i) => isPackageExists(i));
1407
- const plugins = pluginReact.configs.all.plugins;
1408
1411
  return [
1409
1412
  {
1410
1413
  name: "whoj/react/setup",
1411
1414
  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"]
1415
+ "react": pluginReact.configs.all.plugins["@eslint-react"],
1416
+ "react-refresh": pluginReactRefresh
1417
+ }
1418
+ },
1419
+ {
1420
+ files: filesTypeAware,
1421
+ name: "whoj/react/typescript",
1422
+ rules: {
1423
+ "react/dom-no-unknown-property": "off",
1424
+ "react/dom-no-string-style-prop": "off"
1420
1425
  }
1421
1426
  },
1422
1427
  {
1423
1428
  files,
1429
+ name: "whoj/react/rules",
1424
1430
  languageOptions: {
1425
- parserOptions: { ecmaFeatures: { jsx: true } },
1426
- sourceType: "module"
1431
+ sourceType: "module",
1432
+ parserOptions: { ecmaFeatures: { jsx: true } }
1427
1433
  },
1428
- name: "whoj/react/rules",
1429
1434
  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
- } : {},
1435
+ ...pluginReact.configs.recommended.rules,
1509
1436
  "react-refresh/only-export-components": ["error", {
1510
1437
  allowConstantExport: isAllowConstantExport,
1511
1438
  allowExportNames: [...isUsingNext ? [
1512
1439
  "dynamic",
1513
- "dynamicParams",
1440
+ "runtime",
1441
+ "metadata",
1442
+ "viewport",
1514
1443
  "revalidate",
1515
1444
  "fetchCache",
1516
- "runtime",
1517
- "preferredRegion",
1518
1445
  "maxDuration",
1519
- "generateStaticParams",
1520
- "metadata",
1446
+ "dynamicParams",
1447
+ "preferredRegion",
1521
1448
  "generateMetadata",
1522
- "viewport",
1523
1449
  "generateViewport",
1524
- "generateImageMetadata",
1525
- "generateSitemaps"
1450
+ "generateSitemaps",
1451
+ "generateStaticParams",
1452
+ "generateImageMetadata"
1526
1453
  ] : [], ...isUsingRemix || isUsingReactRouter ? [
1527
1454
  "meta",
1528
1455
  "links",
1529
- "headers",
1530
1456
  "loader",
1531
1457
  "action",
1458
+ "handle",
1459
+ "headers",
1532
1460
  "clientLoader",
1533
1461
  "clientAction",
1534
- "handle",
1535
1462
  "shouldRevalidate"
1536
1463
  ] : []]
1537
1464
  }],
1538
1465
  ...overrides
1539
1466
  }
1540
1467
  },
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
1468
  ...isTypeAware ? [{
1554
1469
  files: filesTypeAware,
1555
1470
  ignores: ignoresTypeAware,
@@ -1558,11 +1473,10 @@ async function react(options = {}) {
1558
1473
  }] : []
1559
1474
  ];
1560
1475
  }
1561
-
1562
1476
  //#endregion
1563
1477
  //#region src/configs/solid.ts
1564
1478
  async function solid(options = {}) {
1565
- const { overrides = {}, typescript: typescript$1 = true, files = [GLOB_JSX, GLOB_TSX] } = options;
1479
+ const { overrides = {}, typescript = true, files = [GLOB_JSX, GLOB_TSX] } = options;
1566
1480
  await ensurePackages(["eslint-plugin-solid"]);
1567
1481
  const tsconfigPath = options?.tsconfigPath ? toArray(options.tsconfigPath) : void 0;
1568
1482
  const isTypeAware = !!tsconfigPath;
@@ -1596,12 +1510,12 @@ async function solid(options = {}) {
1596
1510
  "solid/jsx-no-duplicate-props": "error",
1597
1511
  "solid/no-react-specific-props": "error",
1598
1512
  "solid/no-innerhtml": ["error", { allowStatic: true }],
1599
- "solid/style-prop": ["error", { styleProps: ["style", "css"] }],
1513
+ "solid/style-prop": ["error", { styleProps: ["css", "style"] }],
1600
1514
  "solid/event-handlers": ["error", {
1601
1515
  ignoreCase: false,
1602
1516
  warnOnSpread: false
1603
1517
  }],
1604
- ...typescript$1 ? {
1518
+ ...typescript ? {
1605
1519
  "solid/no-unknown-namespaces": "off",
1606
1520
  "solid/jsx-no-undef": ["error", { typescriptEnabled: true }]
1607
1521
  } : {},
@@ -1609,7 +1523,6 @@ async function solid(options = {}) {
1609
1523
  }
1610
1524
  }];
1611
1525
  }
1612
-
1613
1526
  //#endregion
1614
1527
  //#region src/configs/nextjs.ts
1615
1528
  function normalizeRules(rules) {
@@ -1619,7 +1532,7 @@ async function nextjs(options = {}) {
1619
1532
  const { overrides = {}, files = [GLOB_SRC] } = options;
1620
1533
  await ensurePackages(["@next/eslint-plugin-next"]);
1621
1534
  const pluginNextJS = await interopDefault(import("@next/eslint-plugin-next"));
1622
- function getRules$1(name) {
1535
+ function getRules(name) {
1623
1536
  const rules = pluginNextJS.configs?.[name]?.rules;
1624
1537
  if (!rules) throw new Error(`[@whoj/eslint-config] Failed to find config ${name} in @next/eslint-plugin-next`);
1625
1538
  return normalizeRules(rules);
@@ -1632,8 +1545,8 @@ async function nextjs(options = {}) {
1632
1545
  name: "whoj/nextjs/rules",
1633
1546
  settings: { react: { version: "detect" } },
1634
1547
  rules: {
1635
- ...getRules$1("recommended"),
1636
- ...getRules$1("core-web-vitals"),
1548
+ ...getRules("recommended"),
1549
+ ...getRules("core-web-vitals"),
1637
1550
  ...overrides
1638
1551
  },
1639
1552
  languageOptions: {
@@ -1642,12 +1555,11 @@ async function nextjs(options = {}) {
1642
1555
  }
1643
1556
  }];
1644
1557
  }
1645
-
1646
1558
  //#endregion
1647
1559
  //#region src/configs/svelte.ts
1648
1560
  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;
1561
+ const { overrides = {}, stylistic = true, files = [GLOB_SVELTE] } = options;
1562
+ const { indent = 2, quotes = "single" } = typeof stylistic === "boolean" ? {} : stylistic;
1651
1563
  await ensurePackages(["eslint-plugin-svelte"]);
1652
1564
  const [pluginSvelte, parserSvelte] = await Promise.all([interopDefault(import("eslint-plugin-svelte")), interopDefault(import("svelte-eslint-parser"))]);
1653
1565
  return [{
@@ -1666,25 +1578,6 @@ async function svelte(options = {}) {
1666
1578
  },
1667
1579
  rules: {
1668
1580
  "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
1581
  "no-unused-vars": ["error", {
1689
1582
  vars: "all",
1690
1583
  args: "none",
@@ -1692,13 +1585,17 @@ async function svelte(options = {}) {
1692
1585
  ignoreRestSiblings: true,
1693
1586
  varsIgnorePattern: "^(\\$\\$Props$|\\$\\$Events$|\\$\\$Slots$)"
1694
1587
  }],
1588
+ ...pluginSvelte.configs.recommended.map((config) => config.rules).reduce((acc, rules) => ({
1589
+ ...acc,
1590
+ ...rules
1591
+ }), {}),
1695
1592
  "unused-imports/no-unused-vars": ["error", {
1696
1593
  vars: "all",
1697
1594
  args: "after-used",
1698
1595
  argsIgnorePattern: "^_",
1699
1596
  varsIgnorePattern: "^(_|\\$\\$Props$|\\$\\$Events$|\\$\\$Slots$)"
1700
1597
  }],
1701
- ...stylistic$1 ? {
1598
+ ...stylistic ? {
1702
1599
  "style/indent": "off",
1703
1600
  "style/no-trailing-spaces": "off",
1704
1601
  "svelte/mustache-spacing": "error",
@@ -1717,7 +1614,6 @@ async function svelte(options = {}) {
1717
1614
  }
1718
1615
  }];
1719
1616
  }
1720
-
1721
1617
  //#endregion
1722
1618
  //#region src/configs/unocss.ts
1723
1619
  async function unocss(options = {}) {
@@ -1734,15 +1630,14 @@ async function unocss(options = {}) {
1734
1630
  }
1735
1631
  }];
1736
1632
  }
1737
-
1738
1633
  //#endregion
1739
1634
  //#region src/configs/angular.ts
1740
1635
  async function angular(options = {}) {
1741
1636
  const { overrides = {} } = options;
1742
1637
  await ensurePackages([
1743
1638
  "@angular-eslint/eslint-plugin",
1744
- "@angular-eslint/eslint-plugin-template",
1745
- "@angular-eslint/template-parser"
1639
+ "@angular-eslint/template-parser",
1640
+ "@angular-eslint/eslint-plugin-template"
1746
1641
  ]);
1747
1642
  const [pluginAngular, pluginAngularTemplate, parserAngularTemplate] = await Promise.all([
1748
1643
  interopDefault(import("@angular-eslint/eslint-plugin")),
@@ -1763,6 +1658,24 @@ async function angular(options = {}) {
1763
1658
  "angular-template": pluginAngularTemplate
1764
1659
  }
1765
1660
  },
1661
+ {
1662
+ files: [GLOB_HTML],
1663
+ name: "whoj/angular/rules/template",
1664
+ languageOptions: { parser: parserAngularTemplate },
1665
+ rules: {
1666
+ /**
1667
+ * we need to mute some style lint rules for angular inline templates,
1668
+ */
1669
+ "style/indent": "off",
1670
+ "style/no-trailing-spaces": "off",
1671
+ "angular-template/eqeqeq": "error",
1672
+ "angular-template/banana-in-box": "error",
1673
+ "angular-template/no-negated-async": "error",
1674
+ "angular-template/prefer-control-flow": "error",
1675
+ "style/no-multiple-empty-lines": ["error", { max: 1 }],
1676
+ ...angularTemplateRules
1677
+ }
1678
+ },
1766
1679
  {
1767
1680
  files: [GLOB_TS],
1768
1681
  name: "whoj/angular/rules/ts",
@@ -1782,25 +1695,9 @@ async function angular(options = {}) {
1782
1695
  "angular/use-pipe-transform-interface": "error",
1783
1696
  ...angularTsRules
1784
1697
  }
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
1698
  }
1801
1699
  ];
1802
1700
  }
1803
-
1804
1701
  //#endregion
1805
1702
  //#region src/configs/command.ts
1806
1703
  async function command() {
@@ -1809,24 +1706,22 @@ async function command() {
1809
1706
  name: "whoj/command/rules"
1810
1707
  }];
1811
1708
  }
1812
-
1813
1709
  //#endregion
1814
1710
  //#region src/configs/ignores.ts
1815
1711
  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];
1712
+ let ignores = [...GLOB_EXCLUDE];
1713
+ if (ignoreTypeScript) ignores.push(GLOB_TS, GLOB_TSX);
1714
+ if (typeof userIgnores === "function") ignores = userIgnores(ignores);
1715
+ else ignores = [...ignores, ...userIgnores];
1820
1716
  return [{
1821
- ignores: ignores$1,
1717
+ ignores,
1822
1718
  name: "whoj/ignores"
1823
1719
  }];
1824
1720
  }
1825
-
1826
1721
  //#endregion
1827
1722
  //#region src/configs/imports.ts
1828
1723
  async function imports(options = {}) {
1829
- const { overrides = {}, stylistic: stylistic$1 = true } = options;
1724
+ const { overrides = {}, stylistic = true } = options;
1830
1725
  return [{
1831
1726
  name: "whoj/imports/rules",
1832
1727
  plugins: {
@@ -1842,19 +1737,21 @@ async function imports(options = {}) {
1842
1737
  "import/no-mutable-exports": "error",
1843
1738
  "whoj/no-import-node-modules-by-path": "error",
1844
1739
  "import/consistent-type-specifier-style": ["error", "top-level"],
1845
- ...stylistic$1 ? { "import/newline-after-import": ["error", { count: 1 }] } : {},
1740
+ ...stylistic ? { "import/newline-after-import": ["error", { count: 1 }] } : {},
1846
1741
  ...overrides
1847
1742
  }
1848
1743
  }];
1849
1744
  }
1850
-
1851
1745
  //#endregion
1852
1746
  //#region src/configs/unicorn.ts
1853
1747
  async function unicorn(options = {}) {
1854
1748
  const { overrides = {}, allRecommended = false } = options;
1855
1749
  return [{
1750
+ name: "whoj/unicorn/setup",
1751
+ plugins: { unicorn: pluginUnicorn }
1752
+ }, {
1753
+ files: [GLOB_SRC],
1856
1754
  name: "whoj/unicorn/rules",
1857
- plugins: { unicorn: pluginUnicorn },
1858
1755
  rules: {
1859
1756
  ...allRecommended ? pluginUnicorn.configs.recommended.rules : {
1860
1757
  "unicorn/escape-case": "error",
@@ -1877,7 +1774,6 @@ async function unicorn(options = {}) {
1877
1774
  }
1878
1775
  }];
1879
1776
  }
1880
-
1881
1777
  //#endregion
1882
1778
  //#region src/configs/comments.ts
1883
1779
  async function comments() {
@@ -1892,19 +1788,14 @@ async function comments() {
1892
1788
  }
1893
1789
  }];
1894
1790
  }
1895
-
1896
1791
  //#endregion
1897
1792
  //#region src/configs/disables.ts
1898
1793
  async function disables() {
1899
1794
  return [
1900
1795
  {
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
- }
1796
+ name: "whoj/disables/cjs",
1797
+ files: ["**/*.js", "**/*.cjs"],
1798
+ rules: { "ts/no-require-imports": "off" }
1908
1799
  },
1909
1800
  {
1910
1801
  name: "whoj/disables/cli",
@@ -1922,6 +1813,15 @@ async function disables() {
1922
1813
  "whoj/no-import-node-modules-by-path": "off"
1923
1814
  }
1924
1815
  },
1816
+ {
1817
+ name: "whoj/disables/scripts",
1818
+ files: [`**/scripts/${GLOB_SRC}`],
1819
+ rules: {
1820
+ "no-console": "off",
1821
+ "whoj/no-top-level-await": "off",
1822
+ "ts/explicit-function-return-type": "off"
1823
+ }
1824
+ },
1925
1825
  {
1926
1826
  name: "whoj/disables/dts",
1927
1827
  files: ["**/*.d.?([cm])ts"],
@@ -1931,11 +1831,6 @@ async function disables() {
1931
1831
  "eslint-comments/no-unlimited-disable": "off"
1932
1832
  }
1933
1833
  },
1934
- {
1935
- name: "whoj/disables/cjs",
1936
- files: ["**/*.js", "**/*.cjs"],
1937
- rules: { "ts/no-require-imports": "off" }
1938
- },
1939
1834
  {
1940
1835
  name: "whoj/disables/config-files",
1941
1836
  files: [`**/*.config.${GLOB_SRC_EXT}`, `**/*.config.*.${GLOB_SRC_EXT}`],
@@ -1947,30 +1842,39 @@ async function disables() {
1947
1842
  }
1948
1843
  ];
1949
1844
  }
1950
-
1951
1845
  //#endregion
1952
1846
  //#region src/configs/markdown.ts
1953
1847
  async function markdown(options = {}) {
1954
- const { overrides = {}, componentExts = [], files = [GLOB_MARKDOWN] } = options;
1955
- const markdown$1 = await interopDefault(import("@eslint/markdown"));
1848
+ const { gfm = true, overrides = {}, componentExts = [], overridesMarkdown = {}, files = [GLOB_MARKDOWN] } = options;
1849
+ const markdown = await interopDefault(import("@eslint/markdown"));
1956
1850
  return [
1957
1851
  {
1958
1852
  name: "whoj/markdown/setup",
1959
- plugins: { markdown: markdown$1 }
1853
+ plugins: { markdown }
1960
1854
  },
1961
1855
  {
1962
1856
  files,
1963
- name: "whoj/markdown/processor",
1964
- ignores: [GLOB_MARKDOWN_IN_MARKDOWN],
1965
- processor: mergeProcessors([markdown$1.processors.markdown, processorPassThrough])
1857
+ name: "whoj/markdown/parser",
1858
+ language: gfm ? "markdown/gfm" : "markdown/commonmark"
1966
1859
  },
1967
1860
  {
1968
1861
  files,
1969
- name: "whoj/markdown/parser",
1970
- languageOptions: { parser: parserPlain }
1862
+ name: "whoj/markdown/rules",
1863
+ rules: {
1864
+ ...markdown.configs.recommended.at(0)?.rules,
1865
+ "markdown/fenced-code-language": "off",
1866
+ "markdown/no-missing-label-refs": "off",
1867
+ ...overridesMarkdown
1868
+ }
1869
+ },
1870
+ {
1871
+ files,
1872
+ name: "whoj/markdown/processor",
1873
+ ignores: [GLOB_MARKDOWN_IN_MARKDOWN],
1874
+ processor: mergeProcessors([processorPassThrough, markdown.processors.markdown])
1971
1875
  },
1972
1876
  {
1973
- name: "whoj/markdown/disables",
1877
+ name: "whoj/markdown/disables/code",
1974
1878
  files: [GLOB_MARKDOWN_CODE, ...componentExts.map((ext) => `${GLOB_MARKDOWN}/**/*.${ext}`)],
1975
1879
  languageOptions: { parserOptions: { ecmaFeatures: { impliedStrict: true } } },
1976
1880
  rules: {
@@ -1990,8 +1894,9 @@ async function markdown(options = {}) {
1990
1894
  "no-restricted-syntax": "off",
1991
1895
  "no-unused-expressions": "off",
1992
1896
  "ts/no-require-imports": "off",
1993
- "ts/no-use-before-define": "off",
1994
1897
  "whoj/no-top-level-await": "off",
1898
+ "ts/no-use-before-define": "off",
1899
+ "e18e/prefer-static-regex": "off",
1995
1900
  "ts/no-unused-expressions": "off",
1996
1901
  "node/prefer-global/process": "off",
1997
1902
  "ts/consistent-type-imports": "off",
@@ -2004,7 +1909,6 @@ async function markdown(options = {}) {
2004
1909
  }
2005
1910
  ];
2006
1911
  }
2007
-
2008
1912
  //#endregion
2009
1913
  //#region src/configs/javascript.ts
2010
1914
  async function javascript(options = {}) {
@@ -2154,8 +2058,8 @@ async function javascript(options = {}) {
2154
2058
  }],
2155
2059
  "no-restricted-syntax": [
2156
2060
  "error",
2157
- "TSEnumDeclaration[const=true]",
2158
- "TSExportAssignment"
2061
+ "TSExportAssignment",
2062
+ "TSEnumDeclaration[const=true]"
2159
2063
  ],
2160
2064
  "no-unused-expressions": ["error", {
2161
2065
  allowTernary: true,
@@ -2187,11 +2091,11 @@ async function javascript(options = {}) {
2187
2091
  "no-restricted-globals": [
2188
2092
  "error",
2189
2093
  {
2190
- name: "global",
2094
+ name: "self",
2191
2095
  message: "Use `globalThis` instead."
2192
2096
  },
2193
2097
  {
2194
- name: "self",
2098
+ name: "global",
2195
2099
  message: "Use `globalThis` instead."
2196
2100
  }
2197
2101
  ],
@@ -2204,10 +2108,6 @@ async function javascript(options = {}) {
2204
2108
  }],
2205
2109
  "no-restricted-properties": [
2206
2110
  "error",
2207
- {
2208
- property: "__proto__",
2209
- message: "Use `Object.getPrototypeOf` or `Object.setPrototypeOf` instead."
2210
- },
2211
2111
  {
2212
2112
  property: "__defineGetter__",
2213
2113
  message: "Use `Object.defineProperty` instead."
@@ -2223,25 +2123,28 @@ async function javascript(options = {}) {
2223
2123
  {
2224
2124
  property: "__lookupSetter__",
2225
2125
  message: "Use `Object.getOwnPropertyDescriptor` instead."
2126
+ },
2127
+ {
2128
+ property: "__proto__",
2129
+ message: "Use `Object.getPrototypeOf` or `Object.setPrototypeOf` instead."
2226
2130
  }
2227
2131
  ],
2228
2132
  ...overrides
2229
2133
  }
2230
2134
  }];
2231
2135
  }
2232
-
2233
2136
  //#endregion
2234
2137
  //#region src/configs/typescript.ts
2235
2138
  async function typescript(options = {}) {
2236
2139
  const { type = "app", overrides = {}, componentExts = [], parserOptions = {}, erasableOnly = false, overridesTypeAware = {} } = options;
2237
2140
  const files = options.files ?? [
2238
- GLOB_TS,
2239
- GLOB_TSX,
2141
+ "**/*.?([cm])ts",
2142
+ "**/*.?([cm])tsx",
2240
2143
  ...componentExts.map((ext) => `**/*.${ext}`)
2241
2144
  ];
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;
2145
+ const filesTypeAware = options.filesTypeAware ?? ["**/*.?([cm])ts", "**/*.?([cm])tsx"];
2146
+ const ignoresTypeAware = options.ignoresTypeAware ?? ["**/*.astro/*.ts", `**/*.md/**`];
2147
+ const tsconfigPath = options?.tsconfigPath;
2245
2148
  const isTypeAware = !!tsconfigPath;
2246
2149
  const typeAwareRules = {
2247
2150
  "dot-notation": "off",
@@ -2270,10 +2173,10 @@ async function typescript(options = {}) {
2270
2173
  }]
2271
2174
  };
2272
2175
  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) {
2176
+ function makeParser(typeAware, files, ignores) {
2274
2177
  return {
2275
- files: files$1,
2276
- ...ignores$1 ? { ignores: ignores$1 } : {},
2178
+ files,
2179
+ ...ignores ? { ignores } : {},
2277
2180
  name: `whoj/typescript/${typeAware ? "type-aware-parser" : "parser"}`,
2278
2181
  languageOptions: {
2279
2182
  parser: parserTs,
@@ -2363,7 +2266,7 @@ async function typescript(options = {}) {
2363
2266
  }] : [],
2364
2267
  ...erasableOnly ? [{
2365
2268
  name: "whoj/typescript/erasable-syntax-only",
2366
- plugins: { "erasable-syntax-only": await interopDefault(import("./lib-B1Rme4qD.mjs")) },
2269
+ plugins: { "erasable-syntax-only": await interopDefault(import("./lib-BR_yghPw.mjs")) },
2367
2270
  rules: {
2368
2271
  "erasable-syntax-only/enums": "error",
2369
2272
  "erasable-syntax-only/namespaces": "error",
@@ -2373,16 +2276,24 @@ async function typescript(options = {}) {
2373
2276
  }] : []
2374
2277
  ];
2375
2278
  }
2376
-
2377
2279
  //#endregion
2378
2280
  //#region src/configs/perfectionist.ts
2379
2281
  const LINE_LENGTH_REGEX = /.*(?<!classes|heritage-clauses|intersection-types|interfaces|modules|objects)$/;
2380
2282
  /**
2283
+ * Rules excluded from the blanket natural+line-length sort application:
2284
+ * - `sort-modules`: experimental, prone to false positives.
2285
+ * - `sort-arrays`: sorts *every* array literal/`new` call in a codebase (not just data
2286
+ * arrays), which corrupts semantically-ordered tuples (e.g. `Promise.all([...])`
2287
+ * destructuring pairs) when this config lints itself or any other project.
2288
+ */
2289
+ const EXCLUDED_RULES = /* @__PURE__ */ new Set(["sort-arrays", "sort-modules"]);
2290
+ /**
2381
2291
  * Perfectionist plugin for props and items sorting.
2382
2292
  *
2383
2293
  * @see https://github.com/azat-io/eslint-plugin-perfectionist
2384
2294
  */
2385
- async function perfectionist() {
2295
+ async function perfectionist(options) {
2296
+ const { overrides = {} } = options;
2386
2297
  return [{
2387
2298
  name: "whoj/perfectionist/setup",
2388
2299
  plugins: { perfectionist: pluginPerfectionist },
@@ -2394,24 +2305,24 @@ async function perfectionist() {
2394
2305
  ...getRules({
2395
2306
  order: "asc",
2396
2307
  type: "line-length"
2397
- })
2308
+ }),
2309
+ ...overrides
2398
2310
  }
2399
2311
  }];
2400
2312
  }
2401
2313
  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]]));
2314
+ return Object.fromEntries(Object.keys({ ...pluginPerfectionist.rules }).filter((ruleName) => !EXCLUDED_RULES.has(ruleName)).filter((ruleName) => options.type === "natural" ? !LINE_LENGTH_REGEX.test(ruleName) : LINE_LENGTH_REGEX.test(ruleName)).map((ruleName) => [`perfectionist/${ruleName}`, ["error", options]]));
2403
2315
  }
2404
-
2405
2316
  //#endregion
2406
2317
  //#region src/factory.ts
2407
2318
  const flatConfigProps = [
2408
2319
  "name",
2409
- "languageOptions",
2410
- "linterOptions",
2411
- "processor",
2412
- "plugins",
2413
2320
  "rules",
2414
- "settings"
2321
+ "plugins",
2322
+ "settings",
2323
+ "processor",
2324
+ "linterOptions",
2325
+ "languageOptions"
2415
2326
  ];
2416
2327
  const VuePackages = [
2417
2328
  "vue",
@@ -2427,10 +2338,7 @@ const defaultPluginRenaming = {
2427
2338
  "@stylistic": "style",
2428
2339
  "import-lite": "import",
2429
2340
  "@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"
2341
+ "@typescript-eslint": "ts"
2434
2342
  };
2435
2343
  /**
2436
2344
  * Construct an array of ESLint flat config items.
@@ -2443,7 +2351,7 @@ const defaultPluginRenaming = {
2443
2351
  * The merged ESLint configurations.
2444
2352
  */
2445
2353
  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;
2354
+ const { componentExts = [], jsx: enableJsx = true, type: appType = "app", node: enableNode = true, e18e: enableE18e = 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, perfectionist: enablePerfectionist = true, pnpm: enableCatalogs = !!findUpSync("pnpm-workspace.yaml"), vue: enableVue = VuePackages.some((i) => isPackageExists(i)), typescript: enableTypeScript = isPackageExists("typescript") || isPackageExists("@typescript/native-preview") } = options;
2447
2355
  let isInEditor = options.isInEditor;
2448
2356
  if (isInEditor == null) {
2449
2357
  isInEditor = isInEditorEnv();
@@ -2451,37 +2359,42 @@ function whoj(options = {}, ...userConfigs) {
2451
2359
  }
2452
2360
  const stylisticOptions = options.stylistic === false ? false : typeof options.stylistic === "object" ? options.stylistic : {};
2453
2361
  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({
2362
+ const configs = [];
2363
+ if (enableGitignore) if (typeof enableGitignore !== "boolean") configs.push(interopDefault(import("eslint-config-flat-gitignore")).then((r) => [r({
2456
2364
  name: "whoj/gitignore",
2457
2365
  ...enableGitignore
2458
2366
  })]));
2459
- else configs$1.push(interopDefault(import("eslint-config-flat-gitignore")).then((r) => [r({
2367
+ else configs.push(interopDefault(import("eslint-config-flat-gitignore")).then((r) => [r({
2460
2368
  strict: false,
2461
2369
  name: "whoj/gitignore"
2462
2370
  })]));
2463
2371
  const typescriptOptions = resolveSubOptions(options, "typescript");
2464
2372
  const tsconfigPath = "tsconfigPath" in typescriptOptions ? typescriptOptions.tsconfigPath : void 0;
2465
- configs$1.push(ignores(userIgnores, !enableTypeScript), javascript({
2373
+ configs.push(ignores(userIgnores, !enableTypeScript), javascript({
2466
2374
  isInEditor,
2467
2375
  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({
2376
+ }), comments(), command());
2377
+ if (enablePerfectionist) configs.push(perfectionist({ overrides: getOverrides(options, "perfectionist") }));
2378
+ if (enableNode) configs.push(node());
2379
+ if (enableJsdoc) configs.push(jsdoc({ stylistic: stylisticOptions }));
2380
+ if (enableImports) configs.push(imports({
2472
2381
  stylistic: stylisticOptions,
2473
2382
  ...resolveSubOptions(options, "imports")
2474
2383
  }));
2475
- if (enableUnicorn) configs$1.push(unicorn(enableUnicorn === true ? {} : enableUnicorn));
2384
+ if (enableE18e) configs.push(e18e({
2385
+ isInEditor,
2386
+ ...enableE18e === true ? {} : enableE18e
2387
+ }));
2388
+ if (enableUnicorn) configs.push(unicorn(enableUnicorn === true ? {} : enableUnicorn));
2476
2389
  if (enableVue) componentExts.push("vue");
2477
- if (enableJsx) configs$1.push(jsx(enableJsx === true ? {} : enableJsx));
2478
- if (enableTypeScript) configs$1.push(typescript({
2390
+ if (enableJsx) configs.push(jsx(enableJsx === true ? {} : enableJsx));
2391
+ if (enableTypeScript) configs.push(typescript({
2479
2392
  ...typescriptOptions,
2480
2393
  componentExts,
2481
- type: options.type,
2394
+ type: appType,
2482
2395
  overrides: getOverrides(options, "typescript")
2483
2396
  }));
2484
- if (stylisticOptions) configs$1.push(stylistic({
2397
+ if (stylisticOptions) configs.push(stylistic({
2485
2398
  ...stylisticOptions,
2486
2399
  lessOpinionated: options.lessOpinionated,
2487
2400
  overrides: {
@@ -2492,71 +2405,71 @@ function whoj(options = {}, ...userConfigs) {
2492
2405
  ...getOverrides(options, "stylistic")
2493
2406
  }
2494
2407
  }));
2495
- if (enableRegexp) configs$1.push(regexp(typeof enableRegexp === "boolean" ? {} : enableRegexp));
2496
- if (options.test ?? true) configs$1.push(test({
2408
+ if (enableRegexp) configs.push(regexp(typeof enableRegexp === "boolean" ? {} : enableRegexp));
2409
+ if (options.test ?? true) configs.push(test({
2497
2410
  isInEditor,
2498
2411
  overrides: getOverrides(options, "test")
2499
2412
  }));
2500
- if (enableVue) configs$1.push(vue({
2413
+ if (enableVue) configs.push(vue({
2501
2414
  ...resolveSubOptions(options, "vue"),
2502
2415
  stylistic: stylisticOptions,
2503
2416
  typescript: !!enableTypeScript,
2504
2417
  overrides: getOverrides(options, "vue")
2505
2418
  }));
2506
- if (enableReact) configs$1.push(react({
2419
+ if (enableReact) configs.push(react({
2507
2420
  ...typescriptOptions,
2508
2421
  ...resolveSubOptions(options, "react"),
2509
2422
  tsconfigPath,
2510
2423
  overrides: getOverrides(options, "react")
2511
2424
  }));
2512
- if (enableNextjs) configs$1.push(nextjs({ overrides: getOverrides(options, "nextjs") }));
2513
- if (enableSolid) configs$1.push(solid({
2425
+ if (enableNextjs) configs.push(nextjs({ overrides: getOverrides(options, "nextjs") }));
2426
+ if (enableSolid) configs.push(solid({
2514
2427
  tsconfigPath,
2515
2428
  typescript: !!enableTypeScript,
2516
2429
  overrides: getOverrides(options, "solid")
2517
2430
  }));
2518
- if (enableSvelte) configs$1.push(svelte({
2431
+ if (enableSvelte) configs.push(svelte({
2519
2432
  stylistic: stylisticOptions,
2520
2433
  typescript: !!enableTypeScript,
2521
2434
  overrides: getOverrides(options, "svelte")
2522
2435
  }));
2523
- if (enableUnoCSS) configs$1.push(unocss({
2436
+ if (enableUnoCSS) configs.push(unocss({
2524
2437
  ...resolveSubOptions(options, "unocss"),
2525
2438
  overrides: getOverrides(options, "unocss")
2526
2439
  }));
2527
- if (enableAstro) configs$1.push(astro({
2440
+ if (enableAstro) configs.push(astro({
2528
2441
  stylistic: stylisticOptions,
2529
2442
  overrides: getOverrides(options, "astro")
2530
2443
  }));
2531
- if (enableAngular) configs$1.push(angular({ overrides: getOverrides(options, "angular") }));
2532
- if (options.jsonc ?? true) configs$1.push(jsonc({
2444
+ if (enableAngular) configs.push(angular({ overrides: getOverrides(options, "angular") }));
2445
+ if (options.jsonc ?? true) configs.push(jsonc({
2533
2446
  stylistic: stylisticOptions,
2534
2447
  overrides: getOverrides(options, "jsonc")
2535
2448
  }), sortPackageJson(), sortTsconfig());
2536
2449
  if (enableCatalogs) {
2537
2450
  const optionsPnpm = resolveSubOptions(options, "pnpm");
2538
- configs$1.push(pnpm({
2451
+ configs.push(pnpm({
2539
2452
  isInEditor,
2540
2453
  yaml: options.yaml !== false,
2541
2454
  json: options.jsonc !== false,
2542
2455
  ...optionsPnpm
2543
2456
  }));
2544
2457
  }
2545
- if (options.yaml ?? true) configs$1.push(yaml({
2458
+ if (options.yaml ?? true) configs.push(yaml({
2546
2459
  stylistic: stylisticOptions,
2547
2460
  overrides: getOverrides(options, "yaml")
2548
2461
  }));
2549
- if (options.toml ?? true) configs$1.push(toml({
2462
+ if (options.toml ?? true) configs.push(toml({
2550
2463
  stylistic: stylisticOptions,
2551
2464
  overrides: getOverrides(options, "toml")
2552
2465
  }));
2553
- if (options.markdown ?? true) configs$1.push(markdown({
2466
+ if (options.markdown ?? true) configs.push(markdown({
2554
2467
  componentExts,
2555
2468
  overrides: getOverrides(options, "markdown")
2556
2469
  }));
2557
- if (options.formatters) configs$1.push(formatters(options.formatters, typeof stylisticOptions === "boolean" ? {} : stylisticOptions));
2558
- configs$1.push(disables());
2559
- configs$1.push([{ rules: {
2470
+ if (options.formatters) configs.push(formatters(options.formatters, typeof stylisticOptions === "boolean" ? {} : stylisticOptions));
2471
+ configs.push(disables());
2472
+ configs.push([{ rules: {
2560
2473
  "eqeqeq": "warn",
2561
2474
  "require-await": "off",
2562
2475
  "no-useless-escape": "warn"
@@ -2566,14 +2479,15 @@ function whoj(options = {}, ...userConfigs) {
2566
2479
  if (key in options) acc[key] = options[key];
2567
2480
  return acc;
2568
2481
  }, {});
2569
- if (Object.keys(fusedConfig).length) configs$1.push([fusedConfig]);
2482
+ if (Object.keys(fusedConfig).length) configs.push([fusedConfig]);
2570
2483
  let composer = new FlatConfigComposer();
2571
- composer = composer.append(...configs$1, ...userConfigs);
2484
+ composer = composer.append(...configs, ...userConfigs);
2485
+ if (options.markdown ?? true) composer = composer.setDefaultIgnores((prev) => [...prev, GLOB_MARKDOWN]);
2572
2486
  if (autoRenamePlugins) composer = composer.renamePlugins(defaultPluginRenaming);
2573
2487
  if (isInEditor) composer = composer.disableRulesFix([
2574
- "unused-imports/no-unused-imports",
2488
+ "prefer-const",
2575
2489
  "test/no-only-tests",
2576
- "prefer-const"
2490
+ "unused-imports/no-unused-imports"
2577
2491
  ], { builtinRules: () => import(["eslint", "use-at-your-own-risk"].join("/")).then((r) => r.builtinRules) });
2578
2492
  return composer;
2579
2493
  }
@@ -2587,7 +2501,6 @@ function getOverrides(options, key) {
2587
2501
  ..."overrides" in sub ? sub.overrides : {}
2588
2502
  };
2589
2503
  }
2590
-
2591
2504
  //#endregion
2592
2505
  //#region src/config-presets.ts
2593
2506
  const CONFIG_PRESET_FULL_ON = {
@@ -2599,6 +2512,7 @@ const CONFIG_PRESET_FULL_ON = {
2599
2512
  astro: true,
2600
2513
  jsdoc: true,
2601
2514
  jsonc: true,
2515
+ react: true,
2602
2516
  solid: true,
2603
2517
  nextjs: true,
2604
2518
  regexp: true,
@@ -2610,9 +2524,9 @@ const CONFIG_PRESET_FULL_ON = {
2610
2524
  markdown: true,
2611
2525
  gitignore: true,
2612
2526
  formatters: true,
2527
+ perfectionist: true,
2613
2528
  jsx: { a11y: true },
2614
2529
  vue: { a11y: true },
2615
- react: { reactCompiler: true },
2616
2530
  stylistic: { experimental: true },
2617
2531
  typescript: {
2618
2532
  erasableOnly: true,
@@ -2643,12 +2557,11 @@ const CONFIG_PRESET_FULL_OFF = {
2643
2557
  gitignore: false,
2644
2558
  stylistic: false,
2645
2559
  formatters: false,
2646
- typescript: false
2560
+ typescript: false,
2561
+ perfectionist: false
2647
2562
  };
2648
-
2649
2563
  //#endregion
2650
2564
  //#region src/index.ts
2651
2565
  var src_default = whoj;
2652
-
2653
2566
  //#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 };
2567
+ 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 };