diff --git a/docs/rules/no-v-text-v-html-on-component.md b/docs/rules/no-v-text-v-html-on-component.md
index 8e504d859..7d75eb9c9 100644
--- a/docs/rules/no-v-text-v-html-on-component.md
+++ b/docs/rules/no-v-text-v-html-on-component.md
@@ -25,11 +25,15 @@ If you use v-text / v-html on a component, it will overwrite the component's con
+
+
{{ content }}
+
+
```
@@ -39,14 +43,15 @@ If you use v-text / v-html on a component, it will overwrite the component's con
```json
{
- "vue/no-v-text-v-html-on-component": [
- "error",
- { "allow": ["router-link", "nuxt-link"] }
- ]
+ "vue/no-v-text-v-html-on-component": ["error", {
+ "allow": ["router-link", "nuxt-link"],
+ "ignoreElementNamespaces": false
+ }]
}
```
- `allow` (`string[]`) ... Specify a list of custom components for which the rule should not apply.
+- `ignoreElementNamespaces` (`boolean`) ... If `true`, always treat SVG and MathML tag names as HTML elements, even if they are not used inside a SVG/MathML root element. Default is `false`.
### `{ "allow": ["router-link", "nuxt-link"] }`
@@ -65,6 +70,20 @@ If you use v-text / v-html on a component, it will overwrite the component's con
+### `{ "ignoreElementNamespaces": true }`
+
+
+
+```vue
+
+
+
+
+
+```
+
+
+
## :rocket: Version
This rule was introduced in eslint-plugin-vue v8.4.0
diff --git a/lib/rules/no-v-text-v-html-on-component.js b/lib/rules/no-v-text-v-html-on-component.js
index 50ef9c76e..e3f1f5409 100644
--- a/lib/rules/no-v-text-v-html-on-component.js
+++ b/lib/rules/no-v-text-v-html-on-component.js
@@ -26,6 +26,9 @@ module.exports = {
type: 'string'
},
uniqueItems: true
+ },
+ ignoreElementNamespaces: {
+ type: 'boolean'
}
},
additionalProperties: false
@@ -41,6 +44,8 @@ module.exports = {
const options = context.options[0] || {}
/** @type {Set} */
const allow = new Set(options.allow)
+ /** @type {boolean} */
+ const ignoreElementNamespaces = options.ignoreElementNamespaces === true
/**
* Check whether the given node is an allowed component or not.
@@ -62,7 +67,10 @@ module.exports = {
*/
function verify(node) {
const element = node.parent.parent
- if (utils.isCustomComponent(element) && !isAllowedComponent(element)) {
+ if (
+ utils.isCustomComponent(element, ignoreElementNamespaces) &&
+ !isAllowedComponent(element)
+ ) {
context.report({
node,
loc: node.loc,
diff --git a/lib/utils/index.js b/lib/utils/index.js
index 58cd32689..eb84c1279 100644
--- a/lib/utils/index.js
+++ b/lib/utils/index.js
@@ -941,19 +941,30 @@ module.exports = {
/**
* Check whether the given node is a custom component or not.
* @param {VElement} node The start tag node to check.
+ * @param {boolean} [ignoreElementNamespaces=false] If `true`, ignore element namespaces.
* @returns {boolean} `true` if the node is a custom component.
*/
- isCustomComponent(node) {
- return (
- (this.isHtmlElementNode(node) &&
- !this.isHtmlWellKnownElementName(node.rawName)) ||
- (this.isSvgElementNode(node) &&
- !this.isSvgWellKnownElementName(node.rawName)) ||
- (this.isMathElementNode(node) &&
- !this.isMathWellKnownElementName(node.rawName)) ||
+ isCustomComponent(node, ignoreElementNamespaces = false) {
+ if (
hasAttribute(node, 'is') ||
hasDirective(node, 'bind', 'is') ||
hasDirective(node, 'is')
+ ) {
+ return true
+ }
+
+ const isHtmlName = this.isHtmlWellKnownElementName(node.rawName)
+ const isSvgName = this.isSvgWellKnownElementName(node.rawName)
+ const isMathName = this.isMathWellKnownElementName(node.rawName)
+
+ if (ignoreElementNamespaces) {
+ return !isHtmlName && !isSvgName && !isMathName
+ }
+
+ return (
+ (this.isHtmlElementNode(node) && !isHtmlName) ||
+ (this.isSvgElementNode(node) && !isSvgName) ||
+ (this.isMathElementNode(node) && !isMathName)
)
},
diff --git a/tests/lib/rules/no-v-text-v-html-on-component.js b/tests/lib/rules/no-v-text-v-html-on-component.js
index ebf2901ba..bb403489e 100644
--- a/tests/lib/rules/no-v-text-v-html-on-component.js
+++ b/tests/lib/rules/no-v-text-v-html-on-component.js
@@ -59,6 +59,26 @@ tester.run('no-v-text-v-html-on-component', rule, {
`,
options: [{ allow: ['RouterLink', 'nuxt-link'] }]
+ },
+ {
+ filename: 'test.vue',
+ code: `
+
+
+
+
+ `
+ },
+ {
+ filename: 'test.vue',
+ code: `
+
+
+
+
+
+ `,
+ options: [{ ignoreElementNamespaces: true }]
}
],
invalid: [
@@ -167,6 +187,28 @@ tester.run('no-v-text-v-html-on-component', rule, {
column: 22
}
]
+ },
+ {
+ filename: 'test.vue',
+ code: `
+
+
+
+
+ `,
+ options: [{ ignoreElementNamespaces: false }],
+ errors: [
+ {
+ message: "Using v-text on component may break component's content.",
+ line: 3,
+ column: 12
+ },
+ {
+ message: "Using v-text on component may break component's content.",
+ line: 4,
+ column: 13
+ }
+ ]
}
]
})