Skip to content

Commit

Permalink
Fix review comments for no-deprecated-router-link-tag-prop
Browse files Browse the repository at this point in the history
- Use helper functions from utils to get attributes for nodes.
- Add more test cases.
- Handle both kebab-case and PascalCase version of components.
  • Loading branch information
csordasmarton committed Oct 19, 2021
1 parent 3d970ba commit 47270f3
Show file tree
Hide file tree
Showing 3 changed files with 218 additions and 28 deletions.
27 changes: 23 additions & 4 deletions docs/rules/no-deprecated-router-link-tag-prop.md
Expand Up @@ -20,16 +20,24 @@ This rule reports deprecated the `tag` attribute on `RouterLink` elements (remov
<template>
<!-- ✓ GOOD -->
<RouterLink to="/">Home</RouterLink>
<router-link to="/">Home</router-link>
<RouterLink to="/">
<div>Home</div>
</RouterLink>
<router-link to="/">
<div>Home</div>
</router-link>
<NuxtLink tag="div" to="/">Home</NuxtLink>
<nuxt-link tag="div" to="/">Home</nuxt-link>
<!-- ✗ BAD -->
<RouterLink tag="div" to="/">Home</RouterLink>
<router-link tag="div" to="/">Home</router-link>
<RouterLink :tag="someVariable" to="/">Home</RouterLink>
<router-link :tag="someVariable" to="/">Home</router-link>
</template>
```

Expand All @@ -40,23 +48,34 @@ 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'] }`

<eslint-code-block :rules="{'vue/no-deprecated-router-link-tag-prop': ['error', {'components': ['RouterLink', 'NuxtLink']}]}">

```vue
<template>
<!-- ✗ BAD -->
<NuxtLink tag="div" to="/">Home</NuxtLink>
<NuxtLink :tag="someVariable" to="/">Home</NuxtLink>
<RouterLink tag="div" to="/">Home</RouterLink>
<router-link tag="div" to="/">Home</router-link>
<RouterLink :tag="someVariable" to="/">Home</RouterLink>
<router-link :tag="someVariable" to="/">Home</router-link>
<NuxtLink tag="div" to="/">Home</NuxtLink>
<nuxt-link tag="div" to="/">Home</nuxt-link>
<NuxtLink :tag="someVariable" to="/">Home</NuxtLink>
<nuxt-link :tag="someVariable" to="/">Home</nuxt-link>
</template>
```

Expand Down
66 changes: 42 additions & 24 deletions lib/rules/no-deprecated-router-link-tag-prop.js
Expand Up @@ -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
Expand Down Expand Up @@ -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
}
})
}
}
})
}
Expand Down
153 changes: 153 additions & 0 deletions tests/lib/rules/no-deprecated-router-link-tag-prop.js
Expand Up @@ -25,6 +25,14 @@ tester.run('no-deprecated-router-link-tag-prop', rule, {
</template>
`
},
{
filename: 'test.vue',
code: `
<template>
<router-link to="/">Home</router-link>
</template>
`
},
{
filename: 'test.vue',
code: `
Expand All @@ -35,6 +43,16 @@ tester.run('no-deprecated-router-link-tag-prop', rule, {
</template>
`
},
{
filename: 'test.vue',
code: `
<template>
<router-link to="/">
<div>Home</div>
</router-link>
</template>
`
},
{
filename: 'test.vue',
code: `
Expand All @@ -43,6 +61,14 @@ tester.run('no-deprecated-router-link-tag-prop', rule, {
</template>
`
},
{
filename: 'test.vue',
code: `
<template>
<nuxt-link to="/">Home</nuxt-link>
</template>
`
},
{
filename: 'test.vue',
code: `
Expand All @@ -52,6 +78,16 @@ tester.run('no-deprecated-router-link-tag-prop', rule, {
</NuxtLink>
</template>
`
},
{
filename: 'test.vue',
code: `
<template>
<nuxt-link to="/">
<div>Home</div>
</nuxt-link>
</template>
`
}
],
invalid: [
Expand All @@ -71,6 +107,22 @@ tester.run('no-deprecated-router-link-tag-prop', rule, {
}
]
},
{
filename: 'test.vue',
code: `
<template>
<router-link tag="div" to="/">Home</router-link>
</template>
`,
errors: [
{
message:
"'tag' property on 'router-link' component is deprecated. Use scoped slots instead.",
line: 3,
column: 22
}
]
},
{
filename: 'test.vue',
code: `
Expand All @@ -88,6 +140,40 @@ tester.run('no-deprecated-router-link-tag-prop', rule, {
}
]
},
{
filename: 'test.vue',
code: `
<template>
<RouterLink tag="div" to="/">Home</RouterLink>
</template>
`,
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: `
<template>
<router-link tag="div" to="/">Home</router-link>
</template>
`,
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: `
Expand All @@ -104,6 +190,22 @@ tester.run('no-deprecated-router-link-tag-prop', rule, {
}
]
},
{
filename: 'test.vue',
code: `
<template>
<router-link :tag="someVariable" to="/">Home</router-link>
</template>
`,
errors: [
{
message:
"'tag' property on 'router-link' component is deprecated. Use scoped slots instead.",
line: 3,
column: 23
}
]
},
{
filename: 'test.vue',
code: `
Expand All @@ -121,6 +223,23 @@ tester.run('no-deprecated-router-link-tag-prop', rule, {
}
]
},
{
filename: 'test.vue',
code: `
<template>
<router-link :tag="someVariable" to="/">Home</router-link>
</template>
`,
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: `
Expand All @@ -138,6 +257,23 @@ tester.run('no-deprecated-router-link-tag-prop', rule, {
}
]
},
{
filename: 'test.vue',
code: `
<template>
<nuxt-link tag="div" to="/">Home</nuxt-link>
</template>
`,
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: `
Expand All @@ -154,6 +290,23 @@ tester.run('no-deprecated-router-link-tag-prop', rule, {
column: 20
}
]
},
{
filename: 'test.vue',
code: `
<template>
<nuxt-link :tag="someVariable" to="/">Home</nuxt-link>
</template>
`,
options: [{ components: ['NuxtLink'] }],
errors: [
{
message:
"'tag' property on 'nuxt-link' component is deprecated. Use scoped slots instead.",
line: 3,
column: 21
}
]
}
]
})

0 comments on commit 47270f3

Please sign in to comment.