@kirklin/eslint-config 2.3.1 → 2.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -4,33 +4,6 @@ import fs from "node:fs";
4
4
  import { isPackageExists as isPackageExists4 } from "local-pkg";
5
5
  import { FlatConfigComposer } from "eslint-flat-config-utils";
6
6
 
7
- // src/plugins.ts
8
- import { default as default2 } from "eslint-plugin-kirklin";
9
- import { default as default3 } from "eslint-plugin-eslint-comments";
10
- import * as pluginImport from "eslint-plugin-import-x";
11
- import { default as default4 } from "eslint-plugin-n";
12
- import { default as default5 } from "eslint-plugin-unicorn";
13
- import { default as default6 } from "eslint-plugin-unused-imports";
14
- import { default as default7 } from "eslint-plugin-perfectionist";
15
-
16
- // src/configs/comments.ts
17
- async function comments() {
18
- return [
19
- {
20
- name: "kirklin/eslint-comments/rules",
21
- plugins: {
22
- "eslint-comments": default3
23
- },
24
- rules: {
25
- "eslint-comments/no-aggregating-enable": "error",
26
- "eslint-comments/no-duplicate-disable": "error",
27
- "eslint-comments/no-unlimited-disable": "error",
28
- "eslint-comments/no-unused-enable": "error"
29
- }
30
- }
31
- ];
32
- }
33
-
34
7
  // src/globs.ts
35
8
  var GLOB_SRC_EXT = "?([cm])[jt]s?(x)";
36
9
  var GLOB_SRC = "**/*.?([cm])[jt]s?(x)";
@@ -106,127 +79,568 @@ var GLOB_EXCLUDE = [
106
79
  "**/components.d.ts"
107
80
  ];
108
81
 
