Repository: vuejs/eslint-plugin-vue
Pull request #937 (2019-08-02 10:40:27)

Fix: typo in valid-v-else rule


Patch:
diff --git a/docs/rules/attributes-order.md b/docs/rules/attributes-order.md
index 2f41dfa6..8c61d368 100644
--- a/docs/rules/attributes-order.md
+++ b/docs/rules/attributes-order.md
@@ -15,27 +15,27 @@ description: enforce order of attributes
 This rule aims to enforce ordering of component attributes. The default order is specified in the [Vue styleguide](https://vuejs.org/v2/style-guide/#Element-attribute-order-recommended) and is:
 
 - `DEFINITION`
-  ex: 'is'
+  e.g. 'is'
 - `LIST_RENDERING`
-  ex: 'v-for item in items'
+  e.g. 'v-for item in items'
 - `CONDITIONALS`
-  ex: 'v-if', 'v-else-if', 'v-else', 'v-show', 'v-cloak'
+  e.g. 'v-if', 'v-else-if', 'v-else', 'v-show', 'v-cloak'
 - `RENDER_MODIFIERS`
-  ex: 'v-once', 'v-pre'
+  e.g. 'v-once', 'v-pre'
 - `GLOBAL`
-  ex: 'id'
+  e.g. 'id'
 - `UNIQUE`
-  ex: 'ref', 'key', 'v-slot', 'slot'
+  e.g. 'ref', 'key', 'v-slot', 'slot'
 - `TWO_WAY_BINDING`
-  ex: 'v-model'
+  e.g. 'v-model'
 - `OTHER_DIRECTIVES`
-  ex: 'v-custom-directive'
+  e.g. 'v-custom-directive'
 - `OTHER_ATTR`
-  ex: 'custom-prop="foo"', 'v-bind:prop="foo"', ':prop="foo"'
+  e.g. 'custom-prop="foo"', 'v-bind:prop="foo"', ':prop="foo"'
 - `EVENTS`
-  ex: '@click="functionCall"', 'v-on="event"'
+  e.g. '@click="functionCall"', 'v-on="event"'
 - `CONTENT`
-  ex: 'v-text', 'v-html'
+  e.g. 'v-text', 'v-html'
 
 ### the default order
 
@@ -96,14 +96,14 @@ This rule aims to enforce ordering of component attributes. The default order is
     "order": [
       "DEFINITION",
       "LIST_RENDERING",
-      "CONDITIONALS", 
+      "CONDITIONALS",
       "RENDER_MODIFIERS",
-      "GLOBAL", 
-      "UNIQUE", 
-      "TWO_WAY_BINDING", 
-      "OTHER_DIRECTIVES", 
-      "OTHER_ATTR", 
-      "EVENTS", 
+      "GLOBAL",
+      "UNIQUE",
+      "TWO_WAY_BINDING",
+      "OTHER_DIRECTIVES",
+      "OTHER_ATTR",
+      "EVENTS",
       "CONTENT"
     ]
   }]
diff --git a/lib/rules/use-v-on-exact.js b/lib/rules/use-v-on-exact.js
index bf194fd8..29862b84 100644
--- a/lib/rules/use-v-on-exact.js
+++ b/lib/rules/use-v-on-exact.js
@@ -11,6 +11,7 @@
 const utils = require('../utils')
 
 const SYSTEM_MODIFIERS = new Set(['ctrl', 'shift', 'alt', 'meta'])
+const GLOBAL_MODIFIERS = new Set(['stop', 'prevent', 'capture', 'self', 'once', 'passive', 'native'])
 
 // ------------------------------------------------------------------------------
 // Helpers
@@ -36,6 +37,16 @@ function getEventDirectives (attributes, sourceCode) {
     }))
 }
 
