-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcssMinify.ts
137 lines (133 loc) · 3.2 KB
/
cssMinify.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
import { composeVisitors, transform } from 'lightningcss'
function resolveThemeVariables(themeLookup: Map<string, any>) {
themeLookup.forEach((values, key, map) => {
map.set(
key,
values.flatMap(v => {
if (v.type === 'var') {
const lookup = map.get(v.value.name.ident)
if (lookup) {
return lookup
}
}
return v
}),
)
})
return themeLookup
}
const referencedVariables = new Map<string, number>()
const referencedAnimations = new Set<string>()
let themeLookup = new Map<string, any>()
let variableCounter = 0
let pass1Visitor = {
Variable(v) {
const name = v.name.ident
if (!referencedVariables.has(name))
referencedVariables.set(name, variableCounter++)
},
Declaration: {
animation(v) {
v.value.forEach(element => {
const name = element?.name?.value
if (name) referencedAnimations.add(name)
})
},
},
Rule(v) {
if (v.type === 'layer-block' && v.value.name?.includes('theme')) {
const declarations = v.value.rules
.flatMap(r => r.value.declarations.declarations)
.filter(r => r.property === 'custom')
declarations.forEach(declaration => {
const name = declaration.value.name
const value = declaration.value.value
themeLookup.set(name, value)
})
}
return v
},
}
let pass2Visitor = {
Declaration(v) {
if (v.property === 'custom' && v?.value?.name?.startsWith('--')) {
if (!referencedVariables.has(v.value.name)) {
return []
}
}
return v
},
VariableExit(v) {
if (themeLookup.has(v.name.ident)) {
return themeLookup.get(v.name.ident)
}
},
Rule: {
keyframes(v) {
if (!referencedAnimations.has(v.value.name.value)) return []
},
property(v) {
if (!referencedVariables.has(v.value.name)) return []
},
},
}
let pass3Visitor = {
Declaration(v) {
if (v.property === 'custom') {
if (themeLookup.has(v.value.name)) {
return []
}
}
},
DashedIdent(v) {
const lookup = referencedVariables.get(v)
if (lookup) {
return '--e' + lookup
}
},
}
export function retransform(css) {
let pass1 = transform({
code: Buffer.from(css),
minify: false,
filename: '',
visitor: composeVisitors([pass1Visitor]),
})
themeLookup = resolveThemeVariables(themeLookup)
themeLookup = resolveThemeVariables(themeLookup)
let pass2 = transform({
code: pass1.code,
minify: false,
filename: '',
visitor: composeVisitors([pass2Visitor]),
})
let pass3 = transform({
code: pass2.code,
minify: true,
filename: '',
visitor: composeVisitors([pass3Visitor]),
unusedSymbols: [
'container',
'!transition',
'!transform',
'!visible',
'!block',
],
})
return pass3.code.toString()
}
export function cssMinify() {
return {
name: 'minifyCss',
generateBundle(options, bundle) {
const cssFiles = Object.keys(bundle)
.filter(key => key.endsWith('.css'))
.map(key => bundle[key])
cssFiles.forEach(css => {
let cssCode = css.source
cssCode = retransform(cssCode)
css.source = cssCode
})
},
}
}