diff --git a/docs/rules/README.md b/docs/rules/README.md index 735dc87d0..49a6c6389 100644 --- a/docs/rules/README.md +++ b/docs/rules/README.md @@ -349,6 +349,7 @@ For example: | [vue/no-use-computed-property-like-method](./no-use-computed-property-like-method.md) | disallow use computed property like method | | | [vue/no-useless-mustaches](./no-useless-mustaches.md) | disallow unnecessary mustache interpolations | :wrench: | | [vue/no-useless-v-bind](./no-useless-v-bind.md) | disallow unnecessary `v-bind` directives | :wrench: | +| [vue/no-v-text-v-html-on-component](./no-v-text-v-html-on-component.md) | disallow v-text / v-html on component | | | [vue/no-v-text](./no-v-text.md) | disallow use of v-text | | | [vue/padding-line-between-blocks](./padding-line-between-blocks.md) | require or disallow padding lines between blocks | :wrench: | | [vue/prefer-separate-static-class](./prefer-separate-static-class.md) | require static class names in template to be in a separate `class` attribute | :wrench: | diff --git a/docs/rules/no-v-text-v-html-on-component.md b/docs/rules/no-v-text-v-html-on-component.md new file mode 100644 index 000000000..5d8c8c434 --- /dev/null +++ b/docs/rules/no-v-text-v-html-on-component.md @@ -0,0 +1,43 @@ +--- +pageClass: rule-details +sidebarDepth: 0 +title: vue/no-v-text-v-html-on-component +description: disallow v-text / v-html on component +--- +# vue/no-v-text-v-html-on-component + +> disallow v-text / v-html on component + +- :exclamation: ***This rule has not been released yet.*** + +## :book: Rule Details + +This rule disallows the use of v-text / v-html on component. + +If you use v-text / v-html on a component, it will overwrite the component's content and may break the component. + + + +```vue + +``` + + + +## :wrench: Options + +Nothing. + +## :mag: Implementation + +- [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/no-v-text-v-html-on-component.js) +- [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/no-v-text-v-html-on-component.js) diff --git a/lib/index.js b/lib/index.js index 3c628c559..021710984 100644 --- a/lib/index.js +++ b/lib/index.js @@ -145,6 +145,7 @@ module.exports = { 'no-v-for-template-key': require('./rules/no-v-for-template-key'), 'no-v-html': require('./rules/no-v-html'), 'no-v-model-argument': require('./rules/no-v-model-argument'), + 'no-v-text-v-html-on-component': require('./rules/no-v-text-v-html-on-component'), 'no-v-text': require('./rules/no-v-text'), 'no-watch-after-await': require('./rules/no-watch-after-await'), 'object-curly-newline': require('./rules/object-curly-newline'), diff --git a/lib/rules/no-v-text-v-html-on-component.js b/lib/rules/no-v-text-v-html-on-component.js new file mode 100644 index 000000000..4a208627d --- /dev/null +++ b/lib/rules/no-v-text-v-html-on-component.js @@ -0,0 +1,59 @@ +/** + * @author Yosuke Ota + * See LICENSE file in root directory for full license. + */ +'use strict' + +// ------------------------------------------------------------------------------ +// Requirements +// ------------------------------------------------------------------------------ + +const utils = require('../utils') + +// ------------------------------------------------------------------------------ +// Rule Definition +// ------------------------------------------------------------------------------ + +module.exports = { + meta: { + type: 'problem', + docs: { + description: 'disallow v-text / v-html on component', + // TODO We will change it in the next major version. + // categories: ['essential', 'vue3-essential'], + categories: undefined, + url: 'https://eslint.vuejs.org/rules/no-v-text-v-html-on-component.html' + }, + fixable: null, + schema: [], + messages: { + disallow: + "Using {{directiveName}} on component may break component's content." + } + }, + /** @param {RuleContext} context */ + create(context) { + /** + * Verify for v-text and v-html directive + * @param {VDirective} node + */ + function verify(node) { + const element = node.parent.parent + if (utils.isCustomComponent(element)) { + context.report({ + node, + loc: node.loc, + messageId: 'disallow', + data: { + directiveName: `v-${node.key.name.name}` + } + }) + } + } + + return utils.defineTemplateBodyVisitor(context, { + "VAttribute[directive=true][key.name.name='text']": verify, + "VAttribute[directive=true][key.name.name='html']": verify + }) + } +} 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 new file mode 100644 index 000000000..c50071346 --- /dev/null +++ b/tests/lib/rules/no-v-text-v-html-on-component.js @@ -0,0 +1,137 @@ +/** + * @author Yosuke Ota + * See LICENSE file in root directory for full license. + */ +'use strict' + +const RuleTester = require('eslint').RuleTester +const rule = require('../../../lib/rules/no-v-text-v-html-on-component') + +const tester = new RuleTester({ + parser: require.resolve('vue-eslint-parser'), + parserOptions: { + ecmaVersion: 2020, + sourceType: 'module' + } +}) + +tester.run('no-v-text-v-html-on-component', rule, { + valid: [ + { + filename: 'test.vue', + code: ` + + ` + }, + { + filename: 'test.vue', + code: ` + + ` + }, + { + filename: 'test.vue', + code: ` + + ` + } + ], + invalid: [ + { + filename: 'test.vue', + code: ` + + `, + errors: [ + { + message: "Using v-text on component may break component's content.", + line: 3, + column: 22 + } + ] + }, + { + filename: 'test.vue', + code: ` + + `, + errors: [ + { + message: "Using v-html on component may break component's content.", + line: 3, + column: 22 + } + ] + }, + { + filename: 'test.vue', + code: ` + + `, + errors: [ + { + message: "Using v-text on component may break component's content.", + line: 3, + column: 36 + } + ] + }, + { + filename: 'test.vue', + code: ` + + `, + errors: [ + { + message: "Using v-html on component may break component's content.", + line: 3, + column: 36 + } + ] + }, + { + filename: 'test.vue', + code: ` + + `, + errors: [ + { + message: "Using v-text on component may break component's content.", + line: 3, + column: 30 + } + ] + }, + { + filename: 'test.vue', + code: ` + + `, + errors: [ + { + message: "Using v-html on component may break component's content.", + line: 3, + column: 30 + } + ] + } + ] +})