diff --git a/packages/eslint/src/rules/html/migrations/no-deprecated-btn-rg.ts b/packages/eslint/src/rules/html/migrations/no-deprecated-btn-rg.ts index 29304cafc1..e4fdfb6b16 100644 --- a/packages/eslint/src/rules/html/migrations/no-deprecated-btn-rg.ts +++ b/packages/eslint/src/rules/html/migrations/no-deprecated-btn-rg.ts @@ -1,43 +1,15 @@ -import { createRule } from '../../../utils/create-rule'; -import { HtmlNode } from '../../../parsers/html/html-node'; +import { createClassUpdateRule } from '../../../utils/create-class-update-rule'; export const name = 'no-deprecated-btn-rg'; -// Type: RuleModule<"uppercase", ...> -export default createRule({ +export default createClassUpdateRule({ name, - meta: { - docs: { - dir: 'html', - description: - 'Flags deprecated "btn-rg" class and suggests removal or replacement with "btn-sm".', - }, - messages: { - deprecatedBtnRg: - 'The "btn-rg" class is deprecated. Please remove it or replace it with "btn-sm".', - }, - type: 'suggestion', - fixable: 'code', - schema: [], + type:'suggestion', + description: 'Flags deprecated "btn-rg" class and suggests removal or replacement with "btn-sm".', + messages: { + deprecatedBtnRg: 'The "btn-rg" class is deprecated. Please remove it or replace it with "btn-sm".', }, - defaultOptions: [], - create(context) { - return { - tag(node: HtmlNode) { - if (node.name && ['button', 'input', 'a'].includes(node.name)) { - const $node = node.toCheerio(); - if ($node.hasClass('btn-rg')) { - context.report({ - messageId: 'deprecatedBtnRg', - loc: node.loc, - fix(fixer) { - const fixedNode = $node.removeClass('btn-rg').addClass('btn-sm'); - return fixer.replaceTextRange(node.range, fixedNode.toString()); - }, - }); - } - } - }, - }; + mutations: { + deprecatedBtnRg: ['btn-rg', 'btn-sm'] }, }); diff --git a/packages/eslint/src/utils/create-class-update-rule.ts b/packages/eslint/src/utils/create-class-update-rule.ts new file mode 100644 index 0000000000..71eff6b38c --- /dev/null +++ b/packages/eslint/src/utils/create-class-update-rule.ts @@ -0,0 +1,50 @@ +import { createRule } from './create-rule'; +import { HtmlNode } from '../parsers/html/html-node'; +import { Rule } from 'eslint'; + +interface RuleConfig{ + name: string; + description: string; + messages: T; + mutations: Record; + type?: Rule.RuleMetaData['type']; +} + +export const createClassUpdateRule = >( + config: RuleConfig +) => createRule({ + name: config.name, + meta: { + docs: { + dir: 'html', + description: config.description, + }, + messages: config.messages, + type: config.type || 'problem', + fixable: 'code', + schema: [], + }, + defaultOptions: [], + create(context) { + return { + tag(node: HtmlNode) { + const $node = node.toCheerio(); + + Object.entries(config.mutations).forEach(([messageId, [oldClass, newClass]]) => { + if ($node.hasClass(oldClass)) { + context.report({ + messageId, + loc: node.loc, + ... newClass ? { + fix(fixer) { + const fixedNode = $node.removeClass(oldClass).addClass(newClass); + return fixer.replaceTextRange(node.range, fixedNode.toString()); + } + } : {}, + }); + } + }); + }, + }; + }, +});