From 038da916c3fb7075f478b2bd37228227dfffb115 Mon Sep 17 00:00:00 2001
From: chouchouji <1305974212@qq.com>
Date: Fri, 14 Feb 2025 22:33:20 +0800
Subject: [PATCH 1/6] feat(no-multiple-template-root): support disallowComments
property
---
lib/rules/no-multiple-template-root.js | 45 +++++++++++-
tests/lib/rules/no-multiple-template-root.js | 76 ++++++++++++++++++++
2 files changed, 120 insertions(+), 1 deletion(-)
diff --git a/lib/rules/no-multiple-template-root.js b/lib/rules/no-multiple-template-root.js
index 45c22389f..7d89c696f 100644
--- a/lib/rules/no-multiple-template-root.js
+++ b/lib/rules/no-multiple-template-root.js
@@ -15,8 +15,19 @@ module.exports = {
url: 'https://eslint.vuejs.org/rules/no-multiple-template-root.html'
},
fixable: null,
- schema: [],
+ schema: [
+ {
+ type: 'object',
+ properties: {
+ disallowComments: {
+ type: 'boolean'
+ }
+ },
+ additionalProperties: false
+ }
+ ],
messages: {
+ commentRoot: 'The template root disallows comments.',
multipleRoot: 'The template root requires exactly one element.',
textRoot: 'The template root requires an element rather than texts.',
disallowedElement: "The template root disallows '<{{name}}>' elements.",
@@ -28,6 +39,8 @@ module.exports = {
* @returns {RuleListener} AST event handlers.
*/
create(context) {
+ const options = context.options[0] || {}
+ const disallowComments = options.disallowComments
const sourceCode = context.getSourceCode()
return {
@@ -37,6 +50,36 @@ module.exports = {
return
}
+ const commentRangesMap = new Map()
+ const comments = element.comments
+ if (disallowComments && comments.length > 0) {
+ for (const comment of comments) {
+ const [start, end] = comment.range
+ commentRangesMap.set(`${start}-${end}`, comment)
+ }
+
+ for (const child of element.children) {
+ if (child.type === 'VElement') {
+ for (const range of commentRangesMap.keys()) {
+ const ranges = range.split('-')
+ if (ranges[0] > child.range[0] && ranges[1] < child.range[1]) {
+ commentRangesMap.delete(range)
+ }
+ }
+ }
+ }
+
+ if (commentRangesMap.size > 0) {
+ for (const node of commentRangesMap.values()) {
+ context.report({
+ node,
+ loc: node.loc,
+ messageId: 'commentRoot'
+ })
+ }
+ }
+ }
+
const rootElements = []
let extraText = null
let extraElement = null
diff --git a/tests/lib/rules/no-multiple-template-root.js b/tests/lib/rules/no-multiple-template-root.js
index 7ab80af7e..c452ebe45 100644
--- a/tests/lib/rules/no-multiple-template-root.js
+++ b/tests/lib/rules/no-multiple-template-root.js
@@ -62,6 +62,30 @@ ruleTester.run('no-multiple-template-root', rule, {
`
+ },
+ {
+ filename: 'test.vue',
+ code: `
+
+
+ 12333
+
+
+ `,
+ options: [{ disallowComments: false }]
+ },
+ {
+ filename: 'test.vue',
+ code: `
+
+
+
+
+ 12333
+
+
+ `,
+ options: [{ disallowComments: false }]
}
],
invalid: [
@@ -104,6 +128,58 @@ ruleTester.run('no-multiple-template-root', rule, {
filename: 'test.vue',
code: '',
errors: ["The template root disallows '' elements."]
+ },
+ {
+ code: `
+
+
+ 12333
+
+
+ `,
+ options: [{ disallowComments: true }],
+ errors: [
+ {
+ message: 'The template root disallows comments.',
+ line: 3
+ },
+ {
+ message: 'The template root disallows comments.',
+ line: 5
+ }
+ ]
+ },
+ {
+ code: `
+
+
+
+ 12333
+
+
+
+ `,
+ options: [{ disallowComments: true }],
+ errors: [
+ {
+ message: 'The template root disallows comments.',
+ line: 3
+ }
+ ]
+ },
+ {
+ code: `
+
+
+
+ 12333
+
+
+
+ `,
+ options: [{ disallowComments: true }],
+ errors: ['The template root disallows comments.']
}
]
})
From 5601d918d88df53737d49050e3dc9155ef52b0d7 Mon Sep 17 00:00:00 2001
From: chouchouji <1305974212@qq.com>
Date: Sat, 15 Feb 2025 14:13:49 +0800
Subject: [PATCH 2/6] refactor(no-multiple-template-root): optimize code
---
lib/rules/no-multiple-template-root.js | 59 ++++++++++++++------
tests/lib/rules/no-multiple-template-root.js | 36 ++++++++++++
2 files changed, 78 insertions(+), 17 deletions(-)
diff --git a/lib/rules/no-multiple-template-root.js b/lib/rules/no-multiple-template-root.js
index 7d89c696f..e25f0b94f 100644
--- a/lib/rules/no-multiple-template-root.js
+++ b/lib/rules/no-multiple-template-root.js
@@ -50,30 +50,55 @@ module.exports = {
return
}
- const commentRangesMap = new Map()
const comments = element.comments
if (disallowComments && comments.length > 0) {
- for (const comment of comments) {
- const [start, end] = comment.range
- commentRangesMap.set(`${start}-${end}`, comment)
- }
+ const commentRanges = comments.map((comment) => comment.range)
+ const elementRanges = element.children
+ .filter((child) => child.type === 'VElement')
+ .map((child) => child.range)
+
+ let commentIndex = 0
+ let elementIndex = 0
+
+ const needReportComments = elementRanges.length === 0 ? comments : []
+ while (
+ commentIndex < commentRanges.length &&
+ elementRanges.length > 0
+ ) {
+ const [commentStart, commentEnd] = commentRanges[commentIndex]
+ const [elementStart, elementEnd] = elementRanges[elementIndex]
+ if (commentStart > elementStart && commentEnd < elementEnd) {
+ commentIndex += 1
+ continue
+ }
+
+ if (commentEnd < elementStart) {
+ needReportComments.push(comments[commentIndex])
+ commentIndex += 1
+ }
+
+ // the element array has no any element, but comment still has some elements
+ if (
+ elementIndex === elementRanges.length - 1 &&
+ commentStart > elementEnd
+ ) {
+ needReportComments.push(comments[commentIndex])
+ commentIndex += 1
+ }
- for (const child of element.children) {
- if (child.type === 'VElement') {
- for (const range of commentRangesMap.keys()) {
- const ranges = range.split('-')
- if (ranges[0] > child.range[0] && ranges[1] < child.range[1]) {
- commentRangesMap.delete(range)
- }
- }
+ if (
+ elementIndex < elementRanges.length - 1 &&
+ commentStart > elementEnd
+ ) {
+ elementIndex += 1
}
}
- if (commentRangesMap.size > 0) {
- for (const node of commentRangesMap.values()) {
+ if (needReportComments.length > 0) {
+ for (const comment of needReportComments) {
context.report({
- node,
- loc: node.loc,
+ node: comment,
+ loc: comment.loc,
messageId: 'commentRoot'
})
}
diff --git a/tests/lib/rules/no-multiple-template-root.js b/tests/lib/rules/no-multiple-template-root.js
index c452ebe45..517fdeccd 100644
--- a/tests/lib/rules/no-multiple-template-root.js
+++ b/tests/lib/rules/no-multiple-template-root.js
@@ -86,6 +86,42 @@ ruleTester.run('no-multiple-template-root', rule, {
`,
options: [{ disallowComments: false }]
+ },
+ {
+ filename: 'test.vue',
+ code: `
+
+
+
+ 12333
+
+
+ 12333
+
+
+
+ `,
+ options: [{ disallowComments: true }]
+ },
+ {
+ filename: 'test.vue',
+ code: `
+
+
+
+ 12333
+
+
+ 12333
+
+
+
+
+ 12333
+
+
+ `,
+ options: [{ disallowComments: true }]
}
],
invalid: [
From f802a5fc4fa40a27f7fc321a696179e20337fd13 Mon Sep 17 00:00:00 2001
From: chouchouji <1305974212@qq.com>
Date: Sat, 15 Feb 2025 15:58:35 +0800
Subject: [PATCH 3/6] refactor(no-multiple-template-root): optimize code
---
lib/rules/no-multiple-template-root.js | 95 +++++++++++---------
tests/lib/rules/no-multiple-template-root.js | 54 +++++++++++
2 files changed, 107 insertions(+), 42 deletions(-)
diff --git a/lib/rules/no-multiple-template-root.js b/lib/rules/no-multiple-template-root.js
index e25f0b94f..1d728b1f5 100644
--- a/lib/rules/no-multiple-template-root.js
+++ b/lib/rules/no-multiple-template-root.js
@@ -6,6 +6,58 @@
const utils = require('../utils')
+/**
+ * Get all comments that need to be reported
+ * @param {(HTMLComment | HTMLBogusComment | Comment)[]} comments
+ * @param {VRootElement} element
+ * @returns {(HTMLComment | HTMLBogusComment | Comment)[]}
+ */
+function getReportComments(comments, element) {
+ const commentRanges = comments.map((comment) => comment.range)
+ const elementRanges = element.children
+ .filter((child) => child.type === 'VElement')
+ .map((child) => child.range)
+
+ // should return comment directly when no any elements
+ if (elementRanges.length === 0) {
+ return comments
+ }
+
+ let commentIndex = 0
+ let elementIndex = 0
+
+ const needReportComments = []
+ while (commentIndex < commentRanges.length) {
+ const [commentStart, commentEnd] = commentRanges[commentIndex]
+ const [elementStart, elementEnd] = elementRanges[elementIndex]
+ // if the comment is in the range of element, should skip
+ if (commentStart > elementStart && commentEnd < elementEnd) {
+ commentIndex += 1
+ continue
+ }
+
+ if (commentEnd < elementStart) {
+ needReportComments.push(comments[commentIndex])
+ commentIndex += 1
+ }
+
+ // the element array has no any element, but comment still has some elements
+ if (
+ elementIndex === elementRanges.length - 1 &&
+ commentStart > elementEnd
+ ) {
+ needReportComments.push(comments[commentIndex])
+ commentIndex += 1
+ }
+
+ if (elementIndex < elementRanges.length - 1 && commentStart > elementEnd) {
+ elementIndex += 1
+ }
+ }
+
+ return needReportComments
+}
+
module.exports = {
meta: {
type: 'problem',
@@ -52,48 +104,7 @@ module.exports = {
const comments = element.comments
if (disallowComments && comments.length > 0) {
- const commentRanges = comments.map((comment) => comment.range)
- const elementRanges = element.children
- .filter((child) => child.type === 'VElement')
- .map((child) => child.range)
-
- let commentIndex = 0
- let elementIndex = 0
-
- const needReportComments = elementRanges.length === 0 ? comments : []
- while (
- commentIndex < commentRanges.length &&
- elementRanges.length > 0
- ) {
- const [commentStart, commentEnd] = commentRanges[commentIndex]
- const [elementStart, elementEnd] = elementRanges[elementIndex]
- if (commentStart > elementStart && commentEnd < elementEnd) {
- commentIndex += 1
- continue
- }
-
- if (commentEnd < elementStart) {
- needReportComments.push(comments[commentIndex])
- commentIndex += 1
- }
-
- // the element array has no any element, but comment still has some elements
- if (
- elementIndex === elementRanges.length - 1 &&
- commentStart > elementEnd
- ) {
- needReportComments.push(comments[commentIndex])
- commentIndex += 1
- }
-
- if (
- elementIndex < elementRanges.length - 1 &&
- commentStart > elementEnd
- ) {
- elementIndex += 1
- }
- }
-
+ const needReportComments = getReportComments(comments, element)
if (needReportComments.length > 0) {
for (const comment of needReportComments) {
context.report({
diff --git a/tests/lib/rules/no-multiple-template-root.js b/tests/lib/rules/no-multiple-template-root.js
index 517fdeccd..0bc425e93 100644
--- a/tests/lib/rules/no-multiple-template-root.js
+++ b/tests/lib/rules/no-multiple-template-root.js
@@ -203,6 +203,60 @@ ruleTester.run('no-multiple-template-root', rule, {
}
]
},
+ {
+ code: `
+
+
+
+
+ 12333
+
+
+ 12333
+
+
+
+
+
+ 12333
+
+
+
+ `,
+ options: [{ disallowComments: true }],
+ errors: [
+ {
+ message: 'The template root disallows comments.',
+ line: 3
+ },
+ {
+ message: 'The template root disallows comments.',
+ line: 12
+ },
+ {
+ message: 'The template root disallows comments.',
+ line: 17
+ }
+ ]
+ },
+ {
+ code: `
+
+
+ 12333
+
+
+
+
+ `,
+ options: [{ disallowComments: true }],
+ errors: [
+ {
+ message: 'The template root disallows comments.',
+ line: 7
+ }
+ ]
+ },
{
code: `
From b33de2808c1ff616b095ec986bc45e74af6fddad Mon Sep 17 00:00:00 2001
From: chouchouji <70570907+chouchouji@users.noreply.github.com>
Date: Wed, 5 Mar 2025 06:47:17 +0000
Subject: [PATCH 4/6] docs(no-multiple-template-root): update docs
---
docs/rules/no-multiple-template-root.md | 27 ++++++++++++++++++++++++-
1 file changed, 26 insertions(+), 1 deletion(-)
diff --git a/docs/rules/no-multiple-template-root.md b/docs/rules/no-multiple-template-root.md
index 90b5488fc..8a85c9201 100644
--- a/docs/rules/no-multiple-template-root.md
+++ b/docs/rules/no-multiple-template-root.md
@@ -61,7 +61,32 @@ This rule checks whether template contains single root element valid for Vue 2.
## :wrench: Options
-Nothing.
+```json
+{
+ "vue/no-multiple-template-root": ["error", {
+ "disallowComments": false
+ }]
+}
+```
+
+- "disallowComments" (`boolean`) Enables there should not be any comments in the template root. Default is `false`.
+
+### "disallowComments": true
+
+
+
+```vue
+/* ✗ BAD */
+
+
+
+ vue eslint plugin
+
+
+
+```
+
+
## :rocket: Version
From 0d774c76ee04757b428bcd1ac7fe63724b8919cc Mon Sep 17 00:00:00 2001
From: chouchouji <70570907+chouchouji@users.noreply.github.com>
Date: Wed, 5 Mar 2025 08:22:30 +0000
Subject: [PATCH 5/6] refactor(no-multiple-template-root): optimize code
---
lib/rules/no-multiple-template-root.js | 69 +++++---------------
tests/lib/rules/no-multiple-template-root.js | 20 ++++++
2 files changed, 35 insertions(+), 54 deletions(-)
diff --git a/lib/rules/no-multiple-template-root.js b/lib/rules/no-multiple-template-root.js
index 1d728b1f5..84610eb5f 100644
--- a/lib/rules/no-multiple-template-root.js
+++ b/lib/rules/no-multiple-template-root.js
@@ -9,53 +9,16 @@ const utils = require('../utils')
/**
* Get all comments that need to be reported
* @param {(HTMLComment | HTMLBogusComment | Comment)[]} comments
- * @param {VRootElement} element
+ * @param {Range[]} elementRanges
* @returns {(HTMLComment | HTMLBogusComment | Comment)[]}
*/
-function getReportComments(comments, element) {
- const commentRanges = comments.map((comment) => comment.range)
- const elementRanges = element.children
- .filter((child) => child.type === 'VElement')
- .map((child) => child.range)
-
- // should return comment directly when no any elements
- if (elementRanges.length === 0) {
- return comments
- }
-
- let commentIndex = 0
- let elementIndex = 0
-
- const needReportComments = []
- while (commentIndex < commentRanges.length) {
- const [commentStart, commentEnd] = commentRanges[commentIndex]
- const [elementStart, elementEnd] = elementRanges[elementIndex]
- // if the comment is in the range of element, should skip
- if (commentStart > elementStart && commentEnd < elementEnd) {
- commentIndex += 1
- continue
- }
-
- if (commentEnd < elementStart) {
- needReportComments.push(comments[commentIndex])
- commentIndex += 1
- }
-
- // the element array has no any element, but comment still has some elements
- if (
- elementIndex === elementRanges.length - 1 &&
- commentStart > elementEnd
- ) {
- needReportComments.push(comments[commentIndex])
- commentIndex += 1
- }
-
- if (elementIndex < elementRanges.length - 1 && commentStart > elementEnd) {
- elementIndex += 1
- }
- }
-
- return needReportComments
+function getReportComments(comments, elementRanges) {
+ return comments.filter(
+ (comment) =>
+ !elementRanges.some(
+ (range) => range[0] <= comment.range[0] && comment.range[1] <= range[1]
+ )
+ )
}
module.exports = {
@@ -103,16 +66,14 @@ module.exports = {
}
const comments = element.comments
+ const elementRanges = element.children.map((child) => child.range)
if (disallowComments && comments.length > 0) {
- const needReportComments = getReportComments(comments, element)
- if (needReportComments.length > 0) {
- for (const comment of needReportComments) {
- context.report({
- node: comment,
- loc: comment.loc,
- messageId: 'commentRoot'
- })
- }
+ for (const comment of getReportComments(comments, elementRanges)) {
+ context.report({
+ node: comment,
+ loc: comment.loc,
+ messageId: 'commentRoot'
+ })
}
}
diff --git a/tests/lib/rules/no-multiple-template-root.js b/tests/lib/rules/no-multiple-template-root.js
index 0bc425e93..c52c1c202 100644
--- a/tests/lib/rules/no-multiple-template-root.js
+++ b/tests/lib/rules/no-multiple-template-root.js
@@ -257,6 +257,26 @@ ruleTester.run('no-multiple-template-root', rule, {
}
]
},
+ {
+ code: `
+
+
+
+
+
+ `,
+ options: [{ disallowComments: true }],
+ errors: [
+ {
+ message: 'The template root disallows comments.',
+ line: 4
+ },
+ {
+ message: 'The template root requires exactly one element.',
+ line: 5
+ }
+ ]
+ },
{
code: `
From 7dcd6833cdccfc818f050671fc39c909d3fada32 Mon Sep 17 00:00:00 2001
From: chouchouji <70570907+chouchouji@users.noreply.github.com>
Date: Wed, 5 Mar 2025 08:24:55 +0000
Subject: [PATCH 6/6] style: format code
---
lib/rules/no-multiple-template-root.js | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/lib/rules/no-multiple-template-root.js b/lib/rules/no-multiple-template-root.js
index 84610eb5f..524b7a2b1 100644
--- a/lib/rules/no-multiple-template-root.js
+++ b/lib/rules/no-multiple-template-root.js
@@ -13,12 +13,12 @@ const utils = require('../utils')
* @returns {(HTMLComment | HTMLBogusComment | Comment)[]}
*/
function getReportComments(comments, elementRanges) {
- return comments.filter(
- (comment) =>
- !elementRanges.some(
- (range) => range[0] <= comment.range[0] && comment.range[1] <= range[1]
- )
- )
+ return comments.filter(
+ (comment) =>
+ !elementRanges.some(
+ (range) => range[0] <= comment.range[0] && comment.range[1] <= range[1]
+ )
+ )
}
module.exports = {