diff --git a/.changeset/crazy-impalas-pick.md b/.changeset/crazy-impalas-pick.md new file mode 100644 index 000000000..834a6ec8f --- /dev/null +++ b/.changeset/crazy-impalas-pick.md @@ -0,0 +1,5 @@ +--- +'eslint-plugin-vue': minor +--- + +[vue/no-restricted-html-elements](https://eslint.vuejs.org/rules/no-restricted-html-elements.html) now accepts multiple elements in each entry. diff --git a/docs/rules/no-restricted-html-elements.md b/docs/rules/no-restricted-html-elements.md index 2a6d6c997..fef08aeb2 100644 --- a/docs/rules/no-restricted-html-elements.md +++ b/docs/rules/no-restricted-html-elements.md @@ -37,16 +37,16 @@ This rule takes a list of strings, where each string is an HTML element name to ```json { - "vue/no-restricted-html-elements": ["error", "button", "marquee"] + "vue/no-restricted-html-elements": ["error", "a", "marquee"] } ``` - + ```vue ``` @@ -60,8 +60,8 @@ Alternatively, the rule also accepts objects. "vue/no-restricted-html-elements": [ "error", { - "element": "button", - "message": "Prefer use of our custom component" + "element": ["a", "RouterLink"], + "message": "Prefer the use of component" }, { "element": "marquee", @@ -73,18 +73,18 @@ Alternatively, the rule also accepts objects. The following properties can be specified for the object. -- `element` ... Specify the html element. +- `element` ... Specify the HTML element or an array of HTML elements. - `message` ... Specify an optional custom message. -### `{ "element": "marquee" }, { "element": "button" }` +### `{ "element": "marquee" }, { "element": "a" }` - + ```vue ``` diff --git a/lib/rules/no-restricted-html-elements.js b/lib/rules/no-restricted-html-elements.js index e906d86f2..8d5f3c300 100644 --- a/lib/rules/no-restricted-html-elements.js +++ b/lib/rules/no-restricted-html-elements.js @@ -23,7 +23,12 @@ module.exports = { { type: 'object', properties: { - element: { type: 'string' }, + element: { + oneOf: [ + { type: 'string' }, + { type: 'array', items: { type: 'string' } } + ] + }, message: { type: 'string', minLength: 1 } }, required: ['element'], @@ -55,9 +60,12 @@ module.exports = { } for (const option of context.options) { - const element = option.element || option + const restrictedItem = option.element || option + const elementsToRestrict = Array.isArray(restrictedItem) + ? restrictedItem + : [restrictedItem] - if (element === node.rawName) { + if (elementsToRestrict.includes(node.rawName)) { context.report({ messageId: option.message ? 'customMessage' : 'forbiddenElement', data: { @@ -66,6 +74,8 @@ module.exports = { }, node: node.startTag }) + + return } } } diff --git a/tests/lib/rules/no-restricted-html-elements.js b/tests/lib/rules/no-restricted-html-elements.js index c3e3e9eeb..6180b046b 100644 --- a/tests/lib/rules/no-restricted-html-elements.js +++ b/tests/lib/rules/no-restricted-html-elements.js @@ -31,6 +31,11 @@ tester.run('no-restricted-html-elements', rule, { filename: 'test.vue', code: '', options: ['button'] + }, + { + filename: 'test.vue', + code: '', + options: [{ element: ['div', 'span'] }] } ], invalid: [ @@ -69,6 +74,28 @@ tester.run('no-restricted-html-elements', rule, { column: 11 } ] + }, + { + filename: 'test.vue', + code: '', + options: [ + { + element: ['a', 'RouterLink'], + message: 'Prefer the use of component' + } + ], + errors: [ + { + message: 'Prefer the use of component', + line: 1, + column: 11 + }, + { + message: 'Prefer the use of component', + line: 1, + column: 18 + } + ] } ] })