Skip to content

Commit 545af71

Browse files
committed
feat(require-toggle-inside-transition): add additionalDirectives option (#2535)
1 parent 0fbe35e commit 545af71

File tree

3 files changed

+118
-5
lines changed

3 files changed

+118
-5
lines changed

docs/rules/require-toggle-inside-transition.md

+36-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,42 @@ This rule reports elements inside `<transition>` that do not control the display
3333

3434
## :wrench: Options
3535

36-
Nothing.
36+
```json
37+
{
38+
"vue/require-toggle-inside-transition": ["error", {
39+
"additionalDirectives": []
40+
}]
41+
}
42+
```
43+
44+
- `additionalDirectives` (`string[]`) ... Custom directives which will satisfy this rule in addition to `v-show` and `v-if`. Should be added without the `v-` prefix.
45+
46+
### `additionalDirectives: ["dialog"]`
47+
48+
<eslint-code-block :rules="{'vue/require-toggle-inside-transition': ['error', {additionalDirectives: ['dialog']}]}">
49+
50+
```vue
51+
<template>
52+
<!-- ✓ GOOD -->
53+
<transition><div v-if="show" /></transition>
54+
<transition><div v-show="show" /></transition>
55+
<transition><dialog v-dialog="show" /></transition>
56+
<template>
57+
```
58+
59+
</eslint-code-block>
60+
61+
<eslint-code-block :rules="{'vue/require-toggle-inside-transition': ['error', {additionalDirectives: ['dialog']}]}">
62+
63+
```vue
64+
<template>
65+
<!-- ✗ BAD -->
66+
<transition><div /></transition>
67+
<transition><div v-custom="show" /></transition>
68+
<template>
69+
```
70+
71+
</eslint-code-block>
3772

3873
## :books: Further Reading
3974

lib/rules/require-toggle-inside-transition.js

+53-4
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,25 @@ function isValidBindAppear(vBindAppear) {
2020
return true
2121
}
2222

23+
/**
24+
* @param {string[]} directives
25+
*/
26+
function createDirectiveList(directives) {
27+
let str = ''
28+
29+
for (const [index, directive] of directives.entries()) {
30+
if (index === directives.length - 1) {
31+
str += ` or \`v-${directive}\``
32+
} else if (index === 0) {
33+
str += ` \`v-${directive}\``
34+
} else {
35+
str += `, \`v-${directive}\``
36+
}
37+
}
38+
39+
return str
40+
}
41+
2342
module.exports = {
2443
meta: {
2544
type: 'problem',
@@ -30,14 +49,38 @@ module.exports = {
3049
url: 'https://eslint.vuejs.org/rules/require-toggle-inside-transition.html'
3150
},
3251
fixable: null,
33-
schema: [],
52+
schema: [
53+
{
54+
type: 'object',
55+
properties: {
56+
additionalDirectives: {
57+
type: 'array',
58+
items: {
59+
type: 'string'
60+
},
61+
uniqueItems: true
62+
}
63+
},
64+
additionalProperties: false
65+
}
66+
],
3467
messages: {
3568
expected:
36-
'The element inside `<transition>` is expected to have a `v-if` or `v-show` directive.'
69+
'The element inside `<transition>` is expected to have a {{allowedDirectives}} directive.'
3770
}
3871
},
3972
/** @param {RuleContext} context */
4073
create(context) {
74+
/** @type {Array<string>} */
75+
const additionalDirectives =
76+
(context.options[0] && context.options[0].additionalDirectives) || []
77+
78+
const allowedDirectivesString = createDirectiveList([
79+
'if',
80+
'show',
81+
...additionalDirectives
82+
])
83+
4184
/**
4285
* Check if the given element has display control.
4386
* @param {VElement} element The element node to check.
@@ -61,12 +104,18 @@ module.exports = {
61104
element.name !== 'slot' &&
62105
!utils.hasDirective(element, 'if') &&
63106
!utils.hasDirective(element, 'show') &&
64-
!utils.hasDirective(element, 'bind', 'key')
107+
!utils.hasDirective(element, 'bind', 'key') &&
108+
!additionalDirectives.some((directive) =>
109+
utils.hasDirective(element, directive)
110+
)
65111
) {
66112
context.report({
67113
node: element.startTag,
68114
loc: element.startTag.loc,
69-
messageId: 'expected'
115+
messageId: 'expected',
116+
data: {
117+
allowedDirectives: allowedDirectivesString
118+
}
70119
})
71120
}
72121
}

tests/lib/rules/require-toggle-inside-transition.js

+29
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,15 @@ tester.run('require-toggle-inside-transition', rule, {
7777
{
7878
filename: 'test.vue',
7979
code: '<template><transition :appear="true"><div /></transition></template>'
80+
},
81+
{
82+
filename: 'test.vue',
83+
code: '<template><transition><dialog v-dialog="show" /></transition></template>',
84+
options: [
85+
{
86+
additionalDirectives: ['dialog']
87+
}
88+
]
8089
}
8190
],
8291
invalid: [
@@ -132,6 +141,26 @@ tester.run('require-toggle-inside-transition', rule, {
132141
filename: 'test.vue',
133142
code: '<template><transition @appear="isLoaded"><div /></transition></template>',
134143
errors: [{ messageId: 'expected' }]
144+
},
145+
{
146+
filename: 'test.vue',
147+
code: '<template><transition><dialog v-dialog="show" /></transition></template>',
148+
options: [
149+
{
150+
additionalDirectives: []
151+
}
152+
],
153+
errors: [{ messageId: 'expected' }]
154+
},
155+
{
156+
filename: 'test.vue',
157+
code: '<template><transition><div v-custom="show" /></transition></template>',
158+
options: [
159+
{
160+
additionalDirectives: ['dialog']
161+
}
162+
],
163+
errors: [{ messageId: 'expected' }]
135164
}
136165
]
137166
})

0 commit comments

Comments
 (0)