Skip to content

Commit 9140c63

Browse files
ST-DDTFloEdelmann
andauthored
feat(no-deprecated-slot-attribute): add ignoreParents option (#2784)
Co-authored-by: Flo Edelmann <git@flo-edelmann.de>
1 parent 26d99fd commit 9140c63

File tree

6 files changed

+167
-6
lines changed

6 files changed

+167
-6
lines changed

.changeset/beige-teams-camp.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'eslint-plugin-vue': minor
3+
---
4+
5+
Added `ignoreParents` option to [`vue/no-deprecated-slot-attribute`](https://eslint.vuejs.org/rules/no-deprecated-slot-attribute.html)

docs/rules/no-deprecated-slot-attribute.md

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,16 +43,18 @@ This rule reports deprecated `slot` attribute in Vue.js v2.6.0+.
4343
```json
4444
{
4545
"vue/no-deprecated-slot-attribute": ["error", {
46-
"ignore": ["my-component"]
46+
"ignore": ["my-component"],
47+
"ignoreParents": ["my-web-component"],
4748
}]
4849
}
4950
```
5051

5152
- `"ignore"` (`string[]`) An array of tags or regular expression patterns (e.g. `/^custom-/`) that ignore these rules. This option will check both kebab-case and PascalCase versions of the given tag names. Default is empty.
53+
- `"ignoreParents"` (`string[]`) An array of tags or regular expression patterns (e.g. `/^custom-/`) for parents that ignore these rules. This option is especially useful for [Web-Components](https://developer.mozilla.org/en-US/docs/Web/API/Web_components). Default is empty.
5254

5355
### `"ignore": ["my-component"]`
5456

55-
<eslint-code-block fix :rules="{'vue/no-dupe-keys': ['error', {ignore: ['my-component']}]}">
57+
<eslint-code-block fix :rules="{'vue/no-deprecated-slot-attribute': ['error', {ignore: ['my-component']}]}">
5658

5759
```vue
5860
<template>
@@ -81,9 +83,41 @@ This rule reports deprecated `slot` attribute in Vue.js v2.6.0+.
8183

8284
</eslint-code-block>
8385

86+
### `"ignoreParents": ["my-web-component"]`
87+
88+
<eslint-code-block fix :rules="{'vue/no-deprecated-slot-attribute': ['error', {ignoreParents: ['my-web-component']}]}">
89+
90+
```vue
91+
<template>
92+
<my-web-component>
93+
<!-- ✓ GOOD -->
94+
<template v-slot:name>
95+
{{ props.title }}
96+
</template>
97+
</my-web-component>
98+
99+
<my-web-component>
100+
<!-- ✓ GOOD -->
101+
<my-component slot="name">
102+
{{ props.title }}
103+
</my-component>
104+
</my-web-component>
105+
106+
<other-component>
107+
<!-- ✗ BAD -->
108+
<my-component slot="name">
109+
{{ props.title }}
110+
</my-component>
111+
</other-component>
112+
</template>
113+
```
114+
115+
</eslint-code-block>
116+
84117
## :books: Further Reading
85118

86119
- [API - slot](https://v2.vuejs.org/v2/api/#slot-deprecated)
120+
- [Web - slot](https://developer.mozilla.org/en-US/docs/Web/API/Element/slot)
87121

88122
## :rocket: Version
89123

lib/rules/no-deprecated-slot-attribute.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ module.exports = {
2525
type: 'array',
2626
items: { type: 'string' },
2727
uniqueItems: true
28+
},
29+
ignoreParents: {
30+
type: 'array',
31+
items: { type: 'string' },
32+
uniqueItems: true
2833
}
2934
},
3035
additionalProperties: false

lib/rules/syntaxes/slot-attribute.js

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,18 @@
77
const canConvertToVSlot = require('./utils/can-convert-to-v-slot')
88
const regexp = require('../../utils/regexp')
99
const casing = require('../../utils/casing')
10+
const { isVElement } = require('../../utils')
1011

1112
module.exports = {
1213
deprecated: '2.6.0',
1314
supported: '<3.0.0',
1415
/** @param {RuleContext} context @returns {TemplateListener} */
1516
createTemplateBodyVisitor(context) {
16-
/** @type {{ ignore: string[] }} */
17+
/** @type {{ ignore: string[], ignoreParents: string[] }} */
1718
const options = context.options[0] || {}
18-
const { ignore = [] } = options
19+
const { ignore = [], ignoreParents = [] } = options
1920
const isAnyIgnored = regexp.toRegExpGroupMatcher(ignore)
21+
const isParentIgnored = regexp.toRegExpGroupMatcher(ignoreParents)
2022

2123
const sourceCode = context.getSourceCode()
2224
const tokenStore =
@@ -123,7 +125,8 @@ module.exports = {
123125
* @returns {void}
124126
*/
125127
function reportSlot(slotAttr) {
126-
const componentName = slotAttr.parent.parent.rawName
128+
const component = slotAttr.parent.parent
129+
const componentName = component.rawName
127130

128131
if (
129132
isAnyIgnored(
@@ -135,6 +138,12 @@ module.exports = {
135138
return
136139
}
137140

141+
const parent = component.parent
142+
const parentName = isVElement(parent) ? parent.rawName : null
143+
if (parentName && isParentIgnored(parentName)) {
144+
return
145+
}
146+
138147
context.report({
139148
node: slotAttr.key,
140149
messageId: 'forbiddenSlotAttribute',

lib/utils/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2462,7 +2462,7 @@ function isAssignmentProperty(node) {
24622462
}
24632463
/**
24642464
* Checks whether the given node is VElement.
2465-
* @param {VElement | VExpressionContainer | VText} node
2465+
* @param {VElement | VExpressionContainer | VText | VDocumentFragment} node
24662466
* @returns {node is VElement}
24672467
*/
24682468
function isVElement(node) {

tests/lib/rules/no-deprecated-slot-attribute.js

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,30 @@ tester.run('no-deprecated-slot-attribute', rule, {
6767
</LinkList>
6868
</template>`,
6969
options: [{ ignore: ['/one/', '/^Two$/i', '/^my-.*/i'] }]
70+
},
71+
{
72+
code: `<template>
73+
<LinkList>
74+
<one slot="one" />
75+
<two slot="two" />
76+
<my-component slot="my-component-slot" />
77+
<myComponent slot="myComponent-slot" />
78+
<MyComponent slot="MyComponent-slot" />
79+
</LinkList>
80+
</template>`,
81+
options: [{ ignoreParents: ['LinkList'] }]
82+
},
83+
{
84+
code: `<template>
85+
<LinkList>
86+
<one slot="one" />
87+
<two slot="two" />
88+
<my-component slot="my-component-slot" />
89+
<myComponent slot="myComponent-slot" />
90+
<MyComponent slot="MyComponent-slot" />
91+
</LinkList>
92+
</template>`,
93+
options: [{ ignoreParents: ['/^Link/'] }]
7094
}
7195
],
7296
invalid: [
@@ -732,6 +756,90 @@ tester.run('no-deprecated-slot-attribute', rule, {
732756
}
733757
]
734758
},
759+
{
760+
code: `
761+
<template>
762+
<my-component>
763+
<one slot="one">
764+
A
765+
</one>
766+
</my-component>
767+
<my-component2>
768+
<two slot="two">
769+
B
770+
</two>
771+
</my-component2>
772+
</template>`,
773+
output: `
774+
<template>
775+
<my-component>
776+
<one slot="one">
777+
A
778+
</one>
779+
</my-component>
780+
<my-component2>
781+
<template v-slot:two>\n<two >
782+
B
783+
</two>\n</template>
784+
</my-component2>
785+
</template>`,
786+
options: [
787+
{
788+
ignoreParents: ['my-component']
789+
}
790+
],
791+
errors: [
792+
{
793+
message: '`slot` attributes are deprecated.',
794+
line: 9,
795+
column: 16,
796+
endLine: 9,
797+
endColumn: 20
798+
}
799+
]
800+
},
801+
{
802+
code: `
803+
<template>
804+
<my-component>
805+
<one slot="one">
806+
A
807+
</one>
808+
</my-component>
809+
<my-component2>
810+
<two slot="two">
811+
B
812+
</two>
813+
</my-component2>
814+
</template>`,
815+
output: `
816+
<template>
817+
<my-component>
818+
<one slot="one">
819+
A
820+
</one>
821+
</my-component>
822+
<my-component2>
823+
<template v-slot:two>\n<two >
824+
B
825+
</two>\n</template>
826+
</my-component2>
827+
</template>`,
828+
options: [
829+
{
830+
ignoreParents: ['/component$/']
831+
}
832+
],
833+
errors: [
834+
{
835+
message: '`slot` attributes are deprecated.',
836+
line: 9,
837+
column: 16,
838+
endLine: 9,
839+
endColumn: 20
840+
}
841+
]
842+
},
735843
{
736844
code: `
737845
<template>

0 commit comments

Comments
 (0)