Repository: francoismassart/eslint-plugin-tailwindcss
Pull request #248 (2023-05-31 07:10:43)

fix: incorrect conflicting classnames (#186)
Fix for issue #186 


Patch:
diff --git a/lib/config/groups.js b/lib/config/groups.js
index 859cef6..a77a6be 100644
--- a/lib/config/groups.js
+++ b/lib/config/groups.js
@@ -619,6 +619,10 @@ module.exports.groups = [
   {
     type: 'Backgrounds',
     members: [
+      {
+        type: 'Background Image URL',
+        members: 'bg\\-\\[url\\((?<value>${backgroundImageUrl})\\)\\]',
+      },
       {
         type: 'Background Attachment',
         members: 'bg\\-(fixed|local|scroll)',
diff --git a/lib/util/groupMethods.js b/lib/util/groupMethods.js
index 7627a53..4ee1558 100644
--- a/lib/util/groupMethods.js
+++ b/lib/util/groupMethods.js
@@ -252,6 +252,10 @@ function generateOptions(propName, keys, config, isNegative = false) {
       // Forbidden prefixes
       escapedKeys.push(`\\[length\:.{1,}\\]`);
       return '(' + escapedKeys.join('|') + ')';
+    case 'backgroundImageUrl':
+      // Forbidden prefixes
+      escapedKeys.push(`.{1,}`);
+      return '(' + escapedKeys.join('|') + ')';
     case 'backgroundImage':
       // Forbidden prefixes
       escapedKeys.push(`\\[url\\(.{1,}\\)\\]`);
@@ -324,6 +328,10 @@ function patchRegex(re, config) {
         generateOptions(absoluteProp, [], config, isNegative)
       );
       return `${patched}(${replaced})`;
+    } else if (prop === 'backgroundImageUrl') {
+      // Special case
+      replaced = replaced.replace(new RegExp('\\$\\{' + prop + '\\}'), generateOptions(prop, [], config, false));
+      return `${patched}(${replaced})`;
     } else if (!config.theme || !config.theme[absoluteProp]) {
       // prop not found in config
       return;
diff --git a/package-lock.json b/package-lock.json
index c916c01..c7ea352 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
 {
   "name": "eslint-plugin-tailwindcss",
-  "version": "3.12.1-beta.0",
+  "version": "3.12.1",
   "lockfileVersion": 2,
   "requires": true,
   "packages": {
     "": {
       "name": "eslint-plugin-tailwindcss",
-      "version": "3.12.1-beta.0",
+      "version": "3.12.1",
       "license": "MIT",
       "dependencies": {
         "fast-glob": "^3.2.5",
diff --git a/package.json b/package.json
index 29a2f82..3de8d36 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-plugin-tailwindcss",
-  "version": "3.12.1-beta.0",
+  "version": "3.12.1",
   "description": "Rules enforcing best practices while using Tailwind CSS",
   "keywords": [
     "eslint",


Test patch:
diff --git a/tests/lib/rules/no-contradicting-classname.js b/tests/lib/rules/no-contradicting-classname.js
index c587f7f..87f9ae6 100644
--- a/tests/lib/rules/no-contradicting-classname.js
+++ b/tests/lib/rules/no-contradicting-classname.js
@@ -291,6 +291,10 @@ ruleTester.run("no-contradicting-classname", rule, {
         \`)}
       />`,
     },
+    {
+      code: `
+      <div class="bg-[url('/image.jpg')] bg-center">Issue #186</div>`,
+    },
   ],
 
   invalid: [
@@ -694,6 +698,13 @@ ruleTester.run("no-contradicting-classname", rule, {
       </div>`,
       errors: generateErrors(["group/name:scale-75 group/name:scale-50"]),
     },
+    {
+      code: `
+      <div class="bg-[url('default.jpg')] sm:bg-[url('foo.jpg')] sm:bg-[url('bar.jpg')]">
+        named group
+      </div>`,
+      errors: generateErrors(["sm:bg-[url('foo.jpg')] sm:bg-[url('bar.jpg')]"]),
+    },
     // {
     //   code: `
     //   <div class="scale-75 transform-none">
diff --git a/tests/lib/util/groupMethods.js b/tests/lib/util/groupMethods.js
index 0f37f6a..9583f06 100644
--- a/tests/lib/util/groupMethods.js
+++ b/tests/lib/util/groupMethods.js
@@ -244,3 +244,54 @@ describe("parseClassname", function () {
     assert.equal(regex1.exec(str1).groups.negPos, "0");
   });
 });
+
+describe("getGroupIndex", function () {
+  const targetProperties = {
+    Backgrounds: [
+      "Background Image URL",
+      "Background Attachment",
+      "Background Clip",
+      "Background Color",
+      "Deprecated Background Opacity",
+      "Background Origin",
+      "Background Position",
+      "Background Repeat",
+      "Background Size",
+      "Background Image",
+      "Gradient Color Stops",
+    ],
+  };
+  const targetGroups = defaultGroups.filter((g) => Object.keys(targetProperties).includes(g.type));
+
+  it("should have filtered `targetGroups`", function () {
+    assert.equal(targetGroups.length, Object.keys(targetProperties).length);
+  });
+
+  it(`should parse classnames`, function () {
+    let name, actual, expected;
+    name = "md:bg-[url('/image-md.jpg')]";
+    actual = groupUtil.parseClassname(name, targetGroups, mergedConfig, 0);
+    expected = {
+      index: 0,
+      name: name,
+      variants: "md:",
+      parentType: "Backgrounds",
+      body: "bg-[url('/",
+      value: "'/image-md.jpg'",
+      shorthand: "",
+      leading: "",
+      trailing: "",
+      important: false,
+    };
+    assert.deepEqual(actual, expected);
+  });
+
+  it(`should get correct group index`, function () {
+    let name, actual, expected;
+    const groups = groupUtil.getGroups(targetGroups, mergedConfig);
+    name = "md:bg-[url(some)]";
+    actual = groupUtil.getGroupIndex(name, groups, mergedConfig.separator);
+    expected = 0;
+    assert.equal(actual, expected);
+  });
+});