Skip to content

Commit ba35630

Browse files
committed
feat: add ignore identifier twIgnore
1 parent 06c6dfc commit ba35630

File tree

10 files changed

+967
-1053
lines changed

10 files changed

+967
-1053
lines changed

.changeset/afraid-ads-unite.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
---
2+
"@tailwindcss-mangle/core": patch
3+
---
4+
5+
feat: add `twIgnore` for ignore mangle
6+
7+
8+
## Example
9+
10+
### Input
11+
12+
```js
13+
const twIgnore = String.raw
14+
const className = `${twIgnore`gap-y-4`} bg-zinc-800/30`
15+
```
16+
17+
### Output
18+
19+
```js
20+
const twIgnore = String.raw
21+
const className = `${twIgnore`gap-y-4`} tw-a`
22+
```

package.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@
3838
"@commitlint/config-conventional": "^19.5.0",
3939
"@commitlint/prompt-cli": "^19.5.0",
4040
"@commitlint/types": "^19.5.0",
41-
"@icebreakers/eslint-config": "^0.6.1",
42-
"@icebreakers/monorepo": "^0.6.12",
41+
"@icebreakers/eslint-config": "^0.7.0",
42+
"@icebreakers/monorepo": "^0.6.13",
4343
"@icebreakers/stylelint-config": "^0.1.2",
4444
"@rollup/pluginutils": "^5.1.3",
4545
"@tailwindcss-mangle/core": "workspace:*",
@@ -57,12 +57,12 @@
5757
"@types/lodash": "^4.17.13",
5858
"@types/lodash-es": "^4.17.12",
5959
"@types/micromatch": "^4.0.9",
60-
"@types/node": "^22.8.6",
60+
"@types/node": "^22.9.0",
6161
"@types/resolve": "^1.20.6",
6262
"@types/semver": "^7.5.8",
6363
"@types/set-value": "^4.0.3",
6464
"@vitest/coverage-v8": "~2.1.4",
65-
"astro": "^4.16.8",
65+
"astro": "^4.16.10",
6666
"ci-info": "^4.0.0",
6767
"comment-json": "^4.2.5",
6868
"cross-env": "^7.0.3",
@@ -94,7 +94,7 @@
9494
"postcss7": "npm:postcss@7",
9595
"prettier": "^3.3.3",
9696
"rimraf": "^6.0.1",
97-
"rollup": "^4.24.3",
97+
"rollup": "^4.25.0",
9898
"set-value": "^4.1.0",
9999
"tailwindcss": "^3.4.14",
100100
"tailwindcss-patch": "workspace:*",
@@ -108,7 +108,7 @@
108108
"unplugin": "^1.15.0",
109109
"unplugin-tailwindcss-mangle": "workspace:*",
110110
"vite": "^5.4.10",
111-
"vite-tsconfig-paths": "^5.0.1",
111+
"vite-tsconfig-paths": "^5.1.1",
112112
"vitest": "~2.1.4",
113113
"webpack": "^5.96.1",
114114
"webpack-build-utils": "^0.0.7",

packages/core/src/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const ignoreIdentifier = 'twIgnore'

packages/core/src/js/index.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { jsStringEscape } from '@ast-core/escape'
44
import { sort } from 'fast-sort'
55
import MagicString from 'magic-string'
66
import { parse, traverse } from '../babel'
7+
import { ignoreIdentifier } from '../constants'
78
import { makeRegex, splitCode } from '../shared'
89

