@2030/eslint-config 0.0.8 → 1.0.0-beta.1

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