Skip to content

Commit 92efc1d

Browse files
committed
⭐️New: Add vue/no-deprecated-slot-scope-attribute rule
1 parent 66a252d commit 92efc1d

6 files changed

+262
-0
lines changed

docs/rules/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ For example:
151151
| [vue/key-spacing](./key-spacing.md) | enforce consistent spacing between keys and values in object literal properties | :wrench: |
152152
| [vue/match-component-file-name](./match-component-file-name.md) | require component name property to match its file name | |
153153
| [vue/no-boolean-default](./no-boolean-default.md) | disallow boolean defaults | :wrench: |
154+
| [vue/no-deprecated-slot-scope-attribute](./no-deprecated-slot-scope-attribute.md) | disallow deprecated `slot-scope` attribute (in Vue.js 2.6.0+) | :wrench: |
154155
| [vue/no-empty-pattern](./no-empty-pattern.md) | disallow empty destructuring patterns | |
155156
| [vue/no-restricted-syntax](./no-restricted-syntax.md) | disallow specified syntax | |
156157
| [vue/object-curly-spacing](./object-curly-spacing.md) | enforce consistent spacing inside braces | :wrench: |
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
---
2+
pageClass: rule-details
3+
sidebarDepth: 0
4+
title: vue/no-deprecated-slot-scope-attribute
5+
description: disallow deprecated `slot-scope` attribute (in Vue.js 2.6.0+)
6+
---
7+
# vue/no-deprecated-slot-scope-attribute
8+
> disallow deprecated `slot-scope` attribute (in Vue.js 2.6.0+)
9+
10+
- :wrench: The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can automatically fix some of the problems reported by this rule.
11+
12+
## :book: Rule Details
13+
14+
This rule reports deprecated `slot-scope` attribute in Vue.js v2.6.0+.
15+
16+
<eslint-code-block fix :rules="{'vue/no-deprecated-slot-scope-attribute': ['error']}">
17+
18+
```vue
19+
<template>
20+
<ListComponent>
21+
<!-- ✓ GOOD -->
22+
<template v-slot="props">
23+
{{ props.title }}
24+
</template>
25+
</ListComponent>
26+
<ListComponent>
27+
<!-- ✗ BAD -->
28+
<template slot-scope="props">
29+
{{ props.title }}
30+
</template>
31+
</ListComponent>
32+
</template>
33+
```
34+
35+
</eslint-code-block>
36+
37+
## :books: Further reading
38+
39+
- [API - slot-scope](https://vuejs.org/v2/api/#slot-scope-deprecated)
40+
41+
## :mag: Implementation
42+
43+
- [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/no-deprecated-slot-scope-attribute.js)
44+
- [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/no-deprecated-slot-scope-attribute.js)

lib/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ module.exports = {
3535
'no-async-in-computed-properties': require('./rules/no-async-in-computed-properties'),
3636
'no-boolean-default': require('./rules/no-boolean-default'),
3737
'no-confusing-v-for-v-if': require('./rules/no-confusing-v-for-v-if'),
38+
'no-deprecated-slot-scope-attribute': require('./rules/no-deprecated-slot-scope-attribute'),
3839
'no-dupe-keys': require('./rules/no-dupe-keys'),
3940
'no-duplicate-attributes': require('./rules/no-duplicate-attributes'),
4041
'no-empty-pattern': require('./rules/no-empty-pattern'),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/**
2+
* @author Yosuke Ota
3+
* See LICENSE file in root directory for full license.
4+
*/
5+
'use strict'
6+
7+
const utils = require('../utils')
8+
const slotScopeAttribute = require('./syntaxes/slot-scope-attribute')
9+
10+
module.exports = {
11+
meta: {
12+
type: 'suggestion',
13+
docs: {
14+
description: 'disallow deprecated `slot-scope` attribute (in Vue.js 2.6.0+)',
15+
category: undefined,
16+
url: 'https://eslint.vuejs.org/rules/no-deprecated-slot-scope-attribute.html'
17+
},
18+
fixable: 'code',
19+
schema: [],
20+
messages: {
21+
forbiddenSlotScopeAttribute: '`slot-scope` are deprecated.'
22+
}
23+
},
24+
create (context) {
25+
const templateBodyVisitor = slotScopeAttribute.createTemplateBodyVisitor(context, { fixToUpgrade: true })
26+
return utils.defineTemplateBodyVisitor(context, templateBodyVisitor)
27+
}
28+
}
+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/**
2+
* @author Yosuke Ota
3+
* See LICENSE file in root directory for full license.
4+
*/
5+
'use strict'
6+
module.exports = {
7+
deprecated: '2.6.0',
8+
supported: '2.5.0',
9+
createTemplateBodyVisitor (context, { fixToUpgrade } = {}) {
10+
const sourceCode = context.getSourceCode()
11+
/**
12+
* Convert to `v-slot`.
13+
* @param {object} fixer fixer
14+
* @param {VAttribute | null} slotAttr node of `slot`
15+
* @param {VAttribute | null} scopeAttr node of `slot-scope`
16+
* @returns {*} fix data
17+
*/
18+
function fixSlotToVSlot (fixer, slotAttr, scopeAttr) {
19+
const nameArgument = slotAttr && slotAttr.value && slotAttr && slotAttr.value.value
20+
? `:${slotAttr.value.value}`
21+
: ''
22+
const scopeValue = scopeAttr && scopeAttr.value
23+
? `=${sourceCode.getText(scopeAttr.value)}`
24+
: ''
25+
26+
const replaceText = `v-slot${nameArgument}${scopeValue}`
27+
const fixers = [
28+
fixer.replaceText(slotAttr || scopeAttr, replaceText)
29+
]
30+
if (slotAttr && scopeAttr) {
31+
fixers.push(fixer.remove(scopeAttr))
32+
}
33+
return fixers
34+
}
35+
/**
36+
* Reports `slot-scope` node
37+
* @param {VAttribute} scopeAttr node of `slot-scope`
38+
* @returns {void}
39+
*/
40+
function reportSlotScope (scopeAttr) {
41+
context.report({
42+
node: scopeAttr.key,
43+
messageId: 'forbiddenSlotScopeAttribute',
44+
fix: fixToUpgrade
45+
// fix to use `v-slot`
46+
? (fixer) => {
47+
const element = scopeAttr.parent
48+
const slotAttr = element.attributes
49+
.find(attr => attr.directive === false && attr.key.name === 'slot')
50+
return fixSlotToVSlot(fixer, slotAttr, scopeAttr)
51+
}
52+
: null
53+
})
54+
}
55+
56+
return {
57+
"VAttribute[directive=true][key.name.name='slot-scope']": reportSlotScope
58+
}
59+
}
60+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
'use strict'
2+
3+
const RuleTester = require('eslint').RuleTester
4+
const rule = require('../../../lib/rules/no-deprecated-slot-scope-attribute')
5+
6+
const tester = new RuleTester({
7+
parser: 'vue-eslint-parser',
8+
parserOptions: {
9+
ecmaVersion: 2015
10+
}
11+
})
12+
13+
tester.run('no-deprecated-slot-scope-attribute', rule, {
14+
valid: [
15+
`<template>
16+
<LinkList>
17+
<a v-slot:name />
18+
</LinkList>
19+
</template>`,
20+
`<template>
21+
<LinkList>
22+
<a #name />
23+
</LinkList>
24+
</template>`,
25+
`<template>
26+
<LinkList>
27+
<a v-slot="{a}" />
28+
</LinkList>
29+
</template>`,
30+
`<template>
31+
<LinkList>
32+
<a #default="{a}" />
33+
</LinkList>
34+
</template>`,
35+
`<template>
36+
<LinkList>
37+
<a slot="name" />
38+
</LinkList>
39+
</template>`,
40+
`<template>
41+
<LinkList>
42+
<a />
43+
</LinkList>
44+
</template>`
45+
],
46+
invalid: [
47+
{
48+
code: `
49+
<template>
50+
<LinkList>
51+
<a slot="name" disabled slot-scope="{a}"/>
52+
</LinkList>
53+
</template>`,
54+
output: `
55+
<template>
56+
<LinkList>
57+
<a v-slot:name="{a}" disabled />
58+
</LinkList>
59+
</template>`,
60+
errors: [
61+
{
62+
message: '`slot-scope` are deprecated.',
63+
line: 4
64+
}
65+
]
66+
},
67+
{
68+
code: `
69+
<template>
70+
<LinkList>
71+
<a slot-scope />
72+
</LinkList>
73+
</template>`,
74+
output: `
75+
<template>
76+
<LinkList>
77+
<a v-slot />
78+
</LinkList>
79+
</template>`,
80+
errors: [
81+
{
82+
message: '`slot-scope` are deprecated.',
83+
line: 4
84+
}
85+
]
86+
},
87+
{
88+
code: `
89+
<template>
90+
<LinkList>
91+
<a slot-scope="{a}" />
92+
</LinkList>
93+
</template>`,
94+
output: `
95+
<template>
96+
<LinkList>
97+
<a v-slot="{a}" />
98+
</LinkList>
99+
</template>`,
100+
errors: [
101+
{
102+
message: '`slot-scope` are deprecated.',
103+
line: 4
104+
}
105+
]
106+
},
107+
{
108+
code: `
109+
<template>
110+
<LinkList>
111+
<a slot-scope="{a}" slot="name"/>
112+
</LinkList>
113+
</template>`,
114+
output: `
115+
<template>
116+
<LinkList>
117+
<a v-slot:name="{a}"/>
118+
</LinkList>
119+
</template>`,
120+
errors: [
121+
{
122+
message: '`slot-scope` are deprecated.',
123+
line: 4
124+
}
125+
]
126+
}
127+
]
128+
})

0 commit comments

Comments
 (0)