@oliver139/eslint-config 6.0.4 → 7.0.0

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