109
- // src/configs/ignores.ts
110
- async function ignores() {
111
- return [
112
- {
113
- ignores: GLOB_EXCLUDE
114
- // Awaits https://github.com/humanwhocodes/config-array/pull/131
115
- // name: 'kirklin/ignores',
82
+ // src/utils.ts
83
+ import process from "node:process";
84
+ import { isPackageExists } from "local-pkg";
85
+ var parserPlain = {
86
+ meta: {
87
+ name: "parser-plain"
88
+ },
89
+ parseForESLint: (code) => ({
90
+ ast: {
91
+ body: [],
92
+ comments: [],
93
+ loc: { end: code.length, start: 0 },
94
+ range: [0, code.length],
95
+ tokens: [],
96
+ type: "Program"
97
+ },
98
+ scopeManager: null,
99
+ services: { isPlain: true },
100
+ visitorKeys: {
101
+ Program: []
116
102
  }
117
- ];
103
+ })
104
+ };
105
+ async function combine(...configs) {
106
+ const resolved = await Promise.all(configs);
107
+ return resolved.flat();
108
+ }
109
+ function renameRules(rules, map) {
110
+ return Object.fromEntries(
111
+ Object.entries(rules).map(([key, value]) => {
112
+ for (const [from, to] of Object.entries(map)) {
113
+ if (key.startsWith(`${from}/`)) {
114
+ return [to + key.slice(from.length), value];
115
+ }
116
+ }
117
+ return [key, value];
118
+ })
119
+ );
120
+ }
121
+ function renamePluginInConfigs(configs, map) {
122
+ return configs.map((i) => {
123
+ const clone = { ...i };
124
+ if (clone.rules) {
125
+ clone.rules = renameRules(clone.rules, map);
126
+ }
127
+ if (clone.plugins) {
128
+ clone.plugins = Object.fromEntries(
129
+ Object.entries(clone.plugins).map(([key, value]) => {
130
+ if (key in map) {
131
+ return [map[key], value];
132
+ }
133
+ return [key, value];
134
+ })
135
+ );
136
+ }
137
+ return clone;
138
+ });
139
+ }
140
+ function toArray(value) {
141
+ return Array.isArray(value) ? value : [value];
142
+ }
143
+ async function interopDefault(m) {
144
+ const resolved = await m;
145
+ return resolved.default || resolved;
146
+ }
147
+ async function ensurePackages(packages) {
148
+ if (process.env.CI || process.stdout.isTTY === false) {
149
+ return;
150
+ }
151
+ const nonExistingPackages = packages.filter((i) => i && !isPackageExists(i));
152
+ if (nonExistingPackages.length === 0) {
153
+ return;
154
+ }
155
+ const p = await import("@clack/prompts");
156
+ const result = await p.confirm({
157
+ message: `${nonExistingPackages.length === 1 ? "Package is" : "Packages are"} required for this config: ${nonExistingPackages.join(", ")}. Do you want to install them?`
158
+ });
159
+ if (result) {
160
+ await import("@antfu/install-pkg").then((i) => i.installPackage(nonExistingPackages, { dev: true }));
161
+ }
118
162
  }
119
163
 
120
- // src/configs/imports.ts
121
- async function imports(options = {}) {
164
+ // src/configs/astro.ts
165
+ async function astro(options = {}) {
122
166
  const {
167
+ files = [GLOB_ASTRO],
168
+ overrides = {},
123
169
  stylistic: stylistic2 = true
124
170
  } = options;
171
+ const [
172
+ pluginAstro,
173
+ parserAstro,
174
+ parserTs
175
+ ] = await Promise.all([
176
+ interopDefault(import("eslint-plugin-astro")),
177
+ interopDefault(import("astro-eslint-parser")),
178
+ interopDefault(import("@typescript-eslint/parser"))
179
+ ]);
125
180
  return [
126
181
  {
127
- name: "kirklin/imports/rules",
182
+ name: "kirklin/astro/setup",
128
183
  plugins: {
129
- import: pluginImport,
130
- kirklin: default2
131
- },
132
- rules: {
133
- "import/first": "error",
134
- "import/no-duplicates": "error",
135
- "import/no-mutable-exports": "error",
136
- "import/no-named-default": "error",
137
- "import/no-self-import": "error",
138
- "import/no-webpack-loader-syntax": "error",
139
- "import/order": "error",
140
- "kirklin/import-dedupe": "error",
141
- "kirklin/no-import-dist": "error",
142
- "kirklin/no-import-node-modules-by-path": "error",
143
- ...stylistic2 ? {
144
- "import/newline-after-import": ["error", { count: 1 }]
145
- } : {}
184
+ astro: pluginAstro
146
185
  }
147
186
  },
148
187
  {
149
- files: ["**/bin/**/*", `**/bin.${GLOB_SRC_EXT}`],
150
- name: "kirklin/imports/disables/bin",
188
+ files,
189
+ languageOptions: {
190
+ parser: parserAstro,
191
+ parserOptions: {
192
+ extraFileExtensions: [".astro"],
193
+ parser: parserTs
194
+ }
195
+ },
196
+ name: "kirklin/astro/rules",
151
197
  rules: {
152
- "kirklin/no-import-dist": "off",
153
- "kirklin/no-import-node-modules-by-path": "off"
198
+ "astro/no-set-html-directive": "off",
199
+ ...stylistic2 ? {
200
+ "style/indent": "off",
201
+ "style/jsx-closing-tag-location": "off",
202
+ "style/jsx-indent": "off",
203
+ "style/jsx-one-expression-per-line": "off",
204
+ "style/no-multiple-empty-lines": "off"
205
+ } : {},
206
+ ...overrides
154
207
  }
155
208
  }
156
209
  ];
157
210
  }
158
211
 
159
- // src/configs/javascript.ts
160
- import globals from "globals";
161
- async function javascript(options = {}) {
162
- const {
163
- isInEditor = false,
164
- overrides = {}
165
- } = options;
212
+ // src/configs/command.ts
213
+ import createCommand from "eslint-plugin-command/config";
214
+ async function command() {
166
215
  return [
167
216
  {
168
- languageOptions: {
169
- ecmaVersion: 2022,
170
- globals: {
171
- ...globals.browser,
172
- ...globals.es2021,
173
- ...globals.node,
174
- document: "readonly",
175
- navigator: "readonly",
176
- window: "readonly"
177
- },
178
- parserOptions: {
179
- ecmaFeatures: {
180
- jsx: true
181
- },
182
- ecmaVersion: 2022,
183
- sourceType: "module"
184
- },
185
- sourceType: "module"
186
- },
187
- linterOptions: {
188
- reportUnusedDisableDirectives: true
189
- },
190
- name: "kirklin/javascript/rules",
217
+ ...createCommand(),
218
+ name: "kirklin/command/rules"
219
+ }
220
+ ];
221
+ }
222
+
223
+ // src/plugins.ts
224
+ import { default as default2 } from "eslint-plugin-kirklin";
225
+ import { default as default3 } from "eslint-plugin-eslint-comments";
226
+ import * as pluginImport from "eslint-plugin-import-x";
227
+ import { default as default4 } from "eslint-plugin-n";
228
+ import { default as default5 } from "eslint-plugin-unicorn";
229
+ import { default as default6 } from "eslint-plugin-unused-imports";
230
+ import { default as default7 } from "eslint-plugin-perfectionist";
231
+
232
+ // src/configs/comments.ts
233
+ async function comments() {
234
+ return [
235
+ {
236
+ name: "kirklin/eslint-comments/rules",
191
237
  plugins: {
192
- "kirklin": default2,
193
- "unused-imports": default6
238
+ "eslint-comments": default3
194
239
  },
195
240
  rules: {
196
- "accessor-pairs": ["error", { enforceForClassMembers: true, setWithoutGet: true }],
197
- "array-callback-return": "error",
198
- "block-scoped-var": "error",
199
- "constructor-super": "error",
200
- "default-case-last": "error",
201
- "dot-notation": ["error", { allowKeywords: true }],
202
- "eqeqeq": ["error", "smart"],
203
- "new-cap": ["error", { capIsNew: false, newIsCap: true, properties: true }],
204
- "no-alert": "error",
205
- "no-array-constructor": "error",
206
- "no-async-promise-executor": "error",
207
- "no-caller": "error",
208
- "no-case-declarations": "error",
209
- "no-class-assign": "error",
210
- "no-compare-neg-zero": "error",
211
- "no-cond-assign": ["error", "always"],
212
- "no-console": ["error", { allow: ["warn", "error"] }],
213
- "no-const-assign": "error",
214
- "no-control-regex": "error",
215
- "no-debugger": "error",
216
- "no-delete-var": "error",
217
- "no-dupe-args": "error",
218
- "no-dupe-class-members": "error",
219
- "no-dupe-keys": "error",
220
- "no-duplicate-case": "error",
221
- "no-empty": ["error", { allowEmptyCatch: true }],
222
- "no-empty-character-class": "error",
223
- "no-empty-pattern": "error",
224
- "no-eval": "error",
225
- "no-ex-assign": "error",
226
- "no-extend-native": "error",
227
- "no-extra-bind": "error",
228
- "no-extra-boolean-cast": "error",
229
- "no-fallthrough": "error",
241
+ "eslint-comments/no-aggregating-enable": "error",
242
+ "eslint-comments/no-duplicate-disable": "error",
243
+ "eslint-comments/no-unlimited-disable": "error",
244
+ "eslint-comments/no-unused-enable": "error"
245
+ }
246
+ }
247
+ ];
248
+ }
249
+
250
+ // src/configs/formatters.ts
251
+ import { isPackageExists as isPackageExists2 } from "local-pkg";
252
+
253
+ // src/configs/stylistic.ts
254
+ var StylisticConfigDefaults = {
255
+ indent: 2,
256
+ jsx: true,
257
+ quotes: "double",
258
+ semi: true
259
+ };
260
+ async function stylistic(options = {}) {
261
+ const {
262
+ indent,
263
+ jsx,
264
+ lessOpinionated = false,
265
+ overrides = {},
266
+ quotes,
267
+ semi
268
+ } = {
269
+ ...StylisticConfigDefaults,
270
+ ...options
271
+ };
272
+ const pluginStylistic = await interopDefault(import("@stylistic/eslint-plugin"));
273
+ const config = pluginStylistic.configs.customize({
274
+ flat: true,
275
+ indent,
276
+ jsx,
277
+ pluginName: "style",
278
+ quotes,
279
+ semi
280
+ });
281
+ return [
282
+ {
283
+ name: "kirklin/stylistic/rules",
284
+ plugins: {
285
+ kirklin: default2,
286
+ style: pluginStylistic
287
+ },
288
+ rules: {
289
+ ...config.rules,
290
+ "kirklin/consistent-list-newline": "error",
291
+ "style/brace-style": ["error", "1tbs", { allowSingleLine: false }],
292
+ "style/member-delimiter-style": ["error", { multiline: { delimiter: "semi" } }],
293
+ ...lessOpinionated ? {
294
+ curly: ["error", "multi-or-nest", "consistent"]
295
+ } : {
296
+ "curly": ["error", "all"],
297
+ "kirklin/if-newline": "error",
298
+ "kirklin/top-level-function": "error"
299
+ },
300
+ ...overrides
301
+ }
302
+ }
303
+ ];
304
+ }
305
+
306
+ // src/configs/formatters.ts
307
+ async function formatters(options = {}, stylistic2 = {}) {
308
+ if (options === true) {
309
+ options = {
310
+ astro: isPackageExists2("astro"),
311
+ css: true,
312
+ graphql: true,
313
+ html: true,
314
+ markdown: true,
315
+ slidev: isPackageExists2("@slidev/cli")
316
+ };
317
+ }
318
+ await ensurePackages([
319
+ "eslint-plugin-format",
320
+ options.markdown && options.slidev ? "prettier-plugin-slidev" : void 0,
321
+ options.astro ? "prettier-plugin-astro" : void 0
322
+ ]);
323
+ if (options.slidev && options.markdown !== true && options.markdown !== "prettier") {
324
+ throw new Error("`slidev` option only works when `markdown` is enabled with `prettier`");
325
+ }
326
+ const {
327
+ indent,
328
+ quotes,
329
+ semi
330
+ } = {
331
+ ...StylisticConfigDefaults,
332
+ ...stylistic2
333
+ };
334
+ const prettierOptions = Object.assign(
335
+ {
336
+ endOfLine: "auto",
337
+ semi,
338
+ singleQuote: quotes === "single",
339
+ tabWidth: typeof indent === "number" ? indent : 2,
340
+ trailingComma: "all",
341
+ useTabs: indent === "tab"
342
+ },
343
+ options.prettierOptions || {}
344
+ );
345
+ const dprintOptions = Object.assign(
346
+ {
347
+ indentWidth: typeof indent === "number" ? indent : 2,
348
+ quoteStyle: quotes === "single" ? "preferSingle" : "preferDouble",
349
+ useTabs: indent === "tab"
350
+ },
351
+ options.dprintOptions || {}
352
+ );
353
+ const pluginFormat = await interopDefault(import("eslint-plugin-format"));
354
+ const configs = [
355
+ {
356
+ name: "kirklin/formatter/setup",
357
+ plugins: {
358
+ format: pluginFormat
359
+ }
360
+ }
361
+ ];
362
+ if (options.css) {
363
+ configs.push(
364
+ {
365
+ files: [GLOB_CSS, GLOB_POSTCSS],
366
+ languageOptions: {
367
+ parser: parserPlain
368
+ },
369
+ name: "kirklin/formatter/css",
370
+ rules: {
371
+ "format/prettier": [
372
+ "error",
373
+ {
374
+ ...prettierOptions,
375
+ parser: "css"
376
+ }
377
+ ]
378
+ }
379
+ },
380
+ {
381
+ files: [GLOB_SCSS],
382
+ languageOptions: {
383
+ parser: parserPlain
384
+ },
385
+ name: "kirklin/formatter/scss",
386
+ rules: {
387
+ "format/prettier": [
388
+ "error",
389
+ {
390
+ ...prettierOptions,
391
+ parser: "scss"
392
+ }
393
+ ]
394
+ }
395
+ },
396
+ {
397
+ files: [GLOB_LESS],
398
+ languageOptions: {
399
+ parser: parserPlain
400
+ },
401
+ name: "kirklin/formatter/less",
402
+ rules: {
403
+ "format/prettier": [
404
+ "error",
405
+ {
406
+ ...prettierOptions,
407
+ parser: "less"
408
+ }
409
+ ]
410
+ }
411
+ }
412
+ );
413
+ }
414
+ if (options.html) {
415
+ configs.push({
416
+ files: [GLOB_HTML],
417
+ languageOptions: {
418
+ parser: parserPlain
419
+ },
420
+ name: "kirklin/formatter/html",
421
+ rules: {
422
+ "format/prettier": [
423
+ "error",
424
+ {
425
+ ...prettierOptions,
426
+ parser: "html"
427
+ }
428
+ ]
429
+ }
430
+ });
431
+ }
432
+ if (options.markdown) {
433
+ const formater = options.markdown === true ? "prettier" : options.markdown;
434
+ const GLOB_SLIDEV = !options.slidev ? [] : options.slidev === true ? ["**/slides.md"] : options.slidev.files;
435
+ configs.push({
436
+ files: [GLOB_MARKDOWN],
437
+ ignores: GLOB_SLIDEV,
438
+ languageOptions: {
439
+ parser: parserPlain
440
+ },
441
+ name: "kirklin/formatter/markdown",
442
+ rules: {
443
+ [`format/${formater}`]: [
444
+ "error",
445
+ formater === "prettier" ? {
446
+ printWidth: 120,
447
+ ...prettierOptions,
448
+ embeddedLanguageFormatting: "off",
449
+ parser: "markdown"
450
+ } : {
451
+ ...dprintOptions,
452
+ language: "markdown"
453
+ }
454
+ ]
455
+ }
456
+ });
457
+ if (options.slidev) {
458
+ configs.push({
459
+ files: GLOB_SLIDEV,
460
+ languageOptions: {
461
+ parser: parserPlain
462
+ },
463
+ name: "kirklin/formatter/slidev",
464
+ rules: {
465
+ "format/prettier": [
466
+ "error",
467
+ {
468
+ printWidth: 120,
469
+ ...prettierOptions,
470
+ embeddedLanguageFormatting: "off",
471
+ parser: "slidev",
472
+ plugins: [
473
+ "prettier-plugin-slidev"
474
+ ]
475
+ }
476
+ ]
477
+ }
478
+ });
479
+ }
480
+ }
481
+ if (options.astro) {
482
+ configs.push({
483
+ files: [GLOB_ASTRO],
484
+ languageOptions: {
485
+ parser: parserPlain
486
+ },
487
+ name: "kirklin/formatter/astro",
488
+ rules: {
489
+ "format/prettier": [
490
+ "error",
491
+ {
492
+ ...prettierOptions,
493
+ parser: "astro",
494
+ plugins: [
495
+ "prettier-plugin-astro"
496
+ ]
497
+ }
498
+ ]
499
+ }
500
+ });
501
+ }
502
+ if (options.graphql) {
503
+ configs.push({
504
+ files: [GLOB_GRAPHQL],
505
+ languageOptions: {
506
+ parser: parserPlain
507
+ },
508
+ name: "kirklin/formatter/graphql",
509
+ rules: {
510
+ "format/prettier": [
511
+ "error",
512
+ {
513
+ ...prettierOptions,
514
+ parser: "graphql"
515
+ }
516
+ ]
517
+ }
518
+ });
519
+ }
520
+ return configs;
521
+ }
522
+
523
+ // src/configs/ignores.ts
524
+ async function ignores() {
525
+ return [
526
+ {
527
+ ignores: GLOB_EXCLUDE
528
+ // Awaits https://github.com/humanwhocodes/config-array/pull/131
529
+ // name: 'kirklin/ignores',
530
+ }
531
+ ];
532
+ }
533
+
534
+ // src/configs/imports.ts
535
+ async function imports(options = {}) {
536
+ const {
537
+ stylistic: stylistic2 = true
538
+ } = options;
539
+ return [
540
+ {
541
+ name: "kirklin/imports/rules",
542
+ plugins: {
543
+ import: pluginImport,
544
+ kirklin: default2
545
+ },
546
+ rules: {
547
+ "import/first": "error",
548
+ "import/no-duplicates": "error",
549
+ "import/no-mutable-exports": "error",
550
+ "import/no-named-default": "error",
551
+ "import/no-self-import": "error",
552
+ "import/no-webpack-loader-syntax": "error",
553
+ "import/order": "error",
554
+ "kirklin/import-dedupe": "error",
555
+ "kirklin/no-import-dist": "error",
556
+ "kirklin/no-import-node-modules-by-path": "error",
557
+ ...stylistic2 ? {
558
+ "import/newline-after-import": ["error", { count: 1 }]
559
+ } : {}
560
+ }
561
+ },
562
+ {
563
+ files: ["**/bin/**/*", `**/bin.${GLOB_SRC_EXT}`],
564
+ name: "kirklin/imports/disables/bin",
565
+ rules: {
566
+ "kirklin/no-import-dist": "off",
567
+ "kirklin/no-import-node-modules-by-path": "off"
568
+ }
569
+ }
570
+ ];
571
+ }
572
+
573
+ // src/configs/javascript.ts
574
+ import globals from "globals";
575
+ async function javascript(options = {}) {
576
+ const {
577
+ isInEditor = false,
578
+ overrides = {}
579
+ } = options;
580
+ return [
581
+ {
582
+ languageOptions: {
583
+ ecmaVersion: 2022,
584
+ globals: {
585
+ ...globals.browser,
586
+ ...globals.es2021,
587
+ ...globals.node,
588
+ document: "readonly",
589
+ navigator: "readonly",
590
+ window: "readonly"
591
+ },
592
+ parserOptions: {
593
+ ecmaFeatures: {
594
+ jsx: true
595
+ },
596
+ ecmaVersion: 2022,
597
+ sourceType: "module"
598
+ },
599
+ sourceType: "module"
600
+ },
601
+ linterOptions: {
602
+ reportUnusedDisableDirectives: true
603
+ },
604
+ name: "kirklin/javascript/rules",
605
+ plugins: {
606
+ "kirklin": default2,
607
+ "unused-imports": default6
608
+ },
609
+ rules: {
610
+ "accessor-pairs": ["error", { enforceForClassMembers: true, setWithoutGet: true }],
611
+ "array-callback-return": "error",
612
+ "block-scoped-var": "error",
613
+ "constructor-super": "error",
614
+ "default-case-last": "error",
615
+ "dot-notation": ["error", { allowKeywords: true }],
616
+ "eqeqeq": ["error", "smart"],
617
+ "new-cap": ["error", { capIsNew: false, newIsCap: true, properties: true }],
618
+ "no-alert": "error",
619
+ "no-array-constructor": "error",
620
+ "no-async-promise-executor": "error",
621
+ "no-caller": "error",
622
+ "no-case-declarations": "error",
623
+ "no-class-assign": "error",
624
+ "no-compare-neg-zero": "error",
625
+ "no-cond-assign": ["error", "always"],
626
+ "no-console": ["error", { allow: ["warn", "error"] }],
627
+ "no-const-assign": "error",
628
+ "no-control-regex": "error",
629
+ "no-debugger": "error",
630
+ "no-delete-var": "error",
631
+ "no-dupe-args": "error",
632
+ "no-dupe-class-members": "error",
633
+ "no-dupe-keys": "error",
634
+ "no-duplicate-case": "error",
635
+ "no-empty": ["error", { allowEmptyCatch: true }],
636
+ "no-empty-character-class": "error",
637
+ "no-empty-pattern": "error",
638
+ "no-eval": "error",
639
+ "no-ex-assign": "error",
640
+ "no-extend-native": "error",
641
+ "no-extra-bind": "error",
642
+ "no-extra-boolean-cast": "error",
643
+ "no-fallthrough": "error",
230
644
  "no-func-assign": "error",
231
645
  "no-global-assign": "error",
232
646
  "no-implied-eval": "error",
@@ -358,106 +772,24 @@ async function javascript(options = {}) {
358
772
  argsIgnorePattern: "^_",
359
773
  ignoreRestSiblings: true,
360
774
  vars: "all",
361
- varsIgnorePattern: "^_"
362
- }
363
- ],
364
- "use-isnan": ["error", { enforceForIndexOf: true, enforceForSwitchCase: true }],
365
- "valid-typeof": ["error", { requireStringLiterals: true }],
366
- "vars-on-top": "error",
367
- "yoda": ["error", "never"],
368
- ...overrides
369
- }
370
- },
371
- {
372
- files: [`scripts/${GLOB_SRC}`, `cli.${GLOB_SRC_EXT}`],
373
- name: "kirklin/javascript/disables/cli",
374
- rules: {
375
- "no-console": "off"
376
- }
377
- }
378
- ];
379
- }
380
-
381
- // src/utils.ts
382
- import process from "node:process";
383
- import { isPackageExists } from "local-pkg";
384
- var parserPlain = {
385
- meta: {
386
- name: "parser-plain"
387
- },
388
- parseForESLint: (code) => ({
389
- ast: {
390
- body: [],
391
- comments: [],
392
- loc: { end: code.length, start: 0 },
393
- range: [0, code.length],
394
- tokens: [],
395
- type: "Program"
396
- },
397
- scopeManager: null,
398
- services: { isPlain: true },
399
- visitorKeys: {
400
- Program: []
401
- }
402
- })
403
- };
404
- async function combine(...configs) {
405
- const resolved = await Promise.all(configs);
406
- return resolved.flat();
407
- }
408
- function renameRules(rules, map) {
409
- return Object.fromEntries(
410
- Object.entries(rules).map(([key, value]) => {
411
- for (const [from, to] of Object.entries(map)) {
412
- if (key.startsWith(`${from}/`)) {
413
- return [to + key.slice(from.length), value];
414
- }
415
- }
416
- return [key, value];
417
- })
418
- );
419
- }
420
- function renamePluginInConfigs(configs, map) {
421
- return configs.map((i) => {
422
- const clone = { ...i };
423
- if (clone.rules) {
424
- clone.rules = renameRules(clone.rules, map);
425
- }
426
- if (clone.plugins) {
427
- clone.plugins = Object.fromEntries(
428
- Object.entries(clone.plugins).map(([key, value]) => {
429
- if (key in map) {
430
- return [map[key], value];
431
- }
432
- return [key, value];
433
- })
434
- );
775
+ varsIgnorePattern: "^_"
776
+ }
777
+ ],
778
+ "use-isnan": ["error", { enforceForIndexOf: true, enforceForSwitchCase: true }],
779
+ "valid-typeof": ["error", { requireStringLiterals: true }],
780
+ "vars-on-top": "error",
781
+ "yoda": ["error", "never"],
782
+ ...overrides
783
+ }
784
+ },
785
+ {
786
+ files: [`scripts/${GLOB_SRC}`, `cli.${GLOB_SRC_EXT}`],
787
+ name: "kirklin/javascript/disables/cli",
788
+ rules: {
789
+ "no-console": "off"
790
+ }
435
791
  }
436
- return clone;
437
- });
438
- }
439
- function toArray(value) {
440
- return Array.isArray(value) ? value : [value];
441
- }
442
- async function interopDefault(m) {
443
- const resolved = await m;
444
- return resolved.default || resolved;
445
- }
446
- async function ensurePackages(packages) {
447
- if (process.env.CI || process.stdout.isTTY === false) {
448
- return;
449
- }
450
- const nonExistingPackages = packages.filter((i) => i && !isPackageExists(i));
451
- if (nonExistingPackages.length === 0) {
452
- return;
453
- }
454
- const p = await import("@clack/prompts");
455
- const result = await p.confirm({
456
- message: `${nonExistingPackages.length === 1 ? "Package is" : "Packages are"} required for this config: ${nonExistingPackages.join(", ")}. Do you want to install them?`
457
- });
458
- if (result) {
459
- await import("@antfu/install-pkg").then((i) => i.installPackage(nonExistingPackages, { dev: true }));
460
- }
792
+ ];
461
793
  }
