@antfu/eslint-config 9.5.0 → 9.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -14
- package/dist/cli.mjs +8 -7
- package/dist/index.d.mts +12 -3
- package/dist/index.mjs +223 -162
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -336,36 +336,38 @@ And that's it! Or you can configure each integration individually, for example:
|
|
|
336
336
|
import antfu from '@antfu/eslint-config'
|
|
337
337
|
|
|
338
338
|
export default antfu({
|
|
339
|
-
|
|
339
|
+
/** Type of the project. 'lib' for libraries, the default is 'app' */
|
|
340
340
|
type: 'lib',
|
|
341
341
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
342
|
+
/**
|
|
343
|
+
* `.eslintignore` is no longer supported in Flat config, use `ignores` instead
|
|
344
|
+
* The `ignores` option in the option (first argument) is specifically treated to always be global ignores
|
|
345
|
+
* And will **extend** the config's default ignores, not override them
|
|
346
|
+
* You can also pass a function to modify the default ignores
|
|
347
|
+
*/
|
|
346
348
|
ignores: [
|
|
347
349
|
'**/fixtures',
|
|
348
350
|
// ...globs
|
|
349
351
|
],
|
|
350
352
|
|
|
351
|
-
|
|
353
|
+
/** Parse the `.gitignore` file to get the ignores, on by default */
|
|
352
354
|
gitignore: true,
|
|
353
355
|
|
|
354
356
|
// Enable stylistic formatting rules
|
|
355
357
|
// stylistic: true,
|
|
356
358
|
|
|
357
|
-
|
|
359
|
+
/** Or customize the stylistic rules */
|
|
358
360
|
stylistic: {
|
|
359
361
|
indent: 2, // 4, or 'tab'
|
|
360
362
|
quotes: 'single', // or 'double'
|
|
361
363
|
braceStyle: 'stroustrup', // '1tbs', or 'allman'
|
|
362
364
|
},
|
|
363
365
|
|
|
364
|
-
|
|
366
|
+
/** TypeScript and Vue are autodetected, you can also explicitly enable them: */
|
|
365
367
|
typescript: true,
|
|
366
368
|
vue: true,
|
|
367
369
|
|
|
368
|
-
|
|
370
|
+
/** Disable jsonc and yaml support */
|
|
369
371
|
jsonc: false,
|
|
370
372
|
yaml: false,
|
|
371
373
|
})
|
|
@@ -514,14 +516,14 @@ export default antfu(
|
|
|
514
516
|
typescript: true
|
|
515
517
|
},
|
|
516
518
|
{
|
|
517
|
-
|
|
519
|
+
/** Remember to specify the file glob here, otherwise it might cause the vue plugin to handle non-vue files */
|
|
518
520
|
files: ['**/*.vue'],
|
|
519
521
|
rules: {
|
|
520
522
|
'vue/operator-linebreak': ['error', 'before'],
|
|
521
523
|
},
|
|
522
524
|
},
|
|
523
525
|
{
|
|
524
|
-
|
|
526
|
+
/** Without `files`, they are general rules for all files (Markdown excluded, see note below) */
|
|
525
527
|
rules: {
|
|
526
528
|
'style/semi': ['error', 'never'],
|
|
527
529
|
},
|
|
@@ -548,7 +550,7 @@ export default antfu({
|
|
|
548
550
|
overrides: {
|
|
549
551
|
'ts/consistent-type-definitions': ['error', 'interface'],
|
|
550
552
|
},
|
|
551
|
-
|
|
553
|
+
/** type aware rules overrides should write here */
|
|
552
554
|
overridesTypeAware: {
|
|
553
555
|
'ts/no-unsafe-assignment': ['warn'],
|
|
554
556
|
}
|
|
@@ -841,8 +843,10 @@ import antfu from '@antfu/eslint-config'
|
|
|
841
843
|
export default antfu({
|
|
842
844
|
antislop: {
|
|
843
845
|
sonarjs: false,
|
|
844
|
-
|
|
845
|
-
|
|
846
|
+
/**
|
|
847
|
+
* an object enables `eslint-plugin-slop` and is forwarded to it
|
|
848
|
+
* via `settings.slop`, for example to only inspect recently changed code
|
|
849
|
+
*/
|
|
846
850
|
slop: {
|
|
847
851
|
inspection: { mode: 'recent-changes', tracebackCommits: 5 },
|
|
848
852
|
},
|
package/dist/cli.mjs
CHANGED
|
@@ -8,7 +8,7 @@ import { cac } from "cac";
|
|
|
8
8
|
import parse from "parse-gitignore";
|
|
9
9
|
import { execSync } from "node:child_process";
|
|
10
10
|
//#region package.json
|
|
11
|
-
var version = "9.5.
|
|
11
|
+
var version = "9.5.1";
|
|
12
12
|
//#endregion
|
|
13
13
|
//#region src/cli/constants.ts
|
|
14
14
|
const vscodeSettingsString = `
|
|
@@ -188,21 +188,22 @@ async function updatePackageJson(result) {
|
|
|
188
188
|
const pkgContent = await fsPromises.readFile(pathPackageJSON, "utf-8");
|
|
189
189
|
const pkg = JSON.parse(pkgContent);
|
|
190
190
|
pkg.devDependencies ??= {};
|
|
191
|
-
|
|
192
|
-
|
|
191
|
+
const devDependencies = pkg.devDependencies;
|
|
192
|
+
devDependencies["@antfu/eslint-config"] = `^${version}`;
|
|
193
|
+
devDependencies.eslint ??= versionsMap.eslint;
|
|
193
194
|
const addedPackages = [];
|
|
194
195
|
if (result.extra.length) result.extra.forEach((item) => {
|
|
195
196
|
switch (item) {
|
|
196
197
|
case "formatter":
|
|
197
198
|
[...dependenciesMap.formatter, ...result.frameworks.includes("astro") ? dependenciesMap.formatterAstro : []].forEach((f) => {
|
|
198
199
|
if (!f) return;
|
|
199
|
-
|
|
200
|
+
devDependencies[f] = versionsMap[f];
|
|
200
201
|
addedPackages.push(f);
|
|
201
202
|
});
|
|
202
203
|
break;
|
|
203
204
|
case "unocss":
|
|
204
205
|
dependenciesMap.unocss.forEach((f) => {
|
|
205
|
-
|
|
206
|
+
devDependencies[f] = versionsMap[f];
|
|
206
207
|
addedPackages.push(f);
|
|
207
208
|
});
|
|
208
209
|
break;
|
|
@@ -211,7 +212,7 @@ async function updatePackageJson(result) {
|
|
|
211
212
|
for (const framework of result.frameworks) {
|
|
212
213
|
const deps = dependenciesMap[framework];
|
|
213
214
|
if (deps) deps.forEach((f) => {
|
|
214
|
-
|
|
215
|
+
devDependencies[f] = versionsMap[f];
|
|
215
216
|
addedPackages.push(f);
|
|
216
217
|
});
|
|
217
218
|
}
|
|
@@ -259,7 +260,7 @@ async function run(options = {}) {
|
|
|
259
260
|
if (!argSkipPrompt) {
|
|
260
261
|
result = await p.group({
|
|
261
262
|
uncommittedConfirmed: () => {
|
|
262
|
-
if (
|
|
263
|
+
if (isGitClean()) return Promise.resolve(true);
|
|
263
264
|
return p.confirm({
|
|
264
265
|
initialValue: false,
|
|
265
266
|
message: "There are uncommitted changes in the current repository, are you sure to continue?"
|
package/dist/index.d.mts
CHANGED
|
@@ -23418,7 +23418,7 @@ type Yoda = [] | [("always" | "never")] | [("always" | "never"), {
|
|
|
23418
23418
|
onlyEquality?: boolean;
|
|
23419
23419
|
}];
|
|
23420
23420
|
// Names of all the configs
|
|
23421
|
-
type ConfigNames = 'antfu/gitignore' | 'antfu/ignores' | 'antfu/javascript/setup' | 'antfu/javascript/rules' | 'antfu/eslint-comments/rules' | 'antfu/command/rules' | 'antfu/perfectionist/setup' | 'antfu/node/setup' | 'antfu/node/rules' | 'antfu/jsdoc/setup' | 'antfu/jsdoc/rules' | 'antfu/imports/rules' | 'antfu/e18e/rules' | 'antfu/unicorn/setup' | 'antfu/unicorn/rules' | 'antfu/jsx/setup' | 'antfu/typescript/setup' | 'antfu/typescript/parser' | 'antfu/typescript/type-aware-parser' | 'antfu/typescript/rules' | 'antfu/typescript/rules-type-aware' | 'antfu/typescript/erasable-syntax-only' | 'antfu/antislop/rules' | 'antfu/stylistic/rules' | 'antfu/regexp/rules' | 'antfu/test/setup' | 'antfu/test/rules' | 'antfu/vue/setup' | 'antfu/vue/rules' | 'antfu/react/setup' | 'antfu/react/rules' | 'antfu/react/typescript' | 'antfu/react/type-aware-rules' | 'antfu/nextjs/setup' | 'antfu/nextjs/rules' | 'antfu/solid/setup' | 'antfu/solid/rules' | 'antfu/svelte/setup' | 'antfu/svelte/rules' | 'antfu/unocss' | 'antfu/astro/setup' | 'antfu/astro/rules' | 'antfu/angular/setup' | 'antfu/angular/rules/ts' | 'antfu/angular/rules/template' | 'antfu/jsonc/setup' | 'antfu/jsonc/rules' | 'antfu/sort/package-json' | 'antfu/sort/tsconfig-json' | 'antfu/pnpm/package-json' | 'antfu/pnpm/pnpm-workspace-yaml' | 'antfu/pnpm/pnpm-workspace-yaml-stylistic' | 'antfu/pnpm/pnpm-workspace-yaml-sort' | 'antfu/yaml/setup' | 'antfu/yaml/rules' | 'antfu/toml/setup' | 'antfu/toml/rules' | 'antfu/markdown/setup' | 'antfu/markdown/processor' | 'antfu/markdown/parser' | 'antfu/markdown/rules' | 'antfu/markdown/disables/code' | 'antfu/formatter/setup' | 'antfu/formatter/css' | 'antfu/formatter/scss' | 'antfu/formatter/less' | 'antfu/formatter/html' | 'antfu/formatter/xml' | 'antfu/formatter/svg' | 'antfu/formatter/markdown' | 'antfu/formatter/astro' | 'antfu/formatter/astro/disables' | 'antfu/formatter/graphql' | 'antfu/disables/scripts' | 'antfu/disables/cli' | 'antfu/disables/bin' | 'antfu/disables/dts' | 'antfu/disables/cjs' | 'antfu/disables/config-files';
|
|
23421
|
+
type ConfigNames = 'antfu/gitignore' | 'antfu/ignores' | 'antfu/javascript/setup' | 'antfu/javascript/rules' | 'antfu/eslint-comments/rules' | 'antfu/command/rules' | 'antfu/perfectionist/setup' | 'antfu/node/setup' | 'antfu/node/rules' | 'antfu/jsdoc/setup' | 'antfu/jsdoc/rules' | 'antfu/imports/rules' | 'antfu/e18e/rules' | 'antfu/unicorn/setup' | 'antfu/unicorn/rules' | 'antfu/jsx/setup' | 'antfu/typescript/setup' | 'antfu/typescript/parser' | 'antfu/typescript/type-aware-parser' | 'antfu/typescript/rules' | 'antfu/typescript/rules-type-aware' | 'antfu/typescript/erasable-syntax-only' | 'antfu/antislop/setup' | 'antfu/antislop/rules/universal' | 'antfu/antislop/rules/javascript' | 'antfu/stylistic/rules' | 'antfu/regexp/rules' | 'antfu/test/setup' | 'antfu/test/rules' | 'antfu/vue/setup' | 'antfu/vue/rules' | 'antfu/react/setup' | 'antfu/react/rules' | 'antfu/react/typescript' | 'antfu/react/type-aware-rules' | 'antfu/nextjs/setup' | 'antfu/nextjs/rules' | 'antfu/solid/setup' | 'antfu/solid/rules' | 'antfu/svelte/setup' | 'antfu/svelte/rules' | 'antfu/unocss' | 'antfu/astro/setup' | 'antfu/astro/rules' | 'antfu/angular/setup' | 'antfu/angular/rules/ts' | 'antfu/angular/rules/template' | 'antfu/jsonc/setup' | 'antfu/jsonc/rules' | 'antfu/sort/package-json' | 'antfu/sort/tsconfig-json' | 'antfu/pnpm/package-json' | 'antfu/pnpm/pnpm-workspace-yaml' | 'antfu/pnpm/pnpm-workspace-yaml-stylistic' | 'antfu/pnpm/pnpm-workspace-yaml-sort' | 'antfu/yaml/setup' | 'antfu/yaml/rules' | 'antfu/toml/setup' | 'antfu/toml/rules' | 'antfu/markdown/setup' | 'antfu/markdown/processor' | 'antfu/markdown/parser' | 'antfu/markdown/rules' | 'antfu/markdown/disables/code' | 'antfu/formatter/setup' | 'antfu/formatter/css' | 'antfu/formatter/scss' | 'antfu/formatter/less' | 'antfu/formatter/html' | 'antfu/formatter/xml' | 'antfu/formatter/svg' | 'antfu/formatter/markdown' | 'antfu/formatter/astro' | 'antfu/formatter/astro/disables' | 'antfu/formatter/graphql' | 'antfu/disables/scripts' | 'antfu/disables/cli' | 'antfu/disables/bin' | 'antfu/disables/dts' | 'antfu/disables/cjs' | 'antfu/disables/config-files';
|
|
23422
23422
|
//#endregion
|
|
23423
23423
|
//#region src/vender/prettier-types.d.ts
|
|
23424
23424
|
/**
|
|
@@ -23492,7 +23492,7 @@ interface VendoredPrettierOptionsRequired {
|
|
|
23492
23492
|
/**
|
|
23493
23493
|
* Provide ability to support new languages to prettier.
|
|
23494
23494
|
*/
|
|
23495
|
-
plugins: Array<string |
|
|
23495
|
+
plugins: Array<string | Record<string, unknown>>;
|
|
23496
23496
|
/**
|
|
23497
23497
|
* How to handle whitespaces in HTML.
|
|
23498
23498
|
* @default "css"
|
|
@@ -23727,6 +23727,14 @@ interface OptionsAntislop extends OptionsOverrides {
|
|
|
23727
23727
|
* @default true
|
|
23728
23728
|
*/
|
|
23729
23729
|
sonarjs?: boolean;
|
|
23730
|
+
/**
|
|
23731
|
+
* Maximum allowed cognitive complexity for `sonarjs/cognitive-complexity`.
|
|
23732
|
+
*
|
|
23733
|
+
* Pass `false` to disable the rule entirely.
|
|
23734
|
+
*
|
|
23735
|
+
* @default 15
|
|
23736
|
+
*/
|
|
23737
|
+
cognitiveComplexity?: number | false;
|
|
23730
23738
|
}
|
|
23731
23739
|
interface OptionsUnicorn extends OptionsOverrides {
|
|
23732
23740
|
/**
|
|
@@ -24156,6 +24164,7 @@ declare function resolveSubOptions<K extends keyof OptionsConfig>(options: Optio
|
|
|
24156
24164
|
declare function getOverrides<K extends keyof OptionsConfig>(options: OptionsConfig, key: K): Partial<Linter.RulesRecord & RuleOptions>;
|
|
24157
24165
|
//#endregion
|
|
24158
24166
|
//#region src/config-presets.d.ts
|
|
24167
|
+
/** @keep-sorted */
|
|
24159
24168
|
declare const CONFIG_PRESET_FULL_ON: OptionsConfig;
|
|
24160
24169
|
declare const CONFIG_PRESET_FULL_OFF: OptionsConfig;
|
|
24161
24170
|
//#endregion
|
|
@@ -24178,7 +24187,7 @@ declare function comments(): Promise<TypedFlatConfigItem[]>;
|
|
|
24178
24187
|
declare function disables(): Promise<TypedFlatConfigItem[]>;
|
|
24179
24188
|
//#endregion
|
|
24180
24189
|
//#region src/configs/formatters.d.ts
|
|
24181
|
-
declare function formatters(
|
|
24190
|
+
declare function formatters(rawOptions?: OptionsFormatters | true, stylistic?: StylisticConfig): Promise<TypedFlatConfigItem[]>;
|
|
24182
24191
|
//#endregion
|
|
24183
24192
|
//#region src/configs/ignores.d.ts
|
|
24184
24193
|
declare function ignores(userIgnores?: string[] | ((originals: string[]) => string[]), ignoreTypeScript?: boolean): Promise<TypedFlatConfigItem[]>;
|
package/dist/index.mjs
CHANGED
|
@@ -307,51 +307,71 @@ async function angular(options = {}) {
|
|
|
307
307
|
//#endregion
|
|
308
308
|
//#region src/configs/antislop.ts
|
|
309
309
|
async function antislop(options = {}) {
|
|
310
|
-
const { overrides = {}, slop = true, sonarjs = true
|
|
310
|
+
const { cognitiveComplexity = 15, overrides = {}, slop = true, sonarjs = true } = options;
|
|
311
311
|
await ensurePackages([...slop ? ["eslint-plugin-slop"] : [], ...sonarjs ? ["eslint-plugin-sonarjs"] : []]);
|
|
312
312
|
const [pluginSlop, pluginSonarjs] = await Promise.all([slop ? interopDefault(import("eslint-plugin-slop")) : void 0, sonarjs ? interopDefault(import("eslint-plugin-sonarjs")) : void 0]);
|
|
313
|
-
return [
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
313
|
+
return [
|
|
314
|
+
{
|
|
315
|
+
name: "antfu/antislop/setup",
|
|
316
|
+
plugins: {
|
|
317
|
+
...slop ? { slop: pluginSlop } : {},
|
|
318
|
+
...sonarjs ? { sonarjs: pluginSonarjs } : {}
|
|
319
|
+
},
|
|
320
|
+
...typeof slop === "object" ? { settings: { slop } } : {}
|
|
318
321
|
},
|
|
319
|
-
...
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
322
|
+
...slop ? [{
|
|
323
|
+
files: [
|
|
324
|
+
...GLOB_ALL_SRC,
|
|
325
|
+
GLOB_JSONC,
|
|
326
|
+
GLOB_TOML,
|
|
327
|
+
GLOB_GRAPHQL
|
|
328
|
+
],
|
|
329
|
+
/**
|
|
330
|
+
* Markdown code fences are already scanned as part of the raw
|
|
331
|
+
* Markdown text, so exclude the virtual embedded-code files to
|
|
332
|
+
* avoid reporting the same em dash twice
|
|
333
|
+
*/
|
|
334
|
+
ignores: [GLOB_MARKDOWN_CODE],
|
|
335
|
+
name: "antfu/antislop/rules/universal",
|
|
336
|
+
rules: { "slop/no-em-dash": "error" }
|
|
337
|
+
}] : [],
|
|
338
|
+
{
|
|
339
|
+
files: [GLOB_SRC],
|
|
340
|
+
name: "antfu/antislop/rules/javascript",
|
|
341
|
+
rules: {
|
|
342
|
+
...slop ? {
|
|
343
|
+
"slop/max-comment-length": "error",
|
|
344
|
+
"slop/no-chained-type-assertions": "error",
|
|
345
|
+
"slop/no-jargon": "error",
|
|
346
|
+
"slop/no-trivial-functions": "error",
|
|
347
|
+
"slop/no-trivial-type-aliases": "error",
|
|
348
|
+
"slop/prefer-jsdoc": "error"
|
|
349
|
+
} : {},
|
|
350
|
+
...sonarjs ? {
|
|
351
|
+
...cognitiveComplexity === false ? {} : { "sonarjs/cognitive-complexity": ["error", cognitiveComplexity] },
|
|
352
|
+
"sonarjs/no-all-duplicated-branches": "error",
|
|
353
|
+
"sonarjs/no-collapsible-if": "error",
|
|
354
|
+
"sonarjs/no-commented-code": "error",
|
|
355
|
+
"sonarjs/no-dead-store": "error",
|
|
356
|
+
"sonarjs/no-duplicated-branches": "error",
|
|
357
|
+
"sonarjs/no-element-overwrite": "error",
|
|
358
|
+
"sonarjs/no-empty-collection": "error",
|
|
359
|
+
"sonarjs/no-gratuitous-expressions": "error",
|
|
360
|
+
"sonarjs/no-identical-conditions": "error",
|
|
361
|
+
"sonarjs/no-identical-expressions": "error",
|
|
362
|
+
"sonarjs/no-identical-functions": "error",
|
|
363
|
+
"sonarjs/no-invariant-returns": "error",
|
|
364
|
+
"sonarjs/no-inverted-boolean-check": "error",
|
|
365
|
+
"sonarjs/no-redundant-boolean": "error",
|
|
366
|
+
"sonarjs/no-redundant-jump": "error",
|
|
367
|
+
"sonarjs/no-unused-collection": "error",
|
|
368
|
+
"sonarjs/no-use-of-empty-return-value": "error",
|
|
369
|
+
"sonarjs/prefer-single-boolean-return": "error"
|
|
370
|
+
} : {},
|
|
371
|
+
...overrides
|
|
372
|
+
}
|
|
353
373
|
}
|
|
354
|
-
|
|
374
|
+
];
|
|
355
375
|
}
|
|
356
376
|
//#endregion
|
|
357
377
|
//#region src/configs/astro.ts
|
|
@@ -379,7 +399,12 @@ async function astro(options = {}) {
|
|
|
379
399
|
name: "antfu/astro/rules",
|
|
380
400
|
processor: "astro/client-side-ts",
|
|
381
401
|
rules: {
|
|
402
|
+
/**
|
|
403
|
+
* Astro uses top level await for e.g. data fetching
|
|
404
|
+
* https://docs.astro.build/en/guides/data-fetching/#fetch-in-astro
|
|
405
|
+
*/
|
|
382
406
|
"antfu/no-top-level-await": "off",
|
|
407
|
+
/** use recommended rules */
|
|
383
408
|
"astro/missing-client-only-directive-value": "error",
|
|
384
409
|
"astro/no-conflict-set-directives": "error",
|
|
385
410
|
"astro/no-deprecated-astro-canonicalurl": "error",
|
|
@@ -537,26 +562,136 @@ function mergePrettierOptions(options, overrides) {
|
|
|
537
562
|
plugins: [...overrides.plugins || [], ...options.plugins || []]
|
|
538
563
|
};
|
|
539
564
|
}
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
css
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
565
|
+
function buildCssConfigs(prettierOptions) {
|
|
566
|
+
return [
|
|
567
|
+
[
|
|
568
|
+
[GLOB_CSS, GLOB_POSTCSS],
|
|
569
|
+
"css",
|
|
570
|
+
"antfu/formatter/css"
|
|
571
|
+
],
|
|
572
|
+
[
|
|
573
|
+
[GLOB_SCSS],
|
|
574
|
+
"scss",
|
|
575
|
+
"antfu/formatter/scss"
|
|
576
|
+
],
|
|
577
|
+
[
|
|
578
|
+
[GLOB_LESS],
|
|
579
|
+
"less",
|
|
580
|
+
"antfu/formatter/less"
|
|
581
|
+
]
|
|
582
|
+
].map(([files, parser, name]) => ({
|
|
583
|
+
files: [...files],
|
|
584
|
+
languageOptions: { parser: parserPlain },
|
|
585
|
+
name,
|
|
586
|
+
rules: { "format/prettier": ["error", mergePrettierOptions(prettierOptions, { parser })] }
|
|
587
|
+
}));
|
|
588
|
+
}
|
|
589
|
+
function buildXmlLikeConfig(prettierOptions, prettierXmlOptions, files, name) {
|
|
590
|
+
return {
|
|
591
|
+
files,
|
|
592
|
+
languageOptions: { parser: parserPlain },
|
|
593
|
+
name,
|
|
594
|
+
rules: { "format/prettier": ["error", mergePrettierOptions({
|
|
595
|
+
...prettierXmlOptions,
|
|
596
|
+
...prettierOptions
|
|
597
|
+
}, {
|
|
598
|
+
parser: "xml",
|
|
599
|
+
plugins: ["@prettier/plugin-xml"]
|
|
600
|
+
})] }
|
|
601
|
+
};
|
|
602
|
+
}
|
|
603
|
+
function buildMarkdownConfigs(options, prettierOptions, dprintOptions) {
|
|
604
|
+
const formater = options.markdown === true ? "prettier" : options.markdown;
|
|
605
|
+
const GLOB_SLIDEV = !options.slidev ? [] : options.slidev === true ? ["**/slides.md"] : options.slidev.files;
|
|
606
|
+
const configs = [{
|
|
607
|
+
files: [GLOB_MARKDOWN],
|
|
608
|
+
ignores: GLOB_SLIDEV,
|
|
609
|
+
languageOptions: { parser: parserPlain },
|
|
610
|
+
name: "antfu/formatter/markdown",
|
|
611
|
+
rules: { [`format/${formater}`]: ["error", formater === "prettier" ? mergePrettierOptions(prettierOptions, {
|
|
612
|
+
embeddedLanguageFormatting: "off",
|
|
613
|
+
parser: "markdown"
|
|
614
|
+
}) : {
|
|
615
|
+
...dprintOptions,
|
|
616
|
+
language: "markdown"
|
|
617
|
+
}] }
|
|
618
|
+
}];
|
|
619
|
+
if (options.slidev) configs.push({
|
|
620
|
+
files: GLOB_SLIDEV,
|
|
621
|
+
languageOptions: { parser: parserPlain },
|
|
622
|
+
name: "antfu/formatter/slidev",
|
|
623
|
+
rules: { "format/prettier": ["error", mergePrettierOptions(prettierOptions, {
|
|
624
|
+
embeddedLanguageFormatting: "off",
|
|
625
|
+
parser: "slidev",
|
|
626
|
+
plugins: ["prettier-plugin-slidev"]
|
|
627
|
+
})] }
|
|
628
|
+
});
|
|
629
|
+
return configs;
|
|
630
|
+
}
|
|
631
|
+
function buildAstroConfigs(prettierOptions) {
|
|
632
|
+
return [{
|
|
633
|
+
files: [GLOB_ASTRO],
|
|
634
|
+
languageOptions: { parser: parserPlain },
|
|
635
|
+
name: "antfu/formatter/astro",
|
|
636
|
+
rules: { "format/prettier": ["error", mergePrettierOptions(prettierOptions, {
|
|
637
|
+
parser: "astro",
|
|
638
|
+
plugins: ["prettier-plugin-astro"]
|
|
639
|
+
})] }
|
|
640
|
+
}, {
|
|
641
|
+
files: [GLOB_ASTRO, GLOB_ASTRO_TS],
|
|
642
|
+
name: "antfu/formatter/astro/disables",
|
|
643
|
+
rules: {
|
|
644
|
+
"style/arrow-parens": "off",
|
|
645
|
+
"style/block-spacing": "off",
|
|
646
|
+
"style/comma-dangle": "off",
|
|
647
|
+
"style/indent": "off",
|
|
648
|
+
"style/no-multi-spaces": "off",
|
|
649
|
+
"style/quotes": "off",
|
|
650
|
+
"style/semi": "off"
|
|
651
|
+
}
|
|
652
|
+
}];
|
|
653
|
+
}
|
|
654
|
+
function resolveFormattersOptions(options) {
|
|
655
|
+
if (options !== true) return options;
|
|
656
|
+
const isPrettierPluginXmlInScope = isPackageInScope("@prettier/plugin-xml");
|
|
657
|
+
return {
|
|
658
|
+
astro: isPackageInScope("prettier-plugin-astro"),
|
|
659
|
+
css: true,
|
|
660
|
+
graphql: true,
|
|
661
|
+
html: true,
|
|
662
|
+
markdown: true,
|
|
663
|
+
slidev: isPackageExists("@slidev/cli"),
|
|
664
|
+
svg: isPrettierPluginXmlInScope,
|
|
665
|
+
xml: isPrettierPluginXmlInScope
|
|
666
|
+
};
|
|
667
|
+
}
|
|
668
|
+
function buildHtmlConfig(prettierOptions) {
|
|
669
|
+
return {
|
|
670
|
+
files: [GLOB_HTML],
|
|
671
|
+
languageOptions: { parser: parserPlain },
|
|
672
|
+
name: "antfu/formatter/html",
|
|
673
|
+
rules: { "format/prettier": ["error", mergePrettierOptions(prettierOptions, { parser: "html" })] }
|
|
674
|
+
};
|
|
675
|
+
}
|
|
676
|
+
function buildGraphqlConfig(prettierOptions) {
|
|
677
|
+
return {
|
|
678
|
+
files: [GLOB_GRAPHQL],
|
|
679
|
+
languageOptions: { parser: parserPlain },
|
|
680
|
+
name: "antfu/formatter/graphql",
|
|
681
|
+
rules: { "format/prettier": ["error", mergePrettierOptions(prettierOptions, { parser: "graphql" })] }
|
|
682
|
+
};
|
|
683
|
+
}
|
|
684
|
+
function getFormattersPackagesToEnsure(options) {
|
|
685
|
+
return [
|
|
555
686
|
"eslint-plugin-format",
|
|
556
687
|
options.markdown && options.slidev ? "prettier-plugin-slidev" : void 0,
|
|
557
688
|
options.astro ? "prettier-plugin-astro" : void 0,
|
|
558
689
|
options.xml || options.svg ? "@prettier/plugin-xml" : void 0
|
|
559
|
-
]
|
|
690
|
+
];
|
|
691
|
+
}
|
|
692
|
+
async function formatters(rawOptions = {}, stylistic = {}) {
|
|
693
|
+
const options = resolveFormattersOptions(rawOptions);
|
|
694
|
+
await ensurePackages(getFormattersPackagesToEnsure(options));
|
|
560
695
|
if (options.slidev && options.markdown !== true && options.markdown !== "prettier") throw new Error("`slidev` option only works when `markdown` is enabled with `prettier`");
|
|
561
696
|
const { indent, quotes, semi } = {
|
|
562
697
|
...StylisticConfigDefaults,
|
|
@@ -587,109 +722,13 @@ async function formatters(options = {}, stylistic = {}) {
|
|
|
587
722
|
name: "antfu/formatter/setup",
|
|
588
723
|
plugins: { format: await interopDefault(import("eslint-plugin-format")) }
|
|
589
724
|
}];
|
|
590
|
-
if (options.css) configs.push(
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
languageOptions: { parser: parserPlain },
|
|
598
|
-
name: "antfu/formatter/scss",
|
|
599
|
-
rules: { "format/prettier": ["error", mergePrettierOptions(prettierOptions, { parser: "scss" })] }
|
|
600
|
-
}, {
|
|
601
|
-
files: [GLOB_LESS],
|
|
602
|
-
languageOptions: { parser: parserPlain },
|
|
603
|
-
name: "antfu/formatter/less",
|
|
604
|
-
rules: { "format/prettier": ["error", mergePrettierOptions(prettierOptions, { parser: "less" })] }
|
|
605
|
-
});
|
|
606
|
-
if (options.html) configs.push({
|
|
607
|
-
files: [GLOB_HTML],
|
|
608
|
-
languageOptions: { parser: parserPlain },
|
|
609
|
-
name: "antfu/formatter/html",
|
|
610
|
-
rules: { "format/prettier": ["error", mergePrettierOptions(prettierOptions, { parser: "html" })] }
|
|
611
|
-
});
|
|
612
|
-
if (options.xml) configs.push({
|
|
613
|
-
files: [GLOB_XML],
|
|
614
|
-
languageOptions: { parser: parserPlain },
|
|
615
|
-
name: "antfu/formatter/xml",
|
|
616
|
-
rules: { "format/prettier": ["error", mergePrettierOptions({
|
|
617
|
-
...prettierXmlOptions,
|
|
618
|
-
...prettierOptions
|
|
619
|
-
}, {
|
|
620
|
-
parser: "xml",
|
|
621
|
-
plugins: ["@prettier/plugin-xml"]
|
|
622
|
-
})] }
|
|
623
|
-
});
|
|
624
|
-
if (options.svg) configs.push({
|
|
625
|
-
files: [GLOB_SVG],
|
|
626
|
-
languageOptions: { parser: parserPlain },
|
|
627
|
-
name: "antfu/formatter/svg",
|
|
628
|
-
rules: { "format/prettier": ["error", mergePrettierOptions({
|
|
629
|
-
...prettierXmlOptions,
|
|
630
|
-
...prettierOptions
|
|
631
|
-
}, {
|
|
632
|
-
parser: "xml",
|
|
633
|
-
plugins: ["@prettier/plugin-xml"]
|
|
634
|
-
})] }
|
|
635
|
-
});
|
|
636
|
-
if (options.markdown) {
|
|
637
|
-
const formater = options.markdown === true ? "prettier" : options.markdown;
|
|
638
|
-
const GLOB_SLIDEV = !options.slidev ? [] : options.slidev === true ? ["**/slides.md"] : options.slidev.files;
|
|
639
|
-
configs.push({
|
|
640
|
-
files: [GLOB_MARKDOWN],
|
|
641
|
-
ignores: GLOB_SLIDEV,
|
|
642
|
-
languageOptions: { parser: parserPlain },
|
|
643
|
-
name: "antfu/formatter/markdown",
|
|
644
|
-
rules: { [`format/${formater}`]: ["error", formater === "prettier" ? mergePrettierOptions(prettierOptions, {
|
|
645
|
-
embeddedLanguageFormatting: "off",
|
|
646
|
-
parser: "markdown"
|
|
647
|
-
}) : {
|
|
648
|
-
...dprintOptions,
|
|
649
|
-
language: "markdown"
|
|
650
|
-
}] }
|
|
651
|
-
});
|
|
652
|
-
if (options.slidev) configs.push({
|
|
653
|
-
files: GLOB_SLIDEV,
|
|
654
|
-
languageOptions: { parser: parserPlain },
|
|
655
|
-
name: "antfu/formatter/slidev",
|
|
656
|
-
rules: { "format/prettier": ["error", mergePrettierOptions(prettierOptions, {
|
|
657
|
-
embeddedLanguageFormatting: "off",
|
|
658
|
-
parser: "slidev",
|
|
659
|
-
plugins: ["prettier-plugin-slidev"]
|
|
660
|
-
})] }
|
|
661
|
-
});
|
|
662
|
-
}
|
|
663
|
-
if (options.astro) {
|
|
664
|
-
configs.push({
|
|
665
|
-
files: [GLOB_ASTRO],
|
|
666
|
-
languageOptions: { parser: parserPlain },
|
|
667
|
-
name: "antfu/formatter/astro",
|
|
668
|
-
rules: { "format/prettier": ["error", mergePrettierOptions(prettierOptions, {
|
|
669
|
-
parser: "astro",
|
|
670
|
-
plugins: ["prettier-plugin-astro"]
|
|
671
|
-
})] }
|
|
672
|
-
});
|
|
673
|
-
configs.push({
|
|
674
|
-
files: [GLOB_ASTRO, GLOB_ASTRO_TS],
|
|
675
|
-
name: "antfu/formatter/astro/disables",
|
|
676
|
-
rules: {
|
|
677
|
-
"style/arrow-parens": "off",
|
|
678
|
-
"style/block-spacing": "off",
|
|
679
|
-
"style/comma-dangle": "off",
|
|
680
|
-
"style/indent": "off",
|
|
681
|
-
"style/no-multi-spaces": "off",
|
|
682
|
-
"style/quotes": "off",
|
|
683
|
-
"style/semi": "off"
|
|
684
|
-
}
|
|
685
|
-
});
|
|
686
|
-
}
|
|
687
|
-
if (options.graphql) configs.push({
|
|
688
|
-
files: [GLOB_GRAPHQL],
|
|
689
|
-
languageOptions: { parser: parserPlain },
|
|
690
|
-
name: "antfu/formatter/graphql",
|
|
691
|
-
rules: { "format/prettier": ["error", mergePrettierOptions(prettierOptions, { parser: "graphql" })] }
|
|
692
|
-
});
|
|
725
|
+
if (options.css) configs.push(...buildCssConfigs(prettierOptions));
|
|
726
|
+
if (options.html) configs.push(buildHtmlConfig(prettierOptions));
|
|
727
|
+
if (options.xml) configs.push(buildXmlLikeConfig(prettierOptions, prettierXmlOptions, [GLOB_XML], "antfu/formatter/xml"));
|
|
728
|
+
if (options.svg) configs.push(buildXmlLikeConfig(prettierOptions, prettierXmlOptions, [GLOB_SVG], "antfu/formatter/svg"));
|
|
729
|
+
if (options.markdown) configs.push(...buildMarkdownConfigs(options, prettierOptions, dprintOptions));
|
|
730
|
+
if (options.astro) configs.push(...buildAstroConfigs(prettierOptions));
|
|
731
|
+
if (options.graphql) configs.push(buildGraphqlConfig(prettierOptions));
|
|
693
732
|
return configs;
|
|
694
733
|
}
|
|
695
734
|
//#endregion
|
|
@@ -1102,6 +1141,11 @@ async function markdown(options = {}) {
|
|
|
1102
1141
|
files,
|
|
1103
1142
|
ignores: [GLOB_MARKDOWN_IN_MARKDOWN],
|
|
1104
1143
|
name: "antfu/markdown/processor",
|
|
1144
|
+
/**
|
|
1145
|
+
* `eslint-plugin-markdown` only creates virtual files for code blocks,
|
|
1146
|
+
* but not the markdown file itself. We use `eslint-merge-processors` to
|
|
1147
|
+
* add a pass-through processor for the markdown file itself.
|
|
1148
|
+
*/
|
|
1105
1149
|
processor: mergeProcessors([markdown.processors.markdown, processorPassThrough])
|
|
1106
1150
|
},
|
|
1107
1151
|
{
|
|
@@ -1115,6 +1159,7 @@ async function markdown(options = {}) {
|
|
|
1115
1159
|
rules: {
|
|
1116
1160
|
...markdown.configs.recommended.at(0)?.rules,
|
|
1117
1161
|
"markdown/fenced-code-language": "off",
|
|
1162
|
+
/** https://github.com/eslint/markdown/issues/294 */
|
|
1118
1163
|
"markdown/no-missing-label-refs": "off",
|
|
1119
1164
|
...overridesMarkdown
|
|
1120
1165
|
}
|
|
@@ -1309,14 +1354,14 @@ async function pnpm(options) {
|
|
|
1309
1354
|
"pnpm/yaml-no-unused-catalog-item": "error"
|
|
1310
1355
|
}
|
|
1311
1356
|
});
|
|
1312
|
-
if (
|
|
1357
|
+
if (stylistic) configs.push({
|
|
1313
1358
|
files: ["pnpm-workspace.yaml"],
|
|
1314
1359
|
languageOptions: { parser: yamlParser },
|
|
1315
1360
|
name: "antfu/pnpm/pnpm-workspace-yaml-stylistic",
|
|
1316
1361
|
plugins: { pnpm: pluginPnpm },
|
|
1317
1362
|
rules: { "pnpm/yaml-blank-lines": "error" }
|
|
1318
1363
|
});
|
|
1319
|
-
if (
|
|
1364
|
+
if (sort) configs.push({
|
|
1320
1365
|
files: ["pnpm-workspace.yaml"],
|
|
1321
1366
|
languageOptions: { parser: yamlParser },
|
|
1322
1367
|
name: "antfu/pnpm/pnpm-workspace-yaml-sort",
|
|
@@ -1565,6 +1610,7 @@ async function react(options = {}) {
|
|
|
1565
1610
|
name: "antfu/react/rules",
|
|
1566
1611
|
rules: {
|
|
1567
1612
|
...pluginReact.configs.recommended.rules,
|
|
1613
|
+
/** preconfigured rules from eslint-plugin-react-refresh https://github.com/ArnaudBarre/eslint-plugin-react-refresh/tree/main/src */
|
|
1568
1614
|
"react-refresh/only-export-components": ["error", {
|
|
1569
1615
|
allowConstantExport: isAllowConstantExport,
|
|
1570
1616
|
allowExportNames: [...isUsingNext ? [
|
|
@@ -1601,6 +1647,7 @@ async function react(options = {}) {
|
|
|
1601
1647
|
files: filesTypeAware,
|
|
1602
1648
|
name: "antfu/react/typescript",
|
|
1603
1649
|
rules: {
|
|
1650
|
+
/** Disables rules that are already handled by TypeScript */
|
|
1604
1651
|
"react/dom-no-string-style-prop": "off",
|
|
1605
1652
|
"react/dom-no-unknown-property": "off"
|
|
1606
1653
|
}
|
|
@@ -1653,17 +1700,23 @@ async function solid(options = {}) {
|
|
|
1653
1700
|
},
|
|
1654
1701
|
name: "antfu/solid/rules",
|
|
1655
1702
|
rules: {
|
|
1703
|
+
/** reactivity */
|
|
1656
1704
|
"solid/components-return-once": "warn",
|
|
1657
1705
|
"solid/event-handlers": ["error", {
|
|
1706
|
+
/** if true, don't warn on ambiguously named event handlers like `onclick` or `onchange` */
|
|
1658
1707
|
ignoreCase: false,
|
|
1708
|
+
/** if true, warn when spreading event handlers onto JSX. Enable for Solid < v1.6. */
|
|
1659
1709
|
warnOnSpread: false
|
|
1660
1710
|
}],
|
|
1711
|
+
/** these rules are mostly style suggestions */
|
|
1661
1712
|
"solid/imports": "error",
|
|
1713
|
+
/** identifier usage is important */
|
|
1662
1714
|
"solid/jsx-no-duplicate-props": "error",
|
|
1663
1715
|
"solid/jsx-no-script-url": "error",
|
|
1664
1716
|
"solid/jsx-no-undef": "error",
|
|
1665
1717
|
"solid/jsx-uses-vars": "error",
|
|
1666
1718
|
"solid/no-destructure": "error",
|
|
1719
|
+
/** security problems */
|
|
1667
1720
|
"solid/no-innerhtml": ["error", { allowStatic: true }],
|
|
1668
1721
|
"solid/no-react-deps": "error",
|
|
1669
1722
|
"solid/no-react-specific-props": "error",
|
|
@@ -2115,6 +2168,7 @@ async function typescript(options = {}) {
|
|
|
2115
2168
|
}
|
|
2116
2169
|
return [
|
|
2117
2170
|
{
|
|
2171
|
+
/** Install the plugins without globs, so they can be configured separately. */
|
|
2118
2172
|
name: "antfu/typescript/setup",
|
|
2119
2173
|
plugins: {
|
|
2120
2174
|
antfu: pluginAntfu,
|
|
@@ -2257,6 +2311,10 @@ async function vue(options = {}) {
|
|
|
2257
2311
|
...a11y ? [interopDefault(import("eslint-plugin-vuejs-accessibility"))] : []
|
|
2258
2312
|
]);
|
|
2259
2313
|
return [{
|
|
2314
|
+
/**
|
|
2315
|
+
* This allows Vue plugin to work with auto imports
|
|
2316
|
+
* https://github.com/vuejs/eslint-plugin-vue/pull/2422
|
|
2317
|
+
*/
|
|
2260
2318
|
languageOptions: { globals: {
|
|
2261
2319
|
computed: "readonly",
|
|
2262
2320
|
defineEmits: "readonly",
|
|
@@ -2327,6 +2385,7 @@ async function vue(options = {}) {
|
|
|
2327
2385
|
] }],
|
|
2328
2386
|
"vue/component-name-in-template-casing": ["error", "PascalCase"],
|
|
2329
2387
|
"vue/component-options-name-casing": ["error", "PascalCase"],
|
|
2388
|
+
/** this is deprecated */
|
|
2330
2389
|
"vue/component-tags-order": "off",
|
|
2331
2390
|
"vue/custom-event-name-casing": ["error", "camelCase"],
|
|
2332
2391
|
"vue/define-macros-order": ["error", { order: [
|
|
@@ -2508,6 +2567,7 @@ async function e18e(options = {}) {
|
|
|
2508
2567
|
...moduleReplacements ? { ...configs.moduleReplacements.rules } : {},
|
|
2509
2568
|
...performanceImprovements ? { ...configs.performanceImprovements.rules } : {},
|
|
2510
2569
|
...type === "lib" ? {} : { "e18e/prefer-static-regex": "off" },
|
|
2570
|
+
/** these are a bit opinionated and dangerous (introducing behavioral changes), so we'll disable them by default for now */
|
|
2511
2571
|
"e18e/prefer-array-at": "off",
|
|
2512
2572
|
"e18e/prefer-array-from-map": "off",
|
|
2513
2573
|
"e18e/prefer-array-to-reversed": "off",
|
|
@@ -2703,6 +2763,7 @@ function getOverrides(options, key) {
|
|
|
2703
2763
|
}
|
|
2704
2764
|
//#endregion
|
|
2705
2765
|
//#region src/config-presets.ts
|
|
2766
|
+
/** @keep-sorted */
|
|
2706
2767
|
const CONFIG_PRESET_FULL_ON = {
|
|
2707
2768
|
angular: true,
|
|
2708
2769
|
antislop: true,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@antfu/eslint-config",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "9.5.
|
|
4
|
+
"version": "9.5.1",
|
|
5
5
|
"description": "Anthony's ESLint config",
|
|
6
6
|
"author": "Anthony Fu <anthonyfu117@hotmail.com> (https://github.com/antfu/)",
|
|
7
7
|
"license": "MIT",
|
|
@@ -159,10 +159,10 @@
|
|
|
159
159
|
"@angular-eslint/eslint-plugin-template": "^22.2.0",
|
|
160
160
|
"@angular-eslint/template-parser": "^22.2.0",
|
|
161
161
|
"@angular/core": "^22.1.4",
|
|
162
|
-
"@antfu/eslint-config": "9.5.
|
|
162
|
+
"@antfu/eslint-config": "9.5.1",
|
|
163
163
|
"@antfu/ni": "^30.5.0",
|
|
164
164
|
"@eslint-react/eslint-plugin": "^5.18.6",
|
|
165
|
-
"@eslint/config-inspector": "^3.
|
|
165
|
+
"@eslint/config-inspector": "^3.4.0",
|
|
166
166
|
"@next/eslint-plugin-next": "^16.3.3",
|
|
167
167
|
"@prettier/plugin-xml": "^3.4.2",
|
|
168
168
|
"@types/eslint-plugin-jsx-a11y": "^6.10.1",
|
|
@@ -177,7 +177,7 @@
|
|
|
177
177
|
"eslint-plugin-format": "^2.0.1",
|
|
178
178
|
"eslint-plugin-jsx-a11y": "^6.10.2",
|
|
179
179
|
"eslint-plugin-react-refresh": "^0.5.5",
|
|
180
|
-
"eslint-plugin-slop": "^0.1.
|
|
180
|
+
"eslint-plugin-slop": "^0.1.2",
|
|
181
181
|
"eslint-plugin-solid": "^0.17.0",
|
|
182
182
|
"eslint-plugin-sonarjs": "^4.2.0",
|
|
183
183
|
"eslint-plugin-svelte": "^3.23.0",
|
|
@@ -226,7 +226,7 @@
|
|
|
226
226
|
"build": "nr gen && tsdown --clean --dts",
|
|
227
227
|
"stub": "tsdown",
|
|
228
228
|
"dev": "npx @eslint/config-inspector --config eslint.config.ts",
|
|
229
|
-
"build:inspector": "pnpm build && npx @eslint/config-inspector build --config eslint.config.ts --out-dir ./.eslint-config-inspector",
|
|
229
|
+
"build:inspector": "pnpm build && npx @eslint/config-inspector build --stats --config eslint.config.ts --out-dir ./.eslint-config-inspector",
|
|
230
230
|
"watch": "tsdown --watch",
|
|
231
231
|
"lint": "eslint",
|
|
232
232
|
"gen": "tsx scripts/typegen.ts && tsx scripts/versiongen.ts",
|