@csszyx/unplugin 0.8.0 → 0.9.0
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/README.md +16 -7
- package/dist/css-mangler.cjs +4 -4
- package/dist/css-mangler.mjs +4 -4
- package/dist/index.cjs +6 -1
- package/dist/index.d.cts +10 -1
- package/dist/index.d.mts +10 -1
- package/dist/index.mjs +5 -1
- package/dist/shared/{unplugin.DCv0RtVZ.mjs → unplugin.BEOG6ePC.mjs} +486 -49
- package/dist/shared/{unplugin.BNsv2szs.cjs → unplugin.CL0F6RZa.cjs} +486 -47
- package/dist/vite.cjs +5 -1
- package/dist/vite.mjs +5 -1
- package/dist/webpack.cjs +5 -1
- package/dist/webpack.mjs +5 -1
- package/package.json +6 -6
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const fs = require('node:fs');
|
|
4
|
+
const node_module = require('node:module');
|
|
4
5
|
const path = require('node:path');
|
|
6
|
+
const node_perf_hooks = require('node:perf_hooks');
|
|
7
|
+
const node_url = require('node:url');
|
|
5
8
|
const compiler = require('@csszyx/compiler');
|
|
6
9
|
const core = require('@csszyx/core');
|
|
7
10
|
const svelteAdapter = require('@csszyx/svelte-adapter');
|
|
11
|
+
const types = require('@csszyx/types');
|
|
8
12
|
const vueAdapter = require('@csszyx/vue-adapter');
|
|
9
13
|
const unplugin$1 = require('unplugin');
|
|
10
14
|
const cssMangler = require('../css-mangler.cjs');
|
|
11
15
|
const node_crypto = require('node:crypto');
|
|
12
16
|
|
|
17
|
+
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
13
18
|
function _interopNamespaceCompat(e) {
|
|
14
19
|
if (e && typeof e === 'object' && 'default' in e) return e;
|
|
15
20
|
const n = Object.create(null);
|
|
@@ -27,12 +32,16 @@ const path__namespace = /*#__PURE__*/_interopNamespaceCompat(path);
|
|
|
27
32
|
|
|
28
33
|
const SERVER_DIRECTIVE_RE = /^['"]use server['"];?$/;
|
|
29
34
|
const CLIENT_DIRECTIVE_RE = /^['"]use client['"];?$/;
|
|
30
|
-
const
|
|
35
|
+
const RUNTIME_HELPER_MODULES = /* @__PURE__ */ new Set([
|
|
31
36
|
"@csszyx/runtime",
|
|
32
37
|
"@csszyx/runtime/lite",
|
|
33
38
|
"csszyx",
|
|
34
39
|
"csszyx/lite"
|
|
35
40
|
]);
|
|
41
|
+
const CLIENT_RUNTIME_MODULES = /* @__PURE__ */ new Set(["csszyx/browser"]);
|
|
42
|
+
const CLIENT_RUNTIME_MODULE_ROOTS = ["@csszyx/dynamic", "csszyx/dynamic"];
|
|
43
|
+
const normalizedModuleIdCache = /* @__PURE__ */ new Map();
|
|
44
|
+
const resolvedLocalModuleCache = /* @__PURE__ */ new Map();
|
|
36
45
|
const FORBIDDEN_SYMBOLS = /* @__PURE__ */ new Set([
|
|
37
46
|
"_sz",
|
|
38
47
|
"_sz2",
|
|
@@ -102,6 +111,20 @@ function createRSCModuleRecord(code, id) {
|
|
|
102
111
|
)
|
|
103
112
|
};
|
|
104
113
|
}
|
|
114
|
+
function deleteRSCModuleRecord(records, id) {
|
|
115
|
+
const normalized = normalizeModuleId(id);
|
|
116
|
+
const clean = id.split("?")[0]?.replace(/\\/g, "/") ?? id;
|
|
117
|
+
const resolved = path__namespace.resolve(clean).replace(/\\/g, "/");
|
|
118
|
+
pruneRSCModulePathCaches(/* @__PURE__ */ new Set([normalized, resolved, clean]));
|
|
119
|
+
let deleted = records.delete(normalized);
|
|
120
|
+
if (resolved !== normalized) {
|
|
121
|
+
deleted = records.delete(resolved) || deleted;
|
|
122
|
+
}
|
|
123
|
+
if (clean !== normalized && clean !== resolved) {
|
|
124
|
+
deleted = records.delete(clean) || deleted;
|
|
125
|
+
}
|
|
126
|
+
return deleted;
|
|
127
|
+
}
|
|
105
128
|
function findRSCGraphViolation(records) {
|
|
106
129
|
for (const root of records.values()) {
|
|
107
130
|
if (!root.isServer) {
|
|
@@ -125,11 +148,26 @@ function assertNoRSCGraphViolation(records) {
|
|
|
125
148
|
}
|
|
126
149
|
throw new Error(formatRSCViolation(violation));
|
|
127
150
|
}
|
|
151
|
+
const APP_ROUTER_ENTRIES = /* @__PURE__ */ new Set([
|
|
152
|
+
"page",
|
|
153
|
+
"layout",
|
|
154
|
+
"template",
|
|
155
|
+
"loading",
|
|
156
|
+
"error",
|
|
157
|
+
"not-found",
|
|
158
|
+
"global-error",
|
|
159
|
+
"default",
|
|
160
|
+
"route"
|
|
161
|
+
]);
|
|
128
162
|
function isNextAppRouterEntry(id) {
|
|
129
163
|
const clean = id.split("?")[0]?.replace(/\\/g, "/") ?? id;
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
);
|
|
164
|
+
if (!clean.includes("/app/") && !clean.startsWith("app/")) return false;
|
|
165
|
+
const basename = clean.split("/").pop() ?? "";
|
|
166
|
+
const dotIdx = basename.indexOf(".");
|
|
167
|
+
if (dotIdx === -1) return false;
|
|
168
|
+
const stem = basename.slice(0, dotIdx);
|
|
169
|
+
const ext = basename.slice(dotIdx + 1);
|
|
170
|
+
return APP_ROUTER_ENTRIES.has(stem) && /^[cm]?[tj]sx?$/.test(ext);
|
|
133
171
|
}
|
|
134
172
|
function assertNoRSCBoundaryViolation(code, id) {
|
|
135
173
|
const violation = findRSCBoundaryViolation(code, id);
|
|
@@ -230,35 +268,51 @@ function skipWhitespaceAndComments(code, start) {
|
|
|
230
268
|
}
|
|
231
269
|
function findRuntimeImports(code) {
|
|
232
270
|
const imports = [];
|
|
233
|
-
const
|
|
271
|
+
const scanCode = stripCommentsForImportScan(code);
|
|
272
|
+
const staticImportRe = /import\s+(?!type\b)(\S(?:.*\S)?)\s+from\s+['"]([^'"]+)['"]/g;
|
|
234
273
|
const sideEffectImportRe = /import\s+['"]([^'"]+)['"]/g;
|
|
235
274
|
const dynamicImportRe = /import\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
|
|
236
|
-
for (const match of
|
|
275
|
+
for (const match of scanCode.matchAll(staticImportRe)) {
|
|
237
276
|
const clause = match[1];
|
|
238
277
|
const source = match[2];
|
|
239
|
-
if (!
|
|
278
|
+
if (!isRuntimeImportSource(source)) {
|
|
240
279
|
continue;
|
|
241
280
|
}
|
|
242
|
-
imports.push({ source, symbols:
|
|
281
|
+
imports.push({ source, symbols: readRuntimeImportSymbols(source, clause) });
|
|
243
282
|
}
|
|
244
|
-
for (const match of
|
|
283
|
+
for (const match of scanCode.matchAll(sideEffectImportRe)) {
|
|
245
284
|
const source = match[1];
|
|
246
|
-
if (
|
|
247
|
-
imports.push({
|
|
285
|
+
if (isRuntimeImportSource(source)) {
|
|
286
|
+
imports.push({
|
|
287
|
+
source,
|
|
288
|
+
symbols: isWholeRuntimeModuleForbidden(source) ? Array.from(FORBIDDEN_SYMBOLS) : []
|
|
289
|
+
});
|
|
248
290
|
}
|
|
249
291
|
}
|
|
250
|
-
for (const match of
|
|
292
|
+
for (const match of scanCode.matchAll(dynamicImportRe)) {
|
|
251
293
|
const source = match[1];
|
|
252
|
-
if (
|
|
294
|
+
if (isRuntimeImportSource(source)) {
|
|
253
295
|
imports.push({ source, symbols: Array.from(FORBIDDEN_SYMBOLS) });
|
|
254
296
|
}
|
|
255
297
|
}
|
|
256
298
|
return imports;
|
|
257
299
|
}
|
|
300
|
+
function isRuntimeImportSource(source) {
|
|
301
|
+
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}/`));
|
|
302
|
+
}
|
|
303
|
+
function isWholeRuntimeModuleForbidden(source) {
|
|
304
|
+
return source.startsWith("@csszyx/runtime/") || CLIENT_RUNTIME_MODULES.has(source) || CLIENT_RUNTIME_MODULE_ROOTS.some((root) => source === root || source.startsWith(`${root}/`));
|
|
305
|
+
}
|
|
306
|
+
function readRuntimeImportSymbols(source, clause) {
|
|
307
|
+
if (isWholeRuntimeModuleForbidden(source)) {
|
|
308
|
+
return Array.from(FORBIDDEN_SYMBOLS);
|
|
309
|
+
}
|
|
310
|
+
return readImportedSymbols(clause);
|
|
311
|
+
}
|
|
258
312
|
function findLocalImportSources(code) {
|
|
259
313
|
const out = [];
|
|
260
|
-
const staticImportRe = /import\s+(?!type\b)(
|
|
261
|
-
const exportFromRe = /export\s+(?!type\b)
|
|
314
|
+
const staticImportRe = /import\s+(?!type\b)(?:\S(?:.*\S)?\s+from\s+)?['"]([^'"]+)['"]/g;
|
|
315
|
+
const exportFromRe = /export\s+(?!type\b)\S(?:.*\S)?\s+from\s+['"]([^'"]+)['"]/g;
|
|
262
316
|
const dynamicImportRe = /import\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
|
|
263
317
|
for (const re of [staticImportRe, exportFromRe, dynamicImportRe]) {
|
|
264
318
|
for (const match of code.matchAll(re)) {
|
|
@@ -272,13 +326,25 @@ function findLocalImportSources(code) {
|
|
|
272
326
|
}
|
|
273
327
|
function normalizeModuleId(id) {
|
|
274
328
|
const clean = id.split("?")[0] ?? id;
|
|
329
|
+
const cached = normalizedModuleIdCache.get(clean);
|
|
330
|
+
if (cached) {
|
|
331
|
+
return cached;
|
|
332
|
+
}
|
|
333
|
+
let normalized;
|
|
275
334
|
try {
|
|
276
|
-
|
|
335
|
+
normalized = fs__namespace.realpathSync.native(clean).replace(/\\/g, "/");
|
|
277
336
|
} catch {
|
|
278
|
-
|
|
337
|
+
normalized = path__namespace.resolve(clean).replace(/\\/g, "/");
|
|
279
338
|
}
|
|
339
|
+
normalizedModuleIdCache.set(clean, normalized);
|
|
340
|
+
return normalized;
|
|
280
341
|
}
|
|
281
342
|
function resolveLocalModule(importer, source) {
|
|
343
|
+
const cacheKey = `${importer}\0${source}`;
|
|
344
|
+
const cached = resolvedLocalModuleCache.get(cacheKey);
|
|
345
|
+
if (cached) {
|
|
346
|
+
return cached;
|
|
347
|
+
}
|
|
282
348
|
const base = source.startsWith("/") ? source : path__namespace.resolve(path__namespace.dirname(importer), source);
|
|
283
349
|
const candidates = [
|
|
284
350
|
base,
|
|
@@ -295,11 +361,26 @@ function resolveLocalModule(importer, source) {
|
|
|
295
361
|
];
|
|
296
362
|
for (const candidate of candidates) {
|
|
297
363
|
if (fs__namespace.existsSync(candidate) && fs__namespace.statSync(candidate).isFile()) {
|
|
298
|
-
|
|
364
|
+
const resolved = normalizeModuleId(candidate);
|
|
365
|
+
resolvedLocalModuleCache.set(cacheKey, resolved);
|
|
366
|
+
return resolved;
|
|
299
367
|
}
|
|
300
368
|
}
|
|
301
369
|
return null;
|
|
302
370
|
}
|
|
371
|
+
function pruneRSCModulePathCaches(moduleIds) {
|
|
372
|
+
for (const [key, value] of normalizedModuleIdCache) {
|
|
373
|
+
const normalizedKey = key.replace(/\\/g, "/");
|
|
374
|
+
if (moduleIds.has(value) || moduleIds.has(normalizedKey)) {
|
|
375
|
+
normalizedModuleIdCache.delete(key);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
for (const [key, value] of resolvedLocalModuleCache) {
|
|
379
|
+
if (moduleIds.has(value)) {
|
|
380
|
+
resolvedLocalModuleCache.delete(key);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
}
|
|
303
384
|
function readImportedSymbols(clause) {
|
|
304
385
|
const symbols = [];
|
|
305
386
|
const named = clause.match(/\{([\s\S]*?)\}/);
|
|
@@ -318,8 +399,72 @@ function readImportedSymbols(clause) {
|
|
|
318
399
|
if (/\*\s+as\s+\w+/.test(clause)) {
|
|
319
400
|
symbols.push(...FORBIDDEN_SYMBOLS);
|
|
320
401
|
}
|
|
402
|
+
const braceStart = clause.indexOf("{");
|
|
403
|
+
const braceEnd = clause.indexOf("}", braceStart);
|
|
404
|
+
const stripped = braceStart !== -1 && braceEnd !== -1 ? clause.slice(0, braceStart) + clause.slice(braceEnd + 1) : clause;
|
|
405
|
+
const defaultImport = stripped.match(/^\s*([A-Z_$][\w$]*)\s*(?:,|$)/i);
|
|
406
|
+
const defaultSymbol = defaultImport?.[1];
|
|
407
|
+
if (defaultSymbol && FORBIDDEN_SYMBOLS.has(defaultSymbol)) {
|
|
408
|
+
symbols.push(defaultSymbol);
|
|
409
|
+
}
|
|
321
410
|
return symbols;
|
|
322
411
|
}
|
|
412
|
+
function stripCommentsForImportScan(code) {
|
|
413
|
+
let out = "";
|
|
414
|
+
let i = 0;
|
|
415
|
+
let quote = null;
|
|
416
|
+
let escaped = false;
|
|
417
|
+
while (i < code.length) {
|
|
418
|
+
const ch = code[i];
|
|
419
|
+
const next = code[i + 1];
|
|
420
|
+
if (quote) {
|
|
421
|
+
out += ch;
|
|
422
|
+
if (escaped) {
|
|
423
|
+
escaped = false;
|
|
424
|
+
} else if (ch === "\\") {
|
|
425
|
+
escaped = true;
|
|
426
|
+
} else if (ch === quote) {
|
|
427
|
+
quote = null;
|
|
428
|
+
}
|
|
429
|
+
i++;
|
|
430
|
+
continue;
|
|
431
|
+
}
|
|
432
|
+
if (ch === '"' || ch === "'" || ch === "`") {
|
|
433
|
+
quote = ch;
|
|
434
|
+
out += ch;
|
|
435
|
+
i++;
|
|
436
|
+
continue;
|
|
437
|
+
}
|
|
438
|
+
if (ch === "/" && next === "/") {
|
|
439
|
+
out += " ";
|
|
440
|
+
i += 2;
|
|
441
|
+
while (i < code.length && code[i] !== "\n") {
|
|
442
|
+
out += " ";
|
|
443
|
+
i++;
|
|
444
|
+
}
|
|
445
|
+
continue;
|
|
446
|
+
}
|
|
447
|
+
if (ch === "/" && next === "*") {
|
|
448
|
+
out += " ";
|
|
449
|
+
i += 2;
|
|
450
|
+
while (i < code.length) {
|
|
451
|
+
const blockCh = code[i];
|
|
452
|
+
const blockNext = code[i + 1];
|
|
453
|
+
if (blockCh === "*" && blockNext === "/") {
|
|
454
|
+
out += " ";
|
|
455
|
+
i += 2;
|
|
456
|
+
break;
|
|
457
|
+
}
|
|
458
|
+
out += blockCh === "\n" ? "\n" : " ";
|
|
459
|
+
i++;
|
|
460
|
+
}
|
|
461
|
+
continue;
|
|
462
|
+
}
|
|
463
|
+
out += ch;
|
|
464
|
+
i++;
|
|
465
|
+
}
|
|
466
|
+
return out;
|
|
467
|
+
}
|
|
323
468
|
|
|
324
469
|
const EMPTY_THEME = { colors: [], spacings: [], fonts: [], radii: [], shadows: [] };
|
|
325
470
|
function stripLayerWrappers(css) {
|
|
@@ -718,6 +863,149 @@ function writeThemeDts(opts) {
|
|
|
718
863
|
fs.writeFileSync(opts.outputPath, content, "utf-8");
|
|
719
864
|
}
|
|
720
865
|
|
|
866
|
+
const CACHE_SCHEMA_VERSION = 2;
|
|
867
|
+
function resolveTransformCacheDir(rootDir, cacheDir) {
|
|
868
|
+
return path__namespace.resolve(rootDir, cacheDir ?? ".csszyx/cache", "transform");
|
|
869
|
+
}
|
|
870
|
+
function createTransformCacheKey(input) {
|
|
871
|
+
const inputSha256 = node_crypto.createHash("sha256").update(input.source).digest("hex");
|
|
872
|
+
const keyMaterial = [
|
|
873
|
+
`schema=${CACHE_SCHEMA_VERSION}`,
|
|
874
|
+
`plugin=${input.pluginVersion}`,
|
|
875
|
+
`compiler=${input.compilerVersion}`,
|
|
876
|
+
`parser=${input.parserMode}`,
|
|
877
|
+
`producer=${input.producer}`,
|
|
878
|
+
`astBudget=${input.astBudget ?? "default"}`,
|
|
879
|
+
`filename=${input.filename}`,
|
|
880
|
+
`source=${inputSha256}`
|
|
881
|
+
].join("\n");
|
|
882
|
+
return {
|
|
883
|
+
key: node_crypto.createHash("sha256").update(keyMaterial).digest("hex").slice(0, 16),
|
|
884
|
+
inputSha256
|
|
885
|
+
};
|
|
886
|
+
}
|
|
887
|
+
function readTransformCache(cacheRoot, input, precomputedKey) {
|
|
888
|
+
const { key, inputSha256 } = precomputedKey ?? createTransformCacheKey(input);
|
|
889
|
+
const file = cacheEntryPath(cacheRoot, key);
|
|
890
|
+
let entry;
|
|
891
|
+
try {
|
|
892
|
+
entry = JSON.parse(fs__namespace.readFileSync(file, "utf8"));
|
|
893
|
+
} catch {
|
|
894
|
+
return null;
|
|
895
|
+
}
|
|
896
|
+
if (entry.version !== CACHE_SCHEMA_VERSION || entry.pluginVersion !== input.pluginVersion || entry.compilerVersion !== input.compilerVersion || entry.parserMode !== input.parserMode || entry.producer !== input.producer || entry.astBudget !== (input.astBudget ?? null) || entry.filename !== input.filename || entry.inputSha256 !== inputSha256) {
|
|
897
|
+
return null;
|
|
898
|
+
}
|
|
899
|
+
return deserializeResult(entry.result);
|
|
900
|
+
}
|
|
901
|
+
function writeTransformCache(cacheRoot, input, result, precomputedKey) {
|
|
902
|
+
const { key, inputSha256 } = precomputedKey ?? createTransformCacheKey(input);
|
|
903
|
+
const file = cacheEntryPath(cacheRoot, key);
|
|
904
|
+
const dir = path__namespace.dirname(file);
|
|
905
|
+
const tmp = path__namespace.join(
|
|
906
|
+
dir,
|
|
907
|
+
`.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`
|
|
908
|
+
);
|
|
909
|
+
const entry = {
|
|
910
|
+
version: CACHE_SCHEMA_VERSION,
|
|
911
|
+
pluginVersion: input.pluginVersion,
|
|
912
|
+
compilerVersion: input.compilerVersion,
|
|
913
|
+
parserMode: input.parserMode,
|
|
914
|
+
producer: input.producer,
|
|
915
|
+
astBudget: input.astBudget ?? null,
|
|
916
|
+
filename: input.filename,
|
|
917
|
+
inputSha256,
|
|
918
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
919
|
+
result: serializeResult(result)
|
|
920
|
+
};
|
|
921
|
+
try {
|
|
922
|
+
fs__namespace.mkdirSync(dir, { recursive: true });
|
|
923
|
+
fs__namespace.writeFileSync(tmp, JSON.stringify(entry), "utf8");
|
|
924
|
+
fs__namespace.renameSync(tmp, file);
|
|
925
|
+
} catch {
|
|
926
|
+
try {
|
|
927
|
+
fs__namespace.rmSync(tmp, { force: true });
|
|
928
|
+
} catch {
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
function evictOldTransformCacheEntries(cacheRoot, options) {
|
|
933
|
+
let deleted = 0;
|
|
934
|
+
const now = options.now ?? Date.now();
|
|
935
|
+
const survivors = [];
|
|
936
|
+
for (const file of listJsonFiles(cacheRoot)) {
|
|
937
|
+
try {
|
|
938
|
+
const entry = JSON.parse(fs__namespace.readFileSync(file, "utf8"));
|
|
939
|
+
const timestamp = typeof entry.timestamp === "string" ? Date.parse(entry.timestamp) : 0;
|
|
940
|
+
if (!Number.isFinite(timestamp) || now - timestamp > options.maxAgeMs) {
|
|
941
|
+
fs__namespace.rmSync(file, { force: true });
|
|
942
|
+
deleted++;
|
|
943
|
+
} else {
|
|
944
|
+
survivors.push({ file, timestamp });
|
|
945
|
+
}
|
|
946
|
+
} catch {
|
|
947
|
+
fs__namespace.rmSync(file, { force: true });
|
|
948
|
+
deleted++;
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
const overflow = survivors.length - options.maxEntries ;
|
|
952
|
+
if (overflow > 0) {
|
|
953
|
+
survivors.sort((a, b) => a.timestamp - b.timestamp);
|
|
954
|
+
for (const survivor of survivors.slice(0, overflow)) {
|
|
955
|
+
fs__namespace.rmSync(survivor.file, { force: true });
|
|
956
|
+
deleted++;
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
return deleted;
|
|
960
|
+
}
|
|
961
|
+
function cacheEntryPath(cacheRoot, key) {
|
|
962
|
+
return path__namespace.join(cacheRoot, key.slice(0, 2), `${key.slice(2)}.json`);
|
|
963
|
+
}
|
|
964
|
+
function serializeResult(result) {
|
|
965
|
+
return {
|
|
966
|
+
code: result.code,
|
|
967
|
+
transformed: result.transformed,
|
|
968
|
+
usesRuntime: result.usesRuntime,
|
|
969
|
+
usesMerge: result.usesMerge,
|
|
970
|
+
usesColorVar: result.usesColorVar,
|
|
971
|
+
classes: [...result.classes],
|
|
972
|
+
rawClassNames: [...result.rawClassNames],
|
|
973
|
+
diagnostics: [...result.diagnostics],
|
|
974
|
+
recoveryTokens: [...result.recoveryTokens]
|
|
975
|
+
};
|
|
976
|
+
}
|
|
977
|
+
function deserializeResult(result) {
|
|
978
|
+
return {
|
|
979
|
+
code: result.code,
|
|
980
|
+
transformed: result.transformed,
|
|
981
|
+
usesRuntime: result.usesRuntime,
|
|
982
|
+
usesMerge: result.usesMerge,
|
|
983
|
+
usesColorVar: result.usesColorVar,
|
|
984
|
+
classes: new Set(result.classes),
|
|
985
|
+
rawClassNames: new Set(result.rawClassNames),
|
|
986
|
+
diagnostics: [...result.diagnostics],
|
|
987
|
+
recoveryTokens: new Map(result.recoveryTokens)
|
|
988
|
+
};
|
|
989
|
+
}
|
|
990
|
+
function listJsonFiles(dir) {
|
|
991
|
+
let entries;
|
|
992
|
+
try {
|
|
993
|
+
entries = fs__namespace.readdirSync(dir, { withFileTypes: true });
|
|
994
|
+
} catch {
|
|
995
|
+
return [];
|
|
996
|
+
}
|
|
997
|
+
const files = [];
|
|
998
|
+
for (const entry of entries) {
|
|
999
|
+
const fullPath = path__namespace.join(dir, entry.name);
|
|
1000
|
+
if (entry.isDirectory()) {
|
|
1001
|
+
files.push(...listJsonFiles(fullPath));
|
|
1002
|
+
} else if (entry.isFile() && entry.name.endsWith(".json")) {
|
|
1003
|
+
files.push(fullPath);
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
return files;
|
|
1007
|
+
}
|
|
1008
|
+
|
|
721
1009
|
const VIRTUAL_MODULE_ID = "virtual:csszyx/mangle-map";
|
|
722
1010
|
const RESOLVED_VIRTUAL_MODULE_ID = `\0${VIRTUAL_MODULE_ID}`;
|
|
723
1011
|
const VIRTUAL_CHECKSUM_ID = "virtual:csszyx/checksum";
|
|
@@ -768,7 +1056,37 @@ function resolveVirtualModule(id) {
|
|
|
768
1056
|
|
|
769
1057
|
const CHECKSUM_PLACEHOLDER = "___CSSZYX_CHECKSUM___";
|
|
770
1058
|
const MANGLE_MAP_PLACEHOLDER = "___CSSZYX_MANGLE_MAP___";
|
|
1059
|
+
const UNKNOWN_PACKAGE_VERSION = "0.0.0";
|
|
1060
|
+
const TRANSFORM_CACHE_MAX_AGE_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
1061
|
+
const TRANSFORM_CACHE_MAX_ENTRIES = 1e4;
|
|
1062
|
+
const TRANSFORM_MEMORY_CACHE_MAX_ENTRIES = 1e3;
|
|
1063
|
+
const DIRECTIVE_PROLOGUE_PREFIX_RE = /^((?:\s|\/\/[^\n]*\n|\/\*(?:[^*]|\*(?!\/))*\*\/)*)(['"]use (?:client|server)['"];?\s*)/;
|
|
1064
|
+
const RUNTIME_HELPER_IMPORT_RE = {
|
|
1065
|
+
_sz: /\{[^}]*\b_sz\b[^}]*\}\s*from\s*['"]@csszyx\/runtime['"]/,
|
|
1066
|
+
_szMerge: /\{[^}]*\b_szMerge\b[^}]*\}\s*from\s*['"]@csszyx\/runtime['"]/,
|
|
1067
|
+
__szColorVar: /\{[^}]*\b__szColorVar\b[^}]*\}\s*from\s*['"]@csszyx\/runtime['"]/
|
|
1068
|
+
};
|
|
771
1069
|
let _hasWarnedTsConfig = false;
|
|
1070
|
+
let _hasWarnedTransformCacheVersion = false;
|
|
1071
|
+
const requireFromHere = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('shared/unplugin.CL0F6RZa.cjs', document.baseURI).href)));
|
|
1072
|
+
const PLUGIN_VERSION = findPackageVersionFromFile(
|
|
1073
|
+
node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('shared/unplugin.CL0F6RZa.cjs', document.baseURI).href))),
|
|
1074
|
+
UNKNOWN_PACKAGE_VERSION
|
|
1075
|
+
);
|
|
1076
|
+
const COMPILER_VERSION = findPackageVersionFromModule("@csszyx/compiler", UNKNOWN_PACKAGE_VERSION);
|
|
1077
|
+
const BENCH_TRACE_ENABLED = process.env.CSSZYX_BENCH_TRACE === "1";
|
|
1078
|
+
const BENCH_TRACE_FILE = process.env.CSSZYX_BENCH_TRACE_FILE;
|
|
1079
|
+
function traceBenchTiming(label, filename, elapsedMs) {
|
|
1080
|
+
if (!BENCH_TRACE_ENABLED) {
|
|
1081
|
+
return;
|
|
1082
|
+
}
|
|
1083
|
+
if (BENCH_TRACE_FILE && !filename.includes(BENCH_TRACE_FILE)) {
|
|
1084
|
+
return;
|
|
1085
|
+
}
|
|
1086
|
+
console.log(
|
|
1087
|
+
`[csszyx:bench] ${label} ${elapsedMs.toFixed(3)}ms ${normalizeSourceFilename(filename)}`
|
|
1088
|
+
);
|
|
1089
|
+
}
|
|
772
1090
|
function runThemeScan(rootDir, scanCss) {
|
|
773
1091
|
if (!scanCss) {
|
|
774
1092
|
return;
|
|
@@ -811,6 +1129,42 @@ function runThemeScan(rootDir, scanCss) {
|
|
|
811
1129
|
}
|
|
812
1130
|
}
|
|
813
1131
|
}
|
|
1132
|
+
function findPackageVersionFromModule(specifier, fallback) {
|
|
1133
|
+
try {
|
|
1134
|
+
return findPackageVersionFromFile(requireFromHere.resolve(specifier), fallback);
|
|
1135
|
+
} catch {
|
|
1136
|
+
return fallback;
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1139
|
+
function findPackageVersionFromFile(file, fallback) {
|
|
1140
|
+
let dir = path__namespace.dirname(file);
|
|
1141
|
+
while (true) {
|
|
1142
|
+
const packageJson = path__namespace.join(dir, "package.json");
|
|
1143
|
+
try {
|
|
1144
|
+
const parsed = JSON.parse(fs__namespace.readFileSync(packageJson, "utf8"));
|
|
1145
|
+
if (typeof parsed.version === "string") {
|
|
1146
|
+
return parsed.version;
|
|
1147
|
+
}
|
|
1148
|
+
return fallback;
|
|
1149
|
+
} catch {
|
|
1150
|
+
}
|
|
1151
|
+
const parent = path__namespace.dirname(dir);
|
|
1152
|
+
if (parent === dir) {
|
|
1153
|
+
return fallback;
|
|
1154
|
+
}
|
|
1155
|
+
dir = parent;
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
function normalizeSourceFilename(filename) {
|
|
1159
|
+
return filename.replace(/\\/g, "/");
|
|
1160
|
+
}
|
|
1161
|
+
function insertRuntimeImport(code, importStmt) {
|
|
1162
|
+
const directiveMatch = code.match(DIRECTIVE_PROLOGUE_PREFIX_RE);
|
|
1163
|
+
if (!directiveMatch) {
|
|
1164
|
+
return `${importStmt}${code}`;
|
|
1165
|
+
}
|
|
1166
|
+
return code.replace(directiveMatch[0], `${directiveMatch[1]}${directiveMatch[2]}${importStmt}`);
|
|
1167
|
+
}
|
|
814
1168
|
function mangleCodeClassesSync(code, mangleMap) {
|
|
815
1169
|
function mangleClassString(classString) {
|
|
816
1170
|
return classString.split(/\s+/).filter(Boolean).map((cls) => {
|
|
@@ -986,8 +1340,20 @@ function mangleCodeClassesSync(code, mangleMap) {
|
|
|
986
1340
|
function createCsszyxPlugins(options = {}) {
|
|
987
1341
|
const manglingEnabled = options.production?.mangle !== false;
|
|
988
1342
|
const astBudgetOverride = options.build?.astBudgetLimit;
|
|
1343
|
+
const cacheRequested = (options.build?.cache ?? types.DEFAULT_BUILD_CONFIG.cache) !== false;
|
|
1344
|
+
const cacheVersionsKnown = PLUGIN_VERSION !== UNKNOWN_PACKAGE_VERSION && COMPILER_VERSION !== UNKNOWN_PACKAGE_VERSION;
|
|
1345
|
+
const cacheEnabled = cacheRequested && cacheVersionsKnown;
|
|
1346
|
+
if (cacheRequested && !cacheVersionsKnown && !_hasWarnedTransformCacheVersion) {
|
|
1347
|
+
_hasWarnedTransformCacheVersion = true;
|
|
1348
|
+
console.warn(
|
|
1349
|
+
"[csszyx] Transform cache disabled because package versions could not be resolved."
|
|
1350
|
+
);
|
|
1351
|
+
}
|
|
989
1352
|
const parserOverride = process.env.CSSZYX_PARSER;
|
|
990
|
-
const
|
|
1353
|
+
const defaultParser = types.DEFAULT_BUILD_CONFIG.parser ?? "rust";
|
|
1354
|
+
const parserMode = parserOverride === "babel" || parserOverride === "oxc" || parserOverride === "rust" ? parserOverride : options.build?.parser ?? defaultParser;
|
|
1355
|
+
let evictedCacheRoot = null;
|
|
1356
|
+
const transformMemoryCache = /* @__PURE__ */ new Map();
|
|
991
1357
|
const state = {
|
|
992
1358
|
classes: /* @__PURE__ */ new Set(),
|
|
993
1359
|
mangleMap: {},
|
|
@@ -1017,19 +1383,84 @@ function createCsszyxPlugins(options = {}) {
|
|
|
1017
1383
|
}
|
|
1018
1384
|
function transformConfiguredSource(source, filename) {
|
|
1019
1385
|
const compilerOptions = { astBudget: astBudgetOverride };
|
|
1020
|
-
|
|
1021
|
-
|
|
1386
|
+
const effectiveFilename = normalizeSourceFilename(filename);
|
|
1387
|
+
const cacheRoot = resolveTransformCacheDir(state.rootDir, options.build?.cacheDir);
|
|
1388
|
+
if (cacheEnabled) {
|
|
1389
|
+
evictTransformCacheOnce();
|
|
1390
|
+
}
|
|
1391
|
+
const cacheInput = {
|
|
1392
|
+
pluginVersion: PLUGIN_VERSION,
|
|
1393
|
+
compilerVersion: COMPILER_VERSION,
|
|
1394
|
+
parserMode,
|
|
1395
|
+
producer: parserMode,
|
|
1396
|
+
astBudget: astBudgetOverride,
|
|
1397
|
+
filename: effectiveFilename,
|
|
1398
|
+
source
|
|
1399
|
+
};
|
|
1400
|
+
if (parserMode === "rust") {
|
|
1401
|
+
compiler.ensureRustTransformAvailable();
|
|
1402
|
+
}
|
|
1403
|
+
const cacheKey = cacheEnabled ? createTransformCacheKey(cacheInput) : null;
|
|
1404
|
+
if (cacheEnabled && cacheKey) {
|
|
1405
|
+
const memoryCached = transformMemoryCache.get(cacheKey.key);
|
|
1406
|
+
if (memoryCached) {
|
|
1407
|
+
transformMemoryCache.delete(cacheKey.key);
|
|
1408
|
+
transformMemoryCache.set(cacheKey.key, memoryCached);
|
|
1409
|
+
return memoryCached;
|
|
1410
|
+
}
|
|
1411
|
+
const cached = readTransformCache(cacheRoot, cacheInput, cacheKey);
|
|
1412
|
+
if (cached) {
|
|
1413
|
+
rememberTransformCacheEntry(cacheKey.key, cached);
|
|
1414
|
+
return cached;
|
|
1415
|
+
}
|
|
1022
1416
|
}
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1417
|
+
let result;
|
|
1418
|
+
if (parserMode === "babel") {
|
|
1419
|
+
result = compiler.transformSourceCode(source, effectiveFilename, compilerOptions);
|
|
1420
|
+
} else if (parserMode === "rust") {
|
|
1421
|
+
result = compiler.transformRust(source, effectiveFilename, compilerOptions);
|
|
1422
|
+
} else {
|
|
1423
|
+
try {
|
|
1424
|
+
result = compiler.transformOxc(source, effectiveFilename, compilerOptions);
|
|
1425
|
+
} catch (err) {
|
|
1426
|
+
result = compiler.transformSourceCode(source, effectiveFilename, compilerOptions);
|
|
1427
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
1428
|
+
result.diagnostics.push(
|
|
1429
|
+
`[csszyx] oxc parser fell back to Babel for ${effectiveFilename}: ${reason}`
|
|
1430
|
+
);
|
|
1431
|
+
return result;
|
|
1432
|
+
}
|
|
1032
1433
|
}
|
|
1434
|
+
if (cacheEnabled && cacheKey) {
|
|
1435
|
+
writeTransformCache(cacheRoot, cacheInput, result, cacheKey);
|
|
1436
|
+
rememberTransformCacheEntry(cacheKey.key, result);
|
|
1437
|
+
}
|
|
1438
|
+
return result;
|
|
1439
|
+
}
|
|
1440
|
+
function rememberTransformCacheEntry(key, result) {
|
|
1441
|
+
transformMemoryCache.delete(key);
|
|
1442
|
+
transformMemoryCache.set(key, result);
|
|
1443
|
+
if (transformMemoryCache.size <= TRANSFORM_MEMORY_CACHE_MAX_ENTRIES) {
|
|
1444
|
+
return;
|
|
1445
|
+
}
|
|
1446
|
+
const oldest = transformMemoryCache.keys().next().value;
|
|
1447
|
+
if (oldest) {
|
|
1448
|
+
transformMemoryCache.delete(oldest);
|
|
1449
|
+
}
|
|
1450
|
+
}
|
|
1451
|
+
function evictTransformCacheOnce() {
|
|
1452
|
+
if (!cacheEnabled) {
|
|
1453
|
+
return;
|
|
1454
|
+
}
|
|
1455
|
+
const cacheRoot = resolveTransformCacheDir(state.rootDir, options.build?.cacheDir);
|
|
1456
|
+
if (evictedCacheRoot === cacheRoot) {
|
|
1457
|
+
return;
|
|
1458
|
+
}
|
|
1459
|
+
evictedCacheRoot = cacheRoot;
|
|
1460
|
+
evictOldTransformCacheEntries(cacheRoot, {
|
|
1461
|
+
maxAgeMs: TRANSFORM_CACHE_MAX_AGE_MS,
|
|
1462
|
+
maxEntries: TRANSFORM_CACHE_MAX_ENTRIES
|
|
1463
|
+
});
|
|
1033
1464
|
}
|
|
1034
1465
|
function writeSafelistFile(classes) {
|
|
1035
1466
|
if (classes.size === 0) {
|
|
@@ -1311,7 +1742,13 @@ ${sourceDirective}`
|
|
|
1311
1742
|
transformed = true;
|
|
1312
1743
|
}
|
|
1313
1744
|
} else {
|
|
1745
|
+
const transformStarted = node_perf_hooks.performance.now();
|
|
1314
1746
|
const result = transformConfiguredSource(code, id);
|
|
1747
|
+
traceBenchTiming(
|
|
1748
|
+
"transform-hook",
|
|
1749
|
+
id,
|
|
1750
|
+
node_perf_hooks.performance.now() - transformStarted
|
|
1751
|
+
);
|
|
1315
1752
|
transformedCode = result.code;
|
|
1316
1753
|
usesRuntime = result.usesRuntime;
|
|
1317
1754
|
usesMerge = result.usesMerge;
|
|
@@ -1355,11 +1792,10 @@ ${sourceDirective}`
|
|
|
1355
1792
|
if (usesColorVar) {
|
|
1356
1793
|
imports.push("__szColorVar");
|
|
1357
1794
|
}
|
|
1358
|
-
const
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
);
|
|
1795
|
+
const hasRuntimeImport = imports.length > 0 && transformedCode.includes("@csszyx/runtime");
|
|
1796
|
+
const needed = hasRuntimeImport ? imports.filter(
|
|
1797
|
+
(name) => !RUNTIME_HELPER_IMPORT_RE[name]?.test(transformedCode)
|
|
1798
|
+
) : imports;
|
|
1363
1799
|
if (needed.length > 0) {
|
|
1364
1800
|
const existingImport = transformedCode.match(
|
|
1365
1801
|
/^(import\s*\{[^}]*)\}\s*from\s*'@csszyx\/runtime'/m
|
|
@@ -1372,18 +1808,7 @@ ${sourceDirective}`
|
|
|
1372
1808
|
} else {
|
|
1373
1809
|
const importStmt = `import { ${needed.join(", ")} } from '@csszyx/runtime';
|
|
1374
1810
|
`;
|
|
1375
|
-
|
|
1376
|
-
/^['"]use (client|server)['"];?\s*/
|
|
1377
|
-
);
|
|
1378
|
-
if (directiveMatch) {
|
|
1379
|
-
const directive = directiveMatch[0];
|
|
1380
|
-
transformedCode = transformedCode.replace(
|
|
1381
|
-
directive,
|
|
1382
|
-
`${directive}${importStmt}`
|
|
1383
|
-
);
|
|
1384
|
-
} else {
|
|
1385
|
-
transformedCode = `${importStmt}${transformedCode}`;
|
|
1386
|
-
}
|
|
1811
|
+
transformedCode = insertRuntimeImport(transformedCode, importStmt);
|
|
1387
1812
|
}
|
|
1388
1813
|
transformed = true;
|
|
1389
1814
|
}
|
|
@@ -1413,6 +1838,11 @@ ${sourceDirective}`
|
|
|
1413
1838
|
globalThis.__csszyx_ssr_mangle_map = state.mangleMap;
|
|
1414
1839
|
}
|
|
1415
1840
|
},
|
|
1841
|
+
watchChange(id, change) {
|
|
1842
|
+
if (change.event === "delete") {
|
|
1843
|
+
deleteRSCModuleRecord(state.rscModules, id);
|
|
1844
|
+
}
|
|
1845
|
+
},
|
|
1416
1846
|
/**
|
|
1417
1847
|
* Webpack hook: pre-scans source files before compilation for Tailwind class discovery.
|
|
1418
1848
|
* @param compiler - the Webpack compiler instance
|
|
@@ -1421,6 +1851,7 @@ ${sourceDirective}`
|
|
|
1421
1851
|
compiler.hooks.beforeCompile.tap("csszyx:prescan", () => {
|
|
1422
1852
|
const root = compiler.context || process.cwd();
|
|
1423
1853
|
state.rootDir = root;
|
|
1854
|
+
evictTransformCacheOnce();
|
|
1424
1855
|
if (state.classes.size === 0) {
|
|
1425
1856
|
prescanAndWriteClasses();
|
|
1426
1857
|
}
|
|
@@ -1444,6 +1875,7 @@ ${sourceDirective}`
|
|
|
1444
1875
|
configResolved(config) {
|
|
1445
1876
|
const root = config.root || process.cwd();
|
|
1446
1877
|
state.rootDir = root;
|
|
1878
|
+
evictTransformCacheOnce();
|
|
1447
1879
|
prescanAndWriteClasses();
|
|
1448
1880
|
runThemeScan(root, options.build?.scanCss);
|
|
1449
1881
|
},
|
|
@@ -1473,7 +1905,13 @@ ${sourceDirective}`
|
|
|
1473
1905
|
return;
|
|
1474
1906
|
}
|
|
1475
1907
|
try {
|
|
1908
|
+
const hmrTransformStarted = node_perf_hooks.performance.now();
|
|
1476
1909
|
result = transformConfiguredSource(fileContent, ctx.file);
|
|
1910
|
+
traceBenchTiming(
|
|
1911
|
+
"handle-hot-update",
|
|
1912
|
+
ctx.file,
|
|
1913
|
+
node_perf_hooks.performance.now() - hmrTransformStarted
|
|
1914
|
+
);
|
|
1477
1915
|
} catch {
|
|
1478
1916
|
return;
|
|
1479
1917
|
}
|
|
@@ -1737,6 +2175,7 @@ const esbuildPlugin = (options = {}) => {
|
|
|
1737
2175
|
exports.assertNoRSCBoundaryViolation = assertNoRSCBoundaryViolation;
|
|
1738
2176
|
exports.assertNoRSCGraphViolation = assertNoRSCGraphViolation;
|
|
1739
2177
|
exports.createRSCModuleRecord = createRSCModuleRecord;
|
|
2178
|
+
exports.deleteRSCModuleRecord = deleteRSCModuleRecord;
|
|
1740
2179
|
exports.esbuildPlugin = esbuildPlugin;
|
|
1741
2180
|
exports.findRSCBoundaryViolation = findRSCBoundaryViolation;
|
|
1742
2181
|
exports.findRSCGraphViolation = findRSCGraphViolation;
|