462
794
 
463
795
  // src/configs/jsdoc.ts
@@ -483,496 +815,223 @@ async function jsdoc(options = {}) {
483
815
  "jsdoc/require-param-name": "warn",
484
816
  "jsdoc/require-property": "warn",
485
817
  "jsdoc/require-property-description": "warn",
486
- "jsdoc/require-property-name": "warn",
487
- "jsdoc/require-returns-check": "warn",
488
- "jsdoc/require-returns-description": "warn",
489
- "jsdoc/require-yields-check": "warn",
490
- ...stylistic2 ? {
491
- "jsdoc/check-alignment": "warn",
492
- "jsdoc/multiline-blocks": "warn"
493
- } : {}
494
- }
495
- }
496
- ];
497
- }
498
-
499
- // src/configs/jsonc.ts
500
- async function jsonc(options = {}) {
501
- const {
502
- files = [GLOB_JSON, GLOB_JSON5, GLOB_JSONC],
503
- overrides = {},
504
- stylistic: stylistic2 = true
505
- } = options;
506
- const {
507
- indent = 2
508
- } = typeof stylistic2 === "boolean" ? {} : stylistic2;
509
- const [
510
- pluginJsonc,
511
- parserJsonc
512
- ] = await Promise.all([
513
- interopDefault(import("eslint-plugin-jsonc")),
514
- interopDefault(import("jsonc-eslint-parser"))
515
- ]);
516
- return [
517
- {
518
- name: "kirklin/jsonc/setup",
519
- plugins: {
520
- jsonc: pluginJsonc
521
- }
522
- },
523
- {
524
- files,
525
- languageOptions: {
526
- parser: parserJsonc
527
- },
528
- name: "kirklin/jsonc/rules",
529
- rules: {
530
- "jsonc/no-bigint-literals": "error",
531
- "jsonc/no-binary-expression": "error",
532
- "jsonc/no-binary-numeric-literals": "error",
533
- "jsonc/no-dupe-keys": "error",
534
- "jsonc/no-escape-sequence-in-identifier": "error",
535
- "jsonc/no-floating-decimal": "error",
536
- "jsonc/no-hexadecimal-numeric-literals": "error",
537
- "jsonc/no-infinity": "error",
538
- "jsonc/no-multi-str": "error",
539
- "jsonc/no-nan": "error",
540
- "jsonc/no-number-props": "error",
541
- "jsonc/no-numeric-separators": "error",
542
- "jsonc/no-octal": "error",
543
- "jsonc/no-octal-escape": "error",
544
- "jsonc/no-octal-numeric-literals": "error",
545
- "jsonc/no-parenthesized": "error",
546
- "jsonc/no-plus-sign": "error",
547
- "jsonc/no-regexp-literals": "error",
548
- "jsonc/no-sparse-arrays": "error",
549
- "jsonc/no-template-literals": "error",
550
- "jsonc/no-undefined-value": "error",
551
- "jsonc/no-unicode-codepoint-escapes": "error",
552
- "jsonc/no-useless-escape": "error",
553
- "jsonc/space-unary-ops": "error",
554
- "jsonc/valid-json-number": "error",
555
- "jsonc/vue-custom-block/no-parsing-error": "error",
556
- ...stylistic2 ? {
557
- "jsonc/array-bracket-spacing": ["error", "never"],
558
- "jsonc/comma-dangle": ["error", "never"],
559
- "jsonc/comma-style": ["error", "last"],
560
- "jsonc/indent": ["error", indent],
561
- "jsonc/key-spacing": ["error", { afterColon: true, beforeColon: false }],
562
- "jsonc/object-curly-newline": ["error", { consistent: true, multiline: true }],
563
- "jsonc/object-curly-spacing": ["error", "always"],
564
- "jsonc/object-property-newline": ["error", { allowMultiplePropertiesPerLine: true }],
565
- "jsonc/quote-props": "error",
566
- "jsonc/quotes": "error"
567
- } : {},
568
- ...overrides
569
- }
570
- }
571
- ];
572
- }
573
-
574
- // src/configs/markdown.ts
575
- import { mergeProcessors, processorPassThrough } from "eslint-merge-processors";
576
- async function markdown(options = {}) {
577
- const {
578
- componentExts = [],
579
- files = [GLOB_MARKDOWN],
580
- overrides = {}
581
- } = options;
582
- const markdown2 = await interopDefault(import("eslint-plugin-markdown"));
583
- return [
584
- {
585
- name: "kirklin/markdown/setup",
586
- plugins: {
587
- markdown: markdown2
588
- }
589
- },
590
- {
591
- files,
592
- ignores: [GLOB_MARKDOWN_IN_MARKDOWN],
593
- name: "kirklin/markdown/processor",
594
- // `eslint-plugin-markdown` only creates virtual files for code blocks,
595
- // but not the markdown file itself. We use `eslint-merge-processors` to
596
- // add a pass-through processor for the markdown file itself.
597
- processor: mergeProcessors([
598
- markdown2.processors.markdown,
599
- processorPassThrough
600
- ])
601
- },
602
- {
603
- files,
604
- languageOptions: {
605
- parser: parserPlain
606
- },
607
- name: "kirklin/markdown/parser"
608
- },
609
- {
610
- files: [
611
- GLOB_MARKDOWN_CODE,
612
- ...componentExts.map((ext) => `${GLOB_MARKDOWN}/**/*.${ext}`)
613
- ],
614
- languageOptions: {
615
- parserOptions: {
616
- ecmaFeatures: {
617
- impliedStrict: true
618
- }
619
- }
620
- },
621
- name: "kirklin/markdown/disables",
622
- rules: {
623
- "import/newline-after-import": "off",
624
- "no-alert": "off",
625
- "no-console": "off",
626
- "no-labels": "off",
627
- "no-lone-blocks": "off",
628
- "no-restricted-syntax": "off",
629
- "no-undef": "off",
630
- "no-unused-expressions": "off",
631
- "no-unused-labels": "off",
632
- "no-unused-vars": "off",
633
- "node/prefer-global/process": "off",
634
- "style/comma-dangle": "off",
635
- "style/eol-last": "off",
636
- "ts/consistent-type-imports": "off",
637
- "ts/no-namespace": "off",
638
- "ts/no-redeclare": "off",
639
- "ts/no-require-imports": "off",
640
- "ts/no-unused-vars": "off",
641
- "ts/no-use-before-define": "off",
642
- "ts/no-var-requires": "off",
643
- "unicode-bom": "off",
644
- "unused-imports/no-unused-imports": "off",
645
- "unused-imports/no-unused-vars": "off",
646
- // Type aware rules
647
- ...{
648
- "ts/await-thenable": "off",
649
- "ts/dot-notation": "off",
650
- "ts/no-floating-promises": "off",
651
- "ts/no-for-in-array": "off",
652
- "ts/no-implied-eval": "off",
653
- "ts/no-misused-promises": "off",
654
- "ts/no-throw-literal": "off",
655
- "ts/no-unnecessary-type-assertion": "off",
656
- "ts/no-unsafe-argument": "off",
657
- "ts/no-unsafe-assignment": "off",
658
- "ts/no-unsafe-call": "off",
659
- "ts/no-unsafe-member-access": "off",
660
- "ts/no-unsafe-return": "off",
661
- "ts/restrict-plus-operands": "off",
662
- "ts/restrict-template-expressions": "off",
663
- "ts/unbound-method": "off"
664
- },
665
- ...overrides
666
- }
667
- }
668
- ];
669
- }
670
-
671
- // src/configs/node.ts
672
- async function node() {
673
- return [
674
- {
675
- name: "kirklin/node/rules",
676
- plugins: {
677
- node: default4
678
- },
679
- rules: {
680
- "node/handle-callback-err": ["error", "^(err|error)$"],
681
- "node/no-deprecated-api": "error",
682
- "node/no-exports-assign": "error",
683
- "node/no-new-require": "error",
684
- "node/no-path-concat": "error",
685
- "node/prefer-global/buffer": ["error", "never"],
686
- "node/prefer-global/process": ["error", "never"],
687
- "node/process-exit-as-throw": "error"
688
- }
689
- }
690
- ];
691
- }
692
-
693
- // src/configs/perfectionist.ts
694
- async function perfectionist() {
695
- return [
696
- {
697
- name: "kirklin/perfectionist/setup",
698
- plugins: {
699
- perfectionist: default7
818
+ "jsdoc/require-property-name": "warn",
819
+ "jsdoc/require-returns-check": "warn",
820
+ "jsdoc/require-returns-description": "warn",
821
+ "jsdoc/require-yields-check": "warn",
822
+ ...stylistic2 ? {
823
+ "jsdoc/check-alignment": "warn",
824
+ "jsdoc/multiline-blocks": "warn"
825
+ } : {}
700
826
  }
701
827
  }
702
828
  ];
703
829
  }
