Repository: francoismassart/eslint-plugin-tailwindcss (js)

Issue:
[BUG] classRegex ignored in vuejs
Hi,
Thanks for the great work!

**Describe the bug**
When in vueJS [templates case](https://github.com/francoismassart/eslint-plugin-tailwindcss/blob/893c44d288c07ed56d0dcaf7e5db10893854c03a/lib/util/ast.js#L41), the [checks are made](https://github.com/francoismassart/eslint-plugin-tailwindcss/blob/893c44d288c07ed56d0dcaf7e5db10893854c03a/lib/util/ast.js#L43) against `class` token, and not against the defined `classRegex`.

**To Reproduce**
Steps to reproduce the behavior:
1. Add classRegex to settings
2. Add classes to an attribute that is concerned by the regex.

**Expected behavior**
Any vue attributes concerned by classRegex should be validated.

**Environment (please complete the following information):**
 - OS: macOS
 - Eslint last version


Thanks!

Pull request:
fix: #216 `classRegex` ignored in vuejs
# `classRegex` ignored in vuejs

## Description

Fixes #216 

## Type of change

Please delete options that are not relevant.

- [x] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] This change requires a documentation update

## Checklist:

- [x] My code follows the style guidelines of this project
- [xI have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my feature works
- [x] New and existing unit tests pass locally with my changes
- [x] Any dependent changes have been merged and published in downstream modules
- [x] I have checked my code and corrected any misspellings


Patch:
diff --git a/lib/rules/classnames-order.js b/lib/rules/classnames-order.js
index ffbb76d..c3fb146 100644
--- a/lib/rules/classnames-order.js
+++ b/lib/rules/classnames-order.js
@@ -244,7 +244,7 @@ module.exports = {
       */
       VAttribute: function (node) {
         switch (true) {
-          case !astUtil.isValidVueAttribute(node):
+          case !astUtil.isValidVueAttribute(node, classRegex):
             return;
           case astUtil.isVLiteralValue(node):
             sortNodeArgumentValue(node, null);
diff --git a/lib/rules/enforces-negative-arbitrary-values.js b/lib/rules/enforces-negative-arbitrary-values.js
index 2eb60f4..02ba823 100644
--- a/lib/rules/enforces-negative-arbitrary-values.js
+++ b/lib/rules/enforces-negative-arbitrary-values.js
@@ -188,7 +188,7 @@ module.exports = {
       */
       VAttribute: function (node) {
         switch (true) {
-          case !astUtil.isValidVueAttribute(node):
+          case !astUtil.isValidVueAttribute(node, classRegex):
             return;
           case astUtil.isVLiteralValue(node):
             parseForNegativeArbitraryClassNames(node);
diff --git a/lib/rules/enforces-shorthand.js b/lib/rules/enforces-shorthand.js
index 32139c5..b601130 100644
--- a/lib/rules/enforces-shorthand.js
+++ b/lib/rules/enforces-shorthand.js
@@ -421,7 +421,7 @@ module.exports = {
       */
       VAttribute: function (node) {
         switch (true) {
-          case !astUtil.isValidVueAttribute(node):
+          case !astUtil.isValidVueAttribute(node, classRegex):
             return;
           case astUtil.isVLiteralValue(node):
             parseForShorthandCandidates(node);
diff --git a/lib/rules/migration-from-tailwind-2.js b/lib/rules/migration-from-tailwind-2.js
index aa17bb5..d18bf1e 100644
--- a/lib/rules/migration-from-tailwind-2.js
+++ b/lib/rules/migration-from-tailwind-2.js
@@ -299,7 +299,7 @@ module.exports = {
       */
       VAttribute: function (node) {
         switch (true) {
-          case !astUtil.isValidVueAttribute(node):
+          case !astUtil.isValidVueAttribute(node, classRegex):
             return;
           case astUtil.isVLiteralValue(node):
             parseForObsoleteClassNames(node);
diff --git a/lib/rules/no-arbitrary-value.js b/lib/rules/no-arbitrary-value.js
index 22f9fb3..b9e527f 100644
--- a/lib/rules/no-arbitrary-value.js
+++ b/lib/rules/no-arbitrary-value.js
@@ -188,7 +188,7 @@ module.exports = {
       */
       VAttribute: function (node) {
         switch (true) {
-          case !astUtil.isValidVueAttribute(node):
+          case !astUtil.isValidVueAttribute(node, classRegex):
             return;
           case astUtil.isVLiteralValue(node):
             parseForArbitraryValues(node, null);
diff --git a/lib/rules/no-contradicting-classname.js b/lib/rules/no-contradicting-classname.js
index 6429c7e..e732b60 100644
--- a/lib/rules/no-contradicting-classname.js
+++ b/lib/rules/no-contradicting-classname.js
@@ -216,7 +216,7 @@ module.exports = {
       */
       VAttribute: function (node) {
         switch (true) {
-          case !astUtil.isValidVueAttribute(node):
+          case !astUtil.isValidVueAttribute(node, classRegex):
             return;
           case astUtil.isVLiteralValue(node):
             astUtil.parseNodeRecursive(node, null, parseForContradictingClassNames, true);
diff --git a/lib/rules/no-custom-classname.js b/lib/rules/no-custom-classname.js
index 20eaa0b..66a6eac 100644
--- a/lib/rules/no-custom-classname.js
+++ b/lib/rules/no-custom-classname.js
@@ -187,7 +187,7 @@ module.exports = {
       */
       VAttribute: function (node) {
         switch (true) {
-          case !astUtil.isValidVueAttribute(node):
+          case !astUtil.isValidVueAttribute(node, classRegex):
             return;
           case astUtil.isVLiteralValue(node):
             astUtil.parseNodeRecursive(node, null, parseForCustomClassNames);
diff --git a/lib/util/ast.js b/lib/util/ast.js
index 0141657..60a5d25 100644
--- a/lib/util/ast.js
+++ b/lib/util/ast.js
@@ -36,25 +36,26 @@ function isClassAttribute(node, classRegex) {
  * Find out if node is `class`
  *
  * @param {ASTNode} node The AST node being checked
+ * @param {String} classRegex Regex to test the attribute that is being checked against
  * @returns {Boolean}
  */
-function isVueClassAttribute(node) {
+function isVueClassAttribute(node, classRegex) {
+  const re = new RegExp(classRegex);
+  let name = '';
   switch (true) {
-    case node.key && /^class$/.test(node.key.name):
+    case node.key && node.key.name && re.test(node.key.name):
       // class="vue-classes-as-litteral"
       return true;
-      break;
     case node.key &&
       node.key.name &&
       node.key.name.name &&
       node.key.argument &&
       node.key.argument.name &&
       /^bind$/.test(node.key.name.name) &&
-      /^class$/.test(node.key.argument.name):
+      re.test(node.key.argument.name):
       // v-bind:class="vue-classes-as-bind"
       // :class="vue-classes-as-bind"
       return true;
-      break;
     default:
       return false;
   }
@@ -154,10 +155,11 @@ function isValidJSXAttribute(node, classRegex) {
  * Find out if the node is a valid candidate for our rules
  *
  * @param {ASTNode} node The AST node being checked
+ * @param {String} classRegex Regex to test the attribute that is being checked against
  * @returns {Boolean}
  */
-function isValidVueAttribute(node) {
-  if (!isVueClassAttribute(node)) {
+function isValidVueAttribute(node, classRegex) {
+  if (!isVueClassAttribute(node, classRegex)) {
     // Only run for class attributes
     return false;
   }
diff --git a/package-lock.json b/package-lock.json
index 393f204..9734a59 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
 {
   "name": "eslint-plugin-tailwindcss",
-  "version": "3.10.0",
+  "version": "3.10.1-beta.3",
   "lockfileVersion": 2,
   "requires": true,
   "packages": {
     "": {
       "name": "eslint-plugin-tailwindcss",
-      "version": "3.10.0",
+      "version": "3.10.1-beta.3",
       "license": "MIT",
       "dependencies": {
         "fast-glob": "^3.2.5",
diff --git a/package.json b/package.json
index f0698bb..8fe4fc5 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-plugin-tailwindcss",
-  "version": "3.10.0",
+  "version": "3.10.1-beta.3",
   "description": "Rules enforcing best practices while using Tailwind CSS",
   "keywords": [
     "eslint",


Test patch:
diff --git a/tests/lib/rules/no-custom-classname.js b/tests/lib/rules/no-custom-classname.js
index 861c5c7..5daadfc 100644
--- a/tests/lib/rules/no-custom-classname.js
+++ b/tests/lib/rules/no-custom-classname.js
@@ -1247,5 +1247,25 @@ ruleTester.run("no-custom-classname", rule, {
       code: `<div className="peer-checked/draft:unknown-class">Custom peer name variant with invalid class name</div>`,
       errors: generateErrors("peer-checked/draft:unknown-class"),
     },
+    {
+      code: `<div fooClass="foo" bazClass="baz">Issue #216</div>`,
+      errors: generateErrors("foo baz"),
+      options: [
+        {
+          classRegex: `Class$`,
+        },
+      ],
+    },
+    {
+      code: `<template><div enterActiveClass="foo" enterFromClass="baz">Issue #216</div></template>`,
+      filename: "test.vue",
+      parser: require.resolve("vue-eslint-parser"),
+      errors: generateErrors("foo baz"),
+      options: [
+        {
+          classRegex: `class$`,
+        },
+      ],
+    },
   ],
 });