From d6e24043748c09078df76d46784d7c6beba5169b Mon Sep 17 00:00:00 2001 From: Rishikesh183 Date: Fri, 15 May 2026 01:10:02 +0530 Subject: [PATCH] fix(deps): replace tailwind-merge aliases with peer dependency tailwind-merge-v2 and tailwind-merge-v3 are malicious packages on npm (GHSA-53q4-wj32-3vv9, GHSA-3679-84c2-v5xm). Using them as npm aliases caused security scanners to flag downstream projects even though the malicious packages were never installed. Replace both aliased deps with a single tailwind-merge peer dependency. Users install the version matching their Tailwind CSS (^2 for TW3, ^3 for TW4). BREAKING CHANGE: tailwind-merge must now be installed explicitly. --- packages/ui/package.json | 5 ++--- packages/ui/src/helpers/tailwind-merge.ts | 16 ++++++---------- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/packages/ui/package.json b/packages/ui/package.json index 62f4d468c..7e7e634f7 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -274,9 +274,7 @@ "klona": "2.0.6", "magic-string": "0.30.21", "oxc-parser": "0.112.0", - "package-manager-detector": "1.6.0", - "tailwind-merge-v2": "npm:tailwind-merge@2.6.1", - "tailwind-merge-v3": "npm:tailwind-merge@3.4.0" + "package-manager-detector": "1.6.0" }, "devDependencies": { "@farmfe/core": "1.7.11", @@ -313,6 +311,7 @@ "peerDependencies": { "react": "^18 || ^19", "react-dom": "^18 || ^19", + "tailwind-merge": "^2 || ^3", "tailwindcss": "^3 || ^4" }, "clean-package": { diff --git a/packages/ui/src/helpers/tailwind-merge.ts b/packages/ui/src/helpers/tailwind-merge.ts index b45ca96a7..c43bb40c7 100644 --- a/packages/ui/src/helpers/tailwind-merge.ts +++ b/packages/ui/src/helpers/tailwind-merge.ts @@ -1,21 +1,17 @@ -import { extendTailwindMerge as extendTailwindMerge_v2 } from "tailwind-merge-v2"; -import { extendTailwindMerge as extendTailwindMerge_v3, type ClassNameValue } from "tailwind-merge-v3"; -import { getPrefix, getVersion } from "../store"; +import { extendTailwindMerge, type ClassNameValue } from "tailwind-merge"; +import { getPrefix } from "../store"; -const cache = new Map>(); +const cache = new Map>(); export function twMerge(...classLists: ClassNameValue[]): string { const prefix = getPrefix(); - const version = getVersion(); - - const cacheKey = `${prefix}.${version}`; - const cacheValue = cache.get(cacheKey); + const cacheValue = cache.get(prefix); if (cacheValue) { return cacheValue(...classLists); } - const twMergeFn = (version === 3 ? extendTailwindMerge_v2 : extendTailwindMerge_v3)({ + const twMergeFn = extendTailwindMerge({ extend: { classGroups: { "bg-image": ["bg-arrow-down-icon", "bg-check-icon", "bg-dash-icon", "bg-dot-icon"], @@ -24,7 +20,7 @@ export function twMerge(...classLists: ClassNameValue[]): string { }, prefix, }); - cache.set(cacheKey, twMergeFn); + cache.set(prefix, twMergeFn); return twMergeFn(...classLists); }