Skip to content

Commit f8d0757

Browse files
authored
feat(no-multiple-template-root): support disallowComments property (#2685)
1 parent ce92931 commit f8d0757

File tree

3 files changed

+253
-2
lines changed

3 files changed

+253
-2
lines changed

docs/rules/no-multiple-template-root.md

+26-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,32 @@ This rule checks whether template contains single root element valid for Vue 2.
6161

6262
## :wrench: Options
6363

64-
Nothing.
64+
```json
65+
{
66+
"vue/no-multiple-template-root": ["error", {
67+
"disallowComments": false
68+
}]
69+
}
70+
```
71+
72+
- "disallowComments" (`boolean`) Enables there should not be any comments in the template root. Default is `false`.
73+
74+
### "disallowComments": true
75+
76+
<eslint-code-block :rules="{'vue/no-multiple-template-root': ['error', {disallowComments: true}]}">
77+
78+
```vue
79+
/* ✗ BAD */
80+
<template>
81+
<!-- root comment -->
82+
<div>
83+
vue eslint plugin
84+
</div>
85+
<!-- root comment -->
86+
</template>
87+
```
88+
89+
</eslint-code-block>
6590

6691
## :rocket: Version
6792

lib/rules/no-multiple-template-root.js

+41-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,21 @@
66

77
const utils = require('../utils')
88

9+
/**
10+
* Get all comments that need to be reported
11+
* @param {(HTMLComment | HTMLBogusComment | Comment)[]} comments
12+
* @param {Range[]} elementRanges
13+
* @returns {(HTMLComment | HTMLBogusComment | Comment)[]}
14+
*/
15+
function getReportComments(comments, elementRanges) {
16+
return comments.filter(
17+
(comment) =>
18+
!elementRanges.some(
19+
(range) => range[0] <= comment.range[0] && comment.range[1] <= range[1]
20+
)
21+
)
22+
}
23+
924
module.exports = {
1025
meta: {
1126
type: 'problem',
@@ -15,8 +30,19 @@ module.exports = {
1530
url: 'https://eslint.vuejs.org/rules/no-multiple-template-root.html'
1631
},
1732
fixable: null,
18-
schema: [],
33+
schema: [
34+
{
35+
type: 'object',
36+
properties: {
37+
disallowComments: {
38+
type: 'boolean'
39+
}
40+
},
41+
additionalProperties: false
42+
}
43+
],
1944
messages: {
45+
commentRoot: 'The template root disallows comments.',
2046
multipleRoot: 'The template root requires exactly one element.',
2147
textRoot: 'The template root requires an element rather than texts.',
2248
disallowedElement: "The template root disallows '<{{name}}>' elements.",
@@ -28,6 +54,8 @@ module.exports = {
2854
* @returns {RuleListener} AST event handlers.
2955
*/
3056
create(context) {
57+
const options = context.options[0] || {}
58+
const disallowComments = options.disallowComments
3159
const sourceCode = context.getSourceCode()
3260

3361
return {
@@ -37,6 +65,18 @@ module.exports = {
3765
return
3866
}
3967

68+
const comments = element.comments
69+
const elementRanges = element.children.map((child) => child.range)
70+
if (disallowComments && comments.length > 0) {
71+
for (const comment of getReportComments(comments, elementRanges)) {
72+
context.report({
73+
node: comment,
74+
loc: comment.loc,
75+
messageId: 'commentRoot'
76+
})
77+
}
78+
}
79+
4080
const rootElements = []
4181
let extraText = null
4282
let extraElement = null

tests/lib/rules/no-multiple-template-root.js

+186
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,66 @@ ruleTester.run('no-multiple-template-root', rule, {
6262
</Link>
6363
</template>
6464
`
65+
},
66+
{
67+
filename: 'test.vue',
68+
code: `
69+
<template>
70+
<!-- comments -->
71+
<div>12333</div>
72+
<!-- comments -->
73+
</template>
74+
`,
75+
options: [{ disallowComments: false }]
76+
},
77+
{
78+
filename: 'test.vue',
79+
code: `
80+
<template>
81+
<!-- comments -->
82+
<div>
83+
<!-- comments -->
84+
12333
85+
</div>
86+
</template>
87+
`,
88+
options: [{ disallowComments: false }]
89+
},
90+
{
91+
filename: 'test.vue',
92+
code: `
93+
<template>
94+
<div>
95+
<!-- comments -->
96+
12333
97+
<span>
98+
<!-- comments -->
99+
12333
100+
</span>
101+
</div>
102+
</template>
103+
`,
104+
options: [{ disallowComments: true }]
105+
},
106+
{
107+
filename: 'test.vue',
108+
code: `
109+
<template>
110+
<div v-if="for">
111+
<!-- comments -->
112+
12333
113+
<span>
114+
<!-- comments -->
115+
12333
116+
</span>
117+
</div>
118+
<div v-else>
119+
<!-- comments -->
120+
12333
121+
</div>
122+
</template>
123+
`,
124+
options: [{ disallowComments: true }]
65125
}
66126
],
67127
invalid: [
@@ -104,6 +164,132 @@ ruleTester.run('no-multiple-template-root', rule, {
104164
filename: 'test.vue',
105165
code: '<template><template></template></template>',
106166
errors: ["The template root disallows '<template>' elements."]
167+
},
168+
{
169+
code: `
170+
<template>
171+
<!-- comments -->
172+
<div>12333</div>
173+
<!-- comments -->
174+
</template>
175+
`,
176+
options: [{ disallowComments: true }],
177+
errors: [
178+
{
179+
message: 'The template root disallows comments.',
180+
line: 3
181+
},
182+
{
183+
message: 'The template root disallows comments.',
184+
line: 5
185+
}
186+
]
187+
},
188+
{
189+
code: `
190+
<template>
191+
<!-- comments -->
192+
<div>
193+
12333
194+
<!-- comments -->
195+
</div>
196+
</template>
197+
`,
198+
options: [{ disallowComments: true }],
199+
errors: [
200+
{
201+
message: 'The template root disallows comments.',
202+
line: 3
203+
}
204+
]
205+
},
206+
{
207+
code: `
208+
<template>
209+
<!-- comments -->
210+
<div v-if="for">
211+
<!-- comments -->
212+
12333
213+
<span>
214+
<!-- comments -->
215+
12333
216+
</span>
217+
</div>
218+
<!-- comments -->
219+
<div v-else>
220+
<!-- comments -->
221+
12333
222+
</div>
223+
<!-- comments -->
224+
</template>
225+
`,
226+
options: [{ disallowComments: true }],
227+
errors: [
228+
{
229+
message: 'The template root disallows comments.',
230+
line: 3
231+
},
232+
{
233+
message: 'The template root disallows comments.',
234+
line: 12
235+
},
236+
{
237+
message: 'The template root disallows comments.',
238+
line: 17
239+
}
240+
]
241+
},
242+
{
243+
code: `
244+
<template>
245+
<div>
246+
12333
247+
<!-- comments -->
248+
</div>
249+
<!-- comments -->
250+
</template>
251+
`,
252+
options: [{ disallowComments: true }],
253+
errors: [
254+
{
255+
message: 'The template root disallows comments.',
256+
line: 7
257+
}
258+
]
259+
},
260+
{
261+
code: `
262+
<template>
263+
<div />
264+
<!-- comments -->
265+
<div />
266+
</template>
267+
`,
268+
options: [{ disallowComments: true }],
269+
errors: [
270+
{
271+
message: 'The template root disallows comments.',
272+
line: 4
273+
},
274+
{
275+
message: 'The template root requires exactly one element.',
276+
line: 5
277+
}
278+
]
279+
},
280+
{
281+
code: `
282+
<template>
283+
<!-- When you have a comment in the root of your template in vue 3,
284+
using $el will point to the first text comment instead of the actual DOM element. -->
285+
<div>
286+
12333
287+
<!-- comments -->
288+
</div>
289+
</template>
290+
`,
291+
options: [{ disallowComments: true }],
292+
errors: ['The template root disallows comments.']
107293
}
108294
]
109295
})

0 commit comments

Comments
 (0)