@csszyx/unplugin 0.9.0 → 0.9.2
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.cjs +19 -2
- package/dist/index.d.cts +91 -5
- package/dist/index.d.mts +90 -3
- package/dist/index.mjs +4 -2
- package/dist/next-prebuild.cjs +148 -0
- package/dist/next-prebuild.d.cts +66 -0
- package/dist/next-prebuild.d.mts +66 -0
- package/dist/next-prebuild.mjs +131 -0
- package/dist/next-turbo-loader.cjs +210 -0
- package/dist/next-turbo-loader.d.cts +68 -0
- package/dist/next-turbo-loader.d.mts +66 -0
- package/dist/next-turbo-loader.mjs +190 -0
- package/dist/next-watcher.cjs +237 -0
- package/dist/next-watcher.d.cts +106 -0
- package/dist/next-watcher.d.mts +106 -0
- package/dist/next-watcher.mjs +219 -0
- package/dist/shared/unplugin.8er8o6rn.mjs +276 -0
- package/dist/shared/unplugin.B_U4rZvG.cjs +281 -0
- package/dist/shared/{unplugin.BEOG6ePC.mjs → unplugin.BbtspS8t.mjs} +1436 -324
- package/dist/shared/unplugin.BceVw1eW.mjs +184 -0
- package/dist/shared/unplugin.BtQzlC2C.mjs +567 -0
- package/dist/shared/{unplugin.CL0F6RZa.cjs → unplugin.CFp386gH.cjs} +1456 -327
- package/dist/shared/unplugin.CPEWNSA0.d.cts +77 -0
- package/dist/shared/unplugin.CPEWNSA0.d.mts +77 -0
- package/dist/shared/unplugin.CScQRdTp.d.cts +15 -0
- package/dist/shared/unplugin.CScQRdTp.d.mts +15 -0
- package/dist/shared/unplugin.CdZxp0x-.d.mts +16 -0
- package/dist/shared/unplugin.DLrBgECN.d.cts +282 -0
- package/dist/shared/unplugin.DLrBgECN.d.mts +282 -0
- package/dist/shared/unplugin.DUxdYaSG.cjs +205 -0
- package/dist/shared/unplugin.s62yJbu1.cjs +591 -0
- package/dist/shared/unplugin.xeED_qwh.d.cts +16 -0
- package/dist/vite.cjs +3 -1
- package/dist/vite.d.cts +2 -1
- package/dist/vite.d.mts +2 -1
- package/dist/vite.mjs +3 -1
- package/dist/webpack.cjs +3 -1
- package/dist/webpack.d.cts +2 -1
- package/dist/webpack.d.mts +2 -1
- package/dist/webpack.mjs +3 -1
- package/package.json +41 -8
- package/dist/shared/unplugin.DUbr5w-N.d.cts +0 -49
- package/dist/shared/unplugin.DUbr5w-N.d.mts +0 -49
|
@@ -5,14 +5,441 @@ import * as path from 'node:path';
|
|
|
5
5
|
import { dirname } from 'node:path';
|
|
6
6
|
import { performance } from 'node:perf_hooks';
|
|
7
7
|
import { fileURLToPath } from 'node:url';
|
|
8
|
-
import { ensureRustTransformAvailable, transformSourceCode, transformRust, transformOxc, transform } from '@csszyx/compiler';
|
|
8
|
+
import { scanGlobalVarUsages, ensureRustTransformAvailable, transformSourceCode, transformRust, transformOxc, transformRustBatch, transform } from '@csszyx/compiler';
|
|
9
9
|
import { encode, compute_mangle_checksum } from '@csszyx/core';
|
|
10
10
|
import { preprocess as preprocess$1 } from '@csszyx/svelte-adapter';
|
|
11
|
-
import { DEFAULT_BUILD_CONFIG } from '@csszyx/types';
|
|
11
|
+
import { isTailwindReservedCustomProperty, CSSZYX_GLOBAL_ALIAS_PREFIX, isCsszyxGlobalAliasCustomProperty, DEFAULT_BUILD_CONFIG, validateGlobalVarMangleConfig } from '@csszyx/types';
|
|
12
12
|
import { preprocess } from '@csszyx/vue-adapter';
|
|
13
13
|
import { createUnplugin } from 'unplugin';
|
|
14
14
|
import { mangleCSSSync } from '../css-mangler.mjs';
|
|
15
15
|
import { createHash } from 'node:crypto';
|
|
16
|
+
import { r as resolveTransformCacheDir, c as createTransformCacheKey, a as readTransformCache, w as writeTransformCache, e as evictOldTransformCacheEntries } from './unplugin.BceVw1eW.mjs';
|
|
17
|
+
import postcss from 'postcss';
|
|
18
|
+
import valueParser from 'postcss-value-parser';
|
|
19
|
+
|
|
20
|
+
function resolveGlobalVarScanCacheDir(cacheDir) {
|
|
21
|
+
return path.join(cacheDir, "global-vars");
|
|
22
|
+
}
|
|
23
|
+
function createGlobalVarScanCacheKey(input) {
|
|
24
|
+
const hash = createHash("sha256");
|
|
25
|
+
hash.update(input.filePath);
|
|
26
|
+
hash.update("\0");
|
|
27
|
+
hash.update(String(input.mtimeMs));
|
|
28
|
+
hash.update("\0");
|
|
29
|
+
hash.update(createHash("sha256").update(input.css).digest("hex"));
|
|
30
|
+
return hash.digest("hex");
|
|
31
|
+
}
|
|
32
|
+
function readGlobalVarScanCache(cacheDir, key) {
|
|
33
|
+
try {
|
|
34
|
+
const raw = fs.readFileSync(globalVarScanCacheFile(cacheDir, key), "utf8");
|
|
35
|
+
const entry = JSON.parse(raw);
|
|
36
|
+
if (entry.key !== key || !entry.result) {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
return entry.result;
|
|
40
|
+
} catch {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function writeGlobalVarScanCache(cacheDir, key, result) {
|
|
45
|
+
try {
|
|
46
|
+
fs.mkdirSync(cacheDir, { recursive: true });
|
|
47
|
+
fs.writeFileSync(
|
|
48
|
+
globalVarScanCacheFile(cacheDir, key),
|
|
49
|
+
JSON.stringify({ key, result }),
|
|
50
|
+
"utf8"
|
|
51
|
+
);
|
|
52
|
+
} catch {
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function globalVarScanCacheFile(cacheDir, key) {
|
|
56
|
+
return path.join(cacheDir, `${key}.json`);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const DEFAULT_SCOPE_ID = "<root>";
|
|
60
|
+
function isInsideThemeAtRule(node) {
|
|
61
|
+
let current = node.parent;
|
|
62
|
+
while (current && current.type !== "root") {
|
|
63
|
+
if (current.type === "atrule" && current.name === "theme") {
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
current = current.parent;
|
|
67
|
+
}
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
function hasSiblingDeclaration(decl, prop) {
|
|
71
|
+
const parent = decl.parent;
|
|
72
|
+
if (!parent || !("nodes" in parent)) {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
return parent.nodes.some((node) => node.type === "decl" && node.prop === prop);
|
|
76
|
+
}
|
|
77
|
+
function nodeLocation(node, filePath) {
|
|
78
|
+
return {
|
|
79
|
+
filePath,
|
|
80
|
+
line: node.source?.start?.line ?? 1,
|
|
81
|
+
column: node.source?.start?.column ?? 1
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
function buildScopeId(node) {
|
|
85
|
+
const parts = [];
|
|
86
|
+
let current = node.parent;
|
|
87
|
+
while (current && current.type !== "root") {
|
|
88
|
+
if (current.type === "rule") {
|
|
89
|
+
parts.push(`rule:${current.selector}`);
|
|
90
|
+
} else if (current.type === "atrule") {
|
|
91
|
+
const atRule = current;
|
|
92
|
+
parts.push(`@${atRule.name} ${atRule.params}`.trim());
|
|
93
|
+
}
|
|
94
|
+
current = current.parent;
|
|
95
|
+
}
|
|
96
|
+
return parts.reverse().join(" > ") || DEFAULT_SCOPE_ID;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const VAR_REFERENCE_RE = /var\(\s*(--[\w-]+)/g;
|
|
100
|
+
function scanGlobalVarCss(css, options = {}) {
|
|
101
|
+
const filePath = options.filePath ?? "<inline>";
|
|
102
|
+
const root = postcss.parse(css, { from: filePath });
|
|
103
|
+
const registered = collectRegisteredProperties(root);
|
|
104
|
+
const definitions = [];
|
|
105
|
+
const references = [];
|
|
106
|
+
root.walkDecls((decl) => {
|
|
107
|
+
const scopeId = buildScopeId(decl);
|
|
108
|
+
const tailwindOwned = isInsideThemeAtRule(decl);
|
|
109
|
+
if (decl.prop.startsWith("--")) {
|
|
110
|
+
definitions.push({
|
|
111
|
+
name: decl.prop,
|
|
112
|
+
scopeId,
|
|
113
|
+
tailwindOwned,
|
|
114
|
+
registered: registered.has(decl.prop),
|
|
115
|
+
...nodeLocation(decl, filePath)
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
for (const name of extractVarReferences(decl.value)) {
|
|
119
|
+
references.push({
|
|
120
|
+
name,
|
|
121
|
+
scopeId,
|
|
122
|
+
owner: decl.prop,
|
|
123
|
+
tailwindOwned,
|
|
124
|
+
...nodeLocation(decl, filePath)
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
root.walkAtRules((atRule) => {
|
|
129
|
+
if (atRule.name === "property") {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
for (const name of extractVarReferences(atRule.params)) {
|
|
133
|
+
references.push({
|
|
134
|
+
name,
|
|
135
|
+
scopeId: buildScopeId(atRule),
|
|
136
|
+
owner: `@${atRule.name}`,
|
|
137
|
+
tailwindOwned: isInsideThemeAtRule(atRule),
|
|
138
|
+
...nodeLocation(atRule, filePath)
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
return {
|
|
143
|
+
filePath,
|
|
144
|
+
definitions,
|
|
145
|
+
references,
|
|
146
|
+
registered: [...registered].sort(),
|
|
147
|
+
thirdParty: isThirdPartyCssPath(filePath)
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
function collectRegisteredProperties(root) {
|
|
151
|
+
const registered = /* @__PURE__ */ new Set();
|
|
152
|
+
root.walkAtRules("property", (atRule) => {
|
|
153
|
+
const name = atRule.params.trim();
|
|
154
|
+
if (name.startsWith("--")) {
|
|
155
|
+
registered.add(name);
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
return registered;
|
|
159
|
+
}
|
|
160
|
+
function extractVarReferences(value) {
|
|
161
|
+
const references = /* @__PURE__ */ new Set();
|
|
162
|
+
for (const match of value.matchAll(VAR_REFERENCE_RE)) {
|
|
163
|
+
references.add(match[1]);
|
|
164
|
+
}
|
|
165
|
+
return [...references].sort();
|
|
166
|
+
}
|
|
167
|
+
function isThirdPartyCssPath(filePath) {
|
|
168
|
+
return filePath.split(/[\\/]/).includes("node_modules");
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function planGlobalVarAliases(input) {
|
|
172
|
+
const definitions = flattenDefinitions(input.scans);
|
|
173
|
+
const candidates = collectCandidates(input, definitions);
|
|
174
|
+
const aliasPrefix = input.aliasPrefix ?? CSSZYX_GLOBAL_ALIAS_PREFIX;
|
|
175
|
+
const diagnostics = validateCandidates(
|
|
176
|
+
candidates,
|
|
177
|
+
definitions,
|
|
178
|
+
input.reserved ?? [],
|
|
179
|
+
aliasPrefix
|
|
180
|
+
);
|
|
181
|
+
if (diagnostics.length > 0) {
|
|
182
|
+
return { entries: [], aliases: /* @__PURE__ */ new Map(), diagnostics };
|
|
183
|
+
}
|
|
184
|
+
const definitionNames = new Set(definitions.keys());
|
|
185
|
+
const entries = [];
|
|
186
|
+
for (const [index, original] of candidates.entries()) {
|
|
187
|
+
const alias = `${aliasPrefix}${encode(index)}`;
|
|
188
|
+
if (definitionNames.has(alias)) {
|
|
189
|
+
return {
|
|
190
|
+
entries: [],
|
|
191
|
+
aliases: /* @__PURE__ */ new Map(),
|
|
192
|
+
diagnostics: [
|
|
193
|
+
{
|
|
194
|
+
code: "alias-collision",
|
|
195
|
+
severity: "error",
|
|
196
|
+
name: alias,
|
|
197
|
+
message: `Generated alias ${alias} collides with an existing CSS custom property.`,
|
|
198
|
+
location: definitions.get(alias)?.[0]
|
|
199
|
+
}
|
|
200
|
+
]
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
entries.push({
|
|
204
|
+
original,
|
|
205
|
+
alias,
|
|
206
|
+
scopes: [
|
|
207
|
+
...new Set((definitions.get(original) ?? []).map((definition) => definition.scopeId))
|
|
208
|
+
].sort()
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
return {
|
|
212
|
+
entries,
|
|
213
|
+
aliases: new Map(entries.map((entry) => [entry.original, entry.alias])),
|
|
214
|
+
diagnostics: []
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
function isTailwindReservedGlobalVar(name) {
|
|
218
|
+
return isTailwindReservedCustomProperty(name);
|
|
219
|
+
}
|
|
220
|
+
function flattenDefinitions(scans) {
|
|
221
|
+
const definitions = /* @__PURE__ */ new Map();
|
|
222
|
+
for (const scan of scans) {
|
|
223
|
+
for (const definition of scan.definitions) {
|
|
224
|
+
const existing = definitions.get(definition.name) ?? [];
|
|
225
|
+
existing.push(definition);
|
|
226
|
+
definitions.set(definition.name, existing);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return definitions;
|
|
230
|
+
}
|
|
231
|
+
function collectCandidates(input, definitions) {
|
|
232
|
+
const candidates = new Set(input.tokens ?? []);
|
|
233
|
+
const autoPrefix = input.autoPrefix ?? "";
|
|
234
|
+
if (autoPrefix !== "") {
|
|
235
|
+
for (const name of definitions.keys()) {
|
|
236
|
+
if (name.startsWith(autoPrefix)) {
|
|
237
|
+
candidates.add(name);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
return [...candidates].sort();
|
|
242
|
+
}
|
|
243
|
+
function validateCandidates(candidates, definitions, reserved, aliasPrefix) {
|
|
244
|
+
const diagnostics = [];
|
|
245
|
+
for (const name of candidates) {
|
|
246
|
+
const tokenDefinitions = definitions.get(name) ?? [];
|
|
247
|
+
if (tokenDefinitions.length === 0) {
|
|
248
|
+
diagnostics.push({
|
|
249
|
+
code: "missing-definition",
|
|
250
|
+
severity: "error",
|
|
251
|
+
name,
|
|
252
|
+
message: `Global variable token ${name} is not defined in scanned CSS.`
|
|
253
|
+
});
|
|
254
|
+
continue;
|
|
255
|
+
}
|
|
256
|
+
if (isTailwindReservedGlobalVar(name) || matchesUserReserved(name, reserved)) {
|
|
257
|
+
diagnostics.push({
|
|
258
|
+
code: "tailwind-reserved",
|
|
259
|
+
severity: "error",
|
|
260
|
+
name,
|
|
261
|
+
message: `Global variable token ${name} is reserved and cannot be aliased.`,
|
|
262
|
+
location: tokenDefinitions[0]
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
if (isCsszyxGlobalAliasCustomProperty(name, aliasPrefix)) {
|
|
266
|
+
diagnostics.push({
|
|
267
|
+
code: "tailwind-reserved",
|
|
268
|
+
severity: "error",
|
|
269
|
+
name,
|
|
270
|
+
message: `Global variable token ${name} uses csszyx reserved namespace ${aliasPrefix}* and cannot be aliased.`,
|
|
271
|
+
location: tokenDefinitions[0]
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
const tailwindDefinition = tokenDefinitions.find((definition) => definition.tailwindOwned);
|
|
275
|
+
if (tailwindDefinition) {
|
|
276
|
+
diagnostics.push({
|
|
277
|
+
code: "tailwind-owned",
|
|
278
|
+
severity: "error",
|
|
279
|
+
name,
|
|
280
|
+
message: `Global variable token ${name} is declared inside @theme and cannot be aliased.`,
|
|
281
|
+
location: tailwindDefinition
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
const registeredDefinition = tokenDefinitions.find((definition) => definition.registered);
|
|
285
|
+
if (registeredDefinition) {
|
|
286
|
+
diagnostics.push({
|
|
287
|
+
code: "registered-property",
|
|
288
|
+
severity: "error",
|
|
289
|
+
name,
|
|
290
|
+
message: `Registered custom property ${name} is not aliasable in Phase H v1.`,
|
|
291
|
+
location: registeredDefinition
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
return diagnostics;
|
|
296
|
+
}
|
|
297
|
+
function matchesUserReserved(name, reserved) {
|
|
298
|
+
return reserved.some((pattern) => {
|
|
299
|
+
if (pattern.endsWith("*")) {
|
|
300
|
+
return name.startsWith(pattern.slice(0, -1));
|
|
301
|
+
}
|
|
302
|
+
return name === pattern;
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
function rewriteGlobalVarCssAliases(options) {
|
|
307
|
+
if (options.plan.diagnostics.length > 0 || options.plan.entries.length === 0) {
|
|
308
|
+
return {
|
|
309
|
+
css: options.css,
|
|
310
|
+
aliasDeclarations: 0,
|
|
311
|
+
rewrittenReferences: 0,
|
|
312
|
+
diagnostics: options.plan.diagnostics
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
const root = postcss.parse(options.css, { from: options.filePath });
|
|
316
|
+
const aliasNames = new Set(options.plan.entries.map((entry) => entry.alias));
|
|
317
|
+
const referenceAliases = new Map(
|
|
318
|
+
options.plan.entries.filter((entry) => canRewriteGlobalVarReferences(entry)).map((entry) => [entry.original, entry.alias])
|
|
319
|
+
);
|
|
320
|
+
let aliasDeclarations = 0;
|
|
321
|
+
let rewrittenReferences = 0;
|
|
322
|
+
root.walkDecls((decl) => {
|
|
323
|
+
if (isInsideThemeAtRule(decl)) {
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
const alias = options.plan.aliases.get(decl.prop);
|
|
327
|
+
if (alias && !hasSiblingDeclaration(decl, alias)) {
|
|
328
|
+
decl.cloneAfter({ prop: alias, value: `var(${decl.prop})` });
|
|
329
|
+
aliasDeclarations++;
|
|
330
|
+
}
|
|
331
|
+
if (options.plan.aliases.has(decl.prop) || aliasNames.has(decl.prop)) {
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
const rewrite = rewriteGlobalVarValue(decl.value, referenceAliases);
|
|
335
|
+
if (rewrite.count > 0) {
|
|
336
|
+
decl.value = rewrite.value;
|
|
337
|
+
rewrittenReferences += rewrite.count;
|
|
338
|
+
}
|
|
339
|
+
});
|
|
340
|
+
return {
|
|
341
|
+
css: root.toString(),
|
|
342
|
+
aliasDeclarations,
|
|
343
|
+
rewrittenReferences,
|
|
344
|
+
diagnostics: []
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
function canRewriteGlobalVarReferences(entry) {
|
|
348
|
+
return entry.scopes.some(isInheritedGlobalAliasScope);
|
|
349
|
+
}
|
|
350
|
+
function isInheritedGlobalAliasScope(scope) {
|
|
351
|
+
const leaf = scope.split(" > ").at(-1);
|
|
352
|
+
if (!leaf?.startsWith("rule:")) {
|
|
353
|
+
return false;
|
|
354
|
+
}
|
|
355
|
+
const selector = leaf.slice("rule:".length);
|
|
356
|
+
return selector.split(",").some((part) => {
|
|
357
|
+
const normalized = part.trim();
|
|
358
|
+
return normalized === ":root" || normalized === "html" || normalized === "body";
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
function rewriteGlobalVarValue(value, aliases) {
|
|
362
|
+
const parsed = valueParser(value);
|
|
363
|
+
let count = 0;
|
|
364
|
+
parsed.walk((node) => {
|
|
365
|
+
if (node.type !== "function" || node.value.toLowerCase() !== "var") {
|
|
366
|
+
return;
|
|
367
|
+
}
|
|
368
|
+
const firstArgument = node.nodes.find((child) => child.type !== "space");
|
|
369
|
+
if (!firstArgument || firstArgument.type !== "word") {
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
const alias = aliases.get(firstArgument.value);
|
|
373
|
+
if (!alias) {
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
firstArgument.value = alias;
|
|
377
|
+
count++;
|
|
378
|
+
});
|
|
379
|
+
return { value: count > 0 ? valueParser.stringify(parsed.nodes) : value, count };
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
function validateGlobalVarAliasInputs(options) {
|
|
383
|
+
const scans = options.cssFiles.map(
|
|
384
|
+
(file) => scanCssSourceWithOptionalCache(file, options.cacheDir)
|
|
385
|
+
);
|
|
386
|
+
const plan = planGlobalVarAliases({
|
|
387
|
+
scans,
|
|
388
|
+
tokens: options.tokens,
|
|
389
|
+
autoPrefix: options.autoPrefix,
|
|
390
|
+
aliasPrefix: options.aliasPrefix,
|
|
391
|
+
reserved: options.reserved
|
|
392
|
+
});
|
|
393
|
+
if (plan.diagnostics.length > 0 || plan.entries.length === 0) {
|
|
394
|
+
return { scans, plan, usageDiagnostics: [] };
|
|
395
|
+
}
|
|
396
|
+
const candidateTokens = plan.entries.map((entry) => entry.original);
|
|
397
|
+
const usageDiagnostics = (options.sourceFiles ?? []).flatMap(
|
|
398
|
+
(file) => scanGlobalVarUsages(file.code, file.filePath, { tokens: candidateTokens })
|
|
399
|
+
);
|
|
400
|
+
return { scans, plan, usageDiagnostics };
|
|
401
|
+
}
|
|
402
|
+
function createGlobalVarAliasValidationOptions(input) {
|
|
403
|
+
return {
|
|
404
|
+
cssFiles: input.cssAssets.filter((asset) => /\.css(?:$|\?)/.test(asset.fileName)).map((asset) => ({
|
|
405
|
+
filePath: normalizeBuildAssetPath(input.rootDir, asset.fileName),
|
|
406
|
+
css: cssAssetSourceToString(asset.source),
|
|
407
|
+
mtimeMs: asset.mtimeMs
|
|
408
|
+
})),
|
|
409
|
+
sourceFiles: input.sourceFiles ?? [],
|
|
410
|
+
tokens: input.tokens,
|
|
411
|
+
autoPrefix: input.autoPrefix,
|
|
412
|
+
aliasPrefix: input.aliasPrefix,
|
|
413
|
+
reserved: input.reserved,
|
|
414
|
+
cacheDir: input.cacheDir
|
|
415
|
+
};
|
|
416
|
+
}
|
|
417
|
+
function scanCssSourceWithOptionalCache(file, cacheDir) {
|
|
418
|
+
if (cacheDir === void 0 || file.mtimeMs === void 0) {
|
|
419
|
+
return scanGlobalVarCss(file.css, { filePath: file.filePath });
|
|
420
|
+
}
|
|
421
|
+
const key = createGlobalVarScanCacheKey({
|
|
422
|
+
filePath: file.filePath,
|
|
423
|
+
css: file.css,
|
|
424
|
+
mtimeMs: file.mtimeMs
|
|
425
|
+
});
|
|
426
|
+
const cached = readGlobalVarScanCache(cacheDir, key);
|
|
427
|
+
if (cached) {
|
|
428
|
+
return cached;
|
|
429
|
+
}
|
|
430
|
+
const result = scanGlobalVarCss(file.css, { filePath: file.filePath });
|
|
431
|
+
writeGlobalVarScanCache(cacheDir, key, result);
|
|
432
|
+
return result;
|
|
433
|
+
}
|
|
434
|
+
function normalizeBuildAssetPath(rootDir, fileName) {
|
|
435
|
+
return (path.isAbsolute(fileName) ? fileName : path.join(rootDir, fileName)).replace(
|
|
436
|
+
/\\/g,
|
|
437
|
+
"/"
|
|
438
|
+
);
|
|
439
|
+
}
|
|
440
|
+
function cssAssetSourceToString(source) {
|
|
441
|
+
return typeof source === "string" ? source : Buffer.from(source).toString("utf8");
|
|
442
|
+
}
|
|
16
443
|
|
|
17
444
|
const SERVER_DIRECTIVE_RE = /^['"]use server['"];?$/;
|
|
18
445
|
const CLIENT_DIRECTIVE_RE = /^['"]use client['"];?$/;
|
|
@@ -253,24 +680,18 @@ function skipWhitespaceAndComments(code, start) {
|
|
|
253
680
|
function findRuntimeImports(code) {
|
|
254
681
|
const imports = [];
|
|
255
682
|
const scanCode = stripCommentsForImportScan(code);
|
|
256
|
-
const staticImportRe = /import\s+(?!type\b)(\S(?:.*\S)?)\s+from\s+['"]([^'"]+)['"]/g;
|
|
257
|
-
const sideEffectImportRe = /import\s+['"]([^'"]+)['"]/g;
|
|
258
683
|
const dynamicImportRe = /import\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
|
|
259
|
-
for (const
|
|
260
|
-
const clause = match[1];
|
|
261
|
-
const source = match[2];
|
|
684
|
+
for (const { clause, source } of findStaticImports(scanCode)) {
|
|
262
685
|
if (!isRuntimeImportSource(source)) {
|
|
263
686
|
continue;
|
|
264
687
|
}
|
|
265
|
-
|
|
266
|
-
}
|
|
267
|
-
for (const match of scanCode.matchAll(sideEffectImportRe)) {
|
|
268
|
-
const source = match[1];
|
|
269
|
-
if (isRuntimeImportSource(source)) {
|
|
688
|
+
if (clause === null) {
|
|
270
689
|
imports.push({
|
|
271
690
|
source,
|
|
272
691
|
symbols: isWholeRuntimeModuleForbidden(source) ? Array.from(FORBIDDEN_SYMBOLS) : []
|
|
273
692
|
});
|
|
693
|
+
} else {
|
|
694
|
+
imports.push({ source, symbols: readRuntimeImportSymbols(source, clause) });
|
|
274
695
|
}
|
|
275
696
|
}
|
|
276
697
|
for (const match of scanCode.matchAll(dynamicImportRe)) {
|
|
@@ -281,6 +702,98 @@ function findRuntimeImports(code) {
|
|
|
281
702
|
}
|
|
282
703
|
return imports;
|
|
283
704
|
}
|
|
705
|
+
function findStaticImports(code) {
|
|
706
|
+
const imports = [];
|
|
707
|
+
let cursor = 0;
|
|
708
|
+
while (cursor < code.length) {
|
|
709
|
+
const importStart = code.indexOf("import", cursor);
|
|
710
|
+
if (importStart === -1) {
|
|
711
|
+
break;
|
|
712
|
+
}
|
|
713
|
+
cursor = importStart + 6;
|
|
714
|
+
if (importStart > 0 && isIdentifierPart(code.charCodeAt(importStart - 1)) || isIdentifierPart(code.charCodeAt(cursor))) {
|
|
715
|
+
continue;
|
|
716
|
+
}
|
|
717
|
+
let position = skipAsciiWhitespace(code, cursor);
|
|
718
|
+
const opener = code.charAt(position);
|
|
719
|
+
if (opener === "(") {
|
|
720
|
+
continue;
|
|
721
|
+
}
|
|
722
|
+
if (opener === '"' || opener === "'") {
|
|
723
|
+
const literal2 = readQuotedString(code, position);
|
|
724
|
+
if (literal2) {
|
|
725
|
+
imports.push({ clause: null, source: literal2.value });
|
|
726
|
+
cursor = literal2.end;
|
|
727
|
+
}
|
|
728
|
+
continue;
|
|
729
|
+
}
|
|
730
|
+
const clauseStart = position;
|
|
731
|
+
let fromStart = -1;
|
|
732
|
+
while (position < code.length) {
|
|
733
|
+
if (code.startsWith("from", position) && (position === clauseStart || !isIdentifierPart(code.charCodeAt(position - 1))) && !isIdentifierPart(code.charCodeAt(position + 4))) {
|
|
734
|
+
fromStart = position;
|
|
735
|
+
break;
|
|
736
|
+
}
|
|
737
|
+
if (code.charAt(position) === ";") {
|
|
738
|
+
break;
|
|
739
|
+
}
|
|
740
|
+
position += 1;
|
|
741
|
+
}
|
|
742
|
+
if (fromStart === -1) {
|
|
743
|
+
continue;
|
|
744
|
+
}
|
|
745
|
+
const clause = code.slice(clauseStart, fromStart).trim();
|
|
746
|
+
if (splitAsciiWhitespace(clause)[0] === "type") {
|
|
747
|
+
cursor = fromStart + 4;
|
|
748
|
+
continue;
|
|
749
|
+
}
|
|
750
|
+
position = skipAsciiWhitespace(code, fromStart + 4);
|
|
751
|
+
const literal = readQuotedString(code, position);
|
|
752
|
+
if (literal) {
|
|
753
|
+
imports.push({ clause, source: literal.value });
|
|
754
|
+
cursor = literal.end;
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
return imports;
|
|
758
|
+
}
|
|
759
|
+
function readQuotedString(code, start) {
|
|
760
|
+
const quote = code.charAt(start);
|
|
761
|
+
if (quote !== '"' && quote !== "'") {
|
|
762
|
+
return null;
|
|
763
|
+
}
|
|
764
|
+
let value = "";
|
|
765
|
+
for (let index = start + 1; index < code.length; index += 1) {
|
|
766
|
+
const char = code.charAt(index);
|
|
767
|
+
if (char === "\\") {
|
|
768
|
+
if (index + 1 >= code.length) {
|
|
769
|
+
return null;
|
|
770
|
+
}
|
|
771
|
+
value += code.charAt(index + 1);
|
|
772
|
+
index += 1;
|
|
773
|
+
} else if (char === quote) {
|
|
774
|
+
return { end: index + 1, value };
|
|
775
|
+
} else if (char === "\n" || char === "\r") {
|
|
776
|
+
return null;
|
|
777
|
+
} else {
|
|
778
|
+
value += char;
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
return null;
|
|
782
|
+
}
|
|
783
|
+
function skipAsciiWhitespace(code, start) {
|
|
784
|
+
let index = start;
|
|
785
|
+
while (index < code.length) {
|
|
786
|
+
const charCode = code.charCodeAt(index);
|
|
787
|
+
if (charCode !== 9 && charCode !== 10 && charCode !== 13 && charCode !== 32) {
|
|
788
|
+
break;
|
|
789
|
+
}
|
|
790
|
+
index += 1;
|
|
791
|
+
}
|
|
792
|
+
return index;
|
|
793
|
+
}
|
|
794
|
+
function isIdentifierPart(code) {
|
|
795
|
+
return isIdentifierStart(code) || code >= 48 && code <= 57;
|
|
796
|
+
}
|
|
284
797
|
function isRuntimeImportSource(source) {
|
|
285
798
|
return RUNTIME_HELPER_MODULES.has(source) || source.startsWith("@csszyx/runtime/") || CLIENT_RUNTIME_MODULES.has(source) || CLIENT_RUNTIME_MODULE_ROOTS.some((root) => source === root || source.startsWith(`${root}/`));
|
|
286
799
|
}
|
|
@@ -344,10 +857,17 @@ function resolveLocalModule(importer, source) {
|
|
|
344
857
|
path.join(base, "index.js")
|
|
345
858
|
];
|
|
346
859
|
for (const candidate of candidates) {
|
|
347
|
-
|
|
860
|
+
try {
|
|
861
|
+
if (!fs.statSync(candidate).isFile()) {
|
|
862
|
+
continue;
|
|
863
|
+
}
|
|
348
864
|
const resolved = normalizeModuleId(candidate);
|
|
349
865
|
resolvedLocalModuleCache.set(cacheKey, resolved);
|
|
350
866
|
return resolved;
|
|
867
|
+
} catch (error) {
|
|
868
|
+
if (error.code !== "ENOENT") {
|
|
869
|
+
throw error;
|
|
870
|
+
}
|
|
351
871
|
}
|
|
352
872
|
}
|
|
353
873
|
return null;
|
|
@@ -367,32 +887,67 @@ function pruneRSCModulePathCaches(moduleIds) {
|
|
|
367
887
|
}
|
|
368
888
|
function readImportedSymbols(clause) {
|
|
369
889
|
const symbols = [];
|
|
370
|
-
const
|
|
371
|
-
|
|
372
|
-
|
|
890
|
+
const openBrace = clause.indexOf("{");
|
|
891
|
+
const closeBrace = openBrace === -1 ? -1 : clause.indexOf("}", openBrace);
|
|
892
|
+
if (openBrace !== -1 && closeBrace !== -1) {
|
|
893
|
+
const namedPart = clause.slice(openBrace + 1, closeBrace);
|
|
894
|
+
for (const part of namedPart.split(",")) {
|
|
373
895
|
const trimmed = part.trim();
|
|
374
896
|
if (!trimmed || trimmed.startsWith("type ")) {
|
|
375
897
|
continue;
|
|
376
898
|
}
|
|
377
|
-
const sourceName = trimmed.replace(/^type\
|
|
899
|
+
const sourceName = trimmed.replace(/^type[ \t]+/, "").split(/[ \t]+as[ \t]+/)[0]?.trim();
|
|
378
900
|
if (sourceName) {
|
|
379
901
|
symbols.push(sourceName);
|
|
380
902
|
}
|
|
381
903
|
}
|
|
382
904
|
}
|
|
383
|
-
|
|
905
|
+
const namespaceParts = splitAsciiWhitespace(clause);
|
|
906
|
+
if (namespaceParts.length >= 3 && namespaceParts[0] === "*" && namespaceParts[1] === "as" && isIdentifier(namespaceParts[2] ?? "")) {
|
|
384
907
|
symbols.push(...FORBIDDEN_SYMBOLS);
|
|
385
908
|
}
|
|
386
909
|
const braceStart = clause.indexOf("{");
|
|
387
910
|
const braceEnd = clause.indexOf("}", braceStart);
|
|
388
911
|
const stripped = braceStart !== -1 && braceEnd !== -1 ? clause.slice(0, braceStart) + clause.slice(braceEnd + 1) : clause;
|
|
389
|
-
const
|
|
390
|
-
const defaultSymbol =
|
|
912
|
+
const defaultCandidate = stripped.trimStart().split(",", 1)[0]?.trim() ?? "";
|
|
913
|
+
const defaultSymbol = isIdentifier(defaultCandidate) ? defaultCandidate : void 0;
|
|
391
914
|
if (defaultSymbol && FORBIDDEN_SYMBOLS.has(defaultSymbol)) {
|
|
392
915
|
symbols.push(defaultSymbol);
|
|
393
916
|
}
|
|
394
917
|
return symbols;
|
|
395
918
|
}
|
|
919
|
+
function isIdentifier(value) {
|
|
920
|
+
if (value.length === 0 || !isIdentifierStart(value.charCodeAt(0))) {
|
|
921
|
+
return false;
|
|
922
|
+
}
|
|
923
|
+
for (let index = 1; index < value.length; index += 1) {
|
|
924
|
+
const code = value.charCodeAt(index);
|
|
925
|
+
if (!isIdentifierStart(code) && (code < 48 || code > 57)) {
|
|
926
|
+
return false;
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
return true;
|
|
930
|
+
}
|
|
931
|
+
function isIdentifierStart(code) {
|
|
932
|
+
return code === 36 || code === 95 || code >= 65 && code <= 90 || code >= 97 && code <= 122;
|
|
933
|
+
}
|
|
934
|
+
function splitAsciiWhitespace(value) {
|
|
935
|
+
const parts = [];
|
|
936
|
+
let start = -1;
|
|
937
|
+
for (let index = 0; index <= value.length; index += 1) {
|
|
938
|
+
const code = index < value.length ? value.charCodeAt(index) : 32;
|
|
939
|
+
const whitespace = code === 9 || code === 10 || code === 13 || code === 32;
|
|
940
|
+
if (whitespace) {
|
|
941
|
+
if (start !== -1) {
|
|
942
|
+
parts.push(value.slice(start, index));
|
|
943
|
+
start = -1;
|
|
944
|
+
}
|
|
945
|
+
} else if (start === -1) {
|
|
946
|
+
start = index;
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
return parts;
|
|
950
|
+
}
|
|
396
951
|
function stripCommentsForImportScan(code) {
|
|
397
952
|
let out = "";
|
|
398
953
|
let i = 0;
|
|
@@ -704,6 +1259,10 @@ function expandFilePatterns(rootDir, patterns) {
|
|
|
704
1259
|
return Array.from(files).sort();
|
|
705
1260
|
}
|
|
706
1261
|
|
|
1262
|
+
function safeJsonForScriptTag(value, prettyPrint = false) {
|
|
1263
|
+
const json = prettyPrint ? JSON.stringify(value, null, 2) : JSON.stringify(value);
|
|
1264
|
+
return json.replace(/</g, "\\u003C").replace(/>/g, "\\u003E").replace(/&/g, "\\u0026").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
|
|
1265
|
+
}
|
|
707
1266
|
function injectChecksum(html, checksum, minify = false) {
|
|
708
1267
|
const attrName = minify ? "data-sz-cs" : "data-sz-checksum";
|
|
709
1268
|
const htmlTagPattern = /<html([^>]*)>/i;
|
|
@@ -716,10 +1275,18 @@ function injectChecksum(html, checksum, minify = false) {
|
|
|
716
1275
|
return html.replace(htmlTagPattern, `<html${checksumAttr}${existingAttrs}>`);
|
|
717
1276
|
}
|
|
718
1277
|
function injectMangleMapScript(html, mangleMap, options = {}) {
|
|
719
|
-
const {
|
|
720
|
-
|
|
1278
|
+
const {
|
|
1279
|
+
prettyPrint = false,
|
|
1280
|
+
varMangleMap = {},
|
|
1281
|
+
globalVarAliasPrefix = CSSZYX_GLOBAL_ALIAS_PREFIX
|
|
1282
|
+
} = options;
|
|
1283
|
+
const checksumMap = createHydrationMangleMap(mangleMap, varMangleMap);
|
|
1284
|
+
const jsonContent = safeJsonForScriptTag(checksumMap, prettyPrint);
|
|
1285
|
+
const classMapContent = safeJsonForScriptTag(mangleMap);
|
|
1286
|
+
const varMapContent = safeJsonForScriptTag(varMangleMap);
|
|
721
1287
|
const scriptTag = `<script id="__CSSZYX_MANGLE_MAP__" type="application/json">${jsonContent}<\/script>`;
|
|
722
|
-
const
|
|
1288
|
+
const prefixContent = safeJsonForScriptTag(globalVarAliasPrefix);
|
|
1289
|
+
const debugScript = `<script>(function(){var m=${classMapContent};var vm=${varMapContent};var gp=${prefixContent};var r={};var vr={};for(var k in m)r[m[k]]=k;for(var vk in vm){var vv=vm[vk];var vs=Array.isArray(vv)?vv:[vv];for(var vi=0;vi<vs.length;vi++)(vr[vs[vi]]||(vr[vs[vi]]=[])).push(vk)}var cs=document.documentElement.getAttribute("data-sz-checksum")||"";window.__csszyx={mangleMap:m,varMangleMap:vm,checksum:cs,decode:function(c){return r[c]},encode:function(c){return m[c]},decodeVar:function(v){return vr[v]||[]},encodeVar:function(v){return vm[v]},decodeGlobalVar:function(v){var a=vr[v]||[];return v.indexOf(gp)===0?a[0]:void 0},decodeAll:function(el){return(el.className||"").split(" ").map(function(c){return r[c]||c})}}})()<\/script>`;
|
|
723
1290
|
const combined = `${scriptTag}
|
|
724
1291
|
${debugScript}`;
|
|
725
1292
|
if (html.includes("</head>")) {
|
|
@@ -731,9 +1298,9 @@ ${debugScript}`;
|
|
|
731
1298
|
}
|
|
732
1299
|
return html + combined;
|
|
733
1300
|
}
|
|
734
|
-
function injectMangleMapAttribute(html, mangleMap, minify = false) {
|
|
1301
|
+
function injectMangleMapAttribute(html, mangleMap, minify = false, varMangleMap = {}) {
|
|
735
1302
|
const attrName = minify ? "data-sz-m" : "data-sz-map";
|
|
736
|
-
const jsonContent = JSON.stringify(mangleMap);
|
|
1303
|
+
const jsonContent = JSON.stringify(createHydrationMangleMap(mangleMap, varMangleMap));
|
|
737
1304
|
const htmlTagPattern = /<html([^>]*)>/i;
|
|
738
1305
|
const match = html.match(htmlTagPattern);
|
|
739
1306
|
if (!match) {
|
|
@@ -748,11 +1315,11 @@ function injectHydrationData(html, mangleMap, checksum, options = {}) {
|
|
|
748
1315
|
let result = html;
|
|
749
1316
|
result = injectChecksum(result, checksum, minify);
|
|
750
1317
|
if (mode === "inline") {
|
|
751
|
-
result = injectMangleMapAttribute(result, mangleMap, minify);
|
|
1318
|
+
result = injectMangleMapAttribute(result, mangleMap, minify, options.varMangleMap);
|
|
752
1319
|
} else if (mode === "script") {
|
|
753
1320
|
result = injectMangleMapScript(result, mangleMap, options);
|
|
754
1321
|
} else if (mode === "both") {
|
|
755
|
-
result = injectMangleMapAttribute(result, mangleMap, minify);
|
|
1322
|
+
result = injectMangleMapAttribute(result, mangleMap, minify, options.varMangleMap);
|
|
756
1323
|
result = injectMangleMapScript(result, mangleMap, options);
|
|
757
1324
|
}
|
|
758
1325
|
return result;
|
|
@@ -760,6 +1327,25 @@ function injectHydrationData(html, mangleMap, checksum, options = {}) {
|
|
|
760
1327
|
function transformIndexHtml(html, mangleMap, checksum, options = {}) {
|
|
761
1328
|
return injectHydrationData(html, mangleMap, checksum, options);
|
|
762
1329
|
}
|
|
1330
|
+
function createHydrationMangleMap(classMap, varMap = {}) {
|
|
1331
|
+
if (Object.keys(varMap).length === 0) {
|
|
1332
|
+
return classMap;
|
|
1333
|
+
}
|
|
1334
|
+
const payload = {};
|
|
1335
|
+
for (const [key, value] of Object.entries(classMap)) {
|
|
1336
|
+
payload[`class:${key}`] = value;
|
|
1337
|
+
}
|
|
1338
|
+
for (const [key, value] of Object.entries(varMap)) {
|
|
1339
|
+
if (Array.isArray(value)) {
|
|
1340
|
+
for (const mangled of value) {
|
|
1341
|
+
payload[`var:${key}:${mangled}`] = mangled;
|
|
1342
|
+
}
|
|
1343
|
+
} else {
|
|
1344
|
+
payload[`var:${key}`] = value;
|
|
1345
|
+
}
|
|
1346
|
+
}
|
|
1347
|
+
return payload;
|
|
1348
|
+
}
|
|
763
1349
|
function buildRecoveryManifest(tokens, options) {
|
|
764
1350
|
const stripped = options.production === true;
|
|
765
1351
|
const strippedDevOnlyPaths = [];
|
|
@@ -801,6 +1387,36 @@ function injectRecoveryManifest(html, manifest) {
|
|
|
801
1387
|
return html + scriptTag;
|
|
802
1388
|
}
|
|
803
1389
|
|
|
1390
|
+
const DEFAULT_MAX_ATTEMPTS = 3;
|
|
1391
|
+
const NODE_FS = {
|
|
1392
|
+
openSync: fs.openSync,
|
|
1393
|
+
fstatSync: (fd, options) => fs.fstatSync(fd, options),
|
|
1394
|
+
readFileSync: (fd, encoding) => fs.readFileSync(fd, encoding),
|
|
1395
|
+
closeSync: fs.closeSync
|
|
1396
|
+
};
|
|
1397
|
+
function readStableTextFileSnapshotSync(file, maxAttempts = DEFAULT_MAX_ATTEMPTS, fsApi = NODE_FS) {
|
|
1398
|
+
if (!Number.isInteger(maxAttempts) || maxAttempts < 1) {
|
|
1399
|
+
throw new RangeError("maxAttempts must be a positive integer.");
|
|
1400
|
+
}
|
|
1401
|
+
for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
|
|
1402
|
+
const fd = fsApi.openSync(file, "r");
|
|
1403
|
+
try {
|
|
1404
|
+
const before = fsApi.fstatSync(fd, { bigint: true });
|
|
1405
|
+
const source = fsApi.readFileSync(fd, "utf8");
|
|
1406
|
+
const after = fsApi.fstatSync(fd, { bigint: true });
|
|
1407
|
+
if (isSameFileVersion(before, after)) {
|
|
1408
|
+
return { source, mtimeMs: Number(after.mtimeMs) };
|
|
1409
|
+
}
|
|
1410
|
+
} finally {
|
|
1411
|
+
fsApi.closeSync(fd);
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1414
|
+
throw new Error(`CSS source changed while being read: ${file}`);
|
|
1415
|
+
}
|
|
1416
|
+
function isSameFileVersion(before, after) {
|
|
1417
|
+
return before.dev === after.dev && before.ino === after.ino && before.size === after.size && before.mtimeNs === after.mtimeNs && before.ctimeNs === after.ctimeNs;
|
|
1418
|
+
}
|
|
1419
|
+
|
|
804
1420
|
function generateThemeDts(opts) {
|
|
805
1421
|
const { theme, sourceFiles } = opts;
|
|
806
1422
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -847,219 +1463,368 @@ function writeThemeDts(opts) {
|
|
|
847
1463
|
writeFileSync(opts.outputPath, content, "utf-8");
|
|
848
1464
|
}
|
|
849
1465
|
|
|
850
|
-
const
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
}
|
|
854
|
-
function
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
1466
|
+
const VIRTUAL_MODULE_ID = "virtual:csszyx/mangle-map";
|
|
1467
|
+
const RESOLVED_VIRTUAL_MODULE_ID = `\0${VIRTUAL_MODULE_ID}`;
|
|
1468
|
+
const VIRTUAL_CHECKSUM_ID = "virtual:csszyx/checksum";
|
|
1469
|
+
const RESOLVED_VIRTUAL_CHECKSUM_ID = `\0${VIRTUAL_CHECKSUM_ID}`;
|
|
1470
|
+
function createMangleMapModule(mangleMap, checksum, varMangleMap = {}, cssVarMetrics = null) {
|
|
1471
|
+
return `/**
|
|
1472
|
+
* Auto-generated mangle map for csszyx.
|
|
1473
|
+
* This module is generated at build time and contains the mapping
|
|
1474
|
+
* from original class names and CSS variable names to mangled names.
|
|
1475
|
+
*
|
|
1476
|
+
* @generated
|
|
1477
|
+
*/
|
|
1478
|
+
|
|
1479
|
+
export const mangleMap = ${JSON.stringify(mangleMap, null, 2)};
|
|
1480
|
+
|
|
1481
|
+
export const varMangleMap = ${JSON.stringify(varMangleMap, null, 2)};
|
|
1482
|
+
|
|
1483
|
+
export const cssVarMetrics = ${JSON.stringify(cssVarMetrics, null, 2)};
|
|
1484
|
+
|
|
1485
|
+
export const checksum = ${JSON.stringify(checksum)};
|
|
1486
|
+
|
|
1487
|
+
export default {
|
|
1488
|
+
mangleMap,
|
|
1489
|
+
varMangleMap,
|
|
1490
|
+
cssVarMetrics,
|
|
1491
|
+
checksum,
|
|
1492
|
+
};
|
|
1493
|
+
`;
|
|
870
1494
|
}
|
|
871
|
-
function
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
1495
|
+
function createChecksumModule(checksum) {
|
|
1496
|
+
return `/**
|
|
1497
|
+
* Auto-generated checksum for csszyx mangle map.
|
|
1498
|
+
*
|
|
1499
|
+
* @generated
|
|
1500
|
+
*/
|
|
1501
|
+
|
|
1502
|
+
export const checksum = ${JSON.stringify(checksum)};
|
|
1503
|
+
|
|
1504
|
+
export default checksum;
|
|
1505
|
+
`;
|
|
1506
|
+
}
|
|
1507
|
+
function isVirtualModule(id) {
|
|
1508
|
+
return id === VIRTUAL_MODULE_ID || id === VIRTUAL_CHECKSUM_ID;
|
|
1509
|
+
}
|
|
1510
|
+
function resolveVirtualModule(id) {
|
|
1511
|
+
if (id === VIRTUAL_MODULE_ID) {
|
|
1512
|
+
return RESOLVED_VIRTUAL_MODULE_ID;
|
|
879
1513
|
}
|
|
880
|
-
if (
|
|
881
|
-
return
|
|
1514
|
+
if (id === VIRTUAL_CHECKSUM_ID) {
|
|
1515
|
+
return RESOLVED_VIRTUAL_CHECKSUM_ID;
|
|
882
1516
|
}
|
|
883
|
-
return
|
|
1517
|
+
return void 0;
|
|
884
1518
|
}
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
1519
|
+
|
|
1520
|
+
const CHECKSUM_PLACEHOLDER = "___CSSZYX_CHECKSUM___";
|
|
1521
|
+
const MANGLE_MAP_PLACEHOLDER = "___CSSZYX_MANGLE_MAP___";
|
|
1522
|
+
const VAR_MANGLE_MAP_PLACEHOLDER = "___CSSZYX_VAR_MANGLE_MAP___";
|
|
1523
|
+
const UNKNOWN_PACKAGE_VERSION = "0.0.0";
|
|
1524
|
+
const TRANSFORM_CACHE_MAX_AGE_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
1525
|
+
const TRANSFORM_CACHE_MAX_ENTRIES = 1e4;
|
|
1526
|
+
const TRANSFORM_MEMORY_CACHE_MAX_ENTRIES = 1e3;
|
|
1527
|
+
const DEFAULT_VAR_MANGLE_MAP_MAX_BYTES = 100 * 1024;
|
|
1528
|
+
const GLOBAL_VAR_ALIAS_MAP_OWNER = "\0csszyx:global-var-aliases";
|
|
1529
|
+
const DIRECTIVE_PROLOGUE_PREFIX_RE = /^((?:\s|\/\/[^\n]*\n|\/\*(?:[^*]|\*(?!\/))*\*\/)*)(['"]use (?:client|server)['"];?\s*)/;
|
|
1530
|
+
const RUNTIME_HELPER_IMPORT_RE = {
|
|
1531
|
+
_sz: /\{[^}]*\b_sz\b[^}]*\}\s*from\s*['"]@csszyx\/runtime['"]/,
|
|
1532
|
+
_szMerge: /\{[^}]*\b_szMerge\b[^}]*\}\s*from\s*['"]@csszyx\/runtime['"]/,
|
|
1533
|
+
__szColorVar: /\{[^}]*\b__szColorVar\b[^}]*\}\s*from\s*['"]@csszyx\/runtime['"]/
|
|
1534
|
+
};
|
|
1535
|
+
let _hasWarnedTsConfig = false;
|
|
1536
|
+
let _hasWarnedTransformCacheVersion = false;
|
|
1537
|
+
const requireFromHere = createRequire(import.meta.url);
|
|
1538
|
+
const PLUGIN_VERSION = findPackageVersionFromFile(
|
|
1539
|
+
fileURLToPath(import.meta.url),
|
|
1540
|
+
UNKNOWN_PACKAGE_VERSION
|
|
1541
|
+
);
|
|
1542
|
+
const COMPILER_VERSION = findPackageVersionFromModule("@csszyx/compiler", UNKNOWN_PACKAGE_VERSION);
|
|
1543
|
+
const BENCH_TRACE_ENABLED = process.env.CSSZYX_BENCH_TRACE === "1";
|
|
1544
|
+
const BENCH_TRACE_FILE = process.env.CSSZYX_BENCH_TRACE_FILE;
|
|
1545
|
+
function cssVariableEntries(result) {
|
|
1546
|
+
const entries = [];
|
|
1547
|
+
for (const [original, value] of result.cssVariableMap ?? []) {
|
|
1548
|
+
if (Array.isArray(value)) {
|
|
1549
|
+
for (const mangled of value) {
|
|
1550
|
+
entries.push([original, mangled]);
|
|
1551
|
+
}
|
|
1552
|
+
} else {
|
|
1553
|
+
entries.push([original, value]);
|
|
913
1554
|
}
|
|
914
1555
|
}
|
|
1556
|
+
return entries;
|
|
1557
|
+
}
|
|
1558
|
+
function recordFileVarMangleEntries(state, filename, entries) {
|
|
1559
|
+
const normalizedFilename = normalizeSourceFilename(filename);
|
|
1560
|
+
if (entries.length === 0) {
|
|
1561
|
+
state.varMangleEntriesByFile.delete(normalizedFilename);
|
|
1562
|
+
} else {
|
|
1563
|
+
state.varMangleEntriesByFile.set(normalizedFilename, entries);
|
|
1564
|
+
}
|
|
1565
|
+
state.varMangleMap = buildVarMangleMap(state.varMangleEntriesByFile);
|
|
915
1566
|
}
|
|
916
|
-
function
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
1567
|
+
function recordGlobalVarSourceFile(state, filename, code) {
|
|
1568
|
+
const normalizedFilename = normalizeSourceFilename(filename);
|
|
1569
|
+
if (!/\.[tj]sx?(?:\?.*)?$/.test(normalizedFilename)) {
|
|
1570
|
+
return;
|
|
1571
|
+
}
|
|
1572
|
+
if (code === null) {
|
|
1573
|
+
state.globalVarSourceFilesByFile.delete(normalizedFilename);
|
|
1574
|
+
} else {
|
|
1575
|
+
state.globalVarSourceFilesByFile.set(normalizedFilename, code);
|
|
1576
|
+
}
|
|
1577
|
+
}
|
|
1578
|
+
function buildGlobalVarSourceFiles(state) {
|
|
1579
|
+
return [...state.globalVarSourceFilesByFile.entries()].sort(([left], [right]) => left.localeCompare(right)).map(([filePath, code]) => ({ filePath, code }));
|
|
1580
|
+
}
|
|
1581
|
+
function collectRollupGlobalVarCssAssets(bundle) {
|
|
1582
|
+
return Object.values(bundle).filter(
|
|
1583
|
+
(chunk) => chunk.type === "asset" && typeof chunk.fileName === "string" && /\.css(?:$|\?)/.test(chunk.fileName) && (typeof chunk.source === "string" || chunk.source instanceof Uint8Array)
|
|
1584
|
+
).sort((left, right) => left.fileName.localeCompare(right.fileName)).map((asset) => ({
|
|
1585
|
+
fileName: asset.fileName,
|
|
1586
|
+
source: asset.source
|
|
1587
|
+
}));
|
|
1588
|
+
}
|
|
1589
|
+
function collectConfiguredGlobalVarCssSources(rootDir, scanCss) {
|
|
1590
|
+
if (!scanCss) {
|
|
1591
|
+
return [];
|
|
1592
|
+
}
|
|
1593
|
+
return expandFilePatterns(rootDir, scanCss).filter((file) => file.endsWith(".css")).sort((left, right) => left.localeCompare(right)).flatMap((file) => {
|
|
921
1594
|
try {
|
|
922
|
-
const
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
1595
|
+
const snapshot = readStableTextFileSnapshotSync(file);
|
|
1596
|
+
return [
|
|
1597
|
+
{
|
|
1598
|
+
fileName: file,
|
|
1599
|
+
source: snapshot.source,
|
|
1600
|
+
mtimeMs: snapshot.mtimeMs
|
|
1601
|
+
}
|
|
1602
|
+
];
|
|
930
1603
|
} catch {
|
|
931
|
-
|
|
932
|
-
|
|
1604
|
+
return [];
|
|
1605
|
+
}
|
|
1606
|
+
});
|
|
1607
|
+
}
|
|
1608
|
+
function collectWebpackGlobalVarCssAssets(assets) {
|
|
1609
|
+
return Object.entries(assets).flatMap(([fileName, asset]) => {
|
|
1610
|
+
if (!/\.css(?:$|\?)/.test(fileName)) {
|
|
1611
|
+
return [];
|
|
1612
|
+
}
|
|
1613
|
+
const source = asset.source();
|
|
1614
|
+
if (typeof source !== "string" && !(source instanceof Uint8Array)) {
|
|
1615
|
+
return [];
|
|
1616
|
+
}
|
|
1617
|
+
return [{ fileName, source }];
|
|
1618
|
+
}).sort((left, right) => left.fileName.localeCompare(right.fileName)).map(({ fileName, source }) => ({ fileName, source }));
|
|
1619
|
+
}
|
|
1620
|
+
function assertNoGlobalVarAliasValidationErrors(result) {
|
|
1621
|
+
const messages = [
|
|
1622
|
+
...result.plan.diagnostics.map((diagnostic) => {
|
|
1623
|
+
const location = diagnostic.location ? ` (${diagnostic.location.filePath}:${diagnostic.location.line}:${diagnostic.location.column})` : "";
|
|
1624
|
+
return `[${diagnostic.code}] ${diagnostic.name}${location}: ${diagnostic.message}`;
|
|
1625
|
+
}),
|
|
1626
|
+
...result.usageDiagnostics.map((diagnostic) => {
|
|
1627
|
+
const location = diagnostic.location;
|
|
1628
|
+
return `[${diagnostic.kind}] ${diagnostic.name} (${location.filePath}:${location.line}:${location.column}): ${diagnostic.message}`;
|
|
1629
|
+
})
|
|
1630
|
+
];
|
|
1631
|
+
if (messages.length > 0) {
|
|
1632
|
+
throw new Error(
|
|
1633
|
+
`[csszyx] production.mangleGlobalVars validation failed:
|
|
1634
|
+
${messages.join("\n")}`
|
|
1635
|
+
);
|
|
1636
|
+
}
|
|
1637
|
+
}
|
|
1638
|
+
function rewriteCssWithValidatedGlobalVarPlan(css, filePath, result) {
|
|
1639
|
+
if (result === null || result.plan.entries.length === 0) {
|
|
1640
|
+
return css;
|
|
1641
|
+
}
|
|
1642
|
+
const rewrite = rewriteGlobalVarCssAliases({
|
|
1643
|
+
css,
|
|
1644
|
+
plan: result.plan,
|
|
1645
|
+
filePath
|
|
1646
|
+
});
|
|
1647
|
+
assertNoGlobalVarAliasValidationErrors({
|
|
1648
|
+
scans: result.scans,
|
|
1649
|
+
plan: {
|
|
1650
|
+
...result.plan,
|
|
1651
|
+
diagnostics: rewrite.diagnostics
|
|
1652
|
+
},
|
|
1653
|
+
usageDiagnostics: []
|
|
1654
|
+
});
|
|
1655
|
+
return rewrite.css;
|
|
1656
|
+
}
|
|
1657
|
+
function assertGlobalVarPlanMatchesEarlyAliases(result, expectedEntries) {
|
|
1658
|
+
const actualEntries = [...result.plan.aliases.entries()].sort(
|
|
1659
|
+
([left], [right]) => left.localeCompare(right)
|
|
1660
|
+
);
|
|
1661
|
+
const expected = expectedEntries.map(([original, alias]) => [original, alias]).sort(([left], [right]) => left.localeCompare(right));
|
|
1662
|
+
const expectedJson = JSON.stringify(expected);
|
|
1663
|
+
const actualJson = JSON.stringify(actualEntries);
|
|
1664
|
+
if (expectedJson !== actualJson) {
|
|
1665
|
+
throw new Error(
|
|
1666
|
+
`[csszyx] production.mangleGlobalVars validation failed:
|
|
1667
|
+
CSS alias plan ${actualJson} does not match source-transform alias table ${expectedJson}.`
|
|
1668
|
+
);
|
|
1669
|
+
}
|
|
1670
|
+
}
|
|
1671
|
+
function buildVarMangleMap(entriesByFile) {
|
|
1672
|
+
const next = {};
|
|
1673
|
+
const files = [...entriesByFile.keys()].sort();
|
|
1674
|
+
for (const file of files) {
|
|
1675
|
+
for (const [original, mangled] of entriesByFile.get(file) ?? []) {
|
|
1676
|
+
addVarMangleMapping(next, original, mangled);
|
|
933
1677
|
}
|
|
934
1678
|
}
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
1679
|
+
return next;
|
|
1680
|
+
}
|
|
1681
|
+
function extractGlobalVarAliasesForManifest(varMangleMap, aliasPrefix = CSSZYX_GLOBAL_ALIAS_PREFIX, validationResult = null) {
|
|
1682
|
+
const aliases = {};
|
|
1683
|
+
for (const [original, value] of Object.entries(varMangleMap).sort(
|
|
1684
|
+
([left], [right]) => left.localeCompare(right)
|
|
1685
|
+
)) {
|
|
1686
|
+
const values = Array.isArray(value) ? value : [value];
|
|
1687
|
+
const alias = values.find((candidate) => candidate.startsWith(aliasPrefix));
|
|
1688
|
+
if (alias) {
|
|
1689
|
+
aliases[original] = alias;
|
|
941
1690
|
}
|
|
942
1691
|
}
|
|
943
|
-
|
|
1692
|
+
for (const entry of validationResult?.plan.entries ?? []) {
|
|
1693
|
+
if (entry.alias.startsWith(aliasPrefix)) {
|
|
1694
|
+
aliases[entry.original] = entry.alias;
|
|
1695
|
+
}
|
|
1696
|
+
}
|
|
1697
|
+
return Object.fromEntries(
|
|
1698
|
+
Object.entries(aliases).sort(([left], [right]) => left.localeCompare(right))
|
|
1699
|
+
);
|
|
944
1700
|
}
|
|
945
|
-
function
|
|
946
|
-
|
|
1701
|
+
function createGlobalVarMapAssetSource(varMangleMap, aliasPrefix = CSSZYX_GLOBAL_ALIAS_PREFIX, validationResult = null) {
|
|
1702
|
+
const aliases = extractGlobalVarAliasesForManifest(varMangleMap, aliasPrefix, validationResult);
|
|
1703
|
+
return Object.keys(aliases).length > 0 ? JSON.stringify(aliases) : null;
|
|
947
1704
|
}
|
|
948
|
-
function
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
1705
|
+
function normalizeGlobalVarAliasesForCache(aliases) {
|
|
1706
|
+
if (!aliases) {
|
|
1707
|
+
return [];
|
|
1708
|
+
}
|
|
1709
|
+
const entries = aliases instanceof Map ? aliases.entries() : Array.isArray(aliases) ? aliases : Object.entries(aliases);
|
|
1710
|
+
const normalized = /* @__PURE__ */ new Map();
|
|
1711
|
+
for (const [original, alias] of entries) {
|
|
1712
|
+
if (original.startsWith("--") && alias.startsWith("--")) {
|
|
1713
|
+
normalized.set(original, alias);
|
|
1714
|
+
}
|
|
1715
|
+
}
|
|
1716
|
+
return [...normalized].sort(([left], [right]) => left.localeCompare(right));
|
|
1717
|
+
}
|
|
1718
|
+
function createEarlyGlobalVarAliasEntries(config, aliasPrefix) {
|
|
1719
|
+
if (config?.enabled !== true || !config.tokens || config.tokens.length === 0) {
|
|
1720
|
+
return [];
|
|
1721
|
+
}
|
|
1722
|
+
const tokens = [...new Set(config.tokens)].sort();
|
|
1723
|
+
return tokens.map((original, index) => [original, `${aliasPrefix}${encode(index)}`]);
|
|
1724
|
+
}
|
|
1725
|
+
function shouldEmitGlobalVarMapAsset(config) {
|
|
1726
|
+
return config?.emitMap !== false;
|
|
1727
|
+
}
|
|
1728
|
+
function assertVarMangleMapSize(varMangleMap, maxBytes) {
|
|
1729
|
+
const size = Buffer.byteLength(JSON.stringify(varMangleMap), "utf8");
|
|
1730
|
+
if (size <= maxBytes) {
|
|
1731
|
+
return;
|
|
1732
|
+
}
|
|
1733
|
+
throw new Error(
|
|
1734
|
+
`[csszyx] CSS variable mangle map is ${size} bytes, which exceeds the ${maxBytes} byte safety cap. Reduce production.mangleVars usage, split the bundle, or raise CSSZYX_VAR_MANGLE_MAP_MAX_BYTES if this payload size is intentional.`
|
|
1735
|
+
);
|
|
1736
|
+
}
|
|
1737
|
+
function resolveVarMangleMapMaxBytes() {
|
|
1738
|
+
const raw = process.env.CSSZYX_VAR_MANGLE_MAP_MAX_BYTES;
|
|
1739
|
+
if (!raw) {
|
|
1740
|
+
return DEFAULT_VAR_MANGLE_MAP_MAX_BYTES;
|
|
1741
|
+
}
|
|
1742
|
+
const value = Number.parseInt(raw, 10);
|
|
1743
|
+
return Number.isFinite(value) && value > 0 ? value : DEFAULT_VAR_MANGLE_MAP_MAX_BYTES;
|
|
960
1744
|
}
|
|
961
|
-
function
|
|
1745
|
+
function addVarMangleMapping(map, original, mangled) {
|
|
1746
|
+
const existing = map[original];
|
|
1747
|
+
if (!existing) {
|
|
1748
|
+
map[original] = mangled;
|
|
1749
|
+
return;
|
|
1750
|
+
}
|
|
1751
|
+
const values = Array.isArray(existing) ? existing : [existing];
|
|
1752
|
+
if (!values.includes(mangled)) {
|
|
1753
|
+
map[original] = [...values, mangled];
|
|
1754
|
+
}
|
|
1755
|
+
}
|
|
1756
|
+
function emptyCSSVariableMetrics() {
|
|
962
1757
|
return {
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
classes: new Set(result.classes),
|
|
969
|
-
rawClassNames: new Set(result.rawClassNames),
|
|
970
|
-
diagnostics: [...result.diagnostics],
|
|
971
|
-
recoveryTokens: new Map(result.recoveryTokens)
|
|
1758
|
+
componentClassUses: 0,
|
|
1759
|
+
componentStyleDeclarations: 0,
|
|
1760
|
+
estimatedHoistedDeclarationsSaved: 0,
|
|
1761
|
+
scopedClassUses: 0,
|
|
1762
|
+
scopedStyleDeclarations: 0
|
|
972
1763
|
};
|
|
973
1764
|
}
|
|
974
|
-
function
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
}
|
|
979
|
-
|
|
1765
|
+
function recordFileCSSVariableMetrics(state, filename, code) {
|
|
1766
|
+
const normalizedFilename = normalizeSourceFilename(filename);
|
|
1767
|
+
if (!code) {
|
|
1768
|
+
state.cssVarMetricsByFile.delete(normalizedFilename);
|
|
1769
|
+
} else {
|
|
1770
|
+
const metrics = collectCSSVariableMetrics(code);
|
|
1771
|
+
if (hasCSSVariableMetrics(metrics)) {
|
|
1772
|
+
state.cssVarMetricsByFile.set(normalizedFilename, metrics);
|
|
1773
|
+
} else {
|
|
1774
|
+
state.cssVarMetricsByFile.delete(normalizedFilename);
|
|
1775
|
+
}
|
|
1776
|
+
}
|
|
1777
|
+
state.cssVarMetrics = buildCSSVariableMetrics(state.cssVarMetricsByFile);
|
|
1778
|
+
}
|
|
1779
|
+
function collectCSSVariableMetrics(code) {
|
|
1780
|
+
const componentUses = /* @__PURE__ */ new Map();
|
|
1781
|
+
const componentDeclarations = /* @__PURE__ */ new Map();
|
|
1782
|
+
const metrics = emptyCSSVariableMetrics();
|
|
1783
|
+
for (const match of code.matchAll(/\(--([cs][A-Za-z0-9]+)\)/g)) {
|
|
1784
|
+
const name = `--${match[1]}`;
|
|
1785
|
+
if (name.startsWith("--c")) {
|
|
1786
|
+
metrics.componentClassUses++;
|
|
1787
|
+
incrementCount(componentUses, name);
|
|
1788
|
+
} else {
|
|
1789
|
+
metrics.scopedClassUses++;
|
|
1790
|
+
}
|
|
980
1791
|
}
|
|
981
|
-
const
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
} else
|
|
987
|
-
|
|
1792
|
+
for (const match of code.matchAll(/["'](--([cs][A-Za-z0-9]+))["']\s*:/g)) {
|
|
1793
|
+
const name = match[1];
|
|
1794
|
+
if (name.startsWith("--c")) {
|
|
1795
|
+
metrics.componentStyleDeclarations++;
|
|
1796
|
+
incrementCount(componentDeclarations, name);
|
|
1797
|
+
} else {
|
|
1798
|
+
metrics.scopedStyleDeclarations++;
|
|
988
1799
|
}
|
|
989
1800
|
}
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
const VIRTUAL_CHECKSUM_ID = "virtual:csszyx/checksum";
|
|
996
|
-
const RESOLVED_VIRTUAL_CHECKSUM_ID = `\0${VIRTUAL_CHECKSUM_ID}`;
|
|
997
|
-
function createMangleMapModule(mangleMap, checksum) {
|
|
998
|
-
return `/**
|
|
999
|
-
* Auto-generated mangle map for csszyx.
|
|
1000
|
-
* This module is generated at build time and contains the mapping
|
|
1001
|
-
* from original class names to mangled class names.
|
|
1002
|
-
*
|
|
1003
|
-
* @generated
|
|
1004
|
-
*/
|
|
1005
|
-
|
|
1006
|
-
export const mangleMap = ${JSON.stringify(mangleMap, null, 2)};
|
|
1007
|
-
|
|
1008
|
-
export const checksum = ${JSON.stringify(checksum)};
|
|
1009
|
-
|
|
1010
|
-
export default {
|
|
1011
|
-
mangleMap,
|
|
1012
|
-
checksum,
|
|
1013
|
-
};
|
|
1014
|
-
`;
|
|
1801
|
+
for (const [name, uses] of componentUses) {
|
|
1802
|
+
const declarations = componentDeclarations.get(name) ?? 0;
|
|
1803
|
+
metrics.estimatedHoistedDeclarationsSaved += Math.max(0, uses - declarations);
|
|
1804
|
+
}
|
|
1805
|
+
return metrics;
|
|
1015
1806
|
}
|
|
1016
|
-
function
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1807
|
+
function buildCSSVariableMetrics(metricsByFile) {
|
|
1808
|
+
const total = emptyCSSVariableMetrics();
|
|
1809
|
+
for (const file of [...metricsByFile.keys()].sort()) {
|
|
1810
|
+
const metrics = metricsByFile.get(file);
|
|
1811
|
+
if (!metrics) {
|
|
1812
|
+
continue;
|
|
1813
|
+
}
|
|
1814
|
+
total.componentClassUses += metrics.componentClassUses;
|
|
1815
|
+
total.componentStyleDeclarations += metrics.componentStyleDeclarations;
|
|
1816
|
+
total.estimatedHoistedDeclarationsSaved += metrics.estimatedHoistedDeclarationsSaved;
|
|
1817
|
+
total.scopedClassUses += metrics.scopedClassUses;
|
|
1818
|
+
total.scopedStyleDeclarations += metrics.scopedStyleDeclarations;
|
|
1819
|
+
}
|
|
1820
|
+
return total;
|
|
1027
1821
|
}
|
|
1028
|
-
function
|
|
1029
|
-
return
|
|
1822
|
+
function hasCSSVariableMetrics(metrics) {
|
|
1823
|
+
return Object.values(metrics).some((value) => value > 0);
|
|
1030
1824
|
}
|
|
1031
|
-
function
|
|
1032
|
-
|
|
1033
|
-
return RESOLVED_VIRTUAL_MODULE_ID;
|
|
1034
|
-
}
|
|
1035
|
-
if (id === VIRTUAL_CHECKSUM_ID) {
|
|
1036
|
-
return RESOLVED_VIRTUAL_CHECKSUM_ID;
|
|
1037
|
-
}
|
|
1038
|
-
return void 0;
|
|
1825
|
+
function incrementCount(map, key) {
|
|
1826
|
+
map.set(key, (map.get(key) ?? 0) + 1);
|
|
1039
1827
|
}
|
|
1040
|
-
|
|
1041
|
-
const CHECKSUM_PLACEHOLDER = "___CSSZYX_CHECKSUM___";
|
|
1042
|
-
const MANGLE_MAP_PLACEHOLDER = "___CSSZYX_MANGLE_MAP___";
|
|
1043
|
-
const UNKNOWN_PACKAGE_VERSION = "0.0.0";
|
|
1044
|
-
const TRANSFORM_CACHE_MAX_AGE_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
1045
|
-
const TRANSFORM_CACHE_MAX_ENTRIES = 1e4;
|
|
1046
|
-
const TRANSFORM_MEMORY_CACHE_MAX_ENTRIES = 1e3;
|
|
1047
|
-
const DIRECTIVE_PROLOGUE_PREFIX_RE = /^((?:\s|\/\/[^\n]*\n|\/\*(?:[^*]|\*(?!\/))*\*\/)*)(['"]use (?:client|server)['"];?\s*)/;
|
|
1048
|
-
const RUNTIME_HELPER_IMPORT_RE = {
|
|
1049
|
-
_sz: /\{[^}]*\b_sz\b[^}]*\}\s*from\s*['"]@csszyx\/runtime['"]/,
|
|
1050
|
-
_szMerge: /\{[^}]*\b_szMerge\b[^}]*\}\s*from\s*['"]@csszyx\/runtime['"]/,
|
|
1051
|
-
__szColorVar: /\{[^}]*\b__szColorVar\b[^}]*\}\s*from\s*['"]@csszyx\/runtime['"]/
|
|
1052
|
-
};
|
|
1053
|
-
let _hasWarnedTsConfig = false;
|
|
1054
|
-
let _hasWarnedTransformCacheVersion = false;
|
|
1055
|
-
const requireFromHere = createRequire(import.meta.url);
|
|
1056
|
-
const PLUGIN_VERSION = findPackageVersionFromFile(
|
|
1057
|
-
fileURLToPath(import.meta.url),
|
|
1058
|
-
UNKNOWN_PACKAGE_VERSION
|
|
1059
|
-
);
|
|
1060
|
-
const COMPILER_VERSION = findPackageVersionFromModule("@csszyx/compiler", UNKNOWN_PACKAGE_VERSION);
|
|
1061
|
-
const BENCH_TRACE_ENABLED = process.env.CSSZYX_BENCH_TRACE === "1";
|
|
1062
|
-
const BENCH_TRACE_FILE = process.env.CSSZYX_BENCH_TRACE_FILE;
|
|
1063
1828
|
function traceBenchTiming(label, filename, elapsedMs) {
|
|
1064
1829
|
if (!BENCH_TRACE_ENABLED) {
|
|
1065
1830
|
return;
|
|
@@ -1081,7 +1846,7 @@ function runThemeScan(rootDir, scanCss) {
|
|
|
1081
1846
|
}
|
|
1082
1847
|
const themes = sourceFiles.map((f) => {
|
|
1083
1848
|
try {
|
|
1084
|
-
return parseThemeBlocks(
|
|
1849
|
+
return parseThemeBlocks(readStableTextFileSnapshotSync(f).source);
|
|
1085
1850
|
} catch {
|
|
1086
1851
|
return null;
|
|
1087
1852
|
}
|
|
@@ -1093,18 +1858,23 @@ function runThemeScan(rootDir, scanCss) {
|
|
|
1093
1858
|
_hasWarnedTsConfig = true;
|
|
1094
1859
|
try {
|
|
1095
1860
|
const checkFile = (cfgPath) => {
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1861
|
+
let content;
|
|
1862
|
+
try {
|
|
1863
|
+
content = fs.readFileSync(cfgPath, "utf-8");
|
|
1864
|
+
} catch (err) {
|
|
1865
|
+
if (err?.code === "ENOENT") {
|
|
1866
|
+
return false;
|
|
1867
|
+
}
|
|
1868
|
+
throw err;
|
|
1869
|
+
}
|
|
1870
|
+
if (!content.includes(".csszyx")) {
|
|
1871
|
+
console.warn(
|
|
1872
|
+
`
|
|
1101
1873
|
\x1B[33m\u26A0\uFE0F CSSzyx: Theme Auto-Scan enabled, but TypeScript isn't configured. Run "npx @csszyx/cli init" to fix.\x1B[0m
|
|
1102
1874
|
`
|
|
1103
|
-
|
|
1104
|
-
}
|
|
1105
|
-
return true;
|
|
1875
|
+
);
|
|
1106
1876
|
}
|
|
1107
|
-
return
|
|
1877
|
+
return true;
|
|
1108
1878
|
};
|
|
1109
1879
|
if (!checkFile(path.join(rootDir, "tsconfig.json"))) {
|
|
1110
1880
|
checkFile(path.join(rootDir, "tsconfig.app.json"));
|
|
@@ -1321,12 +2091,43 @@ function mangleCodeClassesSync(code, mangleMap) {
|
|
|
1321
2091
|
});
|
|
1322
2092
|
return result;
|
|
1323
2093
|
}
|
|
2094
|
+
function assertGlobalVarMangleConfig(options) {
|
|
2095
|
+
const config = options.production?.mangleGlobalVars;
|
|
2096
|
+
const errors = validateGlobalVarMangleConfig(config);
|
|
2097
|
+
if (errors.length > 0) {
|
|
2098
|
+
throw new Error(
|
|
2099
|
+
`[csszyx] Invalid production.mangleGlobalVars config:
|
|
2100
|
+
${errors.join("\n")}`
|
|
2101
|
+
);
|
|
2102
|
+
}
|
|
2103
|
+
if (config?.enabled === true) {
|
|
2104
|
+
if (!config.tokens || config.tokens.length === 0) {
|
|
2105
|
+
throw new Error(
|
|
2106
|
+
"[csszyx] production.mangleGlobalVars.enabled requires explicit tokens in Phase H v1."
|
|
2107
|
+
);
|
|
2108
|
+
}
|
|
2109
|
+
if (config.autoPrefix !== void 0 && config.autoPrefix !== "") {
|
|
2110
|
+
throw new Error(
|
|
2111
|
+
"[csszyx] production.mangleGlobalVars.autoPrefix requires CSS pre-scan support and is not enabled in Phase H v1."
|
|
2112
|
+
);
|
|
2113
|
+
}
|
|
2114
|
+
}
|
|
2115
|
+
}
|
|
1324
2116
|
function createCsszyxPlugins(options = {}) {
|
|
2117
|
+
assertGlobalVarMangleConfig(options);
|
|
1325
2118
|
const manglingEnabled = options.production?.mangle !== false;
|
|
1326
2119
|
const astBudgetOverride = options.build?.astBudgetLimit;
|
|
1327
2120
|
const cacheRequested = (options.build?.cache ?? DEFAULT_BUILD_CONFIG.cache) !== false;
|
|
1328
2121
|
const cacheVersionsKnown = PLUGIN_VERSION !== UNKNOWN_PACKAGE_VERSION && COMPILER_VERSION !== UNKNOWN_PACKAGE_VERSION;
|
|
1329
2122
|
const cacheEnabled = cacheRequested && cacheVersionsKnown;
|
|
2123
|
+
const varMangleMapMaxBytes = resolveVarMangleMapMaxBytes();
|
|
2124
|
+
const globalVarMangleConfig = options.production?.mangleGlobalVars;
|
|
2125
|
+
const globalVarAliasPrefix = globalVarMangleConfig?.aliasPrefix ?? CSSZYX_GLOBAL_ALIAS_PREFIX;
|
|
2126
|
+
const encodedGlobalVarAliasPrefix = encodeURIComponent(globalVarAliasPrefix);
|
|
2127
|
+
const earlyGlobalVarAliasEntries = createEarlyGlobalVarAliasEntries(
|
|
2128
|
+
globalVarMangleConfig,
|
|
2129
|
+
globalVarAliasPrefix
|
|
2130
|
+
);
|
|
1330
2131
|
if (cacheRequested && !cacheVersionsKnown && !_hasWarnedTransformCacheVersion) {
|
|
1331
2132
|
_hasWarnedTransformCacheVersion = true;
|
|
1332
2133
|
console.warn(
|
|
@@ -1341,12 +2142,21 @@ function createCsszyxPlugins(options = {}) {
|
|
|
1341
2142
|
const state = {
|
|
1342
2143
|
classes: /* @__PURE__ */ new Set(),
|
|
1343
2144
|
mangleMap: {},
|
|
2145
|
+
varMangleEntriesByFile: /* @__PURE__ */ new Map(),
|
|
2146
|
+
varMangleMap: Object.fromEntries(earlyGlobalVarAliasEntries),
|
|
2147
|
+
cssVarMetricsByFile: /* @__PURE__ */ new Map(),
|
|
2148
|
+
cssVarMetrics: emptyCSSVariableMetrics(),
|
|
1344
2149
|
checksum: "",
|
|
1345
2150
|
finalized: false,
|
|
1346
2151
|
rootDir: process.cwd(),
|
|
1347
2152
|
recoveryTokens: /* @__PURE__ */ new Map(),
|
|
1348
|
-
rscModules: /* @__PURE__ */ new Map()
|
|
2153
|
+
rscModules: /* @__PURE__ */ new Map(),
|
|
2154
|
+
globalVarSourceFilesByFile: /* @__PURE__ */ new Map(),
|
|
2155
|
+
globalVarValidationResult: null
|
|
1349
2156
|
};
|
|
2157
|
+
if (earlyGlobalVarAliasEntries.length > 0) {
|
|
2158
|
+
state.varMangleEntriesByFile.set(GLOBAL_VAR_ALIAS_MAP_OWNER, earlyGlobalVarAliasEntries);
|
|
2159
|
+
}
|
|
1350
2160
|
const SAFELIST_FILENAME = "csszyx-classes.html";
|
|
1351
2161
|
const SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([".tsx", ".jsx", ".ts", ".js"]);
|
|
1352
2162
|
const IGNORE_DIRS = /* @__PURE__ */ new Set(["node_modules", ".next", ".git", "dist", "build", ".turbo"]);
|
|
@@ -1356,6 +2166,40 @@ function createCsszyxPlugins(options = {}) {
|
|
|
1356
2166
|
function isUserIncluded(id) {
|
|
1357
2167
|
return !options.include || matchesAnyPattern(id, options.include, state.rootDir);
|
|
1358
2168
|
}
|
|
2169
|
+
function resolveGlobalVarValidationCacheDir() {
|
|
2170
|
+
if (!cacheEnabled) {
|
|
2171
|
+
return void 0;
|
|
2172
|
+
}
|
|
2173
|
+
const cacheRoot = path.resolve(
|
|
2174
|
+
state.rootDir,
|
|
2175
|
+
options.build?.cacheDir ?? DEFAULT_BUILD_CONFIG.cacheDir ?? ".csszyx/cache"
|
|
2176
|
+
);
|
|
2177
|
+
return resolveGlobalVarScanCacheDir(cacheRoot);
|
|
2178
|
+
}
|
|
2179
|
+
function validateGlobalVarBundleInputs(cssAssets) {
|
|
2180
|
+
if (globalVarMangleConfig?.enabled !== true) {
|
|
2181
|
+
return null;
|
|
2182
|
+
}
|
|
2183
|
+
const configuredCssAssets = collectConfiguredGlobalVarCssSources(
|
|
2184
|
+
state.rootDir,
|
|
2185
|
+
options.build?.scanCss
|
|
2186
|
+
);
|
|
2187
|
+
const result = validateGlobalVarAliasInputs(
|
|
2188
|
+
createGlobalVarAliasValidationOptions({
|
|
2189
|
+
rootDir: state.rootDir,
|
|
2190
|
+
cssAssets: [...configuredCssAssets, ...cssAssets],
|
|
2191
|
+
sourceFiles: buildGlobalVarSourceFiles(state),
|
|
2192
|
+
tokens: globalVarMangleConfig.tokens,
|
|
2193
|
+
autoPrefix: globalVarMangleConfig.autoPrefix,
|
|
2194
|
+
aliasPrefix: globalVarAliasPrefix,
|
|
2195
|
+
reserved: globalVarMangleConfig.reserved,
|
|
2196
|
+
cacheDir: resolveGlobalVarValidationCacheDir()
|
|
2197
|
+
})
|
|
2198
|
+
);
|
|
2199
|
+
assertNoGlobalVarAliasValidationErrors(result);
|
|
2200
|
+
assertGlobalVarPlanMatchesEarlyAliases(result, earlyGlobalVarAliasEntries);
|
|
2201
|
+
return result;
|
|
2202
|
+
}
|
|
1359
2203
|
function isHardIgnored(id) {
|
|
1360
2204
|
return id.includes("node_modules") || id.includes("/packages/") || id.includes(".next") && !id.includes("static");
|
|
1361
2205
|
}
|
|
@@ -1366,21 +2210,17 @@ function createCsszyxPlugins(options = {}) {
|
|
|
1366
2210
|
return !isHardIgnored(id) && !isUserExcluded(id) && /\.css(\?.*)?$/.test(id);
|
|
1367
2211
|
}
|
|
1368
2212
|
function transformConfiguredSource(source, filename) {
|
|
1369
|
-
const compilerOptions =
|
|
2213
|
+
const compilerOptions = createCompilerOptions();
|
|
1370
2214
|
const effectiveFilename = normalizeSourceFilename(filename);
|
|
1371
2215
|
const cacheRoot = resolveTransformCacheDir(state.rootDir, options.build?.cacheDir);
|
|
1372
2216
|
if (cacheEnabled) {
|
|
1373
2217
|
evictTransformCacheOnce();
|
|
1374
2218
|
}
|
|
1375
|
-
const cacheInput =
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
astBudget: astBudgetOverride,
|
|
1381
|
-
filename: effectiveFilename,
|
|
1382
|
-
source
|
|
1383
|
-
};
|
|
2219
|
+
const cacheInput = createConfiguredTransformCacheInput(
|
|
2220
|
+
source,
|
|
2221
|
+
effectiveFilename,
|
|
2222
|
+
compilerOptions
|
|
2223
|
+
);
|
|
1384
2224
|
if (parserMode === "rust") {
|
|
1385
2225
|
ensureRustTransformAvailable();
|
|
1386
2226
|
}
|
|
@@ -1421,6 +2261,126 @@ function createCsszyxPlugins(options = {}) {
|
|
|
1421
2261
|
}
|
|
1422
2262
|
return result;
|
|
1423
2263
|
}
|
|
2264
|
+
function createCompilerOptions() {
|
|
2265
|
+
return {
|
|
2266
|
+
astBudget: astBudgetOverride,
|
|
2267
|
+
mangleVars: options.production?.mangleVars === true,
|
|
2268
|
+
mangleVarHoistMaxDepth: options.production?.mangleVarHoistMaxDepth,
|
|
2269
|
+
globalVarAliases: earlyGlobalVarAliasEntries.length > 0 ? earlyGlobalVarAliasEntries : void 0
|
|
2270
|
+
};
|
|
2271
|
+
}
|
|
2272
|
+
function createConfiguredTransformCacheInput(source, effectiveFilename, compilerOptions) {
|
|
2273
|
+
return {
|
|
2274
|
+
pluginVersion: PLUGIN_VERSION,
|
|
2275
|
+
compilerVersion: COMPILER_VERSION,
|
|
2276
|
+
parserMode,
|
|
2277
|
+
producer: parserMode,
|
|
2278
|
+
astBudget: astBudgetOverride,
|
|
2279
|
+
mangleVars: compilerOptions.mangleVars,
|
|
2280
|
+
mangleVarHoistMaxDepth: compilerOptions.mangleVarHoistMaxDepth,
|
|
2281
|
+
globalVarAliases: normalizeGlobalVarAliasesForCache(compilerOptions.globalVarAliases),
|
|
2282
|
+
filename: effectiveFilename,
|
|
2283
|
+
source
|
|
2284
|
+
};
|
|
2285
|
+
}
|
|
2286
|
+
function transformPrescanSources(files) {
|
|
2287
|
+
if (parserMode !== "rust" || files.length <= 1) {
|
|
2288
|
+
return transformPrescanSourcesIndividually(files);
|
|
2289
|
+
}
|
|
2290
|
+
const compilerOptions = createCompilerOptions();
|
|
2291
|
+
const cacheRoot = resolveTransformCacheDir(state.rootDir, options.build?.cacheDir);
|
|
2292
|
+
const results = /* @__PURE__ */ new Map();
|
|
2293
|
+
const misses = [];
|
|
2294
|
+
if (cacheEnabled) {
|
|
2295
|
+
evictTransformCacheOnce();
|
|
2296
|
+
}
|
|
2297
|
+
ensureRustTransformAvailable();
|
|
2298
|
+
for (const file of files) {
|
|
2299
|
+
const effectiveFilename = normalizeSourceFilename(file.filePath);
|
|
2300
|
+
const cacheInput = createConfiguredTransformCacheInput(
|
|
2301
|
+
file.content,
|
|
2302
|
+
effectiveFilename,
|
|
2303
|
+
compilerOptions
|
|
2304
|
+
);
|
|
2305
|
+
const cacheKey = cacheEnabled ? createTransformCacheKey(cacheInput) : null;
|
|
2306
|
+
if (cacheEnabled && cacheKey) {
|
|
2307
|
+
const memoryCached = transformMemoryCache.get(cacheKey.key);
|
|
2308
|
+
if (memoryCached) {
|
|
2309
|
+
transformMemoryCache.delete(cacheKey.key);
|
|
2310
|
+
transformMemoryCache.set(cacheKey.key, memoryCached);
|
|
2311
|
+
results.set(file.filePath, memoryCached);
|
|
2312
|
+
continue;
|
|
2313
|
+
}
|
|
2314
|
+
const cached = readTransformCache(cacheRoot, cacheInput, cacheKey);
|
|
2315
|
+
if (cached) {
|
|
2316
|
+
rememberTransformCacheEntry(cacheKey.key, cached);
|
|
2317
|
+
results.set(file.filePath, cached);
|
|
2318
|
+
continue;
|
|
2319
|
+
}
|
|
2320
|
+
}
|
|
2321
|
+
misses.push({
|
|
2322
|
+
filePath: file.filePath,
|
|
2323
|
+
effectiveFilename,
|
|
2324
|
+
content: file.content,
|
|
2325
|
+
cacheInput,
|
|
2326
|
+
cacheKey
|
|
2327
|
+
});
|
|
2328
|
+
}
|
|
2329
|
+
if (misses.length === 0) {
|
|
2330
|
+
return files.map((file) => {
|
|
2331
|
+
const result = results.get(file.filePath);
|
|
2332
|
+
return result ? { filePath: file.filePath, result } : null;
|
|
2333
|
+
}).filter((entry) => entry !== null);
|
|
2334
|
+
}
|
|
2335
|
+
try {
|
|
2336
|
+
const batchResults = transformRustBatch(
|
|
2337
|
+
misses.map((file) => ({
|
|
2338
|
+
filename: file.effectiveFilename,
|
|
2339
|
+
source: file.content
|
|
2340
|
+
})),
|
|
2341
|
+
compilerOptions
|
|
2342
|
+
);
|
|
2343
|
+
for (let index = 0; index < misses.length; index++) {
|
|
2344
|
+
const miss = misses[index];
|
|
2345
|
+
const result = batchResults[index];
|
|
2346
|
+
if (!miss || !result) {
|
|
2347
|
+
continue;
|
|
2348
|
+
}
|
|
2349
|
+
if (cacheEnabled && miss.cacheKey) {
|
|
2350
|
+
writeTransformCache(cacheRoot, miss.cacheInput, result, miss.cacheKey);
|
|
2351
|
+
rememberTransformCacheEntry(miss.cacheKey.key, result);
|
|
2352
|
+
}
|
|
2353
|
+
results.set(miss.filePath, result);
|
|
2354
|
+
}
|
|
2355
|
+
} catch {
|
|
2356
|
+
for (const miss of misses) {
|
|
2357
|
+
try {
|
|
2358
|
+
results.set(
|
|
2359
|
+
miss.filePath,
|
|
2360
|
+
transformConfiguredSource(miss.content, miss.effectiveFilename)
|
|
2361
|
+
);
|
|
2362
|
+
} catch {
|
|
2363
|
+
}
|
|
2364
|
+
}
|
|
2365
|
+
}
|
|
2366
|
+
return files.map((file) => {
|
|
2367
|
+
const result = results.get(file.filePath);
|
|
2368
|
+
return result ? { filePath: file.filePath, result } : null;
|
|
2369
|
+
}).filter((entry) => entry !== null);
|
|
2370
|
+
}
|
|
2371
|
+
function transformPrescanSourcesIndividually(files) {
|
|
2372
|
+
const results = [];
|
|
2373
|
+
for (const file of files) {
|
|
2374
|
+
try {
|
|
2375
|
+
results.push({
|
|
2376
|
+
filePath: file.filePath,
|
|
2377
|
+
result: transformConfiguredSource(file.content, file.filePath)
|
|
2378
|
+
});
|
|
2379
|
+
} catch {
|
|
2380
|
+
}
|
|
2381
|
+
}
|
|
2382
|
+
return results;
|
|
2383
|
+
}
|
|
1424
2384
|
function rememberTransformCacheEntry(key, result) {
|
|
1425
2385
|
transformMemoryCache.delete(key);
|
|
1426
2386
|
transformMemoryCache.set(key, result);
|
|
@@ -1457,7 +2417,14 @@ function createCsszyxPlugins(options = {}) {
|
|
|
1457
2417
|
<div class="${classList}"><div class="${classList}">x</div><div class="${classList}">x</div></div>
|
|
1458
2418
|
`;
|
|
1459
2419
|
try {
|
|
1460
|
-
|
|
2420
|
+
let existing = "";
|
|
2421
|
+
try {
|
|
2422
|
+
existing = fs.readFileSync(safelistPath, "utf-8");
|
|
2423
|
+
} catch (err) {
|
|
2424
|
+
if (err?.code !== "ENOENT") {
|
|
2425
|
+
throw err;
|
|
2426
|
+
}
|
|
2427
|
+
}
|
|
1461
2428
|
if (existing !== content) {
|
|
1462
2429
|
fs.writeFileSync(safelistPath, content);
|
|
1463
2430
|
}
|
|
@@ -1465,8 +2432,10 @@ function createCsszyxPlugins(options = {}) {
|
|
|
1465
2432
|
}
|
|
1466
2433
|
}
|
|
1467
2434
|
function prescanAndWriteClasses() {
|
|
2435
|
+
const prescanStarted = performance.now();
|
|
1468
2436
|
const discoveredClasses = /* @__PURE__ */ new Set();
|
|
1469
2437
|
const rawDiscoveredClasses = /* @__PURE__ */ new Set();
|
|
2438
|
+
const prescanSources = [];
|
|
1470
2439
|
function scanDir(dir) {
|
|
1471
2440
|
let entries;
|
|
1472
2441
|
try {
|
|
@@ -1484,85 +2453,107 @@ function createCsszyxPlugins(options = {}) {
|
|
|
1484
2453
|
if (!shouldProcessSource(filePath)) {
|
|
1485
2454
|
continue;
|
|
1486
2455
|
}
|
|
2456
|
+
let content;
|
|
1487
2457
|
try {
|
|
1488
|
-
|
|
1489
|
-
if (!content.includes("sz=") && !content.includes("sz:")) {
|
|
1490
|
-
continue;
|
|
1491
|
-
}
|
|
1492
|
-
const result = transformConfiguredSource(content, filePath);
|
|
1493
|
-
if (!result.transformed) {
|
|
1494
|
-
continue;
|
|
1495
|
-
}
|
|
1496
|
-
for (const cls of result.classes) {
|
|
1497
|
-
discoveredClasses.add(cls);
|
|
1498
|
-
}
|
|
1499
|
-
for (const cls of result.rawClassNames) {
|
|
1500
|
-
rawDiscoveredClasses.add(cls);
|
|
1501
|
-
}
|
|
1502
|
-
for (const [token, data] of result.recoveryTokens) {
|
|
1503
|
-
state.recoveryTokens.set(token, data);
|
|
1504
|
-
}
|
|
1505
|
-
if (result.usesRuntime) {
|
|
1506
|
-
const szCallRe = /_sz\(\s*\{/g;
|
|
1507
|
-
for (const szMatch of result.code.matchAll(szCallRe)) {
|
|
1508
|
-
let depth = 1;
|
|
1509
|
-
let idx = (szMatch.index ?? 0) + szMatch[0].length;
|
|
1510
|
-
while (idx < result.code.length && depth > 0) {
|
|
1511
|
-
if (result.code[idx] === "{") {
|
|
1512
|
-
depth++;
|
|
1513
|
-
} else if (result.code[idx] === "}") {
|
|
1514
|
-
depth--;
|
|
1515
|
-
}
|
|
1516
|
-
idx++;
|
|
1517
|
-
}
|
|
1518
|
-
const objStr = result.code.slice(
|
|
1519
|
-
(szMatch.index ?? 0) + szMatch[0].length,
|
|
1520
|
-
idx - 1
|
|
1521
|
-
);
|
|
1522
|
-
const strKv = /(\w+)\s*:\s*(?:"([^"]*)"|'([^']*)')/g;
|
|
1523
|
-
for (const kv of objStr.matchAll(strKv)) {
|
|
1524
|
-
try {
|
|
1525
|
-
const val = kv[2] ?? kv[3];
|
|
1526
|
-
const r = transform({ [kv[1]]: val });
|
|
1527
|
-
for (const c of r.className.split(/\s+/).filter(Boolean)) {
|
|
1528
|
-
discoveredClasses.add(c);
|
|
1529
|
-
}
|
|
1530
|
-
} catch {
|
|
1531
|
-
}
|
|
1532
|
-
}
|
|
1533
|
-
const numKv = /(\w+)\s*:\s*(-?\d+(?:\.\d+)?)\s*(?=[,}\n])/g;
|
|
1534
|
-
for (const kv of objStr.matchAll(numKv)) {
|
|
1535
|
-
try {
|
|
1536
|
-
const r = transform({ [kv[1]]: parseFloat(kv[2]) });
|
|
1537
|
-
for (const c of r.className.split(/\s+/).filter(Boolean)) {
|
|
1538
|
-
discoveredClasses.add(c);
|
|
1539
|
-
}
|
|
1540
|
-
} catch {
|
|
1541
|
-
}
|
|
1542
|
-
}
|
|
1543
|
-
const boolKv = /(\w+)\s*:\s*(true|false)\s*(?=[,}\n])/g;
|
|
1544
|
-
for (const kv of objStr.matchAll(boolKv)) {
|
|
1545
|
-
try {
|
|
1546
|
-
const r = transform({ [kv[1]]: kv[2] === "true" });
|
|
1547
|
-
for (const c of r.className.split(/\s+/).filter(Boolean)) {
|
|
1548
|
-
discoveredClasses.add(c);
|
|
1549
|
-
}
|
|
1550
|
-
} catch {
|
|
1551
|
-
}
|
|
1552
|
-
}
|
|
1553
|
-
}
|
|
1554
|
-
}
|
|
2458
|
+
content = fs.readFileSync(filePath, "utf-8");
|
|
1555
2459
|
} catch {
|
|
2460
|
+
continue;
|
|
2461
|
+
}
|
|
2462
|
+
if (!content.includes("sz=") && !content.includes("sz:")) {
|
|
2463
|
+
continue;
|
|
1556
2464
|
}
|
|
2465
|
+
prescanSources.push({ filePath, content });
|
|
1557
2466
|
}
|
|
1558
2467
|
}
|
|
1559
2468
|
}
|
|
1560
2469
|
scanDir(state.rootDir);
|
|
2470
|
+
for (const { filePath, result } of transformPrescanSources(prescanSources)) {
|
|
2471
|
+
if (!result.transformed) {
|
|
2472
|
+
continue;
|
|
2473
|
+
}
|
|
2474
|
+
collectPrescanResult(result, filePath, discoveredClasses, rawDiscoveredClasses);
|
|
2475
|
+
}
|
|
1561
2476
|
for (const cls of discoveredClasses) {
|
|
1562
2477
|
state.classes.add(cls);
|
|
1563
2478
|
}
|
|
1564
2479
|
const safelistClasses = /* @__PURE__ */ new Set([...discoveredClasses, ...rawDiscoveredClasses]);
|
|
1565
2480
|
writeSafelistFile(safelistClasses);
|
|
2481
|
+
traceBenchTiming("prescan", state.rootDir, performance.now() - prescanStarted);
|
|
2482
|
+
}
|
|
2483
|
+
function collectPrescanResult(result, filePath, discoveredClasses, rawDiscoveredClasses) {
|
|
2484
|
+
for (const cls of result.classes) {
|
|
2485
|
+
discoveredClasses.add(cls);
|
|
2486
|
+
}
|
|
2487
|
+
for (const cls of result.rawClassNames) {
|
|
2488
|
+
rawDiscoveredClasses.add(cls);
|
|
2489
|
+
}
|
|
2490
|
+
for (const [token, data] of result.recoveryTokens) {
|
|
2491
|
+
state.recoveryTokens.set(token, data);
|
|
2492
|
+
}
|
|
2493
|
+
recordFileVarMangleEntries(state, filePath, cssVariableEntries(result));
|
|
2494
|
+
recordFileCSSVariableMetrics(state, filePath, result.code);
|
|
2495
|
+
collectRuntimeStaticClasses(result, discoveredClasses);
|
|
2496
|
+
}
|
|
2497
|
+
function collectRuntimeStaticClasses(result, discoveredClasses) {
|
|
2498
|
+
if (!result.usesRuntime) {
|
|
2499
|
+
return;
|
|
2500
|
+
}
|
|
2501
|
+
const szCallRe = /_sz\(\s*\{/g;
|
|
2502
|
+
for (const szMatch of result.code.matchAll(szCallRe)) {
|
|
2503
|
+
let depth = 1;
|
|
2504
|
+
let idx = (szMatch.index ?? 0) + szMatch[0].length;
|
|
2505
|
+
while (idx < result.code.length && depth > 0) {
|
|
2506
|
+
if (result.code[idx] === "{") {
|
|
2507
|
+
depth++;
|
|
2508
|
+
} else if (result.code[idx] === "}") {
|
|
2509
|
+
depth--;
|
|
2510
|
+
}
|
|
2511
|
+
idx++;
|
|
2512
|
+
}
|
|
2513
|
+
const objStr = result.code.slice((szMatch.index ?? 0) + szMatch[0].length, idx - 1);
|
|
2514
|
+
collectRuntimeStringClasses(objStr, discoveredClasses);
|
|
2515
|
+
collectRuntimeNumberClasses(objStr, discoveredClasses);
|
|
2516
|
+
collectRuntimeBooleanClasses(objStr, discoveredClasses);
|
|
2517
|
+
}
|
|
2518
|
+
}
|
|
2519
|
+
function collectRuntimeStringClasses(objStr, discoveredClasses) {
|
|
2520
|
+
const strKv = /(\w+)\s*:\s*(?:"([^"]*)"|'([^']*)')/g;
|
|
2521
|
+
for (const kv of objStr.matchAll(strKv)) {
|
|
2522
|
+
try {
|
|
2523
|
+
const val = kv[2] ?? kv[3];
|
|
2524
|
+
collectTransformClasses(transform({ [kv[1]]: val }), discoveredClasses);
|
|
2525
|
+
} catch {
|
|
2526
|
+
}
|
|
2527
|
+
}
|
|
2528
|
+
}
|
|
2529
|
+
function collectRuntimeNumberClasses(objStr, discoveredClasses) {
|
|
2530
|
+
const numKv = /(\w+)\s*:\s*(-?\d+(?:\.\d+)?)\s*(?=[,}\n])/g;
|
|
2531
|
+
for (const kv of objStr.matchAll(numKv)) {
|
|
2532
|
+
try {
|
|
2533
|
+
collectTransformClasses(
|
|
2534
|
+
transform({ [kv[1]]: parseFloat(kv[2]) }),
|
|
2535
|
+
discoveredClasses
|
|
2536
|
+
);
|
|
2537
|
+
} catch {
|
|
2538
|
+
}
|
|
2539
|
+
}
|
|
2540
|
+
}
|
|
2541
|
+
function collectRuntimeBooleanClasses(objStr, discoveredClasses) {
|
|
2542
|
+
const boolKv = /(\w+)\s*:\s*(true|false)\s*(?=[,}\n])/g;
|
|
2543
|
+
for (const kv of objStr.matchAll(boolKv)) {
|
|
2544
|
+
try {
|
|
2545
|
+
collectTransformClasses(
|
|
2546
|
+
transform({ [kv[1]]: kv[2] === "true" }),
|
|
2547
|
+
discoveredClasses
|
|
2548
|
+
);
|
|
2549
|
+
} catch {
|
|
2550
|
+
}
|
|
2551
|
+
}
|
|
2552
|
+
}
|
|
2553
|
+
function collectTransformClasses(result, discoveredClasses) {
|
|
2554
|
+
for (const cls of result.className.split(/\s+/).filter(Boolean)) {
|
|
2555
|
+
discoveredClasses.add(cls);
|
|
2556
|
+
}
|
|
1566
2557
|
}
|
|
1567
2558
|
function extractClasses(code) {
|
|
1568
2559
|
const dqPattern = /(?:class(?:Name)?|sz)[:=]\s*"([^"]*)"/g;
|
|
@@ -1605,7 +2596,10 @@ function createCsszyxPlugins(options = {}) {
|
|
|
1605
2596
|
newMap[sortedClasses[i]] = encode(i);
|
|
1606
2597
|
}
|
|
1607
2598
|
state.mangleMap = newMap;
|
|
1608
|
-
state.
|
|
2599
|
+
assertVarMangleMapSize(state.varMangleMap, varMangleMapMaxBytes);
|
|
2600
|
+
state.checksum = compute_mangle_checksum(
|
|
2601
|
+
createHydrationMangleMap(state.mangleMap, state.varMangleMap)
|
|
2602
|
+
);
|
|
1609
2603
|
state.finalized = true;
|
|
1610
2604
|
}
|
|
1611
2605
|
function mangleCodeClasses(code) {
|
|
@@ -1621,6 +2615,11 @@ function createCsszyxPlugins(options = {}) {
|
|
|
1621
2615
|
const escapedMap = result.includes("eval(") ? jsonMap.replace(/"/g, '\\"') : jsonMap;
|
|
1622
2616
|
result = result.split(MANGLE_MAP_PLACEHOLDER).join(escapedMap);
|
|
1623
2617
|
}
|
|
2618
|
+
if (result.includes(VAR_MANGLE_MAP_PLACEHOLDER)) {
|
|
2619
|
+
const jsonMap = JSON.stringify(state.varMangleMap);
|
|
2620
|
+
const escapedMap = result.includes("eval(") ? jsonMap.replace(/"/g, '\\"') : jsonMap;
|
|
2621
|
+
result = result.split(VAR_MANGLE_MAP_PLACEHOLDER).join(escapedMap);
|
|
2622
|
+
}
|
|
1624
2623
|
return result;
|
|
1625
2624
|
}
|
|
1626
2625
|
const prePlugin = createUnplugin(
|
|
@@ -1646,7 +2645,12 @@ function createCsszyxPlugins(options = {}) {
|
|
|
1646
2645
|
load(id) {
|
|
1647
2646
|
if (id === RESOLVED_VIRTUAL_MODULE_ID) {
|
|
1648
2647
|
finalizeMangleMap();
|
|
1649
|
-
return createMangleMapModule(
|
|
2648
|
+
return createMangleMapModule(
|
|
2649
|
+
state.mangleMap,
|
|
2650
|
+
state.checksum,
|
|
2651
|
+
state.varMangleMap,
|
|
2652
|
+
state.cssVarMetrics
|
|
2653
|
+
);
|
|
1650
2654
|
}
|
|
1651
2655
|
if (id === RESOLVED_VIRTUAL_CHECKSUM_ID) {
|
|
1652
2656
|
finalizeMangleMap();
|
|
@@ -1677,6 +2681,9 @@ function createCsszyxPlugins(options = {}) {
|
|
|
1677
2681
|
if (!shouldProcessCss(id) && !shouldProcessSource(id)) {
|
|
1678
2682
|
return null;
|
|
1679
2683
|
}
|
|
2684
|
+
if (shouldProcessSource(id)) {
|
|
2685
|
+
recordGlobalVarSourceFile(state, id, code);
|
|
2686
|
+
}
|
|
1680
2687
|
if (/\.[tj]sx?(\?.*)?$/.test(id)) {
|
|
1681
2688
|
assertNoRSCBoundaryViolation(code, id);
|
|
1682
2689
|
}
|
|
@@ -1739,6 +2746,8 @@ ${sourceDirective}`
|
|
|
1739
2746
|
usesColorVar = result.usesColorVar;
|
|
1740
2747
|
transformed = result.transformed;
|
|
1741
2748
|
szClasses = result.classes;
|
|
2749
|
+
recordFileVarMangleEntries(state, id, cssVariableEntries(result));
|
|
2750
|
+
recordFileCSSVariableMetrics(state, id, result.code);
|
|
1742
2751
|
if (result.diagnostics.length > 0 && process.env.NODE_ENV !== "production") {
|
|
1743
2752
|
for (const msg of result.diagnostics) {
|
|
1744
2753
|
this.warn(`[csszyx] ${id}
|
|
@@ -1749,14 +2758,17 @@ ${sourceDirective}`
|
|
|
1749
2758
|
state.recoveryTokens.set(token, data);
|
|
1750
2759
|
}
|
|
1751
2760
|
}
|
|
2761
|
+
} else if (shouldProcessSource(id)) {
|
|
2762
|
+
recordFileVarMangleEntries(state, id, []);
|
|
2763
|
+
recordFileCSSVariableMetrics(state, id, null);
|
|
1752
2764
|
}
|
|
1753
|
-
if (transformedCode.includes("<html") && /layout|Root|Document|app
|
|
2765
|
+
if (transformedCode.includes("<html") && /(?:layout|Root|Document|app)\.tsx?$/i.test(id)) {
|
|
1754
2766
|
const attrName = options.production?.minify ? "data-sz-cs" : "data-sz-checksum";
|
|
1755
2767
|
transformedCode = transformedCode.replace(
|
|
1756
2768
|
/<html([^>]*)>/i,
|
|
1757
2769
|
`<html$1 ${attrName}="${CHECKSUM_PLACEHOLDER}">`
|
|
1758
2770
|
);
|
|
1759
|
-
const debugScript = `<script dangerouslySetInnerHTML={{__html: \`(function(){var m=${MANGLE_MAP_PLACEHOLDER};var r={};for(var k in m)r[m[k]]=k;window.__csszyx={mangleMap:m,checksum:"${CHECKSUM_PLACEHOLDER}",decode:function(c){return r[c]},encode:function(c){return m[c]},decodeAll:function(el){return(el.className||"").split(" ").map(function(c){return r[c]||c})}}})()\`}} />`;
|
|
2771
|
+
const debugScript = `<script dangerouslySetInnerHTML={{__html: \`(function(){var m=${MANGLE_MAP_PLACEHOLDER};var vm=${VAR_MANGLE_MAP_PLACEHOLDER};var gp=decodeURIComponent(${JSON.stringify(encodedGlobalVarAliasPrefix)});var r={};var vr={};for(var k in m)r[m[k]]=k;for(var vk in vm){var vv=vm[vk];var vs=Array.isArray(vv)?vv:[vv];for(var vi=0;vi<vs.length;vi++)(vr[vs[vi]]||(vr[vs[vi]]=[])).push(vk)}window.__csszyx={mangleMap:m,varMangleMap:vm,checksum:"${CHECKSUM_PLACEHOLDER}",decode:function(c){return r[c]},encode:function(c){return m[c]},decodeVar:function(v){return vr[v]||[]},encodeVar:function(v){return vm[v]},decodeGlobalVar:function(v){var a=vr[v]||[];return v.indexOf(gp)===0?a[0]:void 0},decodeAll:function(el){return(el.className||"").split(" ").map(function(c){return r[c]||c})}}})()\`}} />`;
|
|
1760
2772
|
if (transformedCode.includes("<body")) {
|
|
1761
2773
|
transformedCode = transformedCode.replace(
|
|
1762
2774
|
/(<body[^>]*>)/i,
|
|
@@ -1825,6 +2837,9 @@ ${sourceDirective}`
|
|
|
1825
2837
|
watchChange(id, change) {
|
|
1826
2838
|
if (change.event === "delete") {
|
|
1827
2839
|
deleteRSCModuleRecord(state.rscModules, id);
|
|
2840
|
+
recordGlobalVarSourceFile(state, id, null);
|
|
2841
|
+
recordFileVarMangleEntries(state, id, []);
|
|
2842
|
+
recordFileCSSVariableMetrics(state, id, null);
|
|
1828
2843
|
}
|
|
1829
2844
|
},
|
|
1830
2845
|
/**
|
|
@@ -1886,6 +2901,9 @@ ${sourceDirective}`
|
|
|
1886
2901
|
return;
|
|
1887
2902
|
}
|
|
1888
2903
|
if (!fileContent.includes("sz=") && !/\bsz\s*:\s*["'{]/.test(fileContent)) {
|
|
2904
|
+
recordGlobalVarSourceFile(state, ctx.file, fileContent);
|
|
2905
|
+
recordFileVarMangleEntries(state, ctx.file, []);
|
|
2906
|
+
recordFileCSSVariableMetrics(state, ctx.file, null);
|
|
1889
2907
|
return;
|
|
1890
2908
|
}
|
|
1891
2909
|
try {
|
|
@@ -1897,15 +2915,24 @@ ${sourceDirective}`
|
|
|
1897
2915
|
performance.now() - hmrTransformStarted
|
|
1898
2916
|
);
|
|
1899
2917
|
} catch {
|
|
2918
|
+
recordGlobalVarSourceFile(state, ctx.file, fileContent);
|
|
2919
|
+
recordFileVarMangleEntries(state, ctx.file, []);
|
|
2920
|
+
recordFileCSSVariableMetrics(state, ctx.file, null);
|
|
1900
2921
|
return;
|
|
1901
2922
|
}
|
|
1902
2923
|
if (!result.transformed) {
|
|
2924
|
+
recordGlobalVarSourceFile(state, ctx.file, fileContent);
|
|
2925
|
+
recordFileVarMangleEntries(state, ctx.file, []);
|
|
2926
|
+
recordFileCSSVariableMetrics(state, ctx.file, null);
|
|
1903
2927
|
return;
|
|
1904
2928
|
}
|
|
1905
2929
|
const sizeBefore = state.classes.size;
|
|
2930
|
+
recordGlobalVarSourceFile(state, ctx.file, fileContent);
|
|
1906
2931
|
for (const cls of result.classes) {
|
|
1907
2932
|
state.classes.add(cls);
|
|
1908
2933
|
}
|
|
2934
|
+
recordFileVarMangleEntries(state, ctx.file, cssVariableEntries(result));
|
|
2935
|
+
recordFileCSSVariableMetrics(state, ctx.file, result.code);
|
|
1909
2936
|
for (const [token, data] of result.recoveryTokens) {
|
|
1910
2937
|
state.recoveryTokens.set(token, data);
|
|
1911
2938
|
}
|
|
@@ -1927,7 +2954,9 @@ ${sourceDirective}`
|
|
|
1927
2954
|
finalizeMangleMap();
|
|
1928
2955
|
let result = transformIndexHtml(html, state.mangleMap, state.checksum, {
|
|
1929
2956
|
mode: options.production?.injectChecksum === false ? "script" : "script",
|
|
1930
|
-
minify: process.env.NODE_ENV === "production"
|
|
2957
|
+
minify: process.env.NODE_ENV === "production",
|
|
2958
|
+
varMangleMap: state.varMangleMap,
|
|
2959
|
+
globalVarAliasPrefix
|
|
1931
2960
|
});
|
|
1932
2961
|
if (state.recoveryTokens.size > 0) {
|
|
1933
2962
|
const isProduction = process.env.NODE_ENV === "production";
|
|
@@ -1971,6 +3000,9 @@ ${sourceDirective}`
|
|
|
1971
3000
|
},
|
|
1972
3001
|
(assets) => {
|
|
1973
3002
|
finalizeMangleMap();
|
|
3003
|
+
state.globalVarValidationResult = validateGlobalVarBundleInputs(
|
|
3004
|
+
collectWebpackGlobalVarCssAssets(assets)
|
|
3005
|
+
);
|
|
1974
3006
|
const isWebpackDevMode = compiler.options.mode === "development";
|
|
1975
3007
|
const manifestData = {
|
|
1976
3008
|
version: "0.4.0",
|
|
@@ -1980,33 +3012,71 @@ ${sourceDirective}`
|
|
|
1980
3012
|
if (manglingEnabled && !isWebpackDevMode && Object.keys(state.mangleMap).length > 0) {
|
|
1981
3013
|
manifestData.mangleMap = state.mangleMap;
|
|
1982
3014
|
}
|
|
3015
|
+
if (Object.keys(state.varMangleMap).length > 0) {
|
|
3016
|
+
manifestData.varMangleMap = state.varMangleMap;
|
|
3017
|
+
}
|
|
3018
|
+
const globalVarAliases = extractGlobalVarAliasesForManifest(
|
|
3019
|
+
state.varMangleMap,
|
|
3020
|
+
globalVarAliasPrefix,
|
|
3021
|
+
state.globalVarValidationResult
|
|
3022
|
+
);
|
|
3023
|
+
if (Object.keys(globalVarAliases).length > 0) {
|
|
3024
|
+
manifestData.globalVarAliases = globalVarAliases;
|
|
3025
|
+
}
|
|
3026
|
+
if (hasCSSVariableMetrics(state.cssVarMetrics)) {
|
|
3027
|
+
manifestData.cssVarMetrics = state.cssVarMetrics;
|
|
3028
|
+
}
|
|
1983
3029
|
compilation.emitAsset(
|
|
1984
3030
|
"csszyx-manifest.json",
|
|
1985
3031
|
new compiler.webpack.sources.RawSource(JSON.stringify(manifestData))
|
|
1986
3032
|
);
|
|
3033
|
+
if (shouldEmitGlobalVarMapAsset(globalVarMangleConfig)) {
|
|
3034
|
+
const globalVarMapAsset = createGlobalVarMapAssetSource(
|
|
3035
|
+
state.varMangleMap,
|
|
3036
|
+
globalVarAliasPrefix,
|
|
3037
|
+
state.globalVarValidationResult
|
|
3038
|
+
);
|
|
3039
|
+
if (globalVarMapAsset) {
|
|
3040
|
+
compilation.emitAsset(
|
|
3041
|
+
".csszyx/global-var-map.json",
|
|
3042
|
+
new compiler.webpack.sources.RawSource(globalVarMapAsset)
|
|
3043
|
+
);
|
|
3044
|
+
}
|
|
3045
|
+
}
|
|
1987
3046
|
for (const file in assets) {
|
|
1988
3047
|
const asset = assets[file];
|
|
1989
3048
|
const source = asset.source().toString();
|
|
1990
|
-
if (
|
|
1991
|
-
|
|
3049
|
+
if (file.endsWith(".css")) {
|
|
3050
|
+
let css = rewriteCssWithValidatedGlobalVarPlan(
|
|
3051
|
+
source,
|
|
3052
|
+
file,
|
|
3053
|
+
state.globalVarValidationResult
|
|
3054
|
+
);
|
|
3055
|
+
if (manglingEnabled && !isWebpackDevMode && Object.keys(state.mangleMap).length > 0) {
|
|
1992
3056
|
try {
|
|
1993
|
-
const result = mangleCSSSync(
|
|
3057
|
+
const result = mangleCSSSync(css, state.mangleMap, {
|
|
1994
3058
|
debug: options.development?.debug,
|
|
1995
3059
|
from: file
|
|
1996
3060
|
});
|
|
1997
3061
|
if (result.transformedCount > 0) {
|
|
1998
|
-
|
|
1999
|
-
file,
|
|
2000
|
-
new compiler.webpack.sources.RawSource(result.css)
|
|
2001
|
-
);
|
|
2002
|
-
continue;
|
|
3062
|
+
css = result.css;
|
|
2003
3063
|
}
|
|
2004
3064
|
} catch (e) {
|
|
2005
3065
|
if (e && typeof e === "object" && "name" in e && e.name === "CssSyntaxError") ; else {
|
|
2006
3066
|
throw e;
|
|
2007
3067
|
}
|
|
2008
3068
|
}
|
|
2009
|
-
}
|
|
3069
|
+
}
|
|
3070
|
+
if (css !== source) {
|
|
3071
|
+
compilation.updateAsset(
|
|
3072
|
+
file,
|
|
3073
|
+
new compiler.webpack.sources.RawSource(css)
|
|
3074
|
+
);
|
|
3075
|
+
}
|
|
3076
|
+
continue;
|
|
3077
|
+
}
|
|
3078
|
+
if (manglingEnabled && !isWebpackDevMode && Object.keys(state.mangleMap).length > 0) {
|
|
3079
|
+
if (file.endsWith(".html")) {
|
|
2010
3080
|
const mangledHtml = source.replace(
|
|
2011
3081
|
/\bclass="([^"]*)"/g,
|
|
2012
3082
|
(_m, cls) => {
|
|
@@ -2061,6 +3131,9 @@ ${sourceDirective}`
|
|
|
2061
3131
|
*/
|
|
2062
3132
|
generateBundle(_options, bundle) {
|
|
2063
3133
|
finalizeMangleMap();
|
|
3134
|
+
state.globalVarValidationResult = validateGlobalVarBundleInputs(
|
|
3135
|
+
collectRollupGlobalVarCssAssets(bundle)
|
|
3136
|
+
);
|
|
2064
3137
|
const manifestData = {
|
|
2065
3138
|
version: "0.4.0",
|
|
2066
3139
|
buildId: state.checksum,
|
|
@@ -2069,31 +3142,70 @@ ${sourceDirective}`
|
|
|
2069
3142
|
if (manglingEnabled && Object.keys(state.mangleMap).length > 0) {
|
|
2070
3143
|
manifestData.mangleMap = state.mangleMap;
|
|
2071
3144
|
}
|
|
3145
|
+
if (Object.keys(state.varMangleMap).length > 0) {
|
|
3146
|
+
manifestData.varMangleMap = state.varMangleMap;
|
|
3147
|
+
}
|
|
3148
|
+
const globalVarAliases = extractGlobalVarAliasesForManifest(
|
|
3149
|
+
state.varMangleMap,
|
|
3150
|
+
globalVarAliasPrefix,
|
|
3151
|
+
state.globalVarValidationResult
|
|
3152
|
+
);
|
|
3153
|
+
if (Object.keys(globalVarAliases).length > 0) {
|
|
3154
|
+
manifestData.globalVarAliases = globalVarAliases;
|
|
3155
|
+
}
|
|
3156
|
+
if (hasCSSVariableMetrics(state.cssVarMetrics)) {
|
|
3157
|
+
manifestData.cssVarMetrics = state.cssVarMetrics;
|
|
3158
|
+
}
|
|
2072
3159
|
this.emitFile({
|
|
2073
3160
|
type: "asset",
|
|
2074
3161
|
fileName: "csszyx-manifest.json",
|
|
2075
3162
|
source: JSON.stringify(manifestData)
|
|
2076
3163
|
});
|
|
3164
|
+
if (shouldEmitGlobalVarMapAsset(globalVarMangleConfig)) {
|
|
3165
|
+
const globalVarMapAsset = createGlobalVarMapAssetSource(
|
|
3166
|
+
state.varMangleMap,
|
|
3167
|
+
globalVarAliasPrefix,
|
|
3168
|
+
state.globalVarValidationResult
|
|
3169
|
+
);
|
|
3170
|
+
if (globalVarMapAsset) {
|
|
3171
|
+
this.emitFile({
|
|
3172
|
+
type: "asset",
|
|
3173
|
+
fileName: ".csszyx/global-var-map.json",
|
|
3174
|
+
source: globalVarMapAsset
|
|
3175
|
+
});
|
|
3176
|
+
}
|
|
3177
|
+
}
|
|
2077
3178
|
for (const file in bundle) {
|
|
2078
3179
|
const chunk = bundle[file];
|
|
2079
|
-
if (
|
|
2080
|
-
|
|
2081
|
-
|
|
3180
|
+
if (chunk.type === "asset" && chunk.fileName.endsWith(".css")) {
|
|
3181
|
+
const originalCss = chunk.source.toString();
|
|
3182
|
+
let css = rewriteCssWithValidatedGlobalVarPlan(
|
|
3183
|
+
originalCss,
|
|
3184
|
+
file,
|
|
3185
|
+
state.globalVarValidationResult
|
|
3186
|
+
);
|
|
3187
|
+
if (manglingEnabled && Object.keys(state.mangleMap).length > 0) {
|
|
2082
3188
|
try {
|
|
2083
3189
|
const result = mangleCSSSync(css, state.mangleMap, {
|
|
2084
3190
|
debug: options.development?.debug,
|
|
2085
3191
|
from: file
|
|
2086
3192
|
});
|
|
2087
3193
|
if (result.transformedCount > 0) {
|
|
2088
|
-
|
|
3194
|
+
css = result.css;
|
|
2089
3195
|
}
|
|
2090
3196
|
} catch (e) {
|
|
2091
3197
|
if (e && typeof e === "object" && "name" in e && e.name === "CssSyntaxError") ; else {
|
|
2092
3198
|
throw e;
|
|
2093
3199
|
}
|
|
2094
3200
|
}
|
|
2095
|
-
|
|
2096
|
-
|
|
3201
|
+
}
|
|
3202
|
+
if (css !== originalCss) {
|
|
3203
|
+
chunk.source = css;
|
|
3204
|
+
}
|
|
3205
|
+
continue;
|
|
3206
|
+
}
|
|
3207
|
+
if (manglingEnabled && Object.keys(state.mangleMap).length > 0) {
|
|
3208
|
+
if (chunk.type === "chunk") {
|
|
2097
3209
|
let mangledCode = mangleCodeClasses(chunk.code);
|
|
2098
3210
|
mangledCode = replacePlaceholders(mangledCode);
|
|
2099
3211
|
if (mangledCode !== chunk.code) {
|
|
@@ -2156,4 +3268,4 @@ const esbuildPlugin = (options = {}) => {
|
|
|
2156
3268
|
};
|
|
2157
3269
|
};
|
|
2158
3270
|
|
|
2159
|
-
export { assertNoRSCBoundaryViolation as a, assertNoRSCGraphViolation as b,
|
|
3271
|
+
export { scanGlobalVarCss as A, validateGlobalVarAliasInputs as B, vitePlugin as C, webpackPlugin as D, writeGlobalVarScanCache as E, assertNoRSCBoundaryViolation as a, assertNoRSCGraphViolation as b, createGlobalVarAliasValidationOptions as c, createGlobalVarMapAssetSource as d, createGlobalVarScanCacheKey as e, createRSCModuleRecord as f, deleteRSCModuleRecord as g, esbuildPlugin as h, extractGlobalVarAliasesForManifest as i, findRSCBoundaryViolation as j, findRSCGraphViolation as k, hasTokens as l, hasUseClientDirective as m, hasUseServerDirective as n, isRSCServerModule as o, isTailwindReservedGlobalVar as p, mangleCodeClassesSync as q, mergeThemes as r, normalizeGlobalVarAliasesForCache as s, parseThemeBlocks as t, unplugin as u, planGlobalVarAliases as v, readGlobalVarScanCache as w, resolveGlobalVarScanCacheDir as x, rewriteGlobalVarCssAliases as y, rollupPlugin as z };
|