From f31a824b7e2b6655cdf56d2804998544f7f6a1b7 Mon Sep 17 00:00:00 2001 From: Anthony Fu Date: Fri, 22 Sep 2023 05:38:04 +0800 Subject: [PATCH] feat!: rename plugin prefixes for consistency --- .vscode/settings.json | 1 + README.md | 22 ++- .../eslint-config/src/configs/markdown.ts | 26 ++-- packages/eslint-config/src/configs/node.ts | 19 ++- .../eslint-config/src/configs/stylistic.ts | 135 ++++++++++-------- .../eslint-config/src/configs/typescript.ts | 119 +++++++-------- packages/eslint-config/src/configs/yml.ts | 2 +- packages/eslint-config/src/plugins.ts | 3 +- packages/eslint-config/src/utils.ts | 11 ++ 9 files changed, 199 insertions(+), 139 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index d6b0420f3b..00998ee089 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -15,6 +15,7 @@ // Silent the stylistic rules in you IDE, but still auto fix them "eslint.rules.customizations": [ { "rule": "@stylistic/*", "severity": "off" }, + { "rule": "style*", "severity": "off" }, { "rule": "*-indent", "severity": "off" }, { "rule": "*-spacing", "severity": "off" }, { "rule": "*-spaces", "severity": "off" }, diff --git a/README.md b/README.md index aa37b65d59..d9c8061f4a 100644 --- a/README.md +++ b/README.md @@ -100,7 +100,7 @@ Add the following settings to your `settings.json`: } ``` -## Flat Config +## Customization Since v1.0, we migrated to [ESLint Flat config](https://eslint.org/docs/latest/use/configure/configuration-files-new), provides a much better organization and composition. @@ -197,6 +197,26 @@ Check out the [configs](https://github.com/antfu/eslint-config/blob/main/package > Thanks to [sxzz/eslint-config](https://github.com/sxzz/eslint-config) for the inspiration and reference. +## Plugins Renaming + +Since flat config support explicit provides the plugin names, we renamed some plugins to make them more consistent and hide the implementation details. + +| Original Prefix | New Prefix | Source Plugin | +| --------------- | ---------- | ------------- | +| `i/*` | `import/*` | [eslint-plugin-i](https://github.com/un-es/eslint-plugin-i) | +| `n/*` | `node` | [eslint-plugin-n](https://github.com/eslint-community/eslint-plugin-n) +| `@typescript-eslint/*` | `ts/*` | [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint) | +| `@stylistic/js` | `style/*` | [@stylistic/eslint-plugin-js](https://github.com/eslint-stylistic/eslint-stylistic) | +| `@stylistic/ts` | `style-ts/` | [@stylistic/eslint-plugin-ts](https://github.com/eslint-stylistic/eslint-stylistic) | + +When you want to overrides rules, or disable them inline, you need to update to the new prefix: + +```diff +-// eslint-disable-next-line @typescript-eslint/consistent-type-definitions ++// eslint-disable-next-line ts/consistent-type-definitions +type foo = { bar: 2 } +``` + ### Type Aware Rules You can optionally enable the [type aware rules](https://typescript-eslint.io/linting/typed-linting/) by passing the options object to the `typescript` config: diff --git a/packages/eslint-config/src/configs/markdown.ts b/packages/eslint-config/src/configs/markdown.ts index 7cb609e898..d5f8c0fab5 100644 --- a/packages/eslint-config/src/configs/markdown.ts +++ b/packages/eslint-config/src/configs/markdown.ts @@ -1,6 +1,6 @@ import type { FlatESLintConfigItem } from 'eslint-define-config' import { GLOB_MARKDOWN, GLOB_MARKDOWN_CODE } from '../globs' -import { pluginMarkdown } from '../plugins' +import { pluginMarkdown, pluginTs } from '../plugins' import { OFF } from '../flags' import type { OptionsComponentExts } from '../types' @@ -29,30 +29,34 @@ export function markdown(options: OptionsComponentExts = {}): FlatESLintConfigIt }, }, }, + plugins: { + ts: pluginTs as any, + }, rules: { ...pluginMarkdown.configs.recommended.overrides[1].rules, - '@typescript-eslint/comma-dangle': OFF, - '@typescript-eslint/consistent-type-imports': OFF, - '@typescript-eslint/no-namespace': OFF, - '@typescript-eslint/no-redeclare': OFF, - '@typescript-eslint/no-require-imports': OFF, - '@typescript-eslint/no-unused-vars': OFF, - '@typescript-eslint/no-use-before-define': OFF, - '@typescript-eslint/no-var-requires': OFF, 'antfu/no-cjs-exports': OFF, 'antfu/no-ts-export-equal': OFF, 'import/no-unresolved': OFF, - 'n/prefer-global/process': OFF, - 'no-alert': OFF, 'no-console': OFF, 'no-restricted-imports': OFF, 'no-undef': OFF, 'no-unused-expressions': OFF, 'no-unused-vars': OFF, + + 'node/prefer-global/process': OFF, + + 'ts/comma-dangle': OFF, + 'ts/consistent-type-imports': OFF, + 'ts/no-namespace': OFF, + 'ts/no-redeclare': OFF, + 'ts/no-require-imports': OFF, + 'ts/no-unused-vars': OFF, + 'ts/no-use-before-define': OFF, + 'ts/no-var-requires': OFF, 'unused-imports/no-unused-imports': OFF, 'unused-imports/no-unused-vars': OFF, diff --git a/packages/eslint-config/src/configs/node.ts b/packages/eslint-config/src/configs/node.ts index e7f7aeb2f1..adf0dde1ea 100644 --- a/packages/eslint-config/src/configs/node.ts +++ b/packages/eslint-config/src/configs/node.ts @@ -4,18 +4,17 @@ import { pluginNode } from '../plugins' export const node: FlatESLintConfigItem[] = [ { plugins: { - n: pluginNode, + node: pluginNode, }, rules: { - // Node - 'n/handle-callback-err': ['error', '^(err|error)$'], - 'n/no-deprecated-api': 'error', - 'n/no-exports-assign': 'error', - 'n/no-new-require': 'error', - 'n/no-path-concat': 'error', - 'n/prefer-global/buffer': ['error', 'never'], - 'n/prefer-global/process': ['error', 'never'], - 'n/process-exit-as-throw': 'error', + 'node/handle-callback-err': ['error', '^(err|error)$'], + 'node/no-deprecated-api': 'error', + 'node/no-exports-assign': 'error', + 'node/no-new-require': 'error', + 'node/no-path-concat': 'error', + 'node/prefer-global/buffer': ['error', 'never'], + 'node/prefer-global/process': ['error', 'never'], + 'node/process-exit-as-throw': 'error', }, }, ] diff --git a/packages/eslint-config/src/configs/stylistic.ts b/packages/eslint-config/src/configs/stylistic.ts index c01d6a5734..cd91db23ed 100644 --- a/packages/eslint-config/src/configs/stylistic.ts +++ b/packages/eslint-config/src/configs/stylistic.ts @@ -1,25 +1,34 @@ import type { FlatESLintConfigItem } from 'eslint-define-config' -import { rules } from '@eslint-stylistic/metadata' -import { pluginStylisticJs, pluginStylisticTs } from '../plugins' +import { packages } from '@eslint-stylistic/metadata' +import { pluginStylisticJs, pluginStylisticTs, pluginTs } from '../plugins' import { OFF } from '../flags' +const tsPackage = packages.find(i => i.shortId === 'ts')! +const jsPackage = packages.find(i => i.shortId === 'js')! + export const javascriptStylistic: FlatESLintConfigItem[] = [ { plugins: { - '@stylistic/js': pluginStylisticJs, + style: pluginStylisticJs, }, rules: { - '@stylistic/js/array-bracket-spacing': ['error', 'never'], - '@stylistic/js/arrow-spacing': ['error', { after: true, before: true }], - '@stylistic/js/block-spacing': ['error', 'always'], - '@stylistic/js/brace-style': ['error', 'stroustrup', { allowSingleLine: true }], - '@stylistic/js/comma-spacing': ['error', { after: true, before: false }], - '@stylistic/js/comma-style': ['error', 'last'], - '@stylistic/js/computed-property-spacing': ['error', 'never', { enforceForClassMembers: true }], - '@stylistic/js/dot-location': ['error', 'property'], - '@stylistic/js/func-call-spacing': OFF, - '@stylistic/js/generator-star-spacing': OFF, - '@stylistic/js/indent': ['error', 2, { + 'antfu/if-newline': 'error', + 'comma-dangle': ['error', 'always-multiline'], + 'curly': ['error', 'multi-or-nest', 'consistent'], + 'quotes': ['error', 'single'], + 'semi': ['error', 'never'], + + 'style/array-bracket-spacing': ['error', 'never'], + 'style/arrow-spacing': ['error', { after: true, before: true }], + 'style/block-spacing': ['error', 'always'], + 'style/brace-style': ['error', 'stroustrup', { allowSingleLine: true }], + 'style/comma-spacing': ['error', { after: true, before: false }], + 'style/comma-style': ['error', 'last'], + 'style/computed-property-spacing': ['error', 'never', { enforceForClassMembers: true }], + 'style/dot-location': ['error', 'property'], + 'style/func-call-spacing': OFF, + 'style/generator-star-spacing': OFF, + 'style/indent': ['error', 2, { ArrayExpression: 1, CallExpression: { arguments: 1 }, FunctionDeclaration: { body: 1, parameters: 1 }, @@ -57,29 +66,29 @@ export const javascriptStylistic: FlatESLintConfigItem[] = [ offsetTernaryExpressions: true, outerIIFEBody: 1, }], - '@stylistic/js/key-spacing': ['error', { afterColon: true, beforeColon: false }], - '@stylistic/js/keyword-spacing': ['error', { after: true, before: true }], - '@stylistic/js/lines-between-class-members': ['error', 'always', { exceptAfterSingleLine: true }], - '@stylistic/js/multiline-ternary': ['error', 'always-multiline'], - '@stylistic/js/no-mixed-spaces-and-tabs': 'error', - '@stylistic/js/no-multi-spaces': 'error', - '@stylistic/js/no-multiple-empty-lines': ['error', { max: 1, maxBOF: 0, maxEOF: 0 }], - '@stylistic/js/no-tabs': 'error', - '@stylistic/js/no-trailing-spaces': 'error', - '@stylistic/js/no-whitespace-before-property': 'error', - '@stylistic/js/object-curly-newline': ['error', { consistent: true, multiline: true }], - '@stylistic/js/object-curly-spacing': ['error', 'always'], - '@stylistic/js/object-property-newline': ['error', { allowMultiplePropertiesPerLine: true }], - '@stylistic/js/operator-linebreak': ['error', 'before'], - '@stylistic/js/padded-blocks': ['error', { blocks: 'never', classes: 'never', switches: 'never' }], - '@stylistic/js/rest-spread-spacing': ['error', 'never'], - '@stylistic/js/semi-spacing': ['error', { after: true, before: false }], - '@stylistic/js/space-before-blocks': ['error', 'always'], - '@stylistic/js/space-before-function-paren': ['error', { anonymous: 'always', asyncArrow: 'always', named: 'never' }], - '@stylistic/js/space-in-parens': ['error', 'never'], - '@stylistic/js/space-infix-ops': 'error', - '@stylistic/js/space-unary-ops': ['error', { nonwords: false, words: true }], - '@stylistic/js/spaced-comment': ['error', 'always', { + 'style/key-spacing': ['error', { afterColon: true, beforeColon: false }], + 'style/keyword-spacing': ['error', { after: true, before: true }], + 'style/lines-between-class-members': ['error', 'always', { exceptAfterSingleLine: true }], + 'style/multiline-ternary': ['error', 'always-multiline'], + 'style/no-mixed-spaces-and-tabs': 'error', + 'style/no-multi-spaces': 'error', + 'style/no-multiple-empty-lines': ['error', { max: 1, maxBOF: 0, maxEOF: 0 }], + 'style/no-tabs': 'error', + 'style/no-trailing-spaces': 'error', + 'style/no-whitespace-before-property': 'error', + 'style/object-curly-newline': ['error', { consistent: true, multiline: true }], + 'style/object-curly-spacing': ['error', 'always'], + 'style/object-property-newline': ['error', { allowMultiplePropertiesPerLine: true }], + 'style/operator-linebreak': ['error', 'before'], + 'style/padded-blocks': ['error', { blocks: 'never', classes: 'never', switches: 'never' }], + 'style/rest-spread-spacing': ['error', 'never'], + 'style/semi-spacing': ['error', { after: true, before: false }], + 'style/space-before-blocks': ['error', 'always'], + 'style/space-before-function-paren': ['error', { anonymous: 'always', asyncArrow: 'always', named: 'never' }], + 'style/space-in-parens': ['error', 'never'], + 'style/space-infix-ops': 'error', + 'style/space-unary-ops': ['error', { nonwords: false, words: true }], + 'style/spaced-comment': ['error', 'always', { block: { balanced: true, exceptions: ['*'], @@ -90,15 +99,9 @@ export const javascriptStylistic: FlatESLintConfigItem[] = [ markers: ['/'], }, }], - '@stylistic/js/template-curly-spacing': 'error', - '@stylistic/js/template-tag-spacing': ['error', 'never'], - '@stylistic/js/yield-star-spacing': ['error', 'both'], - - 'antfu/if-newline': 'error', - 'comma-dangle': ['error', 'always-multiline'], - 'curly': ['error', 'multi-or-nest', 'consistent'], - 'quotes': ['error', 'single'], - 'semi': ['error', 'never'], + 'style/template-curly-spacing': 'error', + 'style/template-tag-spacing': ['error', 'never'], + 'style/yield-star-spacing': ['error', 'both'], }, }, ] @@ -106,13 +109,22 @@ export const javascriptStylistic: FlatESLintConfigItem[] = [ export const typescriptStylistic: FlatESLintConfigItem[] = [ { plugins: { - '@stylistic/js': pluginStylisticJs, - '@stylistic/ts': pluginStylisticTs, + 'style-ts': pluginStylisticTs, + 'ts': pluginTs as any, }, rules: { - ...stylisticJsToTS(rules), - '@stylistic/ts/member-delimiter-style': ['error', { multiline: { delimiter: 'none' } }], - '@stylistic/ts/type-annotation-spacing': ['error', {}], + ...stylisticJsToTS(javascriptStylistic[0].rules!), + + 'comma-dangle': OFF, + 'quotes': OFF, + 'semi': OFF, + + 'style-ts/member-delimiter-style': ['error', { multiline: { delimiter: 'none' } }], + 'style-ts/type-annotation-spacing': ['error', {}], + + 'ts/comma-dangle': ['error', 'always-multiline'], + 'ts/quotes': ['error', 'single'], + 'ts/semi': ['error', 'never'], }, }, ] @@ -120,21 +132,28 @@ export const typescriptStylistic: FlatESLintConfigItem[] = [ // TODO: move to ESLint Stylistic function stylisticJsToTS(input: Record) { return { - // turn off all stylistic rules from @stylistic/js + // turn off all stylistic rules from style ...Object.fromEntries( Object.entries(input) - .map(([key]) => rules.find(i => i.name === key) ? [key, OFF] : null!) + .map(([key]) => { + if (!key.startsWith('style/')) + return null! + const basename = key.replace('style/', '') + if (jsPackage.rules.find(i => i.name === basename)) + return [key, OFF] + return null! + }) .filter(Boolean), ), - // rename all stylistic rules from @stylistic/js to @stylistic/ts + // rename all stylistic rules from style to style/ts ...Object.fromEntries( Object.entries(input) .map(([key, value]) => { - const newKey = key.replace('@stylistic/js', '@stylistic/ts') - if (newKey === key) + if (!key.startsWith('style/')) return null! - return rules.find(i => i.name === newKey) - ? [key.replace('@stylistic/js', '@stylistic/ts'), value] + const basename = key.replace('style/', '') + return tsPackage.rules.find(i => i.name === basename) + ? [`style-ts/${basename}`, value] : null! }) .filter(Boolean), diff --git a/packages/eslint-config/src/configs/typescript.ts b/packages/eslint-config/src/configs/typescript.ts index af141afc8e..a11639fa5f 100644 --- a/packages/eslint-config/src/configs/typescript.ts +++ b/packages/eslint-config/src/configs/typescript.ts @@ -4,6 +4,7 @@ import { GLOB_TS, GLOB_TSX } from '../globs' import { parserTs, pluginAntfu, pluginImport, pluginTs } from '../plugins' import { OFF } from '../flags' import type { OptionsComponentExts, OptionsTypeScriptWithLanguageServer } from '../types' +import { renameRules } from '../utils' export function typescript(options?: OptionsComponentExts): FlatESLintConfigItem[] { const { @@ -24,42 +25,21 @@ export function typescript(options?: OptionsComponentExts): FlatESLintConfigItem }, }, plugins: { - '@typescript-eslint': pluginTs as any, - 'antfu': pluginAntfu, - 'import': pluginImport, + antfu: pluginAntfu, + import: pluginImport, + ts: pluginTs as any, }, rules: { - ...pluginTs.configs['eslint-recommended'].overrides![0].rules, - ...pluginTs.configs.strict.rules, - - // TS - '@typescript-eslint/ban-ts-comment': ['error', { 'ts-ignore': 'allow-with-description' }], - '@typescript-eslint/ban-ts-ignore': OFF, - '@typescript-eslint/comma-dangle': ['error', 'always-multiline'], - '@typescript-eslint/consistent-indexed-object-style': OFF, - '@typescript-eslint/consistent-type-definitions': ['error', 'interface'], - '@typescript-eslint/consistent-type-imports': ['error', { disallowTypeAnnotations: false, prefer: 'type-imports' }], - '@typescript-eslint/explicit-function-return-type': OFF, - '@typescript-eslint/explicit-member-accessibility': OFF, - '@typescript-eslint/explicit-module-boundary-types': OFF, - '@typescript-eslint/naming-convention': OFF, - '@typescript-eslint/no-dupe-class-members': 'error', - '@typescript-eslint/no-empty-function': OFF, - '@typescript-eslint/no-empty-interface': OFF, - '@typescript-eslint/no-explicit-any': OFF, - '@typescript-eslint/no-extra-parens': ['error', 'functions'], - '@typescript-eslint/no-invalid-this': 'error', - '@typescript-eslint/no-loss-of-precision': 'error', - '@typescript-eslint/no-non-null-assertion': OFF, - '@typescript-eslint/no-redeclare': 'error', - '@typescript-eslint/no-require-imports': 'error', - '@typescript-eslint/no-unused-vars': OFF, - '@typescript-eslint/no-use-before-define': ['error', { classes: false, functions: false, variables: true }], - '@typescript-eslint/parameter-properties': OFF, - '@typescript-eslint/prefer-ts-expect-error': 'error', - '@typescript-eslint/quotes': ['error', 'single'], - '@typescript-eslint/semi': ['error', 'never'], - '@typescript-eslint/triple-slash-reference': OFF, + ...renameRules( + pluginTs.configs['eslint-recommended'].overrides![0].rules!, + '@typescript-eslint/', + 'ts/', + ), + ...renameRules( + pluginTs.configs.strict.rules!, + '@typescript-eslint/', + 'ts/', + ), 'antfu/generic-spacing': 'error', 'antfu/named-tuple-spacing': 'error', @@ -67,7 +47,6 @@ export function typescript(options?: OptionsComponentExts): FlatESLintConfigItem 'antfu/no-const-enum': 'error', 'antfu/no-ts-export-equal': 'error', - 'comma-dangle': OFF, 'no-dupe-class-members': OFF, 'no-extra-parens': OFF, 'no-invalid-this': OFF, @@ -75,8 +54,34 @@ export function typescript(options?: OptionsComponentExts): FlatESLintConfigItem 'no-redeclare': OFF, 'no-use-before-define': OFF, 'no-useless-constructor': OFF, - 'quotes': OFF, - 'semi': OFF, + + // TS + 'ts/ban-ts-comment': ['error', { 'ts-ignore': 'allow-with-description' }], + 'ts/ban-ts-ignore': OFF, + 'ts/consistent-indexed-object-style': OFF, + 'ts/consistent-type-definitions': ['error', 'interface'], + 'ts/consistent-type-imports': ['error', { disallowTypeAnnotations: false, prefer: 'type-imports' }], + 'ts/explicit-function-return-type': OFF, + 'ts/explicit-member-accessibility': OFF, + 'ts/explicit-module-boundary-types': OFF, + 'ts/naming-convention': OFF, + 'ts/no-dupe-class-members': 'error', + 'ts/no-empty-function': OFF, + + 'ts/no-empty-interface': OFF, + 'ts/no-explicit-any': OFF, + 'ts/no-extra-parens': ['error', 'functions'], + 'ts/no-invalid-this': 'error', + 'ts/no-loss-of-precision': 'error', + + 'ts/no-non-null-assertion': OFF, + 'ts/no-redeclare': 'error', + 'ts/no-require-imports': 'error', + 'ts/no-unused-vars': OFF, + 'ts/no-use-before-define': ['error', { classes: false, functions: false, variables: true }], + 'ts/parameter-properties': OFF, + 'ts/prefer-ts-expect-error': 'error', + 'ts/triple-slash-reference': OFF, }, }, { @@ -96,8 +101,8 @@ export function typescript(options?: OptionsComponentExts): FlatESLintConfigItem { files: ['**/*.js', '**/*.cjs'], rules: { - '@typescript-eslint/no-require-imports': OFF, - '@typescript-eslint/no-var-requires': OFF, + 'ts/no-require-imports': OFF, + 'ts/no-var-requires': OFF, }, }, ] @@ -126,30 +131,30 @@ export function typescriptWithLanguageServer(options: OptionsTypeScriptWithLangu }, }, plugins: { - '@typescript-eslint': pluginTs as any, + ts: pluginTs as any, }, rules: { - '@typescript-eslint/await-thenable': 'error', - '@typescript-eslint/dot-notation': ['error', { allowKeywords: true }], - '@typescript-eslint/no-floating-promises': 'error', - '@typescript-eslint/no-for-in-array': 'error', - '@typescript-eslint/no-implied-eval': 'error', - '@typescript-eslint/no-misused-promises': 'error', - '@typescript-eslint/no-throw-literal': 'error', - '@typescript-eslint/no-unnecessary-type-assertion': 'error', - '@typescript-eslint/no-unsafe-argument': 'error', - '@typescript-eslint/no-unsafe-assignment': 'error', - '@typescript-eslint/no-unsafe-call': 'error', - '@typescript-eslint/no-unsafe-member-access': 'error', - '@typescript-eslint/no-unsafe-return': 'error', - '@typescript-eslint/require-await': 'error', - '@typescript-eslint/restrict-plus-operands': 'error', - '@typescript-eslint/restrict-template-expressions': 'error', - '@typescript-eslint/unbound-method': 'error', 'dot-notation': OFF, 'no-implied-eval': OFF, 'no-throw-literal': OFF, 'require-await': OFF, + 'ts/await-thenable': 'error', + 'ts/dot-notation': ['error', { allowKeywords: true }], + 'ts/no-floating-promises': 'error', + 'ts/no-for-in-array': 'error', + 'ts/no-implied-eval': 'error', + 'ts/no-misused-promises': 'error', + 'ts/no-throw-literal': 'error', + 'ts/no-unnecessary-type-assertion': 'error', + 'ts/no-unsafe-argument': 'error', + 'ts/no-unsafe-assignment': 'error', + 'ts/no-unsafe-call': 'error', + 'ts/no-unsafe-member-access': 'error', + 'ts/no-unsafe-return': 'error', + 'ts/require-await': 'error', + 'ts/restrict-plus-operands': 'error', + 'ts/restrict-template-expressions': 'error', + 'ts/unbound-method': 'error', }, }, ] diff --git a/packages/eslint-config/src/configs/yml.ts b/packages/eslint-config/src/configs/yml.ts index c9c27a4aa6..7f3d0d29b8 100644 --- a/packages/eslint-config/src/configs/yml.ts +++ b/packages/eslint-config/src/configs/yml.ts @@ -15,7 +15,7 @@ export const yml: FlatESLintConfigItem[] = [ rules: { ...pluginYml.configs.standard.rules as any, - '@stylistic/js/spaced-comment': OFF, + 'style/spaced-comment': OFF, 'yml/no-empty-document': OFF, 'yml/no-empty-mapping-value': OFF, diff --git a/packages/eslint-config/src/plugins.ts b/packages/eslint-config/src/plugins.ts index 21238be365..bc6fcd5692 100644 --- a/packages/eslint-config/src/plugins.ts +++ b/packages/eslint-config/src/plugins.ts @@ -1,4 +1,4 @@ -// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// eslint-disable-next-line ts/ban-ts-comment // @ts-nocheck export { default as pluginAntfu } from 'eslint-plugin-antfu' @@ -21,3 +21,4 @@ export { default as parserTs } from '@typescript-eslint/parser' export { default as parserVue } from 'vue-eslint-parser' export { default as parserYml } from 'yaml-eslint-parser' export { default as parserJsonc } from 'jsonc-eslint-parser' + diff --git a/packages/eslint-config/src/utils.ts b/packages/eslint-config/src/utils.ts index 1d41e6e84a..a8454e9830 100644 --- a/packages/eslint-config/src/utils.ts +++ b/packages/eslint-config/src/utils.ts @@ -6,3 +6,14 @@ import type { FlatESLintConfigItem } from 'eslint-define-config' export function combine(...configs: (FlatESLintConfigItem | FlatESLintConfigItem[])[]): FlatESLintConfigItem[] { return configs.flatMap(config => Array.isArray(config) ? config : [config]) } + +export function renameRules(rules: Record, from: string, to: string) { + return Object.fromEntries( + Object.entries(rules) + .map(([key, value]) => { + if (key.startsWith(from)) + return [to + key.slice(from.length), value] + return [key, value] + }), + ) +}