diff --git a/docs/rules/no-deprecated-router-link-tag-prop.md b/docs/rules/no-deprecated-router-link-tag-prop.md index c57d05db8..e00cd8a67 100644 --- a/docs/rules/no-deprecated-router-link-tag-prop.md +++ b/docs/rules/no-deprecated-router-link-tag-prop.md @@ -20,16 +20,24 @@ This rule reports deprecated the `tag` attribute on `RouterLink` elements (remov ``` @@ -40,11 +48,16 @@ This rule reports deprecated the `tag` attribute on `RouterLink` elements (remov ```json { "vue/no-deprecated-router-link-tag-prop": ["error", { - "components": ['RouterLink', 'NuxtLink'] + "components": ['RouterLink'] }] } ``` +- `components` (`string[]`) ... Component names which will be checked with the `tag` attribute. default `['RouterLink']`. + +Note: this rule will check both `CamelCase` and `PascalCase` versions of the +given component names. + ### `{ "components": ['RouterLink', 'NuxtLink'] }` @@ -52,11 +65,17 @@ This rule reports deprecated the `tag` attribute on `RouterLink` elements (remov ```vue ``` diff --git a/lib/rules/no-deprecated-router-link-tag-prop.js b/lib/rules/no-deprecated-router-link-tag-prop.js index d9d1a2ee4..d73cf0ceb 100644 --- a/lib/rules/no-deprecated-router-link-tag-prop.js +++ b/lib/rules/no-deprecated-router-link-tag-prop.js @@ -9,6 +9,26 @@ // ------------------------------------------------------------------------------ const utils = require('../utils') +const casing = require('../utils/casing') + +// -------------------------------------------------------------------------- +// Helpers +// -------------------------------------------------------------------------- + +/** @param {RuleContext} context */ +function getComponentNames(context) { + let components = ['RouterLink'] + + if (context.options[0] && context.options[0].components) { + components = context.options[0].components + } + + return components.reduce((prev, curr) => { + prev.add(casing.kebabCase(curr)) + prev.add(casing.pascalCase(curr)) + return prev + }, new Set()) +} // ------------------------------------------------------------------------------ // Rule Definition @@ -46,39 +66,37 @@ module.exports = { }, /** @param {RuleContext} context */ create(context) { - let components = ['RouterLink'] - if (context.options[0] && context.options[0].components) { - components = context.options[0].components - } + const components = getComponentNames(context) return utils.defineTemplateBodyVisitor(context, { VElement(node) { - if (!components.includes(node.rawName)) return + if (!components.has(node.rawName)) return - const attributes = node.startTag.attributes - attributes.forEach((attr) => { - /** @type VIdentifier | null */ - let tagAttr = null + /** @type VIdentifier | null */ + let tagKey = null - if (attr.key.type === 'VIdentifier') { - tagAttr = attr.key - } else if (attr.directive && attr.key.type === 'VDirectiveKey') { - const arg = attr.key.argument + const tagAttr = utils.getAttribute(node, 'tag') + if (tagAttr) { + tagKey = tagAttr.key + } else { + const directive = utils.getDirective(node, 'bind', 'tag') + if (directive) { + const arg = directive.key.argument if (arg && arg.type === 'VIdentifier') { - tagAttr = arg + tagKey = arg } } + } - if (tagAttr && tagAttr.name === 'tag') { - context.report({ - node: tagAttr, - messageId: 'deprecated', - data: { - element: node.rawName - } - }) - } - }) + if (tagKey) { + context.report({ + node: tagKey, + messageId: 'deprecated', + data: { + element: node.rawName + } + }) + } } }) } diff --git a/tests/lib/rules/no-deprecated-router-link-tag-prop.js b/tests/lib/rules/no-deprecated-router-link-tag-prop.js index 6e61cd862..9154cf31c 100644 --- a/tests/lib/rules/no-deprecated-router-link-tag-prop.js +++ b/tests/lib/rules/no-deprecated-router-link-tag-prop.js @@ -25,6 +25,14 @@ tester.run('no-deprecated-router-link-tag-prop', rule, { ` }, + { + filename: 'test.vue', + code: ` + + ` + }, { filename: 'test.vue', code: ` @@ -35,6 +43,16 @@ tester.run('no-deprecated-router-link-tag-prop', rule, { ` }, + { + filename: 'test.vue', + code: ` + + ` + }, { filename: 'test.vue', code: ` @@ -43,6 +61,14 @@ tester.run('no-deprecated-router-link-tag-prop', rule, { ` }, + { + filename: 'test.vue', + code: ` + + ` + }, { filename: 'test.vue', code: ` @@ -52,6 +78,16 @@ tester.run('no-deprecated-router-link-tag-prop', rule, { ` + }, + { + filename: 'test.vue', + code: ` + + ` } ], invalid: [ @@ -71,6 +107,22 @@ tester.run('no-deprecated-router-link-tag-prop', rule, { } ] }, + { + filename: 'test.vue', + code: ` + + `, + errors: [ + { + message: + "'tag' property on 'router-link' component is deprecated. Use scoped slots instead.", + line: 3, + column: 22 + } + ] + }, { filename: 'test.vue', code: ` @@ -88,6 +140,40 @@ tester.run('no-deprecated-router-link-tag-prop', rule, { } ] }, + { + filename: 'test.vue', + code: ` + + `, + options: [{ components: ['router-link'] }], + errors: [ + { + message: + "'tag' property on 'RouterLink' component is deprecated. Use scoped slots instead.", + line: 3, + column: 21 + } + ] + }, + { + filename: 'test.vue', + code: ` + + `, + options: [{ components: ['RouterLink'] }], + errors: [ + { + message: + "'tag' property on 'router-link' component is deprecated. Use scoped slots instead.", + line: 3, + column: 22 + } + ] + }, { filename: 'test.vue', code: ` @@ -104,6 +190,22 @@ tester.run('no-deprecated-router-link-tag-prop', rule, { } ] }, + { + filename: 'test.vue', + code: ` + + `, + errors: [ + { + message: + "'tag' property on 'router-link' component is deprecated. Use scoped slots instead.", + line: 3, + column: 23 + } + ] + }, { filename: 'test.vue', code: ` @@ -121,6 +223,23 @@ tester.run('no-deprecated-router-link-tag-prop', rule, { } ] }, + { + filename: 'test.vue', + code: ` + + `, + options: [{ components: ['RouterLink'] }], + errors: [ + { + message: + "'tag' property on 'router-link' component is deprecated. Use scoped slots instead.", + line: 3, + column: 23 + } + ] + }, { filename: 'test.vue', code: ` @@ -138,6 +257,23 @@ tester.run('no-deprecated-router-link-tag-prop', rule, { } ] }, + { + filename: 'test.vue', + code: ` + + `, + options: [{ components: ['NuxtLink'] }], + errors: [ + { + message: + "'tag' property on 'nuxt-link' component is deprecated. Use scoped slots instead.", + line: 3, + column: 20 + } + ] + }, { filename: 'test.vue', code: ` @@ -154,6 +290,23 @@ tester.run('no-deprecated-router-link-tag-prop', rule, { column: 20 } ] + }, + { + filename: 'test.vue', + code: ` + + `, + options: [{ components: ['NuxtLink'] }], + errors: [ + { + message: + "'tag' property on 'nuxt-link' component is deprecated. Use scoped slots instead.", + line: 3, + column: 21 + } + ] } ] })