sibujs 1.0.0-beta.1
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/LICENSE +21 -0
- package/README.md +1630 -0
- package/dist/browser.cjs +815 -0
- package/dist/browser.d.cts +174 -0
- package/dist/browser.d.ts +174 -0
- package/dist/browser.js +458 -0
- package/dist/build.cjs +4970 -0
- package/dist/build.d.cts +630 -0
- package/dist/build.d.ts +630 -0
- package/dist/build.js +2478 -0
- package/dist/cdn.global.js +115 -0
- package/dist/chunk-27QC4FPL.js +67 -0
- package/dist/chunk-2ABBWCGC.js +65 -0
- package/dist/chunk-2MUNQYZ7.js +26 -0
- package/dist/chunk-2PSPKNUI.js +1711 -0
- package/dist/chunk-35CDLDX5.js +1758 -0
- package/dist/chunk-36MU4CFV.js +41 -0
- package/dist/chunk-3FIQOFI6.js +182 -0
- package/dist/chunk-3GHNC2BN.js +28 -0
- package/dist/chunk-3HLWWEPU.js +909 -0
- package/dist/chunk-3IVI3J54.js +252 -0
- package/dist/chunk-3KZ72WNW.js +944 -0
- package/dist/chunk-4AU64SQV.js +182 -0
- package/dist/chunk-4MOK7HAR.js +84 -0
- package/dist/chunk-4QK6FBDH.js +1429 -0
- package/dist/chunk-566Z7HXB.js +737 -0
- package/dist/chunk-5CRBB7XP.js +358 -0
- package/dist/chunk-5G67D3IZ.js +168 -0
- package/dist/chunk-5NCPAWBE.js +99 -0
- package/dist/chunk-5O2RKXR3.js +1444 -0
- package/dist/chunk-6BTBDO6A.js +633 -0
- package/dist/chunk-6IWEHW57.js +43 -0
- package/dist/chunk-6JGMNCD6.js +282 -0
- package/dist/chunk-6QRLJNXR.js +1425 -0
- package/dist/chunk-7HM5UE5T.js +270 -0
- package/dist/chunk-7JOLTGUH.js +58 -0
- package/dist/chunk-7MCWJCQK.js +909 -0
- package/dist/chunk-7RIIFP3E.js +1758 -0
- package/dist/chunk-7UASYN3G.js +254 -0
- package/dist/chunk-7W2WYHDI.js +741 -0
- package/dist/chunk-7Y35RDSJ.js +872 -0
- package/dist/chunk-A65GFJBL.js +65 -0
- package/dist/chunk-AD6ZIEDK.js +67 -0
- package/dist/chunk-AK5Y72F3.js +1426 -0
- package/dist/chunk-APOMMWH4.js +282 -0
- package/dist/chunk-ARZVTWIQ.js +1750 -0
- package/dist/chunk-AWWBM2BI.js +664 -0
- package/dist/chunk-AX5VEQTY.js +58 -0
- package/dist/chunk-AYTXVOW3.js +1708 -0
- package/dist/chunk-BG4A246G.js +1746 -0
- package/dist/chunk-BNFJJA2L.js +1425 -0
- package/dist/chunk-BPKPBVU5.js +59 -0
- package/dist/chunk-BPKPPSXC.js +282 -0
- package/dist/chunk-BPWKKK7F.js +1711 -0
- package/dist/chunk-CCKX6YTC.js +1735 -0
- package/dist/chunk-CIF5Z3MP.js +58 -0
- package/dist/chunk-CSXYU7IO.js +457 -0
- package/dist/chunk-D6JD4FDC.js +26 -0
- package/dist/chunk-E7NGA7X2.js +59 -0
- package/dist/chunk-EEPPJKAE.js +443 -0
- package/dist/chunk-EJMYGAGQ.js +717 -0
- package/dist/chunk-EL6Z5MDY.js +55 -0
- package/dist/chunk-EP7VRLEB.js +41 -0
- package/dist/chunk-ETMEC6FH.js +99 -0
- package/dist/chunk-EZ2WHYVL.js +65 -0
- package/dist/chunk-EZRVMSZK.js +67 -0
- package/dist/chunk-F2TRGINX.js +254 -0
- package/dist/chunk-F5JCIH3Q.js +642 -0
- package/dist/chunk-FGK3JKMN.js +909 -0
- package/dist/chunk-FQWPKSTD.js +1437 -0
- package/dist/chunk-FWHVLMCI.js +26 -0
- package/dist/chunk-GBEYQRO2.js +303 -0
- package/dist/chunk-GBLES3NK.js +248 -0
- package/dist/chunk-GQVGUQW6.js +1436 -0
- package/dist/chunk-HCV2T76T.js +457 -0
- package/dist/chunk-HS7ZKVPR.js +182 -0
- package/dist/chunk-HXDVV7HZ.js +909 -0
- package/dist/chunk-IB23VMO3.js +1746 -0
- package/dist/chunk-IEMZ7RTT.js +99 -0
- package/dist/chunk-IPGRSN42.js +1750 -0
- package/dist/chunk-IVMOK2QN.js +1750 -0
- package/dist/chunk-JCLGQO7T.js +443 -0
- package/dist/chunk-JDXL7KDB.js +1436 -0
- package/dist/chunk-JIIFW636.js +270 -0
- package/dist/chunk-JWGEEH7H.js +944 -0
- package/dist/chunk-K2BESAG7.js +1688 -0
- package/dist/chunk-K2U5YGF4.js +877 -0
- package/dist/chunk-K45FQ4Y4.js +175 -0
- package/dist/chunk-K7BPE427.js +1432 -0
- package/dist/chunk-KL3266RS.js +26 -0
- package/dist/chunk-KNN4P7DZ.js +84 -0
- package/dist/chunk-KP2DZH5Q.js +254 -0
- package/dist/chunk-KZHAJSQR.js +1636 -0
- package/dist/chunk-LBKGHMQV.js +1750 -0
- package/dist/chunk-LBTEPL7A.js +1731 -0
- package/dist/chunk-LEBBPTDB.js +1444 -0
- package/dist/chunk-LLH63WVQ.js +98 -0
- package/dist/chunk-LWVR2C4G.js +1711 -0
- package/dist/chunk-M3MDTVV2.js +896 -0
- package/dist/chunk-M5GNLDEO.js +303 -0
- package/dist/chunk-MFHVGKET.js +267 -0
- package/dist/chunk-MGWSG3PM.js +358 -0
- package/dist/chunk-MJNB47HB.js +19 -0
- package/dist/chunk-MLKGABMK.js +9 -0
- package/dist/chunk-MQWTY3JY.js +944 -0
- package/dist/chunk-MZZOQHNI.js +642 -0
- package/dist/chunk-NIHWGZS4.js +1426 -0
- package/dist/chunk-NSVVHQK5.js +41 -0
- package/dist/chunk-NVI2WE7D.js +443 -0
- package/dist/chunk-O7QBO3PH.js +58 -0
- package/dist/chunk-OAUPQBO2.js +270 -0
- package/dist/chunk-OB2LMD7C.js +297 -0
- package/dist/chunk-OHEYBWQU.js +58 -0
- package/dist/chunk-OI6OXUHJ.js +443 -0
- package/dist/chunk-OX2VMRMV.js +633 -0
- package/dist/chunk-P4FYE5TX.js +866 -0
- package/dist/chunk-P5KFWM4H.js +98 -0
- package/dist/chunk-PUMLE7RJ.js +1711 -0
- package/dist/chunk-Q4MFANBF.js +282 -0
- package/dist/chunk-QLEKZMMU.js +282 -0
- package/dist/chunk-RGGNGVO3.js +98 -0
- package/dist/chunk-RKJDRVV6.js +443 -0
- package/dist/chunk-S5BHU353.js +43 -0
- package/dist/chunk-SHQUSFH7.js +1426 -0
- package/dist/chunk-SMB4DBMD.js +182 -0
- package/dist/chunk-SNYHQP3D.js +743 -0
- package/dist/chunk-T24L3TBF.js +1717 -0
- package/dist/chunk-TAQNSOKT.js +692 -0
- package/dist/chunk-TDNY4SUA.js +41 -0
- package/dist/chunk-TNNF56IQ.js +1750 -0
- package/dist/chunk-TR7E6LYX.js +457 -0
- package/dist/chunk-URWUFH45.js +98 -0
- package/dist/chunk-UUSIH3XH.js +1429 -0
- package/dist/chunk-UYFNXLKR.js +1436 -0
- package/dist/chunk-V6F7KUWD.js +270 -0
- package/dist/chunk-VCZLXRMR.js +254 -0
- package/dist/chunk-VDHXSSBT.js +1426 -0
- package/dist/chunk-VM4QMKVK.js +254 -0
- package/dist/chunk-VWGYKYL2.js +737 -0
- package/dist/chunk-VX2OFBJN.js +1426 -0
- package/dist/chunk-VXVIE6DG.js +84 -0
- package/dist/chunk-W4OH7HG4.js +40 -0
- package/dist/chunk-WBVJX4GZ.js +98 -0
- package/dist/chunk-WDU2ZV4I.js +1426 -0
- package/dist/chunk-X6VUCICU.js +457 -0
- package/dist/chunk-XAY7FM7Y.js +618 -0
- package/dist/chunk-XJZ5Z2CM.js +642 -0
- package/dist/chunk-XKVFQTJJ.js +254 -0
- package/dist/chunk-XRLFASCY.js +22 -0
- package/dist/chunk-XYU6TZOW.js +182 -0
- package/dist/chunk-Y745CBVB.js +944 -0
- package/dist/chunk-YLBJSXYY.js +944 -0
- package/dist/chunk-YQJIKVPZ.js +1429 -0
- package/dist/chunk-YRM2VCZF.js +457 -0
- package/dist/chunk-YS33KBVJ.js +944 -0
- package/dist/chunk-Z27DZPDG.js +41 -0
- package/dist/chunk-ZXQ5NAEN.js +32 -0
- package/dist/contracts-B552GopR.d.cts +245 -0
- package/dist/contracts-B552GopR.d.ts +245 -0
- package/dist/contracts-Bg1ECISC.d.cts +245 -0
- package/dist/contracts-Bg1ECISC.d.ts +245 -0
- package/dist/contracts-CMriKJ6P.d.cts +245 -0
- package/dist/contracts-CMriKJ6P.d.ts +245 -0
- package/dist/contracts-DOrhwbke.d.cts +245 -0
- package/dist/contracts-DOrhwbke.d.ts +245 -0
- package/dist/data.cjs +1373 -0
- package/dist/data.d.cts +434 -0
- package/dist/data.d.ts +434 -0
- package/dist/data.js +945 -0
- package/dist/devtools.cjs +1357 -0
- package/dist/devtools.d.cts +473 -0
- package/dist/devtools.d.ts +473 -0
- package/dist/devtools.js +1084 -0
- package/dist/ecosystem.cjs +1046 -0
- package/dist/ecosystem.d.cts +247 -0
- package/dist/ecosystem.d.ts +247 -0
- package/dist/ecosystem.js +369 -0
- package/dist/extras.cjs +8457 -0
- package/dist/extras.d.cts +2356 -0
- package/dist/extras.d.ts +2356 -0
- package/dist/extras.js +5152 -0
- package/dist/index.cjs +2648 -0
- package/dist/index.d.cts +869 -0
- package/dist/index.d.ts +869 -0
- package/dist/index.js +386 -0
- package/dist/motion.cjs +604 -0
- package/dist/motion.d.cts +146 -0
- package/dist/motion.d.ts +146 -0
- package/dist/motion.js +346 -0
- package/dist/patterns.cjs +815 -0
- package/dist/patterns.d.cts +163 -0
- package/dist/patterns.d.ts +163 -0
- package/dist/patterns.js +296 -0
- package/dist/performance.cjs +927 -0
- package/dist/performance.d.cts +416 -0
- package/dist/performance.d.ts +416 -0
- package/dist/performance.js +654 -0
- package/dist/plugins.cjs +2487 -0
- package/dist/plugins.d.cts +393 -0
- package/dist/plugins.d.ts +393 -0
- package/dist/plugins.js +1504 -0
- package/dist/signal-BnWpq6WB.d.cts +5 -0
- package/dist/signal-BnWpq6WB.d.ts +5 -0
- package/dist/src/components/ErrorBoundary.d.ts +15 -0
- package/dist/src/components/ErrorBoundary.js +119 -0
- package/dist/src/core/catch.d.ts +11 -0
- package/dist/src/core/catch.js +28 -0
- package/dist/src/core/each.d.ts +13 -0
- package/dist/src/core/each.js +68 -0
- package/dist/src/core/for.d.ts +12 -0
- package/dist/src/core/for.js +67 -0
- package/dist/src/core/html.d.ts +137 -0
- package/dist/src/core/html.js +155 -0
- package/dist/src/core/htmlIf.d.ts +11 -0
- package/dist/src/core/htmlIf.js +18 -0
- package/dist/src/core/lazy.d.ts +7 -0
- package/dist/src/core/lazy.js +16 -0
- package/dist/src/core/mount.d.ts +7 -0
- package/dist/src/core/mount.js +12 -0
- package/dist/src/core/slots.d.ts +3 -0
- package/dist/src/core/slots.js +3 -0
- package/dist/src/core/suspense.d.ts +10 -0
- package/dist/src/core/suspense.js +33 -0
- package/dist/src/core/tagFactory.d.ts +13 -0
- package/dist/src/core/tagFactory.js +86 -0
- package/dist/src/core/test.d.ts +11 -0
- package/dist/src/core/test.js +28 -0
- package/dist/src/core/types.d.ts +2 -0
- package/dist/src/core/types.js +1 -0
- package/dist/src/core/useComputed.d.ts +6 -0
- package/dist/src/core/useComputed.js +30 -0
- package/dist/src/core/useEffect.d.ts +6 -0
- package/dist/src/core/useEffect.js +23 -0
- package/dist/src/core/useState.d.ts +10 -0
- package/dist/src/core/useState.js +34 -0
- package/dist/src/core/useStore.d.ts +19 -0
- package/dist/src/core/useStore.js +53 -0
- package/dist/src/core/useWatch.d.ts +8 -0
- package/dist/src/core/useWatch.js +23 -0
- package/dist/src/plugins/i18n.d.ts +6 -0
- package/dist/src/plugins/i18n.js +16 -0
- package/dist/src/plugins/router.d.ts +188 -0
- package/dist/src/plugins/router.js +1178 -0
- package/dist/src/reactivity/bindAttribute.d.ts +5 -0
- package/dist/src/reactivity/bindAttribute.js +31 -0
- package/dist/src/reactivity/bindChildNode.d.ts +10 -0
- package/dist/src/reactivity/bindChildNode.js +46 -0
- package/dist/src/reactivity/bindTextNode.d.ts +10 -0
- package/dist/src/reactivity/bindTextNode.js +27 -0
- package/dist/src/reactivity/signal.d.ts +3 -0
- package/dist/src/reactivity/signal.js +1 -0
- package/dist/src/reactivity/track.d.ts +18 -0
- package/dist/src/reactivity/track.js +73 -0
- package/dist/src/reactivity/useComputed.d.ts +6 -0
- package/dist/src/reactivity/useComputed.js +30 -0
- package/dist/src/reactivity/useEffect.d.ts +6 -0
- package/dist/src/reactivity/useEffect.js +23 -0
- package/dist/src/reactivity/useState.d.ts +10 -0
- package/dist/src/reactivity/useState.js +34 -0
- package/dist/src/reactivity/useStore.d.ts +19 -0
- package/dist/src/reactivity/useStore.js +53 -0
- package/dist/src/reactivity/useWatch.d.ts +8 -0
- package/dist/src/reactivity/useWatch.js +23 -0
- package/dist/src/utils/sanitize.d.ts +1 -0
- package/dist/src/utils/sanitize.js +8 -0
- package/dist/ssr-27FOM46T.js +35 -0
- package/dist/ssr-GFUTTSJD.js +22 -0
- package/dist/ssr-K7DCR6BZ.js +35 -0
- package/dist/ssr-O6LFMRFP.js +35 -0
- package/dist/ssr-QZEVGMMK.js +35 -0
- package/dist/ssr-SGVBCAGC.js +35 -0
- package/dist/ssr-UB2IXCYX.js +35 -0
- package/dist/ssr-XBZQNV4O.js +22 -0
- package/dist/ssr-Y76FSXDU.js +35 -0
- package/dist/ssr-YQJ4AYBD.js +35 -0
- package/dist/ssr.cjs +1757 -0
- package/dist/ssr.d.cts +478 -0
- package/dist/ssr.d.ts +478 -0
- package/dist/ssr.js +743 -0
- package/dist/tagFactory-CZPO4RXF.d.cts +34 -0
- package/dist/tagFactory-CZPO4RXF.d.ts +34 -0
- package/dist/tagFactory-CgImPVMY.d.cts +22 -0
- package/dist/tagFactory-CgImPVMY.d.ts +22 -0
- package/dist/tagFactory-Cw1iv5if.d.cts +22 -0
- package/dist/tagFactory-Cw1iv5if.d.ts +22 -0
- package/dist/tagFactory-DeAXq9ef.d.cts +30 -0
- package/dist/tagFactory-DeAXq9ef.d.ts +30 -0
- package/dist/tagFactory-SkY0a7L1.d.cts +22 -0
- package/dist/tagFactory-SkY0a7L1.d.ts +22 -0
- package/dist/testing.cjs +1919 -0
- package/dist/testing.d.cts +491 -0
- package/dist/testing.d.ts +491 -0
- package/dist/testing.js +1862 -0
- package/dist/ui.cjs +1497 -0
- package/dist/ui.d.cts +264 -0
- package/dist/ui.d.ts +264 -0
- package/dist/ui.js +900 -0
- package/dist/widgets.cjs +919 -0
- package/dist/widgets.d.cts +165 -0
- package/dist/widgets.d.ts +165 -0
- package/dist/widgets.js +545 -0
- package/package.json +134 -0
package/dist/plugins.cjs
ADDED
|
@@ -0,0 +1,2487 @@
|
|
|
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 __esm = (fn, res) => function __init() {
|
|
7
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
8
|
+
};
|
|
9
|
+
var __export = (target, all) => {
|
|
10
|
+
for (var name in all)
|
|
11
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
12
|
+
};
|
|
13
|
+
var __copyProps = (to, from, except, desc) => {
|
|
14
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
+
for (let key of __getOwnPropNames(from))
|
|
16
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
17
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
18
|
+
}
|
|
19
|
+
return to;
|
|
20
|
+
};
|
|
21
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
22
|
+
|
|
23
|
+
// src/platform/ssr.ts
|
|
24
|
+
var ssr_exports = {};
|
|
25
|
+
__export(ssr_exports, {
|
|
26
|
+
collectStream: () => collectStream,
|
|
27
|
+
deserializeState: () => deserializeState,
|
|
28
|
+
hydrate: () => hydrate,
|
|
29
|
+
hydrateIslands: () => hydrateIslands,
|
|
30
|
+
hydrateProgressively: () => hydrateProgressively,
|
|
31
|
+
island: () => island,
|
|
32
|
+
renderToDocument: () => renderToDocument,
|
|
33
|
+
renderToReadableStream: () => renderToReadableStream,
|
|
34
|
+
renderToStream: () => renderToStream,
|
|
35
|
+
renderToString: () => renderToString,
|
|
36
|
+
renderToSuspenseStream: () => renderToSuspenseStream,
|
|
37
|
+
resetSSRState: () => resetSSRState,
|
|
38
|
+
serializeState: () => serializeState,
|
|
39
|
+
ssrSuspense: () => ssrSuspense,
|
|
40
|
+
suspenseSwapScript: () => suspenseSwapScript
|
|
41
|
+
});
|
|
42
|
+
function renderToString(element) {
|
|
43
|
+
if (element instanceof DocumentFragment) {
|
|
44
|
+
return Array.from(element.childNodes).map((child) => renderToString(child)).join("");
|
|
45
|
+
}
|
|
46
|
+
if (element.nodeType === 3) {
|
|
47
|
+
return escapeHtml(element.textContent || "");
|
|
48
|
+
}
|
|
49
|
+
if (element.nodeType === 8) {
|
|
50
|
+
const content = (element.textContent || "").replace(/-->/g, "-->");
|
|
51
|
+
return `<!--${content}-->`;
|
|
52
|
+
}
|
|
53
|
+
if (!(element instanceof HTMLElement)) {
|
|
54
|
+
return element.textContent || "";
|
|
55
|
+
}
|
|
56
|
+
const tag = element.tagName.toLowerCase();
|
|
57
|
+
let html2 = `<${tag}`;
|
|
58
|
+
for (const attr of Array.from(element.attributes)) {
|
|
59
|
+
html2 += ` ${attr.name}="${escapeAttr(attr.value)}"`;
|
|
60
|
+
}
|
|
61
|
+
if (element.dataset && !element.dataset.sibuHydrate) {
|
|
62
|
+
html2 += ` data-sibu-ssr="true"`;
|
|
63
|
+
}
|
|
64
|
+
if (VOID_ELEMENTS.has(tag)) {
|
|
65
|
+
return `${html2} />`;
|
|
66
|
+
}
|
|
67
|
+
html2 += ">";
|
|
68
|
+
for (const child of Array.from(element.childNodes)) {
|
|
69
|
+
html2 += renderToString(child);
|
|
70
|
+
}
|
|
71
|
+
html2 += `</${tag}>`;
|
|
72
|
+
return html2;
|
|
73
|
+
}
|
|
74
|
+
function hydrate(component, container) {
|
|
75
|
+
const clientTree = component();
|
|
76
|
+
hydrateNode(container.firstElementChild, clientTree);
|
|
77
|
+
container.setAttribute("data-sibu-hydrated", "true");
|
|
78
|
+
}
|
|
79
|
+
function hydrateNode(serverNode, clientNode) {
|
|
80
|
+
if (!serverNode) return;
|
|
81
|
+
const serverChildren = Array.from(serverNode.children);
|
|
82
|
+
const clientChildren = Array.from(clientNode.children);
|
|
83
|
+
for (let i2 = 0; i2 < Math.min(serverChildren.length, clientChildren.length); i2++) {
|
|
84
|
+
hydrateNode(serverChildren[i2], clientChildren[i2]);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
function renderToDocument(component, options = {}) {
|
|
88
|
+
const content = renderToString(component());
|
|
89
|
+
const metaTags = (options.meta || []).map(
|
|
90
|
+
(attrs) => `<meta ${Object.entries(attrs).map(([k, v]) => `${k}="${escapeAttr(v)}"`).join(" ")} />`
|
|
91
|
+
).join("\n ");
|
|
92
|
+
const linkTags = (options.links || []).map(
|
|
93
|
+
(attrs) => `<link ${Object.entries(attrs).map(([k, v]) => `${k}="${escapeAttr(v)}"`).join(" ")} />`
|
|
94
|
+
).join("\n ");
|
|
95
|
+
const scriptTags = (options.scripts || []).map((src) => `<script src="${escapeAttr(src)}"></script>`).join("\n ");
|
|
96
|
+
const bodyAttrs = options.bodyAttrs ? " " + Object.entries(options.bodyAttrs).map(([k, v]) => `${k}="${escapeAttr(v)}"`).join(" ") : "";
|
|
97
|
+
return `<!DOCTYPE html>
|
|
98
|
+
<html>
|
|
99
|
+
<head>
|
|
100
|
+
<meta charset="UTF-8" />
|
|
101
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
102
|
+
${options.title ? `<title>${escapeHtml(options.title)}</title>` : ""}
|
|
103
|
+
${metaTags}
|
|
104
|
+
${linkTags}
|
|
105
|
+
${options.headExtra || ""}
|
|
106
|
+
</head>
|
|
107
|
+
<body${bodyAttrs}>
|
|
108
|
+
<div id="app">${content}</div>
|
|
109
|
+
${scriptTags}
|
|
110
|
+
</body>
|
|
111
|
+
</html>`;
|
|
112
|
+
}
|
|
113
|
+
async function* renderToStream(element) {
|
|
114
|
+
if (element instanceof DocumentFragment) {
|
|
115
|
+
for (const child of Array.from(element.childNodes)) {
|
|
116
|
+
yield* renderToStream(child);
|
|
117
|
+
}
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
if (element.nodeType === 3) {
|
|
121
|
+
yield escapeHtml(element.textContent || "");
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
if (element.nodeType === 8) {
|
|
125
|
+
yield `<!--${element.textContent || ""}-->`;
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
if (!(element instanceof HTMLElement)) {
|
|
129
|
+
yield element.textContent || "";
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
const tag = element.tagName.toLowerCase();
|
|
133
|
+
let openTag = `<${tag}`;
|
|
134
|
+
for (const attr of Array.from(element.attributes)) {
|
|
135
|
+
openTag += ` ${attr.name}="${escapeAttr(attr.value)}"`;
|
|
136
|
+
}
|
|
137
|
+
if (VOID_ELEMENTS.has(tag)) {
|
|
138
|
+
yield `${openTag} />`;
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
yield `${openTag}>`;
|
|
142
|
+
for (const child of Array.from(element.childNodes)) {
|
|
143
|
+
yield* renderToStream(child);
|
|
144
|
+
}
|
|
145
|
+
yield `</${tag}>`;
|
|
146
|
+
}
|
|
147
|
+
async function collectStream(stream) {
|
|
148
|
+
let result = "";
|
|
149
|
+
for await (const chunk of stream) {
|
|
150
|
+
result += chunk;
|
|
151
|
+
}
|
|
152
|
+
return result;
|
|
153
|
+
}
|
|
154
|
+
function renderToReadableStream(element) {
|
|
155
|
+
const generator = renderToStream(element);
|
|
156
|
+
return new ReadableStream({
|
|
157
|
+
async pull(controller) {
|
|
158
|
+
const { value, done } = await generator.next();
|
|
159
|
+
if (done) {
|
|
160
|
+
controller.close();
|
|
161
|
+
} else {
|
|
162
|
+
controller.enqueue(value);
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
cancel() {
|
|
166
|
+
generator.return(void 0);
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
function island(id, component) {
|
|
171
|
+
const el = component();
|
|
172
|
+
el.setAttribute("data-sibu-island", id);
|
|
173
|
+
return el;
|
|
174
|
+
}
|
|
175
|
+
function hydrateIslands(container, islands) {
|
|
176
|
+
const markers = container.querySelectorAll("[data-sibu-island]");
|
|
177
|
+
for (const marker2 of Array.from(markers)) {
|
|
178
|
+
const id = marker2.getAttribute("data-sibu-island") ?? "";
|
|
179
|
+
const factory = islands[id];
|
|
180
|
+
if (!factory) continue;
|
|
181
|
+
const clientTree = factory();
|
|
182
|
+
hydrateNode(marker2, clientTree);
|
|
183
|
+
marker2.setAttribute("data-sibu-hydrated", "true");
|
|
184
|
+
}
|
|
185
|
+
container.setAttribute("data-sibu-hydrated", "partial");
|
|
186
|
+
}
|
|
187
|
+
function hydrateProgressively(container, islands, options) {
|
|
188
|
+
const markers = container.querySelectorAll("[data-sibu-island]");
|
|
189
|
+
const cleanups = [];
|
|
190
|
+
for (const marker2 of Array.from(markers)) {
|
|
191
|
+
const id = marker2.getAttribute("data-sibu-island") ?? "";
|
|
192
|
+
const factory = islands[id];
|
|
193
|
+
if (!factory) continue;
|
|
194
|
+
const observer = new IntersectionObserver(
|
|
195
|
+
(entries) => {
|
|
196
|
+
for (const entry of entries) {
|
|
197
|
+
if (entry.isIntersecting) {
|
|
198
|
+
const clientTree = factory();
|
|
199
|
+
hydrateNode(marker2, clientTree);
|
|
200
|
+
marker2.setAttribute("data-sibu-hydrated", "true");
|
|
201
|
+
observer.disconnect();
|
|
202
|
+
break;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
},
|
|
206
|
+
{ rootMargin: "200px", ...options }
|
|
207
|
+
);
|
|
208
|
+
observer.observe(marker2);
|
|
209
|
+
cleanups.push(() => observer.disconnect());
|
|
210
|
+
}
|
|
211
|
+
container.setAttribute("data-sibu-hydrated", "progressive");
|
|
212
|
+
return () => {
|
|
213
|
+
for (const cleanup2 of cleanups) cleanup2();
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
function resetSSRState() {
|
|
217
|
+
suspenseIdCounter = 0;
|
|
218
|
+
}
|
|
219
|
+
function ssrSuspense(props) {
|
|
220
|
+
const id = `sibu-sus-${suspenseIdCounter++}`;
|
|
221
|
+
const fallbackEl = props.fallback();
|
|
222
|
+
const wrapper = document.createElement("div");
|
|
223
|
+
wrapper.setAttribute("data-sibu-suspense-id", id);
|
|
224
|
+
wrapper.appendChild(fallbackEl);
|
|
225
|
+
const promise = props.content().then((resolvedEl) => ({
|
|
226
|
+
id,
|
|
227
|
+
html: renderToString(resolvedEl)
|
|
228
|
+
}));
|
|
229
|
+
return { element: wrapper, promise };
|
|
230
|
+
}
|
|
231
|
+
function suspenseSwapScript(id) {
|
|
232
|
+
const safeId = id.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/</g, "\\u003c").replace(/>/g, "\\u003e");
|
|
233
|
+
return `<script>(function(){var t=document.getElementById("sibu-resolved-${safeId}");var f=document.querySelector('[data-sibu-suspense-id="${safeId}"]');if(t&&f){while(t.firstChild)f.appendChild(t.firstChild);t.remove();f.removeAttribute("data-sibu-suspense-id");}})()</script>`;
|
|
234
|
+
}
|
|
235
|
+
async function* renderToSuspenseStream(element, pendingBoundaries = []) {
|
|
236
|
+
yield* renderToStream(element);
|
|
237
|
+
if (pendingBoundaries.length > 0) {
|
|
238
|
+
const resolved = await Promise.all(pendingBoundaries);
|
|
239
|
+
for (const { id, html: html2 } of resolved) {
|
|
240
|
+
yield `<div hidden id="sibu-resolved-${id}">${html2}</div>`;
|
|
241
|
+
yield suspenseSwapScript(id);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
function serializeState(state) {
|
|
246
|
+
const json = JSON.stringify(state).replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/&/g, "\\u0026");
|
|
247
|
+
return `<script>window.${SSR_DATA_ATTR}=${json}</script>`;
|
|
248
|
+
}
|
|
249
|
+
function deserializeState() {
|
|
250
|
+
if (typeof window === "undefined") return void 0;
|
|
251
|
+
return window[SSR_DATA_ATTR];
|
|
252
|
+
}
|
|
253
|
+
function escapeHtml(str) {
|
|
254
|
+
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
255
|
+
}
|
|
256
|
+
function escapeAttr(str) {
|
|
257
|
+
return str.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
258
|
+
}
|
|
259
|
+
var VOID_ELEMENTS, suspenseIdCounter, SSR_DATA_ATTR;
|
|
260
|
+
var init_ssr = __esm({
|
|
261
|
+
"src/platform/ssr.ts"() {
|
|
262
|
+
"use strict";
|
|
263
|
+
VOID_ELEMENTS = /* @__PURE__ */ new Set([
|
|
264
|
+
"area",
|
|
265
|
+
"base",
|
|
266
|
+
"br",
|
|
267
|
+
"col",
|
|
268
|
+
"embed",
|
|
269
|
+
"hr",
|
|
270
|
+
"img",
|
|
271
|
+
"input",
|
|
272
|
+
"link",
|
|
273
|
+
"meta",
|
|
274
|
+
"param",
|
|
275
|
+
"source",
|
|
276
|
+
"track",
|
|
277
|
+
"wbr"
|
|
278
|
+
]);
|
|
279
|
+
suspenseIdCounter = 0;
|
|
280
|
+
SSR_DATA_ATTR = "__SIBU_SSR_DATA__";
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
// plugins.ts
|
|
285
|
+
var plugins_exports = {};
|
|
286
|
+
__export(plugins_exports, {
|
|
287
|
+
Outlet: () => Outlet,
|
|
288
|
+
Route: () => Route,
|
|
289
|
+
RouterLink: () => RouterLink,
|
|
290
|
+
SibuRouter: () => SibuRouter,
|
|
291
|
+
Suspense: () => Suspense,
|
|
292
|
+
Trans: () => Trans,
|
|
293
|
+
addRoute: () => addRoute,
|
|
294
|
+
afterEach: () => afterEach,
|
|
295
|
+
back: () => back,
|
|
296
|
+
beforeEach: () => beforeEach,
|
|
297
|
+
beforeResolve: () => beforeResolve,
|
|
298
|
+
buildURL: () => buildURL,
|
|
299
|
+
createMemoryRouter: () => createMemoryRouter,
|
|
300
|
+
createRouter: () => createRouter,
|
|
301
|
+
createSSRRouter: () => createSSRRouter,
|
|
302
|
+
deserializeRouteState: () => deserializeRouteState,
|
|
303
|
+
destroyRouter: () => destroyRouter,
|
|
304
|
+
forward: () => forward,
|
|
305
|
+
getAvailableLocales: () => getAvailableLocales,
|
|
306
|
+
getLocale: () => getLocale,
|
|
307
|
+
getRouteInfo: () => getRouteInfo,
|
|
308
|
+
getRouteTransition: () => getRouteTransition,
|
|
309
|
+
go: () => go,
|
|
310
|
+
hasRoute: () => hasRoute,
|
|
311
|
+
hasTranslation: () => hasTranslation,
|
|
312
|
+
hydrateRouter: () => hydrateRouter,
|
|
313
|
+
lazy: () => lazy,
|
|
314
|
+
navigate: () => navigate,
|
|
315
|
+
preloadRoute: () => preloadRoute,
|
|
316
|
+
push: () => push,
|
|
317
|
+
registerTranslations: () => registerTranslations,
|
|
318
|
+
removeRoute: () => removeRoute,
|
|
319
|
+
renderRouteToDocument: () => renderRouteToDocument,
|
|
320
|
+
renderRouteToString: () => renderRouteToString,
|
|
321
|
+
replace: () => replace,
|
|
322
|
+
resolveServerRoute: () => resolveServerRoute,
|
|
323
|
+
route: () => route,
|
|
324
|
+
router: () => router,
|
|
325
|
+
routerPlugin: () => routerPlugin,
|
|
326
|
+
routerState: () => routerState,
|
|
327
|
+
serializeRouteState: () => serializeRouteState,
|
|
328
|
+
setLocale: () => setLocale,
|
|
329
|
+
setRouteTransition: () => setRouteTransition,
|
|
330
|
+
setRoutes: () => setRoutes,
|
|
331
|
+
t: () => t
|
|
332
|
+
});
|
|
333
|
+
module.exports = __toCommonJS(plugins_exports);
|
|
334
|
+
|
|
335
|
+
// src/utils/sanitize.ts
|
|
336
|
+
function sanitize(value) {
|
|
337
|
+
return String(value).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
338
|
+
}
|
|
339
|
+
function sanitizeUrl(url) {
|
|
340
|
+
const trimmed = url.replace(/[\x00-\x20\x7f-\x9f]+/g, "").trim();
|
|
341
|
+
if (!trimmed) return "";
|
|
342
|
+
const lower = trimmed.toLowerCase();
|
|
343
|
+
if (lower.startsWith("javascript:") || lower.startsWith("data:") || lower.startsWith("vbscript:") || lower.startsWith("blob:")) {
|
|
344
|
+
return "";
|
|
345
|
+
}
|
|
346
|
+
return trimmed;
|
|
347
|
+
}
|
|
348
|
+
var URL_ATTRIBUTES = /* @__PURE__ */ new Set(["href", "src", "action", "formaction", "cite", "poster", "background", "srcset"]);
|
|
349
|
+
function isUrlAttribute(attr) {
|
|
350
|
+
return URL_ATTRIBUTES.has(attr);
|
|
351
|
+
}
|
|
352
|
+
function sanitizeAttribute(attr, value) {
|
|
353
|
+
if (isUrlAttribute(attr)) {
|
|
354
|
+
return sanitizeUrl(value);
|
|
355
|
+
}
|
|
356
|
+
return sanitize(value);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// src/reactivity/track.ts
|
|
360
|
+
var subscriberStack = [];
|
|
361
|
+
var currentSubscriber = null;
|
|
362
|
+
var signalSubscribers = /* @__PURE__ */ new WeakMap();
|
|
363
|
+
var SUBS = "__s";
|
|
364
|
+
var notifyDepth = 0;
|
|
365
|
+
var pendingQueue = [];
|
|
366
|
+
var pendingSet = /* @__PURE__ */ new Set();
|
|
367
|
+
var suspendDepth = 0;
|
|
368
|
+
var trackingSuspended = false;
|
|
369
|
+
function track(effectFn, subscriber) {
|
|
370
|
+
if (!subscriber) subscriber = effectFn;
|
|
371
|
+
cleanup(subscriber);
|
|
372
|
+
subscriberStack.push(subscriber);
|
|
373
|
+
currentSubscriber = subscriber;
|
|
374
|
+
effectFn();
|
|
375
|
+
subscriberStack.pop();
|
|
376
|
+
currentSubscriber = subscriberStack[subscriberStack.length - 1] || null;
|
|
377
|
+
return () => cleanup(subscriber);
|
|
378
|
+
}
|
|
379
|
+
function suspendTracking() {
|
|
380
|
+
if (suspendDepth === 0) {
|
|
381
|
+
subscriberStack.push(null);
|
|
382
|
+
currentSubscriber = null;
|
|
383
|
+
trackingSuspended = true;
|
|
384
|
+
}
|
|
385
|
+
suspendDepth++;
|
|
386
|
+
}
|
|
387
|
+
function resumeTracking() {
|
|
388
|
+
suspendDepth--;
|
|
389
|
+
if (suspendDepth === 0) {
|
|
390
|
+
subscriberStack.pop();
|
|
391
|
+
currentSubscriber = subscriberStack[subscriberStack.length - 1] || null;
|
|
392
|
+
trackingSuspended = false;
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
function recordDependency(signal2) {
|
|
396
|
+
if (!currentSubscriber) return;
|
|
397
|
+
let deps = currentSubscriber._deps;
|
|
398
|
+
if (!deps) {
|
|
399
|
+
deps = /* @__PURE__ */ new Set();
|
|
400
|
+
currentSubscriber._deps = deps;
|
|
401
|
+
}
|
|
402
|
+
if (!deps.has(signal2)) {
|
|
403
|
+
deps.add(signal2);
|
|
404
|
+
let subs = signal2[SUBS];
|
|
405
|
+
if (!subs) {
|
|
406
|
+
subs = /* @__PURE__ */ new Set();
|
|
407
|
+
signalSubscribers.set(signal2, subs);
|
|
408
|
+
signal2[SUBS] = subs;
|
|
409
|
+
}
|
|
410
|
+
subs.add(currentSubscriber);
|
|
411
|
+
if (subs.size === 1) {
|
|
412
|
+
signal2.__f = currentSubscriber;
|
|
413
|
+
} else if (signal2.__f !== void 0) {
|
|
414
|
+
signal2.__f = void 0;
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
function propagateDirty(sub2) {
|
|
419
|
+
sub2();
|
|
420
|
+
let sig = sub2._sig;
|
|
421
|
+
let suspended = false;
|
|
422
|
+
if (sig && sig._g) {
|
|
423
|
+
const sDeps = sub2._deps;
|
|
424
|
+
if (sDeps && sDeps.size === 1) {
|
|
425
|
+
suspendTracking();
|
|
426
|
+
suspended = true;
|
|
427
|
+
const s2 = sig;
|
|
428
|
+
s2._d = false;
|
|
429
|
+
s2._v = s2._g();
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
while (sig) {
|
|
433
|
+
const first = sig.__f;
|
|
434
|
+
if (first) {
|
|
435
|
+
if (first._c) {
|
|
436
|
+
const nSig = first._sig;
|
|
437
|
+
nSig._d = true;
|
|
438
|
+
if (suspended && nSig._g) {
|
|
439
|
+
const fDeps = first._deps;
|
|
440
|
+
if (fDeps && fDeps.size === 1) {
|
|
441
|
+
nSig._d = false;
|
|
442
|
+
nSig._v = nSig._g();
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
sig = nSig;
|
|
446
|
+
continue;
|
|
447
|
+
}
|
|
448
|
+
if (!pendingSet.has(first)) {
|
|
449
|
+
pendingSet.add(first);
|
|
450
|
+
pendingQueue.push(first);
|
|
451
|
+
}
|
|
452
|
+
break;
|
|
453
|
+
}
|
|
454
|
+
const subs = sig[SUBS];
|
|
455
|
+
if (!subs) break;
|
|
456
|
+
let nextSig;
|
|
457
|
+
for (const s2 of subs) {
|
|
458
|
+
if (s2._c) {
|
|
459
|
+
s2();
|
|
460
|
+
const nSig = s2._sig;
|
|
461
|
+
if (nSig && !nextSig) {
|
|
462
|
+
nextSig = nSig;
|
|
463
|
+
} else if (nSig) {
|
|
464
|
+
propagateDirty(s2);
|
|
465
|
+
}
|
|
466
|
+
} else if (!pendingSet.has(s2)) {
|
|
467
|
+
pendingSet.add(s2);
|
|
468
|
+
pendingQueue.push(s2);
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
sig = nextSig;
|
|
472
|
+
}
|
|
473
|
+
if (suspended) resumeTracking();
|
|
474
|
+
}
|
|
475
|
+
function notifySubscribers(signal2) {
|
|
476
|
+
const first = signal2.__f;
|
|
477
|
+
if (first) {
|
|
478
|
+
if (notifyDepth > 0) {
|
|
479
|
+
if (first._c) {
|
|
480
|
+
propagateDirty(first);
|
|
481
|
+
} else if (!pendingSet.has(first)) {
|
|
482
|
+
pendingSet.add(first);
|
|
483
|
+
pendingQueue.push(first);
|
|
484
|
+
}
|
|
485
|
+
return;
|
|
486
|
+
}
|
|
487
|
+
notifyDepth++;
|
|
488
|
+
try {
|
|
489
|
+
if (first._c) {
|
|
490
|
+
propagateDirty(first);
|
|
491
|
+
} else {
|
|
492
|
+
first();
|
|
493
|
+
}
|
|
494
|
+
let i2 = 0;
|
|
495
|
+
while (i2 < pendingQueue.length) {
|
|
496
|
+
pendingQueue[i2]();
|
|
497
|
+
i2++;
|
|
498
|
+
}
|
|
499
|
+
} finally {
|
|
500
|
+
pendingQueue.length = 0;
|
|
501
|
+
pendingSet.clear();
|
|
502
|
+
notifyDepth--;
|
|
503
|
+
}
|
|
504
|
+
return;
|
|
505
|
+
}
|
|
506
|
+
const subs = signal2[SUBS];
|
|
507
|
+
if (!subs || subs.size === 0) return;
|
|
508
|
+
if (notifyDepth > 0) {
|
|
509
|
+
for (const sub2 of subs) {
|
|
510
|
+
if (sub2._c) {
|
|
511
|
+
propagateDirty(sub2);
|
|
512
|
+
} else if (!pendingSet.has(sub2)) {
|
|
513
|
+
pendingSet.add(sub2);
|
|
514
|
+
pendingQueue.push(sub2);
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
return;
|
|
518
|
+
}
|
|
519
|
+
notifyDepth++;
|
|
520
|
+
try {
|
|
521
|
+
let directCount = 0;
|
|
522
|
+
for (const sub2 of subs) {
|
|
523
|
+
pendingQueue[directCount++] = sub2;
|
|
524
|
+
}
|
|
525
|
+
for (let i3 = 0; i3 < directCount; i3++) {
|
|
526
|
+
if (pendingQueue[i3]._c) {
|
|
527
|
+
propagateDirty(pendingQueue[i3]);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
for (let i3 = 0; i3 < directCount; i3++) {
|
|
531
|
+
if (!pendingQueue[i3]._c) {
|
|
532
|
+
if (!pendingSet.has(pendingQueue[i3])) {
|
|
533
|
+
pendingQueue[i3]();
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
let i2 = directCount;
|
|
538
|
+
while (i2 < pendingQueue.length) {
|
|
539
|
+
pendingQueue[i2]();
|
|
540
|
+
i2++;
|
|
541
|
+
}
|
|
542
|
+
} finally {
|
|
543
|
+
pendingQueue.length = 0;
|
|
544
|
+
pendingSet.clear();
|
|
545
|
+
notifyDepth--;
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
function cleanup(subscriber) {
|
|
549
|
+
const deps = subscriber._deps;
|
|
550
|
+
if (!deps || deps.size === 0) return;
|
|
551
|
+
for (const signal2 of deps) {
|
|
552
|
+
const subs = signal2[SUBS];
|
|
553
|
+
if (subs) {
|
|
554
|
+
subs.delete(subscriber);
|
|
555
|
+
if (signal2.__f === subscriber) {
|
|
556
|
+
signal2.__f = void 0;
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
deps.clear();
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
// src/reactivity/bindAttribute.ts
|
|
564
|
+
function bindAttribute(el, attr, getter) {
|
|
565
|
+
function commit() {
|
|
566
|
+
let value;
|
|
567
|
+
try {
|
|
568
|
+
value = getter();
|
|
569
|
+
} catch {
|
|
570
|
+
return;
|
|
571
|
+
}
|
|
572
|
+
if (typeof value === "boolean") {
|
|
573
|
+
if (attr in el && (attr === "checked" || attr === "disabled" || attr === "selected")) {
|
|
574
|
+
el[attr] = value;
|
|
575
|
+
} else if (value) {
|
|
576
|
+
el.setAttribute(attr, "");
|
|
577
|
+
} else {
|
|
578
|
+
el.removeAttribute(attr);
|
|
579
|
+
}
|
|
580
|
+
return;
|
|
581
|
+
}
|
|
582
|
+
const str = sanitizeAttribute(attr, String(value));
|
|
583
|
+
if ((attr === "value" || attr === "checked") && attr in el) {
|
|
584
|
+
el[attr] = attr === "checked" ? Boolean(value) : str;
|
|
585
|
+
} else {
|
|
586
|
+
el.setAttribute(attr, str);
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
const teardown = track(commit);
|
|
590
|
+
return teardown;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
// src/reactivity/bindChildNode.ts
|
|
594
|
+
function bindChildNode(placeholder, getter) {
|
|
595
|
+
let lastNodes = [];
|
|
596
|
+
function commit() {
|
|
597
|
+
let result;
|
|
598
|
+
try {
|
|
599
|
+
result = getter();
|
|
600
|
+
} catch {
|
|
601
|
+
return;
|
|
602
|
+
}
|
|
603
|
+
for (const node of lastNodes) {
|
|
604
|
+
node.parentNode?.removeChild(node);
|
|
605
|
+
}
|
|
606
|
+
lastNodes = [];
|
|
607
|
+
if (result == null) return;
|
|
608
|
+
const parent = placeholder.parentNode;
|
|
609
|
+
if (!parent) return;
|
|
610
|
+
const anchor = placeholder.nextSibling;
|
|
611
|
+
const newNodes = [];
|
|
612
|
+
const insertItem = (item) => {
|
|
613
|
+
const node = item instanceof Node ? item : document.createTextNode(String(item));
|
|
614
|
+
parent.insertBefore(node, anchor);
|
|
615
|
+
newNodes.push(node);
|
|
616
|
+
};
|
|
617
|
+
if (Array.isArray(result)) {
|
|
618
|
+
for (const item of result) insertItem(item);
|
|
619
|
+
} else {
|
|
620
|
+
insertItem(result);
|
|
621
|
+
}
|
|
622
|
+
lastNodes = newNodes;
|
|
623
|
+
}
|
|
624
|
+
return track(commit);
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
// src/core/rendering/dispose.ts
|
|
628
|
+
var elementDisposers = /* @__PURE__ */ new WeakMap();
|
|
629
|
+
var activeBindingCount = 0;
|
|
630
|
+
function registerDisposer(node, teardown) {
|
|
631
|
+
let disposers = elementDisposers.get(node);
|
|
632
|
+
if (!disposers) {
|
|
633
|
+
disposers = [];
|
|
634
|
+
elementDisposers.set(node, disposers);
|
|
635
|
+
}
|
|
636
|
+
disposers.push(teardown);
|
|
637
|
+
activeBindingCount++;
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
// src/core/rendering/tagFactory.ts
|
|
641
|
+
var SVG_NS = "http://www.w3.org/2000/svg";
|
|
642
|
+
var kebabCache = /* @__PURE__ */ new Map();
|
|
643
|
+
function toKebab(prop) {
|
|
644
|
+
let cached = kebabCache.get(prop);
|
|
645
|
+
if (cached !== void 0) return cached;
|
|
646
|
+
cached = prop.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`);
|
|
647
|
+
kebabCache.set(prop, cached);
|
|
648
|
+
return cached;
|
|
649
|
+
}
|
|
650
|
+
function applyStyle(el, style2) {
|
|
651
|
+
if (!style2) return;
|
|
652
|
+
if (typeof style2 === "function") {
|
|
653
|
+
const teardown = track(() => {
|
|
654
|
+
el.setAttribute("style", style2());
|
|
655
|
+
});
|
|
656
|
+
registerDisposer(el, teardown);
|
|
657
|
+
return;
|
|
658
|
+
}
|
|
659
|
+
if (typeof style2 === "string") {
|
|
660
|
+
el.setAttribute("style", style2);
|
|
661
|
+
return;
|
|
662
|
+
}
|
|
663
|
+
const htmlEl = el;
|
|
664
|
+
for (const prop in style2) {
|
|
665
|
+
const val = style2[prop];
|
|
666
|
+
const name = toKebab(prop);
|
|
667
|
+
if (typeof val === "function") {
|
|
668
|
+
const getter = val;
|
|
669
|
+
const teardown = track(() => {
|
|
670
|
+
htmlEl.style.setProperty(name, String(getter()));
|
|
671
|
+
});
|
|
672
|
+
registerDisposer(el, teardown);
|
|
673
|
+
} else {
|
|
674
|
+
htmlEl.style.setProperty(name, String(val));
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
function applyClass(el, cls) {
|
|
679
|
+
if (cls == null) return;
|
|
680
|
+
if (typeof cls === "string") {
|
|
681
|
+
el.setAttribute("class", cls);
|
|
682
|
+
return;
|
|
683
|
+
}
|
|
684
|
+
if (typeof cls === "function") {
|
|
685
|
+
const getter = cls;
|
|
686
|
+
const teardown = track(() => {
|
|
687
|
+
el.setAttribute("class", getter());
|
|
688
|
+
});
|
|
689
|
+
registerDisposer(el, teardown);
|
|
690
|
+
return;
|
|
691
|
+
}
|
|
692
|
+
if (typeof cls === "object") {
|
|
693
|
+
const obj = cls;
|
|
694
|
+
let hasReactive = false;
|
|
695
|
+
for (const name in obj) {
|
|
696
|
+
if (typeof obj[name] === "function") {
|
|
697
|
+
hasReactive = true;
|
|
698
|
+
break;
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
if (hasReactive) {
|
|
702
|
+
const update = () => {
|
|
703
|
+
let result = "";
|
|
704
|
+
for (const name in obj) {
|
|
705
|
+
const val = obj[name];
|
|
706
|
+
const active = typeof val === "function" ? val() : val;
|
|
707
|
+
if (active) result = result ? `${result} ${name}` : name;
|
|
708
|
+
}
|
|
709
|
+
el.setAttribute("class", result);
|
|
710
|
+
};
|
|
711
|
+
const teardown = track(update);
|
|
712
|
+
registerDisposer(el, teardown);
|
|
713
|
+
} else {
|
|
714
|
+
let result = "";
|
|
715
|
+
for (const name in obj) {
|
|
716
|
+
if (obj[name]) result = result ? `${result} ${name}` : name;
|
|
717
|
+
}
|
|
718
|
+
el.setAttribute("class", result);
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
function renderChild(child) {
|
|
723
|
+
if (child == null) {
|
|
724
|
+
return document.createTextNode("");
|
|
725
|
+
}
|
|
726
|
+
if (child instanceof Node) {
|
|
727
|
+
return child;
|
|
728
|
+
}
|
|
729
|
+
return document.createTextNode(String(child));
|
|
730
|
+
}
|
|
731
|
+
function appendOneChild(el, child) {
|
|
732
|
+
if (typeof child === "function") {
|
|
733
|
+
const placeholder = document.createComment("bind:child");
|
|
734
|
+
el.appendChild(placeholder);
|
|
735
|
+
const teardown = bindChildNode(placeholder, child);
|
|
736
|
+
registerDisposer(el, teardown);
|
|
737
|
+
} else {
|
|
738
|
+
el.appendChild(renderChild(child));
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
function appendChildren(el, nodes) {
|
|
742
|
+
if (Array.isArray(nodes)) {
|
|
743
|
+
for (let i2 = 0; i2 < nodes.length; i2++) {
|
|
744
|
+
const c = nodes[i2];
|
|
745
|
+
if (Array.isArray(c)) {
|
|
746
|
+
for (let j = 0; j < c.length; j++) {
|
|
747
|
+
appendOneChild(el, c[j]);
|
|
748
|
+
}
|
|
749
|
+
} else {
|
|
750
|
+
appendOneChild(el, c);
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
} else {
|
|
754
|
+
appendOneChild(el, nodes);
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
function isTagProps(value) {
|
|
758
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) && !(value instanceof Node);
|
|
759
|
+
}
|
|
760
|
+
var tagFactory = (tag, ns) => (first, second) => {
|
|
761
|
+
let props;
|
|
762
|
+
if (first === void 0) {
|
|
763
|
+
props = {};
|
|
764
|
+
} else if (isTagProps(first)) {
|
|
765
|
+
props = first;
|
|
766
|
+
} else if (second !== void 0) {
|
|
767
|
+
props = { class: first, nodes: second };
|
|
768
|
+
} else {
|
|
769
|
+
props = { nodes: first };
|
|
770
|
+
}
|
|
771
|
+
const el = ns ? document.createElementNS(ns, tag) : document.createElement(tag);
|
|
772
|
+
for (const key in props) {
|
|
773
|
+
const value = props[key];
|
|
774
|
+
if (value == null) continue;
|
|
775
|
+
switch (key) {
|
|
776
|
+
case "id":
|
|
777
|
+
el.id = value;
|
|
778
|
+
break;
|
|
779
|
+
case "class":
|
|
780
|
+
applyClass(el, value);
|
|
781
|
+
break;
|
|
782
|
+
case "style":
|
|
783
|
+
applyStyle(el, value);
|
|
784
|
+
break;
|
|
785
|
+
case "ref":
|
|
786
|
+
if (value && typeof value === "object" && "current" in value) {
|
|
787
|
+
value.current = el;
|
|
788
|
+
}
|
|
789
|
+
break;
|
|
790
|
+
case "on": {
|
|
791
|
+
const handlers = value;
|
|
792
|
+
const eventNames = [];
|
|
793
|
+
for (const ev in handlers) {
|
|
794
|
+
el.addEventListener(ev, handlers[ev]);
|
|
795
|
+
eventNames.push(ev);
|
|
796
|
+
}
|
|
797
|
+
if (eventNames.length) {
|
|
798
|
+
el.__sibu_events__ = eventNames;
|
|
799
|
+
}
|
|
800
|
+
break;
|
|
801
|
+
}
|
|
802
|
+
case "nodes":
|
|
803
|
+
appendChildren(el, value);
|
|
804
|
+
break;
|
|
805
|
+
default:
|
|
806
|
+
if (key.toLowerCase().startsWith("on")) break;
|
|
807
|
+
if (typeof value === "function") {
|
|
808
|
+
const teardown = bindAttribute(el, key, value);
|
|
809
|
+
registerDisposer(el, teardown);
|
|
810
|
+
} else if (typeof value === "boolean") {
|
|
811
|
+
if (value) el.setAttribute(key, "");
|
|
812
|
+
else el.removeAttribute(key);
|
|
813
|
+
} else {
|
|
814
|
+
el.setAttribute(key, sanitizeAttribute(key, String(value)));
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
return el;
|
|
819
|
+
};
|
|
820
|
+
|
|
821
|
+
// src/core/rendering/html.ts
|
|
822
|
+
var html = tagFactory("html");
|
|
823
|
+
var head = tagFactory("head");
|
|
824
|
+
var body = tagFactory("body");
|
|
825
|
+
var title = tagFactory("title");
|
|
826
|
+
var div = tagFactory("div");
|
|
827
|
+
var span = tagFactory("span");
|
|
828
|
+
var section = tagFactory("section");
|
|
829
|
+
var article = tagFactory("article");
|
|
830
|
+
var header = tagFactory("header");
|
|
831
|
+
var footer = tagFactory("footer");
|
|
832
|
+
var nav = tagFactory("nav");
|
|
833
|
+
var main = tagFactory("main");
|
|
834
|
+
var aside = tagFactory("aside");
|
|
835
|
+
var address = tagFactory("address");
|
|
836
|
+
var p = tagFactory("p");
|
|
837
|
+
var h1 = tagFactory("h1");
|
|
838
|
+
var h2 = tagFactory("h2");
|
|
839
|
+
var h3 = tagFactory("h3");
|
|
840
|
+
var h4 = tagFactory("h4");
|
|
841
|
+
var h5 = tagFactory("h5");
|
|
842
|
+
var h6 = tagFactory("h6");
|
|
843
|
+
var blockquote = tagFactory("blockquote");
|
|
844
|
+
var dd = tagFactory("dd");
|
|
845
|
+
var dl = tagFactory("dl");
|
|
846
|
+
var dt = tagFactory("dt");
|
|
847
|
+
var figcaption = tagFactory("figcaption");
|
|
848
|
+
var figure = tagFactory("figure");
|
|
849
|
+
var hr = tagFactory("hr");
|
|
850
|
+
var li = tagFactory("li");
|
|
851
|
+
var ol = tagFactory("ol");
|
|
852
|
+
var ul = tagFactory("ul");
|
|
853
|
+
var pre = tagFactory("pre");
|
|
854
|
+
var a = tagFactory("a");
|
|
855
|
+
var abbr = tagFactory("abbr");
|
|
856
|
+
var b = tagFactory("b");
|
|
857
|
+
var bdi = tagFactory("bdi");
|
|
858
|
+
var bdo = tagFactory("bdo");
|
|
859
|
+
var br = tagFactory("br");
|
|
860
|
+
var cite = tagFactory("cite");
|
|
861
|
+
var code = tagFactory("code");
|
|
862
|
+
var data = tagFactory("data");
|
|
863
|
+
var dfn = tagFactory("dfn");
|
|
864
|
+
var em = tagFactory("em");
|
|
865
|
+
var i = tagFactory("i");
|
|
866
|
+
var kbd = tagFactory("kbd");
|
|
867
|
+
var mark = tagFactory("mark");
|
|
868
|
+
var q = tagFactory("q");
|
|
869
|
+
var rp = tagFactory("rp");
|
|
870
|
+
var rt = tagFactory("rt");
|
|
871
|
+
var ruby = tagFactory("ruby");
|
|
872
|
+
var s = tagFactory("s");
|
|
873
|
+
var samp = tagFactory("samp");
|
|
874
|
+
var small = tagFactory("small");
|
|
875
|
+
var strong = tagFactory("strong");
|
|
876
|
+
var sub = tagFactory("sub");
|
|
877
|
+
var sup = tagFactory("sup");
|
|
878
|
+
var time = tagFactory("time");
|
|
879
|
+
var u = tagFactory("u");
|
|
880
|
+
var var_ = tagFactory("var");
|
|
881
|
+
var area = tagFactory("area");
|
|
882
|
+
var audio = tagFactory("audio");
|
|
883
|
+
var img = tagFactory("img");
|
|
884
|
+
var map = tagFactory("map");
|
|
885
|
+
var track2 = tagFactory("track");
|
|
886
|
+
var video = tagFactory("video");
|
|
887
|
+
var embed = tagFactory("embed");
|
|
888
|
+
var iframe = tagFactory("iframe");
|
|
889
|
+
var object = tagFactory("object");
|
|
890
|
+
var param = tagFactory("param");
|
|
891
|
+
var picture = tagFactory("picture");
|
|
892
|
+
var portal = tagFactory("portal");
|
|
893
|
+
var source = tagFactory("source");
|
|
894
|
+
var svg = tagFactory("svg", SVG_NS);
|
|
895
|
+
var math = tagFactory("math");
|
|
896
|
+
var canvas = tagFactory("canvas");
|
|
897
|
+
var noscript = tagFactory("noscript");
|
|
898
|
+
var script = tagFactory("script");
|
|
899
|
+
var del = tagFactory("del");
|
|
900
|
+
var ins = tagFactory("ins");
|
|
901
|
+
var caption = tagFactory("caption");
|
|
902
|
+
var col = tagFactory("col");
|
|
903
|
+
var colgroup = tagFactory("colgroup");
|
|
904
|
+
var table = tagFactory("table");
|
|
905
|
+
var tbody = tagFactory("tbody");
|
|
906
|
+
var td = tagFactory("td");
|
|
907
|
+
var tfoot = tagFactory("tfoot");
|
|
908
|
+
var th = tagFactory("th");
|
|
909
|
+
var thead = tagFactory("thead");
|
|
910
|
+
var tr = tagFactory("tr");
|
|
911
|
+
var button = tagFactory("button");
|
|
912
|
+
var datalist = tagFactory("datalist");
|
|
913
|
+
var fieldset = tagFactory("fieldset");
|
|
914
|
+
var form = tagFactory("form");
|
|
915
|
+
var input = tagFactory("input");
|
|
916
|
+
var label = tagFactory("label");
|
|
917
|
+
var legend = tagFactory("legend");
|
|
918
|
+
var meter = tagFactory("meter");
|
|
919
|
+
var optgroup = tagFactory("optgroup");
|
|
920
|
+
var option = tagFactory("option");
|
|
921
|
+
var output = tagFactory("output");
|
|
922
|
+
var progress = tagFactory("progress");
|
|
923
|
+
var select = tagFactory("select");
|
|
924
|
+
var textarea = tagFactory("textarea");
|
|
925
|
+
var details = tagFactory("details");
|
|
926
|
+
var dialog = tagFactory("dialog");
|
|
927
|
+
var menu = tagFactory("menu");
|
|
928
|
+
var summary = tagFactory("summary");
|
|
929
|
+
var slot = tagFactory("slot");
|
|
930
|
+
var template = tagFactory("template");
|
|
931
|
+
var base = tagFactory("base");
|
|
932
|
+
var link = tagFactory("link");
|
|
933
|
+
var meta = tagFactory("meta");
|
|
934
|
+
var style = tagFactory("style");
|
|
935
|
+
var circle = tagFactory("circle", SVG_NS);
|
|
936
|
+
var ellipse = tagFactory("ellipse", SVG_NS);
|
|
937
|
+
var g = tagFactory("g", SVG_NS);
|
|
938
|
+
var line = tagFactory("line", SVG_NS);
|
|
939
|
+
var path = tagFactory("path", SVG_NS);
|
|
940
|
+
var polygon = tagFactory("polygon", SVG_NS);
|
|
941
|
+
var polyline = tagFactory("polyline", SVG_NS);
|
|
942
|
+
var rect = tagFactory("rect", SVG_NS);
|
|
943
|
+
var text = tagFactory("text", SVG_NS);
|
|
944
|
+
var tspan = tagFactory("tspan", SVG_NS);
|
|
945
|
+
var defs = tagFactory("defs", SVG_NS);
|
|
946
|
+
var clipPath = tagFactory("clipPath", SVG_NS);
|
|
947
|
+
var mask = tagFactory("mask", SVG_NS);
|
|
948
|
+
var pattern = tagFactory("pattern", SVG_NS);
|
|
949
|
+
var linearGradient = tagFactory("linearGradient", SVG_NS);
|
|
950
|
+
var radialGradient = tagFactory("radialGradient", SVG_NS);
|
|
951
|
+
var stop = tagFactory("stop", SVG_NS);
|
|
952
|
+
var use = tagFactory("use", SVG_NS);
|
|
953
|
+
var symbol = tagFactory("symbol", SVG_NS);
|
|
954
|
+
var marker = tagFactory("marker", SVG_NS);
|
|
955
|
+
var center = tagFactory("center");
|
|
956
|
+
var font = tagFactory("font");
|
|
957
|
+
var marquee = tagFactory("marquee");
|
|
958
|
+
|
|
959
|
+
// src/reactivity/batch.ts
|
|
960
|
+
var batchDepth = 0;
|
|
961
|
+
var pendingSignals = /* @__PURE__ */ new Set();
|
|
962
|
+
function enqueueBatchedSignal(signal2) {
|
|
963
|
+
if (batchDepth === 0) return false;
|
|
964
|
+
pendingSignals.add(signal2);
|
|
965
|
+
return true;
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
// src/core/signals/signal.ts
|
|
969
|
+
function signal(initial, options) {
|
|
970
|
+
const state = { value: initial };
|
|
971
|
+
const debugName = options?.name;
|
|
972
|
+
if (debugName) {
|
|
973
|
+
state.__name = debugName;
|
|
974
|
+
}
|
|
975
|
+
function get() {
|
|
976
|
+
recordDependency(state);
|
|
977
|
+
return state.value;
|
|
978
|
+
}
|
|
979
|
+
get.__signal = state;
|
|
980
|
+
if (debugName) get.__name = debugName;
|
|
981
|
+
function set(next) {
|
|
982
|
+
const newValue = typeof next === "function" ? next(state.value) : next;
|
|
983
|
+
if (Object.is(newValue, state.value)) return;
|
|
984
|
+
const oldValue = state.value;
|
|
985
|
+
state.value = newValue;
|
|
986
|
+
const hook2 = globalThis.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
987
|
+
if (hook2) hook2.emit("signal:update", { signal: state, name: debugName, oldValue, newValue });
|
|
988
|
+
if (!enqueueBatchedSignal(state)) {
|
|
989
|
+
notifySubscribers(state);
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
const hook = globalThis.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
993
|
+
if (hook) hook.emit("signal:create", { signal: state, name: debugName, getter: get, initial });
|
|
994
|
+
return [get, set];
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
// src/plugins/i18n.ts
|
|
998
|
+
var [currentLocale, setLocaleInternal] = signal("en");
|
|
999
|
+
var locales = {};
|
|
1000
|
+
function setLocale(locale) {
|
|
1001
|
+
setLocaleInternal(locale);
|
|
1002
|
+
}
|
|
1003
|
+
function getLocale() {
|
|
1004
|
+
return currentLocale();
|
|
1005
|
+
}
|
|
1006
|
+
function registerTranslations(locale, messages) {
|
|
1007
|
+
locales[locale] = { ...locales[locale], ...messages };
|
|
1008
|
+
}
|
|
1009
|
+
function t(key, params) {
|
|
1010
|
+
const locale = currentLocale();
|
|
1011
|
+
const message = locales[locale]?.[key] || key;
|
|
1012
|
+
return params ? message.replace(/\{(\w+)\}/g, (_, p2) => String(params[p2] ?? "")) : message;
|
|
1013
|
+
}
|
|
1014
|
+
function Trans(key, params) {
|
|
1015
|
+
return span({
|
|
1016
|
+
nodes: () => t(key, params)
|
|
1017
|
+
});
|
|
1018
|
+
}
|
|
1019
|
+
function hasTranslation(key) {
|
|
1020
|
+
const locale = currentLocale();
|
|
1021
|
+
return key in (locales[locale] || {});
|
|
1022
|
+
}
|
|
1023
|
+
function getAvailableLocales() {
|
|
1024
|
+
return Object.keys(locales);
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
// src/plugins/router.ts
|
|
1028
|
+
var LRUCache = class {
|
|
1029
|
+
constructor(maxSize = 100) {
|
|
1030
|
+
this.cache = /* @__PURE__ */ new Map();
|
|
1031
|
+
this.maxSize = Math.max(1, maxSize);
|
|
1032
|
+
}
|
|
1033
|
+
get(key) {
|
|
1034
|
+
const value = this.cache.get(key);
|
|
1035
|
+
if (value !== void 0) {
|
|
1036
|
+
this.cache.delete(key);
|
|
1037
|
+
this.cache.set(key, value);
|
|
1038
|
+
}
|
|
1039
|
+
return value;
|
|
1040
|
+
}
|
|
1041
|
+
set(key, value) {
|
|
1042
|
+
if (this.cache.has(key)) {
|
|
1043
|
+
this.cache.delete(key);
|
|
1044
|
+
} else if (this.cache.size >= this.maxSize) {
|
|
1045
|
+
const firstKey = this.cache.keys().next().value;
|
|
1046
|
+
if (firstKey !== void 0) {
|
|
1047
|
+
this.cache.delete(firstKey);
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
this.cache.set(key, value);
|
|
1051
|
+
}
|
|
1052
|
+
has(key) {
|
|
1053
|
+
return this.cache.has(key);
|
|
1054
|
+
}
|
|
1055
|
+
delete(key) {
|
|
1056
|
+
return this.cache.delete(key);
|
|
1057
|
+
}
|
|
1058
|
+
clear() {
|
|
1059
|
+
this.cache.clear();
|
|
1060
|
+
}
|
|
1061
|
+
get size() {
|
|
1062
|
+
return this.cache.size;
|
|
1063
|
+
}
|
|
1064
|
+
};
|
|
1065
|
+
var NavigationController = class {
|
|
1066
|
+
constructor() {
|
|
1067
|
+
this.currentController = null;
|
|
1068
|
+
}
|
|
1069
|
+
async navigate(navigationFn) {
|
|
1070
|
+
if (this.currentController) {
|
|
1071
|
+
this.currentController.abort();
|
|
1072
|
+
}
|
|
1073
|
+
this.currentController = new AbortController();
|
|
1074
|
+
const signal2 = this.currentController.signal;
|
|
1075
|
+
try {
|
|
1076
|
+
await navigationFn(signal2);
|
|
1077
|
+
} catch (error) {
|
|
1078
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
1079
|
+
return;
|
|
1080
|
+
}
|
|
1081
|
+
throw error;
|
|
1082
|
+
} finally {
|
|
1083
|
+
if (this.currentController?.signal === signal2) {
|
|
1084
|
+
this.currentController = null;
|
|
1085
|
+
}
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
abort() {
|
|
1089
|
+
if (this.currentController) {
|
|
1090
|
+
this.currentController.abort();
|
|
1091
|
+
this.currentController = null;
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
get isNavigating() {
|
|
1095
|
+
return this.currentController !== null;
|
|
1096
|
+
}
|
|
1097
|
+
};
|
|
1098
|
+
var RouteMatcher = class {
|
|
1099
|
+
constructor(routes) {
|
|
1100
|
+
this.routeTrie = /* @__PURE__ */ new Map();
|
|
1101
|
+
this.namedRoutes = /* @__PURE__ */ new Map();
|
|
1102
|
+
this.compiledPatterns = new LRUCache(50);
|
|
1103
|
+
this.buildIndex(routes);
|
|
1104
|
+
}
|
|
1105
|
+
buildIndex(routes, parentPath = "") {
|
|
1106
|
+
for (const route2 of routes) {
|
|
1107
|
+
const fullPath = parentPath + route2.path;
|
|
1108
|
+
this.routeTrie.set(fullPath, route2);
|
|
1109
|
+
if (route2.name) {
|
|
1110
|
+
this.namedRoutes.set(route2.name, route2);
|
|
1111
|
+
}
|
|
1112
|
+
if (route2.alias) {
|
|
1113
|
+
const aliases = Array.isArray(route2.alias) ? route2.alias : [route2.alias];
|
|
1114
|
+
for (const alias of aliases) {
|
|
1115
|
+
this.routeTrie.set(parentPath + alias, route2);
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
if (route2.children?.length) {
|
|
1119
|
+
this.buildIndex(route2.children, fullPath);
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
match(path2) {
|
|
1124
|
+
const exactMatch = this.routeTrie.get(path2);
|
|
1125
|
+
if (exactMatch) {
|
|
1126
|
+
return { route: exactMatch, params: {}, matched: [exactMatch] };
|
|
1127
|
+
}
|
|
1128
|
+
for (const [routePath, route2] of this.routeTrie) {
|
|
1129
|
+
const match = this.matchPattern(path2, routePath);
|
|
1130
|
+
if (match) {
|
|
1131
|
+
return { route: route2, params: match.params, matched: [route2] };
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
return null;
|
|
1135
|
+
}
|
|
1136
|
+
findByName(name) {
|
|
1137
|
+
return this.namedRoutes.get(name) || null;
|
|
1138
|
+
}
|
|
1139
|
+
matchPattern(path2, routePath) {
|
|
1140
|
+
if (routePath === "*" || routePath.endsWith("/*")) {
|
|
1141
|
+
const basePath = routePath.slice(0, -2);
|
|
1142
|
+
if (path2.startsWith(basePath)) {
|
|
1143
|
+
return { params: { pathMatch: path2.slice(basePath.length) } };
|
|
1144
|
+
}
|
|
1145
|
+
return null;
|
|
1146
|
+
}
|
|
1147
|
+
let compiled = this.compiledPatterns.get(routePath);
|
|
1148
|
+
if (!compiled) {
|
|
1149
|
+
compiled = this.compileRoute(routePath);
|
|
1150
|
+
this.compiledPatterns.set(routePath, compiled);
|
|
1151
|
+
}
|
|
1152
|
+
const match = path2.match(compiled.regex);
|
|
1153
|
+
if (match) {
|
|
1154
|
+
const params = {};
|
|
1155
|
+
compiled.keys.forEach((key, i2) => {
|
|
1156
|
+
if (match[i2 + 1] !== void 0) {
|
|
1157
|
+
params[key] = decodeURIComponent(match[i2 + 1]);
|
|
1158
|
+
}
|
|
1159
|
+
});
|
|
1160
|
+
return { params };
|
|
1161
|
+
}
|
|
1162
|
+
return null;
|
|
1163
|
+
}
|
|
1164
|
+
compileRoute(routePath) {
|
|
1165
|
+
const keys = [];
|
|
1166
|
+
const escapeRegex = (s2) => s2.replace(/[.+*?^${}()|[\]\\]/g, "\\$&");
|
|
1167
|
+
const parts = routePath.split(/(\/:[^/]+\??)/);
|
|
1168
|
+
let pattern2 = "";
|
|
1169
|
+
for (const part of parts) {
|
|
1170
|
+
if (part.startsWith("/:")) {
|
|
1171
|
+
if (part.endsWith("?")) {
|
|
1172
|
+
keys.push(part.slice(2, -1));
|
|
1173
|
+
pattern2 += "(?:/([^/]+))?";
|
|
1174
|
+
} else {
|
|
1175
|
+
keys.push(part.slice(2));
|
|
1176
|
+
pattern2 += "/([^/]+)";
|
|
1177
|
+
}
|
|
1178
|
+
} else {
|
|
1179
|
+
pattern2 += escapeRegex(part);
|
|
1180
|
+
}
|
|
1181
|
+
}
|
|
1182
|
+
return {
|
|
1183
|
+
regex: new RegExp(`^${pattern2}$`),
|
|
1184
|
+
keys
|
|
1185
|
+
};
|
|
1186
|
+
}
|
|
1187
|
+
rebuild(routes) {
|
|
1188
|
+
this.routeTrie.clear();
|
|
1189
|
+
this.namedRoutes.clear();
|
|
1190
|
+
this.compiledPatterns.clear();
|
|
1191
|
+
this.buildIndex(routes);
|
|
1192
|
+
}
|
|
1193
|
+
addRoute(route2, parentPath = "") {
|
|
1194
|
+
const fullPath = parentPath + route2.path;
|
|
1195
|
+
this.routeTrie.set(fullPath, route2);
|
|
1196
|
+
if (route2.name) {
|
|
1197
|
+
this.namedRoutes.set(route2.name, route2);
|
|
1198
|
+
}
|
|
1199
|
+
if (route2.children?.length) {
|
|
1200
|
+
this.buildIndex(route2.children, fullPath);
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
1203
|
+
removeRoute(path2) {
|
|
1204
|
+
this.routeTrie.delete(path2);
|
|
1205
|
+
this.compiledPatterns.clear();
|
|
1206
|
+
for (const [name, route2] of this.namedRoutes) {
|
|
1207
|
+
if (route2.path === path2) {
|
|
1208
|
+
this.namedRoutes.delete(name);
|
|
1209
|
+
break;
|
|
1210
|
+
}
|
|
1211
|
+
}
|
|
1212
|
+
}
|
|
1213
|
+
};
|
|
1214
|
+
var GuardManager = class {
|
|
1215
|
+
constructor(timeout = 5e3) {
|
|
1216
|
+
this.beforeEachGuards = [];
|
|
1217
|
+
this.beforeResolveGuards = [];
|
|
1218
|
+
this.afterEachHooks = [];
|
|
1219
|
+
this.timeout = timeout;
|
|
1220
|
+
}
|
|
1221
|
+
async runBeforeEach(to, from, signal2) {
|
|
1222
|
+
for (const guard of this.beforeEachGuards) {
|
|
1223
|
+
if (signal2.aborted) throw new Error("Navigation aborted");
|
|
1224
|
+
const result = await this.runGuard(guard, to, from, signal2);
|
|
1225
|
+
if (result !== true) return result;
|
|
1226
|
+
}
|
|
1227
|
+
return true;
|
|
1228
|
+
}
|
|
1229
|
+
async runBeforeResolve(to, from, signal2) {
|
|
1230
|
+
for (const guard of this.beforeResolveGuards) {
|
|
1231
|
+
if (signal2.aborted) throw new Error("Navigation aborted");
|
|
1232
|
+
const result = await this.runGuard(guard, to, from, signal2);
|
|
1233
|
+
if (result !== true) return result;
|
|
1234
|
+
}
|
|
1235
|
+
return true;
|
|
1236
|
+
}
|
|
1237
|
+
runAfterEach(to, from) {
|
|
1238
|
+
for (const hook of this.afterEachHooks) {
|
|
1239
|
+
try {
|
|
1240
|
+
hook(to, from);
|
|
1241
|
+
} catch (error) {
|
|
1242
|
+
console.error("[Router] AfterEach hook error:", error);
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
runGuard(guard, to, from, signal2) {
|
|
1247
|
+
return new Promise((resolve, reject) => {
|
|
1248
|
+
if (signal2.aborted) {
|
|
1249
|
+
reject(new Error("Navigation aborted"));
|
|
1250
|
+
return;
|
|
1251
|
+
}
|
|
1252
|
+
let resolved = false;
|
|
1253
|
+
const next = (result) => {
|
|
1254
|
+
if (resolved || signal2.aborted) return;
|
|
1255
|
+
resolved = true;
|
|
1256
|
+
if (result instanceof Error) {
|
|
1257
|
+
reject(result);
|
|
1258
|
+
} else if (result === false) {
|
|
1259
|
+
resolve(false);
|
|
1260
|
+
} else if (typeof result === "string") {
|
|
1261
|
+
resolve(result);
|
|
1262
|
+
} else {
|
|
1263
|
+
resolve(true);
|
|
1264
|
+
}
|
|
1265
|
+
};
|
|
1266
|
+
const abortHandler = () => {
|
|
1267
|
+
if (!resolved) {
|
|
1268
|
+
resolved = true;
|
|
1269
|
+
reject(new Error("Navigation aborted"));
|
|
1270
|
+
}
|
|
1271
|
+
};
|
|
1272
|
+
signal2.addEventListener("abort", abortHandler);
|
|
1273
|
+
const timeoutId = setTimeout(() => {
|
|
1274
|
+
if (!resolved) {
|
|
1275
|
+
resolved = true;
|
|
1276
|
+
signal2.removeEventListener("abort", abortHandler);
|
|
1277
|
+
reject(new Error("Guard timeout"));
|
|
1278
|
+
}
|
|
1279
|
+
}, this.timeout);
|
|
1280
|
+
try {
|
|
1281
|
+
guard(to, from, next);
|
|
1282
|
+
} catch (error) {
|
|
1283
|
+
clearTimeout(timeoutId);
|
|
1284
|
+
signal2.removeEventListener("abort", abortHandler);
|
|
1285
|
+
if (!resolved) {
|
|
1286
|
+
resolved = true;
|
|
1287
|
+
reject(error instanceof Error ? error : new Error(String(error)));
|
|
1288
|
+
}
|
|
1289
|
+
}
|
|
1290
|
+
Promise.resolve().then(() => {
|
|
1291
|
+
if (resolved) {
|
|
1292
|
+
clearTimeout(timeoutId);
|
|
1293
|
+
signal2.removeEventListener("abort", abortHandler);
|
|
1294
|
+
}
|
|
1295
|
+
});
|
|
1296
|
+
});
|
|
1297
|
+
}
|
|
1298
|
+
addBeforeEach(guard) {
|
|
1299
|
+
this.beforeEachGuards.push(guard);
|
|
1300
|
+
return () => {
|
|
1301
|
+
const index = this.beforeEachGuards.indexOf(guard);
|
|
1302
|
+
if (index > -1) this.beforeEachGuards.splice(index, 1);
|
|
1303
|
+
};
|
|
1304
|
+
}
|
|
1305
|
+
addBeforeResolve(guard) {
|
|
1306
|
+
this.beforeResolveGuards.push(guard);
|
|
1307
|
+
return () => {
|
|
1308
|
+
const index = this.beforeResolveGuards.indexOf(guard);
|
|
1309
|
+
if (index > -1) this.beforeResolveGuards.splice(index, 1);
|
|
1310
|
+
};
|
|
1311
|
+
}
|
|
1312
|
+
addAfterEach(hook) {
|
|
1313
|
+
this.afterEachHooks.push(hook);
|
|
1314
|
+
return () => {
|
|
1315
|
+
const index = this.afterEachHooks.indexOf(hook);
|
|
1316
|
+
if (index > -1) this.afterEachHooks.splice(index, 1);
|
|
1317
|
+
};
|
|
1318
|
+
}
|
|
1319
|
+
clear() {
|
|
1320
|
+
this.beforeEachGuards = [];
|
|
1321
|
+
this.beforeResolveGuards = [];
|
|
1322
|
+
this.afterEachHooks = [];
|
|
1323
|
+
}
|
|
1324
|
+
};
|
|
1325
|
+
var ComponentLoader = class {
|
|
1326
|
+
constructor(cacheSize = 50, retryDelay = 1e3) {
|
|
1327
|
+
this.errorCache = /* @__PURE__ */ new Map();
|
|
1328
|
+
this.loadingPromises = /* @__PURE__ */ new Map();
|
|
1329
|
+
this.componentCache = new LRUCache(cacheSize);
|
|
1330
|
+
this.retryDelay = retryDelay;
|
|
1331
|
+
}
|
|
1332
|
+
async loadComponent(route2, routePath) {
|
|
1333
|
+
if (!("component" in route2)) {
|
|
1334
|
+
throw new Error(`Route ${routePath} does not have a component`);
|
|
1335
|
+
}
|
|
1336
|
+
const comp = route2.component;
|
|
1337
|
+
const cached = this.componentCache.get(routePath);
|
|
1338
|
+
if (cached) return cached;
|
|
1339
|
+
const existingPromise = this.loadingPromises.get(routePath);
|
|
1340
|
+
if (existingPromise) return existingPromise;
|
|
1341
|
+
const errorInfo = this.errorCache.get(routePath);
|
|
1342
|
+
if (errorInfo && Date.now() - errorInfo.timestamp < this.retryDelay) {
|
|
1343
|
+
throw new Error(`Component loading failed recently, retry in ${this.retryDelay}ms`);
|
|
1344
|
+
}
|
|
1345
|
+
const loadingPromise = this.doLoadComponent(comp, routePath);
|
|
1346
|
+
this.loadingPromises.set(routePath, loadingPromise);
|
|
1347
|
+
try {
|
|
1348
|
+
const component = await loadingPromise;
|
|
1349
|
+
this.componentCache.set(routePath, component);
|
|
1350
|
+
this.errorCache.delete(routePath);
|
|
1351
|
+
return component;
|
|
1352
|
+
} catch (error) {
|
|
1353
|
+
const currentError = this.errorCache.get(routePath) || { timestamp: 0, count: 0 };
|
|
1354
|
+
this.errorCache.set(routePath, {
|
|
1355
|
+
timestamp: Date.now(),
|
|
1356
|
+
count: currentError.count + 1
|
|
1357
|
+
});
|
|
1358
|
+
throw error;
|
|
1359
|
+
} finally {
|
|
1360
|
+
this.loadingPromises.delete(routePath);
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1363
|
+
async doLoadComponent(comp, routePath) {
|
|
1364
|
+
if (!this.isAsyncComponent(comp)) {
|
|
1365
|
+
const result = comp();
|
|
1366
|
+
if (!this.isElement(result)) {
|
|
1367
|
+
throw new Error(`Component for route "${routePath}" must return Element, got ${typeof result}`);
|
|
1368
|
+
}
|
|
1369
|
+
return comp;
|
|
1370
|
+
}
|
|
1371
|
+
try {
|
|
1372
|
+
const result = await comp();
|
|
1373
|
+
const component = this.extractComponent(result, routePath);
|
|
1374
|
+
const testElement = component();
|
|
1375
|
+
if (!this.isElement(testElement)) {
|
|
1376
|
+
throw new Error(`Component for route "${routePath}" must return Element, got ${typeof testElement}`);
|
|
1377
|
+
}
|
|
1378
|
+
return component;
|
|
1379
|
+
} catch (error) {
|
|
1380
|
+
throw new Error(
|
|
1381
|
+
`Failed to load component for route "${routePath}": ${error instanceof Error ? error.message : String(error)}`
|
|
1382
|
+
);
|
|
1383
|
+
}
|
|
1384
|
+
}
|
|
1385
|
+
isAsyncComponent(comp) {
|
|
1386
|
+
return comp.constructor.name === "AsyncFunction" || typeof comp === "function" && comp.toString().includes("import(");
|
|
1387
|
+
}
|
|
1388
|
+
isElement(value) {
|
|
1389
|
+
return value instanceof Element;
|
|
1390
|
+
}
|
|
1391
|
+
extractComponent(result, routePath) {
|
|
1392
|
+
if ("default" in result && typeof result.default === "function") {
|
|
1393
|
+
return result.default;
|
|
1394
|
+
}
|
|
1395
|
+
if (typeof result === "function") {
|
|
1396
|
+
return result;
|
|
1397
|
+
}
|
|
1398
|
+
if (this.isElement(result)) {
|
|
1399
|
+
return () => result;
|
|
1400
|
+
}
|
|
1401
|
+
throw new Error(`Invalid component module for route "${routePath}"`);
|
|
1402
|
+
}
|
|
1403
|
+
clearErrors() {
|
|
1404
|
+
this.errorCache.clear();
|
|
1405
|
+
}
|
|
1406
|
+
clearCache() {
|
|
1407
|
+
this.componentCache.clear();
|
|
1408
|
+
this.errorCache.clear();
|
|
1409
|
+
this.loadingPromises.clear();
|
|
1410
|
+
}
|
|
1411
|
+
};
|
|
1412
|
+
var SibuRouter = class {
|
|
1413
|
+
constructor(routes, options = {}) {
|
|
1414
|
+
// Event listeners cleanup
|
|
1415
|
+
this.cleanup = [];
|
|
1416
|
+
this.options = {
|
|
1417
|
+
mode: "history",
|
|
1418
|
+
base: "",
|
|
1419
|
+
linkActiveClass: "router-link-active",
|
|
1420
|
+
linkExactActiveClass: "router-link-exact-active",
|
|
1421
|
+
fallback: true,
|
|
1422
|
+
guardTimeout: 5e3,
|
|
1423
|
+
cacheSize: 50,
|
|
1424
|
+
errorRetryDelay: 1e3,
|
|
1425
|
+
preloadStrategy: "none",
|
|
1426
|
+
...options
|
|
1427
|
+
};
|
|
1428
|
+
const [currentRouteState, setCurrentRouteState] = signal(this.createInitialRoute());
|
|
1429
|
+
const [isReadyState, setIsReadyState] = signal(false);
|
|
1430
|
+
this.currentRouteGetter = currentRouteState;
|
|
1431
|
+
this.currentRouteSetter = setCurrentRouteState;
|
|
1432
|
+
this.isReadyGetter = isReadyState;
|
|
1433
|
+
this.isReadySetter = setIsReadyState;
|
|
1434
|
+
this.matcher = new RouteMatcher(routes);
|
|
1435
|
+
this.guards = new GuardManager(this.options.guardTimeout);
|
|
1436
|
+
this.loader = new ComponentLoader(this.options.cacheSize, this.options.errorRetryDelay);
|
|
1437
|
+
this.navigator = new NavigationController();
|
|
1438
|
+
this.initialize();
|
|
1439
|
+
}
|
|
1440
|
+
initialize() {
|
|
1441
|
+
if (this.options.mode === "history") {
|
|
1442
|
+
const popstateHandler = () => this.handleLocationChange();
|
|
1443
|
+
window.addEventListener("popstate", popstateHandler);
|
|
1444
|
+
this.cleanup.push(() => window.removeEventListener("popstate", popstateHandler));
|
|
1445
|
+
} else {
|
|
1446
|
+
const hashHandler = () => this.handleLocationChange();
|
|
1447
|
+
window.addEventListener("hashchange", hashHandler);
|
|
1448
|
+
this.cleanup.push(() => window.removeEventListener("hashchange", hashHandler));
|
|
1449
|
+
}
|
|
1450
|
+
queueMicrotask(() => {
|
|
1451
|
+
this.handleLocationChange();
|
|
1452
|
+
this.isReadySetter(true);
|
|
1453
|
+
});
|
|
1454
|
+
}
|
|
1455
|
+
createInitialRoute() {
|
|
1456
|
+
return {
|
|
1457
|
+
path: "/",
|
|
1458
|
+
params: {},
|
|
1459
|
+
query: {},
|
|
1460
|
+
hash: "",
|
|
1461
|
+
meta: {},
|
|
1462
|
+
matched: []
|
|
1463
|
+
};
|
|
1464
|
+
}
|
|
1465
|
+
handleLocationChange() {
|
|
1466
|
+
const path2 = this.getCurrentPath();
|
|
1467
|
+
const context = this.createRouteContext(path2);
|
|
1468
|
+
this.currentRouteSetter(context);
|
|
1469
|
+
}
|
|
1470
|
+
getCurrentPath() {
|
|
1471
|
+
const { mode, base: base2 } = this.options;
|
|
1472
|
+
if (mode === "hash") {
|
|
1473
|
+
return window.location.hash.slice(1) || "/";
|
|
1474
|
+
}
|
|
1475
|
+
let path2 = window.location.pathname;
|
|
1476
|
+
if (base2 && path2.startsWith(base2)) {
|
|
1477
|
+
path2 = path2.slice(base2.length);
|
|
1478
|
+
}
|
|
1479
|
+
return (path2 || "/") + window.location.search + window.location.hash;
|
|
1480
|
+
}
|
|
1481
|
+
createRouteContext(fullPath) {
|
|
1482
|
+
const [pathWithQuery, hash = ""] = fullPath.split("#");
|
|
1483
|
+
const [path2, queryString = ""] = pathWithQuery.split("?");
|
|
1484
|
+
const query = Object.fromEntries(new URLSearchParams(queryString));
|
|
1485
|
+
const match = this.matcher.match(path2 || "/");
|
|
1486
|
+
const params = match?.params || {};
|
|
1487
|
+
const meta2 = match?.route.meta || {};
|
|
1488
|
+
const matched = match ? [match.route] : [];
|
|
1489
|
+
return {
|
|
1490
|
+
path: path2 || "/",
|
|
1491
|
+
params,
|
|
1492
|
+
query,
|
|
1493
|
+
hash,
|
|
1494
|
+
meta: meta2,
|
|
1495
|
+
matched
|
|
1496
|
+
};
|
|
1497
|
+
}
|
|
1498
|
+
// Public API
|
|
1499
|
+
async navigate(to, options = {}) {
|
|
1500
|
+
try {
|
|
1501
|
+
await this.navigator.navigate(async (signal2) => {
|
|
1502
|
+
const targetPath = this.resolvePath(to);
|
|
1503
|
+
const from = this.currentRouteGetter();
|
|
1504
|
+
const toContext = this.createRouteContext(targetPath);
|
|
1505
|
+
if (this.isSameRoute(from, toContext)) {
|
|
1506
|
+
throw new NavigationFailureError("duplicated", from, toContext);
|
|
1507
|
+
}
|
|
1508
|
+
await this.performNavigation(toContext, from, options, signal2);
|
|
1509
|
+
});
|
|
1510
|
+
return { success: true, route: this.currentRouteGetter() };
|
|
1511
|
+
} catch (error) {
|
|
1512
|
+
if (error instanceof NavigationFailureError) {
|
|
1513
|
+
const failure2 = error.toFailure();
|
|
1514
|
+
return { success: false, type: failure2.type, failure: failure2 };
|
|
1515
|
+
}
|
|
1516
|
+
const failure = {
|
|
1517
|
+
type: "aborted",
|
|
1518
|
+
from: this.currentRouteGetter(),
|
|
1519
|
+
to: this.createRouteContext(this.resolvePath(to)),
|
|
1520
|
+
error: error instanceof Error ? error : new Error(String(error))
|
|
1521
|
+
};
|
|
1522
|
+
return { success: false, type: failure.type, failure };
|
|
1523
|
+
}
|
|
1524
|
+
}
|
|
1525
|
+
async performNavigation(to, from, options, signal2) {
|
|
1526
|
+
const beforeEachResult = await this.guards.runBeforeEach(to, from, signal2);
|
|
1527
|
+
if (beforeEachResult !== true) {
|
|
1528
|
+
if (typeof beforeEachResult === "string") {
|
|
1529
|
+
return this.performNavigation(this.createRouteContext(beforeEachResult), from, options, signal2);
|
|
1530
|
+
}
|
|
1531
|
+
throw new NavigationFailureError("aborted", from, to);
|
|
1532
|
+
}
|
|
1533
|
+
const match = this.matcher.match(to.path);
|
|
1534
|
+
if (match) {
|
|
1535
|
+
const { route: route2 } = match;
|
|
1536
|
+
if ("beforeEnter" in route2 && route2.beforeEnter) {
|
|
1537
|
+
const guards = Array.isArray(route2.beforeEnter) ? route2.beforeEnter : [route2.beforeEnter];
|
|
1538
|
+
for (const guard of guards) {
|
|
1539
|
+
if (signal2.aborted) throw new Error("Navigation aborted");
|
|
1540
|
+
const result = await guard(to, from);
|
|
1541
|
+
if (result !== true) {
|
|
1542
|
+
if (typeof result === "string") {
|
|
1543
|
+
return this.performNavigation(this.createRouteContext(result), from, options, signal2);
|
|
1544
|
+
}
|
|
1545
|
+
throw new NavigationFailureError("aborted", from, to);
|
|
1546
|
+
}
|
|
1547
|
+
}
|
|
1548
|
+
}
|
|
1549
|
+
if ("redirect" in route2) {
|
|
1550
|
+
const redirectPath = typeof route2.redirect === "function" ? route2.redirect(to) : route2.redirect;
|
|
1551
|
+
if (typeof redirectPath === "string" && /^https?:\/\/|^\/\//i.test(redirectPath)) {
|
|
1552
|
+
console.warn(
|
|
1553
|
+
`[SibuJS Router] Redirect to absolute URL "${redirectPath}" detected. Use relative paths for safer redirects.`
|
|
1554
|
+
);
|
|
1555
|
+
}
|
|
1556
|
+
return this.performNavigation(this.createRouteContext(redirectPath), from, options, signal2);
|
|
1557
|
+
}
|
|
1558
|
+
}
|
|
1559
|
+
const beforeResolveResult = await this.guards.runBeforeResolve(to, from, signal2);
|
|
1560
|
+
if (beforeResolveResult !== true) {
|
|
1561
|
+
if (typeof beforeResolveResult === "string") {
|
|
1562
|
+
return this.performNavigation(this.createRouteContext(beforeResolveResult), from, options, signal2);
|
|
1563
|
+
}
|
|
1564
|
+
throw new NavigationFailureError("aborted", from, to);
|
|
1565
|
+
}
|
|
1566
|
+
this.updateHistory(to, options);
|
|
1567
|
+
this.currentRouteSetter(to);
|
|
1568
|
+
this.guards.runAfterEach(to, from);
|
|
1569
|
+
this.handleScrollBehavior(to, from);
|
|
1570
|
+
}
|
|
1571
|
+
resolvePath(to) {
|
|
1572
|
+
if (typeof to === "string") return to;
|
|
1573
|
+
let path2 = to.path || "";
|
|
1574
|
+
if (to.name && !path2) {
|
|
1575
|
+
const namedRoute = this.matcher.findByName(to.name);
|
|
1576
|
+
if (namedRoute) {
|
|
1577
|
+
path2 = namedRoute.path;
|
|
1578
|
+
}
|
|
1579
|
+
}
|
|
1580
|
+
if (to.params) {
|
|
1581
|
+
for (const [key, value] of Object.entries(to.params)) {
|
|
1582
|
+
path2 = path2.replace(`:${key}`, encodeURIComponent(value));
|
|
1583
|
+
}
|
|
1584
|
+
}
|
|
1585
|
+
if (to.query && Object.keys(to.query).length > 0) {
|
|
1586
|
+
path2 += `?${new URLSearchParams(to.query).toString()}`;
|
|
1587
|
+
}
|
|
1588
|
+
if (to.hash) {
|
|
1589
|
+
path2 += `#${to.hash}`;
|
|
1590
|
+
}
|
|
1591
|
+
return path2;
|
|
1592
|
+
}
|
|
1593
|
+
isSameRoute(from, to) {
|
|
1594
|
+
return from.path === to.path && JSON.stringify(from.params) === JSON.stringify(to.params) && JSON.stringify(from.query) === JSON.stringify(to.query) && from.hash === to.hash;
|
|
1595
|
+
}
|
|
1596
|
+
updateHistory(to, options) {
|
|
1597
|
+
const fullPath = this.options.base + to.path + (Object.keys(to.query).length ? `?${new URLSearchParams(to.query).toString()}` : "") + (to.hash ? `#${to.hash}` : "");
|
|
1598
|
+
if (options.replace) {
|
|
1599
|
+
history.replaceState(options.state || {}, "", fullPath);
|
|
1600
|
+
} else {
|
|
1601
|
+
history.pushState(options.state || {}, "", fullPath);
|
|
1602
|
+
}
|
|
1603
|
+
}
|
|
1604
|
+
handleScrollBehavior(to, from) {
|
|
1605
|
+
if (this.options.scrollBehavior) {
|
|
1606
|
+
const scrollTo = this.options.scrollBehavior(to, from, null);
|
|
1607
|
+
if (scrollTo) {
|
|
1608
|
+
requestAnimationFrame(() => {
|
|
1609
|
+
window.scrollTo(scrollTo.x, scrollTo.y);
|
|
1610
|
+
});
|
|
1611
|
+
}
|
|
1612
|
+
}
|
|
1613
|
+
}
|
|
1614
|
+
// Component loading
|
|
1615
|
+
async loadComponent(route2, routePath) {
|
|
1616
|
+
return this.loader.loadComponent(route2, routePath);
|
|
1617
|
+
}
|
|
1618
|
+
// Guards API
|
|
1619
|
+
beforeEach(guard) {
|
|
1620
|
+
return this.guards.addBeforeEach(guard);
|
|
1621
|
+
}
|
|
1622
|
+
beforeResolve(guard) {
|
|
1623
|
+
return this.guards.addBeforeResolve(guard);
|
|
1624
|
+
}
|
|
1625
|
+
afterEach(hook) {
|
|
1626
|
+
return this.guards.addAfterEach(hook);
|
|
1627
|
+
}
|
|
1628
|
+
// Utility methods
|
|
1629
|
+
push(to) {
|
|
1630
|
+
return this.navigate(to);
|
|
1631
|
+
}
|
|
1632
|
+
replace(to) {
|
|
1633
|
+
return this.navigate(to, { replace: true });
|
|
1634
|
+
}
|
|
1635
|
+
go(delta) {
|
|
1636
|
+
history.go(delta);
|
|
1637
|
+
}
|
|
1638
|
+
back() {
|
|
1639
|
+
history.back();
|
|
1640
|
+
}
|
|
1641
|
+
forward() {
|
|
1642
|
+
history.forward();
|
|
1643
|
+
}
|
|
1644
|
+
// State getters
|
|
1645
|
+
get currentRoute() {
|
|
1646
|
+
return this.currentRouteGetter();
|
|
1647
|
+
}
|
|
1648
|
+
get isReady() {
|
|
1649
|
+
return this.isReadyGetter();
|
|
1650
|
+
}
|
|
1651
|
+
get isNavigating() {
|
|
1652
|
+
return this.navigator.isNavigating;
|
|
1653
|
+
}
|
|
1654
|
+
// Cleanup
|
|
1655
|
+
destroy() {
|
|
1656
|
+
this.navigator.abort();
|
|
1657
|
+
for (const fn of this.cleanup) fn();
|
|
1658
|
+
this.cleanup = [];
|
|
1659
|
+
this.guards.clear();
|
|
1660
|
+
this.loader.clearCache();
|
|
1661
|
+
this.isReadySetter(false);
|
|
1662
|
+
}
|
|
1663
|
+
// Cache management
|
|
1664
|
+
clearCache() {
|
|
1665
|
+
this.loader.clearCache();
|
|
1666
|
+
}
|
|
1667
|
+
clearErrorCache() {
|
|
1668
|
+
this.loader.clearErrors();
|
|
1669
|
+
}
|
|
1670
|
+
// Route management
|
|
1671
|
+
updateRoutes(routes) {
|
|
1672
|
+
this.matcher.rebuild(routes);
|
|
1673
|
+
this.clearCache();
|
|
1674
|
+
}
|
|
1675
|
+
/**
|
|
1676
|
+
* Add a route dynamically at runtime.
|
|
1677
|
+
*/
|
|
1678
|
+
addRoute(route2, parentPath) {
|
|
1679
|
+
this.matcher.addRoute(route2, parentPath);
|
|
1680
|
+
this.clearCache();
|
|
1681
|
+
}
|
|
1682
|
+
/**
|
|
1683
|
+
* Remove a route by path.
|
|
1684
|
+
*/
|
|
1685
|
+
removeRoute(path2) {
|
|
1686
|
+
this.matcher.removeRoute(path2);
|
|
1687
|
+
this.clearCache();
|
|
1688
|
+
}
|
|
1689
|
+
/**
|
|
1690
|
+
* Get the reactive route getter for tracking.
|
|
1691
|
+
*/
|
|
1692
|
+
get routeGetter() {
|
|
1693
|
+
return this.currentRouteGetter;
|
|
1694
|
+
}
|
|
1695
|
+
};
|
|
1696
|
+
var NavigationFailureError = class extends Error {
|
|
1697
|
+
constructor(type, from, to, error) {
|
|
1698
|
+
super(`Navigation ${type}: from ${from.path} to ${to.path}`);
|
|
1699
|
+
this.name = "NavigationFailureError";
|
|
1700
|
+
this.type = type;
|
|
1701
|
+
this.from = from;
|
|
1702
|
+
this.to = to;
|
|
1703
|
+
if (error) {
|
|
1704
|
+
this.cause = error;
|
|
1705
|
+
}
|
|
1706
|
+
}
|
|
1707
|
+
toFailure() {
|
|
1708
|
+
return {
|
|
1709
|
+
type: this.type,
|
|
1710
|
+
from: this.from,
|
|
1711
|
+
to: this.to,
|
|
1712
|
+
error: this.cause instanceof Error ? this.cause : void 0
|
|
1713
|
+
};
|
|
1714
|
+
}
|
|
1715
|
+
};
|
|
1716
|
+
var globalRouter = null;
|
|
1717
|
+
function createRouter(routesOrOptions, options = {}) {
|
|
1718
|
+
if (globalRouter) {
|
|
1719
|
+
globalRouter.destroy();
|
|
1720
|
+
}
|
|
1721
|
+
let routes;
|
|
1722
|
+
if (Array.isArray(routesOrOptions)) {
|
|
1723
|
+
routes = routesOrOptions;
|
|
1724
|
+
} else {
|
|
1725
|
+
options = routesOrOptions;
|
|
1726
|
+
routes = [];
|
|
1727
|
+
}
|
|
1728
|
+
globalRouter = new SibuRouter(routes, options);
|
|
1729
|
+
return globalRouter;
|
|
1730
|
+
}
|
|
1731
|
+
function setRoutes(routes) {
|
|
1732
|
+
if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
|
|
1733
|
+
globalRouter.updateRoutes(routes);
|
|
1734
|
+
}
|
|
1735
|
+
function route() {
|
|
1736
|
+
if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
|
|
1737
|
+
return globalRouter.currentRoute;
|
|
1738
|
+
}
|
|
1739
|
+
function router() {
|
|
1740
|
+
if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
|
|
1741
|
+
return {
|
|
1742
|
+
currentRoute: globalRouter.currentRoute,
|
|
1743
|
+
isReady: globalRouter.isReady,
|
|
1744
|
+
isNavigating: globalRouter.isNavigating,
|
|
1745
|
+
push: (to) => globalRouter?.push(to),
|
|
1746
|
+
replace: (to) => globalRouter?.replace(to),
|
|
1747
|
+
go: (delta) => globalRouter?.go(delta),
|
|
1748
|
+
back: () => globalRouter?.back(),
|
|
1749
|
+
forward: () => globalRouter?.forward(),
|
|
1750
|
+
beforeEach: (guard) => globalRouter?.beforeEach(guard),
|
|
1751
|
+
beforeResolve: (guard) => globalRouter?.beforeResolve(guard),
|
|
1752
|
+
afterEach: (hook) => globalRouter?.afterEach(hook)
|
|
1753
|
+
};
|
|
1754
|
+
}
|
|
1755
|
+
function navigate(to, options) {
|
|
1756
|
+
if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
|
|
1757
|
+
return globalRouter.navigate(to, options);
|
|
1758
|
+
}
|
|
1759
|
+
function push(to) {
|
|
1760
|
+
if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
|
|
1761
|
+
return globalRouter.push(to);
|
|
1762
|
+
}
|
|
1763
|
+
function replace(to) {
|
|
1764
|
+
if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
|
|
1765
|
+
return globalRouter.replace(to);
|
|
1766
|
+
}
|
|
1767
|
+
function go(delta) {
|
|
1768
|
+
if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
|
|
1769
|
+
globalRouter.go(delta);
|
|
1770
|
+
}
|
|
1771
|
+
function back() {
|
|
1772
|
+
if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
|
|
1773
|
+
globalRouter.back();
|
|
1774
|
+
}
|
|
1775
|
+
function forward() {
|
|
1776
|
+
if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
|
|
1777
|
+
globalRouter.forward();
|
|
1778
|
+
}
|
|
1779
|
+
function beforeEach(guard) {
|
|
1780
|
+
if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
|
|
1781
|
+
return globalRouter.beforeEach(guard);
|
|
1782
|
+
}
|
|
1783
|
+
function beforeResolve(guard) {
|
|
1784
|
+
if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
|
|
1785
|
+
return globalRouter.beforeResolve(guard);
|
|
1786
|
+
}
|
|
1787
|
+
function afterEach(hook) {
|
|
1788
|
+
if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
|
|
1789
|
+
return globalRouter.afterEach(hook);
|
|
1790
|
+
}
|
|
1791
|
+
var routeCleanups = [];
|
|
1792
|
+
function Route() {
|
|
1793
|
+
const anchor = document.createComment("route-outlet");
|
|
1794
|
+
let currentNode = null;
|
|
1795
|
+
let loadingNode = null;
|
|
1796
|
+
let errorNode = null;
|
|
1797
|
+
let isUpdating = false;
|
|
1798
|
+
let currentPath = "";
|
|
1799
|
+
const cleanupNodes = () => {
|
|
1800
|
+
[currentNode, loadingNode, errorNode].forEach((node) => {
|
|
1801
|
+
if (node?.parentNode) {
|
|
1802
|
+
node.parentNode.removeChild(node);
|
|
1803
|
+
}
|
|
1804
|
+
});
|
|
1805
|
+
currentNode = null;
|
|
1806
|
+
loadingNode = null;
|
|
1807
|
+
errorNode = null;
|
|
1808
|
+
};
|
|
1809
|
+
const showLoading = () => {
|
|
1810
|
+
if (!loadingNode && anchor.parentNode) {
|
|
1811
|
+
loadingNode = document.createElement("div");
|
|
1812
|
+
loadingNode.className = "route-loading";
|
|
1813
|
+
loadingNode.setAttribute("role", "status");
|
|
1814
|
+
loadingNode.setAttribute("aria-label", "Loading route");
|
|
1815
|
+
const spinner = document.createElement("div");
|
|
1816
|
+
spinner.className = "route-loading-spinner";
|
|
1817
|
+
spinner.setAttribute("aria-hidden", "true");
|
|
1818
|
+
const text2 = document.createElement("span");
|
|
1819
|
+
text2.textContent = "Loading...";
|
|
1820
|
+
text2.className = "route-loading-text";
|
|
1821
|
+
loadingNode.appendChild(spinner);
|
|
1822
|
+
loadingNode.appendChild(text2);
|
|
1823
|
+
anchor.parentNode.insertBefore(loadingNode, anchor.nextSibling);
|
|
1824
|
+
}
|
|
1825
|
+
};
|
|
1826
|
+
const hideLoading = () => {
|
|
1827
|
+
if (loadingNode?.parentNode) {
|
|
1828
|
+
loadingNode.parentNode.removeChild(loadingNode);
|
|
1829
|
+
loadingNode = null;
|
|
1830
|
+
}
|
|
1831
|
+
};
|
|
1832
|
+
const showError = (error) => {
|
|
1833
|
+
if (!anchor.parentNode) return;
|
|
1834
|
+
cleanupNodes();
|
|
1835
|
+
errorNode = document.createElement("div");
|
|
1836
|
+
errorNode.className = "route-error";
|
|
1837
|
+
errorNode.setAttribute("role", "alert");
|
|
1838
|
+
errorNode.setAttribute("aria-live", "assertive");
|
|
1839
|
+
const title2 = document.createElement("h3");
|
|
1840
|
+
title2.textContent = "Route Error";
|
|
1841
|
+
title2.className = "route-error-title";
|
|
1842
|
+
const message = document.createElement("p");
|
|
1843
|
+
message.textContent = error.message || "Failed to load route component";
|
|
1844
|
+
message.className = "route-error-message";
|
|
1845
|
+
const retryButton = document.createElement("button");
|
|
1846
|
+
retryButton.textContent = "Retry";
|
|
1847
|
+
retryButton.className = "route-error-retry";
|
|
1848
|
+
retryButton.type = "button";
|
|
1849
|
+
retryButton.addEventListener("click", () => {
|
|
1850
|
+
if (globalRouter) {
|
|
1851
|
+
globalRouter.clearErrorCache();
|
|
1852
|
+
update();
|
|
1853
|
+
}
|
|
1854
|
+
});
|
|
1855
|
+
errorNode.appendChild(title2);
|
|
1856
|
+
errorNode.appendChild(message);
|
|
1857
|
+
errorNode.appendChild(retryButton);
|
|
1858
|
+
anchor.parentNode.insertBefore(errorNode, anchor.nextSibling);
|
|
1859
|
+
};
|
|
1860
|
+
let pendingUpdate = false;
|
|
1861
|
+
const update = async () => {
|
|
1862
|
+
if (!globalRouter) return;
|
|
1863
|
+
if (isUpdating) {
|
|
1864
|
+
pendingUpdate = true;
|
|
1865
|
+
return;
|
|
1866
|
+
}
|
|
1867
|
+
const route2 = globalRouter.currentRoute;
|
|
1868
|
+
if (route2.path === currentPath && currentNode) return;
|
|
1869
|
+
isUpdating = true;
|
|
1870
|
+
currentPath = route2.path;
|
|
1871
|
+
try {
|
|
1872
|
+
const match = globalRouter["matcher"].match(route2.path);
|
|
1873
|
+
if (!match) {
|
|
1874
|
+
cleanupNodes();
|
|
1875
|
+
return;
|
|
1876
|
+
}
|
|
1877
|
+
const { route: routeDef } = match;
|
|
1878
|
+
if ("redirect" in routeDef) {
|
|
1879
|
+
const redirectPath = typeof routeDef.redirect === "function" ? routeDef.redirect(route2) : routeDef.redirect;
|
|
1880
|
+
queueMicrotask(() => globalRouter?.navigate(redirectPath));
|
|
1881
|
+
return;
|
|
1882
|
+
}
|
|
1883
|
+
if ("component" in routeDef) {
|
|
1884
|
+
try {
|
|
1885
|
+
const isAsync = routeDef.component.constructor.name === "AsyncFunction" || routeDef.component.toString().includes("import(");
|
|
1886
|
+
if (isAsync) {
|
|
1887
|
+
showLoading();
|
|
1888
|
+
}
|
|
1889
|
+
const component = await globalRouter.loadComponent(routeDef, route2.path);
|
|
1890
|
+
const node = component();
|
|
1891
|
+
if (node && anchor.parentNode && route2.path === currentPath) {
|
|
1892
|
+
cleanupNodes();
|
|
1893
|
+
anchor.parentNode.insertBefore(node, anchor.nextSibling);
|
|
1894
|
+
currentNode = node;
|
|
1895
|
+
}
|
|
1896
|
+
} catch (error) {
|
|
1897
|
+
hideLoading();
|
|
1898
|
+
console.error("[Route] Component error:", error);
|
|
1899
|
+
showError(error instanceof Error ? error : new Error(String(error)));
|
|
1900
|
+
}
|
|
1901
|
+
}
|
|
1902
|
+
} catch (error) {
|
|
1903
|
+
console.error("[Route] Update failed:", error);
|
|
1904
|
+
showError(error instanceof Error ? error : new Error(String(error)));
|
|
1905
|
+
} finally {
|
|
1906
|
+
isUpdating = false;
|
|
1907
|
+
if (pendingUpdate) {
|
|
1908
|
+
pendingUpdate = false;
|
|
1909
|
+
update();
|
|
1910
|
+
}
|
|
1911
|
+
}
|
|
1912
|
+
};
|
|
1913
|
+
let routeInitialized = false;
|
|
1914
|
+
const originalUpdate = update;
|
|
1915
|
+
const wrappedUpdate = async () => {
|
|
1916
|
+
await originalUpdate();
|
|
1917
|
+
routeInitialized = true;
|
|
1918
|
+
};
|
|
1919
|
+
track(wrappedUpdate);
|
|
1920
|
+
if (!routeInitialized) {
|
|
1921
|
+
queueMicrotask(() => {
|
|
1922
|
+
if (!routeInitialized && anchor.parentNode) wrappedUpdate();
|
|
1923
|
+
});
|
|
1924
|
+
}
|
|
1925
|
+
routeCleanups.push(cleanupNodes);
|
|
1926
|
+
return anchor;
|
|
1927
|
+
}
|
|
1928
|
+
function RouterLink(props) {
|
|
1929
|
+
if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
|
|
1930
|
+
const { to, replace: replace2 = false, activeClass, exactActiveClass, nodes, target, rel, ...attrs } = props;
|
|
1931
|
+
const route2 = globalRouter.currentRoute;
|
|
1932
|
+
const href = globalRouter["resolvePath"](to);
|
|
1933
|
+
const isActive = route2.path.startsWith(href.split("?")[0].split("#")[0]);
|
|
1934
|
+
const isExactActive = route2.path === href.split("?")[0].split("#")[0];
|
|
1935
|
+
const link2 = document.createElement("a");
|
|
1936
|
+
link2.href = href;
|
|
1937
|
+
if (target) {
|
|
1938
|
+
link2.target = target;
|
|
1939
|
+
if (target === "_blank") {
|
|
1940
|
+
link2.rel = rel ? `${rel} noopener noreferrer` : "noopener noreferrer";
|
|
1941
|
+
} else if (rel) {
|
|
1942
|
+
link2.rel = rel;
|
|
1943
|
+
}
|
|
1944
|
+
} else if (rel) {
|
|
1945
|
+
link2.rel = rel;
|
|
1946
|
+
}
|
|
1947
|
+
const classes = [];
|
|
1948
|
+
const options = globalRouter["options"];
|
|
1949
|
+
if (isActive) {
|
|
1950
|
+
if (activeClass) classes.push(activeClass);
|
|
1951
|
+
else if (options.linkActiveClass) classes.push(options.linkActiveClass);
|
|
1952
|
+
}
|
|
1953
|
+
if (isExactActive) {
|
|
1954
|
+
if (exactActiveClass) classes.push(exactActiveClass);
|
|
1955
|
+
else if (options.linkExactActiveClass) classes.push(options.linkExactActiveClass);
|
|
1956
|
+
}
|
|
1957
|
+
if (classes.length > 0) {
|
|
1958
|
+
link2.className = classes.join(" ");
|
|
1959
|
+
}
|
|
1960
|
+
Object.entries(attrs).forEach(([key, value]) => {
|
|
1961
|
+
if (key.startsWith("on") || key === "href") return;
|
|
1962
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
1963
|
+
link2.setAttribute(key, String(value));
|
|
1964
|
+
}
|
|
1965
|
+
});
|
|
1966
|
+
if (typeof nodes === "string") {
|
|
1967
|
+
link2.textContent = nodes;
|
|
1968
|
+
} else if (nodes instanceof Node) {
|
|
1969
|
+
link2.appendChild(nodes);
|
|
1970
|
+
} else if (Array.isArray(nodes)) {
|
|
1971
|
+
nodes.forEach((child) => {
|
|
1972
|
+
if (typeof child === "string") {
|
|
1973
|
+
link2.appendChild(document.createTextNode(child));
|
|
1974
|
+
} else if (child instanceof Node) {
|
|
1975
|
+
link2.appendChild(child);
|
|
1976
|
+
}
|
|
1977
|
+
});
|
|
1978
|
+
}
|
|
1979
|
+
link2.addEventListener("click", (e) => {
|
|
1980
|
+
if (target || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey || e.button !== 0) {
|
|
1981
|
+
return;
|
|
1982
|
+
}
|
|
1983
|
+
e.preventDefault();
|
|
1984
|
+
globalRouter?.navigate(to, { replace: replace2 });
|
|
1985
|
+
});
|
|
1986
|
+
return link2;
|
|
1987
|
+
}
|
|
1988
|
+
function Suspense(props) {
|
|
1989
|
+
const anchor = document.createComment("suspense-boundary");
|
|
1990
|
+
let currentNode = null;
|
|
1991
|
+
let fallbackNode = null;
|
|
1992
|
+
let isLoading = false;
|
|
1993
|
+
const cleanupNodes = () => {
|
|
1994
|
+
[currentNode, fallbackNode].forEach((node) => {
|
|
1995
|
+
if (node?.parentNode) {
|
|
1996
|
+
node.parentNode.removeChild(node);
|
|
1997
|
+
}
|
|
1998
|
+
});
|
|
1999
|
+
currentNode = null;
|
|
2000
|
+
fallbackNode = null;
|
|
2001
|
+
};
|
|
2002
|
+
const showFallback = () => {
|
|
2003
|
+
if (fallbackNode || !props.fallback || !anchor.parentNode) return;
|
|
2004
|
+
try {
|
|
2005
|
+
const fallback = typeof props.fallback === "function" ? props.fallback() : props.fallback;
|
|
2006
|
+
if (fallback instanceof HTMLElement) {
|
|
2007
|
+
fallbackNode = fallback;
|
|
2008
|
+
anchor.parentNode.insertBefore(fallbackNode, anchor.nextSibling);
|
|
2009
|
+
}
|
|
2010
|
+
} catch (error) {
|
|
2011
|
+
console.error("[Suspense] Fallback error:", error);
|
|
2012
|
+
}
|
|
2013
|
+
};
|
|
2014
|
+
const hideFallback = () => {
|
|
2015
|
+
if (fallbackNode?.parentNode) {
|
|
2016
|
+
fallbackNode.parentNode.removeChild(fallbackNode);
|
|
2017
|
+
fallbackNode = null;
|
|
2018
|
+
}
|
|
2019
|
+
};
|
|
2020
|
+
const render = async () => {
|
|
2021
|
+
if (isLoading) return;
|
|
2022
|
+
isLoading = true;
|
|
2023
|
+
try {
|
|
2024
|
+
const result = props.nodes();
|
|
2025
|
+
if (result instanceof Promise) {
|
|
2026
|
+
showFallback();
|
|
2027
|
+
const element = await result;
|
|
2028
|
+
if (anchor.parentNode) {
|
|
2029
|
+
cleanupNodes();
|
|
2030
|
+
anchor.parentNode.insertBefore(element, anchor.nextSibling);
|
|
2031
|
+
currentNode = element;
|
|
2032
|
+
}
|
|
2033
|
+
} else {
|
|
2034
|
+
if (anchor.parentNode) {
|
|
2035
|
+
cleanupNodes();
|
|
2036
|
+
anchor.parentNode.insertBefore(result, anchor.nextSibling);
|
|
2037
|
+
currentNode = result;
|
|
2038
|
+
}
|
|
2039
|
+
}
|
|
2040
|
+
} catch (error) {
|
|
2041
|
+
hideFallback();
|
|
2042
|
+
console.error("[Suspense] Nodes error:", error);
|
|
2043
|
+
if (anchor.parentNode) {
|
|
2044
|
+
const errorElement = document.createElement("div");
|
|
2045
|
+
errorElement.className = "suspense-error";
|
|
2046
|
+
errorElement.textContent = error instanceof Error ? error.message : "Failed to load";
|
|
2047
|
+
cleanupNodes();
|
|
2048
|
+
anchor.parentNode.insertBefore(errorElement, anchor.nextSibling);
|
|
2049
|
+
currentNode = errorElement;
|
|
2050
|
+
}
|
|
2051
|
+
} finally {
|
|
2052
|
+
isLoading = false;
|
|
2053
|
+
}
|
|
2054
|
+
};
|
|
2055
|
+
queueMicrotask(render);
|
|
2056
|
+
return anchor;
|
|
2057
|
+
}
|
|
2058
|
+
function lazy(importFn) {
|
|
2059
|
+
return importFn;
|
|
2060
|
+
}
|
|
2061
|
+
async function preloadRoute(to) {
|
|
2062
|
+
if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
|
|
2063
|
+
const path2 = globalRouter["resolvePath"](to);
|
|
2064
|
+
const match = globalRouter["matcher"].match(path2.split("?")[0].split("#")[0]);
|
|
2065
|
+
if (match && "component" in match.route) {
|
|
2066
|
+
try {
|
|
2067
|
+
await globalRouter.loadComponent(match.route, path2);
|
|
2068
|
+
} catch (error) {
|
|
2069
|
+
console.warn("[Router] Preload failed:", error);
|
|
2070
|
+
}
|
|
2071
|
+
}
|
|
2072
|
+
}
|
|
2073
|
+
function hasRoute(name) {
|
|
2074
|
+
if (!globalRouter) return false;
|
|
2075
|
+
return globalRouter["matcher"].findByName(name) !== null;
|
|
2076
|
+
}
|
|
2077
|
+
function getRouteInfo(name) {
|
|
2078
|
+
if (!globalRouter) return null;
|
|
2079
|
+
return globalRouter["matcher"].findByName(name);
|
|
2080
|
+
}
|
|
2081
|
+
function buildURL(to) {
|
|
2082
|
+
if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
|
|
2083
|
+
return globalRouter["resolvePath"](to);
|
|
2084
|
+
}
|
|
2085
|
+
function destroyRouter() {
|
|
2086
|
+
for (const fn of routeCleanups) fn();
|
|
2087
|
+
routeCleanups.length = 0;
|
|
2088
|
+
if (globalRouter) {
|
|
2089
|
+
globalRouter.destroy();
|
|
2090
|
+
globalRouter = null;
|
|
2091
|
+
}
|
|
2092
|
+
}
|
|
2093
|
+
if (typeof window !== "undefined") {
|
|
2094
|
+
window.addEventListener("beforeunload", () => {
|
|
2095
|
+
destroyRouter();
|
|
2096
|
+
});
|
|
2097
|
+
}
|
|
2098
|
+
function Outlet() {
|
|
2099
|
+
const anchor = document.createComment("route-outlet-nested");
|
|
2100
|
+
let currentNode = null;
|
|
2101
|
+
const update = async () => {
|
|
2102
|
+
if (!globalRouter) return;
|
|
2103
|
+
const route2 = globalRouter.currentRoute;
|
|
2104
|
+
if (route2.matched.length < 2) return;
|
|
2105
|
+
const childRoute = route2.matched[route2.matched.length - 1];
|
|
2106
|
+
if (!childRoute || !("component" in childRoute)) return;
|
|
2107
|
+
try {
|
|
2108
|
+
const component = await globalRouter.loadComponent(childRoute, route2.path);
|
|
2109
|
+
const node = component();
|
|
2110
|
+
if (node && anchor.parentNode) {
|
|
2111
|
+
if (currentNode?.parentNode) {
|
|
2112
|
+
currentNode.parentNode.removeChild(currentNode);
|
|
2113
|
+
}
|
|
2114
|
+
anchor.parentNode.insertBefore(node, anchor.nextSibling);
|
|
2115
|
+
currentNode = node;
|
|
2116
|
+
}
|
|
2117
|
+
} catch (error) {
|
|
2118
|
+
console.error("[Outlet] Failed to render child route:", error);
|
|
2119
|
+
}
|
|
2120
|
+
};
|
|
2121
|
+
track(update);
|
|
2122
|
+
if (!anchor.parentNode) {
|
|
2123
|
+
queueMicrotask(() => {
|
|
2124
|
+
if (anchor.parentNode) update();
|
|
2125
|
+
});
|
|
2126
|
+
}
|
|
2127
|
+
return anchor;
|
|
2128
|
+
}
|
|
2129
|
+
function addRoute(route2, parentPath) {
|
|
2130
|
+
if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
|
|
2131
|
+
globalRouter.addRoute(route2, parentPath);
|
|
2132
|
+
}
|
|
2133
|
+
function removeRoute(path2) {
|
|
2134
|
+
if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
|
|
2135
|
+
globalRouter.removeRoute(path2);
|
|
2136
|
+
}
|
|
2137
|
+
function routerState() {
|
|
2138
|
+
if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
|
|
2139
|
+
const router2 = globalRouter;
|
|
2140
|
+
return {
|
|
2141
|
+
currentPath: () => router2.currentRoute.path,
|
|
2142
|
+
params: () => router2.currentRoute.params,
|
|
2143
|
+
query: () => router2.currentRoute.query,
|
|
2144
|
+
hash: () => router2.currentRoute.hash,
|
|
2145
|
+
meta: () => router2.currentRoute.meta,
|
|
2146
|
+
isNavigating: router2.isNavigating,
|
|
2147
|
+
isReady: router2.isReady
|
|
2148
|
+
};
|
|
2149
|
+
}
|
|
2150
|
+
var routerPlugins = [];
|
|
2151
|
+
function routerPlugin(plugin) {
|
|
2152
|
+
routerPlugins.push(plugin);
|
|
2153
|
+
if (globalRouter?.isReady && plugin.onReady) {
|
|
2154
|
+
plugin.onReady();
|
|
2155
|
+
}
|
|
2156
|
+
let removeGuard = null;
|
|
2157
|
+
if (globalRouter && plugin.onNavigate) {
|
|
2158
|
+
removeGuard = globalRouter.afterEach((to, from) => {
|
|
2159
|
+
plugin.onNavigate?.(to, from);
|
|
2160
|
+
});
|
|
2161
|
+
}
|
|
2162
|
+
return () => {
|
|
2163
|
+
const idx = routerPlugins.indexOf(plugin);
|
|
2164
|
+
if (idx !== -1) routerPlugins.splice(idx, 1);
|
|
2165
|
+
removeGuard?.();
|
|
2166
|
+
};
|
|
2167
|
+
}
|
|
2168
|
+
var _routeTransitionOptions = null;
|
|
2169
|
+
function setRouteTransition(options) {
|
|
2170
|
+
_routeTransitionOptions = options;
|
|
2171
|
+
}
|
|
2172
|
+
function getRouteTransition() {
|
|
2173
|
+
return _routeTransitionOptions;
|
|
2174
|
+
}
|
|
2175
|
+
function createMemoryRouter(routes, _initialPath = "/") {
|
|
2176
|
+
const router2 = createRouter(routes, { mode: "hash" });
|
|
2177
|
+
return {
|
|
2178
|
+
router: router2,
|
|
2179
|
+
currentPath: () => router2.currentRoute.path,
|
|
2180
|
+
push: (path2) => router2.push(path2)
|
|
2181
|
+
};
|
|
2182
|
+
}
|
|
2183
|
+
|
|
2184
|
+
// src/plugins/routerSSR.ts
|
|
2185
|
+
init_ssr();
|
|
2186
|
+
function parseURL(url) {
|
|
2187
|
+
let remaining = url;
|
|
2188
|
+
let hash = "";
|
|
2189
|
+
let queryString = "";
|
|
2190
|
+
const hashIndex = remaining.indexOf("#");
|
|
2191
|
+
if (hashIndex !== -1) {
|
|
2192
|
+
hash = remaining.slice(hashIndex + 1);
|
|
2193
|
+
remaining = remaining.slice(0, hashIndex);
|
|
2194
|
+
}
|
|
2195
|
+
const queryIndex = remaining.indexOf("?");
|
|
2196
|
+
if (queryIndex !== -1) {
|
|
2197
|
+
queryString = remaining.slice(queryIndex + 1);
|
|
2198
|
+
remaining = remaining.slice(0, queryIndex);
|
|
2199
|
+
}
|
|
2200
|
+
const path2 = remaining || "/";
|
|
2201
|
+
const query = {};
|
|
2202
|
+
if (queryString) {
|
|
2203
|
+
const pairs = queryString.split("&");
|
|
2204
|
+
for (const pair of pairs) {
|
|
2205
|
+
if (!pair) continue;
|
|
2206
|
+
const eqIndex = pair.indexOf("=");
|
|
2207
|
+
if (eqIndex === -1) {
|
|
2208
|
+
query[decodeURIComponent(pair)] = "";
|
|
2209
|
+
} else {
|
|
2210
|
+
const key = decodeURIComponent(pair.slice(0, eqIndex));
|
|
2211
|
+
const value = decodeURIComponent(pair.slice(eqIndex + 1));
|
|
2212
|
+
query[key] = value;
|
|
2213
|
+
}
|
|
2214
|
+
}
|
|
2215
|
+
}
|
|
2216
|
+
return { path: path2, query, hash };
|
|
2217
|
+
}
|
|
2218
|
+
function compilePattern(routePath) {
|
|
2219
|
+
const keys = [];
|
|
2220
|
+
let pattern2 = "";
|
|
2221
|
+
const segments = routePath.split("/");
|
|
2222
|
+
for (let i2 = 0; i2 < segments.length; i2++) {
|
|
2223
|
+
const segment = segments[i2];
|
|
2224
|
+
if (i2 > 0) pattern2 += "\\/";
|
|
2225
|
+
if (!segment) {
|
|
2226
|
+
continue;
|
|
2227
|
+
}
|
|
2228
|
+
if (segment === "*") {
|
|
2229
|
+
keys.push("pathMatch");
|
|
2230
|
+
pattern2 += "(.*)";
|
|
2231
|
+
continue;
|
|
2232
|
+
}
|
|
2233
|
+
const namedWildcardMatch = segment.match(/^:([^*]+)\*$/);
|
|
2234
|
+
if (namedWildcardMatch) {
|
|
2235
|
+
keys.push(namedWildcardMatch[1]);
|
|
2236
|
+
pattern2 += "(.*)";
|
|
2237
|
+
continue;
|
|
2238
|
+
}
|
|
2239
|
+
const optionalMatch = segment.match(/^:([^?]+)\?$/);
|
|
2240
|
+
if (optionalMatch) {
|
|
2241
|
+
keys.push(optionalMatch[1]);
|
|
2242
|
+
pattern2 = pattern2.replace(/\\\/$/g, "");
|
|
2243
|
+
pattern2 += "(?:\\/([^\\/]+))?";
|
|
2244
|
+
continue;
|
|
2245
|
+
}
|
|
2246
|
+
const paramMatch = segment.match(/^:(.+)$/);
|
|
2247
|
+
if (paramMatch) {
|
|
2248
|
+
keys.push(paramMatch[1]);
|
|
2249
|
+
pattern2 += "([^\\/]+)";
|
|
2250
|
+
continue;
|
|
2251
|
+
}
|
|
2252
|
+
pattern2 += segment.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2253
|
+
}
|
|
2254
|
+
return {
|
|
2255
|
+
regex: new RegExp(`^${pattern2}$`),
|
|
2256
|
+
keys
|
|
2257
|
+
};
|
|
2258
|
+
}
|
|
2259
|
+
function matchRoute(path2, routes, parentPath = "", parentChain = []) {
|
|
2260
|
+
for (const route2 of routes) {
|
|
2261
|
+
const fullPath = normalizePath(`${parentPath}/${route2.path}`);
|
|
2262
|
+
if (route2.children && route2.children.length > 0) {
|
|
2263
|
+
const childResult = matchRoute(path2, route2.children, fullPath, [...parentChain, route2]);
|
|
2264
|
+
if (childResult) {
|
|
2265
|
+
return childResult;
|
|
2266
|
+
}
|
|
2267
|
+
}
|
|
2268
|
+
const compiled = compilePattern(fullPath);
|
|
2269
|
+
const match = path2.match(compiled.regex);
|
|
2270
|
+
if (match) {
|
|
2271
|
+
const params = {};
|
|
2272
|
+
for (let i2 = 0; i2 < compiled.keys.length; i2++) {
|
|
2273
|
+
if (match[i2 + 1] !== void 0) {
|
|
2274
|
+
params[compiled.keys[i2]] = decodeURIComponent(match[i2 + 1]);
|
|
2275
|
+
}
|
|
2276
|
+
}
|
|
2277
|
+
return {
|
|
2278
|
+
route: route2,
|
|
2279
|
+
params,
|
|
2280
|
+
matched: [...parentChain, route2]
|
|
2281
|
+
};
|
|
2282
|
+
}
|
|
2283
|
+
}
|
|
2284
|
+
return null;
|
|
2285
|
+
}
|
|
2286
|
+
function normalizePath(path2) {
|
|
2287
|
+
let normalized = path2.replace(/\/+/g, "/");
|
|
2288
|
+
if (!normalized.startsWith("/")) {
|
|
2289
|
+
normalized = `/${normalized}`;
|
|
2290
|
+
}
|
|
2291
|
+
if (normalized.length > 1 && normalized.endsWith("/")) {
|
|
2292
|
+
normalized = normalized.slice(0, -1);
|
|
2293
|
+
}
|
|
2294
|
+
return normalized;
|
|
2295
|
+
}
|
|
2296
|
+
var SSR_ROUTE_STATE_KEY = "__SIBU_ROUTE_STATE__";
|
|
2297
|
+
var MAX_REDIRECT_DEPTH = 10;
|
|
2298
|
+
function resolveServerRoute(url, routes) {
|
|
2299
|
+
return resolveServerRouteInternal(url, routes, 0);
|
|
2300
|
+
}
|
|
2301
|
+
function resolveServerRouteInternal(url, routes, depth) {
|
|
2302
|
+
const { path: path2, query, hash } = parseURL(url);
|
|
2303
|
+
const normalizedPath = normalizePath(path2);
|
|
2304
|
+
const match = matchRoute(normalizedPath, routes);
|
|
2305
|
+
if (!match) {
|
|
2306
|
+
return {
|
|
2307
|
+
route: {
|
|
2308
|
+
path: normalizedPath,
|
|
2309
|
+
params: {},
|
|
2310
|
+
query,
|
|
2311
|
+
hash,
|
|
2312
|
+
meta: {}
|
|
2313
|
+
},
|
|
2314
|
+
component: null
|
|
2315
|
+
};
|
|
2316
|
+
}
|
|
2317
|
+
const { route: matchedDef, params } = match;
|
|
2318
|
+
if (matchedDef.redirect) {
|
|
2319
|
+
if (depth >= MAX_REDIRECT_DEPTH) {
|
|
2320
|
+
return {
|
|
2321
|
+
route: {
|
|
2322
|
+
path: normalizedPath,
|
|
2323
|
+
params,
|
|
2324
|
+
query,
|
|
2325
|
+
hash,
|
|
2326
|
+
meta: matchedDef.meta || {},
|
|
2327
|
+
name: matchedDef.name
|
|
2328
|
+
},
|
|
2329
|
+
component: null,
|
|
2330
|
+
redirect: matchedDef.redirect
|
|
2331
|
+
};
|
|
2332
|
+
}
|
|
2333
|
+
if (typeof matchedDef.redirect === "string" && /^https?:\/\/|^\/\//i.test(matchedDef.redirect)) {
|
|
2334
|
+
console.warn(
|
|
2335
|
+
`[SibuJS Router SSR] Redirect to absolute URL "${matchedDef.redirect}" detected. Use relative paths for safer redirects.`
|
|
2336
|
+
);
|
|
2337
|
+
}
|
|
2338
|
+
return resolveServerRouteInternal(matchedDef.redirect, routes, depth + 1);
|
|
2339
|
+
}
|
|
2340
|
+
const routeState = {
|
|
2341
|
+
path: normalizedPath,
|
|
2342
|
+
params,
|
|
2343
|
+
query,
|
|
2344
|
+
hash,
|
|
2345
|
+
meta: matchedDef.meta || {},
|
|
2346
|
+
name: matchedDef.name
|
|
2347
|
+
};
|
|
2348
|
+
return {
|
|
2349
|
+
route: routeState,
|
|
2350
|
+
component: matchedDef.component || null,
|
|
2351
|
+
redirect: void 0
|
|
2352
|
+
};
|
|
2353
|
+
}
|
|
2354
|
+
function renderRouteToString(url, routes, _options) {
|
|
2355
|
+
const resolved = resolveServerRoute(url, routes);
|
|
2356
|
+
let html2 = "";
|
|
2357
|
+
if (resolved.component) {
|
|
2358
|
+
const element = resolved.component();
|
|
2359
|
+
html2 = renderToString(element);
|
|
2360
|
+
}
|
|
2361
|
+
return {
|
|
2362
|
+
html: html2,
|
|
2363
|
+
state: resolved.route
|
|
2364
|
+
};
|
|
2365
|
+
}
|
|
2366
|
+
function renderRouteToDocument(url, routes, options) {
|
|
2367
|
+
const { html: html2, state } = renderRouteToString(url, routes, options);
|
|
2368
|
+
const opts = options || {};
|
|
2369
|
+
const metaTags = (opts.meta || []).map(
|
|
2370
|
+
(attrs) => `<meta ${Object.entries(attrs).map(([k, v]) => `${k}="${escapeAttr2(v)}"`).join(" ")} />`
|
|
2371
|
+
).join("\n ");
|
|
2372
|
+
const linkTags = (opts.links || []).map(
|
|
2373
|
+
(attrs) => `<link ${Object.entries(attrs).map(([k, v]) => `${k}="${escapeAttr2(v)}"`).join(" ")} />`
|
|
2374
|
+
).join("\n ");
|
|
2375
|
+
const scriptTags = (opts.scripts || []).map((src) => `<script src="${escapeAttr2(src)}"></script>`).join("\n ");
|
|
2376
|
+
const stateScript = serializeRouteState(state);
|
|
2377
|
+
return `<!DOCTYPE html>
|
|
2378
|
+
<html>
|
|
2379
|
+
<head>
|
|
2380
|
+
<meta charset="UTF-8" />
|
|
2381
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
2382
|
+
${opts.title ? `<title>${escapeHtml2(opts.title)}</title>` : ""}
|
|
2383
|
+
${metaTags}
|
|
2384
|
+
${linkTags}
|
|
2385
|
+
${opts.headExtra || ""}
|
|
2386
|
+
</head>
|
|
2387
|
+
<body>
|
|
2388
|
+
<div id="app">${html2}</div>
|
|
2389
|
+
${stateScript}
|
|
2390
|
+
${scriptTags}
|
|
2391
|
+
</body>
|
|
2392
|
+
</html>`;
|
|
2393
|
+
}
|
|
2394
|
+
function serializeRouteState(state) {
|
|
2395
|
+
const json = JSON.stringify(state).replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/&/g, "\\u0026");
|
|
2396
|
+
return `<script>window.${SSR_ROUTE_STATE_KEY}=${json}</script>`;
|
|
2397
|
+
}
|
|
2398
|
+
function deserializeRouteState() {
|
|
2399
|
+
if (typeof window === "undefined") return void 0;
|
|
2400
|
+
return window[SSR_ROUTE_STATE_KEY];
|
|
2401
|
+
}
|
|
2402
|
+
function hydrateRouter(routes, options) {
|
|
2403
|
+
const serverState = deserializeRouteState();
|
|
2404
|
+
if (!serverState) {
|
|
2405
|
+
createRouter(routes);
|
|
2406
|
+
return;
|
|
2407
|
+
}
|
|
2408
|
+
createRouter(routes);
|
|
2409
|
+
const container = options?.container || document.getElementById("app");
|
|
2410
|
+
if (container && serverState.path) {
|
|
2411
|
+
const resolved = resolveServerRoute(serverState.path, routes);
|
|
2412
|
+
if (resolved.component) {
|
|
2413
|
+
Promise.resolve().then(() => (init_ssr(), ssr_exports)).then(({ hydrate: hydrate2 }) => {
|
|
2414
|
+
if (resolved.component) {
|
|
2415
|
+
hydrate2(resolved.component, container);
|
|
2416
|
+
}
|
|
2417
|
+
});
|
|
2418
|
+
}
|
|
2419
|
+
}
|
|
2420
|
+
}
|
|
2421
|
+
function createSSRRouter(routes) {
|
|
2422
|
+
return {
|
|
2423
|
+
resolve(url) {
|
|
2424
|
+
return resolveServerRoute(url, routes);
|
|
2425
|
+
},
|
|
2426
|
+
renderToString(url) {
|
|
2427
|
+
return renderRouteToString(url, routes);
|
|
2428
|
+
},
|
|
2429
|
+
renderToDocument(url, options) {
|
|
2430
|
+
return renderRouteToDocument(url, routes, options);
|
|
2431
|
+
}
|
|
2432
|
+
};
|
|
2433
|
+
}
|
|
2434
|
+
function escapeHtml2(str) {
|
|
2435
|
+
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
2436
|
+
}
|
|
2437
|
+
function escapeAttr2(str) {
|
|
2438
|
+
return str.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
2439
|
+
}
|
|
2440
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
2441
|
+
0 && (module.exports = {
|
|
2442
|
+
Outlet,
|
|
2443
|
+
Route,
|
|
2444
|
+
RouterLink,
|
|
2445
|
+
SibuRouter,
|
|
2446
|
+
Suspense,
|
|
2447
|
+
Trans,
|
|
2448
|
+
addRoute,
|
|
2449
|
+
afterEach,
|
|
2450
|
+
back,
|
|
2451
|
+
beforeEach,
|
|
2452
|
+
beforeResolve,
|
|
2453
|
+
buildURL,
|
|
2454
|
+
createMemoryRouter,
|
|
2455
|
+
createRouter,
|
|
2456
|
+
createSSRRouter,
|
|
2457
|
+
deserializeRouteState,
|
|
2458
|
+
destroyRouter,
|
|
2459
|
+
forward,
|
|
2460
|
+
getAvailableLocales,
|
|
2461
|
+
getLocale,
|
|
2462
|
+
getRouteInfo,
|
|
2463
|
+
getRouteTransition,
|
|
2464
|
+
go,
|
|
2465
|
+
hasRoute,
|
|
2466
|
+
hasTranslation,
|
|
2467
|
+
hydrateRouter,
|
|
2468
|
+
lazy,
|
|
2469
|
+
navigate,
|
|
2470
|
+
preloadRoute,
|
|
2471
|
+
push,
|
|
2472
|
+
registerTranslations,
|
|
2473
|
+
removeRoute,
|
|
2474
|
+
renderRouteToDocument,
|
|
2475
|
+
renderRouteToString,
|
|
2476
|
+
replace,
|
|
2477
|
+
resolveServerRoute,
|
|
2478
|
+
route,
|
|
2479
|
+
router,
|
|
2480
|
+
routerPlugin,
|
|
2481
|
+
routerState,
|
|
2482
|
+
serializeRouteState,
|
|
2483
|
+
setLocale,
|
|
2484
|
+
setRouteTransition,
|
|
2485
|
+
setRoutes,
|
|
2486
|
+
t
|
|
2487
|
+
});
|