704
830
 
705
- // src/configs/formatters.ts
706
- import { isPackageExists as isPackageExists2 } from "local-pkg";
707
-
708
- // src/configs/stylistic.ts
709
- var StylisticConfigDefaults = {
710
- indent: 2,
711
- jsx: true,
712
- quotes: "double",
713
- semi: true
714
- };
715
- async function stylistic(options = {}) {
831
+ // src/configs/jsonc.ts
832
+ async function jsonc(options = {}) {
716
833
  const {
717
- indent,
718
- jsx,
719
- lessOpinionated = false,
834
+ files = [GLOB_JSON, GLOB_JSON5, GLOB_JSONC],
720
835
  overrides = {},
721
- quotes,
722
- semi
723
- } = {
724
- ...StylisticConfigDefaults,
725
- ...options
726
- };
727
- const pluginStylistic = await interopDefault(import("@stylistic/eslint-plugin"));
728
- const config = pluginStylistic.configs.customize({
729
- flat: true,
730
- indent,
731
- jsx,
732
- pluginName: "style",
733
- quotes,
734
- semi
735
- });
836
+ stylistic: stylistic2 = true
837
+ } = options;
838
+ const {
839
+ indent = 2
840
+ } = typeof stylistic2 === "boolean" ? {} : stylistic2;
841
+ const [
842
+ pluginJsonc,
843
+ parserJsonc
844
+ ] = await Promise.all([
845
+ interopDefault(import("eslint-plugin-jsonc")),
846
+ interopDefault(import("jsonc-eslint-parser"))
847
+ ]);
736
848
  return [
737
849
  {
738
- name: "kirklin/stylistic/rules",
850
+ name: "kirklin/jsonc/setup",
739
851
  plugins: {
740
- kirklin: default2,
741
- style: pluginStylistic
852
+ jsonc: pluginJsonc
853
+ }
854
+ },
855
+ {
856
+ files,
857
+ languageOptions: {
858
+ parser: parserJsonc
742
859
  },
860
+ name: "kirklin/jsonc/rules",
743
861
  rules: {
744
- ...config.rules,
745
- "kirklin/consistent-list-newline": "error",
746
- "style/brace-style": ["error", "1tbs", { allowSingleLine: false }],
747
- "style/member-delimiter-style": ["error", { multiline: { delimiter: "semi" } }],
748
- ...lessOpinionated ? {
749
- curly: ["error", "multi-or-nest", "consistent"]
750
- } : {
751
- "curly": ["error", "all"],
752
- "kirklin/if-newline": "error",
753
- "kirklin/top-level-function": "error"
754
- },
862
+ "jsonc/no-bigint-literals": "error",
863
+ "jsonc/no-binary-expression": "error",
864
+ "jsonc/no-binary-numeric-literals": "error",
865
+ "jsonc/no-dupe-keys": "error",
866
+ "jsonc/no-escape-sequence-in-identifier": "error",
867
+ "jsonc/no-floating-decimal": "error",
868
+ "jsonc/no-hexadecimal-numeric-literals": "error",
869
+ "jsonc/no-infinity": "error",
870
+ "jsonc/no-multi-str": "error",
871
+ "jsonc/no-nan": "error",
872
+ "jsonc/no-number-props": "error",
873
+ "jsonc/no-numeric-separators": "error",
874
+ "jsonc/no-octal": "error",
875
+ "jsonc/no-octal-escape": "error",
876
+ "jsonc/no-octal-numeric-literals": "error",
877
+ "jsonc/no-parenthesized": "error",
878
+ "jsonc/no-plus-sign": "error",
879
+ "jsonc/no-regexp-literals": "error",
880
+ "jsonc/no-sparse-arrays": "error",
881
+ "jsonc/no-template-literals": "error",
882
+ "jsonc/no-undefined-value": "error",
883
+ "jsonc/no-unicode-codepoint-escapes": "error",
884
+ "jsonc/no-useless-escape": "error",
885
+ "jsonc/space-unary-ops": "error",
886
+ "jsonc/valid-json-number": "error",
887
+ "jsonc/vue-custom-block/no-parsing-error": "error",
888
+ ...stylistic2 ? {
889
+ "jsonc/array-bracket-spacing": ["error", "never"],
890
+ "jsonc/comma-dangle": ["error", "never"],
891
+ "jsonc/comma-style": ["error", "last"],
892
+ "jsonc/indent": ["error", indent],
893
+ "jsonc/key-spacing": ["error", { afterColon: true, beforeColon: false }],
894
+ "jsonc/object-curly-newline": ["error", { consistent: true, multiline: true }],
895
+ "jsonc/object-curly-spacing": ["error", "always"],
896
+ "jsonc/object-property-newline": ["error", { allowMultiplePropertiesPerLine: true }],
897
+ "jsonc/quote-props": "error",
898
+ "jsonc/quotes": "error"
899
+ } : {},
755
900
  ...overrides
756
901
  }
757
902
  }
758
903
  ];
759
904
  }
