Skip to content
5 changes: 5 additions & 0 deletions .changeset/purple-lights-invite.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'eslint-plugin-vue': minor
---

Added `ignorePattern` option to [`vue/no-v-html`](https://eslint.vuejs.org/rules/no-v-html.html)
32 changes: 31 additions & 1 deletion docs/rules/no-v-html.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,42 @@ This rule reports all uses of `v-html` directive in order to reduce the risk of

## :wrench: Options

Nothing.
```json
{
"vue/no-v-html": ["error", {
"ignorePattern": ".Html$"
}]
}
```

- `ignorePattern` ... disables reporting when the `v-html` directive references a variable matching this pattern. By default, all `v-html` uses are forbidden.

### `{ "ignorePattern": ".Html$" }`

<eslint-code-block :rules="{'vue/no-v-html': ['error', { 'ignorePattern': '.Html$' }]}">

```vue
<template>
<!-- ✓ GOOD -->
<h2>{{ userName }}</h2>
<span v-html="userLinkHtml" />

<!-- ✗ BAD -->
<span v-html="userName" />
</template>
```

</eslint-code-block>

## :mute: When Not To Use It

If you are certain the content passed to `v-html` is sanitized HTML you can disable this rule.

## :couple: Related Rules

- [vue/no-v-text](./no-v-text.md)
- [vue/no-v-text-v-html-on-component](./no-v-text-v-html-on-component.md)

## :rocket: Version

This rule was introduced in eslint-plugin-vue v4.7.0
Expand Down
5 changes: 5 additions & 0 deletions docs/rules/no-v-text-v-html-on-component.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,11 @@ If you use v-text / v-html on a component, it will overwrite the component's con

</eslint-code-block>

## :couple: Related Rules

- [vue/no-v-text](./no-v-text.md)
- [vue/no-v-html](./no-v-html.md)

## :rocket: Version

This rule was introduced in eslint-plugin-vue v8.4.0
Expand Down
5 changes: 5 additions & 0 deletions docs/rules/no-v-text.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ This rule reports all uses of `v-text` directive.

Nothing.

## :couple: Related Rules

- [vue/no-v-html](./no-v-html.md)
- [vue/no-v-text-v-html-on-component](./no-v-text-v-html-on-component.md)

## :rocket: Version

This rule was introduced in eslint-plugin-vue v7.17.0
Expand Down
24 changes: 23 additions & 1 deletion lib/rules/no-v-html.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,38 @@ module.exports = {
url: 'https://eslint.vuejs.org/rules/no-v-html.html'
},
fixable: null,
schema: [],
schema: [
{
type: 'object',
properties: {
ignorePattern: {
type: 'string'
}
},
additionalProperties: false
}
],
messages: {
unexpected: "'v-html' directive can lead to XSS attack."
}
},
/** @param {RuleContext} context */
create(context) {
const options = context.options[0]
const ignoreRegEx = options?.ignorePattern
? new RegExp(options.ignorePattern, 'u')
: undefined

return utils.defineTemplateBodyVisitor(context, {
/** @param {VDirective} node */
"VAttribute[directive=true][key.name.name='html']"(node) {
if (
ignoreRegEx &&
node.value.expression.type === 'Identifier' &&
ignoreRegEx.test(node.value.expression.name)
) {
return
}
context.report({
node,
loc: node.loc,
Expand Down
11 changes: 11 additions & 0 deletions tests/lib/rules/no-v-html.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ ruleTester.run('no-v-html', rule, {
{
filename: 'test.vue',
code: '<template><div v-if="foo" v-bind="bar"></div></template>'
},
{
filename: 'test.vue',
code: '<template><div v-html="knownHtml"></div></template>',
options: [{ ignorePattern: '.Html$' }]
}
],
invalid: [
Expand All @@ -45,6 +50,12 @@ ruleTester.run('no-v-html', rule, {
filename: 'test.vue',
code: '<template><section v-html/></template>',
errors: ["'v-html' directive can lead to XSS attack."]
},
{
filename: 'test.vue',
code: '<template><div v-html="unsafeString"></div></template>',
options: [{ ignorePattern: '.Html$' }],
errors: ["'v-html' directive can lead to XSS attack."]
}
]
})