From c91086a4dcf366bcef4c3f3c938d938f001018f7 Mon Sep 17 00:00:00 2001
From: waynzh <waynzh19@gmail.com>
Date: Sat, 16 Nov 2024 12:51:20 +0800
Subject: [PATCH 01/12] feat: add exclude tags option

---
 lib/rules/attribute-hyphenation.js        | 23 ++++++++++++++--
 lib/rules/v-on-event-hyphenation.js       | 26 +++++++++++++++++-
 tests/lib/rules/attribute-hyphenation.js  | 32 ++++++++++++++++++++++
 tests/lib/rules/v-on-event-hyphenation.js | 33 +++++++++++++++++++++++
 4 files changed, 111 insertions(+), 3 deletions(-)

diff --git a/lib/rules/attribute-hyphenation.js b/lib/rules/attribute-hyphenation.js
index 35519d231..bcd6bad0c 100644
--- a/lib/rules/attribute-hyphenation.js
+++ b/lib/rules/attribute-hyphenation.js
@@ -6,6 +6,7 @@
 
 const utils = require('../utils')
 const casing = require('../utils/casing')
+const { toRegExp } = require('../utils/regexp')
 const svgAttributes = require('../utils/svg-attributes-weird-case.json')
 
 /**
@@ -56,6 +57,12 @@ module.exports = {
             },
             uniqueItems: true,
             additionalItems: false
+          },
+          exclude: {
+            type: 'array',
+            items: { type: 'string' },
+            uniqueItems: true,
+            additionalItems: false
           }
         },
         additionalProperties: false
@@ -72,6 +79,10 @@ module.exports = {
     const option = context.options[0]
     const optionsPayload = context.options[1]
     const useHyphenated = option !== 'never'
+    /** @type {RegExp[]} */
+    const excludedTags = ((optionsPayload && optionsPayload.exclude) || []).map(
+      toRegExp
+    )
     const ignoredAttributes = ['data-', 'aria-', 'slot-scope', ...svgAttributes]
 
     if (optionsPayload && optionsPayload.ignore) {
@@ -130,11 +141,19 @@ module.exports = {
       return useHyphenated ? value.toLowerCase() === value : !/-/.test(value)
     }
 
+    /**
+     * @param {string} name
+     */
+    function isExcludedTags(name) {
+      return excludedTags.some((re) => re.test(name))
+    }
+
     return utils.defineTemplateBodyVisitor(context, {
       VAttribute(node) {
+        const element = node.parent.parent
         if (
-          !utils.isCustomComponent(node.parent.parent) &&
-          node.parent.parent.name !== 'slot'
+          (!utils.isCustomComponent(element) && element.name !== 'slot') ||
+          isExcludedTags(element.rawName)
         )
           return
 
diff --git a/lib/rules/v-on-event-hyphenation.js b/lib/rules/v-on-event-hyphenation.js
index f99a45fdc..5be579576 100644
--- a/lib/rules/v-on-event-hyphenation.js
+++ b/lib/rules/v-on-event-hyphenation.js
@@ -2,6 +2,7 @@
 
 const utils = require('../utils')
 const casing = require('../utils/casing')
+const { toRegExp } = require('../utils/regexp')
 
 module.exports = {
   meta: {
@@ -35,6 +36,12 @@ module.exports = {
             },
             uniqueItems: true,
             additionalItems: false
+          },
+          exclude: {
+            type: 'array',
+            items: { type: 'string' },
+            uniqueItems: true,
+            additionalItems: false
           }
         },
         additionalProperties: false
@@ -56,6 +63,10 @@ module.exports = {
     const useHyphenated = option !== 'never'
     /** @type {string[]} */
     const ignoredAttributes = (optionsPayload && optionsPayload.ignore) || []
+    /** @type {RegExp[]} */
+    const excludedTags = ((optionsPayload && optionsPayload.exclude) || []).map(
+      toRegExp
+    )
     const autofix = Boolean(optionsPayload && optionsPayload.autofix)
 
     const caseConverter = casing.getConverter(
@@ -99,9 +110,22 @@ module.exports = {
       return useHyphenated ? value.toLowerCase() === value : !/-/.test(value)
     }
 
+    /**
+     * @param {string} name
+     */
+    function isExcludedTags(name) {
+      return excludedTags.some((re) => re.test(name))
+    }
+
     return utils.defineTemplateBodyVisitor(context, {
       "VAttribute[directive=true][key.name.name='on']"(node) {
-        if (!utils.isCustomComponent(node.parent.parent)) return
+        const element = node.parent.parent
+        if (
+          !utils.isCustomComponent(element) ||
+          isExcludedTags(element.rawName)
+        ) {
+          return
+        }
         if (!node.key.argument || node.key.argument.type !== 'VIdentifier') {
           return
         }
diff --git a/tests/lib/rules/attribute-hyphenation.js b/tests/lib/rules/attribute-hyphenation.js
index 18d60e19c..e8912c867 100644
--- a/tests/lib/rules/attribute-hyphenation.js
+++ b/tests/lib/rules/attribute-hyphenation.js
@@ -85,6 +85,16 @@ ruleTester.run('attribute-hyphenation', rule, {
       filename: 'test.vue',
       code: '<template><div><custom :myName.sync="prop"></custom></div></template>',
       options: ['never']
+    },
+    {
+      filename: 'test.vue',
+      code: `
+      <template>
+        <VueComponent my-prop></VueComponent>
+        <custom-component my-prop></custom-component>
+      </template>
+      `,
+      options: ['never', { exclude: ['VueComponent', '/^custom-/'] }]
     }
   ],
 
@@ -450,6 +460,28 @@ ruleTester.run('attribute-hyphenation', rule, {
           line: 1
         }
       ]
+    },
+    {
+      code: `
+      <template>
+        <custom my-prop/>
+        <CustomComponent my-prop/>
+      </template>
+      `,
+      output: `
+      <template>
+        <custom myProp/>
+        <CustomComponent my-prop/>
+      </template>
+      `,
+      options: ['never', { exclude: ['CustomComponent'] }],
+      errors: [
+        {
+          message: "Attribute 'my-prop' can't be hyphenated.",
+          type: 'VIdentifier',
+          line: 3
+        }
+      ]
     }
   ]
 })
diff --git a/tests/lib/rules/v-on-event-hyphenation.js b/tests/lib/rules/v-on-event-hyphenation.js
index 54d2ec435..9d548c76d 100644
--- a/tests/lib/rules/v-on-event-hyphenation.js
+++ b/tests/lib/rules/v-on-event-hyphenation.js
@@ -44,6 +44,23 @@ tester.run('v-on-event-hyphenation', rule, {
       </template>
       `,
       options: ['never', { ignore: ['custom'] }]
+    },
+    {
+      code: `
+      <template>
+          <VueComponent v-on:custom-event="events"/>
+      </template>
+      `,
+      options: ['never', { ignore: ['custom-event'] }]
+    },
+    {
+      code: `
+      <template>
+          <VueComponent v-on:custom-event="events"/>
+          <custom-component v-on:custom-event="events"/>
+      </template>
+      `,
+      options: ['never', { exclude: ['/^Vue/', 'custom-component'] }]
     }
   ],
   invalid: [
@@ -179,6 +196,22 @@ tester.run('v-on-event-hyphenation', rule, {
         "v-on event '@upDate:model-value' can't be hyphenated.",
         "v-on event '@up-date:model-value' can't be hyphenated."
       ]
+    },
+    {
+      code: `
+      <template>
+        <VueComponent v-on:custom-event="events"/>
+        <CustomComponent v-on:custom-event="events"/>
+      </template>
+      `,
+      output: `
+      <template>
+        <VueComponent v-on:customEvent="events"/>
+        <CustomComponent v-on:custom-event="events"/>
+      </template>
+      `,
+      options: ['never', { autofix: true, exclude: ['CustomComponent'] }],
+      errors: ["v-on event 'v-on:custom-event' can't be hyphenated."]
     }
   ]
 })

From 254e4c537bfb481c24597055b3ac3ea38c6dccf7 Mon Sep 17 00:00:00 2001
From: waynzh <waynzh19@gmail.com>
Date: Sat, 16 Nov 2024 13:53:20 +0800
Subject: [PATCH 02/12] docs: update

---
 docs/rules/attribute-hyphenation.md  | 24 ++++++++++++++++++++++--
 docs/rules/v-on-event-hyphenation.md | 24 ++++++++++++++++++++++--
 2 files changed, 44 insertions(+), 4 deletions(-)

diff --git a/docs/rules/attribute-hyphenation.md b/docs/rules/attribute-hyphenation.md
index d5fba2e31..33b2bc675 100644
--- a/docs/rules/attribute-hyphenation.md
+++ b/docs/rules/attribute-hyphenation.md
@@ -36,7 +36,8 @@ This rule enforces using hyphenated attribute names on custom components in Vue
 ```json
 {
   "vue/attribute-hyphenation": ["error", "always" | "never", {
-    "ignore": []
+    "ignore": [],
+    "exclude": []
   }]
 }
 ```
@@ -46,7 +47,8 @@ and all the [SVG attributes](https://developer.mozilla.org/en-US/docs/Web/SVG/At
 
 - `"always"` (default) ... Use hyphenated name.
 - `"never"` ... Don't use hyphenated name except the ones that are ignored.
-- `"ignore"` ... Array of ignored names
+- `"ignore"` ... Array of ignored names.
+- `"exclude"` ... Array of exclude tag names.
 
 ### `"always"`
 
@@ -109,6 +111,24 @@ Don't use hyphenated name but allow custom attributes
 
 </eslint-code-block>
 
+### `"never", { "exclude": ["/^custom-/"] }`
+
+Exclude tags from applying this rule.
+
+<eslint-code-block fix :rules="{'vue/attribute-hyphenation': ['error', 'never', { exclude: ['/^custom-/'] }]}">
+
+```vue
+<template>
+  <!-- ✓ GOOD -->
+  <custom-component custom-prop="prop" />
+
+  <!-- ✗ BAD -->
+  <my-component custom-prop="prop" />
+</template>
+```
+
+</eslint-code-block>
+
 ## :couple: Related Rules
 
 - [vue/v-on-event-hyphenation](./v-on-event-hyphenation.md)
diff --git a/docs/rules/v-on-event-hyphenation.md b/docs/rules/v-on-event-hyphenation.md
index 811b37437..354abe698 100644
--- a/docs/rules/v-on-event-hyphenation.md
+++ b/docs/rules/v-on-event-hyphenation.md
@@ -39,14 +39,16 @@ This rule enforces using hyphenated v-on event names on custom components in Vue
 {
   "vue/v-on-event-hyphenation": ["error", "always" | "never", {
     "autofix": false,
-    "ignore": []
+    "ignore": [],
+    "exclude": []
   }]
 }
 ```
 
 - `"always"` (default) ... Use hyphenated name.
 - `"never"` ... Don't use hyphenated name.
-- `"ignore"` ... Array of ignored names
+- `"ignore"` ... Array of ignored names.
+- `"exclude"` ... Array of exclude tag names.
 - `"autofix"` ... If `true`, enable autofix. If you are using Vue 2, we recommend that you do not use it due to its side effects.
 
 ### `"always"`
@@ -104,6 +106,24 @@ Don't use hyphenated name but allow custom event names
 
 </eslint-code-block>
 
+### `"never", { "exclude": ["/^custom-/"] }`
+
+Exclude tags from applying this rule.
+
+<eslint-code-block fix :rules="{'vue/v-on-event-hyphenation': ['error', 'never', { exclude: ['/^custom-/'], autofix: true }]}">
+
+```vue
+<template>
+  <!-- ✓ GOOD -->
+  <custom-component v-on:custom-event="handleEvent" />
+
+  <!-- ✗ BAD -->
+  <my-component v-on:custom-event="handleEvent" />
+</template>
+```
+
+</eslint-code-block>
+
 ## :couple: Related Rules
 
 - [vue/custom-event-name-casing](./custom-event-name-casing.md)

From ddbdd83c7b353e7ca48a2f8a041224145b39a577 Mon Sep 17 00:00:00 2001
From: waynzh <waynzh19@gmail.com>
Date: Wed, 20 Nov 2024 00:09:24 +0800
Subject: [PATCH 03/12] refactor: rename

---
 docs/rules/attribute-hyphenation.md       | 10 +++++-----
 docs/rules/v-on-event-hyphenation.md      | 10 +++++-----
 lib/rules/attribute-hyphenation.js        | 15 ++++++++-------
 lib/rules/v-on-event-hyphenation.js       | 15 ++++++++-------
 tests/lib/rules/attribute-hyphenation.js  |  7 ++++---
 tests/lib/rules/v-on-event-hyphenation.js | 12 +++++++++---
 6 files changed, 39 insertions(+), 30 deletions(-)

diff --git a/docs/rules/attribute-hyphenation.md b/docs/rules/attribute-hyphenation.md
index 33b2bc675..78e94b88a 100644
--- a/docs/rules/attribute-hyphenation.md
+++ b/docs/rules/attribute-hyphenation.md
@@ -37,7 +37,7 @@ This rule enforces using hyphenated attribute names on custom components in Vue
 {
   "vue/attribute-hyphenation": ["error", "always" | "never", {
     "ignore": [],
-    "exclude": []
+    "ignoreTags": []
   }]
 }
 ```
@@ -48,7 +48,7 @@ and all the [SVG attributes](https://developer.mozilla.org/en-US/docs/Web/SVG/At
 - `"always"` (default) ... Use hyphenated name.
 - `"never"` ... Don't use hyphenated name except the ones that are ignored.
 - `"ignore"` ... Array of ignored names.
-- `"exclude"` ... Array of exclude tag names.
+- `"ignoreTags"` ... Array of exclude tag names.
 
 ### `"always"`
 
@@ -111,11 +111,11 @@ Don't use hyphenated name but allow custom attributes
 
 </eslint-code-block>
 
-### `"never", { "exclude": ["/^custom-/"] }`
+### `"never", { "ignoreTags": ["/^custom-/"] }`
 
-Exclude tags from applying this rule.
+Ignore tags from applying this rule.
 
-<eslint-code-block fix :rules="{'vue/attribute-hyphenation': ['error', 'never', { exclude: ['/^custom-/'] }]}">
+<eslint-code-block fix :rules="{'vue/attribute-hyphenation': ['error', 'never', { ignoreTags: ['/^custom-/'] }]}">
 
 ```vue
 <template>
diff --git a/docs/rules/v-on-event-hyphenation.md b/docs/rules/v-on-event-hyphenation.md
index 354abe698..6dbfd4498 100644
--- a/docs/rules/v-on-event-hyphenation.md
+++ b/docs/rules/v-on-event-hyphenation.md
@@ -40,7 +40,7 @@ This rule enforces using hyphenated v-on event names on custom components in Vue
   "vue/v-on-event-hyphenation": ["error", "always" | "never", {
     "autofix": false,
     "ignore": [],
-    "exclude": []
+    "ignoreTags": []
   }]
 }
 ```
@@ -48,7 +48,7 @@ This rule enforces using hyphenated v-on event names on custom components in Vue
 - `"always"` (default) ... Use hyphenated name.
 - `"never"` ... Don't use hyphenated name.
 - `"ignore"` ... Array of ignored names.
-- `"exclude"` ... Array of exclude tag names.
+- `"ignoreTags"` ... Array of exclude tag names.
 - `"autofix"` ... If `true`, enable autofix. If you are using Vue 2, we recommend that you do not use it due to its side effects.
 
 ### `"always"`
@@ -106,11 +106,11 @@ Don't use hyphenated name but allow custom event names
 
 </eslint-code-block>
 
-### `"never", { "exclude": ["/^custom-/"] }`
+### `"never", { "ignoreTags": ["/^custom-/"] }`
 
-Exclude tags from applying this rule.
+Ignore tags from applying this rule.
 
-<eslint-code-block fix :rules="{'vue/v-on-event-hyphenation': ['error', 'never', { exclude: ['/^custom-/'], autofix: true }]}">
+<eslint-code-block fix :rules="{'vue/v-on-event-hyphenation': ['error', 'never', { ignoreTags: ['/^custom-/'], autofix: true }]}">
 
 ```vue
 <template>
diff --git a/lib/rules/attribute-hyphenation.js b/lib/rules/attribute-hyphenation.js
index bcd6bad0c..37d45c938 100644
--- a/lib/rules/attribute-hyphenation.js
+++ b/lib/rules/attribute-hyphenation.js
@@ -58,7 +58,7 @@ module.exports = {
             uniqueItems: true,
             additionalItems: false
           },
-          exclude: {
+          ignoreTags: {
             type: 'array',
             items: { type: 'string' },
             uniqueItems: true,
@@ -80,9 +80,10 @@ module.exports = {
     const optionsPayload = context.options[1]
     const useHyphenated = option !== 'never'
     /** @type {RegExp[]} */
-    const excludedTags = ((optionsPayload && optionsPayload.exclude) || []).map(
-      toRegExp
-    )
+    const ignoreTags = (
+      (optionsPayload && optionsPayload.ignoreTags) ||
+      []
+    ).map(toRegExp)
     const ignoredAttributes = ['data-', 'aria-', 'slot-scope', ...svgAttributes]
 
     if (optionsPayload && optionsPayload.ignore) {
@@ -144,8 +145,8 @@ module.exports = {
     /**
      * @param {string} name
      */
-    function isExcludedTags(name) {
-      return excludedTags.some((re) => re.test(name))
+    function isIgnoredTags(name) {
+      return ignoreTags.some((re) => re.test(name))
     }
 
     return utils.defineTemplateBodyVisitor(context, {
@@ -153,7 +154,7 @@ module.exports = {
         const element = node.parent.parent
         if (
           (!utils.isCustomComponent(element) && element.name !== 'slot') ||
-          isExcludedTags(element.rawName)
+          isIgnoredTags(element.rawName)
         )
           return
 
diff --git a/lib/rules/v-on-event-hyphenation.js b/lib/rules/v-on-event-hyphenation.js
index 5be579576..84d65ade4 100644
--- a/lib/rules/v-on-event-hyphenation.js
+++ b/lib/rules/v-on-event-hyphenation.js
@@ -37,7 +37,7 @@ module.exports = {
             uniqueItems: true,
             additionalItems: false
           },
-          exclude: {
+          ignoreTags: {
             type: 'array',
             items: { type: 'string' },
             uniqueItems: true,
@@ -64,9 +64,10 @@ module.exports = {
     /** @type {string[]} */
     const ignoredAttributes = (optionsPayload && optionsPayload.ignore) || []
     /** @type {RegExp[]} */
-    const excludedTags = ((optionsPayload && optionsPayload.exclude) || []).map(
-      toRegExp
-    )
+    const ignoreTags = (
+      (optionsPayload && optionsPayload.ignoreTags) ||
+      []
+    ).map(toRegExp)
     const autofix = Boolean(optionsPayload && optionsPayload.autofix)
 
     const caseConverter = casing.getConverter(
@@ -113,8 +114,8 @@ module.exports = {
     /**
      * @param {string} name
      */
-    function isExcludedTags(name) {
-      return excludedTags.some((re) => re.test(name))
+    function isIgnoreTags(name) {
+      return ignoreTags.some((re) => re.test(name))
     }
 
     return utils.defineTemplateBodyVisitor(context, {
@@ -122,7 +123,7 @@ module.exports = {
         const element = node.parent.parent
         if (
           !utils.isCustomComponent(element) ||
-          isExcludedTags(element.rawName)
+          isIgnoreTags(element.rawName)
         ) {
           return
         }
diff --git a/tests/lib/rules/attribute-hyphenation.js b/tests/lib/rules/attribute-hyphenation.js
index e8912c867..d0cf4185d 100644
--- a/tests/lib/rules/attribute-hyphenation.js
+++ b/tests/lib/rules/attribute-hyphenation.js
@@ -94,7 +94,7 @@ ruleTester.run('attribute-hyphenation', rule, {
         <custom-component my-prop></custom-component>
       </template>
       `,
-      options: ['never', { exclude: ['VueComponent', '/^custom-/'] }]
+      options: ['never', { ignoreTags: ['VueComponent', '/^custom-/'] }]
     }
   ],
 
@@ -474,12 +474,13 @@ ruleTester.run('attribute-hyphenation', rule, {
         <CustomComponent my-prop/>
       </template>
       `,
-      options: ['never', { exclude: ['CustomComponent'] }],
+      options: ['never', { ignoreTags: ['CustomComponent'] }],
       errors: [
         {
           message: "Attribute 'my-prop' can't be hyphenated.",
           type: 'VIdentifier',
-          line: 3
+          line: 3,
+          column: 17
         }
       ]
     }
diff --git a/tests/lib/rules/v-on-event-hyphenation.js b/tests/lib/rules/v-on-event-hyphenation.js
index 9d548c76d..8b7374682 100644
--- a/tests/lib/rules/v-on-event-hyphenation.js
+++ b/tests/lib/rules/v-on-event-hyphenation.js
@@ -60,7 +60,7 @@ tester.run('v-on-event-hyphenation', rule, {
           <custom-component v-on:custom-event="events"/>
       </template>
       `,
-      options: ['never', { exclude: ['/^Vue/', 'custom-component'] }]
+      options: ['never', { ignoreTags: ['/^Vue/', 'custom-component'] }]
     }
   ],
   invalid: [
@@ -210,8 +210,14 @@ tester.run('v-on-event-hyphenation', rule, {
         <CustomComponent v-on:custom-event="events"/>
       </template>
       `,
-      options: ['never', { autofix: true, exclude: ['CustomComponent'] }],
-      errors: ["v-on event 'v-on:custom-event' can't be hyphenated."]
+      options: ['never', { autofix: true, ignoreTags: ['CustomComponent'] }],
+      errors: [
+        {
+          message: "v-on event 'v-on:custom-event' can't be hyphenated.",
+          line: 3,
+          column: 23
+        }
+      ]
     }
   ]
 })

From 300b438eed30db18ee2f24f046c7f5c59c743abd Mon Sep 17 00:00:00 2001
From: Wayne Zhang <zhanghaowei19W@gmail.com>
Date: Wed, 20 Nov 2024 10:22:03 +0800
Subject: [PATCH 04/12] Update docs/rules/attribute-hyphenation.md

Co-authored-by: Flo Edelmann <git@flo-edelmann.de>
---
 docs/rules/attribute-hyphenation.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/docs/rules/attribute-hyphenation.md b/docs/rules/attribute-hyphenation.md
index 78e94b88a..74b1d647e 100644
--- a/docs/rules/attribute-hyphenation.md
+++ b/docs/rules/attribute-hyphenation.md
@@ -45,8 +45,8 @@ This rule enforces using hyphenated attribute names on custom components in Vue
 Default casing is set to `always`. By default the following attributes are ignored: `data-`, `aria-`, `slot-scope`,
 and all the [SVG attributes](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute) with either an upper case letter or an hyphen.
 
-- `"always"` (default) ... Use hyphenated name.
-- `"never"` ... Don't use hyphenated name except the ones that are ignored.
+- `"always"` (default) ... Use hyphenated attribute name.
+- `"never"` ... Don't use hyphenated attribute name.
 - `"ignore"` ... Array of ignored names.
 - `"ignoreTags"` ... Array of exclude tag names.
 

From a5e78cb7a30ddd6dd6114ee13d2368fbf4ee4c75 Mon Sep 17 00:00:00 2001
From: Wayne Zhang <zhanghaowei19W@gmail.com>
Date: Wed, 20 Nov 2024 10:22:20 +0800
Subject: [PATCH 05/12] Update docs/rules/attribute-hyphenation.md

Co-authored-by: Flo Edelmann <git@flo-edelmann.de>
---
 docs/rules/attribute-hyphenation.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/docs/rules/attribute-hyphenation.md b/docs/rules/attribute-hyphenation.md
index 74b1d647e..632896235 100644
--- a/docs/rules/attribute-hyphenation.md
+++ b/docs/rules/attribute-hyphenation.md
@@ -47,8 +47,8 @@ and all the [SVG attributes](https://developer.mozilla.org/en-US/docs/Web/SVG/At
 
 - `"always"` (default) ... Use hyphenated attribute name.
 - `"never"` ... Don't use hyphenated attribute name.
-- `"ignore"` ... Array of ignored names.
-- `"ignoreTags"` ... Array of exclude tag names.
+- `"ignore"` ... Array of attribute names that don't need to follow the specified casing.
+- `"ignoreTags"` ... Array of tag names whose attributes don't need to follow the specified casing.
 
 ### `"always"`
 

From c0edcfc962e4abccd30bf820b242db8fd8a590d4 Mon Sep 17 00:00:00 2001
From: Wayne Zhang <zhanghaowei19W@gmail.com>
Date: Wed, 20 Nov 2024 10:22:35 +0800
Subject: [PATCH 06/12] Update docs/rules/attribute-hyphenation.md

Co-authored-by: Flo Edelmann <git@flo-edelmann.de>
---
 docs/rules/attribute-hyphenation.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/docs/rules/attribute-hyphenation.md b/docs/rules/attribute-hyphenation.md
index 632896235..9661b2f30 100644
--- a/docs/rules/attribute-hyphenation.md
+++ b/docs/rules/attribute-hyphenation.md
@@ -120,10 +120,10 @@ Ignore tags from applying this rule.
 ```vue
 <template>
   <!-- ✓ GOOD -->
-  <custom-component custom-prop="prop" />
+  <custom-component my-prop="prop" />
 
   <!-- ✗ BAD -->
-  <my-component custom-prop="prop" />
+  <my-component my-prop="prop" />
 </template>
 ```
 

From 07ec4f52e707a239a5fb3110296bbcadf3d529ea Mon Sep 17 00:00:00 2001
From: Wayne Zhang <zhanghaowei19W@gmail.com>
Date: Wed, 20 Nov 2024 10:23:04 +0800
Subject: [PATCH 07/12] Update docs/rules/attribute-hyphenation.md

Co-authored-by: Flo Edelmann <git@flo-edelmann.de>
---
 docs/rules/attribute-hyphenation.md | 2 --
 1 file changed, 2 deletions(-)

diff --git a/docs/rules/attribute-hyphenation.md b/docs/rules/attribute-hyphenation.md
index 9661b2f30..89442fceb 100644
--- a/docs/rules/attribute-hyphenation.md
+++ b/docs/rules/attribute-hyphenation.md
@@ -113,8 +113,6 @@ Don't use hyphenated name but allow custom attributes
 
 ### `"never", { "ignoreTags": ["/^custom-/"] }`
 
-Ignore tags from applying this rule.
-
 <eslint-code-block fix :rules="{'vue/attribute-hyphenation': ['error', 'never', { ignoreTags: ['/^custom-/'] }]}">
 
 ```vue

From 37e7a7ebb352d06a787297d2d7ba5b7c6fa302f0 Mon Sep 17 00:00:00 2001
From: Wayne Zhang <zhanghaowei19W@gmail.com>
Date: Wed, 20 Nov 2024 10:23:15 +0800
Subject: [PATCH 08/12] Update docs/rules/v-on-event-hyphenation.md

Co-authored-by: Flo Edelmann <git@flo-edelmann.de>
---
 docs/rules/v-on-event-hyphenation.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/docs/rules/v-on-event-hyphenation.md b/docs/rules/v-on-event-hyphenation.md
index 6dbfd4498..2a15b81f7 100644
--- a/docs/rules/v-on-event-hyphenation.md
+++ b/docs/rules/v-on-event-hyphenation.md
@@ -45,8 +45,8 @@ This rule enforces using hyphenated v-on event names on custom components in Vue
 }
 ```
 
-- `"always"` (default) ... Use hyphenated name.
-- `"never"` ... Don't use hyphenated name.
+- `"always"` (default) ... Use hyphenated event name.
+- `"never"` ... Don't use hyphenated event name.
 - `"ignore"` ... Array of ignored names.
 - `"ignoreTags"` ... Array of exclude tag names.
 - `"autofix"` ... If `true`, enable autofix. If you are using Vue 2, we recommend that you do not use it due to its side effects.

From 988ef2f854a2195e97477bd2b3af38591a1adb3c Mon Sep 17 00:00:00 2001
From: Wayne Zhang <zhanghaowei19W@gmail.com>
Date: Wed, 20 Nov 2024 10:25:00 +0800
Subject: [PATCH 09/12] Update docs/rules/v-on-event-hyphenation.md

Co-authored-by: Flo Edelmann <git@flo-edelmann.de>
---
 docs/rules/v-on-event-hyphenation.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/docs/rules/v-on-event-hyphenation.md b/docs/rules/v-on-event-hyphenation.md
index 2a15b81f7..890eb9d4b 100644
--- a/docs/rules/v-on-event-hyphenation.md
+++ b/docs/rules/v-on-event-hyphenation.md
@@ -47,8 +47,8 @@ This rule enforces using hyphenated v-on event names on custom components in Vue
 
 - `"always"` (default) ... Use hyphenated event name.
 - `"never"` ... Don't use hyphenated event name.
-- `"ignore"` ... Array of ignored names.
-- `"ignoreTags"` ... Array of exclude tag names.
+- `"ignore"` ... Array of event names that don't need to follow the specified casing.
+- `"ignoreTags"` ... Array of tag names whose events don't need to follow the specified casing.
 - `"autofix"` ... If `true`, enable autofix. If you are using Vue 2, we recommend that you do not use it due to its side effects.
 
 ### `"always"`

From 914f52d492a30c30909a967d81e261525d48ad26 Mon Sep 17 00:00:00 2001
From: Wayne Zhang <zhanghaowei19W@gmail.com>
Date: Wed, 20 Nov 2024 10:26:46 +0800
Subject: [PATCH 10/12] Apply suggestions from code review

Co-authored-by: Flo Edelmann <git@flo-edelmann.de>
---
 docs/rules/v-on-event-hyphenation.md | 6 ++----
 lib/rules/attribute-hyphenation.js   | 4 +---
 lib/rules/v-on-event-hyphenation.js  | 4 +---
 3 files changed, 4 insertions(+), 10 deletions(-)

diff --git a/docs/rules/v-on-event-hyphenation.md b/docs/rules/v-on-event-hyphenation.md
index 890eb9d4b..493a9dac9 100644
--- a/docs/rules/v-on-event-hyphenation.md
+++ b/docs/rules/v-on-event-hyphenation.md
@@ -108,17 +108,15 @@ Don't use hyphenated name but allow custom event names
 
 ### `"never", { "ignoreTags": ["/^custom-/"] }`
 
-Ignore tags from applying this rule.
-
 <eslint-code-block fix :rules="{'vue/v-on-event-hyphenation': ['error', 'never', { ignoreTags: ['/^custom-/'], autofix: true }]}">
 
 ```vue
 <template>
   <!-- ✓ GOOD -->
-  <custom-component v-on:custom-event="handleEvent" />
+  <custom-component v-on:my-event="handleEvent" />
 
   <!-- ✗ BAD -->
-  <my-component v-on:custom-event="handleEvent" />
+  <my-component v-on:my-event="handleEvent" />
 </template>
 ```
 
diff --git a/lib/rules/attribute-hyphenation.js b/lib/rules/attribute-hyphenation.js
index 37d45c938..237701eb1 100644
--- a/lib/rules/attribute-hyphenation.js
+++ b/lib/rules/attribute-hyphenation.js
@@ -142,9 +142,7 @@ module.exports = {
       return useHyphenated ? value.toLowerCase() === value : !/-/.test(value)
     }
 
-    /**
-     * @param {string} name
-     */
+    /** @param {string} name */
     function isIgnoredTags(name) {
       return ignoreTags.some((re) => re.test(name))
     }
diff --git a/lib/rules/v-on-event-hyphenation.js b/lib/rules/v-on-event-hyphenation.js
index 84d65ade4..0187aac1b 100644
--- a/lib/rules/v-on-event-hyphenation.js
+++ b/lib/rules/v-on-event-hyphenation.js
@@ -111,9 +111,7 @@ module.exports = {
       return useHyphenated ? value.toLowerCase() === value : !/-/.test(value)
     }
 
-    /**
-     * @param {string} name
-     */
+    /** @param {string} name */
     function isIgnoreTags(name) {
       return ignoreTags.some((re) => re.test(name))
     }

From 262480951e6d797660be469ef48c6258dc0fef7e Mon Sep 17 00:00:00 2001
From: waynzh <waynzh19@gmail.com>
Date: Wed, 20 Nov 2024 10:39:29 +0800
Subject: [PATCH 11/12] feat: add test cases

---
 lib/rules/attribute-hyphenation.js        |  4 +--
 lib/rules/v-on-event-hyphenation.js       |  4 +--
 tests/lib/rules/attribute-hyphenation.js  | 33 +++++++++++++++++++++++
 tests/lib/rules/v-on-event-hyphenation.js | 31 +++++++++++++++++++++
 4 files changed, 68 insertions(+), 4 deletions(-)

diff --git a/lib/rules/attribute-hyphenation.js b/lib/rules/attribute-hyphenation.js
index 237701eb1..23bb16dae 100644
--- a/lib/rules/attribute-hyphenation.js
+++ b/lib/rules/attribute-hyphenation.js
@@ -143,7 +143,7 @@ module.exports = {
     }
 
     /** @param {string} name */
-    function isIgnoredTags(name) {
+    function isIgnoredTagName(name) {
       return ignoreTags.some((re) => re.test(name))
     }
 
@@ -152,7 +152,7 @@ module.exports = {
         const element = node.parent.parent
         if (
           (!utils.isCustomComponent(element) && element.name !== 'slot') ||
-          isIgnoredTags(element.rawName)
+          isIgnoredTagName(element.rawName)
         )
           return
 
diff --git a/lib/rules/v-on-event-hyphenation.js b/lib/rules/v-on-event-hyphenation.js
index 0187aac1b..3fbf5314c 100644
--- a/lib/rules/v-on-event-hyphenation.js
+++ b/lib/rules/v-on-event-hyphenation.js
@@ -112,7 +112,7 @@ module.exports = {
     }
 
     /** @param {string} name */
-    function isIgnoreTags(name) {
+    function isIgnoredTagName(name) {
       return ignoreTags.some((re) => re.test(name))
     }
 
@@ -121,7 +121,7 @@ module.exports = {
         const element = node.parent.parent
         if (
           !utils.isCustomComponent(element) ||
-          isIgnoreTags(element.rawName)
+          isIgnoredTagName(element.rawName)
         ) {
           return
         }
diff --git a/tests/lib/rules/attribute-hyphenation.js b/tests/lib/rules/attribute-hyphenation.js
index d0cf4185d..738d59ae9 100644
--- a/tests/lib/rules/attribute-hyphenation.js
+++ b/tests/lib/rules/attribute-hyphenation.js
@@ -95,6 +95,16 @@ ruleTester.run('attribute-hyphenation', rule, {
       </template>
       `,
       options: ['never', { ignoreTags: ['VueComponent', '/^custom-/'] }]
+    },
+    {
+      filename: 'test.vue',
+      code: `
+      <template>
+        <VueComponent myProp="prop"></VueComponent>
+        <custom-component myProp="prop"></custom-component>
+      </template>
+      `,
+      options: ['always', { ignoreTags: ['VueComponent', '/^custom-/'] }]
     }
   ],
 
@@ -483,6 +493,29 @@ ruleTester.run('attribute-hyphenation', rule, {
           column: 17
         }
       ]
+    },
+    {
+      code: `
+      <template>
+        <custom myProp/>
+        <CustomComponent myProp/>
+      </template>
+      `,
+      output: `
+      <template>
+        <custom my-prop/>
+        <CustomComponent myProp/>
+      </template>
+      `,
+      options: ['always', { ignoreTags: ['CustomComponent'] }],
+      errors: [
+        {
+          message: "Attribute 'myProp' must be hyphenated.",
+          type: 'VIdentifier',
+          line: 3,
+          column: 17
+        }
+      ]
     }
   ]
 })
diff --git a/tests/lib/rules/v-on-event-hyphenation.js b/tests/lib/rules/v-on-event-hyphenation.js
index 8b7374682..3f58ce1f0 100644
--- a/tests/lib/rules/v-on-event-hyphenation.js
+++ b/tests/lib/rules/v-on-event-hyphenation.js
@@ -61,6 +61,15 @@ tester.run('v-on-event-hyphenation', rule, {
       </template>
       `,
       options: ['never', { ignoreTags: ['/^Vue/', 'custom-component'] }]
+    },
+    {
+      code: `
+      <template>
+          <VueComponent v-on:customEvent="events"/>
+          <custom-component v-on:customEvent="events"/>
+      </template>
+      `,
+      options: ['always', { ignoreTags: ['/^Vue/', 'custom-component'] }]
     }
   ],
   invalid: [
@@ -218,6 +227,28 @@ tester.run('v-on-event-hyphenation', rule, {
           column: 23
         }
       ]
+    },
+    {
+      code: `
+      <template>
+        <VueComponent v-on:customEvent="events"/>
+        <CustomComponent v-on:customEvent="events"/>
+      </template>
+      `,
+      output: `
+      <template>
+        <VueComponent v-on:custom-event="events"/>
+        <CustomComponent v-on:customEvent="events"/>
+      </template>
+      `,
+      options: ['always', { autofix: true, ignoreTags: ['CustomComponent'] }],
+      errors: [
+        {
+          message: "v-on event 'v-on:customEvent' must be hyphenated.",
+          line: 3,
+          column: 23
+        }
+      ]
     }
   ]
 })

From c938035c28598df81f0a7da2187cf30271f9ca75 Mon Sep 17 00:00:00 2001
From: waynzh <waynzh19@gmail.com>
Date: Wed, 20 Nov 2024 10:42:19 +0800
Subject: [PATCH 12/12] feat: rename

---
 lib/rules/attribute-hyphenation.js  | 4 ++--
 lib/rules/v-on-event-hyphenation.js | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/lib/rules/attribute-hyphenation.js b/lib/rules/attribute-hyphenation.js
index 23bb16dae..65d096cd4 100644
--- a/lib/rules/attribute-hyphenation.js
+++ b/lib/rules/attribute-hyphenation.js
@@ -80,7 +80,7 @@ module.exports = {
     const optionsPayload = context.options[1]
     const useHyphenated = option !== 'never'
     /** @type {RegExp[]} */
-    const ignoreTags = (
+    const ignoredTagsRegexps = (
       (optionsPayload && optionsPayload.ignoreTags) ||
       []
     ).map(toRegExp)
@@ -144,7 +144,7 @@ module.exports = {
 
     /** @param {string} name */
     function isIgnoredTagName(name) {
-      return ignoreTags.some((re) => re.test(name))
+      return ignoredTagsRegexps.some((re) => re.test(name))
     }
 
     return utils.defineTemplateBodyVisitor(context, {
diff --git a/lib/rules/v-on-event-hyphenation.js b/lib/rules/v-on-event-hyphenation.js
index 3fbf5314c..c9fac76e8 100644
--- a/lib/rules/v-on-event-hyphenation.js
+++ b/lib/rules/v-on-event-hyphenation.js
@@ -64,7 +64,7 @@ module.exports = {
     /** @type {string[]} */
     const ignoredAttributes = (optionsPayload && optionsPayload.ignore) || []
     /** @type {RegExp[]} */
-    const ignoreTags = (
+    const ignoredTagsRegexps = (
       (optionsPayload && optionsPayload.ignoreTags) ||
       []
     ).map(toRegExp)
@@ -113,7 +113,7 @@ module.exports = {
 
     /** @param {string} name */
     function isIgnoredTagName(name) {
-      return ignoreTags.some((re) => re.test(name))
+      return ignoredTagsRegexps.some((re) => re.test(name))
     }
 
     return utils.defineTemplateBodyVisitor(context, {