@csszyx/unplugin 0.5.0 → 0.6.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/{chunk-CW4XYEQR.js → chunk-JGJOUK2R.js} +71 -5
- package/dist/index.cjs +71 -5
- package/dist/index.js +1 -1
- package/dist/vite.cjs +71 -5
- package/dist/vite.js +1 -1
- package/dist/webpack.cjs +71 -5
- package/dist/webpack.js +1 -1
- package/package.json +6 -6
|
@@ -154,6 +154,7 @@ import { preprocess as vuePreprocess } from "@csszyx/vue-adapter";
|
|
|
154
154
|
import { createUnplugin } from "unplugin";
|
|
155
155
|
|
|
156
156
|
// src/html-transformer.ts
|
|
157
|
+
import { createHash } from "crypto";
|
|
157
158
|
function injectChecksum(html, checksum, minify = false) {
|
|
158
159
|
const attrName = minify ? "data-sz-cs" : "data-sz-checksum";
|
|
159
160
|
const htmlTagPattern = /<html([^>]*)>/i;
|
|
@@ -213,6 +214,46 @@ function injectHydrationData(html, mangleMap, checksum, options = {}) {
|
|
|
213
214
|
function transformIndexHtml(html, mangleMap, checksum, options = {}) {
|
|
214
215
|
return injectHydrationData(html, mangleMap, checksum, options);
|
|
215
216
|
}
|
|
217
|
+
function buildRecoveryManifest(tokens, options = {}) {
|
|
218
|
+
const stripped = options.production === true;
|
|
219
|
+
const strippedDevOnlyPaths = [];
|
|
220
|
+
const sorted = {};
|
|
221
|
+
const sortedKeys = [...tokens.keys()].sort();
|
|
222
|
+
for (const key of sortedKeys) {
|
|
223
|
+
const data = tokens.get(key);
|
|
224
|
+
if (!data) {
|
|
225
|
+
continue;
|
|
226
|
+
}
|
|
227
|
+
if (stripped && data.mode === "dev-only") {
|
|
228
|
+
strippedDevOnlyPaths.push(data.path);
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
sorted[key] = stripped ? { mode: data.mode, component: data.component, path: "" } : data;
|
|
232
|
+
}
|
|
233
|
+
const serialised = JSON.stringify(sorted);
|
|
234
|
+
const fullChecksum = createHash("sha256").update(serialised).digest("hex");
|
|
235
|
+
const checksum = fullChecksum.substring(0, 16);
|
|
236
|
+
const buildId = `${Date.now().toString(36)}-${fullChecksum.substring(0, 6)}`;
|
|
237
|
+
return {
|
|
238
|
+
manifest: { buildId, checksum, tokens: sorted },
|
|
239
|
+
strippedDevOnlyPaths
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
function injectRecoveryManifest(html, manifest) {
|
|
243
|
+
if (Object.keys(manifest.tokens).length === 0) {
|
|
244
|
+
return html;
|
|
245
|
+
}
|
|
246
|
+
const json = JSON.stringify(manifest);
|
|
247
|
+
const scriptTag = `<script id="__SZ_RECOVERY_MANIFEST__" type="application/json">${json}</script>`;
|
|
248
|
+
if (html.includes("</head>")) {
|
|
249
|
+
return html.replace("</head>", `${scriptTag}
|
|
250
|
+
</head>`);
|
|
251
|
+
} else if (html.includes("</html>")) {
|
|
252
|
+
return html.replace("</html>", `${scriptTag}
|
|
253
|
+
</html>`);
|
|
254
|
+
}
|
|
255
|
+
return html + scriptTag;
|
|
256
|
+
}
|
|
216
257
|
|
|
217
258
|
// src/theme-type-writer.ts
|
|
218
259
|
import { mkdirSync, writeFileSync } from "fs";
|
|
@@ -537,12 +578,14 @@ function mangleCodeClassesSync(code, mangleMap) {
|
|
|
537
578
|
}
|
|
538
579
|
function createCsszyxPlugins(options = {}) {
|
|
539
580
|
const manglingEnabled = options.production?.mangle !== false;
|
|
581
|
+
const astBudgetOverride = options.build?.astBudgetLimit;
|
|
540
582
|
const state = {
|
|
541
583
|
classes: /* @__PURE__ */ new Set(),
|
|
542
584
|
mangleMap: {},
|
|
543
585
|
checksum: "",
|
|
544
586
|
finalized: false,
|
|
545
|
-
rootDir: process.cwd()
|
|
587
|
+
rootDir: process.cwd(),
|
|
588
|
+
recoveryTokens: /* @__PURE__ */ new Map()
|
|
546
589
|
};
|
|
547
590
|
const SAFELIST_FILENAME = "csszyx-classes.html";
|
|
548
591
|
const SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([".tsx", ".jsx", ".ts", ".js"]);
|
|
@@ -587,7 +630,7 @@ function createCsszyxPlugins(options = {}) {
|
|
|
587
630
|
if (!content.includes("sz=") && !content.includes("sz:")) {
|
|
588
631
|
continue;
|
|
589
632
|
}
|
|
590
|
-
const result = transformSourceCode(content);
|
|
633
|
+
const result = transformSourceCode(content, filePath, { astBudget: astBudgetOverride });
|
|
591
634
|
if (!result.transformed) {
|
|
592
635
|
continue;
|
|
593
636
|
}
|
|
@@ -597,6 +640,9 @@ function createCsszyxPlugins(options = {}) {
|
|
|
597
640
|
for (const cls of result.rawClassNames) {
|
|
598
641
|
rawDiscoveredClasses.add(cls);
|
|
599
642
|
}
|
|
643
|
+
for (const [token, data] of result.recoveryTokens) {
|
|
644
|
+
state.recoveryTokens.set(token, data);
|
|
645
|
+
}
|
|
600
646
|
if (result.usesRuntime) {
|
|
601
647
|
const szCallRe = /_sz\(\s*\{/g;
|
|
602
648
|
let szMatch;
|
|
@@ -818,7 +864,7 @@ ${sourceDirective}`
|
|
|
818
864
|
transformed = true;
|
|
819
865
|
}
|
|
820
866
|
} else {
|
|
821
|
-
const result = transformSourceCode(code);
|
|
867
|
+
const result = transformSourceCode(code, id, { astBudget: astBudgetOverride });
|
|
822
868
|
transformedCode = result.code;
|
|
823
869
|
usesRuntime = result.usesRuntime;
|
|
824
870
|
usesMerge = result.usesMerge;
|
|
@@ -831,6 +877,9 @@ ${sourceDirective}`
|
|
|
831
877
|
${msg}`);
|
|
832
878
|
}
|
|
833
879
|
}
|
|
880
|
+
for (const [token, data] of result.recoveryTokens) {
|
|
881
|
+
state.recoveryTokens.set(token, data);
|
|
882
|
+
}
|
|
834
883
|
}
|
|
835
884
|
}
|
|
836
885
|
if (transformedCode.includes("<html") && /layout|Root|Document|app\\.tsx?$/i.test(id)) {
|
|
@@ -971,7 +1020,7 @@ ${sourceDirective}`
|
|
|
971
1020
|
return;
|
|
972
1021
|
}
|
|
973
1022
|
try {
|
|
974
|
-
result = transformSourceCode(fileContent);
|
|
1023
|
+
result = transformSourceCode(fileContent, ctx.file, { astBudget: astBudgetOverride });
|
|
975
1024
|
} catch {
|
|
976
1025
|
return;
|
|
977
1026
|
}
|
|
@@ -982,6 +1031,9 @@ ${sourceDirective}`
|
|
|
982
1031
|
for (const cls of result.classes) {
|
|
983
1032
|
state.classes.add(cls);
|
|
984
1033
|
}
|
|
1034
|
+
for (const [token, data] of result.recoveryTokens) {
|
|
1035
|
+
state.recoveryTokens.set(token, data);
|
|
1036
|
+
}
|
|
985
1037
|
if (state.classes.size > sizeBefore) {
|
|
986
1038
|
writeSafelistFile(state.classes);
|
|
987
1039
|
const safelistPath = path.join(state.rootDir, SAFELIST_FILENAME);
|
|
@@ -998,10 +1050,24 @@ ${sourceDirective}`
|
|
|
998
1050
|
*/
|
|
999
1051
|
handler(html) {
|
|
1000
1052
|
finalizeMangleMap();
|
|
1001
|
-
|
|
1053
|
+
let result = transformIndexHtml(html, state.mangleMap, state.checksum, {
|
|
1002
1054
|
mode: options.production?.injectChecksum === false ? "script" : "script",
|
|
1003
1055
|
minify: process.env.NODE_ENV === "production"
|
|
1004
1056
|
});
|
|
1057
|
+
if (state.recoveryTokens.size > 0) {
|
|
1058
|
+
const isProduction = process.env.NODE_ENV === "production";
|
|
1059
|
+
const { manifest, strippedDevOnlyPaths } = buildRecoveryManifest(
|
|
1060
|
+
state.recoveryTokens,
|
|
1061
|
+
{ production: isProduction }
|
|
1062
|
+
);
|
|
1063
|
+
if (strippedDevOnlyPaths.length > 0) {
|
|
1064
|
+
console.warn(
|
|
1065
|
+
`[csszyx] Stripped ${strippedDevOnlyPaths.length} szRecover="dev-only" token(s) from the production manifest. Recovery for these elements is disabled in production by design. Sites: ${strippedDevOnlyPaths.join(", ")}`
|
|
1066
|
+
);
|
|
1067
|
+
}
|
|
1068
|
+
result = injectRecoveryManifest(result, manifest);
|
|
1069
|
+
}
|
|
1070
|
+
return result;
|
|
1005
1071
|
}
|
|
1006
1072
|
}
|
|
1007
1073
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -395,6 +395,7 @@ var import_vue_adapter = require("@csszyx/vue-adapter");
|
|
|
395
395
|
var import_unplugin = require("unplugin");
|
|
396
396
|
|
|
397
397
|
// src/html-transformer.ts
|
|
398
|
+
var import_node_crypto = require("crypto");
|
|
398
399
|
function injectChecksum(html, checksum, minify = false) {
|
|
399
400
|
const attrName = minify ? "data-sz-cs" : "data-sz-checksum";
|
|
400
401
|
const htmlTagPattern = /<html([^>]*)>/i;
|
|
@@ -454,6 +455,46 @@ function injectHydrationData(html, mangleMap, checksum, options = {}) {
|
|
|
454
455
|
function transformIndexHtml(html, mangleMap, checksum, options = {}) {
|
|
455
456
|
return injectHydrationData(html, mangleMap, checksum, options);
|
|
456
457
|
}
|
|
458
|
+
function buildRecoveryManifest(tokens, options = {}) {
|
|
459
|
+
const stripped = options.production === true;
|
|
460
|
+
const strippedDevOnlyPaths = [];
|
|
461
|
+
const sorted = {};
|
|
462
|
+
const sortedKeys = [...tokens.keys()].sort();
|
|
463
|
+
for (const key of sortedKeys) {
|
|
464
|
+
const data = tokens.get(key);
|
|
465
|
+
if (!data) {
|
|
466
|
+
continue;
|
|
467
|
+
}
|
|
468
|
+
if (stripped && data.mode === "dev-only") {
|
|
469
|
+
strippedDevOnlyPaths.push(data.path);
|
|
470
|
+
continue;
|
|
471
|
+
}
|
|
472
|
+
sorted[key] = stripped ? { mode: data.mode, component: data.component, path: "" } : data;
|
|
473
|
+
}
|
|
474
|
+
const serialised = JSON.stringify(sorted);
|
|
475
|
+
const fullChecksum = (0, import_node_crypto.createHash)("sha256").update(serialised).digest("hex");
|
|
476
|
+
const checksum = fullChecksum.substring(0, 16);
|
|
477
|
+
const buildId = `${Date.now().toString(36)}-${fullChecksum.substring(0, 6)}`;
|
|
478
|
+
return {
|
|
479
|
+
manifest: { buildId, checksum, tokens: sorted },
|
|
480
|
+
strippedDevOnlyPaths
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
function injectRecoveryManifest(html, manifest) {
|
|
484
|
+
if (Object.keys(manifest.tokens).length === 0) {
|
|
485
|
+
return html;
|
|
486
|
+
}
|
|
487
|
+
const json = JSON.stringify(manifest);
|
|
488
|
+
const scriptTag = `<script id="__SZ_RECOVERY_MANIFEST__" type="application/json">${json}</script>`;
|
|
489
|
+
if (html.includes("</head>")) {
|
|
490
|
+
return html.replace("</head>", `${scriptTag}
|
|
491
|
+
</head>`);
|
|
492
|
+
} else if (html.includes("</html>")) {
|
|
493
|
+
return html.replace("</html>", `${scriptTag}
|
|
494
|
+
</html>`);
|
|
495
|
+
}
|
|
496
|
+
return html + scriptTag;
|
|
497
|
+
}
|
|
457
498
|
|
|
458
499
|
// src/theme-type-writer.ts
|
|
459
500
|
var import_node_fs = require("fs");
|
|
@@ -778,12 +819,14 @@ function mangleCodeClassesSync(code, mangleMap) {
|
|
|
778
819
|
}
|
|
779
820
|
function createCsszyxPlugins(options = {}) {
|
|
780
821
|
const manglingEnabled = options.production?.mangle !== false;
|
|
822
|
+
const astBudgetOverride = options.build?.astBudgetLimit;
|
|
781
823
|
const state = {
|
|
782
824
|
classes: /* @__PURE__ */ new Set(),
|
|
783
825
|
mangleMap: {},
|
|
784
826
|
checksum: "",
|
|
785
827
|
finalized: false,
|
|
786
|
-
rootDir: process.cwd()
|
|
828
|
+
rootDir: process.cwd(),
|
|
829
|
+
recoveryTokens: /* @__PURE__ */ new Map()
|
|
787
830
|
};
|
|
788
831
|
const SAFELIST_FILENAME = "csszyx-classes.html";
|
|
789
832
|
const SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([".tsx", ".jsx", ".ts", ".js"]);
|
|
@@ -828,7 +871,7 @@ function createCsszyxPlugins(options = {}) {
|
|
|
828
871
|
if (!content.includes("sz=") && !content.includes("sz:")) {
|
|
829
872
|
continue;
|
|
830
873
|
}
|
|
831
|
-
const result = (0, import_compiler.transformSourceCode)(content);
|
|
874
|
+
const result = (0, import_compiler.transformSourceCode)(content, filePath, { astBudget: astBudgetOverride });
|
|
832
875
|
if (!result.transformed) {
|
|
833
876
|
continue;
|
|
834
877
|
}
|
|
@@ -838,6 +881,9 @@ function createCsszyxPlugins(options = {}) {
|
|
|
838
881
|
for (const cls of result.rawClassNames) {
|
|
839
882
|
rawDiscoveredClasses.add(cls);
|
|
840
883
|
}
|
|
884
|
+
for (const [token, data] of result.recoveryTokens) {
|
|
885
|
+
state.recoveryTokens.set(token, data);
|
|
886
|
+
}
|
|
841
887
|
if (result.usesRuntime) {
|
|
842
888
|
const szCallRe = /_sz\(\s*\{/g;
|
|
843
889
|
let szMatch;
|
|
@@ -1059,7 +1105,7 @@ ${sourceDirective}`
|
|
|
1059
1105
|
transformed = true;
|
|
1060
1106
|
}
|
|
1061
1107
|
} else {
|
|
1062
|
-
const result = (0, import_compiler.transformSourceCode)(code);
|
|
1108
|
+
const result = (0, import_compiler.transformSourceCode)(code, id, { astBudget: astBudgetOverride });
|
|
1063
1109
|
transformedCode = result.code;
|
|
1064
1110
|
usesRuntime = result.usesRuntime;
|
|
1065
1111
|
usesMerge = result.usesMerge;
|
|
@@ -1072,6 +1118,9 @@ ${sourceDirective}`
|
|
|
1072
1118
|
${msg}`);
|
|
1073
1119
|
}
|
|
1074
1120
|
}
|
|
1121
|
+
for (const [token, data] of result.recoveryTokens) {
|
|
1122
|
+
state.recoveryTokens.set(token, data);
|
|
1123
|
+
}
|
|
1075
1124
|
}
|
|
1076
1125
|
}
|
|
1077
1126
|
if (transformedCode.includes("<html") && /layout|Root|Document|app\\.tsx?$/i.test(id)) {
|
|
@@ -1212,7 +1261,7 @@ ${sourceDirective}`
|
|
|
1212
1261
|
return;
|
|
1213
1262
|
}
|
|
1214
1263
|
try {
|
|
1215
|
-
result = (0, import_compiler.transformSourceCode)(fileContent);
|
|
1264
|
+
result = (0, import_compiler.transformSourceCode)(fileContent, ctx.file, { astBudget: astBudgetOverride });
|
|
1216
1265
|
} catch {
|
|
1217
1266
|
return;
|
|
1218
1267
|
}
|
|
@@ -1223,6 +1272,9 @@ ${sourceDirective}`
|
|
|
1223
1272
|
for (const cls of result.classes) {
|
|
1224
1273
|
state.classes.add(cls);
|
|
1225
1274
|
}
|
|
1275
|
+
for (const [token, data] of result.recoveryTokens) {
|
|
1276
|
+
state.recoveryTokens.set(token, data);
|
|
1277
|
+
}
|
|
1226
1278
|
if (state.classes.size > sizeBefore) {
|
|
1227
1279
|
writeSafelistFile(state.classes);
|
|
1228
1280
|
const safelistPath = path.join(state.rootDir, SAFELIST_FILENAME);
|
|
@@ -1239,10 +1291,24 @@ ${sourceDirective}`
|
|
|
1239
1291
|
*/
|
|
1240
1292
|
handler(html) {
|
|
1241
1293
|
finalizeMangleMap();
|
|
1242
|
-
|
|
1294
|
+
let result = transformIndexHtml(html, state.mangleMap, state.checksum, {
|
|
1243
1295
|
mode: options.production?.injectChecksum === false ? "script" : "script",
|
|
1244
1296
|
minify: process.env.NODE_ENV === "production"
|
|
1245
1297
|
});
|
|
1298
|
+
if (state.recoveryTokens.size > 0) {
|
|
1299
|
+
const isProduction = process.env.NODE_ENV === "production";
|
|
1300
|
+
const { manifest, strippedDevOnlyPaths } = buildRecoveryManifest(
|
|
1301
|
+
state.recoveryTokens,
|
|
1302
|
+
{ production: isProduction }
|
|
1303
|
+
);
|
|
1304
|
+
if (strippedDevOnlyPaths.length > 0) {
|
|
1305
|
+
console.warn(
|
|
1306
|
+
`[csszyx] Stripped ${strippedDevOnlyPaths.length} szRecover="dev-only" token(s) from the production manifest. Recovery for these elements is disabled in production by design. Sites: ${strippedDevOnlyPaths.join(", ")}`
|
|
1307
|
+
);
|
|
1308
|
+
}
|
|
1309
|
+
result = injectRecoveryManifest(result, manifest);
|
|
1310
|
+
}
|
|
1311
|
+
return result;
|
|
1246
1312
|
}
|
|
1247
1313
|
}
|
|
1248
1314
|
}
|
package/dist/index.js
CHANGED
package/dist/vite.cjs
CHANGED
|
@@ -140,6 +140,7 @@ function mangleCSSSync(css, mangleMap, options = {}) {
|
|
|
140
140
|
}
|
|
141
141
|
|
|
142
142
|
// src/html-transformer.ts
|
|
143
|
+
var import_node_crypto = require("crypto");
|
|
143
144
|
function injectChecksum(html, checksum, minify = false) {
|
|
144
145
|
const attrName = minify ? "data-sz-cs" : "data-sz-checksum";
|
|
145
146
|
const htmlTagPattern = /<html([^>]*)>/i;
|
|
@@ -199,6 +200,46 @@ function injectHydrationData(html, mangleMap, checksum, options = {}) {
|
|
|
199
200
|
function transformIndexHtml(html, mangleMap, checksum, options = {}) {
|
|
200
201
|
return injectHydrationData(html, mangleMap, checksum, options);
|
|
201
202
|
}
|
|
203
|
+
function buildRecoveryManifest(tokens, options = {}) {
|
|
204
|
+
const stripped = options.production === true;
|
|
205
|
+
const strippedDevOnlyPaths = [];
|
|
206
|
+
const sorted = {};
|
|
207
|
+
const sortedKeys = [...tokens.keys()].sort();
|
|
208
|
+
for (const key of sortedKeys) {
|
|
209
|
+
const data = tokens.get(key);
|
|
210
|
+
if (!data) {
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
if (stripped && data.mode === "dev-only") {
|
|
214
|
+
strippedDevOnlyPaths.push(data.path);
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
217
|
+
sorted[key] = stripped ? { mode: data.mode, component: data.component, path: "" } : data;
|
|
218
|
+
}
|
|
219
|
+
const serialised = JSON.stringify(sorted);
|
|
220
|
+
const fullChecksum = (0, import_node_crypto.createHash)("sha256").update(serialised).digest("hex");
|
|
221
|
+
const checksum = fullChecksum.substring(0, 16);
|
|
222
|
+
const buildId = `${Date.now().toString(36)}-${fullChecksum.substring(0, 6)}`;
|
|
223
|
+
return {
|
|
224
|
+
manifest: { buildId, checksum, tokens: sorted },
|
|
225
|
+
strippedDevOnlyPaths
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
function injectRecoveryManifest(html, manifest) {
|
|
229
|
+
if (Object.keys(manifest.tokens).length === 0) {
|
|
230
|
+
return html;
|
|
231
|
+
}
|
|
232
|
+
const json = JSON.stringify(manifest);
|
|
233
|
+
const scriptTag = `<script id="__SZ_RECOVERY_MANIFEST__" type="application/json">${json}</script>`;
|
|
234
|
+
if (html.includes("</head>")) {
|
|
235
|
+
return html.replace("</head>", `${scriptTag}
|
|
236
|
+
</head>`);
|
|
237
|
+
} else if (html.includes("</html>")) {
|
|
238
|
+
return html.replace("</html>", `${scriptTag}
|
|
239
|
+
</html>`);
|
|
240
|
+
}
|
|
241
|
+
return html + scriptTag;
|
|
242
|
+
}
|
|
202
243
|
|
|
203
244
|
// src/theme-scanner.ts
|
|
204
245
|
var EMPTY_THEME = { colors: [], spacings: [], fonts: [], radii: [], shadows: [] };
|
|
@@ -662,12 +703,14 @@ function mangleCodeClassesSync(code, mangleMap) {
|
|
|
662
703
|
}
|
|
663
704
|
function createCsszyxPlugins(options = {}) {
|
|
664
705
|
const manglingEnabled = options.production?.mangle !== false;
|
|
706
|
+
const astBudgetOverride = options.build?.astBudgetLimit;
|
|
665
707
|
const state = {
|
|
666
708
|
classes: /* @__PURE__ */ new Set(),
|
|
667
709
|
mangleMap: {},
|
|
668
710
|
checksum: "",
|
|
669
711
|
finalized: false,
|
|
670
|
-
rootDir: process.cwd()
|
|
712
|
+
rootDir: process.cwd(),
|
|
713
|
+
recoveryTokens: /* @__PURE__ */ new Map()
|
|
671
714
|
};
|
|
672
715
|
const SAFELIST_FILENAME = "csszyx-classes.html";
|
|
673
716
|
const SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([".tsx", ".jsx", ".ts", ".js"]);
|
|
@@ -712,7 +755,7 @@ function createCsszyxPlugins(options = {}) {
|
|
|
712
755
|
if (!content.includes("sz=") && !content.includes("sz:")) {
|
|
713
756
|
continue;
|
|
714
757
|
}
|
|
715
|
-
const result = (0, import_compiler.transformSourceCode)(content);
|
|
758
|
+
const result = (0, import_compiler.transformSourceCode)(content, filePath, { astBudget: astBudgetOverride });
|
|
716
759
|
if (!result.transformed) {
|
|
717
760
|
continue;
|
|
718
761
|
}
|
|
@@ -722,6 +765,9 @@ function createCsszyxPlugins(options = {}) {
|
|
|
722
765
|
for (const cls of result.rawClassNames) {
|
|
723
766
|
rawDiscoveredClasses.add(cls);
|
|
724
767
|
}
|
|
768
|
+
for (const [token, data] of result.recoveryTokens) {
|
|
769
|
+
state.recoveryTokens.set(token, data);
|
|
770
|
+
}
|
|
725
771
|
if (result.usesRuntime) {
|
|
726
772
|
const szCallRe = /_sz\(\s*\{/g;
|
|
727
773
|
let szMatch;
|
|
@@ -943,7 +989,7 @@ ${sourceDirective}`
|
|
|
943
989
|
transformed = true;
|
|
944
990
|
}
|
|
945
991
|
} else {
|
|
946
|
-
const result = (0, import_compiler.transformSourceCode)(code);
|
|
992
|
+
const result = (0, import_compiler.transformSourceCode)(code, id, { astBudget: astBudgetOverride });
|
|
947
993
|
transformedCode = result.code;
|
|
948
994
|
usesRuntime = result.usesRuntime;
|
|
949
995
|
usesMerge = result.usesMerge;
|
|
@@ -956,6 +1002,9 @@ ${sourceDirective}`
|
|
|
956
1002
|
${msg}`);
|
|
957
1003
|
}
|
|
958
1004
|
}
|
|
1005
|
+
for (const [token, data] of result.recoveryTokens) {
|
|
1006
|
+
state.recoveryTokens.set(token, data);
|
|
1007
|
+
}
|
|
959
1008
|
}
|
|
960
1009
|
}
|
|
961
1010
|
if (transformedCode.includes("<html") && /layout|Root|Document|app\\.tsx?$/i.test(id)) {
|
|
@@ -1096,7 +1145,7 @@ ${sourceDirective}`
|
|
|
1096
1145
|
return;
|
|
1097
1146
|
}
|
|
1098
1147
|
try {
|
|
1099
|
-
result = (0, import_compiler.transformSourceCode)(fileContent);
|
|
1148
|
+
result = (0, import_compiler.transformSourceCode)(fileContent, ctx.file, { astBudget: astBudgetOverride });
|
|
1100
1149
|
} catch {
|
|
1101
1150
|
return;
|
|
1102
1151
|
}
|
|
@@ -1107,6 +1156,9 @@ ${sourceDirective}`
|
|
|
1107
1156
|
for (const cls of result.classes) {
|
|
1108
1157
|
state.classes.add(cls);
|
|
1109
1158
|
}
|
|
1159
|
+
for (const [token, data] of result.recoveryTokens) {
|
|
1160
|
+
state.recoveryTokens.set(token, data);
|
|
1161
|
+
}
|
|
1110
1162
|
if (state.classes.size > sizeBefore) {
|
|
1111
1163
|
writeSafelistFile(state.classes);
|
|
1112
1164
|
const safelistPath = path.join(state.rootDir, SAFELIST_FILENAME);
|
|
@@ -1123,10 +1175,24 @@ ${sourceDirective}`
|
|
|
1123
1175
|
*/
|
|
1124
1176
|
handler(html) {
|
|
1125
1177
|
finalizeMangleMap();
|
|
1126
|
-
|
|
1178
|
+
let result = transformIndexHtml(html, state.mangleMap, state.checksum, {
|
|
1127
1179
|
mode: options.production?.injectChecksum === false ? "script" : "script",
|
|
1128
1180
|
minify: process.env.NODE_ENV === "production"
|
|
1129
1181
|
});
|
|
1182
|
+
if (state.recoveryTokens.size > 0) {
|
|
1183
|
+
const isProduction = process.env.NODE_ENV === "production";
|
|
1184
|
+
const { manifest, strippedDevOnlyPaths } = buildRecoveryManifest(
|
|
1185
|
+
state.recoveryTokens,
|
|
1186
|
+
{ production: isProduction }
|
|
1187
|
+
);
|
|
1188
|
+
if (strippedDevOnlyPaths.length > 0) {
|
|
1189
|
+
console.warn(
|
|
1190
|
+
`[csszyx] Stripped ${strippedDevOnlyPaths.length} szRecover="dev-only" token(s) from the production manifest. Recovery for these elements is disabled in production by design. Sites: ${strippedDevOnlyPaths.join(", ")}`
|
|
1191
|
+
);
|
|
1192
|
+
}
|
|
1193
|
+
result = injectRecoveryManifest(result, manifest);
|
|
1194
|
+
}
|
|
1195
|
+
return result;
|
|
1130
1196
|
}
|
|
1131
1197
|
}
|
|
1132
1198
|
}
|
package/dist/vite.js
CHANGED
package/dist/webpack.cjs
CHANGED
|
@@ -140,6 +140,7 @@ function mangleCSSSync(css, mangleMap, options = {}) {
|
|
|
140
140
|
}
|
|
141
141
|
|
|
142
142
|
// src/html-transformer.ts
|
|
143
|
+
var import_node_crypto = require("crypto");
|
|
143
144
|
function injectChecksum(html, checksum, minify = false) {
|
|
144
145
|
const attrName = minify ? "data-sz-cs" : "data-sz-checksum";
|
|
145
146
|
const htmlTagPattern = /<html([^>]*)>/i;
|
|
@@ -199,6 +200,46 @@ function injectHydrationData(html, mangleMap, checksum, options = {}) {
|
|
|
199
200
|
function transformIndexHtml(html, mangleMap, checksum, options = {}) {
|
|
200
201
|
return injectHydrationData(html, mangleMap, checksum, options);
|
|
201
202
|
}
|
|
203
|
+
function buildRecoveryManifest(tokens, options = {}) {
|
|
204
|
+
const stripped = options.production === true;
|
|
205
|
+
const strippedDevOnlyPaths = [];
|
|
206
|
+
const sorted = {};
|
|
207
|
+
const sortedKeys = [...tokens.keys()].sort();
|
|
208
|
+
for (const key of sortedKeys) {
|
|
209
|
+
const data = tokens.get(key);
|
|
210
|
+
if (!data) {
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
if (stripped && data.mode === "dev-only") {
|
|
214
|
+
strippedDevOnlyPaths.push(data.path);
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
217
|
+
sorted[key] = stripped ? { mode: data.mode, component: data.component, path: "" } : data;
|
|
218
|
+
}
|
|
219
|
+
const serialised = JSON.stringify(sorted);
|
|
220
|
+
const fullChecksum = (0, import_node_crypto.createHash)("sha256").update(serialised).digest("hex");
|
|
221
|
+
const checksum = fullChecksum.substring(0, 16);
|
|
222
|
+
const buildId = `${Date.now().toString(36)}-${fullChecksum.substring(0, 6)}`;
|
|
223
|
+
return {
|
|
224
|
+
manifest: { buildId, checksum, tokens: sorted },
|
|
225
|
+
strippedDevOnlyPaths
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
function injectRecoveryManifest(html, manifest) {
|
|
229
|
+
if (Object.keys(manifest.tokens).length === 0) {
|
|
230
|
+
return html;
|
|
231
|
+
}
|
|
232
|
+
const json = JSON.stringify(manifest);
|
|
233
|
+
const scriptTag = `<script id="__SZ_RECOVERY_MANIFEST__" type="application/json">${json}</script>`;
|
|
234
|
+
if (html.includes("</head>")) {
|
|
235
|
+
return html.replace("</head>", `${scriptTag}
|
|
236
|
+
</head>`);
|
|
237
|
+
} else if (html.includes("</html>")) {
|
|
238
|
+
return html.replace("</html>", `${scriptTag}
|
|
239
|
+
</html>`);
|
|
240
|
+
}
|
|
241
|
+
return html + scriptTag;
|
|
242
|
+
}
|
|
202
243
|
|
|
203
244
|
// src/theme-scanner.ts
|
|
204
245
|
var EMPTY_THEME = { colors: [], spacings: [], fonts: [], radii: [], shadows: [] };
|
|
@@ -662,12 +703,14 @@ function mangleCodeClassesSync(code, mangleMap) {
|
|
|
662
703
|
}
|
|
663
704
|
function createCsszyxPlugins(options = {}) {
|
|
664
705
|
const manglingEnabled = options.production?.mangle !== false;
|
|
706
|
+
const astBudgetOverride = options.build?.astBudgetLimit;
|
|
665
707
|
const state = {
|
|
666
708
|
classes: /* @__PURE__ */ new Set(),
|
|
667
709
|
mangleMap: {},
|
|
668
710
|
checksum: "",
|
|
669
711
|
finalized: false,
|
|
670
|
-
rootDir: process.cwd()
|
|
712
|
+
rootDir: process.cwd(),
|
|
713
|
+
recoveryTokens: /* @__PURE__ */ new Map()
|
|
671
714
|
};
|
|
672
715
|
const SAFELIST_FILENAME = "csszyx-classes.html";
|
|
673
716
|
const SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([".tsx", ".jsx", ".ts", ".js"]);
|
|
@@ -712,7 +755,7 @@ function createCsszyxPlugins(options = {}) {
|
|
|
712
755
|
if (!content.includes("sz=") && !content.includes("sz:")) {
|
|
713
756
|
continue;
|
|
714
757
|
}
|
|
715
|
-
const result = (0, import_compiler.transformSourceCode)(content);
|
|
758
|
+
const result = (0, import_compiler.transformSourceCode)(content, filePath, { astBudget: astBudgetOverride });
|
|
716
759
|
if (!result.transformed) {
|
|
717
760
|
continue;
|
|
718
761
|
}
|
|
@@ -722,6 +765,9 @@ function createCsszyxPlugins(options = {}) {
|
|
|
722
765
|
for (const cls of result.rawClassNames) {
|
|
723
766
|
rawDiscoveredClasses.add(cls);
|
|
724
767
|
}
|
|
768
|
+
for (const [token, data] of result.recoveryTokens) {
|
|
769
|
+
state.recoveryTokens.set(token, data);
|
|
770
|
+
}
|
|
725
771
|
if (result.usesRuntime) {
|
|
726
772
|
const szCallRe = /_sz\(\s*\{/g;
|
|
727
773
|
let szMatch;
|
|
@@ -943,7 +989,7 @@ ${sourceDirective}`
|
|
|
943
989
|
transformed = true;
|
|
944
990
|
}
|
|
945
991
|
} else {
|
|
946
|
-
const result = (0, import_compiler.transformSourceCode)(code);
|
|
992
|
+
const result = (0, import_compiler.transformSourceCode)(code, id, { astBudget: astBudgetOverride });
|
|
947
993
|
transformedCode = result.code;
|
|
948
994
|
usesRuntime = result.usesRuntime;
|
|
949
995
|
usesMerge = result.usesMerge;
|
|
@@ -956,6 +1002,9 @@ ${sourceDirective}`
|
|
|
956
1002
|
${msg}`);
|
|
957
1003
|
}
|
|
958
1004
|
}
|
|
1005
|
+
for (const [token, data] of result.recoveryTokens) {
|
|
1006
|
+
state.recoveryTokens.set(token, data);
|
|
1007
|
+
}
|
|
959
1008
|
}
|
|
960
1009
|
}
|
|
961
1010
|
if (transformedCode.includes("<html") && /layout|Root|Document|app\\.tsx?$/i.test(id)) {
|
|
@@ -1096,7 +1145,7 @@ ${sourceDirective}`
|
|
|
1096
1145
|
return;
|
|
1097
1146
|
}
|
|
1098
1147
|
try {
|
|
1099
|
-
result = (0, import_compiler.transformSourceCode)(fileContent);
|
|
1148
|
+
result = (0, import_compiler.transformSourceCode)(fileContent, ctx.file, { astBudget: astBudgetOverride });
|
|
1100
1149
|
} catch {
|
|
1101
1150
|
return;
|
|
1102
1151
|
}
|
|
@@ -1107,6 +1156,9 @@ ${sourceDirective}`
|
|
|
1107
1156
|
for (const cls of result.classes) {
|
|
1108
1157
|
state.classes.add(cls);
|
|
1109
1158
|
}
|
|
1159
|
+
for (const [token, data] of result.recoveryTokens) {
|
|
1160
|
+
state.recoveryTokens.set(token, data);
|
|
1161
|
+
}
|
|
1110
1162
|
if (state.classes.size > sizeBefore) {
|
|
1111
1163
|
writeSafelistFile(state.classes);
|
|
1112
1164
|
const safelistPath = path.join(state.rootDir, SAFELIST_FILENAME);
|
|
@@ -1123,10 +1175,24 @@ ${sourceDirective}`
|
|
|
1123
1175
|
*/
|
|
1124
1176
|
handler(html) {
|
|
1125
1177
|
finalizeMangleMap();
|
|
1126
|
-
|
|
1178
|
+
let result = transformIndexHtml(html, state.mangleMap, state.checksum, {
|
|
1127
1179
|
mode: options.production?.injectChecksum === false ? "script" : "script",
|
|
1128
1180
|
minify: process.env.NODE_ENV === "production"
|
|
1129
1181
|
});
|
|
1182
|
+
if (state.recoveryTokens.size > 0) {
|
|
1183
|
+
const isProduction = process.env.NODE_ENV === "production";
|
|
1184
|
+
const { manifest, strippedDevOnlyPaths } = buildRecoveryManifest(
|
|
1185
|
+
state.recoveryTokens,
|
|
1186
|
+
{ production: isProduction }
|
|
1187
|
+
);
|
|
1188
|
+
if (strippedDevOnlyPaths.length > 0) {
|
|
1189
|
+
console.warn(
|
|
1190
|
+
`[csszyx] Stripped ${strippedDevOnlyPaths.length} szRecover="dev-only" token(s) from the production manifest. Recovery for these elements is disabled in production by design. Sites: ${strippedDevOnlyPaths.join(", ")}`
|
|
1191
|
+
);
|
|
1192
|
+
}
|
|
1193
|
+
result = injectRecoveryManifest(result, manifest);
|
|
1194
|
+
}
|
|
1195
|
+
return result;
|
|
1130
1196
|
}
|
|
1131
1197
|
}
|
|
1132
1198
|
}
|
package/dist/webpack.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@csszyx/unplugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.2",
|
|
4
4
|
"description": "Vite and Webpack integration for csszyx",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"csszyx",
|
|
@@ -55,11 +55,11 @@
|
|
|
55
55
|
"postcss": "^8.4.35",
|
|
56
56
|
"postcss-selector-parser": "^6.0.15",
|
|
57
57
|
"unplugin": "^1.10.1",
|
|
58
|
-
"@csszyx/
|
|
59
|
-
"@csszyx/
|
|
60
|
-
"@csszyx/svelte-adapter": "0.
|
|
61
|
-
"@csszyx/types": "0.
|
|
62
|
-
"@csszyx/vue-adapter": "0.
|
|
58
|
+
"@csszyx/core": "0.6.2",
|
|
59
|
+
"@csszyx/compiler": "0.6.2",
|
|
60
|
+
"@csszyx/svelte-adapter": "0.6.2",
|
|
61
|
+
"@csszyx/types": "0.6.2",
|
|
62
|
+
"@csszyx/vue-adapter": "0.6.2"
|
|
63
63
|
},
|
|
64
64
|
"devDependencies": {
|
|
65
65
|
"@types/node": "^20.11.0",
|