@csszyx/unplugin 0.5.0 → 0.6.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/dist/{chunk-CW4XYEQR.js → chunk-HOQTC45W.js} +70 -5
- package/dist/index.cjs +70 -5
- package/dist/index.js +1 -1
- package/dist/vite.cjs +70 -5
- package/dist/vite.js +1 -1
- package/dist/webpack.cjs +70 -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] = 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";
|
|
@@ -542,7 +583,8 @@ function createCsszyxPlugins(options = {}) {
|
|
|
542
583
|
mangleMap: {},
|
|
543
584
|
checksum: "",
|
|
544
585
|
finalized: false,
|
|
545
|
-
rootDir: process.cwd()
|
|
586
|
+
rootDir: process.cwd(),
|
|
587
|
+
recoveryTokens: /* @__PURE__ */ new Map()
|
|
546
588
|
};
|
|
547
589
|
const SAFELIST_FILENAME = "csszyx-classes.html";
|
|
548
590
|
const SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([".tsx", ".jsx", ".ts", ".js"]);
|
|
@@ -587,7 +629,7 @@ function createCsszyxPlugins(options = {}) {
|
|
|
587
629
|
if (!content.includes("sz=") && !content.includes("sz:")) {
|
|
588
630
|
continue;
|
|
589
631
|
}
|
|
590
|
-
const result = transformSourceCode(content);
|
|
632
|
+
const result = transformSourceCode(content, filePath);
|
|
591
633
|
if (!result.transformed) {
|
|
592
634
|
continue;
|
|
593
635
|
}
|
|
@@ -597,6 +639,9 @@ function createCsszyxPlugins(options = {}) {
|
|
|
597
639
|
for (const cls of result.rawClassNames) {
|
|
598
640
|
rawDiscoveredClasses.add(cls);
|
|
599
641
|
}
|
|
642
|
+
for (const [token, data] of result.recoveryTokens) {
|
|
643
|
+
state.recoveryTokens.set(token, data);
|
|
644
|
+
}
|
|
600
645
|
if (result.usesRuntime) {
|
|
601
646
|
const szCallRe = /_sz\(\s*\{/g;
|
|
602
647
|
let szMatch;
|
|
@@ -818,7 +863,7 @@ ${sourceDirective}`
|
|
|
818
863
|
transformed = true;
|
|
819
864
|
}
|
|
820
865
|
} else {
|
|
821
|
-
const result = transformSourceCode(code);
|
|
866
|
+
const result = transformSourceCode(code, id);
|
|
822
867
|
transformedCode = result.code;
|
|
823
868
|
usesRuntime = result.usesRuntime;
|
|
824
869
|
usesMerge = result.usesMerge;
|
|
@@ -831,6 +876,9 @@ ${sourceDirective}`
|
|
|
831
876
|
${msg}`);
|
|
832
877
|
}
|
|
833
878
|
}
|
|
879
|
+
for (const [token, data] of result.recoveryTokens) {
|
|
880
|
+
state.recoveryTokens.set(token, data);
|
|
881
|
+
}
|
|
834
882
|
}
|
|
835
883
|
}
|
|
836
884
|
if (transformedCode.includes("<html") && /layout|Root|Document|app\\.tsx?$/i.test(id)) {
|
|
@@ -971,7 +1019,7 @@ ${sourceDirective}`
|
|
|
971
1019
|
return;
|
|
972
1020
|
}
|
|
973
1021
|
try {
|
|
974
|
-
result = transformSourceCode(fileContent);
|
|
1022
|
+
result = transformSourceCode(fileContent, ctx.file);
|
|
975
1023
|
} catch {
|
|
976
1024
|
return;
|
|
977
1025
|
}
|
|
@@ -982,6 +1030,9 @@ ${sourceDirective}`
|
|
|
982
1030
|
for (const cls of result.classes) {
|
|
983
1031
|
state.classes.add(cls);
|
|
984
1032
|
}
|
|
1033
|
+
for (const [token, data] of result.recoveryTokens) {
|
|
1034
|
+
state.recoveryTokens.set(token, data);
|
|
1035
|
+
}
|
|
985
1036
|
if (state.classes.size > sizeBefore) {
|
|
986
1037
|
writeSafelistFile(state.classes);
|
|
987
1038
|
const safelistPath = path.join(state.rootDir, SAFELIST_FILENAME);
|
|
@@ -998,10 +1049,24 @@ ${sourceDirective}`
|
|
|
998
1049
|
*/
|
|
999
1050
|
handler(html) {
|
|
1000
1051
|
finalizeMangleMap();
|
|
1001
|
-
|
|
1052
|
+
let result = transformIndexHtml(html, state.mangleMap, state.checksum, {
|
|
1002
1053
|
mode: options.production?.injectChecksum === false ? "script" : "script",
|
|
1003
1054
|
minify: process.env.NODE_ENV === "production"
|
|
1004
1055
|
});
|
|
1056
|
+
if (state.recoveryTokens.size > 0) {
|
|
1057
|
+
const isProduction = process.env.NODE_ENV === "production";
|
|
1058
|
+
const { manifest, strippedDevOnlyPaths } = buildRecoveryManifest(
|
|
1059
|
+
state.recoveryTokens,
|
|
1060
|
+
{ production: isProduction }
|
|
1061
|
+
);
|
|
1062
|
+
if (strippedDevOnlyPaths.length > 0) {
|
|
1063
|
+
console.warn(
|
|
1064
|
+
`[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(", ")}`
|
|
1065
|
+
);
|
|
1066
|
+
}
|
|
1067
|
+
result = injectRecoveryManifest(result, manifest);
|
|
1068
|
+
}
|
|
1069
|
+
return result;
|
|
1005
1070
|
}
|
|
1006
1071
|
}
|
|
1007
1072
|
}
|
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] = 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");
|
|
@@ -783,7 +824,8 @@ function createCsszyxPlugins(options = {}) {
|
|
|
783
824
|
mangleMap: {},
|
|
784
825
|
checksum: "",
|
|
785
826
|
finalized: false,
|
|
786
|
-
rootDir: process.cwd()
|
|
827
|
+
rootDir: process.cwd(),
|
|
828
|
+
recoveryTokens: /* @__PURE__ */ new Map()
|
|
787
829
|
};
|
|
788
830
|
const SAFELIST_FILENAME = "csszyx-classes.html";
|
|
789
831
|
const SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([".tsx", ".jsx", ".ts", ".js"]);
|
|
@@ -828,7 +870,7 @@ function createCsszyxPlugins(options = {}) {
|
|
|
828
870
|
if (!content.includes("sz=") && !content.includes("sz:")) {
|
|
829
871
|
continue;
|
|
830
872
|
}
|
|
831
|
-
const result = (0, import_compiler.transformSourceCode)(content);
|
|
873
|
+
const result = (0, import_compiler.transformSourceCode)(content, filePath);
|
|
832
874
|
if (!result.transformed) {
|
|
833
875
|
continue;
|
|
834
876
|
}
|
|
@@ -838,6 +880,9 @@ function createCsszyxPlugins(options = {}) {
|
|
|
838
880
|
for (const cls of result.rawClassNames) {
|
|
839
881
|
rawDiscoveredClasses.add(cls);
|
|
840
882
|
}
|
|
883
|
+
for (const [token, data] of result.recoveryTokens) {
|
|
884
|
+
state.recoveryTokens.set(token, data);
|
|
885
|
+
}
|
|
841
886
|
if (result.usesRuntime) {
|
|
842
887
|
const szCallRe = /_sz\(\s*\{/g;
|
|
843
888
|
let szMatch;
|
|
@@ -1059,7 +1104,7 @@ ${sourceDirective}`
|
|
|
1059
1104
|
transformed = true;
|
|
1060
1105
|
}
|
|
1061
1106
|
} else {
|
|
1062
|
-
const result = (0, import_compiler.transformSourceCode)(code);
|
|
1107
|
+
const result = (0, import_compiler.transformSourceCode)(code, id);
|
|
1063
1108
|
transformedCode = result.code;
|
|
1064
1109
|
usesRuntime = result.usesRuntime;
|
|
1065
1110
|
usesMerge = result.usesMerge;
|
|
@@ -1072,6 +1117,9 @@ ${sourceDirective}`
|
|
|
1072
1117
|
${msg}`);
|
|
1073
1118
|
}
|
|
1074
1119
|
}
|
|
1120
|
+
for (const [token, data] of result.recoveryTokens) {
|
|
1121
|
+
state.recoveryTokens.set(token, data);
|
|
1122
|
+
}
|
|
1075
1123
|
}
|
|
1076
1124
|
}
|
|
1077
1125
|
if (transformedCode.includes("<html") && /layout|Root|Document|app\\.tsx?$/i.test(id)) {
|
|
@@ -1212,7 +1260,7 @@ ${sourceDirective}`
|
|
|
1212
1260
|
return;
|
|
1213
1261
|
}
|
|
1214
1262
|
try {
|
|
1215
|
-
result = (0, import_compiler.transformSourceCode)(fileContent);
|
|
1263
|
+
result = (0, import_compiler.transformSourceCode)(fileContent, ctx.file);
|
|
1216
1264
|
} catch {
|
|
1217
1265
|
return;
|
|
1218
1266
|
}
|
|
@@ -1223,6 +1271,9 @@ ${sourceDirective}`
|
|
|
1223
1271
|
for (const cls of result.classes) {
|
|
1224
1272
|
state.classes.add(cls);
|
|
1225
1273
|
}
|
|
1274
|
+
for (const [token, data] of result.recoveryTokens) {
|
|
1275
|
+
state.recoveryTokens.set(token, data);
|
|
1276
|
+
}
|
|
1226
1277
|
if (state.classes.size > sizeBefore) {
|
|
1227
1278
|
writeSafelistFile(state.classes);
|
|
1228
1279
|
const safelistPath = path.join(state.rootDir, SAFELIST_FILENAME);
|
|
@@ -1239,10 +1290,24 @@ ${sourceDirective}`
|
|
|
1239
1290
|
*/
|
|
1240
1291
|
handler(html) {
|
|
1241
1292
|
finalizeMangleMap();
|
|
1242
|
-
|
|
1293
|
+
let result = transformIndexHtml(html, state.mangleMap, state.checksum, {
|
|
1243
1294
|
mode: options.production?.injectChecksum === false ? "script" : "script",
|
|
1244
1295
|
minify: process.env.NODE_ENV === "production"
|
|
1245
1296
|
});
|
|
1297
|
+
if (state.recoveryTokens.size > 0) {
|
|
1298
|
+
const isProduction = process.env.NODE_ENV === "production";
|
|
1299
|
+
const { manifest, strippedDevOnlyPaths } = buildRecoveryManifest(
|
|
1300
|
+
state.recoveryTokens,
|
|
1301
|
+
{ production: isProduction }
|
|
1302
|
+
);
|
|
1303
|
+
if (strippedDevOnlyPaths.length > 0) {
|
|
1304
|
+
console.warn(
|
|
1305
|
+
`[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(", ")}`
|
|
1306
|
+
);
|
|
1307
|
+
}
|
|
1308
|
+
result = injectRecoveryManifest(result, manifest);
|
|
1309
|
+
}
|
|
1310
|
+
return result;
|
|
1246
1311
|
}
|
|
1247
1312
|
}
|
|
1248
1313
|
}
|
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] = 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: [] };
|
|
@@ -667,7 +708,8 @@ function createCsszyxPlugins(options = {}) {
|
|
|
667
708
|
mangleMap: {},
|
|
668
709
|
checksum: "",
|
|
669
710
|
finalized: false,
|
|
670
|
-
rootDir: process.cwd()
|
|
711
|
+
rootDir: process.cwd(),
|
|
712
|
+
recoveryTokens: /* @__PURE__ */ new Map()
|
|
671
713
|
};
|
|
672
714
|
const SAFELIST_FILENAME = "csszyx-classes.html";
|
|
673
715
|
const SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([".tsx", ".jsx", ".ts", ".js"]);
|
|
@@ -712,7 +754,7 @@ function createCsszyxPlugins(options = {}) {
|
|
|
712
754
|
if (!content.includes("sz=") && !content.includes("sz:")) {
|
|
713
755
|
continue;
|
|
714
756
|
}
|
|
715
|
-
const result = (0, import_compiler.transformSourceCode)(content);
|
|
757
|
+
const result = (0, import_compiler.transformSourceCode)(content, filePath);
|
|
716
758
|
if (!result.transformed) {
|
|
717
759
|
continue;
|
|
718
760
|
}
|
|
@@ -722,6 +764,9 @@ function createCsszyxPlugins(options = {}) {
|
|
|
722
764
|
for (const cls of result.rawClassNames) {
|
|
723
765
|
rawDiscoveredClasses.add(cls);
|
|
724
766
|
}
|
|
767
|
+
for (const [token, data] of result.recoveryTokens) {
|
|
768
|
+
state.recoveryTokens.set(token, data);
|
|
769
|
+
}
|
|
725
770
|
if (result.usesRuntime) {
|
|
726
771
|
const szCallRe = /_sz\(\s*\{/g;
|
|
727
772
|
let szMatch;
|
|
@@ -943,7 +988,7 @@ ${sourceDirective}`
|
|
|
943
988
|
transformed = true;
|
|
944
989
|
}
|
|
945
990
|
} else {
|
|
946
|
-
const result = (0, import_compiler.transformSourceCode)(code);
|
|
991
|
+
const result = (0, import_compiler.transformSourceCode)(code, id);
|
|
947
992
|
transformedCode = result.code;
|
|
948
993
|
usesRuntime = result.usesRuntime;
|
|
949
994
|
usesMerge = result.usesMerge;
|
|
@@ -956,6 +1001,9 @@ ${sourceDirective}`
|
|
|
956
1001
|
${msg}`);
|
|
957
1002
|
}
|
|
958
1003
|
}
|
|
1004
|
+
for (const [token, data] of result.recoveryTokens) {
|
|
1005
|
+
state.recoveryTokens.set(token, data);
|
|
1006
|
+
}
|
|
959
1007
|
}
|
|
960
1008
|
}
|
|
961
1009
|
if (transformedCode.includes("<html") && /layout|Root|Document|app\\.tsx?$/i.test(id)) {
|
|
@@ -1096,7 +1144,7 @@ ${sourceDirective}`
|
|
|
1096
1144
|
return;
|
|
1097
1145
|
}
|
|
1098
1146
|
try {
|
|
1099
|
-
result = (0, import_compiler.transformSourceCode)(fileContent);
|
|
1147
|
+
result = (0, import_compiler.transformSourceCode)(fileContent, ctx.file);
|
|
1100
1148
|
} catch {
|
|
1101
1149
|
return;
|
|
1102
1150
|
}
|
|
@@ -1107,6 +1155,9 @@ ${sourceDirective}`
|
|
|
1107
1155
|
for (const cls of result.classes) {
|
|
1108
1156
|
state.classes.add(cls);
|
|
1109
1157
|
}
|
|
1158
|
+
for (const [token, data] of result.recoveryTokens) {
|
|
1159
|
+
state.recoveryTokens.set(token, data);
|
|
1160
|
+
}
|
|
1110
1161
|
if (state.classes.size > sizeBefore) {
|
|
1111
1162
|
writeSafelistFile(state.classes);
|
|
1112
1163
|
const safelistPath = path.join(state.rootDir, SAFELIST_FILENAME);
|
|
@@ -1123,10 +1174,24 @@ ${sourceDirective}`
|
|
|
1123
1174
|
*/
|
|
1124
1175
|
handler(html) {
|
|
1125
1176
|
finalizeMangleMap();
|
|
1126
|
-
|
|
1177
|
+
let result = transformIndexHtml(html, state.mangleMap, state.checksum, {
|
|
1127
1178
|
mode: options.production?.injectChecksum === false ? "script" : "script",
|
|
1128
1179
|
minify: process.env.NODE_ENV === "production"
|
|
1129
1180
|
});
|
|
1181
|
+
if (state.recoveryTokens.size > 0) {
|
|
1182
|
+
const isProduction = process.env.NODE_ENV === "production";
|
|
1183
|
+
const { manifest, strippedDevOnlyPaths } = buildRecoveryManifest(
|
|
1184
|
+
state.recoveryTokens,
|
|
1185
|
+
{ production: isProduction }
|
|
1186
|
+
);
|
|
1187
|
+
if (strippedDevOnlyPaths.length > 0) {
|
|
1188
|
+
console.warn(
|
|
1189
|
+
`[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(", ")}`
|
|
1190
|
+
);
|
|
1191
|
+
}
|
|
1192
|
+
result = injectRecoveryManifest(result, manifest);
|
|
1193
|
+
}
|
|
1194
|
+
return result;
|
|
1130
1195
|
}
|
|
1131
1196
|
}
|
|
1132
1197
|
}
|
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] = 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: [] };
|
|
@@ -667,7 +708,8 @@ function createCsszyxPlugins(options = {}) {
|
|
|
667
708
|
mangleMap: {},
|
|
668
709
|
checksum: "",
|
|
669
710
|
finalized: false,
|
|
670
|
-
rootDir: process.cwd()
|
|
711
|
+
rootDir: process.cwd(),
|
|
712
|
+
recoveryTokens: /* @__PURE__ */ new Map()
|
|
671
713
|
};
|
|
672
714
|
const SAFELIST_FILENAME = "csszyx-classes.html";
|
|
673
715
|
const SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([".tsx", ".jsx", ".ts", ".js"]);
|
|
@@ -712,7 +754,7 @@ function createCsszyxPlugins(options = {}) {
|
|
|
712
754
|
if (!content.includes("sz=") && !content.includes("sz:")) {
|
|
713
755
|
continue;
|
|
714
756
|
}
|
|
715
|
-
const result = (0, import_compiler.transformSourceCode)(content);
|
|
757
|
+
const result = (0, import_compiler.transformSourceCode)(content, filePath);
|
|
716
758
|
if (!result.transformed) {
|
|
717
759
|
continue;
|
|
718
760
|
}
|
|
@@ -722,6 +764,9 @@ function createCsszyxPlugins(options = {}) {
|
|
|
722
764
|
for (const cls of result.rawClassNames) {
|
|
723
765
|
rawDiscoveredClasses.add(cls);
|
|
724
766
|
}
|
|
767
|
+
for (const [token, data] of result.recoveryTokens) {
|
|
768
|
+
state.recoveryTokens.set(token, data);
|
|
769
|
+
}
|
|
725
770
|
if (result.usesRuntime) {
|
|
726
771
|
const szCallRe = /_sz\(\s*\{/g;
|
|
727
772
|
let szMatch;
|
|
@@ -943,7 +988,7 @@ ${sourceDirective}`
|
|
|
943
988
|
transformed = true;
|
|
944
989
|
}
|
|
945
990
|
} else {
|
|
946
|
-
const result = (0, import_compiler.transformSourceCode)(code);
|
|
991
|
+
const result = (0, import_compiler.transformSourceCode)(code, id);
|
|
947
992
|
transformedCode = result.code;
|
|
948
993
|
usesRuntime = result.usesRuntime;
|
|
949
994
|
usesMerge = result.usesMerge;
|
|
@@ -956,6 +1001,9 @@ ${sourceDirective}`
|
|
|
956
1001
|
${msg}`);
|
|
957
1002
|
}
|
|
958
1003
|
}
|
|
1004
|
+
for (const [token, data] of result.recoveryTokens) {
|
|
1005
|
+
state.recoveryTokens.set(token, data);
|
|
1006
|
+
}
|
|
959
1007
|
}
|
|
960
1008
|
}
|
|
961
1009
|
if (transformedCode.includes("<html") && /layout|Root|Document|app\\.tsx?$/i.test(id)) {
|
|
@@ -1096,7 +1144,7 @@ ${sourceDirective}`
|
|
|
1096
1144
|
return;
|
|
1097
1145
|
}
|
|
1098
1146
|
try {
|
|
1099
|
-
result = (0, import_compiler.transformSourceCode)(fileContent);
|
|
1147
|
+
result = (0, import_compiler.transformSourceCode)(fileContent, ctx.file);
|
|
1100
1148
|
} catch {
|
|
1101
1149
|
return;
|
|
1102
1150
|
}
|
|
@@ -1107,6 +1155,9 @@ ${sourceDirective}`
|
|
|
1107
1155
|
for (const cls of result.classes) {
|
|
1108
1156
|
state.classes.add(cls);
|
|
1109
1157
|
}
|
|
1158
|
+
for (const [token, data] of result.recoveryTokens) {
|
|
1159
|
+
state.recoveryTokens.set(token, data);
|
|
1160
|
+
}
|
|
1110
1161
|
if (state.classes.size > sizeBefore) {
|
|
1111
1162
|
writeSafelistFile(state.classes);
|
|
1112
1163
|
const safelistPath = path.join(state.rootDir, SAFELIST_FILENAME);
|
|
@@ -1123,10 +1174,24 @@ ${sourceDirective}`
|
|
|
1123
1174
|
*/
|
|
1124
1175
|
handler(html) {
|
|
1125
1176
|
finalizeMangleMap();
|
|
1126
|
-
|
|
1177
|
+
let result = transformIndexHtml(html, state.mangleMap, state.checksum, {
|
|
1127
1178
|
mode: options.production?.injectChecksum === false ? "script" : "script",
|
|
1128
1179
|
minify: process.env.NODE_ENV === "production"
|
|
1129
1180
|
});
|
|
1181
|
+
if (state.recoveryTokens.size > 0) {
|
|
1182
|
+
const isProduction = process.env.NODE_ENV === "production";
|
|
1183
|
+
const { manifest, strippedDevOnlyPaths } = buildRecoveryManifest(
|
|
1184
|
+
state.recoveryTokens,
|
|
1185
|
+
{ production: isProduction }
|
|
1186
|
+
);
|
|
1187
|
+
if (strippedDevOnlyPaths.length > 0) {
|
|
1188
|
+
console.warn(
|
|
1189
|
+
`[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(", ")}`
|
|
1190
|
+
);
|
|
1191
|
+
}
|
|
1192
|
+
result = injectRecoveryManifest(result, manifest);
|
|
1193
|
+
}
|
|
1194
|
+
return result;
|
|
1130
1195
|
}
|
|
1131
1196
|
}
|
|
1132
1197
|
}
|
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.0",
|
|
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/compiler": "0.
|
|
59
|
-
"@csszyx/
|
|
60
|
-
"@csszyx/
|
|
61
|
-
"@csszyx/types": "0.
|
|
62
|
-
"@csszyx/vue-adapter": "0.
|
|
58
|
+
"@csszyx/compiler": "0.6.0",
|
|
59
|
+
"@csszyx/svelte-adapter": "0.6.0",
|
|
60
|
+
"@csszyx/core": "0.6.0",
|
|
61
|
+
"@csszyx/types": "0.6.0",
|
|
62
|
+
"@csszyx/vue-adapter": "0.6.0"
|
|
63
63
|
},
|
|
64
64
|
"devDependencies": {
|
|
65
65
|
"@types/node": "^20.11.0",
|