Skip to content

Commit

Permalink
Add new rule: no-restricted-html-elements (#1820)
Browse files Browse the repository at this point in the history
* Add new rule: html-forbid-elements

* PR Feedback

* Update lib/rules/no-restricted-html-elements.js

Co-authored-by: Flo Edelmann <florian-edelmann@online.de>

* Update docs/rules/no-restricted-html-elements.md

Co-authored-by: Flo Edelmann <florian-edelmann@online.de>

* Update lib/rules/no-restricted-html-elements.js

Co-authored-by: Flo Edelmann <florian-edelmann@online.de>

* Update tests/lib/rules/no-restricted-html-elements.js

Co-authored-by: Yosuke Ota <otameshiyo23@gmail.com>

* Update tests/lib/rules/no-restricted-html-elements.js

Co-authored-by: Yosuke Ota <otameshiyo23@gmail.com>

* Update tests/lib/rules/no-restricted-html-elements.js

Co-authored-by: Yosuke Ota <otameshiyo23@gmail.com>

* Update tests/lib/rules/no-restricted-html-elements.js

Co-authored-by: Yosuke Ota <otameshiyo23@gmail.com>

* Update tests/lib/rules/no-restricted-html-elements.js

Co-authored-by: Yosuke Ota <otameshiyo23@gmail.com>

* Update tests/lib/rules/no-restricted-html-elements.js

Co-authored-by: Yosuke Ota <otameshiyo23@gmail.com>

* Update docs/rules/no-restricted-html-elements.md

Co-authored-by: Yosuke Ota <otameshiyo23@gmail.com>

* Update tests/lib/rules/no-restricted-html-elements.js

Co-authored-by: Yosuke Ota <otameshiyo23@gmail.com>

* Update docs/rules/no-restricted-html-elements.md

Co-authored-by: Flo Edelmann <florian-edelmann@online.de>

* Update docs/rules/no-restricted-html-elements.md

Co-authored-by: Flo Edelmann <florian-edelmann@online.de>

* Update docs/rules/no-restricted-html-elements.md

Co-authored-by: Flo Edelmann <florian-edelmann@online.de>

* run npm update

* Remove messages block

* Update docs/rules/no-restricted-html-elements.md

* Update docs/rules/no-restricted-html-elements.md

* Fix demo site

Co-authored-by: Flo Edelmann <florian-edelmann@online.de>
Co-authored-by: Yosuke Ota <otameshiyo23@gmail.com>
  • Loading branch information
3 people committed Mar 23, 2022
1 parent f5f4f97 commit 1ce68fa
Show file tree
Hide file tree
Showing 5 changed files with 241 additions and 0 deletions.
1 change: 1 addition & 0 deletions docs/rules/README.md
Expand Up @@ -334,6 +334,7 @@ For example:
| [vue/no-restricted-class](./no-restricted-class.md) | disallow specific classes in Vue components | |
| [vue/no-restricted-component-options](./no-restricted-component-options.md) | disallow specific component option | |
| [vue/no-restricted-custom-event](./no-restricted-custom-event.md) | disallow specific custom event | :bulb: |
| [vue/no-restricted-html-elements](./no-restricted-html-elements.md) | disallow specific HTML elements | |
| [vue/no-restricted-props](./no-restricted-props.md) | disallow specific props | :bulb: |
| [vue/no-restricted-static-attribute](./no-restricted-static-attribute.md) | disallow specific attribute | |
| [vue/no-restricted-v-bind](./no-restricted-v-bind.md) | disallow specific argument in `v-bind` | |
Expand Down
96 changes: 96 additions & 0 deletions docs/rules/no-restricted-html-elements.md
@@ -0,0 +1,96 @@
---
pageClass: rule-details
sidebarDepth: 0
title: vue/no-restricted-html-elements
description: disallow specific HTML elements
---
# vue/no-restricted-html-elements

> disallow specific HTML elements
- :exclamation: <badge text="This rule has not been released yet." vertical="middle" type="error"> ***This rule has not been released yet.*** </badge>

## :book: Rule Details

This rule allows you to specify HTML elements that you don't want to use in your application.

<eslint-code-block :rules="{'vue/no-restricted-html-elements': ['error', 'marquee', 'button'] }">

```vue
<template>
<!-- ✓ GOOD -->
<p></p>
<input />
<br />
<!-- ✗ BAD -->
<button></button>
<marquee></marquee>
</template>
```

</eslint-code-block>

## :wrench: Options

This rule takes a list of strings, where each string is an HTML element name to be restricted:

```json
{
"vue/no-restricted-html-elements": ["error", "button", "marquee"]
}
```

<eslint-code-block :rules="{'vue/no-restricted-html-elements': ['error', 'button', 'marquee']}">

```vue
<template>
<!-- ✗ BAD -->
<button></button>
<marquee></marquee>
</template>
```

</eslint-code-block>

Alternatively, the rule also accepts objects.

```json
{
"vue/no-restricted-html-elements": [
"error",
{
"element": "button",
"message": "Prefer use of our custom <AppButton /> component"
},
{
"element": "marquee",
"message": "Do not use deprecated HTML tags"
}
]
}
```

The following properties can be specified for the object.

- `element` ... Specify the html element.
- `message` ... Specify an optional custom message.

### `{ "element": "marquee" }, { "element": "button" }`

<eslint-code-block :rules="{'vue/no-restricted-html-elements': ['error', { element: 'marquee' }, { element: 'button' }]}">

```vue
<template>
<!-- ✗ BAD -->
<marquee></marquee>
<button></button>
</template>
```

</eslint-code-block>

## :mag: Implementation

- [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/no-restricted-html-elements.js)
- [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/no-restricted-html-elements.js)
1 change: 1 addition & 0 deletions lib/index.js
Expand Up @@ -113,6 +113,7 @@ module.exports = {
'no-restricted-class': require('./rules/no-restricted-class'),
'no-restricted-component-options': require('./rules/no-restricted-component-options'),
'no-restricted-custom-event': require('./rules/no-restricted-custom-event'),
'no-restricted-html-elements': require('./rules/no-restricted-html-elements'),
'no-restricted-props': require('./rules/no-restricted-props'),
'no-restricted-static-attribute': require('./rules/no-restricted-static-attribute'),
'no-restricted-syntax': require('./rules/no-restricted-syntax'),
Expand Down
68 changes: 68 additions & 0 deletions lib/rules/no-restricted-html-elements.js
@@ -0,0 +1,68 @@
/**
* @author Doug Wade <douglas.b.wade@gmail.com>
*/

'use strict'

const utils = require('../utils')

module.exports = {
meta: {
type: 'suggestion',
docs: {
description: 'disallow specific HTML elements',
categories: undefined,
url: 'https://eslint.vuejs.org/rules/no-restricted-html-elements.html'
},
fixable: null,
schema: {
type: 'array',
items: {
oneOf: [
{ type: 'string' },
{
type: 'object',
properties: {
element: { type: 'string' },
message: { type: 'string', minLength: 1 }
},
required: ['element'],
additionalProperties: false
}
]
},
uniqueItems: true,
minItems: 0
}
},
/**
* @param {RuleContext} context - The rule context.
* @returns {RuleListener} AST event handlers.
*/
create(context) {
return utils.defineTemplateBodyVisitor(context, {
/**
* @param {VElement} node
*/
VElement(node) {
if (!utils.isHtmlElementNode(node)) {
return
}

context.options.forEach((option) => {
const message =
option.message ||
`Unexpected use of forbidden HTML element ${node.rawName}.`
const element = option.element || option

if (element === node.rawName) {
context.report({
message,
node: node.startTag
})
}
})
}
})
}
}
75 changes: 75 additions & 0 deletions tests/lib/rules/no-restricted-html-elements.js
@@ -0,0 +1,75 @@
/**
* @author Doug Wade
*/
'use strict'

const RuleTester = require('eslint').RuleTester
const rule = require('../../../lib/rules/no-restricted-html-elements')

const tester = new RuleTester({
parser: require.resolve('vue-eslint-parser'),
parserOptions: { ecmaVersion: 2015 }
})

tester.run('no-restricted-html-elements', rule, {
valid: [
{
filename: 'test.vue',
code: '',
options: ['button']
},
{
filename: 'test.vue',
code: '<template><div class="foo"></div></template>',
options: ['button']
},
{
filename: 'test.vue',
code: '<template><button type="button"></button></template>',
options: ['div']
},
{
filename: 'test.vue',
code: '<template><div class="foo"><Button type="button"></Button></div></template>',
options: ['button']
}
],
invalid: [
{
filename: 'test.vue',
code: '<template><div><button type="button"></button><div></template>',
errors: [
{
message: 'Unexpected use of forbidden HTML element button.',
line: 1,
column: 16
}
],
options: ['button']
},
{
filename: 'test.vue',
code: '<template><div class="foo"><button type="button"></button></div></template>',
errors: [
{
message: 'Unexpected use of forbidden HTML element div.',
line: 1,
column: 11
}
],
options: ['div']
},
{
filename: 'test.vue',
code: '<template><marquee>foo</marquee></template>',
errors: [
{
message: 'Custom error',
line: 1,
column: 11
}
],
options: [{ element: 'marquee', message: 'Custom error' }]
}
]
})

0 comments on commit 1ce68fa

Please sign in to comment.