910
export function handleValue(raw: string, node: StringLiteral | TemplateElement, options: IJsHandlerOptions, ms: MagicString, offset: number, escape: boolean) {
@@ -66,6 +67,26 @@ export function jsHandler(rawSource: string | MagicString, options: IJsHandlerOp
6667
TemplateElement: {
6768
enter(p) {
6869
const n = p.node
70+
if (p.parentPath.isTemplateLiteral()) {
71+
if (
72+
(p.parentPath.parentPath.isTaggedTemplateExpression()
73+
&& p.parentPath.parentPath.get('tag').isIdentifier({
74+
name: ignoreIdentifier,
75+
})
76+
)
77+
) {
78+
const { splitQuote = true } = options
79+
const array = splitCode(n.value.raw, {
80+
splitQuote,
81+
})
82+
for (const item of array) {
83+
ctx.addPreserveClass(item)
84+
}
85+
86+
return
87+
}
88+
}
89+
6990
handleValue(n.value.raw, n, options, ms, 0, false)
7091
},
7192
},

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

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

21+
exports[`css > preserveClassNamesSet case 2 1`] = `
22+
".gap-y-4 {color:red;}
23+
.tw-a {color:red;}"
24+
`;
25+
2126
exports[`css > vue scoped .gap-y-4 1`] = `
2227
"@media (min-width: 768px) {
2328
.tw-a {

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,24 @@ exports[`js handler > common StringLiteral with splitQuote false 1`] = `"element
4343
4444
exports[`js handler > common TemplateElement 1`] = `"const counter = 0;element.innerHTML = \`<div class="tw-a tw-b">count is \${counter}</div>\`"`;
4545
46+
exports[`js handler > common ignore StringLiteral 1`] = `
47+
"
48+
const twIgnore = String.raw
49+
element.innerHTML = \`<div class="\${twIgnore\`dark:bg-zinc-800/30\`} tw-a">count is counter</div>\`"
50+
`;
51+
52+
exports[`js handler > common ignore StringLiteral case 0 1`] = `
53+
"
54+
const twIgnore = String.raw
55+
const className = \`\${twIgnore\`gap-y-4\`} tw-a\`"
56+
`;
57+
58+
exports[`js handler > common ignore StringLiteral case 1 1`] = `
59+
"
60+
const twIgnore = String.raw
61+
const className = \`\${twIgnore\`gap-y-4\`} \${twIgnore\`bg-zinc-800/30\`}\`"
62+
`;
63+
4664
exports[`js handler > eval script case 1`] = `
4765
"(function (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
4866
"use strict";

packages/core/test/css.test.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { cssHandler } from '@/css'
22
import { Context } from '@/ctx'
3+
import { jsHandler } from '@/js'
34
import { getTestCase } from './utils'
45

56
describe('css', () => {
@@ -33,6 +34,24 @@ describe('css', () => {
3334
expect(code).toMatchSnapshot()
3435
})
3536

37+
it('preserveClassNamesSet case 2', async () => {
38+
await ctx.initConfig({
39+
classList: ['gap-y-4'],
40+
})
41+
const jsTestCase = `
42+
const twIgnore = String.raw
43+
element.innerHTML = \`<div class="\${twIgnore\`gap-y-4\`} lg:dark:bg-zinc-800/30">count is counter</div>\``
44+
jsHandler(jsTestCase, {
45+
ctx,
46+
})
47+
const testCase = `.gap-y-4 {color:red;}`
48+
49+
const { code } = await cssHandler(testCase, {
50+
ctx,
51+
})
52+
expect(code).toMatchSnapshot()
53+
})
54+
3655
it('vue scoped .gap-y-4', async () => {
3756
const replaceMap = ctx.replaceMap
3857
replaceMap.set('gap-y-4', 'tw-a')

packages/core/test/js.test.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,51 @@ describe('js handler', async () => {
3232
expect(code).toMatchSnapshot()
3333
})
3434

35+
it('common ignore StringLiteral', () => {
36+
const replaceMap = ctx.replaceMap
37+
replaceMap.set('dark:bg-zinc-800/30', '1')
38+
replaceMap.set('lg:dark:bg-zinc-800/30', '1')
39+
40+
const testCase = `
41+
const twIgnore = String.raw
42+
element.innerHTML = \`<div class="\${twIgnore\`dark:bg-zinc-800/30\`} lg:dark:bg-zinc-800/30">count is counter</div>\``
43+
const code = jsHandler(testCase, {
44+
ctx,
45+
46+
}).code
47+
expect(code).toMatchSnapshot()
48+
})
49+
50+
it('common ignore StringLiteral case 0', () => {
51+
const replaceMap = ctx.replaceMap
52+
replaceMap.set('gap-y-4', '1')
53+
replaceMap.set('bg-zinc-800/30', '1')
54+
55+
const testCase = `
56+
const twIgnore = String.raw
57+
const className = \`\${twIgnore\`gap-y-4\`} bg-zinc-800/30\``
58+
const code = jsHandler(testCase, {
59+
ctx,
60+
61+
}).code
62+
expect(code).toMatchSnapshot()
63+
})
64+
65+
it('common ignore StringLiteral case 1', () => {
66+
const replaceMap = ctx.replaceMap
67+
replaceMap.set('gap-y-4', '1')
68+
replaceMap.set('bg-zinc-800/30', '1')
69+
70+
const testCase = `
71+
const twIgnore = String.raw
72+
const className = \`\${twIgnore\`gap-y-4\`} \${twIgnore\`bg-zinc-800/30\`}\``
73+
const code = jsHandler(testCase, {
74+
ctx,
75+
76+
}).code
77+
expect(code).toMatchSnapshot()
78+
})
79+
3580
it('common StringLiteral with splitQuote false', () => {
3681
const replaceMap = ctx.replaceMap
3782
replaceMap.set('dark:bg-zinc-800/30', '1')

0 commit comments

Comments
 (0)