Skip to content

Commit 0ac61d9

Browse files
waynzhFloEdelmann
andauthored
feat(no-v-text-v-html-on-component): add allow option (#2339)
Co-authored-by: Flo Edelmann <git@flo-edelmann.de>
1 parent 05b1286 commit 0ac61d9

File tree

3 files changed

+97
-3
lines changed

3 files changed

+97
-3
lines changed

docs/rules/no-v-text-v-html-on-component.md

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,33 @@ If you use v-text / v-html on a component, it will overwrite the component's con
3636

3737
## :wrench: Options
3838

39-
Nothing.
39+
```json
40+
{
41+
"vue/no-v-text-v-html-on-component": [
42+
"error",
43+
{ "allow": ["router-link", "nuxt-link"] }
44+
]
45+
}
46+
```
47+
48+
- `allow` (`string[]`) ... Specify a list of custom components for which the rule should not apply.
49+
50+
### `{ "allow": ["router-link", "nuxt-link"] }`
51+
52+
<eslint-code-block :rules="{'vue/no-v-text-v-html-on-component': ['error', { allow: ['router-link', 'nuxt-link'] }]}">
53+
54+
```vue
55+
<template>
56+
<!-- ✓ GOOD -->
57+
<router-link v-html="content" />
58+
<NuxtLink v-html="content" />
59+
60+
<!-- ✗ BAD -->
61+
<MyComponent v-html="content" />
62+
</template>
63+
```
64+
65+
</eslint-code-block>
4066

4167
## :rocket: Version
4268

lib/rules/no-v-text-v-html-on-component.js

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
'use strict'
66

77
const utils = require('../utils')
8+
const casing = require('../utils/casing')
89

910
module.exports = {
1011
meta: {
@@ -15,21 +16,53 @@ module.exports = {
1516
url: 'https://eslint.vuejs.org/rules/no-v-text-v-html-on-component.html'
1617
},
1718
fixable: null,
18-
schema: [],
19+
schema: [
20+
{
21+
type: 'object',
22+
properties: {
23+
allow: {
24+
type: 'array',
25+
items: {
26+
type: 'string'
27+
},
28+
uniqueItems: true
29+
}
30+
},
31+
additionalProperties: false
32+
}
33+
],
1934
messages: {
2035
disallow:
2136
"Using {{directiveName}} on component may break component's content."
2237
}
2338
},
2439
/** @param {RuleContext} context */
2540
create(context) {
41+
const options = context.options[0] || {}
42+
/** @type {Set<string>} */
43+
const allow = new Set(options.allow)
44+
45+
/**
46+
* Check whether the given node is an allowed component or not.
47+
* @param {VElement} node The start tag node to check.
48+
* @returns {boolean} `true` if the node is an allowed component.
49+
*/
50+
function isAllowedComponent(node) {
51+
const componentName = node.rawName
52+
return (
53+
allow.has(componentName) ||
54+
allow.has(casing.pascalCase(componentName)) ||
55+
allow.has(casing.kebabCase(componentName))
56+
)
57+
}
58+
2659
/**
2760
* Verify for v-text and v-html directive
2861
* @param {VDirective} node
2962
*/
3063
function verify(node) {
3164
const element = node.parent.parent
32-
if (utils.isCustomComponent(element)) {
65+
if (utils.isCustomComponent(element) && !isAllowedComponent(element)) {
3366
context.report({
3467
node,
3568
loc: node.loc,

tests/lib/rules/no-v-text-v-html-on-component.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,25 @@ tester.run('no-v-text-v-html-on-component', rule, {
4040
<MyComponent v-if="content" />
4141
</template>
4242
`
43+
},
44+
{
45+
filename: 'test.vue',
46+
code: `
47+
<template>
48+
<router-link v-text="content" />
49+
</template>
50+
`,
51+
options: [{ allow: ['router-link'] }]
52+
},
53+
{
54+
filename: 'test.vue',
55+
code: `
56+
<template>
57+
<router-link v-html="content" />
58+
<NuxtLink v-html="content" />
59+
</template>
60+
`,
61+
options: [{ allow: ['RouterLink', 'nuxt-link'] }]
4362
}
4463
],
4564
invalid: [
@@ -132,6 +151,22 @@ tester.run('no-v-text-v-html-on-component', rule, {
132151
column: 30
133152
}
134153
]
154+
},
155+
{
156+
filename: 'test.vue',
157+
code: `
158+
<template>
159+
<router-link v-html="content" />
160+
</template>
161+
`,
162+
options: [{ allow: ['nuxt-link'] }],
163+
errors: [
164+
{
165+
message: "Using v-html on component may break component's content.",
166+
line: 3,
167+
column: 22
168+
}
169+
]
135170
}
136171
]
137172
})

0 commit comments

Comments
 (0)