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 diff --git a/lib/rules/no-multiple-template-root.js b/lib/rules/no-multiple-template-root.js index 45c22389f..524b7a2b1 100644 --- a/lib/rules/no-multiple-template-root.js +++ b/lib/rules/no-multiple-template-root.js @@ -6,6 +6,21 @@ const utils = require('../utils') +/** + * Get all comments that need to be reported + * @param {(HTMLComment | HTMLBogusComment | Comment)[]} comments + * @param {Range[]} elementRanges + * @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] + ) + ) +} + module.exports = { meta: { type: 'problem', @@ -15,8 +30,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 +54,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 +65,18 @@ module.exports = { return } + const comments = element.comments + const elementRanges = element.children.map((child) => child.range) + if (disallowComments && comments.length > 0) { + for (const comment of getReportComments(comments, elementRanges)) { + context.report({ + node: comment, + loc: comment.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..c52c1c202 100644 --- a/tests/lib/rules/no-multiple-template-root.js +++ b/tests/lib/rules/no-multiple-template-root.js @@ -62,6 +62,66 @@ ruleTester.run('no-multiple-template-root', rule, { ` + }, + { + filename: 'test.vue', + code: ` + + + 12333 + + + `, + options: [{ disallowComments: false }] + }, + { + filename: 'test.vue', + code: ` + + + + + 12333 + + + `, + options: [{ disallowComments: false }] + }, + { + filename: 'test.vue', + code: ` + + + + 12333 + + + 12333 + + + + `, + options: [{ disallowComments: true }] + }, + { + filename: 'test.vue', + code: ` + + + + 12333 + + + 12333 + + + + + 12333 + + + `, + options: [{ disallowComments: true }] } ], invalid: [ @@ -104,6 +164,132 @@ 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 + + + 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: ` + + + + + + `, + options: [{ disallowComments: true }], + errors: [ + { + message: 'The template root disallows comments.', + line: 4 + }, + { + message: 'The template root requires exactly one element.', + line: 5 + } + ] + }, + { + code: ` + + + + 12333 + + + + `, + options: [{ disallowComments: true }], + errors: ['The template root disallows comments.'] } ] })