vite-plugin-token-shaker 0.0.3 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.mjs +13 -10
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -37,7 +37,7 @@ function extractTokensVariables(code, registry) {
|
|
|
37
37
|
if (!registry.has(varName)) registry.set(varName, {
|
|
38
38
|
value: varValue,
|
|
39
39
|
usageCount: 0,
|
|
40
|
-
|
|
40
|
+
deoptimized: false,
|
|
41
41
|
isAlias,
|
|
42
42
|
emitDeclaration: false
|
|
43
43
|
});
|
|
@@ -47,10 +47,10 @@ function extractTokensVariables(code, registry) {
|
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
|
-
function
|
|
50
|
+
function markDeoptimizedFromCSS(code, registry) {
|
|
51
51
|
let codeWithoutTokens = code;
|
|
52
52
|
for (const layer of findTokensLayers(code)) codeWithoutTokens = codeWithoutTokens.slice(0, layer.start) + " ".repeat(layer.end - layer.start) + codeWithoutTokens.slice(layer.end);
|
|
53
|
-
for (const [varName, variable] of registry) if (new RegExp(`${escapeRegex(varName)}\\s*:`, "g").test(codeWithoutTokens)) variable.
|
|
53
|
+
for (const [varName, variable] of registry) if (new RegExp(`${escapeRegex(varName)}\\s*:`, "g").test(codeWithoutTokens)) variable.deoptimized = true;
|
|
54
54
|
}
|
|
55
55
|
function countVariableUsage(code, registry, visited = /* @__PURE__ */ new Set()) {
|
|
56
56
|
for (const match of code.matchAll(VAR_REF_REGEX)) {
|
|
@@ -77,7 +77,7 @@ function resolveVariableValue(varName, registry, depth = 0) {
|
|
|
77
77
|
const variable = registry.get(varName);
|
|
78
78
|
if (!variable) return `var(${varName})`;
|
|
79
79
|
return variable.value.replace(VAR_REF_REGEX, (_, nestedVarName) => {
|
|
80
|
-
if (registry.get(nestedVarName)?.
|
|
80
|
+
if (registry.get(nestedVarName)?.deoptimized) return `var(${nestedVarName})`;
|
|
81
81
|
return resolveVariableValue(nestedVarName, registry, depth + 1);
|
|
82
82
|
});
|
|
83
83
|
}
|
|
@@ -125,7 +125,7 @@ function transformCode(code, registry) {
|
|
|
125
125
|
const variable = registry.get(varName);
|
|
126
126
|
if (!variable) continue;
|
|
127
127
|
if (variable.usageCount == 0) continue;
|
|
128
|
-
if (variable.
|
|
128
|
+
if (variable.deoptimized) {
|
|
129
129
|
declarations.push(`${varName}: ${varValue}`);
|
|
130
130
|
continue;
|
|
131
131
|
}
|
|
@@ -145,7 +145,7 @@ function transformCode(code, registry) {
|
|
|
145
145
|
result = result.replace(VAR_REF_REGEX, (original, varName, fallback) => {
|
|
146
146
|
const variable = registry.get(varName);
|
|
147
147
|
if (!variable) return original;
|
|
148
|
-
if (variable.
|
|
148
|
+
if (variable.deoptimized) return original;
|
|
149
149
|
if (variable.mangledName) return `var(${variable.mangledName}${fallback ? `, ${fallback}` : ""})`;
|
|
150
150
|
return resolveVariableValue(varName, registry);
|
|
151
151
|
});
|
|
@@ -154,31 +154,34 @@ function transformCode(code, registry) {
|
|
|
154
154
|
function getStats(registry, mangledCount) {
|
|
155
155
|
let drop = 0, inline = 0, mangle = 0, keep = 0;
|
|
156
156
|
for (const variable of registry.values()) if (variable.usageCount == 0) drop++;
|
|
157
|
-
else if (variable.
|
|
157
|
+
else if (variable.deoptimized) keep++;
|
|
158
158
|
else if (variable.mangledName) mangle++;
|
|
159
159
|
else inline++;
|
|
160
160
|
return `Analysis: ${drop} drop, ${inline} inline, ${mangle} mangle (${mangledCount} unique values), ${keep} keep`;
|
|
161
161
|
}
|
|
162
162
|
function tokenShaker(options = {}) {
|
|
163
163
|
const { manglePrefix = "--_", verbose = false } = options;
|
|
164
|
-
const registry = /* @__PURE__ */ new Map();
|
|
165
164
|
const log = verbose ? (...args) => console.log("[token-shaker]", ...args) : () => {};
|
|
166
165
|
return {
|
|
167
166
|
name: "vite-plugin-token-shaker",
|
|
168
167
|
enforce: "pre",
|
|
169
168
|
generateBundle(_outputOptions, bundle) {
|
|
170
|
-
registry.clear();
|
|
171
169
|
const cssAssets = Object.entries(bundle).filter(([name, asset]) => asset.type == "asset" && name.endsWith(".css"));
|
|
172
170
|
if (cssAssets.length == 0) return;
|
|
171
|
+
const registry = /* @__PURE__ */ new Map();
|
|
173
172
|
for (const [, asset] of cssAssets) extractTokensVariables(asset.source, registry);
|
|
174
173
|
if (registry.size == 0) return;
|
|
175
174
|
const bundledFiles = cssAssets.map(([name, asset]) => [name, asset.source]);
|
|
176
175
|
log(`Analyzing ${registry.size} variables across ${cssAssets.length} CSS files`);
|
|
177
176
|
resetUsageCounts(registry);
|
|
178
177
|
for (const [, code] of bundledFiles) {
|
|
179
|
-
|
|
178
|
+
markDeoptimizedFromCSS(code, registry);
|
|
180
179
|
countVariableUsage(code, registry);
|
|
181
180
|
}
|
|
181
|
+
for (const chunk of Object.values(bundle)) {
|
|
182
|
+
if (chunk.type != "chunk") continue;
|
|
183
|
+
for (const [varName, variable] of registry) if (chunk.code.includes(varName)) variable.deoptimized = true;
|
|
184
|
+
}
|
|
182
185
|
log(getStats(registry, generateMangledNames(registry, manglePrefix)));
|
|
183
186
|
for (const [fileName, asset] of cssAssets) {
|
|
184
187
|
const transformed = transformCode(asset.source, registry);
|