Skip to content

Commit 8f55522

Browse files
committed
feat: add preserveFunction option for tailwindcss-mangle not working with tailwind-merge #44
1 parent 20600d4 commit 8f55522

File tree

13 files changed

+260
-232
lines changed

13 files changed

+260
-232
lines changed

apps/vite-react/src/App.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ function App() {
99
const [count, setCount] = useState(0)
1010

1111
return (
12-
<main className="flex min-h-screen flex-col items-center justify-between p-24">
12+
<main className="px-2 py-1 bg-red-100 hover:bg-red-800 flex min-h-screen flex-col items-center justify-between p-24">
1313
<nav className={aaa}>{aaa}</nav>
1414
<div className="z-10 w-full max-w-5xl items-center justify-between font-mono text-sm lg:flex">
1515
<p className="fixed left-0 top-0 flex w-full justify-center border-b border-gray-300 bg-gradient-to-b from-zinc-200 pb-6 pt-8 backdrop-blur-2xl dark:border-neutral-800 dark:bg-zinc-800/30 dark:from-inherit lg:static lg:w-auto lg:rounded-xl lg:border lg:bg-gray-200 lg:p-4 lg:dark:bg-zinc-800/30">

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"@tailwindcss-mangle/shared": "workspace:*",
2424
"@tsconfig/recommended": "^1.0.2",
2525
"@types/lodash-es": "^4.17.9",
26-
"@types/node": "^20.6.0",
26+
"@types/node": "^20.6.1",
2727
"@vitest/coverage-v8": "^0.34.4",
2828
"cross-env": "^7.0.3",
2929
"dedent": "^1.5.1",

packages/config/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@tailwindcss-mangle/config",
3-
"version": "2.1.0",
3+
"version": "2.2.0",
44
"description": "The config and load function of tailwindcss-mangle",
55
"exports": {
66
".": {

packages/core/package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@tailwindcss-mangle/core",
3-
"version": "2.1.0",
3+
"version": "2.2.0",
44
"description": "The core of tailwindcss-mangle",
55
"exports": {
66
".": {
@@ -44,12 +44,12 @@
4444
},
4545
"dependencies": {
4646
"@ast-core/escape": "^1.0.1",
47-
"@babel/core": "^7.22.17",
47+
"@babel/core": "^7.22.19",
4848
"@babel/helper-plugin-utils": "^7.22.5",
4949
"@babel/parser": "^7.22.16",
5050
"@babel/preset-typescript": "^7.22.15",
51-
"@babel/traverse": "^7.22.17",
52-
"@babel/types": "^7.22.17",
51+
"@babel/traverse": "^7.22.19",
52+
"@babel/types": "^7.22.19",
5353
"@tailwindcss-mangle/config": "workspace:^",
5454
"@tailwindcss-mangle/shared": "workspace:^",
5555
"fast-sort": "^3.4.0",

packages/core/src/css/plugins.ts

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@ export const transformSelectorPostcssPlugin: PluginCreator<ICssHandlerOptions> =
2626
ignoreVueScoped: true
2727
})
2828

29-
const utilitiesSet = new Set<string>()
30-
3129
return {
3230
postcssPlugin,
3331
async Rule(rule) {
@@ -36,25 +34,18 @@ export const transformSelectorPostcssPlugin: PluginCreator<ICssHandlerOptions> =
3634
return
3735
}
3836
await parser((selectors) => {
39-
let flag = false
40-
selectors.walkClasses((s) => {
41-
if (ctx.isPreserveClass(s.value) && !utilitiesSet.has(rule.selector)) {
42-
flag = true
43-
}
44-
})
45-
if (flag) {
46-
const r = rule.cloneBefore()
47-
// @ts-ignore
48-
r[clonedKey] = true
49-
}
50-
5137
selectors.walkClasses((s) => {
5238
if (s.value && replaceMap && replaceMap.has(s.value)) {
5339
if (ignoreVueScoped && isVueScoped(s)) {
5440
return
5541
}
5642
const v = replaceMap.get(s.value)
5743
if (v) {
44+
if (ctx.isPreserveClass(s.value)) {
45+
const r = rule.cloneBefore()
46+
// @ts-ignore
47+
r[clonedKey] = true
48+
}
5849
s.value = v
5950
}
6051
}

packages/core/src/ctx/index.ts

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -77,13 +77,13 @@ export class Context {
7777
}
7878

7979
getReplaceMap() {
80-
const map = new Map<string, string>()
81-
for (const [key, value] of sort([...this.replaceMap.entries()]).desc((x) => x[0].length)) {
82-
if (!this.isPreserveClass(key)) {
83-
map.set(key, value)
84-
}
85-
}
86-
return map
80+
// const map = new Map<string, string>()
81+
// for (const [key, value] of sort([...this.replaceMap.entries()]).desc((x) => x[0].length)) {
82+
// if (!this.isPreserveClass(key)) {
83+
// map.set(key, value)
84+
// }
85+
// }
86+
return this.replaceMap // map
8787
}
8888

8989
addToUsedBy(key: string, file: string) {
@@ -93,18 +93,22 @@ export class Context {
9393
}
9494
}
9595

96+
loadClassSet(classList: string[]) {
97+
const list = sort(classList).desc((c) => c.length)
98+
for (const className of list) {
99+
if (this.currentMangleClassFilter(className)) {
100+
this.classSet.add(className)
101+
}
102+
}
103+
}
104+
96105
async initConfig(opts: InitConfigOptions = {}) {
97106
const { cwd, classList: _classList, mangleOptions } = opts
98107
const { config, cwd: configCwd } = await getConfig(cwd)
99108

100109
this.mergeOptions(mangleOptions, config?.mangle)
101110
if (_classList) {
102-
const classList = sort(_classList).desc((c) => c.length)
103-
for (const className of classList) {
104-
if (this.currentMangleClassFilter(className)) {
105-
this.classSet.add(className)
106-
}
107-
}
111+
this.loadClassSet(_classList)
108112
} else {
109113
let jsonPath = this.options.classListPath ?? resolve(process.cwd(), config?.patch?.output?.filename as string)
110114
if (!isAbsolute(jsonPath)) {
@@ -117,12 +121,7 @@ export class Context {
117121
// why?
118122
// cause bg-red-500 and bg-red-500/50 same time
119123
// transform bg-red-500/50 first
120-
const classList = sort(list).desc((c) => c.length)
121-
for (const className of classList) {
122-
if (this.currentMangleClassFilter(className)) {
123-
this.classSet.add(className)
124-
}
125-
}
124+
this.loadClassSet(list)
126125
}
127126
}
128127

packages/core/test/__snapshots__/css.test.ts.snap

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ exports[`css > preserveClassNamesSet case 0 1`] = `
1313
.tw-a {color:red;}"
1414
`;
1515

16+
exports[`css > preserveClassNamesSet case 1 1`] = `
17+
".gap-y-4 {color:red;}
18+
.tw-a {color:red;}"
19+
`;
20+
1621
exports[`css > vue scoped .gap-y-4 1`] = `
1722
"@media (min-width: 768px) {
1823
.tw-a {

packages/core/test/__snapshots__/js.test.ts.snap

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -736,7 +736,18 @@ cn(\`w-2 h-2 bg-red-600 and bg-red-600/50\`)
736736
twMerge('w-1 h-1 bg-red-400 and bg-red-400/50')"
737737
`;
738738
739-
exports[`js handler > preserve-fn-case0.js case 3 2`] = `Map {}`;
739+
exports[`js handler > preserve-fn-case0.js case 3 2`] = `
740+
Map {
741+
"bg-red-500/50" => "tw-a",
742+
"bg-red-400/50" => "tw-b",
743+
"bg-red-500" => "tw-c",
744+
"bg-red-400" => "tw-d",
745+
"w-2" => "tw-e",
746+
"h-2" => "tw-f",
747+
"w-1" => "tw-g",
748+
"h-1" => "tw-h",
749+
}
750+
`;
740751
741752
exports[`js handler > trailing slash case 0 1`] = `"document.getElementById(\\"#app\\").classList.add(\\"tw-a tw-b\\");"`;
742753

packages/core/test/css.test.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,19 @@ describe('css', () => {
2121
expect(css).toMatchSnapshot()
2222
})
2323

24+
it('preserveClassNamesSet case 1', async () => {
25+
await ctx.initConfig({
26+
classList: ['gap-y-4']
27+
})
28+
const testCase = `.gap-y-4 {color:red;}`
29+
ctx.addPreserveClass('gap-y-4')
30+
const { css } = await cssHandler(testCase, {
31+
ctx,
32+
replaceMap: ctx.getReplaceMap()
33+
})
34+
expect(css).toMatchSnapshot()
35+
})
36+
2437
it('vue scoped .gap-y-4', async () => {
2538
const replaceMap = new Map()
2639
replaceMap.set('gap-y-4', 'tw-a')

packages/shared/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@tailwindcss-mangle/shared",
3-
"version": "2.1.0",
3+
"version": "2.2.0",
44
"description": "The shared utils of tailwindcss-mangle",
55
"exports": {
66
".": {

0 commit comments

Comments
 (0)