From 0cbd831712c86d63c2689935d762c2e330aa8710 Mon Sep 17 00:00:00 2001 From: yoyo930021 Date: Tue, 17 Mar 2020 22:54:46 +0800 Subject: [PATCH] New: Add `vue/no-deprecated-v-on-number-modifiers` rule --- docs/rules/README.md | 1 + .../no-deprecated-v-on-number-modifiers.md | 52 ++++++ lib/configs/vue3-essential.js | 1 + lib/index.js | 1 + .../no-deprecated-v-on-number-modifiers.js | 58 ++++++ lib/utils/keycode-to-key.json | 100 ++++++++++ .../no-deprecated-v-on-number-modifiers.js | 174 ++++++++++++++++++ 7 files changed, 387 insertions(+) create mode 100644 docs/rules/no-deprecated-v-on-number-modifiers.md create mode 100644 lib/rules/no-deprecated-v-on-number-modifiers.js create mode 100644 lib/utils/keycode-to-key.json create mode 100644 tests/lib/rules/no-deprecated-v-on-number-modifiers.js diff --git a/docs/rules/README.md b/docs/rules/README.md index e184873e5..7e507e4b9 100644 --- a/docs/rules/README.md +++ b/docs/rules/README.md @@ -44,6 +44,7 @@ Enforce all the rules in this category, as well as all higher priority rules, wi | [vue/no-deprecated-slot-attribute](./no-deprecated-slot-attribute.md) | disallow deprecated `slot` attribute (in Vue.js 2.6.0+) | :wrench: | | [vue/no-deprecated-slot-scope-attribute](./no-deprecated-slot-scope-attribute.md) | disallow deprecated `slot-scope` attribute (in Vue.js 2.6.0+) | :wrench: | | [vue/no-deprecated-v-bind-sync](./no-deprecated-v-bind-sync.md) | disallow use of deprecated `.sync` modifier on `v-bind` directive (in Vue.js 3.0.0+) | :wrench: | +| [vue/no-deprecated-v-on-number-modifiers](./no-deprecated-v-on-number-modifiers.md) | disallow using deprecated number (keycode) modifiers | :wrench: | | [vue/no-dupe-keys](./no-dupe-keys.md) | disallow duplication of field names | | | [vue/no-duplicate-attributes](./no-duplicate-attributes.md) | disallow duplication of attributes | | | [vue/no-lifecycle-after-await](./no-lifecycle-after-await.md) | disallow asynchronously registered lifecycle hooks | | diff --git a/docs/rules/no-deprecated-v-on-number-modifiers.md b/docs/rules/no-deprecated-v-on-number-modifiers.md new file mode 100644 index 000000000..5ecba24a8 --- /dev/null +++ b/docs/rules/no-deprecated-v-on-number-modifiers.md @@ -0,0 +1,52 @@ +--- +pageClass: rule-details +sidebarDepth: 0 +title: vue/no-deprecated-v-on-number-modifiers +description: disallow using deprecated number (keycode) modifiers (in Vue.js 3.0.0+) +--- +# vue/no-deprecated-v-on-number-modifiers +> disallow using deprecated number (keycode) modifiers (in Vue.js 3.0.0+) + +- :gear: This rule is included in all of `"plugin:vue/vue3-essential"`, `"plugin:vue/vue3-strongly-recommended"` and `"plugin:vue/vue3-recommended"`. +- :wrench: The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can automatically fix some of the problems reported by this rule. + +## :book: Rule Details + +This rule reports use of deprecated `KeyboardEvent.keyCode` modifier on `v-on` directive (in Vue.js 3.0.0+) + + + +```vue + +``` + + + +## :wrench: Options + +Nothing. + +## :couple: Related rules + +- [valid-v-on] + +[valid-v-on]: valid-v-on.md + +## :books: Further reading + +- [RFC: drop keycode support](https://github.com/vuejs/rfcs/blob/master/active-rfcs/0014-drop-keycode-support.md) + +## :mag: Implementation + +- [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/no-deprecated-v-on-number-modifiers.js) +- [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/no-deprecated-v-on-number-modifiers.js) diff --git a/lib/configs/vue3-essential.js b/lib/configs/vue3-essential.js index 3e45ddd2c..1b0c23e08 100644 --- a/lib/configs/vue3-essential.js +++ b/lib/configs/vue3-essential.js @@ -12,6 +12,7 @@ module.exports = { 'vue/no-deprecated-slot-attribute': 'error', 'vue/no-deprecated-slot-scope-attribute': 'error', 'vue/no-deprecated-v-bind-sync': 'error', + 'vue/no-deprecated-v-on-number-modifiers': 'error', 'vue/no-dupe-keys': 'error', 'vue/no-duplicate-attributes': 'error', 'vue/no-lifecycle-after-await': 'error', diff --git a/lib/index.js b/lib/index.js index 10e2e8766..df70ec82a 100644 --- a/lib/index.js +++ b/lib/index.js @@ -45,6 +45,7 @@ module.exports = { 'no-deprecated-slot-attribute': require('./rules/no-deprecated-slot-attribute'), 'no-deprecated-slot-scope-attribute': require('./rules/no-deprecated-slot-scope-attribute'), 'no-deprecated-v-bind-sync': require('./rules/no-deprecated-v-bind-sync'), + 'no-deprecated-v-on-number-modifiers': require('./rules/no-deprecated-v-on-number-modifiers'), 'no-dupe-keys': require('./rules/no-dupe-keys'), 'no-duplicate-attributes': require('./rules/no-duplicate-attributes'), 'no-empty-pattern': require('./rules/no-empty-pattern'), diff --git a/lib/rules/no-deprecated-v-on-number-modifiers.js b/lib/rules/no-deprecated-v-on-number-modifiers.js new file mode 100644 index 000000000..651991cd4 --- /dev/null +++ b/lib/rules/no-deprecated-v-on-number-modifiers.js @@ -0,0 +1,58 @@ +/** + * @fileoverview disallow using deprecated number (keycode) modifiers + * @author yoyo930021 + */ +'use strict' + +// ------------------------------------------------------------------------------ +// Requirements +// ------------------------------------------------------------------------------ + +const utils = require('../utils') +const keyCodeToKey = require('../utils/keycode-to-key.json') + +// ------------------------------------------------------------------------------ +// Rule Definition +// ------------------------------------------------------------------------------ + +module.exports = { + meta: { + type: 'problem', + docs: { + description: 'disallow using deprecated number (keycode) modifiers', + categories: ['vue3-essential'], + url: 'https://eslint.vuejs.org/rules/no-deprecated-v-on-number-modifiers.html' + }, + fixable: 'code', + schema: [], + messages: { + numberModifierIsDeprecated: "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead." + } + }, + + create (context) { + return utils.defineTemplateBodyVisitor(context, { + "VAttribute[directive=true][key.name.name='on']" (node) { + const modifier = node.key.modifiers.find(mod => Number.isInteger(parseInt(mod.name, 10))) + if (!modifier) return + + const keyCodes = parseInt(modifier.name, 10) + if ( + keyCodes > 9 || keyCodes < 0 + ) { + context.report({ + node, + loc: node.loc, + messageId: 'numberModifierIsDeprecated', + fix: (fixer) => { + const key = keyCodeToKey[keyCodes] + if (!key) return + + return fixer.replaceTextRange(modifier.range, `${key}`) + } + }) + } + } + }) + } +} diff --git a/lib/utils/keycode-to-key.json b/lib/utils/keycode-to-key.json new file mode 100644 index 000000000..43f480302 --- /dev/null +++ b/lib/utils/keycode-to-key.json @@ -0,0 +1,100 @@ +{ + "8": "backspace", + "9": "tab", + "13": "enter", + "16": "shift", + "17": "ctrl", + "18": "alt", + "19": "pause-break", + "20": "caps-lock", + "27": "escape", + "33": "page-up", + "34": "page-down", + "35": "end", + "36": "home", + "37": "left-arrow", + "38": "up-arrow", + "39": "right-arrow", + "40": "down-arrow", + "45": "insert", + "46": "delete", + "48": "0", + "49": "1", + "50": "2", + "51": "3", + "52": "4", + "53": "5", + "54": "6", + "55": "7", + "56": "8", + "57": "9", + "65": "a", + "66": "b", + "67": "c", + "68": "d", + "69": "e", + "70": "f", + "71": "g", + "72": "h", + "73": "i", + "74": "j", + "75": "k", + "76": "l", + "77": "m", + "78": "n", + "79": "o", + "80": "p", + "81": "q", + "82": "r", + "83": "s", + "84": "t", + "85": "u", + "86": "v", + "87": "w", + "88": "x", + "89": "y", + "90": "z", + "91": "left-window-key", + "92": "right-window-key", + "93": "select-key", + "96": "numpad-0", + "97": "numpad-1", + "98": "numpad-2", + "99": "numpad-3", + "100": "numpad-4", + "101": "numpad-5", + "102": "numpad-6", + "103": "numpad-7", + "104": "numpad-8", + "105": "numpad-9", + "106": "multiply", + "107": "add", + "109": "subtract", + "110": "decimal-point", + "111": "divide", + "112": "f1", + "113": "f2", + "114": "f3", + "115": "f4", + "116": "f5", + "117": "f6", + "118": "f7", + "119": "f8", + "120": "f9", + "121": "f10", + "122": "f11", + "123": "f12", + "144": "num-lock", + "145": "scroll-lock", + "186": "semi-colon", + "187": "equal-sign", + "188": "comma", + "189": "dash", + "190": "period", + "191": "forward-slash", + "192": "grave-accent", + "219": "open-bracket", + "220": "back-slash", + "221": "close-braket", + "222": "single-quote" +} diff --git a/tests/lib/rules/no-deprecated-v-on-number-modifiers.js b/tests/lib/rules/no-deprecated-v-on-number-modifiers.js new file mode 100644 index 000000000..8c6d72698 --- /dev/null +++ b/tests/lib/rules/no-deprecated-v-on-number-modifiers.js @@ -0,0 +1,174 @@ +/** + * @fileoverview disallow using deprecated number (keyCodes) modifiers + * @author yoyo930021 + */ +'use strict' + +// ------------------------------------------------------------------------------ +// Requirements +// ------------------------------------------------------------------------------ + +const rule = require('../../../lib/rules/no-deprecated-v-on-number-modifiers') +const RuleTester = require('eslint').RuleTester + +// ------------------------------------------------------------------------------ +// Tests +// ------------------------------------------------------------------------------ + +const ruleTester = new RuleTester({ + parser: require.resolve('vue-eslint-parser'), + parserOptions: { ecmaVersion: 2015 } +}) + +ruleTester.run('no-deprecated-v-bind-sync', rule, { + + valid: [ + { + filename: 'test.vue', + code: "" + }, + { + filename: 'test.vue', + code: "" + }, + { + filename: 'test.vue', + code: "" + }, + { + filename: 'test.vue', + code: "" + }, + { + filename: 'test.vue', + code: "" + }, + { + filename: 'test.vue', + code: "" + }, + { + filename: 'test.vue', + code: "" + }, + { + filename: 'test.vue', + code: "" + }, + { + filename: 'test.vue', + code: "" + }, + { + filename: 'test.vue', + code: "" + }, + { + filename: 'test.vue', + code: "" + }, + { + filename: 'test.vue', + code: "" + } + ], + + invalid: [ + { + filename: 'test.vue', + code: "", + output: "", + errors: ["'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead."] + }, + { + filename: 'test.vue', + code: "", + output: "", + errors: ["'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead."] + }, + { + filename: 'test.vue', + code: "", + output: "", + errors: ["'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead."] + }, + { + filename: 'test.vue', + code: "", + output: "", + errors: ["'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead."] + }, + { + filename: 'test.vue', + code: "", + output: "", + errors: ["'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead."] + }, + { + filename: 'test.vue', + code: "", + output: "", + errors: ["'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead."] + }, + { + filename: 'test.vue', + code: "", + output: "", + errors: ["'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead."] + }, + { + filename: 'test.vue', + code: "", + output: "", + errors: ["'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead."] + }, + { + filename: 'test.vue', + code: "", + output: "", + errors: ["'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead."] + }, + { + filename: 'test.vue', + code: "", + output: "", + errors: ["'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead."] + }, + { + filename: 'test.vue', + code: "", + output: "", + errors: ["'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead."] + }, + { + filename: 'test.vue', + code: "", + output: "", + errors: ["'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead."] + }, + { + filename: 'test.vue', + code: "", + output: null, + errors: ["'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead."] + }, + { + filename: 'test.vue', + code: "", + output: null, + errors: ["'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead."] + }, + { + filename: 'test.vue', + code: "", + output: null, + errors: ["'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead."] + }, + { + filename: 'test.vue', + code: "", + output: null, + errors: ["'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead."] + } + ] +})