Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add
no-deprecated-router-link-tag-prop
rule
- Loading branch information
1 parent
7bca4d3
commit be4e0e8
Showing
5 changed files
with
311 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
--- | ||
pageClass: rule-details | ||
sidebarDepth: 0 | ||
title: vue/no-deprecated-router-link-tag-prop | ||
description: disallow using deprecated `tag` property on `RouterLink` (in Vue.js 3.0.0+) | ||
--- | ||
# vue/no-deprecated-router-link-tag-prop | ||
|
||
> disallow using deprecated `tag` property on `RouterLink` (in Vue.js 3.0.0+) | ||
- :exclamation: <badge text="This rule has not been released yet." vertical="middle" type="error"> ***This rule has not been released yet.*** </badge> | ||
|
||
## :book: Rule Details | ||
|
||
This rule reports deprecated the `tag` attribute on `RouterLink` elements (removed in Vue.js v3.0.0+). | ||
|
||
<eslint-code-block :rules="{'vue/no-deprecated-router-link-tag-prop': ['error']}"> | ||
|
||
```vue | ||
<template> | ||
<!-- ✓ GOOD --> | ||
<RouterLink to="/">Home</RouterLink> | ||
<RouterLink to="/"> | ||
<div>Home</div> | ||
</RouterLink> | ||
<NuxtLink tag="div" to="/">Home</NuxtLink> | ||
<!-- ✗ BAD --> | ||
<RouterLink tag="div" to="/">Home</RouterLink> | ||
<RouterLink :tag="someVariable" to="/">Home</RouterLink> | ||
</template> | ||
``` | ||
|
||
</eslint-code-block> | ||
|
||
## :wrench: Options | ||
|
||
```json | ||
{ | ||
"vue/no-deprecated-router-link-tag-prop": ["error", { | ||
"components": ['RouterLink', 'NuxtLink'] | ||
}] | ||
} | ||
``` | ||
|
||
### `{ "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> | ||
<RouterLink :tag="someVariable" to="/">Home</RouterLink> | ||
</template> | ||
``` | ||
|
||
</eslint-code-block> | ||
|
||
## :books: Further Reading | ||
|
||
- [Vue RFCs - 0021-router-link-scoped-slot](https://github.com/vuejs/rfcs/blob/master/active-rfcs/0021-router-link-scoped-slot.md) | ||
|
||
## :mag: Implementation | ||
|
||
- [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/no-deprecated-router-link-tag-prop.js) | ||
- [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/no-deprecated-router-link-tag-prop.js) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
/** | ||
* @author Marton Csordas | ||
* See LICENSE file in root directory for full license. | ||
*/ | ||
'use strict' | ||
|
||
// ------------------------------------------------------------------------------ | ||
// Requirements | ||
// ------------------------------------------------------------------------------ | ||
|
||
const utils = require('../utils') | ||
|
||
// ------------------------------------------------------------------------------ | ||
// Rule Definition | ||
// ------------------------------------------------------------------------------ | ||
|
||
module.exports = { | ||
meta: { | ||
type: 'problem', | ||
docs: { | ||
description: | ||
'disallow using deprecated `tag` property on `RouterLink` (in Vue.js 3.0.0+)', | ||
categories: undefined, | ||
url: 'https://eslint.vuejs.org/rules/no-deprecated-router-link-tag-prop' | ||
}, | ||
fixable: null, | ||
schema: [ | ||
{ | ||
type: 'object', | ||
properties: { | ||
components: { | ||
type: 'array', | ||
items: { | ||
type: 'string' | ||
}, | ||
uniqueItems: true, | ||
minItems: 1 | ||
} | ||
} | ||
} | ||
], | ||
messages: { | ||
deprecated: "'tag' property on '{{element}}' component is deprecated. Use scoped slots instead." | ||
} | ||
}, | ||
/** @param {RuleContext} context */ | ||
create(context) { | ||
let components = ['RouterLink'] | ||
if (context.options[0] && context.options[0].components) { | ||
components = context.options[0].components | ||
} | ||
|
||
return utils.defineTemplateBodyVisitor(context, { | ||
"VElement"(node) { | ||
if (!components.includes(node.rawName)) return | ||
|
||
const attributes = node.startTag.attributes | ||
attributes.forEach(attr => { | ||
/** @type VIdentifier | null */ | ||
let tagAttr = null; | ||
|
||
if (attr.key.type === 'VIdentifier') { | ||
tagAttr = attr.key; | ||
} else if (attr.directive && attr.key.type === 'VDirectiveKey') { | ||
const arg = attr.key.argument | ||
if (arg && arg.type === 'VIdentifier') { | ||
tagAttr = arg | ||
} | ||
} | ||
|
||
if (tagAttr && tagAttr.name === 'tag') { | ||
context.report({ | ||
node: tagAttr, | ||
messageId: 'deprecated', | ||
data: { | ||
element: node.rawName | ||
} | ||
}) | ||
} | ||
}) | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
/** | ||
* @author Marton Csordas | ||
* See LICENSE file in root directory for full license. | ||
*/ | ||
'use strict' | ||
|
||
const RuleTester = require('eslint').RuleTester | ||
const rule = require('../../../lib/rules/no-deprecated-router-link-tag-prop') | ||
|
||
const tester = new RuleTester({ | ||
parser: require.resolve('vue-eslint-parser'), | ||
parserOptions: { | ||
ecmaVersion: 2020, | ||
sourceType: 'module' | ||
} | ||
}) | ||
|
||
tester.run('no-deprecated-router-link-tag-prop', rule, { | ||
valid: [ | ||
{ | ||
filename: 'test.vue', | ||
code: ` | ||
<template> | ||
<RouterLink to="/">Home</RouterLink> | ||
</template> | ||
` | ||
}, | ||
{ | ||
filename: 'test.vue', | ||
code: ` | ||
<template> | ||
<RouterLink to="/"> | ||
<div>Home</div> | ||
</RouterLink> | ||
</template> | ||
` | ||
}, | ||
{ | ||
filename: 'test.vue', | ||
code: ` | ||
<template> | ||
<NuxtLink to="/">Home</NuxtLink> | ||
</template> | ||
` | ||
}, | ||
{ | ||
filename: 'test.vue', | ||
code: ` | ||
<template> | ||
<NuxtLink to="/"> | ||
<div>Home</div> | ||
</NuxtLink> | ||
</template> | ||
` | ||
}, | ||
], | ||
invalid: [ | ||
{ | ||
filename: 'test.vue', | ||
code: ` | ||
<template> | ||
<RouterLink tag="div" to="/">Home</RouterLink> | ||
</template> | ||
`, | ||
errors: [ | ||
{ | ||
message: "'tag' property on 'RouterLink' component is deprecated. Use scoped slots instead.", | ||
line: 3, | ||
column: 21 | ||
}, | ||
] | ||
}, | ||
{ | ||
filename: 'test.vue', | ||
code: ` | ||
<template> | ||
<RouterLink tag="div" to="/">Home</RouterLink> | ||
</template> | ||
`, | ||
options: [{ components: ['RouterLink'] }], | ||
errors: [ | ||
{ | ||
message: "'tag' property on 'RouterLink' component is deprecated. Use scoped slots instead.", | ||
line: 3, | ||
column: 21 | ||
}, | ||
] | ||
}, | ||
{ | ||
filename: 'test.vue', | ||
code: ` | ||
<template> | ||
<RouterLink :tag="someVariable" to="/">Home</RouterLink> | ||
</template> | ||
`, | ||
errors: [ | ||
{ | ||
message: "'tag' property on 'RouterLink' component is deprecated. Use scoped slots instead.", | ||
line: 3, | ||
column: 22 | ||
}, | ||
] | ||
}, | ||
{ | ||
filename: 'test.vue', | ||
code: ` | ||
<template> | ||
<RouterLink :tag="someVariable" to="/">Home</RouterLink> | ||
</template> | ||
`, | ||
options: [{ components: ['RouterLink'] }], | ||
errors: [ | ||
{ | ||
message: "'tag' property on 'RouterLink' component is deprecated. Use scoped slots instead.", | ||
line: 3, | ||
column: 22 | ||
}, | ||
] | ||
}, | ||
{ | ||
filename: 'test.vue', | ||
code: ` | ||
<template> | ||
<NuxtLink tag="div" to="/">Home</NuxtLink> | ||
</template> | ||
`, | ||
options: [{ components: ['NuxtLink'] }], | ||
errors: [ | ||
{ | ||
message: "'tag' property on 'NuxtLink' component is deprecated. Use scoped slots instead.", | ||
line: 3, | ||
column: 19 | ||
}, | ||
] | ||
}, | ||
{ | ||
filename: 'test.vue', | ||
code: ` | ||
<template> | ||
<NuxtLink :tag="someVariable" to="/">Home</NuxtLink> | ||
</template> | ||
`, | ||
options: [{ components: ['NuxtLink'] }], | ||
errors: [ | ||
{ | ||
message: "'tag' property on 'NuxtLink' component is deprecated. Use scoped slots instead.", | ||
line: 3, | ||
column: 20 | ||
}, | ||
] | ||
}, | ||
] | ||
}) |