760
905
 
761
- // src/configs/formatters.ts
762
- async function formatters(options = {}, stylistic2 = {}) {
763
- if (options === true) {
764
- options = {
765
- astro: isPackageExists2("astro"),
766
- css: true,
767
- graphql: true,
768
- html: true,
769
- markdown: true,
770
- slidev: isPackageExists2("@slidev/cli")
771
- };
772
- }
773
- await ensurePackages([
774
- "eslint-plugin-format",
775
- options.markdown && options.slidev ? "prettier-plugin-slidev" : void 0,
776
- options.astro ? "prettier-plugin-astro" : void 0
777
- ]);
778
- if (options.slidev && options.markdown !== true && options.markdown !== "prettier") {
779
- throw new Error("`slidev` option only works when `markdown` is enabled with `prettier`");
780
- }
906
+ // src/configs/markdown.ts
907
+ import { mergeProcessors, processorPassThrough } from "eslint-merge-processors";
908
+ async function markdown(options = {}) {
781
909
  const {
782
- indent,
783
- quotes,
784
- semi
785
- } = {
786
- ...StylisticConfigDefaults,
787
- ...stylistic2
788
- };
789
- const prettierOptions = Object.assign(
790
- {
791
- endOfLine: "auto",
792
- semi,
793
- singleQuote: quotes === "single",
794
- tabWidth: typeof indent === "number" ? indent : 2,
795
- trailingComma: "all",
796
- useTabs: indent === "tab"
797
- },
798
- options.prettierOptions || {}
799
- );
800
- const dprintOptions = Object.assign(
801
- {
802
- indentWidth: typeof indent === "number" ? indent : 2,
803
- quoteStyle: quotes === "single" ? "preferSingle" : "preferDouble",
804
- useTabs: indent === "tab"
805
- },
806
- options.dprintOptions || {}
807
- );
808
- const pluginFormat = await interopDefault(import("eslint-plugin-format"));
809
- const configs = [
910
+ componentExts = [],
911
+ files = [GLOB_MARKDOWN],
912
+ overrides = {}
913
+ } = options;
914
+ const markdown2 = await interopDefault(import("eslint-plugin-markdown"));
915
+ return [
810
916
  {
811
- name: "kirklin/formatter/setup",
917
+ name: "kirklin/markdown/setup",
812
918
  plugins: {
813
- format: pluginFormat
814
- }
815
- }
816
- ];
817
- if (options.css) {
818
- configs.push(
819
- {
820
- files: [GLOB_CSS, GLOB_POSTCSS],
821
- languageOptions: {
822
- parser: parserPlain
823
- },
824
- name: "kirklin/formatter/css",
825
- rules: {
826
- "format/prettier": [
827
- "error",
828
- {
829
- ...prettierOptions,
830
- parser: "css"
831
- }
832
- ]
833
- }
834
- },
835
- {
836
- files: [GLOB_SCSS],
837
- languageOptions: {
838
- parser: parserPlain
839
- },
840
- name: "kirklin/formatter/scss",
841
- rules: {
842
- "format/prettier": [
843
- "error",
844
- {
845
- ...prettierOptions,
846
- parser: "scss"
847
- }
848
- ]
849
- }
850
- },
851
- {
852
- files: [GLOB_LESS],
853
- languageOptions: {
854
- parser: parserPlain
855
- },
856
- name: "kirklin/formatter/less",
857
- rules: {
858
- "format/prettier": [
859
- "error",
860
- {
861
- ...prettierOptions,
862
- parser: "less"
863
- }
864
- ]
865
- }
866
- }
867
- );
868
- }
869
- if (options.html) {
870
- configs.push({
871
- files: [GLOB_HTML],
872
- languageOptions: {
873
- parser: parserPlain
874
- },
875
- name: "kirklin/formatter/html",
876
- rules: {
877
- "format/prettier": [
878
- "error",
879
- {
880
- ...prettierOptions,
881
- parser: "html"
882
- }
883
- ]
919
+ markdown: markdown2
884
920
  }
885
- });
886
- }
887
- if (options.markdown) {
888
- const formater = options.markdown === true ? "prettier" : options.markdown;
889
- const GLOB_SLIDEV = !options.slidev ? [] : options.slidev === true ? ["**/slides.md"] : options.slidev.files;
890
- configs.push({
891
- files: [GLOB_MARKDOWN],
892
- ignores: GLOB_SLIDEV,
921
+ },
922
+ {
923
+ files,
924
+ ignores: [GLOB_MARKDOWN_IN_MARKDOWN],
925
+ name: "kirklin/markdown/processor",
926
+ // `eslint-plugin-markdown` only creates virtual files for code blocks,
927
+ // but not the markdown file itself. We use `eslint-merge-processors` to
928
+ // add a pass-through processor for the markdown file itself.
929
+ processor: mergeProcessors([
930
+ markdown2.processors.markdown,
931
+ processorPassThrough
932
+ ])
933
+ },
934
+ {
935
+ files,
893
936
  languageOptions: {
894
937
  parser: parserPlain
895
938
  },
896
- name: "kirklin/formatter/markdown",
897
- rules: {
898
- [`format/${formater}`]: [
899
- "error",
900
- formater === "prettier" ? {
901
- printWidth: 120,
902
- ...prettierOptions,
903
- embeddedLanguageFormatting: "off",
904
- parser: "markdown"
905
- } : {
906
- ...dprintOptions,
907
- language: "markdown"
939
+ name: "kirklin/markdown/parser"
940
+ },
941
+ {
942
+ files: [
943
+ GLOB_MARKDOWN_CODE,
944
+ ...componentExts.map((ext) => `${GLOB_MARKDOWN}/**/*.${ext}`)
945
+ ],
946
+ languageOptions: {
947
+ parserOptions: {
948
+ ecmaFeatures: {
949
+ impliedStrict: true
908
950
  }
909
- ]
910
- }
911
- });
912
- if (options.slidev) {
913
- configs.push({
914
- files: GLOB_SLIDEV,
915
- languageOptions: {
916
- parser: parserPlain
917
- },
918
- name: "kirklin/formatter/slidev",
919
- rules: {
920
- "format/prettier": [
921
- "error",
922
- {
923
- printWidth: 120,
924
- ...prettierOptions,
925
- embeddedLanguageFormatting: "off",
926
- parser: "slidev",
927
- plugins: [
928
- "prettier-plugin-slidev"
929
- ]
930
- }
931
- ]
932
951
  }
933
- });
934
- }
935
- }
936
- if (options.astro) {
937
- configs.push({
938
- files: [GLOB_ASTRO],
939
- languageOptions: {
940
- parser: parserPlain
941
952
  },
942
- name: "kirklin/formatter/astro",
953
+ name: "kirklin/markdown/disables",
943
954
  rules: {
944
- "format/prettier": [
945
- "error",
946
- {
947
- ...prettierOptions,
948
- parser: "astro",
949
- plugins: [
950
- "prettier-plugin-astro"
951
- ]
952
- }
953
- ]
955
+ "import/newline-after-import": "off",
956
+ "no-alert": "off",
957
+ "no-console": "off",
958
+ "no-labels": "off",
959
+ "no-lone-blocks": "off",
960
+ "no-restricted-syntax": "off",
961
+ "no-undef": "off",
962
+ "no-unused-expressions": "off",
963
+ "no-unused-labels": "off",
964
+ "no-unused-vars": "off",
965
+ "node/prefer-global/process": "off",
966
+ "style/comma-dangle": "off",
967
+ "style/eol-last": "off",
968
+ "ts/consistent-type-imports": "off",
969
+ "ts/no-namespace": "off",
970
+ "ts/no-redeclare": "off",
971
+ "ts/no-require-imports": "off",
972
+ "ts/no-unused-vars": "off",
973
+ "ts/no-use-before-define": "off",
974
+ "ts/no-var-requires": "off",
975
+ "unicode-bom": "off",
976
+ "unused-imports/no-unused-imports": "off",
977
+ "unused-imports/no-unused-vars": "off",
978
+ // Type aware rules
979
+ ...{
980
+ "ts/await-thenable": "off",
981
+ "ts/dot-notation": "off",
982
+ "ts/no-floating-promises": "off",
983
+ "ts/no-for-in-array": "off",
984
+ "ts/no-implied-eval": "off",
985
+ "ts/no-misused-promises": "off",
986
+ "ts/no-throw-literal": "off",
987
+ "ts/no-unnecessary-type-assertion": "off",
988
+ "ts/no-unsafe-argument": "off",
989
+ "ts/no-unsafe-assignment": "off",
990
+ "ts/no-unsafe-call": "off",
991
+ "ts/no-unsafe-member-access": "off",
992
+ "ts/no-unsafe-return": "off",
993
+ "ts/restrict-plus-operands": "off",
994
+ "ts/restrict-template-expressions": "off",
995
+ "ts/unbound-method": "off"
996
+ },
997
+ ...overrides
954
998
  }
955
- });
956
- }
957
- if (options.graphql) {
958
- configs.push({
959
- files: [GLOB_GRAPHQL],
960
- languageOptions: {
961
- parser: parserPlain
999
+ }
1000
+ ];
1001
+ }
1002
+
1003
+ // src/configs/node.ts
1004
+ async function node() {
1005
+ return [
1006
+ {
1007
+ name: "kirklin/node/rules",
1008
+ plugins: {
1009
+ node: default4
962
1010
  },
963
- name: "kirklin/formatter/graphql",
964
1011
  rules: {
965
- "format/prettier": [
966
- "error",
967
- {
968
- ...prettierOptions,
969
- parser: "graphql"
970
- }
971
- ]
1012
+ "node/handle-callback-err": ["error", "^(err|error)$"],
1013
+ "node/no-deprecated-api": "error",
1014
+ "node/no-exports-assign": "error",
1015
+ "node/no-new-require": "error",
1016
+ "node/no-path-concat": "error",
1017
+ "node/prefer-global/buffer": ["error", "never"],
1018
+ "node/prefer-global/process": ["error", "never"],
1019
+ "node/process-exit-as-throw": "error"
972
1020
  }
973
- });
974
- }
975
- return configs;
1021
+ }
1022
+ ];
1023
+ }
1024
+
1025
+ // src/configs/perfectionist.ts
1026
+ async function perfectionist() {
1027
+ return [
1028
+ {
1029
+ name: "kirklin/perfectionist/setup",
1030
+ plugins: {
1031
+ perfectionist: default7
1032
+ }
1033
+ }
1034
+ ];
976
1035
  }
977
1036
 
978
1037
  // src/configs/react.ts
@@ -980,88 +1039,222 @@ import { isPackageExists as isPackageExists3 } from "local-pkg";
980
1039
  var ReactRefreshAllowConstantExportPackages = [
981
1040
  "vite"
982
1041
  ];
1042
+ var RemixPackages = [
1043
+ "@remix-run/node",
1044
+ "@remix-run/react",
1045
+ "@remix-run/serve",
1046
+ "@remix-run/dev"
1047
+ ];
1048
+ var NextJsPackages = [
1049
+ "next"
1050
+ ];
983
1051
  async function react(options = {}) {
984
1052
  const {
985
- files = [GLOB_JSX, GLOB_TSX],
986
- overrides = {},
987
- typescript: typescript2 = true
1053
+ files = [GLOB_TS, GLOB_TSX],
1054
+ overrides = {}
988
1055
  } = options;
989
1056
  await ensurePackages([
990
- "eslint-plugin-react",
1057
+ "@eslint-react/eslint-plugin",
991
1058
  "eslint-plugin-react-hooks",
992
1059
  "eslint-plugin-react-refresh"
993
1060
  ]);
1061
+ const tsconfigPath = options?.tsconfigPath ? toArray(options.tsconfigPath) : void 0;
1062
+ const isTypeAware = !!tsconfigPath;
994
1063
  const [
995
1064
  pluginReact,
996
1065
  pluginReactHooks,
997
- pluginReactRefresh
1066
+ pluginReactRefresh,
1067
+ parserTs
998
1068
  ] = await Promise.all([
999
- interopDefault(import("eslint-plugin-react")),
1069
+ interopDefault(import("@eslint-react/eslint-plugin")),
1000
1070
  interopDefault(import("eslint-plugin-react-hooks")),
1001
- interopDefault(import("eslint-plugin-react-refresh"))
1071
+ interopDefault(import("eslint-plugin-react-refresh")),
1072
+ interopDefault(import("@typescript-eslint/parser"))
1002
1073
  ]);
1003
- const isAllowConstantExport = ReactRefreshAllowConstantExportPackages.some(
1004
- (i) => isPackageExists3(i)
1005
- );
1074
+ const isAllowConstantExport = ReactRefreshAllowConstantExportPackages.some((i) => isPackageExists3(i));
1075
+ const isUsingRemix = RemixPackages.some((i) => isPackageExists3(i));
1076
+ const isUsingNext = NextJsPackages.some((i) => isPackageExists3(i));
1077
+ const plugins = pluginReact.configs.all.plugins;
1006
1078
  return [
1007
1079
  {
1008
1080
  name: "kirklin/react/setup",
1009
1081
  plugins: {
1010
- "react": pluginReact,
1082
+ "react": plugins["@eslint-react"],
1083
+ "react-dom": plugins["@eslint-react/dom"],
1011
1084
  "react-hooks": pluginReactHooks,
1085
+ "react-hooks-extra": plugins["@eslint-react/hooks-extra"],
1086
+ "react-naming-convention": plugins["@eslint-react/naming-convention"],
1012
1087
  "react-refresh": pluginReactRefresh
1013
- },
1014
- settings: {
1015
- react: {
1016
- version: "detect"
1017
- }
1018
1088
  }
1019
1089
  },
1020
1090
  {
1021
1091
  files,
1022
1092
  languageOptions: {
1093
+ parser: parserTs,
1023
1094
  parserOptions: {
1024
1095
  ecmaFeatures: {
1025
1096
  jsx: true
1026
- }
1027
- }
1097
+ },
1098
+ ...isTypeAware ? { project: tsconfigPath } : {}
1099
+ },
1100
+ sourceType: "module"
1028
1101
  },
1029
1102
  name: "kirklin/react/rules",
1030
1103
  rules: {
1104
+ // recommended rules from @eslint-react/dom
1105
+ "react-dom/no-children-in-void-dom-elements": "warn",
1106
+ "react-dom/no-dangerously-set-innerhtml": "warn",
1107
+ "react-dom/no-dangerously-set-innerhtml-with-children": "error",
1108
+ "react-dom/no-find-dom-node": "error",
1109
+ "react-dom/no-missing-button-type": "warn",
1110
+ "react-dom/no-missing-iframe-sandbox": "warn",
1111
+ "react-dom/no-namespace": "error",
1112
+ "react-dom/no-render-return-value": "error",
1113
+ "react-dom/no-script-url": "warn",
1114
+ "react-dom/no-unsafe-iframe-sandbox": "warn",
1115
+ "react-dom/no-unsafe-target-blank": "warn",
1031
1116
  // recommended rules react-hooks
1032
1117
  "react-hooks/exhaustive-deps": "warn",
1033
1118
  "react-hooks/rules-of-hooks": "error",
1034
1119
  // react refresh
1035
1120
  "react-refresh/only-export-components": [
1036
1121
  "warn",
1037
- { allowConstantExport: isAllowConstantExport }
1122
+ {
1123
+ allowConstantExport: isAllowConstantExport,
1124
+ allowExportNames: [
1125
+ ...isUsingNext ? [
1126
+ "config",
1127
+ "generateStaticParams",
1128
+ "metadata",
1129
+ "generateMetadata",
1130
+ "viewport",
1131
+ "generateViewport"
1132
+ ] : [],
1133
+ ...isUsingRemix ? [
1134
+ "meta",
1135
+ "links",
1136
+ "headers",
1137
+ "loader",
1138
+ "action"
1139
+ ] : []
1140
+ ]
1141
+ }
1038
1142
  ],
1039
- // recommended rules react
1040
- "react/display-name": "error",
1041
- "react/jsx-key": "error",
1042
- "react/jsx-no-comment-textnodes": "error",
1043
- "react/jsx-no-duplicate-props": "error",
1044
- "react/jsx-no-target-blank": "error",
1045
- "react/jsx-no-undef": "error",
1046
- "react/jsx-uses-react": "error",
1047
- "react/jsx-uses-vars": "error",
1048
- "react/no-children-prop": "error",
1049
- "react/no-danger-with-children": "error",
1050
- "react/no-deprecated": "error",
1143
+ // recommended rules from @eslint-react
1144
+ "react/ensure-forward-ref-using-ref": "warn",
1145
+ "react/no-access-state-in-setstate": "error",
1146
+ "react/no-array-index-key": "warn",
1147
+ "react/no-children-count": "warn",
1148
+ "react/no-children-for-each": "warn",
1149
+ "react/no-children-map": "warn",
1150
+ "react/no-children-only": "warn",
1151
+ "react/no-children-prop": "warn",
1152
+ "react/no-children-to-array": "warn",
1153
+ "react/no-clone-element": "warn",
1154
+ "react/no-comment-textnodes": "warn",
1155
+ "react/no-component-will-mount": "error",
1156
+ "react/no-component-will-receive-props": "error",
1157
+ "react/no-component-will-update": "error",
1158
+ "react/no-create-ref": "error",
1051
1159
  "react/no-direct-mutation-state": "error",
1052
- "react/no-find-dom-node": "error",
1053
- "react/no-is-mounted": "error",
1054
- "react/no-render-return-value": "error",
1160
+ "react/no-duplicate-key": "error",
1161
+ "react/no-implicit-key": "error",
1162
+ "react/no-missing-key": "error",
1163
+ "react/no-nested-components": "warn",
1164
+ "react/no-redundant-should-component-update": "error",
1165
+ "react/no-set-state-in-component-did-mount": "warn",
1166
+ "react/no-set-state-in-component-did-update": "warn",
1167
+ "react/no-set-state-in-component-will-update": "warn",
1055
1168
  "react/no-string-refs": "error",
1056
- "react/no-unescaped-entities": "error",
1057
- "react/no-unknown-property": "error",
1058
- "react/no-unsafe": "off",
1059
- "react/prop-types": "error",
1060
- "react/react-in-jsx-scope": "off",
1061
- "react/require-render-return": "error",
1169
+ "react/no-unsafe-component-will-mount": "warn",
1170
+ "react/no-unsafe-component-will-receive-props": "warn",
1171
+ "react/no-unsafe-component-will-update": "warn",
1172
+ "react/no-unstable-context-value": "error",
1173
+ "react/no-unstable-default-props": "error",
1174
+ "react/no-unused-class-component-members": "warn",
1175
+ "react/no-unused-state": "warn",
1176
+ "react/no-useless-fragment": "warn",
1177
+ "react/prefer-destructuring-assignment": "warn",
1178
+ "react/prefer-shorthand-boolean": "warn",
1179
+ "react/prefer-shorthand-fragment": "warn",
1180
+ ...isTypeAware ? {
1181
+ "react/no-leaked-conditional-rendering": "warn"
1182
+ } : {},
1183
+ // overrides
1184
+ ...overrides
1185
+ }
1186
+ }
1187
+ ];
1188
+ }
1189
+
1190
+ // src/configs/solid.ts
1191
+ async function solid(options = {}) {
1192
+ const {
1193
+ files = [GLOB_JSX, GLOB_TSX],
1194
+ overrides = {},
1195
+ typescript: typescript2 = true
1196
+ } = options;
1197
+ await ensurePackages([
1198
+ "eslint-plugin-solid"
1199
+ ]);
1200
+ const tsconfigPath = options?.tsconfigPath ? toArray(options.tsconfigPath) : void 0;
1201
+ const isTypeAware = !!tsconfigPath;
1202
+ const [
1203
+ pluginSolid,
1204
+ parserTs
1205
+ ] = await Promise.all([
1206
+ interopDefault(import("eslint-plugin-solid")),
1207
+ interopDefault(import("@typescript-eslint/parser"))
1208
+ ]);
1209
+ return [
1210
+ {
1211
+ name: "kirklin/solid/setup",
1212
+ plugins: {
1213
+ solid: pluginSolid
1214
+ }
1215
+ },
1216
+ {
1217
+ files,
1218
+ languageOptions: {
1219
+ parser: parserTs,
1220
+ parserOptions: {
1221
+ ecmaFeatures: {
1222
+ jsx: true
1223
+ },
1224
+ ...isTypeAware ? { project: tsconfigPath } : {}
1225
+ },
1226
+ sourceType: "module"
1227
+ },
1228
+ name: "kirklin/solid/rules",
1229
+ rules: {
1230
+ // reactivity
1231
+ "solid/components-return-once": "warn",
1232
+ "solid/event-handlers": ["error", {
1233
+ // if true, don't warn on ambiguously named event handlers like `onclick` or `onchange`
1234
+ ignoreCase: false,
1235
+ // if true, warn when spreading event handlers onto JSX. Enable for Solid < v1.6.
1236
+ warnOnSpread: false
1237
+ }],
1238
+ // these rules are mostly style suggestions
1239
+ "solid/imports": "error",
1240
+ // identifier usage is important
1241
+ "solid/jsx-no-duplicate-props": "error",
1242
+ "solid/jsx-no-script-url": "error",
1243
+ "solid/jsx-no-undef": "error",
1244
+ "solid/jsx-uses-vars": "error",
1245
+ "solid/no-destructure": "error",
1246
+ // security problems
1247
+ "solid/no-innerhtml": ["error", { allowStatic: true }],
1248
+ "solid/no-react-deps": "error",
1249
+ "solid/no-react-specific-props": "error",
1250
+ "solid/no-unknown-namespaces": "error",
1251
+ "solid/prefer-for": "error",
1252
+ "solid/reactivity": "warn",
1253
+ "solid/self-closing-comp": "error",
1254
+ "solid/style-prop": ["error", { styleProps: ["style", "css"] }],
1062
1255
  ...typescript2 ? {
1063
- "react/jsx-no-undef": "off",
1064
- "react/prop-type": "off"
1256
+ "solid/jsx-no-undef": ["error", { typescriptEnabled: true }],
1257
+ "solid/no-unknown-namespaces": "off"
1065
1258
  } : {},
1066
1259
  // overrides
1067
1260
  ...overrides
@@ -1441,6 +1634,65 @@ async function test(options = {}) {
1441
1634
  ];
1442
1635
  }
1443
1636
 
1637
+ // src/configs/toml.ts
1638
+ async function toml(options = {}) {
1639
+ const {
1640
+ files = [GLOB_TOML],
1641
+ overrides = {},
1642
+ stylistic: stylistic2 = true
1643
+ } = options;
1644
+ const {
1645
+ indent = 2
1646
+ } = typeof stylistic2 === "boolean" ? {} : stylistic2;
1647
+ const [
1648
+ pluginToml,
1649
+ parserToml
1650
+ ] = await Promise.all([
1651
+ interopDefault(import("eslint-plugin-toml")),
1652
+ interopDefault(import("toml-eslint-parser"))
1653
+ ]);
1654
+ return [
1655
+ {
1656
+ name: "kirklin/toml/setup",
1657
+ plugins: {
1658
+ toml: pluginToml
1659
+ }
1660
+ },
1661
+ {
1662
+ files,
1663
+ languageOptions: {
1664
+ parser: parserToml
1665
+ },
1666
+ name: "kirklin/toml/rules",
1667
+ rules: {
1668
+ "style/spaced-comment": "off",
1669
+ "toml/comma-style": "error",
1670
+ "toml/keys-order": "error",
1671
+ "toml/no-space-dots": "error",
1672
+ "toml/no-unreadable-number-separator": "error",
1673
+ "toml/precision-of-fractional-seconds": "error",
1674
+ "toml/precision-of-integer": "error",
1675
+ "toml/tables-order": "error",
1676
+ "toml/vue-custom-block/no-parsing-error": "error",
1677
+ ...stylistic2 ? {
1678
+ "toml/array-bracket-newline": "error",
1679
+ "toml/array-bracket-spacing": "error",
1680
+ "toml/array-element-newline": "error",
1681
+ "toml/indent": ["error", indent === "tab" ? 2 : indent],
1682
+ "toml/inline-table-curly-spacing": "error",
1683
+ "toml/key-spacing": "error",
1684
+ "toml/padding-line-between-pairs": "error",
1685
+ "toml/padding-line-between-tables": "error",
1686
+ "toml/quoted-keys": "error",
1687
+ "toml/spaced-comment": "error",
1688
+ "toml/table-bracket-spacing": "error"
1689
+ } : {},
1690
+ ...overrides
1691
+ }
1692
+ }
1693
+ ];
1694
+ }
1695
+
1444
1696
  // src/configs/typescript.ts
1445
1697
  import process2 from "node:process";
1446
1698
  async function typescript(options = {}) {
@@ -1899,189 +2151,6 @@ async function yaml(options = {}) {
1899
2151
  ];
1900
2152
  }
1901
2153
 
1902
- // src/configs/toml.ts
1903
- async function toml(options = {}) {
1904
- const {
1905
- files = [GLOB_TOML],
1906
- overrides = {},
1907
- stylistic: stylistic2 = true
1908
- } = options;
1909
- const {
1910
- indent = 2
1911
- } = typeof stylistic2 === "boolean" ? {} : stylistic2;
1912
- const [
1913
- pluginToml,
1914
- parserToml
1915
- ] = await Promise.all([
1916
- interopDefault(import("eslint-plugin-toml")),
1917
- interopDefault(import("toml-eslint-parser"))
1918
- ]);
1919
- return [
1920
- {
1921
- name: "kirklin/toml/setup",
1922
- plugins: {
1923
- toml: pluginToml
1924
- }
1925
- },
1926
- {
1927
- files,
1928
- languageOptions: {
1929
- parser: parserToml
1930
- },
1931
- name: "kirklin/toml/rules",
1932
- rules: {
1933
- "style/spaced-comment": "off",
1934
- "toml/comma-style": "error",
1935
- "toml/keys-order": "error",
1936
- "toml/no-space-dots": "error",
1937
- "toml/no-unreadable-number-separator": "error",
1938
- "toml/precision-of-fractional-seconds": "error",
1939
- "toml/precision-of-integer": "error",
1940
- "toml/tables-order": "error",
1941
- "toml/vue-custom-block/no-parsing-error": "error",
1942
- ...stylistic2 ? {
1943
- "toml/array-bracket-newline": "error",
1944
- "toml/array-bracket-spacing": "error",
1945
- "toml/array-element-newline": "error",
1946
- "toml/indent": ["error", indent === "tab" ? 2 : indent],
1947
- "toml/inline-table-curly-spacing": "error",
1948
- "toml/key-spacing": "error",
1949
- "toml/padding-line-between-pairs": "error",
1950
- "toml/padding-line-between-tables": "error",
1951
- "toml/quoted-keys": "error",
1952
- "toml/spaced-comment": "error",
1953
- "toml/table-bracket-spacing": "error"
1954
- } : {},
1955
- ...overrides
1956
- }
1957
- }
1958
- ];
1959
- }
1960
-
1961
- // src/configs/astro.ts
1962
- async function astro(options = {}) {
1963
- const {
1964
- files = [GLOB_ASTRO],
1965
- overrides = {},
1966
- stylistic: stylistic2 = true
1967
- } = options;
1968
- const [
1969
- pluginAstro,
1970
- parserAstro,
1971
- parserTs
1972
- ] = await Promise.all([
1973
- interopDefault(import("eslint-plugin-astro")),
1974
- interopDefault(import("astro-eslint-parser")),
1975
- interopDefault(import("@typescript-eslint/parser"))
1976
- ]);
1977
- return [
1978
- {
1979
- name: "kirklin/astro/setup",
1980
- plugins: {
1981
- astro: pluginAstro
1982
- }
1983
- },
1984
- {
1985
- files,
1986
- languageOptions: {
1987
- parser: parserAstro,
1988
- parserOptions: {
1989
- extraFileExtensions: [".astro"],
1990
- parser: parserTs
1991
- }
1992
- },
1993
- name: "kirklin/astro/rules",
1994
- rules: {
1995
- "astro/no-set-html-directive": "off",
1996
- ...stylistic2 ? {
1997
- "style/indent": "off",
1998
- "style/jsx-closing-tag-location": "off",
1999
- "style/jsx-indent": "off",
2000
- "style/jsx-one-expression-per-line": "off",
2001
- "style/no-multiple-empty-lines": "off"
2002
- } : {},
2003
- ...overrides
2004
- }
2005
- }
2006
- ];
2007
- }
2008
-
2009
- // src/configs/solid.ts
2010
- async function solid(options = {}) {
2011
- const {
2012
- files = [GLOB_JSX, GLOB_TSX],
2013
- overrides = {},
2014
- typescript: typescript2 = true
2015
- } = options;
2016
- await ensurePackages([
2017
- "eslint-plugin-solid"
2018
- ]);
2019
- const tsconfigPath = options?.tsconfigPath ? toArray(options.tsconfigPath) : void 0;
2020
- const isTypeAware = !!tsconfigPath;
2021
- const [
2022
- pluginSolid,
2023
- parserTs
2024
- ] = await Promise.all([
2025
- interopDefault(import("eslint-plugin-solid")),
2026
- interopDefault(import("@typescript-eslint/parser"))
2027
- ]);
2028
- return [
2029
- {
2030
- name: "kirklin/solid/setup",
2031
- plugins: {
2032
- solid: pluginSolid
2033
- }
2034
- },
2035
- {
2036
- files,
2037
- languageOptions: {
2038
- parser: parserTs,
2039
- parserOptions: {
2040
- ecmaFeatures: {
2041
- jsx: true
2042
- },
2043
- ...isTypeAware ? { project: tsconfigPath } : {}
2044
- },
2045
- sourceType: "module"
2046
- },
2047
- name: "kirklin/solid/rules",
2048
- rules: {
2049
- // reactivity
2050
- "solid/components-return-once": "warn",
2051
- "solid/event-handlers": ["error", {
2052
- // if true, don't warn on ambiguously named event handlers like `onclick` or `onchange`
2053
- ignoreCase: false,
2054
- // if true, warn when spreading event handlers onto JSX. Enable for Solid < v1.6.
2055
- warnOnSpread: false
2056
- }],
2057
- // these rules are mostly style suggestions
2058
- "solid/imports": "error",
2059
- // identifier usage is important
2060
- "solid/jsx-no-duplicate-props": "error",
2061
- "solid/jsx-no-script-url": "error",
2062
- "solid/jsx-no-undef": "error",
2063
- "solid/jsx-uses-vars": "error",
2064
- "solid/no-destructure": "error",
2065
- // security problems
2066
- "solid/no-innerhtml": ["error", { allowStatic: true }],
2067
- "solid/no-react-deps": "error",
2068
- "solid/no-react-specific-props": "error",
2069
- "solid/no-unknown-namespaces": "error",
2070
- "solid/prefer-for": "error",
2071
- "solid/reactivity": "warn",
2072
- "solid/self-closing-comp": "error",
2073
- "solid/style-prop": ["error", { styleProps: ["style", "css"] }],
2074
- ...typescript2 ? {
2075
- "solid/jsx-no-undef": ["error", { typescriptEnabled: true }],
2076
- "solid/no-unknown-namespaces": "off"
2077
- } : {},
2078
- // overrides
2079
- ...overrides
2080
- }
2081
- }
2082
- ];
2083
- }
2084
-
2085
2154
  // src/factory.ts
2086
2155
  var flatConfigProps = [
2087
2156
  "name",
@@ -2101,6 +2170,10 @@ var VuePackages = [
2101
2170
  "@slidev/cli"
2102
2171
  ];
2103
2172
  var defaultPluginRenaming = {
2173
+ "@eslint-react": "react",
2174
+ "@eslint-react/dom": "react-dom",
2175
+ "@eslint-react/hooks-extra": "react-hooks-extra",
2176
+ "@eslint-react/naming-convention": "react-naming-convention",
2104
2177
  "@stylistic": "style",
2105
2178
  "@typescript-eslint": "ts",
2106
2179
  "import-x": "import",
@@ -2151,6 +2224,7 @@ function kirklin(options = {}, ...userConfigs) {
2151
2224
  stylistic: stylisticOptions
2152
2225
  }),
2153
2226
  unicorn(),
2227
+ command(),
2154
2228
  // Optional plugins (installed but not enabled by default)
2155
2229
  perfectionist()
2156
2230
  );
@@ -2188,7 +2262,7 @@ function kirklin(options = {}, ...userConfigs) {
2188
2262
  if (enableReact) {
2189
2263
  configs.push(react({
2190
2264
  overrides: getOverrides(options, "react"),
2191
- typescript: !!enableTypeScript
2265
+ tsconfigPath: getOverrides(options, "typescript").tsconfigPath
2192
2266
  }));
2193
2267
  }
2194
2268
  if (enableSolid) {
@@ -2318,6 +2392,7 @@ export {
2318
2392
  StylisticConfigDefaults,
2319
2393
  astro,
2320
2394
  combine,
2395
+ command,
2321
2396
  comments,
2322
2397
  src_default as default,
2323
2398
  defaultPluginRenaming,