+/**
+ * Checks whether given modifier is key modifier
+ *
+ * @param {string} modifier
+ * @returns {boolean}
+ */
+function isKeyModifier (modifier) {
+  return !GLOBAL_MODIFIERS.has(modifier) && !SYSTEM_MODIFIERS.has(modifier)
+}
+
 /**
  * Checks whether given modifier is system one
  *
@@ -86,6 +97,16 @@ function getSystemModifiersString (modifiers) {
   return modifiers.filter(isSystemModifier).sort().join(',')
 }
 
+/**
+ * Creates alphabetically sorted string with key modifiers
+ *
+ * @param {array[string]} modifiers
+ * @returns {string} e.g. "enter,tab"
+ */
+function getKeyModifiersString (modifiers) {
+  return modifiers.filter(isKeyModifier).sort().join(',')
+}
+
 /**
  * Compares two events based on their modifiers
  * to detect possible event leakeage
@@ -100,13 +121,21 @@ function hasConflictedModifiers (baseEvent, event) {
     event.modifiers.includes('exact')
   ) return false
 
-  const eventModifiers = getSystemModifiersString(event.modifiers)
-  const baseEventModifiers = getSystemModifiersString(baseEvent.modifiers)
+  const eventKeyModifiers = getKeyModifiersString(event.modifiers)
+  const baseEventKeyModifiers = getKeyModifiersString(baseEvent.modifiers)
+
+  if (
+    eventKeyModifiers && baseEventKeyModifiers &&
+    eventKeyModifiers !== baseEventKeyModifiers
+  ) return false
+
+  const eventSystemModifiers = getSystemModifiersString(event.modifiers)
+  const baseEventSystemModifiers = getSystemModifiersString(baseEvent.modifiers)
 
   return (
     baseEvent.modifiers.length >= 1 &&
-    baseEventModifiers !== eventModifiers &&
-    baseEventModifiers.indexOf(eventModifiers) > -1
+    baseEventSystemModifiers !== eventSystemModifiers &&
+    baseEventSystemModifiers.indexOf(eventSystemModifiers) > -1
   )
 }
 
diff --git a/lib/rules/valid-v-else.js b/lib/rules/valid-v-else.js
index e5412237..b0a09cb2 100644
--- a/lib/rules/valid-v-else.js
+++ b/lib/rules/valid-v-else.js
@@ -36,7 +36,7 @@ module.exports = {
           context.report({
             node,
             loc: node.loc,
-            message: "'v-else' directives require being preceded by the element which has a 'v-if' or 'v-else' directive."
+            message: "'v-else' directives require being preceded by the element which has a 'v-if' or 'v-else-if' directive."
           })
         }
         if (utils.hasDirective(element, 'if')) {


Test patch:
diff --git a/tests/lib/rules/use-v-on-exact.js b/tests/lib/rules/use-v-on-exact.js
index 6d994826..726662ca 100644
--- a/tests/lib/rules/use-v-on-exact.js
+++ b/tests/lib/rules/use-v-on-exact.js
@@ -158,6 +158,27 @@ ruleTester.run('use-v-on-exact', rule, {
     },
     {
       code: `<template><button @[foo]="foo" @[bar].ctrl="bar"/></template>`
+    },
+    {
+      code: `<template>
+        <input
+          @keydown.enter="foo"
+          @keydown.shift.tab="bar"/>
+      </template>`
+    },
+    {
+      code: `<template>
+        <input
+          @keydown.enter="foo"
+          @keydown.shift.tab.prevent="bar"/>
+      </template>`
+    },
+    {
+      code: `<template>
+        <input-component
+          @keydown.enter.native="foo"
+          @keydown.shift.tab.native="bar"/>
+      </template>`
     }
   ],
 
diff --git a/tests/lib/rules/valid-v-else.js b/tests/lib/rules/valid-v-else.js
index 7d112a8c..7825e4df 100644
--- a/tests/lib/rules/valid-v-else.js
+++ b/tests/lib/rules/valid-v-else.js
@@ -44,32 +44,32 @@ tester.run('valid-v-else', rule, {
     {
       filename: 'test.vue',
       code: '<template><template v-else><div></div></template></template>',
-      errors: ["'v-else' directives require being preceded by the element which has a 'v-if' or 'v-else' directive."]
+      errors: ["'v-else' directives require being preceded by the element which has a 'v-if' or 'v-else-if' directive."]
     },
     {
       filename: 'test.vue',
       code: '<template><div v-else></div></template>',
-      errors: ["'v-else' directives require being preceded by the element which has a 'v-if' or 'v-else' directive."]
+      errors: ["'v-else' directives require being preceded by the element which has a 'v-if' or 'v-else-if' directive."]
     },
     {
       filename: 'test.vue',
       code: '<template><div><div v-else></div></div></template>',
-      errors: ["'v-else' directives require being preceded by the element which has a 'v-if' or 'v-else' directive."]
+      errors: ["'v-else' directives require being preceded by the element which has a 'v-if' or 'v-else-if' directive."]
     },
     {
       filename: 'test.vue',
       code: '<template><div><div></div><div v-else></div></div></template>',
-      errors: ["'v-else' directives require being preceded by the element which has a 'v-if' or 'v-else' directive."]
+      errors: ["'v-else' directives require being preceded by the element which has a 'v-if' or 'v-else-if' directive."]
     },
     {
       filename: 'test.vue',
       code: '<template><div><div if="foo"></div><div v-else></div></div></template>',
-      errors: ["'v-else' directives require being preceded by the element which has a 'v-if' or 'v-else' directive."]
+      errors: ["'v-else' directives require being preceded by the element which has a 'v-if' or 'v-else-if' directive."]
     },
     {
       filename: 'test.vue',
       code: '<template><div><div v-if="foo"></div><div></div><div v-else></div></div></template>',
-      errors: ["'v-else' directives require being preceded by the element which has a 'v-if' or 'v-else' directive."]
+      errors: ["'v-else' directives require being preceded by the element which has a 'v-if' or 'v-else-if' directive."]
     },
     {
       filename: 'test.vue',