Skip to content

Commit cbfab78

Browse files
committed
refactor: htmlHandler
1 parent 96e6958 commit cbfab78

File tree

8 files changed

+58
-68
lines changed

8 files changed

+58
-68
lines changed

packages/core/package.json

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,15 +62,13 @@
6262
"@tailwindcss-mangle/shared": "workspace:^",
6363
"@vue/compiler-sfc": "^3.4.29",
6464
"fast-sort": "^3.4.0",
65-
"htmlparser2": "^9.1.0",
65+
"htmlparser2": "9.1.0",
6666
"magic-string": "^0.30.10",
6767
"micromatch": "^4.0.7",
68-
"parse5": "^7.1.2",
6968
"postcss": "^8.4.38",
7069
"postcss-selector-parser": "^6.1.0"
7170
},
7271
"devDependencies": {
73-
"@parse5/tools": "^0.5.0",
7472
"@types/babel__core": "^7.20.5",
7573
"@types/babel__traverse": "^7.20.6",
7674
"@types/micromatch": "^4.0.7",

packages/core/src/css/plugins.ts

Lines changed: 19 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ export type PostcssMangleTailwindcssPlugin = PluginCreator<ICssHandlerOptions>
77

88
const postcssPlugin = 'postcss-mangle-tailwindcss-plugin'
99

10-
const clonedKey = '__tw_mangle_cloned__'
11-
1210
export function isVueScoped(s: parser.ClassName): boolean {
1311
if (s.parent) {
1412
const index = s.parent.nodes.indexOf(s)
@@ -30,33 +28,30 @@ export const transformSelectorPostcssPlugin: PluginCreator<ICssHandlerOptions> =
3028

3129
return {
3230
postcssPlugin,
33-
async Rule(rule) {
34-
// @ts-ignore
35-
if (rule[clonedKey]) {
36-
return
37-
}
38-
await parser((selectors) => {
39-
selectors.walkClasses((s) => {
40-
if (s.value && replaceMap && replaceMap.has(s.value)) {
41-
if (ignoreVueScoped && isVueScoped(s)) {
42-
return
43-
}
44-
const v = replaceMap.get(s.value)
45-
if (v) {
46-
if (ctx.isPreserveClass(s.value)) {
47-
const r = rule.cloneBefore()
48-
// @ts-ignore
49-
r[clonedKey] = true
31+
Once(root) {
32+
root.walkRules((rule) => {
33+
parser((selectors) => {
34+
selectors.walkClasses((s) => {
35+
if (s.value && replaceMap && replaceMap.has(s.value)) {
36+
if (ignoreVueScoped && isVueScoped(s)) {
37+
return
38+
}
39+
const v = replaceMap.get(s.value)
40+
if (v) {
41+
if (ctx.isPreserveClass(s.value)) {
42+
rule.cloneBefore()
43+
}
44+
s.value = v
5045
}
51-
s.value = v
5246
}
53-
}
47+
})
48+
}).transformSync(rule, {
49+
lossless: false,
50+
updateSelector: true,
5451
})
55-
}).transform(rule, {
56-
lossless: false,
57-
updateSelector: true,
5852
})
5953
},
54+
6055
}
6156
}
6257
transformSelectorPostcssPlugin.postcss = true

packages/core/src/ctx/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export class Context {
1818
options: MangleUserConfig
1919
private includeMatcher: (file: string) => boolean
2020
private excludeMatcher: (file: string) => boolean
21-
public replaceMap: Map<string, string | boolean>
21+
public replaceMap: Map<string, string>
2222
classSet: Set<string>
2323

2424
classGenerator: ClassGenerator

packages/core/src/html/index.ts

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,29 @@
1-
import { parse, serialize } from 'parse5'
2-
import { traverse } from '@parse5/tools'
1+
import { Parser } from 'htmlparser2'
2+
import MagicString from 'magic-string'
33
import type { IHtmlHandlerOptions } from '../types'
44
import { makeRegex, splitCode } from '../shared'
5-
// const { traverse } = await import('@parse5/tools')
6-
export function htmlHandler(rawSource: string, options: IHtmlHandlerOptions) {
5+
6+
export function htmlHandler(raw: string, options: IHtmlHandlerOptions) {
77
const { ctx } = options
88
const { replaceMap } = ctx
9-
10-
const fragment = parse(rawSource)
11-
traverse(fragment, {
12-
element(node) {
13-
const attribute = node.attrs.find(x => x.name === 'class')
14-
if (attribute) {
15-
const array = splitCode(attribute.value, {
9+
const ms: MagicString = typeof raw === 'string' ? new MagicString(raw) : raw
10+
const parser = new Parser({
11+
onattribute(name, value) {
12+
if (name === 'class') {
13+
const arr = splitCode(value, {
1614
splitQuote: false,
1715
})
18-
for (const v of array) {
16+
let rawValue = value
17+
for (const v of arr) {
1918
if (replaceMap.has(v)) {
20-
attribute.value = attribute.value.replace(makeRegex(v), ctx.classGenerator.generateClassName(v).name)
19+
rawValue = rawValue.replace(makeRegex(v), ctx.classGenerator.generateClassName(v).name)
2120
}
2221
}
22+
ms.update(parser.startIndex + name.length + 2, parser.endIndex - 1, rawValue)
2323
}
2424
},
2525
})
26-
return serialize(fragment)
26+
parser.write(ms.original)
27+
parser.end()
28+
return ms.toString()
2729
}

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

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
22

33
exports[`html handler > common usage 1`] = `
4-
"<!DOCTYPE html><html><head>
4+
"<!doctype html>
5+
<html>
6+
7+
<head>
58
<meta charset="UTF-8">
69
<meta name="viewport" content="width=device-width, initial-scale=1.0">
710
<link href="/main.css" rel="stylesheet">
@@ -11,13 +14,16 @@ exports[`html handler > common usage 1`] = `
1114
<h1 class="tw-a tw-b tw-c">
1215
Hello world!
1316
</h1>
17+
</body>
1418
15-
16-
</body></html>"
19+
</html>"
1720
`;
1821
1922
exports[`html handler > trailing slash case 0 1`] = `
20-
"<!DOCTYPE html><html lang="en"><head>
23+
"<!DOCTYPE html>
24+
<html lang="en">
25+
26+
<head>
2127
<meta charset="UTF-8">
2228
<meta http-equiv="X-UA-Compatible" content="IE=edge">
2329
<meta name="viewport" content="width=device-width, initial-scale=1.0">
@@ -33,13 +39,16 @@ exports[`html handler > trailing slash case 0 1`] = `
3339
Block with bg-red-500 class
3440
</div>
3541
</div>
42+
</body>
3643
37-
38-
</body></html>"
44+
</html>"
3945
`;
4046
4147
exports[`html handler > trailing slash case 1`] = `
42-
"<!DOCTYPE html><html lang="en"><head>
48+
"<!DOCTYPE html>
49+
<html lang="en">
50+
51+
<head>
4352
<meta charset="UTF-8">
4453
<meta http-equiv="X-UA-Compatible" content="IE=edge">
4554
<meta name="viewport" content="width=device-width, initial-scale=1.0">
@@ -55,7 +64,7 @@ exports[`html handler > trailing slash case 1`] = `
5564
Block with bg-red-500/50 class
5665
</div>
5766
</div>
67+
</body>
5868
59-
60-
</body></html>"
69+
</html>"
6170
`;

packages/core/test/html.test.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ describe('html handler', () => {
3030
}
3131
const res = htmlHandler(getTestCase('trailing-slash.html'), {
3232
ctx,
33-
replaceMap,
3433
})
3534
expect(res).toMatchSnapshot()
3635
})
@@ -43,7 +42,6 @@ describe('html handler', () => {
4342
}
4443
const res = htmlHandler(getTestCase('trailing-slash-0.html'), {
4544
ctx,
46-
replaceMap,
4745
})
4846
expect(res).toMatchSnapshot()
4947
})

packages/shared/src/split.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
export const validateFilterRE = /[\w%-?\u00A0-\uFFFF]/
1+
// eslint-disable-next-line regexp/no-obscure-range
2+
export const validateFilterRE = /[\w\u00A0-\uFFFF%-?]/
23

34
export function isValidSelector(selector = ''): selector is string {
45
return validateFilterRE.test(selector)

pnpm-lock.yaml

Lines changed: 1 addition & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)