@csszyx/runtime 0.1.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/index.cjs ADDED
@@ -0,0 +1,526 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ DEFAULT_RUNTIME_CONFIG: () => DEFAULT_RUNTIME_CONFIG,
24
+ VERSION: () => VERSION,
25
+ _sz: () => _sz,
26
+ _sz2: () => _sz2,
27
+ _sz3: () => _sz3,
28
+ _szIf: () => _szIf,
29
+ _szMerge: () => _szMerge,
30
+ _szSwitch: () => _szSwitch,
31
+ abortHydration: () => abortHydration,
32
+ attemptCSRRecovery: () => attemptCSRRecovery,
33
+ clearHydrationErrors: () => clearHydrationErrors,
34
+ disableCSRRecovery: () => disableCSRRecovery,
35
+ enableCSRRecovery: () => enableCSRRecovery,
36
+ endHydration: () => endHydration,
37
+ getAbortedSubtreeCount: () => getAbortedSubtreeCount,
38
+ getHydrationErrors: () => getHydrationErrors,
39
+ getRecoveryMode: () => getRecoveryMode,
40
+ getRuntimeConfig: () => getRuntimeConfig,
41
+ getSSRContext: () => getSSRContext,
42
+ guardHydration: () => guardHydration,
43
+ hasRecoveryToken: () => hasRecoveryToken,
44
+ initRuntime: () => initRuntime,
45
+ isCSRRecoveryAllowed: () => isCSRRecoveryAllowed,
46
+ isHydrating: () => isHydrating,
47
+ isHydrationAborted: () => isHydrationAborted,
48
+ isRuntimeInitialized: () => isRuntimeInitialized,
49
+ isSSREnvironment: () => isSSREnvironment,
50
+ isValidManifest: () => isValidManifest,
51
+ loadMangleMapFromDOM: () => loadMangleMapFromDOM,
52
+ loadManifestFromDOM: () => loadManifestFromDOM,
53
+ resetRuntime: () => resetRuntime,
54
+ startHydration: () => startHydration,
55
+ validateHydrationClass: () => validateHydrationClass,
56
+ verifyAllTokens: () => verifyAllTokens,
57
+ verifyMangleChecksum: () => verifyMangleChecksum,
58
+ verifyMangleMapIntegrity: () => verifyMangleMapIntegrity,
59
+ verifyRecoveryToken: () => verifyRecoveryToken
60
+ });
61
+ module.exports = __toCommonJS(index_exports);
62
+
63
+ // src/verify.ts
64
+ function verifyRecoveryToken(element, manifest) {
65
+ const token = element.getAttribute("data-sz-recovery-token");
66
+ if (!token) {
67
+ return {
68
+ valid: false,
69
+ error: "No recovery token found on element"
70
+ };
71
+ }
72
+ const tokenData = manifest.tokens[token];
73
+ if (!tokenData) {
74
+ return {
75
+ valid: false,
76
+ error: `Token not found in manifest: ${token}`
77
+ };
78
+ }
79
+ const szRecover = element.getAttribute("szRecover");
80
+ if (szRecover !== tokenData.mode) {
81
+ return {
82
+ valid: false,
83
+ error: `szRecover attribute (${szRecover}) does not match token mode (${tokenData.mode})`
84
+ };
85
+ }
86
+ return {
87
+ valid: true,
88
+ tokenData
89
+ };
90
+ }
91
+ function loadManifestFromDOM() {
92
+ if (typeof document === "undefined") {
93
+ return null;
94
+ }
95
+ const scriptElement = document.getElementById("__SZ_RECOVERY_MANIFEST__");
96
+ if (!scriptElement) {
97
+ return null;
98
+ }
99
+ try {
100
+ const content = scriptElement.textContent || "";
101
+ return JSON.parse(content);
102
+ } catch (error) {
103
+ console.error("Failed to parse recovery manifest:", error);
104
+ return null;
105
+ }
106
+ }
107
+ function isValidManifest(manifest) {
108
+ if (!manifest || typeof manifest !== "object") {
109
+ return false;
110
+ }
111
+ const m = manifest;
112
+ return typeof m.buildId === "string" && typeof m.checksum === "string" && typeof m.tokens === "object" && m.tokens !== null;
113
+ }
114
+ function verifyAllTokens(root, manifest) {
115
+ const elements = root.querySelectorAll("[data-sz-recovery-token]");
116
+ const results = [];
117
+ for (let i = 0; i < elements.length; i++) {
118
+ const element = elements[i];
119
+ const result = verifyRecoveryToken(element, manifest);
120
+ results.push(result);
121
+ }
122
+ return results;
123
+ }
124
+ function hasRecoveryToken(element) {
125
+ return element.hasAttribute("data-sz-recovery-token");
126
+ }
127
+ function getRecoveryMode(element) {
128
+ const szRecover = element.getAttribute("szRecover");
129
+ if (szRecover === "csr" || szRecover === "dev-only") {
130
+ return szRecover;
131
+ }
132
+ return null;
133
+ }
134
+
135
+ // src/hydration.ts
136
+ var state = {
137
+ errors: [],
138
+ abortedSubtrees: /* @__PURE__ */ new Set(),
139
+ recoveryAllowed: false
140
+ };
141
+ function enableCSRRecovery() {
142
+ state.recoveryAllowed = true;
143
+ if (typeof window !== "undefined") {
144
+ window.__SZ_ALLOW_CSR_RECOVERY__ = true;
145
+ }
146
+ }
147
+ function disableCSRRecovery() {
148
+ state.recoveryAllowed = false;
149
+ if (typeof window !== "undefined") {
150
+ window.__SZ_ALLOW_CSR_RECOVERY__ = false;
151
+ }
152
+ }
153
+ function isCSRRecoveryAllowed() {
154
+ return state.recoveryAllowed;
155
+ }
156
+ function loadMangleMapFromDOM() {
157
+ if (typeof document === "undefined") {
158
+ return null;
159
+ }
160
+ const scriptElement = document.getElementById("__SZ_MANGLE_MAP__");
161
+ if (!scriptElement) {
162
+ return null;
163
+ }
164
+ try {
165
+ const content = scriptElement.textContent || "";
166
+ return JSON.parse(content);
167
+ } catch (error) {
168
+ console.error("Failed to parse mangle map:", error);
169
+ return null;
170
+ }
171
+ }
172
+ function verifyMangleChecksum(expectedChecksum) {
173
+ if (typeof document === "undefined") {
174
+ return false;
175
+ }
176
+ const htmlElement = document.documentElement;
177
+ const actualChecksum = htmlElement.getAttribute("data-sz-checksum");
178
+ return actualChecksum === expectedChecksum;
179
+ }
180
+ function verifyMangleMapIntegrity() {
181
+ if (typeof document === "undefined") {
182
+ return false;
183
+ }
184
+ const htmlElement = document.documentElement;
185
+ const checksum = htmlElement.getAttribute("data-sz-checksum");
186
+ if (!checksum) {
187
+ console.warn("[csszyx] No checksum found in HTML");
188
+ return false;
189
+ }
190
+ const scriptElement = document.getElementById("__CSSZYX_MANGLE_MAP__");
191
+ if (!scriptElement) {
192
+ console.warn("[csszyx] Mangle map script not found");
193
+ return false;
194
+ }
195
+ try {
196
+ const mangleMap = JSON.parse(scriptElement.textContent || "{}");
197
+ if (typeof window !== "undefined" && "verify_mangle_checksum" in window) {
198
+ const isValid = window.verify_mangle_checksum(mangleMap, checksum);
199
+ return isValid;
200
+ }
201
+ console.warn("[csszyx] Rust core not available, using fallback verification");
202
+ return true;
203
+ } catch (error) {
204
+ console.error("[csszyx] Failed to verify mangle map:", error);
205
+ return false;
206
+ }
207
+ }
208
+ function abortHydration(element, error) {
209
+ state.abortedSubtrees.add(element);
210
+ console.error(
211
+ `[csszyx] Hydration aborted at ${element.tagName}:`,
212
+ error.message
213
+ );
214
+ element.setAttribute("data-sz-hydration-aborted", error.timestamp.toString());
215
+ element.setAttribute("data-sz-abort-reason", error.type);
216
+ element.setAttribute("data-sz-interactive", "false");
217
+ state.errors.push({
218
+ ...error,
219
+ element
220
+ });
221
+ }
222
+ function isHydrationAborted(element) {
223
+ return state.abortedSubtrees.has(element) || element.hasAttribute("data-sz-hydration-aborted");
224
+ }
225
+ function guardHydration(manifest) {
226
+ if (typeof document === "undefined") {
227
+ return true;
228
+ }
229
+ if (!verifyMangleChecksum(manifest.checksum)) {
230
+ const error = {
231
+ type: "checksum_mismatch",
232
+ message: "Mangle map checksum mismatch detected",
233
+ timestamp: Date.now()
234
+ };
235
+ abortHydration(document.documentElement, error);
236
+ return false;
237
+ }
238
+ return true;
239
+ }
240
+ function attemptCSRRecovery(element) {
241
+ if (!state.recoveryAllowed) {
242
+ return false;
243
+ }
244
+ if (!hasRecoveryToken(element)) {
245
+ console.warn("[csszyx] CSR recovery requires explicit szRecover directive");
246
+ return false;
247
+ }
248
+ const mode = getRecoveryMode(element);
249
+ if (mode === "dev-only" && process.env.NODE_ENV === "production") {
250
+ console.warn('[csszyx] szRecover="dev-only" is disabled in production');
251
+ return false;
252
+ }
253
+ console.warn(
254
+ "[csszyx] Hydration mismatch recovered via CSR. Fix root cause before production."
255
+ );
256
+ element.removeAttribute("data-sz-hydration-aborted");
257
+ element.removeAttribute("data-sz-abort-reason");
258
+ element.removeAttribute("data-sz-interactive");
259
+ state.abortedSubtrees.delete(element);
260
+ return true;
261
+ }
262
+ function getHydrationErrors() {
263
+ return [...state.errors];
264
+ }
265
+ function clearHydrationErrors() {
266
+ state.errors = [];
267
+ state.abortedSubtrees.clear();
268
+ }
269
+ function getAbortedSubtreeCount() {
270
+ return state.abortedSubtrees.size;
271
+ }
272
+ function isSSREnvironment() {
273
+ return typeof window === "undefined";
274
+ }
275
+ function isHydrating() {
276
+ if (typeof window === "undefined") {
277
+ return false;
278
+ }
279
+ if (window.__SZ_HYDRATING__ !== void 0) {
280
+ return window.__SZ_HYDRATING__;
281
+ }
282
+ if (window.__NEXT_DATA__ || window.__REMIX_CONTEXT__) {
283
+ return document.documentElement.hasAttribute("data-sz-checksum");
284
+ }
285
+ return false;
286
+ }
287
+ function getSSRContext() {
288
+ if (typeof document === "undefined") {
289
+ return null;
290
+ }
291
+ const htmlElement = document.documentElement;
292
+ const checksum = htmlElement.getAttribute("data-sz-checksum");
293
+ const buildId = htmlElement.getAttribute("data-sz-build-id");
294
+ if (!checksum || !buildId) {
295
+ return null;
296
+ }
297
+ const timestampAttr = htmlElement.getAttribute("data-sz-timestamp");
298
+ const timestamp = timestampAttr ? parseInt(timestampAttr, 10) : 0;
299
+ const hasRecoveryTokens = document.querySelector("[data-sz-recovery-token]") !== null;
300
+ return {
301
+ buildId,
302
+ checksum,
303
+ timestamp,
304
+ hasRecoveryTokens
305
+ };
306
+ }
307
+ function validateHydrationClass(className, expectedClassName) {
308
+ const normalize = (s) => s.split(/\s+/).filter(Boolean).sort().join(" ");
309
+ return normalize(className) === normalize(expectedClassName);
310
+ }
311
+ function startHydration() {
312
+ if (typeof window !== "undefined") {
313
+ window.__SZ_HYDRATING__ = true;
314
+ }
315
+ }
316
+ function endHydration() {
317
+ if (typeof window !== "undefined") {
318
+ window.__SZ_HYDRATING__ = false;
319
+ }
320
+ }
321
+
322
+ // src/concatenate.ts
323
+ var import_compiler = require("@csszyx/compiler");
324
+ function _sz(...classes) {
325
+ if (classes.length === 1) {
326
+ const cls = classes[0];
327
+ if (typeof cls === "string") {
328
+ return cls;
329
+ }
330
+ if (!cls) {
331
+ return "";
332
+ }
333
+ const res = (0, import_compiler.transform)(cls);
334
+ return typeof res === "string" ? res : res.className;
335
+ }
336
+ let result = "";
337
+ let needsSpace = false;
338
+ for (let i = 0; i < classes.length; i++) {
339
+ const cls = classes[i];
340
+ if (!cls) {
341
+ continue;
342
+ }
343
+ const res = typeof cls === "string" ? cls : (0, import_compiler.transform)(cls);
344
+ const str = typeof res === "string" ? res : res.className;
345
+ if (!str) {
346
+ continue;
347
+ }
348
+ if (needsSpace) {
349
+ result += " ";
350
+ }
351
+ result += str;
352
+ needsSpace = true;
353
+ }
354
+ return result;
355
+ }
356
+ function _szIf(condition, truthyValue, falsyValue) {
357
+ const value = condition ? truthyValue : falsyValue;
358
+ if (!value) {
359
+ return "";
360
+ }
361
+ if (typeof value === "string") {
362
+ return value;
363
+ }
364
+ const res = (0, import_compiler.transform)(value);
365
+ return typeof res === "string" ? res : res.className;
366
+ }
367
+ function _szSwitch(conditions, defaultValue = "") {
368
+ for (let i = 0; i < conditions.length; i++) {
369
+ const [condition, value] = conditions[i];
370
+ if (condition) {
371
+ if (!value) {
372
+ return "";
373
+ }
374
+ if (typeof value === "string") {
375
+ return value;
376
+ }
377
+ const res2 = (0, import_compiler.transform)(value);
378
+ return typeof res2 === "string" ? res2 : res2.className;
379
+ }
380
+ }
381
+ if (!defaultValue) {
382
+ return "";
383
+ }
384
+ if (typeof defaultValue === "string") {
385
+ return defaultValue;
386
+ }
387
+ const res = (0, import_compiler.transform)(defaultValue);
388
+ return typeof res === "string" ? res : res.className;
389
+ }
390
+ function _szMerge(...classes) {
391
+ const seen = /* @__PURE__ */ new Set();
392
+ const result = [];
393
+ for (let i = 0; i < classes.length; i++) {
394
+ const cls = classes[i];
395
+ if (!cls) {
396
+ continue;
397
+ }
398
+ const res = typeof cls === "string" ? cls : (0, import_compiler.transform)(cls);
399
+ const str = typeof res === "string" ? res : res.className;
400
+ if (!str) {
401
+ continue;
402
+ }
403
+ const parts = str.split(/\s+/);
404
+ for (let j = 0; j < parts.length; j++) {
405
+ const part = parts[j];
406
+ if (part && !seen.has(part)) {
407
+ seen.add(part);
408
+ result.push(part);
409
+ }
410
+ }
411
+ }
412
+ return result.join(" ");
413
+ }
414
+ function _sz2(a, b) {
415
+ if (!a) {
416
+ return b || "";
417
+ }
418
+ if (!b) {
419
+ return a;
420
+ }
421
+ return a + " " + b;
422
+ }
423
+ function _sz3(a, b, c) {
424
+ let result = "";
425
+ let needsSpace = false;
426
+ if (a) {
427
+ result = a;
428
+ needsSpace = true;
429
+ }
430
+ if (b) {
431
+ if (needsSpace) {
432
+ result += " ";
433
+ }
434
+ result += b;
435
+ needsSpace = true;
436
+ }
437
+ if (c) {
438
+ if (needsSpace) {
439
+ result += " ";
440
+ }
441
+ result += c;
442
+ }
443
+ return result;
444
+ }
445
+
446
+ // src/index.ts
447
+ var VERSION = "0.0.0";
448
+ var DEFAULT_RUNTIME_CONFIG = {
449
+ development: false,
450
+ allowCSRRecovery: false,
451
+ strictHydration: true,
452
+ debug: false
453
+ };
454
+ var runtimeState = {
455
+ config: { ...DEFAULT_RUNTIME_CONFIG },
456
+ initialized: false
457
+ };
458
+ function initRuntime(config = {}) {
459
+ if (runtimeState.initialized) {
460
+ if (runtimeState.config.debug) {
461
+ console.warn("[csszyx] Runtime already initialized");
462
+ }
463
+ return;
464
+ }
465
+ runtimeState.config = {
466
+ ...DEFAULT_RUNTIME_CONFIG,
467
+ ...config
468
+ };
469
+ if (runtimeState.config.allowCSRRecovery) {
470
+ enableCSRRecovery();
471
+ }
472
+ if (runtimeState.config.debug) {
473
+ console.log("[csszyx] Runtime initialized", runtimeState.config);
474
+ }
475
+ runtimeState.initialized = true;
476
+ }
477
+ function getRuntimeConfig() {
478
+ return { ...runtimeState.config };
479
+ }
480
+ function isRuntimeInitialized() {
481
+ return runtimeState.initialized;
482
+ }
483
+ function resetRuntime() {
484
+ runtimeState.config = { ...DEFAULT_RUNTIME_CONFIG };
485
+ runtimeState.initialized = false;
486
+ }
487
+ // Annotate the CommonJS export names for ESM import in node:
488
+ 0 && (module.exports = {
489
+ DEFAULT_RUNTIME_CONFIG,
490
+ VERSION,
491
+ _sz,
492
+ _sz2,
493
+ _sz3,
494
+ _szIf,
495
+ _szMerge,
496
+ _szSwitch,
497
+ abortHydration,
498
+ attemptCSRRecovery,
499
+ clearHydrationErrors,
500
+ disableCSRRecovery,
501
+ enableCSRRecovery,
502
+ endHydration,
503
+ getAbortedSubtreeCount,
504
+ getHydrationErrors,
505
+ getRecoveryMode,
506
+ getRuntimeConfig,
507
+ getSSRContext,
508
+ guardHydration,
509
+ hasRecoveryToken,
510
+ initRuntime,
511
+ isCSRRecoveryAllowed,
512
+ isHydrating,
513
+ isHydrationAborted,
514
+ isRuntimeInitialized,
515
+ isSSREnvironment,
516
+ isValidManifest,
517
+ loadMangleMapFromDOM,
518
+ loadManifestFromDOM,
519
+ resetRuntime,
520
+ startHydration,
521
+ validateHydrationClass,
522
+ verifyAllTokens,
523
+ verifyMangleChecksum,
524
+ verifyMangleMapIntegrity,
525
+ verifyRecoveryToken
526
+ });