diff --git a/docs/rules/use-v-on-extact.md b/docs/rules/use-v-on-extact.md new file mode 100644 index 000000000..2753681ad --- /dev/null +++ b/docs/rules/use-v-on-extact.md @@ -0,0 +1,27 @@ +# Enforce usage of `exact` modifier on `v-on` + +- :gear: This rule is included in `"plugin:vue/essential"`. + +This rule enforce usage of `exact` modifier on `v-on` when there is another `v-on` with modifier. + +:+1: Examples of **correct** code for this rule: + +```html + +``` + +:-1: Examples of **incorrect** code for this rule: + +```html + +``` + +## Related rules + +- [vue/v-on-style](./v-on-style.md) +- [vue/valid-v-on](./valid-v-on.md) diff --git a/lib/rules/use-v-on-exact.js b/lib/rules/use-v-on-exact.js new file mode 100644 index 000000000..b143d619d --- /dev/null +++ b/lib/rules/use-v-on-exact.js @@ -0,0 +1,65 @@ +/** + * @fileoverview enforce usage of `exact` modifier on `v-on`. + * @author Armano + */ +'use strict' + +// ------------------------------------------------------------------------------ +// Requirements +// ------------------------------------------------------------------------------ + +const utils = require('../utils') + +// ------------------------------------------------------------------------------ +// Rule Definition +// ------------------------------------------------------------------------------ + +module.exports = { + meta: { + docs: { + description: 'enforce usage of `exact` modifier on `v-on`', + category: undefined, // essential + url: 'https://github.com/vuejs/eslint-plugin-vue/blob/v5.0.0-beta.3/docs/rules/use-v-on-exact.md' + }, + fixable: null, + schema: [] + }, + + /** + * Creates AST event handlers for use-v-on-exact. + * + * @param {RuleContext} context - The rule context. + * @returns {Object} AST event handlers. + */ + create (context) { + return utils.defineTemplateBodyVisitor(context, { + VStartTag (node) { + if (node.attributes.length > 1) { + const groups = node.attributes + .map(item => item.key) + .filter(item => item && item.type === 'VDirectiveKey' && item.name === 'on') + .reduce((rv, item) => { + (rv[item.argument] = rv[item.argument] || []).push(item) + return rv + }, {}) + + const directives = Object.keys(groups).map(key => groups[key]) + // const directives = Object.values(groups) // Uncomment after node 6 is dropped + .filter(item => item.length > 1) + for (const group of directives) { + if (group.some(item => item.modifiers.length > 0)) { // check if there are directives with modifiers + const invalid = group.filter(item => item.modifiers.length === 0) + for (const node of invalid) { + context.report({ + node, + loc: node.loc, + message: "Consider to use '.exact' modifier." + }) + } + } + } + } + } + }) + } +} diff --git a/tests/lib/rules/use-v-on-exact.js b/tests/lib/rules/use-v-on-exact.js new file mode 100644 index 000000000..e93a46601 --- /dev/null +++ b/tests/lib/rules/use-v-on-exact.js @@ -0,0 +1,75 @@ +/** + * @fileoverview enforce usage of `exact` modifier on `v-on`. + * @author Armano + */ +'use strict' + +// ------------------------------------------------------------------------------ +// Requirements +// ------------------------------------------------------------------------------ + +const rule = require('../../../lib/rules/use-v-on-exact') + +const RuleTester = require('eslint').RuleTester + +// ------------------------------------------------------------------------------ +// Tests +// ------------------------------------------------------------------------------ + +const ruleTester = new RuleTester({ + parser: 'vue-eslint-parser', + parserOptions: { ecmaVersion: 2015 } +}) + +ruleTester.run('use-v-on-exact', rule, { + + valid: [ + { + code: `` + }, + { + code: `` + }, + { + code: `` + }, + { + code: `` + }, + { + code: `` + }, + { + code: `` + }, + { + code: `` + }, + { + code: `` + }, + { + code: `` + }, + { + code: `` + }, + { + code: `` + }, + { + code: `` + } + ], + + invalid: [ + { + code: ``, + errors: ["Consider to use '.exact' modifier."] + }, + { + code: ``, + errors: ["Consider to use '.exact' modifier."] + } + ] +})