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/build.cjs
ADDED
|
@@ -0,0 +1,4970 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// build.ts
|
|
31
|
+
var build_exports = {};
|
|
32
|
+
__export(build_exports, {
|
|
33
|
+
analyzeBundle: () => analyzeBundle,
|
|
34
|
+
analyzeStaticTemplates: () => analyzeStaticTemplates,
|
|
35
|
+
buildRouteEntries: () => buildRouteEntries,
|
|
36
|
+
cdnUrls: () => cdnUrls,
|
|
37
|
+
compileHtmlTemplates: () => compileHtmlTemplates,
|
|
38
|
+
createPureAnnotationsLoader: () => createPureAnnotationsLoader,
|
|
39
|
+
createViteConfig: () => createViteConfig,
|
|
40
|
+
createWebpackConfig: () => createWebpackConfig,
|
|
41
|
+
estimateImportSize: () => estimateImportSize,
|
|
42
|
+
fileToRoute: () => fileToRoute,
|
|
43
|
+
generateEslintConfig: () => generateEslintConfig,
|
|
44
|
+
generateImportMap: () => generateImportMap,
|
|
45
|
+
generateLanguageConfig: () => generateLanguageConfig,
|
|
46
|
+
generateTsConfig: () => generateTsConfig,
|
|
47
|
+
generateTypeStubs: () => generateTypeStubs,
|
|
48
|
+
generateVSCodeSnippets: () => generateVSCodeSnippets,
|
|
49
|
+
getComponentMetadata: () => getComponentMetadata,
|
|
50
|
+
lintRules: () => lintRules,
|
|
51
|
+
lintSource: () => lintSource,
|
|
52
|
+
moduleSizes: () => moduleSizes,
|
|
53
|
+
registerGlobal: () => registerGlobal,
|
|
54
|
+
sibuRouteSplitting: () => sibuRouteSplitting,
|
|
55
|
+
sibuVitePlugin: () => sibuVitePlugin,
|
|
56
|
+
sibuWebpackPlugin: () => sibuWebpackPlugin,
|
|
57
|
+
umdWrapper: () => umdWrapper,
|
|
58
|
+
validateTsConfig: () => validateTsConfig
|
|
59
|
+
});
|
|
60
|
+
module.exports = __toCommonJS(build_exports);
|
|
61
|
+
|
|
62
|
+
// src/build/compileTemplates.ts
|
|
63
|
+
var VOID_ELEMENTS = /* @__PURE__ */ new Set([
|
|
64
|
+
"area",
|
|
65
|
+
"base",
|
|
66
|
+
"br",
|
|
67
|
+
"col",
|
|
68
|
+
"embed",
|
|
69
|
+
"hr",
|
|
70
|
+
"img",
|
|
71
|
+
"input",
|
|
72
|
+
"link",
|
|
73
|
+
"meta",
|
|
74
|
+
"param",
|
|
75
|
+
"source",
|
|
76
|
+
"track",
|
|
77
|
+
"wbr"
|
|
78
|
+
]);
|
|
79
|
+
var SVG_TAGS = /* @__PURE__ */ new Set([
|
|
80
|
+
"svg",
|
|
81
|
+
"circle",
|
|
82
|
+
"ellipse",
|
|
83
|
+
"g",
|
|
84
|
+
"line",
|
|
85
|
+
"path",
|
|
86
|
+
"polygon",
|
|
87
|
+
"polyline",
|
|
88
|
+
"rect",
|
|
89
|
+
"text",
|
|
90
|
+
"tspan",
|
|
91
|
+
"defs",
|
|
92
|
+
"clipPath",
|
|
93
|
+
"mask",
|
|
94
|
+
"pattern",
|
|
95
|
+
"linearGradient",
|
|
96
|
+
"radialGradient",
|
|
97
|
+
"stop",
|
|
98
|
+
"use",
|
|
99
|
+
"symbol",
|
|
100
|
+
"marker"
|
|
101
|
+
]);
|
|
102
|
+
function findHtmlTemplates(code2) {
|
|
103
|
+
const results = [];
|
|
104
|
+
const tagRegex = /\bhtml\s*`/g;
|
|
105
|
+
let match2;
|
|
106
|
+
while ((match2 = tagRegex.exec(code2)) !== null) {
|
|
107
|
+
const start = match2.index;
|
|
108
|
+
const backtickStart = code2.indexOf("`", start + 4);
|
|
109
|
+
if (backtickStart === -1) continue;
|
|
110
|
+
const parsed = parseTemplateLiteral(code2, backtickStart);
|
|
111
|
+
if (!parsed) continue;
|
|
112
|
+
results.push({
|
|
113
|
+
start,
|
|
114
|
+
end: parsed.end,
|
|
115
|
+
strings: parsed.strings,
|
|
116
|
+
exprCount: parsed.exprCount
|
|
117
|
+
});
|
|
118
|
+
tagRegex.lastIndex = parsed.end;
|
|
119
|
+
}
|
|
120
|
+
return results;
|
|
121
|
+
}
|
|
122
|
+
function parseTemplateLiteral(code2, openBacktick) {
|
|
123
|
+
const strings = [];
|
|
124
|
+
let exprCount = 0;
|
|
125
|
+
let pos = openBacktick + 1;
|
|
126
|
+
let current = "";
|
|
127
|
+
while (pos < code2.length) {
|
|
128
|
+
const ch = code2[pos];
|
|
129
|
+
if (ch === "`") {
|
|
130
|
+
strings.push(current);
|
|
131
|
+
return { end: pos + 1, strings, exprCount };
|
|
132
|
+
}
|
|
133
|
+
if (ch === "$" && pos + 1 < code2.length && code2[pos + 1] === "{") {
|
|
134
|
+
strings.push(current);
|
|
135
|
+
current = "";
|
|
136
|
+
exprCount++;
|
|
137
|
+
pos += 2;
|
|
138
|
+
let depth = 1;
|
|
139
|
+
while (pos < code2.length && depth > 0) {
|
|
140
|
+
const c = code2[pos];
|
|
141
|
+
if (c === "{") depth++;
|
|
142
|
+
else if (c === "}") depth--;
|
|
143
|
+
else if (c === '"' || c === "'" || c === "`") {
|
|
144
|
+
pos = skipString(code2, pos);
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
if (depth > 0) pos++;
|
|
148
|
+
}
|
|
149
|
+
if (depth !== 0) return null;
|
|
150
|
+
pos++;
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
if (ch === "\\") {
|
|
154
|
+
current += code2[pos] + (code2[pos + 1] || "");
|
|
155
|
+
pos += 2;
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
current += ch;
|
|
159
|
+
pos++;
|
|
160
|
+
}
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
function skipString(code2, start) {
|
|
164
|
+
const quote = code2[start];
|
|
165
|
+
let pos = start + 1;
|
|
166
|
+
while (pos < code2.length) {
|
|
167
|
+
if (code2[pos] === "\\") {
|
|
168
|
+
pos += 2;
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
if (code2[pos] === quote) return pos + 1;
|
|
172
|
+
if (quote === "`" && code2[pos] === "$" && code2[pos + 1] === "{") {
|
|
173
|
+
pos += 2;
|
|
174
|
+
let depth = 1;
|
|
175
|
+
while (pos < code2.length && depth > 0) {
|
|
176
|
+
if (code2[pos] === "{") depth++;
|
|
177
|
+
else if (code2[pos] === "}") depth--;
|
|
178
|
+
else if (code2[pos] === '"' || code2[pos] === "'" || code2[pos] === "`") {
|
|
179
|
+
pos = skipString(code2, pos);
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
if (depth > 0) pos++;
|
|
183
|
+
}
|
|
184
|
+
pos++;
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
187
|
+
pos++;
|
|
188
|
+
}
|
|
189
|
+
return pos;
|
|
190
|
+
}
|
|
191
|
+
function parseTemplateToAST(strings) {
|
|
192
|
+
const exprCount = strings.length - 1;
|
|
193
|
+
let template2 = strings[0];
|
|
194
|
+
for (let i2 = 0; i2 < exprCount; i2++) {
|
|
195
|
+
template2 += `\0${i2}\0${strings[i2 + 1]}`;
|
|
196
|
+
}
|
|
197
|
+
let pos = 0;
|
|
198
|
+
const len = template2.length;
|
|
199
|
+
function skipWs() {
|
|
200
|
+
while (pos < len && /\s/.test(template2[pos])) pos++;
|
|
201
|
+
}
|
|
202
|
+
function tryExprIdx() {
|
|
203
|
+
if (template2[pos] !== "\0") return -1;
|
|
204
|
+
const start = pos;
|
|
205
|
+
pos++;
|
|
206
|
+
let idxStr = "";
|
|
207
|
+
while (pos < len && template2[pos] !== "\0") idxStr += template2[pos++];
|
|
208
|
+
if (pos < len) pos++;
|
|
209
|
+
const idx = Number.parseInt(idxStr, 10);
|
|
210
|
+
if (Number.isNaN(idx) || idx < 0 || idx >= exprCount) {
|
|
211
|
+
pos = start;
|
|
212
|
+
return -1;
|
|
213
|
+
}
|
|
214
|
+
return idx;
|
|
215
|
+
}
|
|
216
|
+
function readTagName() {
|
|
217
|
+
let name = "";
|
|
218
|
+
while (pos < len && /[a-zA-Z0-9-]/.test(template2[pos])) name += template2[pos++];
|
|
219
|
+
return name;
|
|
220
|
+
}
|
|
221
|
+
function parseAttrValue() {
|
|
222
|
+
skipWs();
|
|
223
|
+
if (template2[pos] !== "=") return { kind: "bool" };
|
|
224
|
+
pos++;
|
|
225
|
+
skipWs();
|
|
226
|
+
const exprIdx = tryExprIdx();
|
|
227
|
+
if (exprIdx >= 0) return { kind: "expr", index: exprIdx };
|
|
228
|
+
const quote = template2[pos];
|
|
229
|
+
if (quote === '"' || quote === "'") {
|
|
230
|
+
pos++;
|
|
231
|
+
const parts = [];
|
|
232
|
+
let current = "";
|
|
233
|
+
while (pos < len && template2[pos] !== quote) {
|
|
234
|
+
const innerIdx = tryExprIdx();
|
|
235
|
+
if (innerIdx >= 0) {
|
|
236
|
+
if (current) parts.push({ kind: "static", value: current });
|
|
237
|
+
current = "";
|
|
238
|
+
parts.push({ kind: "expr", index: innerIdx });
|
|
239
|
+
} else {
|
|
240
|
+
current += template2[pos++];
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
if (pos < len) pos++;
|
|
244
|
+
if (current) parts.push({ kind: "static", value: current });
|
|
245
|
+
if (parts.length === 1 && parts[0].kind === "static") {
|
|
246
|
+
return { kind: "static", value: parts[0].value };
|
|
247
|
+
}
|
|
248
|
+
if (parts.some((p2) => p2.kind === "expr")) {
|
|
249
|
+
return { kind: "mixed", parts };
|
|
250
|
+
}
|
|
251
|
+
return { kind: "static", value: parts.map((p2) => p2.value).join("") };
|
|
252
|
+
}
|
|
253
|
+
let val = "";
|
|
254
|
+
while (pos < len && !/[\s>/]/.test(template2[pos])) val += template2[pos++];
|
|
255
|
+
return { kind: "static", value: val };
|
|
256
|
+
}
|
|
257
|
+
function parseAttrs() {
|
|
258
|
+
const attrs = [];
|
|
259
|
+
while (pos < len) {
|
|
260
|
+
skipWs();
|
|
261
|
+
if (template2[pos] === ">" || template2[pos] === "/") break;
|
|
262
|
+
let attrName = "";
|
|
263
|
+
while (pos < len && /[a-zA-Z0-9\-:_.]/.test(template2[pos])) attrName += template2[pos++];
|
|
264
|
+
if (!attrName) break;
|
|
265
|
+
const val = parseAttrValue();
|
|
266
|
+
if (attrName.startsWith("on:")) {
|
|
267
|
+
if (val.kind === "expr") {
|
|
268
|
+
attrs.push({ name: attrName.slice(3), value: { kind: "event", index: val.index } });
|
|
269
|
+
}
|
|
270
|
+
} else {
|
|
271
|
+
attrs.push({ name: attrName, value: val });
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
return attrs;
|
|
275
|
+
}
|
|
276
|
+
function collapseWs(s2) {
|
|
277
|
+
return s2.replace(/\s+/g, " ");
|
|
278
|
+
}
|
|
279
|
+
function parseTextChildren(children) {
|
|
280
|
+
let text2 = "";
|
|
281
|
+
while (pos < len && template2[pos] !== "<") {
|
|
282
|
+
const idx = tryExprIdx();
|
|
283
|
+
if (idx >= 0) {
|
|
284
|
+
const collapsed2 = collapseWs(text2);
|
|
285
|
+
if (collapsed2) children.push({ kind: "text", value: collapsed2 });
|
|
286
|
+
text2 = "";
|
|
287
|
+
children.push({ kind: "expr", index: idx });
|
|
288
|
+
} else {
|
|
289
|
+
text2 += template2[pos++];
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
const collapsed = collapseWs(text2);
|
|
293
|
+
if (collapsed) children.push({ kind: "text", value: collapsed });
|
|
294
|
+
}
|
|
295
|
+
function parseChildren() {
|
|
296
|
+
const children = [];
|
|
297
|
+
while (pos < len) {
|
|
298
|
+
if (template2[pos] === "<" && pos + 1 < len && template2[pos + 1] === "/") break;
|
|
299
|
+
if (template2[pos] === "<") {
|
|
300
|
+
pos++;
|
|
301
|
+
const tag = readTagName();
|
|
302
|
+
const attrs = parseAttrs();
|
|
303
|
+
skipWs();
|
|
304
|
+
const isVoid = VOID_ELEMENTS.has(tag);
|
|
305
|
+
const isSelfClosing = template2[pos] === "/";
|
|
306
|
+
if (isSelfClosing) pos++;
|
|
307
|
+
if (pos < len) pos++;
|
|
308
|
+
if (isVoid || isSelfClosing) {
|
|
309
|
+
children.push({ kind: "element", el: { tag, attrs, children: [] } });
|
|
310
|
+
} else {
|
|
311
|
+
const inner = parseChildren();
|
|
312
|
+
if (template2[pos] === "<" && pos + 1 < len && template2[pos + 1] === "/") {
|
|
313
|
+
pos += 2;
|
|
314
|
+
readTagName();
|
|
315
|
+
skipWs();
|
|
316
|
+
if (pos < len && template2[pos] === ">") pos++;
|
|
317
|
+
}
|
|
318
|
+
children.push({ kind: "element", el: { tag, attrs, children: inner } });
|
|
319
|
+
}
|
|
320
|
+
} else {
|
|
321
|
+
parseTextChildren(children);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
return children;
|
|
325
|
+
}
|
|
326
|
+
return parseChildren();
|
|
327
|
+
}
|
|
328
|
+
function generateElement(el, valuesVar) {
|
|
329
|
+
const tag = el.tag;
|
|
330
|
+
const isSvg = SVG_TAGS.has(tag);
|
|
331
|
+
const parts = [];
|
|
332
|
+
for (const attr of el.attrs) {
|
|
333
|
+
const v = attr.value;
|
|
334
|
+
switch (v.kind) {
|
|
335
|
+
case "static":
|
|
336
|
+
parts.push(`${JSON.stringify(attr.name)}: ${JSON.stringify(v.value)}`);
|
|
337
|
+
break;
|
|
338
|
+
case "expr":
|
|
339
|
+
parts.push(`${JSON.stringify(attr.name)}: ${valuesVar}[${v.index}]`);
|
|
340
|
+
break;
|
|
341
|
+
case "mixed": {
|
|
342
|
+
const concat = v.parts.map((p2) => p2.kind === "static" ? JSON.stringify(p2.value) : `String(${valuesVar}[${p2.index}])`).join(" + ");
|
|
343
|
+
parts.push(`${JSON.stringify(attr.name)}: ${concat}`);
|
|
344
|
+
break;
|
|
345
|
+
}
|
|
346
|
+
case "bool":
|
|
347
|
+
parts.push(`${JSON.stringify(attr.name)}: true`);
|
|
348
|
+
break;
|
|
349
|
+
case "event":
|
|
350
|
+
break;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
const events = el.attrs.filter((a2) => a2.value.kind === "event");
|
|
354
|
+
if (events.length > 0) {
|
|
355
|
+
const eventEntries = events.map((a2) => {
|
|
356
|
+
const v = a2.value;
|
|
357
|
+
return `${JSON.stringify(a2.name)}: ${valuesVar}[${v.index}]`;
|
|
358
|
+
});
|
|
359
|
+
parts.push(`on: { ${eventEntries.join(", ")} }`);
|
|
360
|
+
}
|
|
361
|
+
if (el.children.length > 0) {
|
|
362
|
+
const childExprs = el.children.map((c) => generateChild(c, valuesVar));
|
|
363
|
+
if (childExprs.length === 1) {
|
|
364
|
+
parts.push(`nodes: ${childExprs[0]}`);
|
|
365
|
+
} else {
|
|
366
|
+
parts.push(`nodes: [${childExprs.join(", ")}]`);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
const propsStr = parts.length > 0 ? `{ ${parts.join(", ")} }` : void 0;
|
|
370
|
+
if (isSvg) {
|
|
371
|
+
return propsStr ? `__sbTagFactory(${JSON.stringify(tag)}, __sbSVG_NS)(${propsStr})` : `__sbTagFactory(${JSON.stringify(tag)}, __sbSVG_NS)({})`;
|
|
372
|
+
}
|
|
373
|
+
return propsStr ? `${tag}(${propsStr})` : `${tag}({})`;
|
|
374
|
+
}
|
|
375
|
+
function generateChild(child, valuesVar) {
|
|
376
|
+
switch (child.kind) {
|
|
377
|
+
case "element":
|
|
378
|
+
return generateElement(child.el, valuesVar);
|
|
379
|
+
case "text":
|
|
380
|
+
return JSON.stringify(child.value);
|
|
381
|
+
case "expr":
|
|
382
|
+
return `${valuesVar}[${child.index}]`;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
function compileHtmlTemplates(code2) {
|
|
386
|
+
const templates = findHtmlTemplates(code2);
|
|
387
|
+
if (templates.length === 0) {
|
|
388
|
+
return { code: null, usedTags: /* @__PURE__ */ new Set(), usesSvg: false, compiledCount: 0 };
|
|
389
|
+
}
|
|
390
|
+
const usedTags = /* @__PURE__ */ new Set();
|
|
391
|
+
let usesSvg = false;
|
|
392
|
+
let result = code2;
|
|
393
|
+
for (let i2 = templates.length - 1; i2 >= 0; i2--) {
|
|
394
|
+
const tmpl = templates[i2];
|
|
395
|
+
const ast = parseTemplateToAST(tmpl.strings);
|
|
396
|
+
collectTags(ast, usedTags);
|
|
397
|
+
if (Array.from(usedTags).some((t) => SVG_TAGS.has(t))) usesSvg = true;
|
|
398
|
+
const valuesVar = "__v";
|
|
399
|
+
const childExprs = ast.map((c) => generateChild(c, valuesVar));
|
|
400
|
+
let compiled;
|
|
401
|
+
if (tmpl.exprCount === 0) {
|
|
402
|
+
compiled = childExprs.length === 1 ? childExprs[0] : childExprs[0];
|
|
403
|
+
} else {
|
|
404
|
+
const body2 = childExprs.length === 1 ? childExprs[0] : childExprs[0];
|
|
405
|
+
const exprSource = extractExpressions(code2, tmpl.start, tmpl.end, tmpl.exprCount);
|
|
406
|
+
compiled = `((${valuesVar}) => ${body2})([${exprSource.join(", ")}])`;
|
|
407
|
+
}
|
|
408
|
+
result = result.slice(0, tmpl.start) + compiled + result.slice(tmpl.end);
|
|
409
|
+
}
|
|
410
|
+
return { code: result, usedTags, usesSvg, compiledCount: templates.length };
|
|
411
|
+
}
|
|
412
|
+
function collectTags(children, tags) {
|
|
413
|
+
for (const child of children) {
|
|
414
|
+
if (child.kind === "element") {
|
|
415
|
+
tags.add(child.el.tag);
|
|
416
|
+
collectTags(child.el.children, tags);
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
function extractExpressions(code2, templateStart, templateEnd, count) {
|
|
421
|
+
const exprs = [];
|
|
422
|
+
const backtickStart = code2.indexOf("`", templateStart + 4);
|
|
423
|
+
let pos = backtickStart + 1;
|
|
424
|
+
for (let i2 = 0; i2 < count; i2++) {
|
|
425
|
+
while (pos < templateEnd) {
|
|
426
|
+
if (code2[pos] === "$" && code2[pos + 1] === "{") {
|
|
427
|
+
pos += 2;
|
|
428
|
+
break;
|
|
429
|
+
}
|
|
430
|
+
if (code2[pos] === "\\") {
|
|
431
|
+
pos += 2;
|
|
432
|
+
continue;
|
|
433
|
+
}
|
|
434
|
+
pos++;
|
|
435
|
+
}
|
|
436
|
+
const exprStart = pos;
|
|
437
|
+
let depth = 1;
|
|
438
|
+
while (pos < templateEnd && depth > 0) {
|
|
439
|
+
const c = code2[pos];
|
|
440
|
+
if (c === "{") depth++;
|
|
441
|
+
else if (c === "}") {
|
|
442
|
+
depth--;
|
|
443
|
+
if (depth === 0) break;
|
|
444
|
+
} else if (c === '"' || c === "'" || c === "`") {
|
|
445
|
+
pos = skipString(code2, pos);
|
|
446
|
+
continue;
|
|
447
|
+
}
|
|
448
|
+
pos++;
|
|
449
|
+
}
|
|
450
|
+
exprs.push(code2.slice(exprStart, pos).trim());
|
|
451
|
+
pos++;
|
|
452
|
+
}
|
|
453
|
+
return exprs;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
// src/build/staticAnalysis.ts
|
|
457
|
+
var HTML_TAGS = /* @__PURE__ */ new Set([
|
|
458
|
+
"div",
|
|
459
|
+
"span",
|
|
460
|
+
"section",
|
|
461
|
+
"article",
|
|
462
|
+
"header",
|
|
463
|
+
"footer",
|
|
464
|
+
"nav",
|
|
465
|
+
"main",
|
|
466
|
+
"aside",
|
|
467
|
+
"p",
|
|
468
|
+
"h1",
|
|
469
|
+
"h2",
|
|
470
|
+
"h3",
|
|
471
|
+
"h4",
|
|
472
|
+
"h5",
|
|
473
|
+
"h6",
|
|
474
|
+
"blockquote",
|
|
475
|
+
"li",
|
|
476
|
+
"ol",
|
|
477
|
+
"ul",
|
|
478
|
+
"pre",
|
|
479
|
+
"a",
|
|
480
|
+
"b",
|
|
481
|
+
"em",
|
|
482
|
+
"i",
|
|
483
|
+
"strong",
|
|
484
|
+
"small",
|
|
485
|
+
"code",
|
|
486
|
+
"mark",
|
|
487
|
+
"img",
|
|
488
|
+
"br",
|
|
489
|
+
"hr",
|
|
490
|
+
"input",
|
|
491
|
+
"button",
|
|
492
|
+
"form",
|
|
493
|
+
"label",
|
|
494
|
+
"select",
|
|
495
|
+
"textarea",
|
|
496
|
+
"option",
|
|
497
|
+
"table",
|
|
498
|
+
"tbody",
|
|
499
|
+
"thead",
|
|
500
|
+
"tfoot",
|
|
501
|
+
"tr",
|
|
502
|
+
"td",
|
|
503
|
+
"th",
|
|
504
|
+
"details",
|
|
505
|
+
"summary",
|
|
506
|
+
"dialog"
|
|
507
|
+
]);
|
|
508
|
+
var VOID_ELEMENTS2 = /* @__PURE__ */ new Set([
|
|
509
|
+
"br",
|
|
510
|
+
"hr",
|
|
511
|
+
"img",
|
|
512
|
+
"input",
|
|
513
|
+
"meta",
|
|
514
|
+
"link",
|
|
515
|
+
"area",
|
|
516
|
+
"base",
|
|
517
|
+
"col",
|
|
518
|
+
"embed",
|
|
519
|
+
"param",
|
|
520
|
+
"source",
|
|
521
|
+
"track",
|
|
522
|
+
"wbr"
|
|
523
|
+
]);
|
|
524
|
+
function analyzeStaticTemplates(code2) {
|
|
525
|
+
const patterns = [];
|
|
526
|
+
const tagCallRegex = new RegExp(`\\b(${Array.from(HTML_TAGS).join("|")})\\s*\\(\\s*\\{([^}]*)\\}\\s*\\)`, "g");
|
|
527
|
+
let match2;
|
|
528
|
+
while ((match2 = tagCallRegex.exec(code2)) !== null) {
|
|
529
|
+
const [fullMatch, tag, propsContent] = match2;
|
|
530
|
+
const start = match2.index;
|
|
531
|
+
const end = start + fullMatch.length;
|
|
532
|
+
if (isStaticPropsContent(propsContent)) {
|
|
533
|
+
const templateHtml = propsToHtml(tag, propsContent);
|
|
534
|
+
if (templateHtml) {
|
|
535
|
+
patterns.push({ original: fullMatch, tag, templateHtml, start, end });
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
return {
|
|
540
|
+
hasStaticPatterns: patterns.length > 0,
|
|
541
|
+
patterns
|
|
542
|
+
};
|
|
543
|
+
}
|
|
544
|
+
function isStaticPropsContent(propsContent) {
|
|
545
|
+
if (/=>|function\s*\(|\bref\b|\bon\s*:/.test(propsContent)) {
|
|
546
|
+
return false;
|
|
547
|
+
}
|
|
548
|
+
const props = propsContent.split(",").map((p2) => p2.trim()).filter(Boolean);
|
|
549
|
+
for (const prop of props) {
|
|
550
|
+
const colonIndex = prop.indexOf(":");
|
|
551
|
+
if (colonIndex === -1) continue;
|
|
552
|
+
const value = prop.substring(colonIndex + 1).trim();
|
|
553
|
+
if (!isStaticValue(value)) {
|
|
554
|
+
return false;
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
return true;
|
|
558
|
+
}
|
|
559
|
+
function isStaticValue(value) {
|
|
560
|
+
if (/^["'].*["']$/.test(value)) return true;
|
|
561
|
+
if (/^-?\d+(\.\d+)?$/.test(value)) return true;
|
|
562
|
+
if (value === "true" || value === "false") return true;
|
|
563
|
+
if (value === "null" || value === "undefined") return true;
|
|
564
|
+
return false;
|
|
565
|
+
}
|
|
566
|
+
function propsToHtml(tag, propsContent) {
|
|
567
|
+
const attrs = [];
|
|
568
|
+
let nodesContent = "";
|
|
569
|
+
const props = propsContent.split(",").map((p2) => p2.trim()).filter(Boolean);
|
|
570
|
+
for (const prop of props) {
|
|
571
|
+
const colonIndex = prop.indexOf(":");
|
|
572
|
+
if (colonIndex === -1) continue;
|
|
573
|
+
const key = prop.substring(0, colonIndex).trim();
|
|
574
|
+
let value = prop.substring(colonIndex + 1).trim();
|
|
575
|
+
if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
|
|
576
|
+
value = value.slice(1, -1);
|
|
577
|
+
}
|
|
578
|
+
if (key === "nodes") {
|
|
579
|
+
nodesContent = escapeHtml(value);
|
|
580
|
+
} else if (key === "class" || key === "id") {
|
|
581
|
+
attrs.push(`${key}="${escapeAttr(value)}"`);
|
|
582
|
+
} else if (key !== "on" && key !== "ref" && key !== "style") {
|
|
583
|
+
attrs.push(`${key}="${escapeAttr(String(value))}"`);
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
const attrStr = attrs.length > 0 ? ` ${attrs.join(" ")}` : "";
|
|
587
|
+
if (VOID_ELEMENTS2.has(tag)) {
|
|
588
|
+
return `<${tag}${attrStr} />`;
|
|
589
|
+
}
|
|
590
|
+
return `<${tag}${attrStr}>${nodesContent}</${tag}>`;
|
|
591
|
+
}
|
|
592
|
+
function escapeHtml(str) {
|
|
593
|
+
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
594
|
+
}
|
|
595
|
+
function escapeAttr(str) {
|
|
596
|
+
return str.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
// src/build/vite.ts
|
|
600
|
+
var SVG_TAGS_SET = /* @__PURE__ */ new Set([
|
|
601
|
+
"svg",
|
|
602
|
+
"circle",
|
|
603
|
+
"ellipse",
|
|
604
|
+
"g",
|
|
605
|
+
"line",
|
|
606
|
+
"path",
|
|
607
|
+
"polygon",
|
|
608
|
+
"polyline",
|
|
609
|
+
"rect",
|
|
610
|
+
"text",
|
|
611
|
+
"tspan",
|
|
612
|
+
"defs",
|
|
613
|
+
"clipPath",
|
|
614
|
+
"mask",
|
|
615
|
+
"pattern",
|
|
616
|
+
"linearGradient",
|
|
617
|
+
"radialGradient",
|
|
618
|
+
"stop",
|
|
619
|
+
"use",
|
|
620
|
+
"symbol",
|
|
621
|
+
"marker"
|
|
622
|
+
]);
|
|
623
|
+
var DEFAULT_INCLUDE = ["**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx"];
|
|
624
|
+
var DEFAULT_EXCLUDE = ["node_modules/**", "dist/**", "**/*.test.*", "**/*.spec.*"];
|
|
625
|
+
function matchesPattern(filePath, patterns) {
|
|
626
|
+
const normalized = filePath.replace(/\\/g, "/");
|
|
627
|
+
return patterns.some((pattern2) => {
|
|
628
|
+
const regexStr = pattern2.replace(/\./g, "\\.").replace(/\*\*/g, "{{GLOBSTAR}}").replace(/\*/g, "[^/]*").replace(/\{\{GLOBSTAR\}\}/g, ".*");
|
|
629
|
+
return new RegExp(regexStr).test(normalized);
|
|
630
|
+
});
|
|
631
|
+
}
|
|
632
|
+
function injectPureAnnotations(code2) {
|
|
633
|
+
const sibuFactories = [
|
|
634
|
+
"tagFactory",
|
|
635
|
+
"context",
|
|
636
|
+
"composable",
|
|
637
|
+
"defineComponent",
|
|
638
|
+
"withProps",
|
|
639
|
+
"withDefaults",
|
|
640
|
+
"pure",
|
|
641
|
+
"noSideEffect"
|
|
642
|
+
];
|
|
643
|
+
let result = code2;
|
|
644
|
+
for (const factory of sibuFactories) {
|
|
645
|
+
const pattern2 = new RegExp(`(?<!/\\*#__PURE__\\*/\\s*)\\b(${factory})\\s*\\(`, "g");
|
|
646
|
+
result = result.replace(pattern2, "/*#__PURE__*/ $1(");
|
|
647
|
+
}
|
|
648
|
+
return result;
|
|
649
|
+
}
|
|
650
|
+
function injectDevHelpers(code2) {
|
|
651
|
+
if (code2.includes('from "sibu"') || code2.includes("from 'sibu'") || code2.includes('from "sibu/') || code2.includes("from 'sibu/")) {
|
|
652
|
+
return `/* SibuJS Dev Mode */
|
|
653
|
+
if (typeof globalThis !== 'undefined') { (globalThis as unknown as Record<string, unknown>).__SIBU_DEV__ = true; }
|
|
654
|
+
${code2}`;
|
|
655
|
+
}
|
|
656
|
+
return code2;
|
|
657
|
+
}
|
|
658
|
+
function sibuVitePlugin(options = {}) {
|
|
659
|
+
const {
|
|
660
|
+
hmr = true,
|
|
661
|
+
pureAnnotations = true,
|
|
662
|
+
include = DEFAULT_INCLUDE,
|
|
663
|
+
exclude = DEFAULT_EXCLUDE,
|
|
664
|
+
devMode,
|
|
665
|
+
staticOptimize,
|
|
666
|
+
compileTemplates
|
|
667
|
+
} = options;
|
|
668
|
+
const isDevMode = devMode ?? (typeof process !== "undefined" && process.env?.NODE_ENV !== "production");
|
|
669
|
+
return {
|
|
670
|
+
name: "sibu-vite-plugin",
|
|
671
|
+
enforce: "pre",
|
|
672
|
+
config() {
|
|
673
|
+
return {
|
|
674
|
+
// Optimize dependency pre-bundling for sibu
|
|
675
|
+
optimizeDeps: {
|
|
676
|
+
include: ["sibu"]
|
|
677
|
+
},
|
|
678
|
+
// Ensure sibu is treated correctly for SSR
|
|
679
|
+
ssr: {
|
|
680
|
+
noExternal: ["sibu"]
|
|
681
|
+
},
|
|
682
|
+
// Define global constants for dead code elimination
|
|
683
|
+
define: {
|
|
684
|
+
__SIBU_DEV__: JSON.stringify(isDevMode),
|
|
685
|
+
__SIBU_HMR__: JSON.stringify(hmr)
|
|
686
|
+
},
|
|
687
|
+
// Enable source maps in dev
|
|
688
|
+
build: {
|
|
689
|
+
sourcemap: isDevMode
|
|
690
|
+
}
|
|
691
|
+
};
|
|
692
|
+
},
|
|
693
|
+
transform(code2, id) {
|
|
694
|
+
if (!matchesPattern(id, include) || matchesPattern(id, exclude)) {
|
|
695
|
+
return null;
|
|
696
|
+
}
|
|
697
|
+
let transformed = code2;
|
|
698
|
+
let modified = false;
|
|
699
|
+
if (pureAnnotations) {
|
|
700
|
+
const annotated = injectPureAnnotations(transformed);
|
|
701
|
+
if (annotated !== transformed) {
|
|
702
|
+
transformed = annotated;
|
|
703
|
+
modified = true;
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
if (isDevMode) {
|
|
707
|
+
const withDevHelpers = injectDevHelpers(transformed);
|
|
708
|
+
if (withDevHelpers !== transformed) {
|
|
709
|
+
transformed = withDevHelpers;
|
|
710
|
+
modified = true;
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
const shouldCompile = compileTemplates ?? !isDevMode;
|
|
714
|
+
if (shouldCompile && transformed.includes("html`")) {
|
|
715
|
+
const compiled = compileHtmlTemplates(transformed);
|
|
716
|
+
if (compiled.code) {
|
|
717
|
+
const tagImports = Array.from(compiled.usedTags).filter((t) => !SVG_TAGS_SET.has(t));
|
|
718
|
+
const needsSvg = compiled.usesSvg;
|
|
719
|
+
const imports = [];
|
|
720
|
+
if (tagImports.length > 0) {
|
|
721
|
+
imports.push(`import { ${tagImports.join(", ")} } from "sibu";`);
|
|
722
|
+
}
|
|
723
|
+
if (needsSvg) {
|
|
724
|
+
imports.push(`import { tagFactory as __sbTagFactory, SVG_NS as __sbSVG_NS } from "sibu";`);
|
|
725
|
+
}
|
|
726
|
+
const newImports = imports.filter((imp) => !transformed.includes(imp));
|
|
727
|
+
if (newImports.length > 0) {
|
|
728
|
+
compiled.code = `${newImports.join("\n")}
|
|
729
|
+
${compiled.code}`;
|
|
730
|
+
}
|
|
731
|
+
transformed = compiled.code;
|
|
732
|
+
modified = true;
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
const shouldOptimize = staticOptimize ?? !isDevMode;
|
|
736
|
+
if (shouldOptimize) {
|
|
737
|
+
const analysis = analyzeStaticTemplates(transformed);
|
|
738
|
+
if (analysis.hasStaticPatterns) {
|
|
739
|
+
const sorted = [...analysis.patterns].sort((a2, b2) => b2.start - a2.start);
|
|
740
|
+
for (const pattern2 of sorted) {
|
|
741
|
+
const replacement = `staticTemplate(${JSON.stringify(pattern2.templateHtml)})`;
|
|
742
|
+
transformed = transformed.slice(0, pattern2.start) + replacement + transformed.slice(pattern2.end);
|
|
743
|
+
}
|
|
744
|
+
if (!transformed.includes("import") || !transformed.includes("staticTemplate")) {
|
|
745
|
+
transformed = `import { staticTemplate } from "sibu";
|
|
746
|
+
${transformed}`;
|
|
747
|
+
}
|
|
748
|
+
modified = true;
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
if (!modified) return null;
|
|
752
|
+
return {
|
|
753
|
+
code: transformed,
|
|
754
|
+
map: void 0
|
|
755
|
+
// Let Vite handle source maps
|
|
756
|
+
};
|
|
757
|
+
},
|
|
758
|
+
handleHotUpdate(ctx) {
|
|
759
|
+
if (!hmr) return;
|
|
760
|
+
const { file } = ctx;
|
|
761
|
+
if (matchesPattern(file, include) && !matchesPattern(file, exclude)) {
|
|
762
|
+
if (isDevMode) {
|
|
763
|
+
console.log(`[sibu-vite-plugin] HMR update: ${file}`);
|
|
764
|
+
}
|
|
765
|
+
return;
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
};
|
|
769
|
+
}
|
|
770
|
+
function createViteConfig(options = {}) {
|
|
771
|
+
const { entry = "src/main.ts", outDir = "dist", ssr = false, overrides = {} } = options;
|
|
772
|
+
const baseConfig = {
|
|
773
|
+
// Use the SibuJS Vite plugin
|
|
774
|
+
plugins: [sibuVitePlugin()],
|
|
775
|
+
// Build configuration
|
|
776
|
+
build: {
|
|
777
|
+
outDir,
|
|
778
|
+
target: "es2020",
|
|
779
|
+
minify: "esbuild",
|
|
780
|
+
sourcemap: true,
|
|
781
|
+
// Library mode configuration when building a library
|
|
782
|
+
lib: ssr ? void 0 : {
|
|
783
|
+
entry,
|
|
784
|
+
formats: ["es", "cjs"]
|
|
785
|
+
},
|
|
786
|
+
// Rollup-specific options
|
|
787
|
+
rollupOptions: {
|
|
788
|
+
input: ssr ? entry : void 0,
|
|
789
|
+
output: {
|
|
790
|
+
// Ensure consistent chunk naming
|
|
791
|
+
chunkFileNames: "chunks/[name]-[hash].js",
|
|
792
|
+
// Preserve pure annotations
|
|
793
|
+
generatedCode: {
|
|
794
|
+
constBindings: true
|
|
795
|
+
}
|
|
796
|
+
},
|
|
797
|
+
// Tree-shaking configuration
|
|
798
|
+
treeshake: {
|
|
799
|
+
moduleSideEffects: false,
|
|
800
|
+
propertyReadSideEffects: false,
|
|
801
|
+
annotations: true
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
},
|
|
805
|
+
// Resolve configuration
|
|
806
|
+
resolve: {
|
|
807
|
+
// Prefer ESM versions of packages
|
|
808
|
+
mainFields: ["module", "jsnext:main", "jsnext", "main"],
|
|
809
|
+
extensions: [".ts", ".tsx", ".js", ".jsx", ".json"]
|
|
810
|
+
},
|
|
811
|
+
// SSR configuration
|
|
812
|
+
...ssr ? {
|
|
813
|
+
ssr: {
|
|
814
|
+
noExternal: ["sibu"],
|
|
815
|
+
target: "node"
|
|
816
|
+
},
|
|
817
|
+
build: {
|
|
818
|
+
outDir,
|
|
819
|
+
target: "node18",
|
|
820
|
+
ssr: true,
|
|
821
|
+
rollupOptions: {
|
|
822
|
+
input: entry,
|
|
823
|
+
output: {
|
|
824
|
+
format: "esm"
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
} : {},
|
|
829
|
+
// Optimize dependency handling
|
|
830
|
+
optimizeDeps: {
|
|
831
|
+
include: ["sibu"],
|
|
832
|
+
// Force pre-bundling of sibu for faster dev startup
|
|
833
|
+
force: false
|
|
834
|
+
},
|
|
835
|
+
// Environment variable handling
|
|
836
|
+
define: {
|
|
837
|
+
__SIBU_SSR__: JSON.stringify(ssr)
|
|
838
|
+
}
|
|
839
|
+
};
|
|
840
|
+
return deepMerge(baseConfig, overrides);
|
|
841
|
+
}
|
|
842
|
+
function deepMerge(target, source2) {
|
|
843
|
+
const result = { ...target };
|
|
844
|
+
for (const key of Object.keys(source2)) {
|
|
845
|
+
if (source2[key] && typeof source2[key] === "object" && !Array.isArray(source2[key]) && target[key] && typeof target[key] === "object" && !Array.isArray(target[key])) {
|
|
846
|
+
result[key] = deepMerge(target[key], source2[key]);
|
|
847
|
+
} else {
|
|
848
|
+
result[key] = source2[key];
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
return result;
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
// src/build/webpack.ts
|
|
855
|
+
var PURE_FACTORIES = [
|
|
856
|
+
"tagFactory",
|
|
857
|
+
"context",
|
|
858
|
+
"composable",
|
|
859
|
+
"defineComponent",
|
|
860
|
+
"withProps",
|
|
861
|
+
"withDefaults",
|
|
862
|
+
"pure",
|
|
863
|
+
"noSideEffect"
|
|
864
|
+
];
|
|
865
|
+
function addPureAnnotations(source2) {
|
|
866
|
+
let result = source2;
|
|
867
|
+
for (const factory of PURE_FACTORIES) {
|
|
868
|
+
const pattern2 = new RegExp(`(?<!/\\*#__PURE__\\*/\\s*)\\b(${factory})\\s*\\(`, "g");
|
|
869
|
+
result = result.replace(pattern2, "/*#__PURE__*/ $1(");
|
|
870
|
+
}
|
|
871
|
+
return result;
|
|
872
|
+
}
|
|
873
|
+
function sibuWebpackPlugin(options = {}) {
|
|
874
|
+
const { pureAnnotations = true, devMode } = options;
|
|
875
|
+
const isDevMode = devMode ?? (typeof process !== "undefined" && process.env?.NODE_ENV !== "production");
|
|
876
|
+
return {
|
|
877
|
+
name: "SibuWebpackPlugin",
|
|
878
|
+
apply(compiler) {
|
|
879
|
+
compiler.hooks?.compilation?.tap("SibuWebpackPlugin", (compilation) => {
|
|
880
|
+
const comp = compilation;
|
|
881
|
+
if (comp.hooks?.optimizeModules) {
|
|
882
|
+
comp.hooks.optimizeModules.tap("SibuWebpackPlugin", () => {
|
|
883
|
+
});
|
|
884
|
+
}
|
|
885
|
+
});
|
|
886
|
+
if (pureAnnotations) {
|
|
887
|
+
compiler.hooks?.afterEnvironment?.tap("SibuWebpackPlugin", () => {
|
|
888
|
+
if (!compiler.options.module) {
|
|
889
|
+
compiler.options.module = { rules: [] };
|
|
890
|
+
}
|
|
891
|
+
if (!compiler.options.module.rules) {
|
|
892
|
+
compiler.options.module.rules = [];
|
|
893
|
+
}
|
|
894
|
+
compiler.options.module.rules.push({
|
|
895
|
+
test: /\.[jt]sx?$/,
|
|
896
|
+
exclude: /node_modules/,
|
|
897
|
+
enforce: "pre",
|
|
898
|
+
use: [
|
|
899
|
+
{
|
|
900
|
+
loader: {
|
|
901
|
+
// Inline loader function
|
|
902
|
+
ident: "sibu-pure-annotations-loader",
|
|
903
|
+
loader: "__sibu_inline_loader__",
|
|
904
|
+
options: {}
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
]
|
|
908
|
+
});
|
|
909
|
+
});
|
|
910
|
+
}
|
|
911
|
+
compiler.hooks?.afterResolvers?.tap("SibuWebpackPlugin", () => {
|
|
912
|
+
if (!compiler.options.resolve) {
|
|
913
|
+
compiler.options.resolve = {};
|
|
914
|
+
}
|
|
915
|
+
if (!compiler.options.resolve.mainFields) {
|
|
916
|
+
compiler.options.resolve.mainFields = ["module", "main"];
|
|
917
|
+
}
|
|
918
|
+
if (!compiler.options.resolve.mainFields.includes("module")) {
|
|
919
|
+
compiler.options.resolve.mainFields.unshift("module");
|
|
920
|
+
}
|
|
921
|
+
});
|
|
922
|
+
if (isDevMode) {
|
|
923
|
+
compiler.hooks?.done?.tap("SibuWebpackPlugin", (stats) => {
|
|
924
|
+
const statsObj = stats;
|
|
925
|
+
const info = statsObj?.toJson?.({ modules: false, chunks: false });
|
|
926
|
+
if (info) {
|
|
927
|
+
console.log(`[SibuWebpackPlugin] Build completed in ${info.time || 0}ms`);
|
|
928
|
+
const warnings = info.warnings;
|
|
929
|
+
if (warnings?.length) {
|
|
930
|
+
console.log(`[SibuWebpackPlugin] ${warnings.length} warning(s)`);
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
});
|
|
934
|
+
}
|
|
935
|
+
compiler.hooks?.environment?.tap("SibuWebpackPlugin", () => {
|
|
936
|
+
if (!compiler.options.plugins) {
|
|
937
|
+
compiler.options.plugins = [];
|
|
938
|
+
}
|
|
939
|
+
const defines = {
|
|
940
|
+
__SIBU_DEV__: JSON.stringify(isDevMode)
|
|
941
|
+
};
|
|
942
|
+
compiler.__sibuDefines = defines;
|
|
943
|
+
});
|
|
944
|
+
}
|
|
945
|
+
};
|
|
946
|
+
}
|
|
947
|
+
function createPureAnnotationsLoader() {
|
|
948
|
+
return function sibuPureAnnotationsLoader(source2) {
|
|
949
|
+
return addPureAnnotations(source2);
|
|
950
|
+
};
|
|
951
|
+
}
|
|
952
|
+
function createWebpackConfig(options = {}) {
|
|
953
|
+
const { entry = "./src/index.ts", outputPath = "dist", mode = "production" } = options;
|
|
954
|
+
const isDev2 = mode === "development";
|
|
955
|
+
return {
|
|
956
|
+
mode,
|
|
957
|
+
entry,
|
|
958
|
+
output: {
|
|
959
|
+
path: outputPath,
|
|
960
|
+
filename: isDev2 ? "[name].js" : "[name].[contenthash:8].js",
|
|
961
|
+
chunkFilename: isDev2 ? "[name].chunk.js" : "[name].[contenthash:8].chunk.js",
|
|
962
|
+
clean: true,
|
|
963
|
+
// Use ESM output
|
|
964
|
+
module: true,
|
|
965
|
+
library: {
|
|
966
|
+
type: "module"
|
|
967
|
+
}
|
|
968
|
+
},
|
|
969
|
+
// Enable experiments for ESM output
|
|
970
|
+
experiments: {
|
|
971
|
+
outputModule: true
|
|
972
|
+
},
|
|
973
|
+
resolve: {
|
|
974
|
+
extensions: [".ts", ".tsx", ".js", ".jsx", ".json"],
|
|
975
|
+
mainFields: ["module", "main"],
|
|
976
|
+
alias: {}
|
|
977
|
+
},
|
|
978
|
+
module: {
|
|
979
|
+
rules: [
|
|
980
|
+
// TypeScript/JavaScript handling
|
|
981
|
+
{
|
|
982
|
+
test: /\.[jt]sx?$/,
|
|
983
|
+
exclude: /node_modules/,
|
|
984
|
+
use: [
|
|
985
|
+
{
|
|
986
|
+
// Users should configure their preferred TS loader
|
|
987
|
+
// (ts-loader, babel-loader, esbuild-loader, swc-loader)
|
|
988
|
+
loader: "ts-loader",
|
|
989
|
+
options: {
|
|
990
|
+
transpileOnly: true,
|
|
991
|
+
compilerOptions: {
|
|
992
|
+
module: "esnext",
|
|
993
|
+
moduleResolution: "node",
|
|
994
|
+
target: "es2020"
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
]
|
|
999
|
+
}
|
|
1000
|
+
]
|
|
1001
|
+
},
|
|
1002
|
+
plugins: [
|
|
1003
|
+
// SibuJS plugin for optimizations
|
|
1004
|
+
sibuWebpackPlugin({ devMode: isDev2 })
|
|
1005
|
+
],
|
|
1006
|
+
optimization: {
|
|
1007
|
+
minimize: !isDev2,
|
|
1008
|
+
// Enable tree-shaking
|
|
1009
|
+
usedExports: true,
|
|
1010
|
+
sideEffects: true,
|
|
1011
|
+
// Split chunks for better caching
|
|
1012
|
+
splitChunks: isDev2 ? false : {
|
|
1013
|
+
chunks: "all",
|
|
1014
|
+
cacheGroups: {
|
|
1015
|
+
// Separate sibu framework code into its own chunk
|
|
1016
|
+
sibu: {
|
|
1017
|
+
test: /[\\/]node_modules[\\/]sibu[\\/]/,
|
|
1018
|
+
name: "sibu",
|
|
1019
|
+
chunks: "all",
|
|
1020
|
+
priority: 20
|
|
1021
|
+
},
|
|
1022
|
+
// Separate other vendor code
|
|
1023
|
+
vendor: {
|
|
1024
|
+
test: /[\\/]node_modules[\\/]/,
|
|
1025
|
+
name: "vendor",
|
|
1026
|
+
chunks: "all",
|
|
1027
|
+
priority: 10
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
},
|
|
1032
|
+
// Source maps
|
|
1033
|
+
devtool: isDev2 ? "eval-cheap-module-source-map" : "source-map",
|
|
1034
|
+
// Dev server configuration
|
|
1035
|
+
devServer: isDev2 ? {
|
|
1036
|
+
hot: true,
|
|
1037
|
+
open: true,
|
|
1038
|
+
port: 3e3,
|
|
1039
|
+
historyApiFallback: true
|
|
1040
|
+
} : void 0,
|
|
1041
|
+
// Performance hints
|
|
1042
|
+
performance: {
|
|
1043
|
+
hints: isDev2 ? false : "warning",
|
|
1044
|
+
maxEntrypointSize: 25e4,
|
|
1045
|
+
maxAssetSize: 25e4
|
|
1046
|
+
},
|
|
1047
|
+
// Cache for faster rebuilds
|
|
1048
|
+
cache: {
|
|
1049
|
+
type: "filesystem",
|
|
1050
|
+
buildDependencies: {
|
|
1051
|
+
config: []
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
};
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
// index.ts
|
|
1058
|
+
var index_exports = {};
|
|
1059
|
+
__export(index_exports, {
|
|
1060
|
+
DynamicComponent: () => DynamicComponent,
|
|
1061
|
+
ErrorBoundary: () => ErrorBoundary,
|
|
1062
|
+
Fragment: () => Fragment,
|
|
1063
|
+
Loading: () => Loading,
|
|
1064
|
+
Portal: () => Portal,
|
|
1065
|
+
SVG_NS: () => SVG_NS,
|
|
1066
|
+
Suspense: () => Suspense,
|
|
1067
|
+
a: () => a,
|
|
1068
|
+
abbr: () => abbr,
|
|
1069
|
+
address: () => address,
|
|
1070
|
+
area: () => area,
|
|
1071
|
+
array: () => array,
|
|
1072
|
+
article: () => article,
|
|
1073
|
+
aside: () => aside,
|
|
1074
|
+
audio: () => audio,
|
|
1075
|
+
b: () => b,
|
|
1076
|
+
base: () => base,
|
|
1077
|
+
batch: () => batch,
|
|
1078
|
+
bdi: () => bdi,
|
|
1079
|
+
bdo: () => bdo,
|
|
1080
|
+
bindDynamic: () => bindDynamic,
|
|
1081
|
+
blockquote: () => blockquote,
|
|
1082
|
+
body: () => body,
|
|
1083
|
+
br: () => br,
|
|
1084
|
+
button: () => button,
|
|
1085
|
+
canvas: () => canvas,
|
|
1086
|
+
caption: () => caption,
|
|
1087
|
+
catchError: () => catchError,
|
|
1088
|
+
catchErrorAsync: () => catchErrorAsync,
|
|
1089
|
+
center: () => center,
|
|
1090
|
+
checkLeaks: () => checkLeaks,
|
|
1091
|
+
circle: () => circle,
|
|
1092
|
+
cite: () => cite,
|
|
1093
|
+
clipPath: () => clipPath,
|
|
1094
|
+
code: () => code,
|
|
1095
|
+
col: () => col,
|
|
1096
|
+
colgroup: () => colgroup,
|
|
1097
|
+
context: () => context,
|
|
1098
|
+
customElement: () => customElement,
|
|
1099
|
+
data: () => data,
|
|
1100
|
+
datalist: () => datalist,
|
|
1101
|
+
dd: () => dd,
|
|
1102
|
+
deepSignal: () => deepSignal,
|
|
1103
|
+
defs: () => defs,
|
|
1104
|
+
del: () => del,
|
|
1105
|
+
derived: () => derived,
|
|
1106
|
+
details: () => details,
|
|
1107
|
+
dfn: () => dfn,
|
|
1108
|
+
dialog: () => dialog,
|
|
1109
|
+
disableSSR: () => disableSSR,
|
|
1110
|
+
dispose: () => dispose,
|
|
1111
|
+
div: () => div,
|
|
1112
|
+
dl: () => dl,
|
|
1113
|
+
dt: () => dt,
|
|
1114
|
+
each: () => each,
|
|
1115
|
+
effect: () => effect,
|
|
1116
|
+
ellipse: () => ellipse,
|
|
1117
|
+
em: () => em,
|
|
1118
|
+
embed: () => embed,
|
|
1119
|
+
enableSSR: () => enableSSR,
|
|
1120
|
+
enqueueBatchedSignal: () => enqueueBatchedSignal,
|
|
1121
|
+
fieldset: () => fieldset,
|
|
1122
|
+
figcaption: () => figcaption,
|
|
1123
|
+
figure: () => figure,
|
|
1124
|
+
font: () => font,
|
|
1125
|
+
footer: () => footer,
|
|
1126
|
+
form: () => form,
|
|
1127
|
+
g: () => g,
|
|
1128
|
+
getSlot: () => getSlot,
|
|
1129
|
+
h1: () => h1,
|
|
1130
|
+
h2: () => h2,
|
|
1131
|
+
h3: () => h3,
|
|
1132
|
+
h4: () => h4,
|
|
1133
|
+
h5: () => h5,
|
|
1134
|
+
h6: () => h6,
|
|
1135
|
+
head: () => head,
|
|
1136
|
+
header: () => header,
|
|
1137
|
+
hr: () => hr,
|
|
1138
|
+
html: () => html2,
|
|
1139
|
+
i: () => i,
|
|
1140
|
+
iframe: () => iframe,
|
|
1141
|
+
img: () => img,
|
|
1142
|
+
input: () => input,
|
|
1143
|
+
ins: () => ins,
|
|
1144
|
+
isBatching: () => isBatching,
|
|
1145
|
+
isSSR: () => isSSR,
|
|
1146
|
+
kbd: () => kbd,
|
|
1147
|
+
label: () => label,
|
|
1148
|
+
lazy: () => lazy,
|
|
1149
|
+
legend: () => legend,
|
|
1150
|
+
li: () => li,
|
|
1151
|
+
line: () => line,
|
|
1152
|
+
linearGradient: () => linearGradient,
|
|
1153
|
+
link: () => link,
|
|
1154
|
+
main: () => main,
|
|
1155
|
+
map: () => map,
|
|
1156
|
+
mark: () => mark,
|
|
1157
|
+
marker: () => marker,
|
|
1158
|
+
marquee: () => marquee,
|
|
1159
|
+
mask: () => mask,
|
|
1160
|
+
match: () => match,
|
|
1161
|
+
math: () => math,
|
|
1162
|
+
memo: () => memo,
|
|
1163
|
+
memoFn: () => memoFn,
|
|
1164
|
+
menu: () => menu,
|
|
1165
|
+
meta: () => meta,
|
|
1166
|
+
meter: () => meter,
|
|
1167
|
+
mount: () => mount,
|
|
1168
|
+
nav: () => nav,
|
|
1169
|
+
noscript: () => noscript,
|
|
1170
|
+
object: () => object,
|
|
1171
|
+
ol: () => ol,
|
|
1172
|
+
onMount: () => onMount,
|
|
1173
|
+
onUnmount: () => onUnmount,
|
|
1174
|
+
optgroup: () => optgroup,
|
|
1175
|
+
option: () => option,
|
|
1176
|
+
output: () => output,
|
|
1177
|
+
p: () => p,
|
|
1178
|
+
param: () => param,
|
|
1179
|
+
path: () => path,
|
|
1180
|
+
pattern: () => pattern,
|
|
1181
|
+
picture: () => picture,
|
|
1182
|
+
polygon: () => polygon,
|
|
1183
|
+
polyline: () => polyline,
|
|
1184
|
+
portal: () => portal,
|
|
1185
|
+
pre: () => pre,
|
|
1186
|
+
progress: () => progress,
|
|
1187
|
+
q: () => q,
|
|
1188
|
+
radialGradient: () => radialGradient,
|
|
1189
|
+
reactiveArray: () => reactiveArray,
|
|
1190
|
+
rect: () => rect,
|
|
1191
|
+
ref: () => ref,
|
|
1192
|
+
registerComponent: () => registerComponent,
|
|
1193
|
+
registerDisposer: () => registerDisposer,
|
|
1194
|
+
resolveComponent: () => resolveComponent,
|
|
1195
|
+
rp: () => rp,
|
|
1196
|
+
rt: () => rt,
|
|
1197
|
+
ruby: () => ruby,
|
|
1198
|
+
s: () => s,
|
|
1199
|
+
samp: () => samp,
|
|
1200
|
+
script: () => script,
|
|
1201
|
+
section: () => section,
|
|
1202
|
+
select: () => select,
|
|
1203
|
+
setGlobalErrorHandler: () => setGlobalErrorHandler,
|
|
1204
|
+
show: () => show,
|
|
1205
|
+
signal: () => signal,
|
|
1206
|
+
slot: () => slot,
|
|
1207
|
+
small: () => small,
|
|
1208
|
+
source: () => source,
|
|
1209
|
+
span: () => span,
|
|
1210
|
+
stop: () => stop,
|
|
1211
|
+
store: () => store,
|
|
1212
|
+
strong: () => strong,
|
|
1213
|
+
style: () => style,
|
|
1214
|
+
sub: () => sub,
|
|
1215
|
+
summary: () => summary,
|
|
1216
|
+
sup: () => sup,
|
|
1217
|
+
svg: () => svg,
|
|
1218
|
+
symbol: () => symbol,
|
|
1219
|
+
table: () => table,
|
|
1220
|
+
tagFactory: () => tagFactory,
|
|
1221
|
+
tbody: () => tbody,
|
|
1222
|
+
td: () => td,
|
|
1223
|
+
template: () => template,
|
|
1224
|
+
text: () => text,
|
|
1225
|
+
textarea: () => textarea,
|
|
1226
|
+
tfoot: () => tfoot,
|
|
1227
|
+
th: () => th,
|
|
1228
|
+
thead: () => thead,
|
|
1229
|
+
time: () => time,
|
|
1230
|
+
title: () => title,
|
|
1231
|
+
tr: () => tr,
|
|
1232
|
+
track: () => track2,
|
|
1233
|
+
tspan: () => tspan,
|
|
1234
|
+
u: () => u,
|
|
1235
|
+
ul: () => ul,
|
|
1236
|
+
unregisterComponent: () => unregisterComponent,
|
|
1237
|
+
use: () => use,
|
|
1238
|
+
var_: () => var_,
|
|
1239
|
+
video: () => video,
|
|
1240
|
+
watch: () => watch,
|
|
1241
|
+
when: () => when,
|
|
1242
|
+
withSSR: () => withSSR
|
|
1243
|
+
});
|
|
1244
|
+
|
|
1245
|
+
// src/utils/sanitize.ts
|
|
1246
|
+
function sanitize(value) {
|
|
1247
|
+
return String(value).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
1248
|
+
}
|
|
1249
|
+
function sanitizeUrl(url) {
|
|
1250
|
+
const trimmed = url.replace(/[\x00-\x20\x7f-\x9f]+/g, "").trim();
|
|
1251
|
+
if (!trimmed) return "";
|
|
1252
|
+
const lower = trimmed.toLowerCase();
|
|
1253
|
+
if (lower.startsWith("javascript:") || lower.startsWith("data:") || lower.startsWith("vbscript:") || lower.startsWith("blob:")) {
|
|
1254
|
+
return "";
|
|
1255
|
+
}
|
|
1256
|
+
return trimmed;
|
|
1257
|
+
}
|
|
1258
|
+
var URL_ATTRIBUTES = /* @__PURE__ */ new Set(["href", "src", "action", "formaction", "cite", "poster", "background", "srcset"]);
|
|
1259
|
+
function isUrlAttribute(attr) {
|
|
1260
|
+
return URL_ATTRIBUTES.has(attr);
|
|
1261
|
+
}
|
|
1262
|
+
function sanitizeAttribute(attr, value) {
|
|
1263
|
+
if (isUrlAttribute(attr)) {
|
|
1264
|
+
return sanitizeUrl(value);
|
|
1265
|
+
}
|
|
1266
|
+
return sanitize(value);
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
// src/reactivity/track.ts
|
|
1270
|
+
var subscriberStack = [];
|
|
1271
|
+
var currentSubscriber = null;
|
|
1272
|
+
var signalSubscribers = /* @__PURE__ */ new WeakMap();
|
|
1273
|
+
var SUBS = "__s";
|
|
1274
|
+
var notifyDepth = 0;
|
|
1275
|
+
var pendingQueue = [];
|
|
1276
|
+
var pendingSet = /* @__PURE__ */ new Set();
|
|
1277
|
+
var suspendDepth = 0;
|
|
1278
|
+
var trackingSuspended = false;
|
|
1279
|
+
function track(effectFn, subscriber) {
|
|
1280
|
+
if (!subscriber) subscriber = effectFn;
|
|
1281
|
+
cleanup(subscriber);
|
|
1282
|
+
subscriberStack.push(subscriber);
|
|
1283
|
+
currentSubscriber = subscriber;
|
|
1284
|
+
effectFn();
|
|
1285
|
+
subscriberStack.pop();
|
|
1286
|
+
currentSubscriber = subscriberStack[subscriberStack.length - 1] || null;
|
|
1287
|
+
return () => cleanup(subscriber);
|
|
1288
|
+
}
|
|
1289
|
+
function suspendTracking() {
|
|
1290
|
+
if (suspendDepth === 0) {
|
|
1291
|
+
subscriberStack.push(null);
|
|
1292
|
+
currentSubscriber = null;
|
|
1293
|
+
trackingSuspended = true;
|
|
1294
|
+
}
|
|
1295
|
+
suspendDepth++;
|
|
1296
|
+
}
|
|
1297
|
+
function resumeTracking() {
|
|
1298
|
+
suspendDepth--;
|
|
1299
|
+
if (suspendDepth === 0) {
|
|
1300
|
+
subscriberStack.pop();
|
|
1301
|
+
currentSubscriber = subscriberStack[subscriberStack.length - 1] || null;
|
|
1302
|
+
trackingSuspended = false;
|
|
1303
|
+
}
|
|
1304
|
+
}
|
|
1305
|
+
function recordDependency(signal2) {
|
|
1306
|
+
if (!currentSubscriber) return;
|
|
1307
|
+
let deps = currentSubscriber._deps;
|
|
1308
|
+
if (!deps) {
|
|
1309
|
+
deps = /* @__PURE__ */ new Set();
|
|
1310
|
+
currentSubscriber._deps = deps;
|
|
1311
|
+
}
|
|
1312
|
+
if (!deps.has(signal2)) {
|
|
1313
|
+
deps.add(signal2);
|
|
1314
|
+
let subs = signal2[SUBS];
|
|
1315
|
+
if (!subs) {
|
|
1316
|
+
subs = /* @__PURE__ */ new Set();
|
|
1317
|
+
signalSubscribers.set(signal2, subs);
|
|
1318
|
+
signal2[SUBS] = subs;
|
|
1319
|
+
}
|
|
1320
|
+
subs.add(currentSubscriber);
|
|
1321
|
+
if (subs.size === 1) {
|
|
1322
|
+
signal2.__f = currentSubscriber;
|
|
1323
|
+
} else if (signal2.__f !== void 0) {
|
|
1324
|
+
signal2.__f = void 0;
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1327
|
+
}
|
|
1328
|
+
function queueSignalNotification(signal2) {
|
|
1329
|
+
const subs = signal2[SUBS];
|
|
1330
|
+
if (!subs) return;
|
|
1331
|
+
for (const sub2 of subs) {
|
|
1332
|
+
if (sub2._c) {
|
|
1333
|
+
propagateDirty(sub2);
|
|
1334
|
+
} else if (!pendingSet.has(sub2)) {
|
|
1335
|
+
pendingSet.add(sub2);
|
|
1336
|
+
pendingQueue.push(sub2);
|
|
1337
|
+
}
|
|
1338
|
+
}
|
|
1339
|
+
}
|
|
1340
|
+
function drainNotificationQueue() {
|
|
1341
|
+
if (notifyDepth > 0) return;
|
|
1342
|
+
notifyDepth++;
|
|
1343
|
+
try {
|
|
1344
|
+
let i2 = 0;
|
|
1345
|
+
while (i2 < pendingQueue.length) {
|
|
1346
|
+
pendingQueue[i2]();
|
|
1347
|
+
i2++;
|
|
1348
|
+
}
|
|
1349
|
+
} finally {
|
|
1350
|
+
pendingQueue.length = 0;
|
|
1351
|
+
pendingSet.clear();
|
|
1352
|
+
notifyDepth--;
|
|
1353
|
+
}
|
|
1354
|
+
}
|
|
1355
|
+
function propagateDirty(sub2) {
|
|
1356
|
+
sub2();
|
|
1357
|
+
let sig = sub2._sig;
|
|
1358
|
+
let suspended = false;
|
|
1359
|
+
if (sig && sig._g) {
|
|
1360
|
+
const sDeps = sub2._deps;
|
|
1361
|
+
if (sDeps && sDeps.size === 1) {
|
|
1362
|
+
suspendTracking();
|
|
1363
|
+
suspended = true;
|
|
1364
|
+
const s2 = sig;
|
|
1365
|
+
s2._d = false;
|
|
1366
|
+
s2._v = s2._g();
|
|
1367
|
+
}
|
|
1368
|
+
}
|
|
1369
|
+
while (sig) {
|
|
1370
|
+
const first = sig.__f;
|
|
1371
|
+
if (first) {
|
|
1372
|
+
if (first._c) {
|
|
1373
|
+
const nSig = first._sig;
|
|
1374
|
+
nSig._d = true;
|
|
1375
|
+
if (suspended && nSig._g) {
|
|
1376
|
+
const fDeps = first._deps;
|
|
1377
|
+
if (fDeps && fDeps.size === 1) {
|
|
1378
|
+
nSig._d = false;
|
|
1379
|
+
nSig._v = nSig._g();
|
|
1380
|
+
}
|
|
1381
|
+
}
|
|
1382
|
+
sig = nSig;
|
|
1383
|
+
continue;
|
|
1384
|
+
}
|
|
1385
|
+
if (!pendingSet.has(first)) {
|
|
1386
|
+
pendingSet.add(first);
|
|
1387
|
+
pendingQueue.push(first);
|
|
1388
|
+
}
|
|
1389
|
+
break;
|
|
1390
|
+
}
|
|
1391
|
+
const subs = sig[SUBS];
|
|
1392
|
+
if (!subs) break;
|
|
1393
|
+
let nextSig;
|
|
1394
|
+
for (const s2 of subs) {
|
|
1395
|
+
if (s2._c) {
|
|
1396
|
+
s2();
|
|
1397
|
+
const nSig = s2._sig;
|
|
1398
|
+
if (nSig && !nextSig) {
|
|
1399
|
+
nextSig = nSig;
|
|
1400
|
+
} else if (nSig) {
|
|
1401
|
+
propagateDirty(s2);
|
|
1402
|
+
}
|
|
1403
|
+
} else if (!pendingSet.has(s2)) {
|
|
1404
|
+
pendingSet.add(s2);
|
|
1405
|
+
pendingQueue.push(s2);
|
|
1406
|
+
}
|
|
1407
|
+
}
|
|
1408
|
+
sig = nextSig;
|
|
1409
|
+
}
|
|
1410
|
+
if (suspended) resumeTracking();
|
|
1411
|
+
}
|
|
1412
|
+
function notifySubscribers(signal2) {
|
|
1413
|
+
const first = signal2.__f;
|
|
1414
|
+
if (first) {
|
|
1415
|
+
if (notifyDepth > 0) {
|
|
1416
|
+
if (first._c) {
|
|
1417
|
+
propagateDirty(first);
|
|
1418
|
+
} else if (!pendingSet.has(first)) {
|
|
1419
|
+
pendingSet.add(first);
|
|
1420
|
+
pendingQueue.push(first);
|
|
1421
|
+
}
|
|
1422
|
+
return;
|
|
1423
|
+
}
|
|
1424
|
+
notifyDepth++;
|
|
1425
|
+
try {
|
|
1426
|
+
if (first._c) {
|
|
1427
|
+
propagateDirty(first);
|
|
1428
|
+
} else {
|
|
1429
|
+
first();
|
|
1430
|
+
}
|
|
1431
|
+
let i2 = 0;
|
|
1432
|
+
while (i2 < pendingQueue.length) {
|
|
1433
|
+
pendingQueue[i2]();
|
|
1434
|
+
i2++;
|
|
1435
|
+
}
|
|
1436
|
+
} finally {
|
|
1437
|
+
pendingQueue.length = 0;
|
|
1438
|
+
pendingSet.clear();
|
|
1439
|
+
notifyDepth--;
|
|
1440
|
+
}
|
|
1441
|
+
return;
|
|
1442
|
+
}
|
|
1443
|
+
const subs = signal2[SUBS];
|
|
1444
|
+
if (!subs || subs.size === 0) return;
|
|
1445
|
+
if (notifyDepth > 0) {
|
|
1446
|
+
for (const sub2 of subs) {
|
|
1447
|
+
if (sub2._c) {
|
|
1448
|
+
propagateDirty(sub2);
|
|
1449
|
+
} else if (!pendingSet.has(sub2)) {
|
|
1450
|
+
pendingSet.add(sub2);
|
|
1451
|
+
pendingQueue.push(sub2);
|
|
1452
|
+
}
|
|
1453
|
+
}
|
|
1454
|
+
return;
|
|
1455
|
+
}
|
|
1456
|
+
notifyDepth++;
|
|
1457
|
+
try {
|
|
1458
|
+
let directCount = 0;
|
|
1459
|
+
for (const sub2 of subs) {
|
|
1460
|
+
pendingQueue[directCount++] = sub2;
|
|
1461
|
+
}
|
|
1462
|
+
for (let i3 = 0; i3 < directCount; i3++) {
|
|
1463
|
+
if (pendingQueue[i3]._c) {
|
|
1464
|
+
propagateDirty(pendingQueue[i3]);
|
|
1465
|
+
}
|
|
1466
|
+
}
|
|
1467
|
+
for (let i3 = 0; i3 < directCount; i3++) {
|
|
1468
|
+
if (!pendingQueue[i3]._c) {
|
|
1469
|
+
if (!pendingSet.has(pendingQueue[i3])) {
|
|
1470
|
+
pendingQueue[i3]();
|
|
1471
|
+
}
|
|
1472
|
+
}
|
|
1473
|
+
}
|
|
1474
|
+
let i2 = directCount;
|
|
1475
|
+
while (i2 < pendingQueue.length) {
|
|
1476
|
+
pendingQueue[i2]();
|
|
1477
|
+
i2++;
|
|
1478
|
+
}
|
|
1479
|
+
} finally {
|
|
1480
|
+
pendingQueue.length = 0;
|
|
1481
|
+
pendingSet.clear();
|
|
1482
|
+
notifyDepth--;
|
|
1483
|
+
}
|
|
1484
|
+
}
|
|
1485
|
+
function cleanup(subscriber) {
|
|
1486
|
+
const deps = subscriber._deps;
|
|
1487
|
+
if (!deps || deps.size === 0) return;
|
|
1488
|
+
for (const signal2 of deps) {
|
|
1489
|
+
const subs = signal2[SUBS];
|
|
1490
|
+
if (subs) {
|
|
1491
|
+
subs.delete(subscriber);
|
|
1492
|
+
if (signal2.__f === subscriber) {
|
|
1493
|
+
signal2.__f = void 0;
|
|
1494
|
+
}
|
|
1495
|
+
}
|
|
1496
|
+
}
|
|
1497
|
+
deps.clear();
|
|
1498
|
+
}
|
|
1499
|
+
|
|
1500
|
+
// src/reactivity/bindAttribute.ts
|
|
1501
|
+
function bindAttribute(el, attr, getter) {
|
|
1502
|
+
function commit() {
|
|
1503
|
+
let value;
|
|
1504
|
+
try {
|
|
1505
|
+
value = getter();
|
|
1506
|
+
} catch {
|
|
1507
|
+
return;
|
|
1508
|
+
}
|
|
1509
|
+
if (typeof value === "boolean") {
|
|
1510
|
+
if (attr in el && (attr === "checked" || attr === "disabled" || attr === "selected")) {
|
|
1511
|
+
el[attr] = value;
|
|
1512
|
+
} else if (value) {
|
|
1513
|
+
el.setAttribute(attr, "");
|
|
1514
|
+
} else {
|
|
1515
|
+
el.removeAttribute(attr);
|
|
1516
|
+
}
|
|
1517
|
+
return;
|
|
1518
|
+
}
|
|
1519
|
+
const str = sanitizeAttribute(attr, String(value));
|
|
1520
|
+
if ((attr === "value" || attr === "checked") && attr in el) {
|
|
1521
|
+
el[attr] = attr === "checked" ? Boolean(value) : str;
|
|
1522
|
+
} else {
|
|
1523
|
+
el.setAttribute(attr, str);
|
|
1524
|
+
}
|
|
1525
|
+
}
|
|
1526
|
+
const teardown = track(commit);
|
|
1527
|
+
return teardown;
|
|
1528
|
+
}
|
|
1529
|
+
function bindDynamic(el, nameGetter, valueGetter) {
|
|
1530
|
+
let prevName = null;
|
|
1531
|
+
function commit() {
|
|
1532
|
+
let name;
|
|
1533
|
+
try {
|
|
1534
|
+
name = typeof nameGetter === "function" ? nameGetter() : nameGetter;
|
|
1535
|
+
} catch {
|
|
1536
|
+
return;
|
|
1537
|
+
}
|
|
1538
|
+
let value;
|
|
1539
|
+
try {
|
|
1540
|
+
value = typeof valueGetter === "function" ? valueGetter() : valueGetter;
|
|
1541
|
+
} catch {
|
|
1542
|
+
return;
|
|
1543
|
+
}
|
|
1544
|
+
if (name.toLowerCase().startsWith("on")) return;
|
|
1545
|
+
if (prevName !== null && prevName !== name) {
|
|
1546
|
+
el.removeAttribute(prevName);
|
|
1547
|
+
}
|
|
1548
|
+
const str = sanitizeAttribute(name, String(value));
|
|
1549
|
+
if ((name === "value" || name === "checked") && name in el) {
|
|
1550
|
+
el[name] = name === "checked" ? Boolean(value) : str;
|
|
1551
|
+
} else {
|
|
1552
|
+
el.setAttribute(name, str);
|
|
1553
|
+
}
|
|
1554
|
+
prevName = name;
|
|
1555
|
+
}
|
|
1556
|
+
const teardown = track(commit);
|
|
1557
|
+
return () => {
|
|
1558
|
+
teardown();
|
|
1559
|
+
if (prevName !== null) {
|
|
1560
|
+
el.removeAttribute(prevName);
|
|
1561
|
+
}
|
|
1562
|
+
};
|
|
1563
|
+
}
|
|
1564
|
+
|
|
1565
|
+
// src/reactivity/bindChildNode.ts
|
|
1566
|
+
function bindChildNode(placeholder, getter) {
|
|
1567
|
+
let lastNodes = [];
|
|
1568
|
+
function commit() {
|
|
1569
|
+
let result;
|
|
1570
|
+
try {
|
|
1571
|
+
result = getter();
|
|
1572
|
+
} catch {
|
|
1573
|
+
return;
|
|
1574
|
+
}
|
|
1575
|
+
for (const node of lastNodes) {
|
|
1576
|
+
node.parentNode?.removeChild(node);
|
|
1577
|
+
}
|
|
1578
|
+
lastNodes = [];
|
|
1579
|
+
if (result == null) return;
|
|
1580
|
+
const parent = placeholder.parentNode;
|
|
1581
|
+
if (!parent) return;
|
|
1582
|
+
const anchor = placeholder.nextSibling;
|
|
1583
|
+
const newNodes = [];
|
|
1584
|
+
const insertItem = (item) => {
|
|
1585
|
+
const node = item instanceof Node ? item : document.createTextNode(String(item));
|
|
1586
|
+
parent.insertBefore(node, anchor);
|
|
1587
|
+
newNodes.push(node);
|
|
1588
|
+
};
|
|
1589
|
+
if (Array.isArray(result)) {
|
|
1590
|
+
for (const item of result) insertItem(item);
|
|
1591
|
+
} else {
|
|
1592
|
+
insertItem(result);
|
|
1593
|
+
}
|
|
1594
|
+
lastNodes = newNodes;
|
|
1595
|
+
}
|
|
1596
|
+
return track(commit);
|
|
1597
|
+
}
|
|
1598
|
+
|
|
1599
|
+
// src/core/dev.ts
|
|
1600
|
+
function isDev() {
|
|
1601
|
+
return typeof globalThis.__SIBU_DEV__ !== "undefined" ? !!globalThis.__SIBU_DEV__ : typeof __SIBU_DEV__ !== "undefined" ? __SIBU_DEV__ : true;
|
|
1602
|
+
}
|
|
1603
|
+
function devAssert(condition, message) {
|
|
1604
|
+
if (isDev() && !condition) {
|
|
1605
|
+
throw new Error(`[Sibu] ${message}`);
|
|
1606
|
+
}
|
|
1607
|
+
}
|
|
1608
|
+
function devWarn(message) {
|
|
1609
|
+
if (isDev()) {
|
|
1610
|
+
console.warn(`[Sibu] ${message}`);
|
|
1611
|
+
}
|
|
1612
|
+
}
|
|
1613
|
+
|
|
1614
|
+
// src/core/rendering/dispose.ts
|
|
1615
|
+
var elementDisposers = /* @__PURE__ */ new WeakMap();
|
|
1616
|
+
var activeBindingCount = 0;
|
|
1617
|
+
function registerDisposer(node, teardown) {
|
|
1618
|
+
let disposers = elementDisposers.get(node);
|
|
1619
|
+
if (!disposers) {
|
|
1620
|
+
disposers = [];
|
|
1621
|
+
elementDisposers.set(node, disposers);
|
|
1622
|
+
}
|
|
1623
|
+
disposers.push(teardown);
|
|
1624
|
+
activeBindingCount++;
|
|
1625
|
+
}
|
|
1626
|
+
function dispose(node) {
|
|
1627
|
+
const children = node.childNodes;
|
|
1628
|
+
for (const child of children) {
|
|
1629
|
+
dispose(child);
|
|
1630
|
+
}
|
|
1631
|
+
const disposers = elementDisposers.get(node);
|
|
1632
|
+
if (disposers) {
|
|
1633
|
+
activeBindingCount -= disposers.length;
|
|
1634
|
+
for (const d of disposers) d();
|
|
1635
|
+
elementDisposers.delete(node);
|
|
1636
|
+
}
|
|
1637
|
+
}
|
|
1638
|
+
function checkLeaks(warnThreshold = 0) {
|
|
1639
|
+
if (activeBindingCount > warnThreshold) {
|
|
1640
|
+
devWarn(
|
|
1641
|
+
`checkLeaks: ${activeBindingCount} active DOM bindings detected. Expected \u2264${warnThreshold}. This may indicate a component was removed from the DOM without calling dispose().`
|
|
1642
|
+
);
|
|
1643
|
+
}
|
|
1644
|
+
return activeBindingCount;
|
|
1645
|
+
}
|
|
1646
|
+
|
|
1647
|
+
// src/core/rendering/tagFactory.ts
|
|
1648
|
+
var SVG_NS = "http://www.w3.org/2000/svg";
|
|
1649
|
+
var kebabCache = /* @__PURE__ */ new Map();
|
|
1650
|
+
function toKebab(prop) {
|
|
1651
|
+
let cached = kebabCache.get(prop);
|
|
1652
|
+
if (cached !== void 0) return cached;
|
|
1653
|
+
cached = prop.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`);
|
|
1654
|
+
kebabCache.set(prop, cached);
|
|
1655
|
+
return cached;
|
|
1656
|
+
}
|
|
1657
|
+
function applyStyle(el, style2) {
|
|
1658
|
+
if (!style2) return;
|
|
1659
|
+
if (typeof style2 === "function") {
|
|
1660
|
+
const teardown = track(() => {
|
|
1661
|
+
el.setAttribute("style", style2());
|
|
1662
|
+
});
|
|
1663
|
+
registerDisposer(el, teardown);
|
|
1664
|
+
return;
|
|
1665
|
+
}
|
|
1666
|
+
if (typeof style2 === "string") {
|
|
1667
|
+
el.setAttribute("style", style2);
|
|
1668
|
+
return;
|
|
1669
|
+
}
|
|
1670
|
+
const htmlEl = el;
|
|
1671
|
+
for (const prop in style2) {
|
|
1672
|
+
const val = style2[prop];
|
|
1673
|
+
const name = toKebab(prop);
|
|
1674
|
+
if (typeof val === "function") {
|
|
1675
|
+
const getter = val;
|
|
1676
|
+
const teardown = track(() => {
|
|
1677
|
+
htmlEl.style.setProperty(name, String(getter()));
|
|
1678
|
+
});
|
|
1679
|
+
registerDisposer(el, teardown);
|
|
1680
|
+
} else {
|
|
1681
|
+
htmlEl.style.setProperty(name, String(val));
|
|
1682
|
+
}
|
|
1683
|
+
}
|
|
1684
|
+
}
|
|
1685
|
+
function applyClass(el, cls) {
|
|
1686
|
+
if (cls == null) return;
|
|
1687
|
+
if (typeof cls === "string") {
|
|
1688
|
+
el.setAttribute("class", cls);
|
|
1689
|
+
return;
|
|
1690
|
+
}
|
|
1691
|
+
if (typeof cls === "function") {
|
|
1692
|
+
const getter = cls;
|
|
1693
|
+
const teardown = track(() => {
|
|
1694
|
+
el.setAttribute("class", getter());
|
|
1695
|
+
});
|
|
1696
|
+
registerDisposer(el, teardown);
|
|
1697
|
+
return;
|
|
1698
|
+
}
|
|
1699
|
+
if (typeof cls === "object") {
|
|
1700
|
+
const obj = cls;
|
|
1701
|
+
let hasReactive = false;
|
|
1702
|
+
for (const name in obj) {
|
|
1703
|
+
if (typeof obj[name] === "function") {
|
|
1704
|
+
hasReactive = true;
|
|
1705
|
+
break;
|
|
1706
|
+
}
|
|
1707
|
+
}
|
|
1708
|
+
if (hasReactive) {
|
|
1709
|
+
const update = () => {
|
|
1710
|
+
let result = "";
|
|
1711
|
+
for (const name in obj) {
|
|
1712
|
+
const val = obj[name];
|
|
1713
|
+
const active = typeof val === "function" ? val() : val;
|
|
1714
|
+
if (active) result = result ? `${result} ${name}` : name;
|
|
1715
|
+
}
|
|
1716
|
+
el.setAttribute("class", result);
|
|
1717
|
+
};
|
|
1718
|
+
const teardown = track(update);
|
|
1719
|
+
registerDisposer(el, teardown);
|
|
1720
|
+
} else {
|
|
1721
|
+
let result = "";
|
|
1722
|
+
for (const name in obj) {
|
|
1723
|
+
if (obj[name]) result = result ? `${result} ${name}` : name;
|
|
1724
|
+
}
|
|
1725
|
+
el.setAttribute("class", result);
|
|
1726
|
+
}
|
|
1727
|
+
}
|
|
1728
|
+
}
|
|
1729
|
+
function renderChild(child) {
|
|
1730
|
+
if (child == null) {
|
|
1731
|
+
return document.createTextNode("");
|
|
1732
|
+
}
|
|
1733
|
+
if (child instanceof Node) {
|
|
1734
|
+
return child;
|
|
1735
|
+
}
|
|
1736
|
+
return document.createTextNode(String(child));
|
|
1737
|
+
}
|
|
1738
|
+
function appendOneChild(el, child) {
|
|
1739
|
+
if (typeof child === "function") {
|
|
1740
|
+
const placeholder = document.createComment("bind:child");
|
|
1741
|
+
el.appendChild(placeholder);
|
|
1742
|
+
const teardown = bindChildNode(placeholder, child);
|
|
1743
|
+
registerDisposer(el, teardown);
|
|
1744
|
+
} else {
|
|
1745
|
+
el.appendChild(renderChild(child));
|
|
1746
|
+
}
|
|
1747
|
+
}
|
|
1748
|
+
function appendChildren(el, nodes) {
|
|
1749
|
+
if (Array.isArray(nodes)) {
|
|
1750
|
+
for (let i2 = 0; i2 < nodes.length; i2++) {
|
|
1751
|
+
const c = nodes[i2];
|
|
1752
|
+
if (Array.isArray(c)) {
|
|
1753
|
+
for (let j = 0; j < c.length; j++) {
|
|
1754
|
+
appendOneChild(el, c[j]);
|
|
1755
|
+
}
|
|
1756
|
+
} else {
|
|
1757
|
+
appendOneChild(el, c);
|
|
1758
|
+
}
|
|
1759
|
+
}
|
|
1760
|
+
} else {
|
|
1761
|
+
appendOneChild(el, nodes);
|
|
1762
|
+
}
|
|
1763
|
+
}
|
|
1764
|
+
function isTagProps(value) {
|
|
1765
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) && !(value instanceof Node);
|
|
1766
|
+
}
|
|
1767
|
+
var tagFactory = (tag, ns) => (first, second) => {
|
|
1768
|
+
let props;
|
|
1769
|
+
if (first === void 0) {
|
|
1770
|
+
props = {};
|
|
1771
|
+
} else if (isTagProps(first)) {
|
|
1772
|
+
props = first;
|
|
1773
|
+
} else if (second !== void 0) {
|
|
1774
|
+
props = { class: first, nodes: second };
|
|
1775
|
+
} else {
|
|
1776
|
+
props = { nodes: first };
|
|
1777
|
+
}
|
|
1778
|
+
const el = ns ? document.createElementNS(ns, tag) : document.createElement(tag);
|
|
1779
|
+
for (const key in props) {
|
|
1780
|
+
const value = props[key];
|
|
1781
|
+
if (value == null) continue;
|
|
1782
|
+
switch (key) {
|
|
1783
|
+
case "id":
|
|
1784
|
+
el.id = value;
|
|
1785
|
+
break;
|
|
1786
|
+
case "class":
|
|
1787
|
+
applyClass(el, value);
|
|
1788
|
+
break;
|
|
1789
|
+
case "style":
|
|
1790
|
+
applyStyle(el, value);
|
|
1791
|
+
break;
|
|
1792
|
+
case "ref":
|
|
1793
|
+
if (value && typeof value === "object" && "current" in value) {
|
|
1794
|
+
value.current = el;
|
|
1795
|
+
}
|
|
1796
|
+
break;
|
|
1797
|
+
case "on": {
|
|
1798
|
+
const handlers = value;
|
|
1799
|
+
const eventNames = [];
|
|
1800
|
+
for (const ev in handlers) {
|
|
1801
|
+
el.addEventListener(ev, handlers[ev]);
|
|
1802
|
+
eventNames.push(ev);
|
|
1803
|
+
}
|
|
1804
|
+
if (eventNames.length) {
|
|
1805
|
+
el.__sibu_events__ = eventNames;
|
|
1806
|
+
}
|
|
1807
|
+
break;
|
|
1808
|
+
}
|
|
1809
|
+
case "nodes":
|
|
1810
|
+
appendChildren(el, value);
|
|
1811
|
+
break;
|
|
1812
|
+
default:
|
|
1813
|
+
if (key.toLowerCase().startsWith("on")) break;
|
|
1814
|
+
if (typeof value === "function") {
|
|
1815
|
+
const teardown = bindAttribute(el, key, value);
|
|
1816
|
+
registerDisposer(el, teardown);
|
|
1817
|
+
} else if (typeof value === "boolean") {
|
|
1818
|
+
if (value) el.setAttribute(key, "");
|
|
1819
|
+
else el.removeAttribute(key);
|
|
1820
|
+
} else {
|
|
1821
|
+
el.setAttribute(key, sanitizeAttribute(key, String(value)));
|
|
1822
|
+
}
|
|
1823
|
+
}
|
|
1824
|
+
}
|
|
1825
|
+
return el;
|
|
1826
|
+
};
|
|
1827
|
+
|
|
1828
|
+
// src/core/rendering/html.ts
|
|
1829
|
+
var html = tagFactory("html");
|
|
1830
|
+
var head = tagFactory("head");
|
|
1831
|
+
var body = tagFactory("body");
|
|
1832
|
+
var title = tagFactory("title");
|
|
1833
|
+
var div = tagFactory("div");
|
|
1834
|
+
var span = tagFactory("span");
|
|
1835
|
+
var section = tagFactory("section");
|
|
1836
|
+
var article = tagFactory("article");
|
|
1837
|
+
var header = tagFactory("header");
|
|
1838
|
+
var footer = tagFactory("footer");
|
|
1839
|
+
var nav = tagFactory("nav");
|
|
1840
|
+
var main = tagFactory("main");
|
|
1841
|
+
var aside = tagFactory("aside");
|
|
1842
|
+
var address = tagFactory("address");
|
|
1843
|
+
var p = tagFactory("p");
|
|
1844
|
+
var h1 = tagFactory("h1");
|
|
1845
|
+
var h2 = tagFactory("h2");
|
|
1846
|
+
var h3 = tagFactory("h3");
|
|
1847
|
+
var h4 = tagFactory("h4");
|
|
1848
|
+
var h5 = tagFactory("h5");
|
|
1849
|
+
var h6 = tagFactory("h6");
|
|
1850
|
+
var blockquote = tagFactory("blockquote");
|
|
1851
|
+
var dd = tagFactory("dd");
|
|
1852
|
+
var dl = tagFactory("dl");
|
|
1853
|
+
var dt = tagFactory("dt");
|
|
1854
|
+
var figcaption = tagFactory("figcaption");
|
|
1855
|
+
var figure = tagFactory("figure");
|
|
1856
|
+
var hr = tagFactory("hr");
|
|
1857
|
+
var li = tagFactory("li");
|
|
1858
|
+
var ol = tagFactory("ol");
|
|
1859
|
+
var ul = tagFactory("ul");
|
|
1860
|
+
var pre = tagFactory("pre");
|
|
1861
|
+
var a = tagFactory("a");
|
|
1862
|
+
var abbr = tagFactory("abbr");
|
|
1863
|
+
var b = tagFactory("b");
|
|
1864
|
+
var bdi = tagFactory("bdi");
|
|
1865
|
+
var bdo = tagFactory("bdo");
|
|
1866
|
+
var br = tagFactory("br");
|
|
1867
|
+
var cite = tagFactory("cite");
|
|
1868
|
+
var code = tagFactory("code");
|
|
1869
|
+
var data = tagFactory("data");
|
|
1870
|
+
var dfn = tagFactory("dfn");
|
|
1871
|
+
var em = tagFactory("em");
|
|
1872
|
+
var i = tagFactory("i");
|
|
1873
|
+
var kbd = tagFactory("kbd");
|
|
1874
|
+
var mark = tagFactory("mark");
|
|
1875
|
+
var q = tagFactory("q");
|
|
1876
|
+
var rp = tagFactory("rp");
|
|
1877
|
+
var rt = tagFactory("rt");
|
|
1878
|
+
var ruby = tagFactory("ruby");
|
|
1879
|
+
var s = tagFactory("s");
|
|
1880
|
+
var samp = tagFactory("samp");
|
|
1881
|
+
var small = tagFactory("small");
|
|
1882
|
+
var strong = tagFactory("strong");
|
|
1883
|
+
var sub = tagFactory("sub");
|
|
1884
|
+
var sup = tagFactory("sup");
|
|
1885
|
+
var time = tagFactory("time");
|
|
1886
|
+
var u = tagFactory("u");
|
|
1887
|
+
var var_ = tagFactory("var");
|
|
1888
|
+
var area = tagFactory("area");
|
|
1889
|
+
var audio = tagFactory("audio");
|
|
1890
|
+
var img = tagFactory("img");
|
|
1891
|
+
var map = tagFactory("map");
|
|
1892
|
+
var track2 = tagFactory("track");
|
|
1893
|
+
var video = tagFactory("video");
|
|
1894
|
+
var embed = tagFactory("embed");
|
|
1895
|
+
var iframe = tagFactory("iframe");
|
|
1896
|
+
var object = tagFactory("object");
|
|
1897
|
+
var param = tagFactory("param");
|
|
1898
|
+
var picture = tagFactory("picture");
|
|
1899
|
+
var portal = tagFactory("portal");
|
|
1900
|
+
var source = tagFactory("source");
|
|
1901
|
+
var svg = tagFactory("svg", SVG_NS);
|
|
1902
|
+
var math = tagFactory("math");
|
|
1903
|
+
var canvas = tagFactory("canvas");
|
|
1904
|
+
var noscript = tagFactory("noscript");
|
|
1905
|
+
var script = tagFactory("script");
|
|
1906
|
+
var del = tagFactory("del");
|
|
1907
|
+
var ins = tagFactory("ins");
|
|
1908
|
+
var caption = tagFactory("caption");
|
|
1909
|
+
var col = tagFactory("col");
|
|
1910
|
+
var colgroup = tagFactory("colgroup");
|
|
1911
|
+
var table = tagFactory("table");
|
|
1912
|
+
var tbody = tagFactory("tbody");
|
|
1913
|
+
var td = tagFactory("td");
|
|
1914
|
+
var tfoot = tagFactory("tfoot");
|
|
1915
|
+
var th = tagFactory("th");
|
|
1916
|
+
var thead = tagFactory("thead");
|
|
1917
|
+
var tr = tagFactory("tr");
|
|
1918
|
+
var button = tagFactory("button");
|
|
1919
|
+
var datalist = tagFactory("datalist");
|
|
1920
|
+
var fieldset = tagFactory("fieldset");
|
|
1921
|
+
var form = tagFactory("form");
|
|
1922
|
+
var input = tagFactory("input");
|
|
1923
|
+
var label = tagFactory("label");
|
|
1924
|
+
var legend = tagFactory("legend");
|
|
1925
|
+
var meter = tagFactory("meter");
|
|
1926
|
+
var optgroup = tagFactory("optgroup");
|
|
1927
|
+
var option = tagFactory("option");
|
|
1928
|
+
var output = tagFactory("output");
|
|
1929
|
+
var progress = tagFactory("progress");
|
|
1930
|
+
var select = tagFactory("select");
|
|
1931
|
+
var textarea = tagFactory("textarea");
|
|
1932
|
+
var details = tagFactory("details");
|
|
1933
|
+
var dialog = tagFactory("dialog");
|
|
1934
|
+
var menu = tagFactory("menu");
|
|
1935
|
+
var summary = tagFactory("summary");
|
|
1936
|
+
var slot = tagFactory("slot");
|
|
1937
|
+
var template = tagFactory("template");
|
|
1938
|
+
var base = tagFactory("base");
|
|
1939
|
+
var link = tagFactory("link");
|
|
1940
|
+
var meta = tagFactory("meta");
|
|
1941
|
+
var style = tagFactory("style");
|
|
1942
|
+
var circle = tagFactory("circle", SVG_NS);
|
|
1943
|
+
var ellipse = tagFactory("ellipse", SVG_NS);
|
|
1944
|
+
var g = tagFactory("g", SVG_NS);
|
|
1945
|
+
var line = tagFactory("line", SVG_NS);
|
|
1946
|
+
var path = tagFactory("path", SVG_NS);
|
|
1947
|
+
var polygon = tagFactory("polygon", SVG_NS);
|
|
1948
|
+
var polyline = tagFactory("polyline", SVG_NS);
|
|
1949
|
+
var rect = tagFactory("rect", SVG_NS);
|
|
1950
|
+
var text = tagFactory("text", SVG_NS);
|
|
1951
|
+
var tspan = tagFactory("tspan", SVG_NS);
|
|
1952
|
+
var defs = tagFactory("defs", SVG_NS);
|
|
1953
|
+
var clipPath = tagFactory("clipPath", SVG_NS);
|
|
1954
|
+
var mask = tagFactory("mask", SVG_NS);
|
|
1955
|
+
var pattern = tagFactory("pattern", SVG_NS);
|
|
1956
|
+
var linearGradient = tagFactory("linearGradient", SVG_NS);
|
|
1957
|
+
var radialGradient = tagFactory("radialGradient", SVG_NS);
|
|
1958
|
+
var stop = tagFactory("stop", SVG_NS);
|
|
1959
|
+
var use = tagFactory("use", SVG_NS);
|
|
1960
|
+
var symbol = tagFactory("symbol", SVG_NS);
|
|
1961
|
+
var marker = tagFactory("marker", SVG_NS);
|
|
1962
|
+
var center = tagFactory("center");
|
|
1963
|
+
var font = tagFactory("font");
|
|
1964
|
+
var marquee = tagFactory("marquee");
|
|
1965
|
+
var customElement = (tagName) => tagFactory(tagName);
|
|
1966
|
+
|
|
1967
|
+
// src/core/rendering/htm.ts
|
|
1968
|
+
var VOID_ELEMENTS3 = /* @__PURE__ */ new Set([
|
|
1969
|
+
"area",
|
|
1970
|
+
"base",
|
|
1971
|
+
"br",
|
|
1972
|
+
"col",
|
|
1973
|
+
"embed",
|
|
1974
|
+
"hr",
|
|
1975
|
+
"img",
|
|
1976
|
+
"input",
|
|
1977
|
+
"link",
|
|
1978
|
+
"meta",
|
|
1979
|
+
"param",
|
|
1980
|
+
"source",
|
|
1981
|
+
"track",
|
|
1982
|
+
"wbr"
|
|
1983
|
+
]);
|
|
1984
|
+
var SVG_TAGS2 = /* @__PURE__ */ new Set([
|
|
1985
|
+
"svg",
|
|
1986
|
+
"circle",
|
|
1987
|
+
"ellipse",
|
|
1988
|
+
"g",
|
|
1989
|
+
"line",
|
|
1990
|
+
"path",
|
|
1991
|
+
"polygon",
|
|
1992
|
+
"polyline",
|
|
1993
|
+
"rect",
|
|
1994
|
+
"text",
|
|
1995
|
+
"tspan",
|
|
1996
|
+
"defs",
|
|
1997
|
+
"clipPath",
|
|
1998
|
+
"mask",
|
|
1999
|
+
"pattern",
|
|
2000
|
+
"linearGradient",
|
|
2001
|
+
"radialGradient",
|
|
2002
|
+
"stop",
|
|
2003
|
+
"use",
|
|
2004
|
+
"symbol",
|
|
2005
|
+
"marker"
|
|
2006
|
+
]);
|
|
2007
|
+
var cache = /* @__PURE__ */ new WeakMap();
|
|
2008
|
+
function parseTemplate(strings) {
|
|
2009
|
+
const exprCount = strings.length - 1;
|
|
2010
|
+
let template2 = strings[0];
|
|
2011
|
+
for (let i2 = 0; i2 < exprCount; i2++) {
|
|
2012
|
+
template2 += `\0${i2}\0${strings[i2 + 1]}`;
|
|
2013
|
+
}
|
|
2014
|
+
let pos = 0;
|
|
2015
|
+
const len = template2.length;
|
|
2016
|
+
function skipWs() {
|
|
2017
|
+
while (pos < len && (template2[pos] === " " || template2[pos] === " " || template2[pos] === "\n" || template2[pos] === "\r"))
|
|
2018
|
+
pos++;
|
|
2019
|
+
}
|
|
2020
|
+
function tryExprIdx() {
|
|
2021
|
+
if (template2[pos] !== "\0") return -1;
|
|
2022
|
+
const start = pos;
|
|
2023
|
+
pos++;
|
|
2024
|
+
let idxStr = "";
|
|
2025
|
+
while (pos < len && template2[pos] !== "\0") idxStr += template2[pos++];
|
|
2026
|
+
if (pos < len) pos++;
|
|
2027
|
+
const idx = Number.parseInt(idxStr, 10);
|
|
2028
|
+
if (Number.isNaN(idx) || idx < 0 || idx >= exprCount) {
|
|
2029
|
+
pos = start;
|
|
2030
|
+
return -1;
|
|
2031
|
+
}
|
|
2032
|
+
return idx;
|
|
2033
|
+
}
|
|
2034
|
+
function readTagName() {
|
|
2035
|
+
let name = "";
|
|
2036
|
+
while (pos < len && /[a-zA-Z0-9-]/.test(template2[pos])) name += template2[pos++];
|
|
2037
|
+
return name;
|
|
2038
|
+
}
|
|
2039
|
+
function parseAttrValue() {
|
|
2040
|
+
skipWs();
|
|
2041
|
+
if (template2[pos] !== "=") return { kind: "bool" };
|
|
2042
|
+
pos++;
|
|
2043
|
+
skipWs();
|
|
2044
|
+
const exprIdx = tryExprIdx();
|
|
2045
|
+
if (exprIdx >= 0) return { kind: "expr", idx: exprIdx };
|
|
2046
|
+
const quote = template2[pos];
|
|
2047
|
+
if (quote === '"' || quote === "'") {
|
|
2048
|
+
pos++;
|
|
2049
|
+
const statics = [];
|
|
2050
|
+
const exprs = [];
|
|
2051
|
+
let current = "";
|
|
2052
|
+
while (pos < len && template2[pos] !== quote) {
|
|
2053
|
+
const innerIdx = tryExprIdx();
|
|
2054
|
+
if (innerIdx >= 0) {
|
|
2055
|
+
statics.push(current);
|
|
2056
|
+
current = "";
|
|
2057
|
+
exprs.push(innerIdx);
|
|
2058
|
+
} else {
|
|
2059
|
+
current += template2[pos++];
|
|
2060
|
+
}
|
|
2061
|
+
}
|
|
2062
|
+
if (pos < len) pos++;
|
|
2063
|
+
statics.push(current);
|
|
2064
|
+
if (exprs.length === 0) {
|
|
2065
|
+
return { kind: "static", value: statics[0] };
|
|
2066
|
+
}
|
|
2067
|
+
return { kind: "mixed", statics, exprs };
|
|
2068
|
+
}
|
|
2069
|
+
let val = "";
|
|
2070
|
+
while (pos < len && !/[\s>/]/.test(template2[pos])) val += template2[pos++];
|
|
2071
|
+
return { kind: "static", value: val };
|
|
2072
|
+
}
|
|
2073
|
+
function parseAttrs() {
|
|
2074
|
+
const attrs = [];
|
|
2075
|
+
while (pos < len) {
|
|
2076
|
+
skipWs();
|
|
2077
|
+
if (template2[pos] === ">" || template2[pos] === "/") break;
|
|
2078
|
+
let attrName = "";
|
|
2079
|
+
while (pos < len && /[a-zA-Z0-9\-:_.]/.test(template2[pos])) attrName += template2[pos++];
|
|
2080
|
+
if (!attrName) break;
|
|
2081
|
+
const val = parseAttrValue();
|
|
2082
|
+
if (attrName.startsWith("on:")) {
|
|
2083
|
+
if (val.kind === "expr") {
|
|
2084
|
+
attrs.push({ t: 3, name: attrName.slice(3), idx: val.idx });
|
|
2085
|
+
}
|
|
2086
|
+
} else if (val.kind === "bool") {
|
|
2087
|
+
attrs.push({ t: 4, name: attrName });
|
|
2088
|
+
} else if (val.kind === "static") {
|
|
2089
|
+
attrs.push({ t: 0, name: attrName, value: val.value });
|
|
2090
|
+
} else if (val.kind === "expr") {
|
|
2091
|
+
attrs.push({ t: 1, name: attrName, idx: val.idx });
|
|
2092
|
+
} else if (val.kind === "mixed") {
|
|
2093
|
+
attrs.push({ t: 2, name: attrName, statics: val.statics, exprs: val.exprs });
|
|
2094
|
+
}
|
|
2095
|
+
}
|
|
2096
|
+
return attrs;
|
|
2097
|
+
}
|
|
2098
|
+
function collapseWs(s2) {
|
|
2099
|
+
return s2.replace(/\s+/g, " ");
|
|
2100
|
+
}
|
|
2101
|
+
function parseTextChildren(children) {
|
|
2102
|
+
let text2 = "";
|
|
2103
|
+
while (pos < len && template2[pos] !== "<") {
|
|
2104
|
+
const idx = tryExprIdx();
|
|
2105
|
+
if (idx >= 0) {
|
|
2106
|
+
const collapsed2 = collapseWs(text2);
|
|
2107
|
+
if (collapsed2) children.push({ t: 1, value: collapsed2 });
|
|
2108
|
+
text2 = "";
|
|
2109
|
+
children.push({ t: 2, idx });
|
|
2110
|
+
} else {
|
|
2111
|
+
text2 += template2[pos++];
|
|
2112
|
+
}
|
|
2113
|
+
}
|
|
2114
|
+
const collapsed = collapseWs(text2);
|
|
2115
|
+
if (collapsed) children.push({ t: 1, value: collapsed });
|
|
2116
|
+
}
|
|
2117
|
+
function parseChildren() {
|
|
2118
|
+
const children = [];
|
|
2119
|
+
while (pos < len) {
|
|
2120
|
+
if (template2[pos] === "<" && pos + 1 < len && template2[pos + 1] === "/") break;
|
|
2121
|
+
if (template2[pos] === "<") {
|
|
2122
|
+
pos++;
|
|
2123
|
+
const tag = readTagName();
|
|
2124
|
+
const attrs = parseAttrs();
|
|
2125
|
+
skipWs();
|
|
2126
|
+
const isVoid = VOID_ELEMENTS3.has(tag);
|
|
2127
|
+
const isSelfClosing = template2[pos] === "/";
|
|
2128
|
+
if (isSelfClosing) pos++;
|
|
2129
|
+
if (pos < len) pos++;
|
|
2130
|
+
if (isVoid || isSelfClosing) {
|
|
2131
|
+
children.push({ t: 0, el: { tag, svg: SVG_TAGS2.has(tag), attrs, children: [] } });
|
|
2132
|
+
} else {
|
|
2133
|
+
const inner = parseChildren();
|
|
2134
|
+
if (template2[pos] === "<" && pos + 1 < len && template2[pos + 1] === "/") {
|
|
2135
|
+
pos += 2;
|
|
2136
|
+
readTagName();
|
|
2137
|
+
skipWs();
|
|
2138
|
+
if (pos < len && template2[pos] === ">") pos++;
|
|
2139
|
+
}
|
|
2140
|
+
children.push({ t: 0, el: { tag, svg: SVG_TAGS2.has(tag), attrs, children: inner } });
|
|
2141
|
+
}
|
|
2142
|
+
} else {
|
|
2143
|
+
parseTextChildren(children);
|
|
2144
|
+
}
|
|
2145
|
+
}
|
|
2146
|
+
return children;
|
|
2147
|
+
}
|
|
2148
|
+
return parseChildren();
|
|
2149
|
+
}
|
|
2150
|
+
var factoryCache = /* @__PURE__ */ new Map();
|
|
2151
|
+
function getFactory(tag, svg2) {
|
|
2152
|
+
const key = svg2 ? `svg:${tag}` : tag;
|
|
2153
|
+
let f = factoryCache.get(key);
|
|
2154
|
+
if (!f) {
|
|
2155
|
+
f = tagFactory(tag, svg2 ? SVG_NS : void 0);
|
|
2156
|
+
factoryCache.set(key, f);
|
|
2157
|
+
}
|
|
2158
|
+
return f;
|
|
2159
|
+
}
|
|
2160
|
+
function executeElement(tmpl, values) {
|
|
2161
|
+
const props = {};
|
|
2162
|
+
const events = {};
|
|
2163
|
+
let hasEvents = false;
|
|
2164
|
+
for (let i2 = 0; i2 < tmpl.attrs.length; i2++) {
|
|
2165
|
+
const attr = tmpl.attrs[i2];
|
|
2166
|
+
switch (attr.t) {
|
|
2167
|
+
case 0:
|
|
2168
|
+
props[attr.name] = attr.value;
|
|
2169
|
+
break;
|
|
2170
|
+
case 1:
|
|
2171
|
+
props[attr.name] = values[attr.idx];
|
|
2172
|
+
break;
|
|
2173
|
+
case 2: {
|
|
2174
|
+
let val = attr.statics[0];
|
|
2175
|
+
for (let j = 0; j < attr.exprs.length; j++) {
|
|
2176
|
+
val += String(values[attr.exprs[j]]) + attr.statics[j + 1];
|
|
2177
|
+
}
|
|
2178
|
+
props[attr.name] = val;
|
|
2179
|
+
break;
|
|
2180
|
+
}
|
|
2181
|
+
case 3:
|
|
2182
|
+
events[attr.name] = values[attr.idx];
|
|
2183
|
+
hasEvents = true;
|
|
2184
|
+
break;
|
|
2185
|
+
case 4:
|
|
2186
|
+
props[attr.name] = true;
|
|
2187
|
+
break;
|
|
2188
|
+
}
|
|
2189
|
+
}
|
|
2190
|
+
if (hasEvents) props.on = events;
|
|
2191
|
+
if (tmpl.children.length > 0) {
|
|
2192
|
+
const nodes = executeChildList(tmpl.children, values);
|
|
2193
|
+
props.nodes = nodes.length === 1 ? nodes[0] : nodes;
|
|
2194
|
+
}
|
|
2195
|
+
return getFactory(tmpl.tag, tmpl.svg)(props);
|
|
2196
|
+
}
|
|
2197
|
+
function executeChildList(children, values) {
|
|
2198
|
+
const nodes = [];
|
|
2199
|
+
for (let i2 = 0; i2 < children.length; i2++) {
|
|
2200
|
+
const child = children[i2];
|
|
2201
|
+
switch (child.t) {
|
|
2202
|
+
case 0:
|
|
2203
|
+
nodes.push(executeElement(child.el, values));
|
|
2204
|
+
break;
|
|
2205
|
+
case 1:
|
|
2206
|
+
nodes.push(child.value);
|
|
2207
|
+
break;
|
|
2208
|
+
case 2:
|
|
2209
|
+
nodes.push(values[child.idx]);
|
|
2210
|
+
break;
|
|
2211
|
+
}
|
|
2212
|
+
}
|
|
2213
|
+
return nodes;
|
|
2214
|
+
}
|
|
2215
|
+
function html2(strings, ...values) {
|
|
2216
|
+
let tmpl = cache.get(strings);
|
|
2217
|
+
if (!tmpl) {
|
|
2218
|
+
tmpl = parseTemplate(strings);
|
|
2219
|
+
cache.set(strings, tmpl);
|
|
2220
|
+
}
|
|
2221
|
+
const result = executeChildList(tmpl, values);
|
|
2222
|
+
if (result.length === 1 && result[0] instanceof Node) {
|
|
2223
|
+
return result[0];
|
|
2224
|
+
}
|
|
2225
|
+
const wrapper = document.createElement("div");
|
|
2226
|
+
for (const node of result) {
|
|
2227
|
+
if (node instanceof Node) {
|
|
2228
|
+
wrapper.appendChild(node);
|
|
2229
|
+
} else if (typeof node === "function") {
|
|
2230
|
+
const placeholder = document.createComment("bind:htm");
|
|
2231
|
+
wrapper.appendChild(placeholder);
|
|
2232
|
+
const teardown = bindChildNode(placeholder, node);
|
|
2233
|
+
registerDisposer(wrapper, teardown);
|
|
2234
|
+
} else if (node != null) {
|
|
2235
|
+
wrapper.appendChild(document.createTextNode(String(node)));
|
|
2236
|
+
}
|
|
2237
|
+
}
|
|
2238
|
+
return wrapper;
|
|
2239
|
+
}
|
|
2240
|
+
|
|
2241
|
+
// src/core/rendering/mount.ts
|
|
2242
|
+
function mount(component, container) {
|
|
2243
|
+
if (!container) {
|
|
2244
|
+
throw new Error(
|
|
2245
|
+
"[Sibu] mount: container element not found. Make sure the DOM element exists before calling mount()."
|
|
2246
|
+
);
|
|
2247
|
+
}
|
|
2248
|
+
devAssert(
|
|
2249
|
+
typeof component === "function" || component instanceof Node,
|
|
2250
|
+
"mount: first argument must be a component function or a DOM Node."
|
|
2251
|
+
);
|
|
2252
|
+
const startTime = typeof performance !== "undefined" ? performance.now() : 0;
|
|
2253
|
+
const node = typeof component === "function" ? component() : component;
|
|
2254
|
+
const duration = typeof performance !== "undefined" ? performance.now() - startTime : 0;
|
|
2255
|
+
container.appendChild(node);
|
|
2256
|
+
const hook = globalThis.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
2257
|
+
if (hook) {
|
|
2258
|
+
hook.emit("app:init", { rootElement: node, container, duration });
|
|
2259
|
+
}
|
|
2260
|
+
return {
|
|
2261
|
+
node,
|
|
2262
|
+
unmount() {
|
|
2263
|
+
if (hook) hook.emit("app:unmount", { rootElement: node });
|
|
2264
|
+
dispose(node);
|
|
2265
|
+
if (node.parentNode) {
|
|
2266
|
+
node.parentNode.removeChild(node);
|
|
2267
|
+
}
|
|
2268
|
+
}
|
|
2269
|
+
};
|
|
2270
|
+
}
|
|
2271
|
+
|
|
2272
|
+
// src/core/rendering/each.ts
|
|
2273
|
+
function resolveNodeChild(child) {
|
|
2274
|
+
if (typeof child === "function") {
|
|
2275
|
+
return resolveNodeChild(child());
|
|
2276
|
+
}
|
|
2277
|
+
if (child instanceof Node) {
|
|
2278
|
+
return child;
|
|
2279
|
+
}
|
|
2280
|
+
return document.createTextNode(String(child));
|
|
2281
|
+
}
|
|
2282
|
+
function longestIncreasingSubsequence(arr, len) {
|
|
2283
|
+
if (len === 0) return [];
|
|
2284
|
+
const tails = [];
|
|
2285
|
+
const predecessor = new Array(len);
|
|
2286
|
+
for (let i2 = 0; i2 < len; i2++) {
|
|
2287
|
+
const val = arr[i2];
|
|
2288
|
+
let lo = 0;
|
|
2289
|
+
let hi = tails.length;
|
|
2290
|
+
while (lo < hi) {
|
|
2291
|
+
const mid = lo + hi >> 1;
|
|
2292
|
+
if (arr[tails[mid]] < val) {
|
|
2293
|
+
lo = mid + 1;
|
|
2294
|
+
} else {
|
|
2295
|
+
hi = mid;
|
|
2296
|
+
}
|
|
2297
|
+
}
|
|
2298
|
+
tails[lo] = i2;
|
|
2299
|
+
predecessor[i2] = lo > 0 ? tails[lo - 1] : -1;
|
|
2300
|
+
}
|
|
2301
|
+
const lisLength = tails.length;
|
|
2302
|
+
const result = new Array(lisLength);
|
|
2303
|
+
let k = tails[lisLength - 1];
|
|
2304
|
+
for (let i2 = lisLength - 1; i2 >= 0; i2--) {
|
|
2305
|
+
result[i2] = k;
|
|
2306
|
+
k = predecessor[k];
|
|
2307
|
+
}
|
|
2308
|
+
return result;
|
|
2309
|
+
}
|
|
2310
|
+
function each(getArray, render, options) {
|
|
2311
|
+
devAssert(typeof getArray === "function", "each: first argument must be a function that returns an array.");
|
|
2312
|
+
devAssert(typeof render === "function", "each: second argument must be a render function.");
|
|
2313
|
+
devAssert(
|
|
2314
|
+
options && typeof options.key === "function",
|
|
2315
|
+
"each: options.key must be a function that returns a unique key per item."
|
|
2316
|
+
);
|
|
2317
|
+
const anchor = document.createComment("each:anchor");
|
|
2318
|
+
const end = document.createComment("each:end");
|
|
2319
|
+
let oldKeys = [];
|
|
2320
|
+
let nodeMap = /* @__PURE__ */ new Map();
|
|
2321
|
+
let workMap = /* @__PURE__ */ new Map();
|
|
2322
|
+
let newNodes = [];
|
|
2323
|
+
const oldKeyIndex = /* @__PURE__ */ new Map();
|
|
2324
|
+
let reusedNewBuf = [];
|
|
2325
|
+
let reusedOldBuf = [];
|
|
2326
|
+
let initialized = false;
|
|
2327
|
+
let sentinelInserted = false;
|
|
2328
|
+
const keyFn = options.key;
|
|
2329
|
+
const update = () => {
|
|
2330
|
+
const arr = getArray();
|
|
2331
|
+
const newLen = arr.length;
|
|
2332
|
+
const parent = anchor.parentNode;
|
|
2333
|
+
if (!parent) return;
|
|
2334
|
+
if (!sentinelInserted) {
|
|
2335
|
+
parent.insertBefore(end, anchor.nextSibling);
|
|
2336
|
+
sentinelInserted = true;
|
|
2337
|
+
}
|
|
2338
|
+
const newKeys = new Array(newLen);
|
|
2339
|
+
for (let i2 = 0; i2 < newLen; i2++) {
|
|
2340
|
+
newKeys[i2] = keyFn(arr[i2]);
|
|
2341
|
+
}
|
|
2342
|
+
if (newNodes.length < newLen) {
|
|
2343
|
+
newNodes = new Array(newLen);
|
|
2344
|
+
}
|
|
2345
|
+
workMap.clear();
|
|
2346
|
+
for (let i2 = 0; i2 < newLen; i2++) {
|
|
2347
|
+
const key = newKeys[i2];
|
|
2348
|
+
const existing = nodeMap.get(key);
|
|
2349
|
+
let node;
|
|
2350
|
+
if (existing !== void 0) {
|
|
2351
|
+
node = existing;
|
|
2352
|
+
} else {
|
|
2353
|
+
node = resolveNodeChild(render(arr[i2], i2));
|
|
2354
|
+
}
|
|
2355
|
+
workMap.set(key, node);
|
|
2356
|
+
newNodes[i2] = node;
|
|
2357
|
+
}
|
|
2358
|
+
for (const [key, node] of nodeMap) {
|
|
2359
|
+
if (!workMap.has(key) && node.parentNode) {
|
|
2360
|
+
parent.removeChild(node);
|
|
2361
|
+
}
|
|
2362
|
+
}
|
|
2363
|
+
if (newLen === 0) {
|
|
2364
|
+
oldKeys = newKeys;
|
|
2365
|
+
const tmp2 = nodeMap;
|
|
2366
|
+
nodeMap = workMap;
|
|
2367
|
+
workMap = tmp2;
|
|
2368
|
+
return;
|
|
2369
|
+
}
|
|
2370
|
+
const oldLen = oldKeys.length;
|
|
2371
|
+
oldKeyIndex.clear();
|
|
2372
|
+
for (let i2 = 0; i2 < oldLen; i2++) {
|
|
2373
|
+
oldKeyIndex.set(oldKeys[i2], i2);
|
|
2374
|
+
}
|
|
2375
|
+
if (reusedNewBuf.length < newLen) {
|
|
2376
|
+
reusedNewBuf = new Array(newLen);
|
|
2377
|
+
reusedOldBuf = new Array(newLen);
|
|
2378
|
+
}
|
|
2379
|
+
let reusedCount = 0;
|
|
2380
|
+
for (let i2 = 0; i2 < newLen; i2++) {
|
|
2381
|
+
const oldIdx = oldKeyIndex.get(newKeys[i2]);
|
|
2382
|
+
if (oldIdx !== void 0) {
|
|
2383
|
+
reusedNewBuf[reusedCount] = i2;
|
|
2384
|
+
reusedOldBuf[reusedCount] = oldIdx;
|
|
2385
|
+
reusedCount++;
|
|
2386
|
+
}
|
|
2387
|
+
}
|
|
2388
|
+
const lisIndices = longestIncreasingSubsequence(reusedOldBuf, reusedCount);
|
|
2389
|
+
const isStable = new Uint8Array(newLen);
|
|
2390
|
+
for (let i2 = 0; i2 < lisIndices.length; i2++) {
|
|
2391
|
+
isStable[reusedNewBuf[lisIndices[i2]]] = 1;
|
|
2392
|
+
}
|
|
2393
|
+
let nextRef = end;
|
|
2394
|
+
for (let i2 = newLen - 1; i2 >= 0; i2--) {
|
|
2395
|
+
const node = newNodes[i2];
|
|
2396
|
+
if (isStable[i2]) {
|
|
2397
|
+
nextRef = node;
|
|
2398
|
+
} else {
|
|
2399
|
+
if (node.nextSibling !== nextRef) {
|
|
2400
|
+
parent.insertBefore(node, nextRef);
|
|
2401
|
+
}
|
|
2402
|
+
nextRef = node;
|
|
2403
|
+
}
|
|
2404
|
+
}
|
|
2405
|
+
oldKeys = newKeys;
|
|
2406
|
+
const tmp = nodeMap;
|
|
2407
|
+
nodeMap = workMap;
|
|
2408
|
+
workMap = tmp;
|
|
2409
|
+
initialized = true;
|
|
2410
|
+
};
|
|
2411
|
+
track(update);
|
|
2412
|
+
if (!initialized) {
|
|
2413
|
+
queueMicrotask(() => {
|
|
2414
|
+
if (!initialized && anchor.parentNode) {
|
|
2415
|
+
update();
|
|
2416
|
+
}
|
|
2417
|
+
});
|
|
2418
|
+
}
|
|
2419
|
+
return anchor;
|
|
2420
|
+
}
|
|
2421
|
+
|
|
2422
|
+
// src/core/rendering/fragment.ts
|
|
2423
|
+
function Fragment(nodes) {
|
|
2424
|
+
const frag = document.createDocumentFragment();
|
|
2425
|
+
for (const child of nodes) {
|
|
2426
|
+
if (child == null) continue;
|
|
2427
|
+
if (Array.isArray(child)) {
|
|
2428
|
+
for (const nested of child) {
|
|
2429
|
+
frag.appendChild(resolveChild(nested));
|
|
2430
|
+
}
|
|
2431
|
+
} else {
|
|
2432
|
+
frag.appendChild(resolveChild(child));
|
|
2433
|
+
}
|
|
2434
|
+
}
|
|
2435
|
+
return frag;
|
|
2436
|
+
}
|
|
2437
|
+
function resolveChild(child) {
|
|
2438
|
+
if (child == null) {
|
|
2439
|
+
return document.createTextNode("");
|
|
2440
|
+
}
|
|
2441
|
+
if (child instanceof Node) {
|
|
2442
|
+
return child;
|
|
2443
|
+
}
|
|
2444
|
+
if (typeof child === "function") {
|
|
2445
|
+
const result = child();
|
|
2446
|
+
if (result instanceof Node) return result;
|
|
2447
|
+
return document.createTextNode(String(result ?? ""));
|
|
2448
|
+
}
|
|
2449
|
+
return document.createTextNode(String(child));
|
|
2450
|
+
}
|
|
2451
|
+
|
|
2452
|
+
// src/core/rendering/portal.ts
|
|
2453
|
+
function Portal(nodes, target) {
|
|
2454
|
+
const anchor = document.createComment("portal");
|
|
2455
|
+
const container = target || document.body;
|
|
2456
|
+
let portalContent = null;
|
|
2457
|
+
queueMicrotask(() => {
|
|
2458
|
+
try {
|
|
2459
|
+
portalContent = nodes();
|
|
2460
|
+
container.appendChild(portalContent);
|
|
2461
|
+
} catch (err) {
|
|
2462
|
+
console.error("[Portal] Render error:", err);
|
|
2463
|
+
}
|
|
2464
|
+
});
|
|
2465
|
+
const observer = new MutationObserver(() => {
|
|
2466
|
+
if (!anchor.isConnected && portalContent) {
|
|
2467
|
+
portalContent.remove();
|
|
2468
|
+
portalContent = null;
|
|
2469
|
+
observer.disconnect();
|
|
2470
|
+
}
|
|
2471
|
+
});
|
|
2472
|
+
queueMicrotask(() => {
|
|
2473
|
+
if (anchor.parentNode) {
|
|
2474
|
+
observer.observe(anchor.parentNode, { childList: true });
|
|
2475
|
+
}
|
|
2476
|
+
});
|
|
2477
|
+
return anchor;
|
|
2478
|
+
}
|
|
2479
|
+
|
|
2480
|
+
// src/core/rendering/dynamic.ts
|
|
2481
|
+
var componentRegistry = /* @__PURE__ */ new Map();
|
|
2482
|
+
function registerComponent(name, component) {
|
|
2483
|
+
componentRegistry.set(name, component);
|
|
2484
|
+
}
|
|
2485
|
+
function unregisterComponent(name) {
|
|
2486
|
+
componentRegistry.delete(name);
|
|
2487
|
+
}
|
|
2488
|
+
function resolveComponent(name) {
|
|
2489
|
+
const component = componentRegistry.get(name);
|
|
2490
|
+
if (component) {
|
|
2491
|
+
return component();
|
|
2492
|
+
}
|
|
2493
|
+
return div({ nodes: `[Component "${name}" not found]` });
|
|
2494
|
+
}
|
|
2495
|
+
function DynamicComponent(is) {
|
|
2496
|
+
const container = div({ class: "sibu-dynamic" });
|
|
2497
|
+
function render() {
|
|
2498
|
+
const target = is();
|
|
2499
|
+
let el;
|
|
2500
|
+
if (typeof target === "function") {
|
|
2501
|
+
el = target();
|
|
2502
|
+
} else {
|
|
2503
|
+
el = resolveComponent(target);
|
|
2504
|
+
}
|
|
2505
|
+
container.replaceChildren(el);
|
|
2506
|
+
}
|
|
2507
|
+
track(render);
|
|
2508
|
+
return container;
|
|
2509
|
+
}
|
|
2510
|
+
|
|
2511
|
+
// src/core/rendering/slots.ts
|
|
2512
|
+
function getSlot(slots, name = "default") {
|
|
2513
|
+
return slots?.[name];
|
|
2514
|
+
}
|
|
2515
|
+
|
|
2516
|
+
// src/core/rendering/directives.ts
|
|
2517
|
+
function show(condition, element) {
|
|
2518
|
+
const update = () => {
|
|
2519
|
+
element.style.display = condition() ? "" : "none";
|
|
2520
|
+
};
|
|
2521
|
+
track(update);
|
|
2522
|
+
return element;
|
|
2523
|
+
}
|
|
2524
|
+
function when(condition, thenBranch, elseBranch) {
|
|
2525
|
+
const anchor = document.createComment("when");
|
|
2526
|
+
let currentNode = null;
|
|
2527
|
+
let initialized = false;
|
|
2528
|
+
const update = () => {
|
|
2529
|
+
const show2 = condition();
|
|
2530
|
+
const parent = anchor.parentNode;
|
|
2531
|
+
if (!parent) return;
|
|
2532
|
+
if (currentNode?.parentNode) {
|
|
2533
|
+
currentNode.parentNode.removeChild(currentNode);
|
|
2534
|
+
currentNode = null;
|
|
2535
|
+
}
|
|
2536
|
+
const result = show2 ? thenBranch() : elseBranch ? elseBranch() : null;
|
|
2537
|
+
if (result != null) {
|
|
2538
|
+
const node = result instanceof Node ? result : document.createTextNode(String(result));
|
|
2539
|
+
parent.insertBefore(node, anchor.nextSibling);
|
|
2540
|
+
currentNode = node;
|
|
2541
|
+
}
|
|
2542
|
+
initialized = true;
|
|
2543
|
+
};
|
|
2544
|
+
track(update);
|
|
2545
|
+
if (!initialized) {
|
|
2546
|
+
queueMicrotask(() => {
|
|
2547
|
+
if (!initialized && anchor.parentNode) update();
|
|
2548
|
+
});
|
|
2549
|
+
}
|
|
2550
|
+
return anchor;
|
|
2551
|
+
}
|
|
2552
|
+
function match(value, cases, fallback) {
|
|
2553
|
+
const anchor = document.createComment("match");
|
|
2554
|
+
let currentNode = null;
|
|
2555
|
+
let initialized = false;
|
|
2556
|
+
const update = () => {
|
|
2557
|
+
const key = String(value());
|
|
2558
|
+
const parent = anchor.parentNode;
|
|
2559
|
+
if (!parent) return;
|
|
2560
|
+
if (currentNode?.parentNode) {
|
|
2561
|
+
currentNode.parentNode.removeChild(currentNode);
|
|
2562
|
+
currentNode = null;
|
|
2563
|
+
}
|
|
2564
|
+
const renderFn = cases[key] || fallback;
|
|
2565
|
+
if (renderFn) {
|
|
2566
|
+
const result = renderFn();
|
|
2567
|
+
if (result != null) {
|
|
2568
|
+
const node = result instanceof Node ? result : document.createTextNode(String(result));
|
|
2569
|
+
parent.insertBefore(node, anchor.nextSibling);
|
|
2570
|
+
currentNode = node;
|
|
2571
|
+
}
|
|
2572
|
+
}
|
|
2573
|
+
initialized = true;
|
|
2574
|
+
};
|
|
2575
|
+
track(update);
|
|
2576
|
+
if (!initialized) {
|
|
2577
|
+
queueMicrotask(() => {
|
|
2578
|
+
if (!initialized && anchor.parentNode) update();
|
|
2579
|
+
});
|
|
2580
|
+
}
|
|
2581
|
+
return anchor;
|
|
2582
|
+
}
|
|
2583
|
+
|
|
2584
|
+
// src/core/rendering/catch.ts
|
|
2585
|
+
var globalErrorHandler = null;
|
|
2586
|
+
function catchError(fn, onError) {
|
|
2587
|
+
try {
|
|
2588
|
+
const result = fn();
|
|
2589
|
+
if (result && typeof result.then === "function") {
|
|
2590
|
+
result.catch((err) => {
|
|
2591
|
+
if (onError) {
|
|
2592
|
+
onError(err, "async");
|
|
2593
|
+
} else if (globalErrorHandler) {
|
|
2594
|
+
globalErrorHandler(err, "async");
|
|
2595
|
+
} else {
|
|
2596
|
+
console.error("Unhandled async error in Sibu.catchError:", err);
|
|
2597
|
+
}
|
|
2598
|
+
});
|
|
2599
|
+
}
|
|
2600
|
+
return result;
|
|
2601
|
+
} catch (err) {
|
|
2602
|
+
if (onError) {
|
|
2603
|
+
onError(err, "sync");
|
|
2604
|
+
} else if (globalErrorHandler) {
|
|
2605
|
+
globalErrorHandler(err, "sync");
|
|
2606
|
+
} else {
|
|
2607
|
+
console.error("Unhandled error in Sibu.catchError:", err);
|
|
2608
|
+
}
|
|
2609
|
+
return null;
|
|
2610
|
+
}
|
|
2611
|
+
}
|
|
2612
|
+
async function catchErrorAsync(fn, onError) {
|
|
2613
|
+
try {
|
|
2614
|
+
return await fn();
|
|
2615
|
+
} catch (err) {
|
|
2616
|
+
if (onError) {
|
|
2617
|
+
onError(err, "async");
|
|
2618
|
+
} else if (globalErrorHandler) {
|
|
2619
|
+
globalErrorHandler(err, "async");
|
|
2620
|
+
} else {
|
|
2621
|
+
console.error("Unhandled async error in Sibu.catchErrorAsync:", err);
|
|
2622
|
+
}
|
|
2623
|
+
return null;
|
|
2624
|
+
}
|
|
2625
|
+
}
|
|
2626
|
+
function setGlobalErrorHandler(handler) {
|
|
2627
|
+
globalErrorHandler = handler;
|
|
2628
|
+
}
|
|
2629
|
+
|
|
2630
|
+
// src/reactivity/batch.ts
|
|
2631
|
+
var batchDepth = 0;
|
|
2632
|
+
var pendingSignals = /* @__PURE__ */ new Set();
|
|
2633
|
+
function batch(fn) {
|
|
2634
|
+
batchDepth++;
|
|
2635
|
+
try {
|
|
2636
|
+
fn();
|
|
2637
|
+
} finally {
|
|
2638
|
+
batchDepth--;
|
|
2639
|
+
if (batchDepth === 0) {
|
|
2640
|
+
flushBatch();
|
|
2641
|
+
}
|
|
2642
|
+
}
|
|
2643
|
+
}
|
|
2644
|
+
function enqueueBatchedSignal(signal2) {
|
|
2645
|
+
if (batchDepth === 0) return false;
|
|
2646
|
+
pendingSignals.add(signal2);
|
|
2647
|
+
return true;
|
|
2648
|
+
}
|
|
2649
|
+
function isBatching() {
|
|
2650
|
+
return batchDepth > 0;
|
|
2651
|
+
}
|
|
2652
|
+
function flushBatch() {
|
|
2653
|
+
const signals = Array.from(pendingSignals);
|
|
2654
|
+
pendingSignals.clear();
|
|
2655
|
+
for (const signal2 of signals) {
|
|
2656
|
+
queueSignalNotification(signal2);
|
|
2657
|
+
}
|
|
2658
|
+
drainNotificationQueue();
|
|
2659
|
+
}
|
|
2660
|
+
|
|
2661
|
+
// src/core/signals/signal.ts
|
|
2662
|
+
function signal(initial, options) {
|
|
2663
|
+
const state = { value: initial };
|
|
2664
|
+
const debugName = options?.name;
|
|
2665
|
+
if (debugName) {
|
|
2666
|
+
state.__name = debugName;
|
|
2667
|
+
}
|
|
2668
|
+
function get() {
|
|
2669
|
+
recordDependency(state);
|
|
2670
|
+
return state.value;
|
|
2671
|
+
}
|
|
2672
|
+
get.__signal = state;
|
|
2673
|
+
if (debugName) get.__name = debugName;
|
|
2674
|
+
function set(next) {
|
|
2675
|
+
const newValue = typeof next === "function" ? next(state.value) : next;
|
|
2676
|
+
if (Object.is(newValue, state.value)) return;
|
|
2677
|
+
const oldValue = state.value;
|
|
2678
|
+
state.value = newValue;
|
|
2679
|
+
const hook2 = globalThis.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
2680
|
+
if (hook2) hook2.emit("signal:update", { signal: state, name: debugName, oldValue, newValue });
|
|
2681
|
+
if (!enqueueBatchedSignal(state)) {
|
|
2682
|
+
notifySubscribers(state);
|
|
2683
|
+
}
|
|
2684
|
+
}
|
|
2685
|
+
const hook = globalThis.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
2686
|
+
if (hook) hook.emit("signal:create", { signal: state, name: debugName, getter: get, initial });
|
|
2687
|
+
return [get, set];
|
|
2688
|
+
}
|
|
2689
|
+
|
|
2690
|
+
// src/core/ssr-context.ts
|
|
2691
|
+
var ssrMode = false;
|
|
2692
|
+
function isSSR() {
|
|
2693
|
+
return ssrMode;
|
|
2694
|
+
}
|
|
2695
|
+
function enableSSR() {
|
|
2696
|
+
ssrMode = true;
|
|
2697
|
+
}
|
|
2698
|
+
function disableSSR() {
|
|
2699
|
+
ssrMode = false;
|
|
2700
|
+
}
|
|
2701
|
+
function withSSR(fn) {
|
|
2702
|
+
enableSSR();
|
|
2703
|
+
try {
|
|
2704
|
+
return fn();
|
|
2705
|
+
} finally {
|
|
2706
|
+
disableSSR();
|
|
2707
|
+
}
|
|
2708
|
+
}
|
|
2709
|
+
|
|
2710
|
+
// src/core/signals/effect.ts
|
|
2711
|
+
function effect(effectFn) {
|
|
2712
|
+
devAssert(typeof effectFn === "function", "effect: argument must be a function.");
|
|
2713
|
+
if (isSSR()) return () => {
|
|
2714
|
+
};
|
|
2715
|
+
let runCount = 0;
|
|
2716
|
+
let cleanupHandle = () => {
|
|
2717
|
+
};
|
|
2718
|
+
const hook = globalThis.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
2719
|
+
const subscriber = () => {
|
|
2720
|
+
cleanupHandle();
|
|
2721
|
+
runCount++;
|
|
2722
|
+
if (hook) hook.emit("effect:run", { effectFn, runCount });
|
|
2723
|
+
cleanupHandle = track(effectFn, subscriber);
|
|
2724
|
+
};
|
|
2725
|
+
cleanupHandle = track(effectFn, subscriber);
|
|
2726
|
+
runCount = 1;
|
|
2727
|
+
if (hook) hook.emit("effect:create", { effectFn });
|
|
2728
|
+
return () => {
|
|
2729
|
+
if (hook) hook.emit("effect:destroy", { effectFn });
|
|
2730
|
+
cleanupHandle();
|
|
2731
|
+
};
|
|
2732
|
+
}
|
|
2733
|
+
|
|
2734
|
+
// src/core/signals/derived.ts
|
|
2735
|
+
function derived(getter, options) {
|
|
2736
|
+
devAssert(typeof getter === "function", "derived: argument must be a getter function.");
|
|
2737
|
+
const debugName = options?.name;
|
|
2738
|
+
const cs = {};
|
|
2739
|
+
cs._d = false;
|
|
2740
|
+
cs._g = getter;
|
|
2741
|
+
const markDirty = () => {
|
|
2742
|
+
if (cs._d) return;
|
|
2743
|
+
cs._d = true;
|
|
2744
|
+
};
|
|
2745
|
+
markDirty._c = 1;
|
|
2746
|
+
markDirty._sig = cs;
|
|
2747
|
+
track(() => {
|
|
2748
|
+
cs._d = false;
|
|
2749
|
+
cs._v = getter();
|
|
2750
|
+
}, markDirty);
|
|
2751
|
+
const hook = globalThis.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
2752
|
+
function computedGetter() {
|
|
2753
|
+
if (trackingSuspended) {
|
|
2754
|
+
if (cs._d) {
|
|
2755
|
+
cs._d = false;
|
|
2756
|
+
cs._v = getter();
|
|
2757
|
+
}
|
|
2758
|
+
return cs._v;
|
|
2759
|
+
}
|
|
2760
|
+
recordDependency(cs);
|
|
2761
|
+
if (cs._d) {
|
|
2762
|
+
const oldValue = cs._v;
|
|
2763
|
+
cs._d = false;
|
|
2764
|
+
suspendTracking();
|
|
2765
|
+
try {
|
|
2766
|
+
cs._v = getter();
|
|
2767
|
+
} finally {
|
|
2768
|
+
resumeTracking();
|
|
2769
|
+
}
|
|
2770
|
+
if (hook && oldValue !== cs._v) {
|
|
2771
|
+
hook.emit("computed:update", { signal: cs, oldValue, newValue: cs._v });
|
|
2772
|
+
}
|
|
2773
|
+
}
|
|
2774
|
+
return cs._v;
|
|
2775
|
+
}
|
|
2776
|
+
if (debugName) {
|
|
2777
|
+
computedGetter.__name = debugName;
|
|
2778
|
+
cs.__name = debugName;
|
|
2779
|
+
}
|
|
2780
|
+
computedGetter.__signal = cs;
|
|
2781
|
+
if (hook) hook.emit("computed:create", { signal: cs, name: debugName, getter: computedGetter });
|
|
2782
|
+
return computedGetter;
|
|
2783
|
+
}
|
|
2784
|
+
|
|
2785
|
+
// src/core/signals/watch.ts
|
|
2786
|
+
function watch(getter, callback) {
|
|
2787
|
+
devAssert(typeof getter === "function", "watch: first argument must be a getter function.");
|
|
2788
|
+
devAssert(typeof callback === "function", "watch: second argument must be a callback function.");
|
|
2789
|
+
if (isSSR()) return () => {
|
|
2790
|
+
};
|
|
2791
|
+
let oldValue = getter();
|
|
2792
|
+
const subscriber = () => {
|
|
2793
|
+
const newValue = getter();
|
|
2794
|
+
if (!Object.is(newValue, oldValue)) {
|
|
2795
|
+
callback(newValue, oldValue);
|
|
2796
|
+
oldValue = newValue;
|
|
2797
|
+
}
|
|
2798
|
+
};
|
|
2799
|
+
const teardown = track(subscriber);
|
|
2800
|
+
return teardown;
|
|
2801
|
+
}
|
|
2802
|
+
|
|
2803
|
+
// src/core/signals/store.ts
|
|
2804
|
+
function store(initialState) {
|
|
2805
|
+
devAssert(
|
|
2806
|
+
initialState !== null && typeof initialState === "object" && !Array.isArray(initialState),
|
|
2807
|
+
"store: argument must be a plain object. For arrays, use array() instead."
|
|
2808
|
+
);
|
|
2809
|
+
const signals = {};
|
|
2810
|
+
Object.keys(initialState).forEach((key) => {
|
|
2811
|
+
const [getter, setter] = signal(initialState[key]);
|
|
2812
|
+
signals[key] = [getter, setter];
|
|
2813
|
+
});
|
|
2814
|
+
const store2 = new Proxy({}, {
|
|
2815
|
+
get(_, prop) {
|
|
2816
|
+
if (prop in signals) {
|
|
2817
|
+
const getter = signals[prop][0];
|
|
2818
|
+
return getter();
|
|
2819
|
+
}
|
|
2820
|
+
return void 0;
|
|
2821
|
+
},
|
|
2822
|
+
set() {
|
|
2823
|
+
throw new Error(
|
|
2824
|
+
"[Sibu] store: Direct mutation is not allowed. Use actions.setState() to update store properties."
|
|
2825
|
+
);
|
|
2826
|
+
}
|
|
2827
|
+
});
|
|
2828
|
+
const getSnapshot = () => {
|
|
2829
|
+
const snapshot = {};
|
|
2830
|
+
Object.keys(signals).forEach((key) => {
|
|
2831
|
+
snapshot[key] = signals[key][0]();
|
|
2832
|
+
});
|
|
2833
|
+
return snapshot;
|
|
2834
|
+
};
|
|
2835
|
+
const setState = (patch) => {
|
|
2836
|
+
const current = getSnapshot();
|
|
2837
|
+
const nextState = typeof patch === "function" ? patch(current) : patch;
|
|
2838
|
+
Object.entries(nextState).forEach(([key, value]) => {
|
|
2839
|
+
if (key in signals) {
|
|
2840
|
+
signals[key][1](value);
|
|
2841
|
+
}
|
|
2842
|
+
});
|
|
2843
|
+
};
|
|
2844
|
+
const reset = () => {
|
|
2845
|
+
Object.keys(initialState).forEach((key) => {
|
|
2846
|
+
const setter = signals[key][1];
|
|
2847
|
+
setter(initialState[key]);
|
|
2848
|
+
});
|
|
2849
|
+
};
|
|
2850
|
+
const subscribe = (callback) => {
|
|
2851
|
+
return effect(() => {
|
|
2852
|
+
const snapshot = getSnapshot();
|
|
2853
|
+
callback(snapshot);
|
|
2854
|
+
});
|
|
2855
|
+
};
|
|
2856
|
+
const subscribeKey = (key, callback) => {
|
|
2857
|
+
let prev = signals[key][0]();
|
|
2858
|
+
return effect(() => {
|
|
2859
|
+
const current = signals[key][0]();
|
|
2860
|
+
if (!Object.is(current, prev)) {
|
|
2861
|
+
const oldPrev = prev;
|
|
2862
|
+
prev = current;
|
|
2863
|
+
callback(current, oldPrev);
|
|
2864
|
+
}
|
|
2865
|
+
});
|
|
2866
|
+
};
|
|
2867
|
+
return [store2, { setState, reset, subscribe, subscribeKey, getSnapshot }];
|
|
2868
|
+
}
|
|
2869
|
+
|
|
2870
|
+
// src/core/signals/ref.ts
|
|
2871
|
+
function ref(initial) {
|
|
2872
|
+
return { current: initial };
|
|
2873
|
+
}
|
|
2874
|
+
|
|
2875
|
+
// src/core/signals/memo.ts
|
|
2876
|
+
function memo(factory) {
|
|
2877
|
+
return derived(factory);
|
|
2878
|
+
}
|
|
2879
|
+
|
|
2880
|
+
// src/core/signals/memoFn.ts
|
|
2881
|
+
function memoFn(callback) {
|
|
2882
|
+
return derived(callback);
|
|
2883
|
+
}
|
|
2884
|
+
|
|
2885
|
+
// src/core/signals/array.ts
|
|
2886
|
+
function array(initial = []) {
|
|
2887
|
+
const [arr, setArr] = signal([...initial]);
|
|
2888
|
+
const actions = {
|
|
2889
|
+
push(...items) {
|
|
2890
|
+
setArr((prev) => [...prev, ...items]);
|
|
2891
|
+
},
|
|
2892
|
+
pop() {
|
|
2893
|
+
let removed;
|
|
2894
|
+
setArr((prev) => {
|
|
2895
|
+
const copy = [...prev];
|
|
2896
|
+
removed = copy.pop();
|
|
2897
|
+
return copy;
|
|
2898
|
+
});
|
|
2899
|
+
return removed;
|
|
2900
|
+
},
|
|
2901
|
+
shift() {
|
|
2902
|
+
let removed;
|
|
2903
|
+
setArr((prev) => {
|
|
2904
|
+
const copy = [...prev];
|
|
2905
|
+
removed = copy.shift();
|
|
2906
|
+
return copy;
|
|
2907
|
+
});
|
|
2908
|
+
return removed;
|
|
2909
|
+
},
|
|
2910
|
+
unshift(...items) {
|
|
2911
|
+
setArr((prev) => [...items, ...prev]);
|
|
2912
|
+
},
|
|
2913
|
+
splice(start, deleteCount = 0, ...items) {
|
|
2914
|
+
let removed = [];
|
|
2915
|
+
setArr((prev) => {
|
|
2916
|
+
const copy = [...prev];
|
|
2917
|
+
removed = copy.splice(start, deleteCount, ...items);
|
|
2918
|
+
return copy;
|
|
2919
|
+
});
|
|
2920
|
+
return removed;
|
|
2921
|
+
},
|
|
2922
|
+
remove(index) {
|
|
2923
|
+
setArr((prev) => prev.filter((_, i2) => i2 !== index));
|
|
2924
|
+
},
|
|
2925
|
+
removeWhere(predicate) {
|
|
2926
|
+
setArr((prev) => {
|
|
2927
|
+
const idx = prev.findIndex(predicate);
|
|
2928
|
+
if (idx === -1) return prev;
|
|
2929
|
+
return prev.filter((_, i2) => i2 !== idx);
|
|
2930
|
+
});
|
|
2931
|
+
},
|
|
2932
|
+
set(items) {
|
|
2933
|
+
setArr([...items]);
|
|
2934
|
+
},
|
|
2935
|
+
update(index, value) {
|
|
2936
|
+
setArr((prev) => prev.map((item, i2) => i2 === index ? value : item));
|
|
2937
|
+
},
|
|
2938
|
+
updateWhere(predicate, updater) {
|
|
2939
|
+
setArr((prev) => prev.map((item) => predicate(item) ? updater(item) : item));
|
|
2940
|
+
},
|
|
2941
|
+
sort(compareFn) {
|
|
2942
|
+
setArr((prev) => [...prev].sort(compareFn));
|
|
2943
|
+
},
|
|
2944
|
+
reverse() {
|
|
2945
|
+
setArr((prev) => [...prev].reverse());
|
|
2946
|
+
},
|
|
2947
|
+
filter(predicate) {
|
|
2948
|
+
setArr((prev) => prev.filter(predicate));
|
|
2949
|
+
},
|
|
2950
|
+
map(transform) {
|
|
2951
|
+
setArr((prev) => prev.map(transform));
|
|
2952
|
+
},
|
|
2953
|
+
clear() {
|
|
2954
|
+
setArr([]);
|
|
2955
|
+
}
|
|
2956
|
+
};
|
|
2957
|
+
return [arr, actions];
|
|
2958
|
+
}
|
|
2959
|
+
function reactiveArray(initial = []) {
|
|
2960
|
+
let data2 = [...initial];
|
|
2961
|
+
let snapshot = null;
|
|
2962
|
+
const signal2 = {};
|
|
2963
|
+
function notify() {
|
|
2964
|
+
snapshot = null;
|
|
2965
|
+
if (!enqueueBatchedSignal(signal2)) {
|
|
2966
|
+
notifySubscribers(signal2);
|
|
2967
|
+
}
|
|
2968
|
+
}
|
|
2969
|
+
function get() {
|
|
2970
|
+
recordDependency(signal2);
|
|
2971
|
+
if (snapshot === null) {
|
|
2972
|
+
snapshot = Object.freeze([...data2]);
|
|
2973
|
+
}
|
|
2974
|
+
return snapshot;
|
|
2975
|
+
}
|
|
2976
|
+
const actions = {
|
|
2977
|
+
push(...items) {
|
|
2978
|
+
if (items.length === 0) return;
|
|
2979
|
+
data2.push(...items);
|
|
2980
|
+
notify();
|
|
2981
|
+
},
|
|
2982
|
+
pop() {
|
|
2983
|
+
if (data2.length === 0) return void 0;
|
|
2984
|
+
const removed = data2.pop();
|
|
2985
|
+
notify();
|
|
2986
|
+
return removed;
|
|
2987
|
+
},
|
|
2988
|
+
shift() {
|
|
2989
|
+
if (data2.length === 0) return void 0;
|
|
2990
|
+
const removed = data2.shift();
|
|
2991
|
+
notify();
|
|
2992
|
+
return removed;
|
|
2993
|
+
},
|
|
2994
|
+
unshift(...items) {
|
|
2995
|
+
if (items.length === 0) return;
|
|
2996
|
+
data2.unshift(...items);
|
|
2997
|
+
notify();
|
|
2998
|
+
},
|
|
2999
|
+
splice(start, deleteCount = 0, ...items) {
|
|
3000
|
+
const removed = data2.splice(start, deleteCount, ...items);
|
|
3001
|
+
if (removed.length > 0 || items.length > 0) {
|
|
3002
|
+
notify();
|
|
3003
|
+
}
|
|
3004
|
+
return removed;
|
|
3005
|
+
},
|
|
3006
|
+
remove(index) {
|
|
3007
|
+
if (index < 0 || index >= data2.length) return;
|
|
3008
|
+
data2.splice(index, 1);
|
|
3009
|
+
notify();
|
|
3010
|
+
},
|
|
3011
|
+
removeWhere(predicate) {
|
|
3012
|
+
const idx = data2.findIndex(predicate);
|
|
3013
|
+
if (idx === -1) return;
|
|
3014
|
+
data2.splice(idx, 1);
|
|
3015
|
+
notify();
|
|
3016
|
+
},
|
|
3017
|
+
set(items) {
|
|
3018
|
+
data2 = [...items];
|
|
3019
|
+
notify();
|
|
3020
|
+
},
|
|
3021
|
+
update(index, value) {
|
|
3022
|
+
if (index < 0 || index >= data2.length) return;
|
|
3023
|
+
if (Object.is(data2[index], value)) return;
|
|
3024
|
+
data2[index] = value;
|
|
3025
|
+
notify();
|
|
3026
|
+
},
|
|
3027
|
+
updateWhere(predicate, updater) {
|
|
3028
|
+
let changed = false;
|
|
3029
|
+
for (let i2 = 0; i2 < data2.length; i2++) {
|
|
3030
|
+
if (predicate(data2[i2])) {
|
|
3031
|
+
const updated = updater(data2[i2]);
|
|
3032
|
+
if (!Object.is(data2[i2], updated)) {
|
|
3033
|
+
data2[i2] = updated;
|
|
3034
|
+
changed = true;
|
|
3035
|
+
}
|
|
3036
|
+
}
|
|
3037
|
+
}
|
|
3038
|
+
if (changed) notify();
|
|
3039
|
+
},
|
|
3040
|
+
sort(compareFn) {
|
|
3041
|
+
if (data2.length <= 1) return;
|
|
3042
|
+
data2.sort(compareFn);
|
|
3043
|
+
notify();
|
|
3044
|
+
},
|
|
3045
|
+
reverse() {
|
|
3046
|
+
if (data2.length <= 1) return;
|
|
3047
|
+
data2.reverse();
|
|
3048
|
+
notify();
|
|
3049
|
+
},
|
|
3050
|
+
filter(predicate) {
|
|
3051
|
+
const filtered = data2.filter(predicate);
|
|
3052
|
+
if (filtered.length === data2.length) return;
|
|
3053
|
+
data2 = filtered;
|
|
3054
|
+
notify();
|
|
3055
|
+
},
|
|
3056
|
+
map(transform) {
|
|
3057
|
+
let changed = false;
|
|
3058
|
+
for (let i2 = 0; i2 < data2.length; i2++) {
|
|
3059
|
+
const transformed = transform(data2[i2], i2);
|
|
3060
|
+
if (!Object.is(data2[i2], transformed)) {
|
|
3061
|
+
data2[i2] = transformed;
|
|
3062
|
+
changed = true;
|
|
3063
|
+
}
|
|
3064
|
+
}
|
|
3065
|
+
if (changed) notify();
|
|
3066
|
+
},
|
|
3067
|
+
clear() {
|
|
3068
|
+
if (data2.length === 0) return;
|
|
3069
|
+
data2 = [];
|
|
3070
|
+
notify();
|
|
3071
|
+
}
|
|
3072
|
+
};
|
|
3073
|
+
return [get, actions];
|
|
3074
|
+
}
|
|
3075
|
+
|
|
3076
|
+
// src/core/signals/deepSignal.ts
|
|
3077
|
+
function deepEqual(a2, b2) {
|
|
3078
|
+
if (Object.is(a2, b2)) return true;
|
|
3079
|
+
if (a2 == null || b2 == null) return false;
|
|
3080
|
+
if (typeof a2 !== typeof b2) return false;
|
|
3081
|
+
if (typeof a2 !== "object") return false;
|
|
3082
|
+
if (Array.isArray(a2)) {
|
|
3083
|
+
if (!Array.isArray(b2)) return false;
|
|
3084
|
+
if (a2.length !== b2.length) return false;
|
|
3085
|
+
return a2.every((val, i2) => deepEqual(val, b2[i2]));
|
|
3086
|
+
}
|
|
3087
|
+
const keysA = Object.keys(a2);
|
|
3088
|
+
const keysB = Object.keys(b2);
|
|
3089
|
+
if (keysA.length !== keysB.length) return false;
|
|
3090
|
+
return keysA.every((key) => deepEqual(a2[key], b2[key]));
|
|
3091
|
+
}
|
|
3092
|
+
function deepSignal(initial) {
|
|
3093
|
+
const state = { value: initial };
|
|
3094
|
+
function get() {
|
|
3095
|
+
recordDependency(state);
|
|
3096
|
+
return state.value;
|
|
3097
|
+
}
|
|
3098
|
+
function set(next) {
|
|
3099
|
+
const newValue = typeof next === "function" ? next(state.value) : next;
|
|
3100
|
+
if (deepEqual(newValue, state.value)) return;
|
|
3101
|
+
state.value = newValue;
|
|
3102
|
+
if (!enqueueBatchedSignal(state)) {
|
|
3103
|
+
notifySubscribers(state);
|
|
3104
|
+
}
|
|
3105
|
+
}
|
|
3106
|
+
return [get, set];
|
|
3107
|
+
}
|
|
3108
|
+
|
|
3109
|
+
// src/core/rendering/lifecycle.ts
|
|
3110
|
+
function onMount(callback, element) {
|
|
3111
|
+
if (typeof document === "undefined") return;
|
|
3112
|
+
if (element) {
|
|
3113
|
+
if (element.isConnected) {
|
|
3114
|
+
queueMicrotask(() => {
|
|
3115
|
+
callback();
|
|
3116
|
+
});
|
|
3117
|
+
return;
|
|
3118
|
+
}
|
|
3119
|
+
const observer = new MutationObserver(() => {
|
|
3120
|
+
if (element.isConnected) {
|
|
3121
|
+
observer.disconnect();
|
|
3122
|
+
callback();
|
|
3123
|
+
}
|
|
3124
|
+
});
|
|
3125
|
+
queueMicrotask(() => {
|
|
3126
|
+
if (element.isConnected) {
|
|
3127
|
+
callback();
|
|
3128
|
+
} else {
|
|
3129
|
+
observer.observe(document.body, { childList: true, subtree: true });
|
|
3130
|
+
}
|
|
3131
|
+
});
|
|
3132
|
+
} else {
|
|
3133
|
+
queueMicrotask(() => {
|
|
3134
|
+
callback();
|
|
3135
|
+
});
|
|
3136
|
+
}
|
|
3137
|
+
}
|
|
3138
|
+
function onUnmount(callback, element) {
|
|
3139
|
+
const startObserving = () => {
|
|
3140
|
+
const observer = new MutationObserver(() => {
|
|
3141
|
+
if (!element.isConnected) {
|
|
3142
|
+
observer.disconnect();
|
|
3143
|
+
callback();
|
|
3144
|
+
}
|
|
3145
|
+
});
|
|
3146
|
+
observer.observe(document.body, { childList: true, subtree: true });
|
|
3147
|
+
};
|
|
3148
|
+
if (element.isConnected) {
|
|
3149
|
+
startObserving();
|
|
3150
|
+
} else {
|
|
3151
|
+
onMount(() => {
|
|
3152
|
+
startObserving();
|
|
3153
|
+
return void 0;
|
|
3154
|
+
}, element);
|
|
3155
|
+
}
|
|
3156
|
+
}
|
|
3157
|
+
|
|
3158
|
+
// src/core/rendering/context.ts
|
|
3159
|
+
function context(defaultValue) {
|
|
3160
|
+
const [getValue, setValue] = signal(defaultValue);
|
|
3161
|
+
return {
|
|
3162
|
+
provide(value) {
|
|
3163
|
+
setValue(value);
|
|
3164
|
+
},
|
|
3165
|
+
use() {
|
|
3166
|
+
return getValue;
|
|
3167
|
+
},
|
|
3168
|
+
get() {
|
|
3169
|
+
return getValue();
|
|
3170
|
+
},
|
|
3171
|
+
set(value) {
|
|
3172
|
+
setValue(value);
|
|
3173
|
+
}
|
|
3174
|
+
};
|
|
3175
|
+
}
|
|
3176
|
+
|
|
3177
|
+
// src/core/rendering/lazy.ts
|
|
3178
|
+
function lazy(importFn) {
|
|
3179
|
+
let cached = null;
|
|
3180
|
+
return function LazyComponent() {
|
|
3181
|
+
if (cached) {
|
|
3182
|
+
return cached();
|
|
3183
|
+
}
|
|
3184
|
+
const [_status, setStatus] = signal("loading");
|
|
3185
|
+
const [_error, setError] = signal(null);
|
|
3186
|
+
const container = div({ class: "sibu-lazy" });
|
|
3187
|
+
importFn().then((mod) => {
|
|
3188
|
+
cached = mod.default;
|
|
3189
|
+
const rendered = cached();
|
|
3190
|
+
container.replaceChildren(rendered);
|
|
3191
|
+
setStatus("loaded");
|
|
3192
|
+
}).catch((err) => {
|
|
3193
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
3194
|
+
setError(errorObj);
|
|
3195
|
+
setStatus("error");
|
|
3196
|
+
container.replaceChildren(
|
|
3197
|
+
div({
|
|
3198
|
+
class: "sibu-lazy-error",
|
|
3199
|
+
nodes: `Failed to load component: ${errorObj.message}`
|
|
3200
|
+
})
|
|
3201
|
+
);
|
|
3202
|
+
});
|
|
3203
|
+
container.appendChild(span({ class: "sibu-lazy-loading", nodes: "Loading..." }));
|
|
3204
|
+
return container;
|
|
3205
|
+
};
|
|
3206
|
+
}
|
|
3207
|
+
function Suspense({ nodes, fallback }) {
|
|
3208
|
+
const container = div({ class: "sibu-suspense" });
|
|
3209
|
+
const fallbackEl = fallback();
|
|
3210
|
+
container.appendChild(fallbackEl);
|
|
3211
|
+
queueMicrotask(() => {
|
|
3212
|
+
try {
|
|
3213
|
+
const childEl = nodes();
|
|
3214
|
+
if (childEl.classList.contains("sibu-lazy")) {
|
|
3215
|
+
const observer = new MutationObserver(() => {
|
|
3216
|
+
const loading = childEl.querySelector(".sibu-lazy-loading");
|
|
3217
|
+
if (!loading) {
|
|
3218
|
+
observer.disconnect();
|
|
3219
|
+
container.replaceChildren(childEl);
|
|
3220
|
+
}
|
|
3221
|
+
});
|
|
3222
|
+
observer.observe(childEl, { childList: true, subtree: true });
|
|
3223
|
+
if (!childEl.querySelector(".sibu-lazy-loading")) {
|
|
3224
|
+
container.replaceChildren(childEl);
|
|
3225
|
+
}
|
|
3226
|
+
} else {
|
|
3227
|
+
container.replaceChildren(childEl);
|
|
3228
|
+
}
|
|
3229
|
+
} catch {
|
|
3230
|
+
}
|
|
3231
|
+
});
|
|
3232
|
+
return container;
|
|
3233
|
+
}
|
|
3234
|
+
|
|
3235
|
+
// src/components/ErrorBoundary.ts
|
|
3236
|
+
var errorBoundaryStyles = `
|
|
3237
|
+
.sibu-error-boundary {
|
|
3238
|
+
position: relative;
|
|
3239
|
+
}
|
|
3240
|
+
|
|
3241
|
+
.sibu-error-fallback {
|
|
3242
|
+
border: 2px solid #dc3545;
|
|
3243
|
+
border-radius: 8px;
|
|
3244
|
+
padding: 20px;
|
|
3245
|
+
margin: 10px 0;
|
|
3246
|
+
background: linear-gradient(135deg, #fff5f5 0%, #ffebee 100%);
|
|
3247
|
+
box-shadow: 0 2px 12px rgba(220, 53, 69, 0.15);
|
|
3248
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
3249
|
+
}
|
|
3250
|
+
|
|
3251
|
+
.sibu-error-fallback .sibu-error-title {
|
|
3252
|
+
margin: 0 0 12px 0;
|
|
3253
|
+
color: #dc3545;
|
|
3254
|
+
font-size: 1.1em;
|
|
3255
|
+
font-weight: 600;
|
|
3256
|
+
}
|
|
3257
|
+
|
|
3258
|
+
.sibu-error-fallback .sibu-error-message {
|
|
3259
|
+
font-family: 'SF Mono', 'Fira Code', 'Roboto Mono', monospace;
|
|
3260
|
+
background-color: rgba(0, 0, 0, 0.04);
|
|
3261
|
+
padding: 10px 14px;
|
|
3262
|
+
border-radius: 6px;
|
|
3263
|
+
border: 1px solid rgba(0, 0, 0, 0.08);
|
|
3264
|
+
margin: 10px 0;
|
|
3265
|
+
color: #495057;
|
|
3266
|
+
word-break: break-word;
|
|
3267
|
+
font-size: 0.9em;
|
|
3268
|
+
line-height: 1.5;
|
|
3269
|
+
}
|
|
3270
|
+
|
|
3271
|
+
.sibu-error-fallback .sibu-error-btn {
|
|
3272
|
+
display: inline-flex;
|
|
3273
|
+
align-items: center;
|
|
3274
|
+
gap: 6px;
|
|
3275
|
+
padding: 8px 18px;
|
|
3276
|
+
border: none;
|
|
3277
|
+
border-radius: 6px;
|
|
3278
|
+
cursor: pointer;
|
|
3279
|
+
font-size: 14px;
|
|
3280
|
+
font-weight: 500;
|
|
3281
|
+
transition: all 0.2s ease;
|
|
3282
|
+
margin-top: 8px;
|
|
3283
|
+
background-color: #dc3545;
|
|
3284
|
+
color: white;
|
|
3285
|
+
}
|
|
3286
|
+
|
|
3287
|
+
.sibu-error-fallback .sibu-error-btn:hover {
|
|
3288
|
+
background-color: #c82333;
|
|
3289
|
+
transform: translateY(-1px);
|
|
3290
|
+
box-shadow: 0 2px 8px rgba(220, 53, 69, 0.3);
|
|
3291
|
+
}
|
|
3292
|
+
|
|
3293
|
+
.sibu-error-fallback .sibu-error-btn:active {
|
|
3294
|
+
transform: translateY(0);
|
|
3295
|
+
}
|
|
3296
|
+
`;
|
|
3297
|
+
var stylesInjected = false;
|
|
3298
|
+
function injectStyles() {
|
|
3299
|
+
if (!stylesInjected && typeof document !== "undefined") {
|
|
3300
|
+
const styleElement = style({ nodes: errorBoundaryStyles });
|
|
3301
|
+
document.head.appendChild(styleElement);
|
|
3302
|
+
stylesInjected = true;
|
|
3303
|
+
}
|
|
3304
|
+
}
|
|
3305
|
+
var fallbackCache = /* @__PURE__ */ new WeakMap();
|
|
3306
|
+
function getMemoizedFallback(fallbackFn, error, retry) {
|
|
3307
|
+
let cache2 = fallbackCache.get(fallbackFn);
|
|
3308
|
+
if (!cache2) {
|
|
3309
|
+
cache2 = /* @__PURE__ */ new Map();
|
|
3310
|
+
fallbackCache.set(fallbackFn, cache2);
|
|
3311
|
+
}
|
|
3312
|
+
const key = error.message;
|
|
3313
|
+
if (!cache2.has(key)) {
|
|
3314
|
+
cache2.set(key, fallbackFn(error, retry));
|
|
3315
|
+
}
|
|
3316
|
+
return cache2.get(key);
|
|
3317
|
+
}
|
|
3318
|
+
function ErrorBoundary({ nodes, fallback, onError }) {
|
|
3319
|
+
injectStyles();
|
|
3320
|
+
const [error, setError] = signal(null);
|
|
3321
|
+
const retry = () => {
|
|
3322
|
+
if (fallback) {
|
|
3323
|
+
fallbackCache.delete(fallback);
|
|
3324
|
+
}
|
|
3325
|
+
setError(null);
|
|
3326
|
+
};
|
|
3327
|
+
const handleError = (e) => {
|
|
3328
|
+
const errorObj = e instanceof Error ? e : new Error(String(e));
|
|
3329
|
+
setError(errorObj);
|
|
3330
|
+
onError?.(errorObj);
|
|
3331
|
+
return errorObj;
|
|
3332
|
+
};
|
|
3333
|
+
const defaultFallback = (err, retryFn) => div({
|
|
3334
|
+
class: "sibu-error-fallback",
|
|
3335
|
+
nodes: [
|
|
3336
|
+
h3({
|
|
3337
|
+
nodes: "Something went wrong",
|
|
3338
|
+
class: "sibu-error-title"
|
|
3339
|
+
}),
|
|
3340
|
+
p({
|
|
3341
|
+
nodes: err.message,
|
|
3342
|
+
class: "sibu-error-message"
|
|
3343
|
+
}),
|
|
3344
|
+
button({
|
|
3345
|
+
nodes: "Retry",
|
|
3346
|
+
class: "sibu-error-btn",
|
|
3347
|
+
on: { click: retryFn }
|
|
3348
|
+
})
|
|
3349
|
+
]
|
|
3350
|
+
});
|
|
3351
|
+
const tryRenderFallback = (err) => {
|
|
3352
|
+
const fn = fallback || defaultFallback;
|
|
3353
|
+
try {
|
|
3354
|
+
return getMemoizedFallback(fn, err, retry);
|
|
3355
|
+
} catch (fallbackError) {
|
|
3356
|
+
const propagateError = fallbackError instanceof Error ? fallbackError : new Error(String(fallbackError));
|
|
3357
|
+
queueMicrotask(() => {
|
|
3358
|
+
if (container.parentNode) {
|
|
3359
|
+
container.dispatchEvent(
|
|
3360
|
+
new CustomEvent("sibu:error-propagate", {
|
|
3361
|
+
bubbles: true,
|
|
3362
|
+
detail: { error: propagateError }
|
|
3363
|
+
})
|
|
3364
|
+
);
|
|
3365
|
+
}
|
|
3366
|
+
});
|
|
3367
|
+
return document.createComment("error-boundary-failed");
|
|
3368
|
+
}
|
|
3369
|
+
};
|
|
3370
|
+
const container = div({
|
|
3371
|
+
class: "sibu-error-boundary",
|
|
3372
|
+
nodes: () => {
|
|
3373
|
+
const currentError = error();
|
|
3374
|
+
if (currentError) {
|
|
3375
|
+
return tryRenderFallback(currentError);
|
|
3376
|
+
}
|
|
3377
|
+
try {
|
|
3378
|
+
const result = nodes();
|
|
3379
|
+
if (result && typeof result.then === "function") {
|
|
3380
|
+
const asyncContainer = div({ class: "sibu-error-async" });
|
|
3381
|
+
asyncContainer.appendChild(span({ class: "sibu-lazy-loading", nodes: "Loading..." }));
|
|
3382
|
+
result.then((el) => {
|
|
3383
|
+
asyncContainer.replaceChildren(el);
|
|
3384
|
+
}).catch((e) => {
|
|
3385
|
+
const err = handleError(e);
|
|
3386
|
+
asyncContainer.replaceChildren(tryRenderFallback(err));
|
|
3387
|
+
});
|
|
3388
|
+
return asyncContainer;
|
|
3389
|
+
}
|
|
3390
|
+
return result;
|
|
3391
|
+
} catch (e) {
|
|
3392
|
+
const errorObj = handleError(e);
|
|
3393
|
+
return tryRenderFallback(errorObj);
|
|
3394
|
+
}
|
|
3395
|
+
}
|
|
3396
|
+
});
|
|
3397
|
+
container.addEventListener("sibu:error-propagate", (e) => {
|
|
3398
|
+
if (error()) return;
|
|
3399
|
+
e.stopPropagation();
|
|
3400
|
+
const customEvent = e;
|
|
3401
|
+
const propagatedError = customEvent.detail?.error;
|
|
3402
|
+
if (propagatedError) {
|
|
3403
|
+
handleError(propagatedError);
|
|
3404
|
+
}
|
|
3405
|
+
});
|
|
3406
|
+
return container;
|
|
3407
|
+
}
|
|
3408
|
+
|
|
3409
|
+
// src/components/Loading.ts
|
|
3410
|
+
var loadingStyles = `
|
|
3411
|
+
@keyframes sibu-spin {
|
|
3412
|
+
to { transform: rotate(360deg); }
|
|
3413
|
+
}
|
|
3414
|
+
|
|
3415
|
+
@keyframes sibu-pulse {
|
|
3416
|
+
0%, 100% { opacity: 1; }
|
|
3417
|
+
50% { opacity: 0.4; }
|
|
3418
|
+
}
|
|
3419
|
+
|
|
3420
|
+
.sibu-loading {
|
|
3421
|
+
display: flex;
|
|
3422
|
+
align-items: center;
|
|
3423
|
+
justify-content: center;
|
|
3424
|
+
padding: 20px;
|
|
3425
|
+
gap: 10px;
|
|
3426
|
+
}
|
|
3427
|
+
|
|
3428
|
+
.sibu-loading-spinner {
|
|
3429
|
+
width: 24px;
|
|
3430
|
+
height: 24px;
|
|
3431
|
+
border: 3px solid #e0e0e0;
|
|
3432
|
+
border-top-color: #3b82f6;
|
|
3433
|
+
border-radius: 50%;
|
|
3434
|
+
animation: sibu-spin 0.8s linear infinite;
|
|
3435
|
+
}
|
|
3436
|
+
|
|
3437
|
+
.sibu-loading-dots {
|
|
3438
|
+
display: flex;
|
|
3439
|
+
gap: 4px;
|
|
3440
|
+
}
|
|
3441
|
+
|
|
3442
|
+
.sibu-loading-dot {
|
|
3443
|
+
width: 8px;
|
|
3444
|
+
height: 8px;
|
|
3445
|
+
border-radius: 50%;
|
|
3446
|
+
background-color: #3b82f6;
|
|
3447
|
+
animation: sibu-pulse 1.2s ease-in-out infinite;
|
|
3448
|
+
}
|
|
3449
|
+
|
|
3450
|
+
.sibu-loading-dot:nth-child(2) { animation-delay: 0.2s; }
|
|
3451
|
+
.sibu-loading-dot:nth-child(3) { animation-delay: 0.4s; }
|
|
3452
|
+
|
|
3453
|
+
.sibu-loading-text {
|
|
3454
|
+
color: #6b7280;
|
|
3455
|
+
font-size: 14px;
|
|
3456
|
+
}
|
|
3457
|
+
|
|
3458
|
+
.sibu-loading-sm .sibu-loading-spinner { width: 16px; height: 16px; border-width: 2px; }
|
|
3459
|
+
.sibu-loading-sm .sibu-loading-dot { width: 6px; height: 6px; }
|
|
3460
|
+
.sibu-loading-lg .sibu-loading-spinner { width: 40px; height: 40px; border-width: 4px; }
|
|
3461
|
+
.sibu-loading-lg .sibu-loading-dot { width: 12px; height: 12px; }
|
|
3462
|
+
.sibu-loading-lg .sibu-loading-dots { gap: 6px; }
|
|
3463
|
+
`;
|
|
3464
|
+
var loadingStylesInjected = false;
|
|
3465
|
+
function injectLoadingStyles() {
|
|
3466
|
+
if (!loadingStylesInjected && typeof document !== "undefined") {
|
|
3467
|
+
document.head.appendChild(style({ nodes: loadingStyles }));
|
|
3468
|
+
loadingStylesInjected = true;
|
|
3469
|
+
}
|
|
3470
|
+
}
|
|
3471
|
+
function Loading(props = {}) {
|
|
3472
|
+
injectLoadingStyles();
|
|
3473
|
+
const { text: text2, variant = "spinner", size = "md" } = props;
|
|
3474
|
+
const sizeClass = size !== "md" ? ` sibu-loading-${size}` : "";
|
|
3475
|
+
if (variant === "dots") {
|
|
3476
|
+
return div({
|
|
3477
|
+
class: `sibu-loading${sizeClass}`,
|
|
3478
|
+
nodes: [
|
|
3479
|
+
div({
|
|
3480
|
+
class: "sibu-loading-dots",
|
|
3481
|
+
nodes: [
|
|
3482
|
+
span({ class: "sibu-loading-dot" }),
|
|
3483
|
+
span({ class: "sibu-loading-dot" }),
|
|
3484
|
+
span({ class: "sibu-loading-dot" })
|
|
3485
|
+
]
|
|
3486
|
+
}),
|
|
3487
|
+
text2 ? span({ class: "sibu-loading-text", nodes: text2 }) : null
|
|
3488
|
+
].filter(Boolean)
|
|
3489
|
+
});
|
|
3490
|
+
}
|
|
3491
|
+
return div({
|
|
3492
|
+
class: `sibu-loading${sizeClass}`,
|
|
3493
|
+
nodes: [
|
|
3494
|
+
div({ class: "sibu-loading-spinner" }),
|
|
3495
|
+
text2 ? span({ class: "sibu-loading-text", nodes: text2 }) : null
|
|
3496
|
+
].filter(Boolean)
|
|
3497
|
+
});
|
|
3498
|
+
}
|
|
3499
|
+
|
|
3500
|
+
// src/build/cdn.ts
|
|
3501
|
+
var PACKAGE_NAME = "sibu";
|
|
3502
|
+
function registerGlobal() {
|
|
3503
|
+
if (typeof window === "undefined") return;
|
|
3504
|
+
window.Sibu = { ...index_exports };
|
|
3505
|
+
}
|
|
3506
|
+
function umdWrapper(name, factory) {
|
|
3507
|
+
const factoryStr = factory.toString();
|
|
3508
|
+
return `(function (root, factory) {
|
|
3509
|
+
if (typeof define === 'function' && define.amd) {
|
|
3510
|
+
// AMD (RequireJS)
|
|
3511
|
+
define([], factory);
|
|
3512
|
+
} else if (typeof module === 'object' && module.exports) {
|
|
3513
|
+
// CommonJS (Node.js)
|
|
3514
|
+
module.exports = factory();
|
|
3515
|
+
} else {
|
|
3516
|
+
// Browser globals
|
|
3517
|
+
root.${name} = factory();
|
|
3518
|
+
}
|
|
3519
|
+
}(typeof self !== 'undefined' ? self : this, ${factoryStr}));`;
|
|
3520
|
+
}
|
|
3521
|
+
var cdnUrls = {
|
|
3522
|
+
/**
|
|
3523
|
+
* Generate an unpkg CDN URL.
|
|
3524
|
+
* @param version - Package version (defaults to 'latest')
|
|
3525
|
+
*/
|
|
3526
|
+
unpkg: (version) => `https://unpkg.com/${PACKAGE_NAME}@${version || "latest"}/dist/cdn.global.js`,
|
|
3527
|
+
/**
|
|
3528
|
+
* Generate a jsDelivr CDN URL.
|
|
3529
|
+
* @param version - Package version (defaults to 'latest')
|
|
3530
|
+
*/
|
|
3531
|
+
jsdelivr: (version) => `https://cdn.jsdelivr.net/npm/${PACKAGE_NAME}@${version || "latest"}/dist/cdn.global.js`,
|
|
3532
|
+
/**
|
|
3533
|
+
* Generate a Skypack CDN URL (ESM-native).
|
|
3534
|
+
* @param version - Package version (defaults to 'latest')
|
|
3535
|
+
*/
|
|
3536
|
+
skypack: (version) => `https://cdn.skypack.dev/${PACKAGE_NAME}@${version || "latest"}`,
|
|
3537
|
+
/**
|
|
3538
|
+
* Generate a complete HTML script tag for including SibuJS from a CDN.
|
|
3539
|
+
*
|
|
3540
|
+
* @param provider - CDN provider to use (defaults to 'jsdelivr')
|
|
3541
|
+
* @param version - Package version (defaults to 'latest')
|
|
3542
|
+
* @returns An HTML script tag string
|
|
3543
|
+
*
|
|
3544
|
+
* @example
|
|
3545
|
+
* ```ts
|
|
3546
|
+
* cdnUrls.scriptTag('jsdelivr', '1.0.0')
|
|
3547
|
+
* // => '<script src="https://cdn.jsdelivr.net/npm/sibu@1.0.0/dist/cdn.global.js"></script>'
|
|
3548
|
+
* ```
|
|
3549
|
+
*/
|
|
3550
|
+
scriptTag: (provider = "jsdelivr", version) => {
|
|
3551
|
+
const url = cdnUrls[provider](version);
|
|
3552
|
+
if (provider === "skypack") {
|
|
3553
|
+
return `<script type="module">
|
|
3554
|
+
import * as Sibu from '${url}';
|
|
3555
|
+
window.Sibu = Sibu;
|
|
3556
|
+
</script>`;
|
|
3557
|
+
}
|
|
3558
|
+
return `<script src="${url}"></script>`;
|
|
3559
|
+
}
|
|
3560
|
+
};
|
|
3561
|
+
function generateImportMap(baseUrl) {
|
|
3562
|
+
const base2 = baseUrl || `https://cdn.jsdelivr.net/npm/${PACKAGE_NAME}@latest`;
|
|
3563
|
+
const imports = {
|
|
3564
|
+
// Main package entry
|
|
3565
|
+
[PACKAGE_NAME]: `${base2}/dist/index.js`,
|
|
3566
|
+
// Sub-path imports for tree-shaking in browsers
|
|
3567
|
+
[`${PACKAGE_NAME}/core`]: `${base2}/dist/core/index.js`,
|
|
3568
|
+
[`${PACKAGE_NAME}/reactivity`]: `${base2}/dist/reactivity/index.js`,
|
|
3569
|
+
[`${PACKAGE_NAME}/plugins`]: `${base2}/dist/plugins/index.js`,
|
|
3570
|
+
[`${PACKAGE_NAME}/components`]: `${base2}/dist/components/index.js`,
|
|
3571
|
+
[`${PACKAGE_NAME}/testing`]: `${base2}/dist/testing/index.js`,
|
|
3572
|
+
[`${PACKAGE_NAME}/build`]: `${base2}/dist/build/index.js`
|
|
3573
|
+
};
|
|
3574
|
+
return {
|
|
3575
|
+
imports,
|
|
3576
|
+
/**
|
|
3577
|
+
* Serialize the import map to a JSON string.
|
|
3578
|
+
*/
|
|
3579
|
+
toJSON() {
|
|
3580
|
+
return JSON.stringify({ imports }, null, 2);
|
|
3581
|
+
},
|
|
3582
|
+
/**
|
|
3583
|
+
* Generate a complete `<script type="importmap">` tag.
|
|
3584
|
+
*/
|
|
3585
|
+
toScriptTag() {
|
|
3586
|
+
return `<script type="importmap">
|
|
3587
|
+
${JSON.stringify({ imports }, null, 2)}
|
|
3588
|
+
</script>`;
|
|
3589
|
+
}
|
|
3590
|
+
};
|
|
3591
|
+
}
|
|
3592
|
+
|
|
3593
|
+
// src/build/declarations.ts
|
|
3594
|
+
var RECOMMENDED_OPTIONS = {
|
|
3595
|
+
target: "ES2020",
|
|
3596
|
+
module: "ESNext",
|
|
3597
|
+
moduleResolution: "bundler",
|
|
3598
|
+
strict: true,
|
|
3599
|
+
esModuleInterop: true,
|
|
3600
|
+
skipLibCheck: true,
|
|
3601
|
+
declaration: true,
|
|
3602
|
+
declarationMap: true,
|
|
3603
|
+
sourceMap: true,
|
|
3604
|
+
jsx: "preserve",
|
|
3605
|
+
lib: ["ES2020", "DOM", "DOM.Iterable"],
|
|
3606
|
+
isolatedModules: true,
|
|
3607
|
+
resolveJsonModule: true,
|
|
3608
|
+
allowSyntheticDefaultImports: true,
|
|
3609
|
+
forceConsistentCasingInFileNames: true,
|
|
3610
|
+
noUncheckedIndexedAccess: true,
|
|
3611
|
+
noEmit: false
|
|
3612
|
+
};
|
|
3613
|
+
var REQUIRED_OPTIONS = {
|
|
3614
|
+
strict: {
|
|
3615
|
+
value: true,
|
|
3616
|
+
reason: "SibuJS relies on strict type checking for safe reactive state handling."
|
|
3617
|
+
},
|
|
3618
|
+
esModuleInterop: {
|
|
3619
|
+
value: true,
|
|
3620
|
+
reason: "Required for correct ESM interop with SibuJS module exports."
|
|
3621
|
+
},
|
|
3622
|
+
moduleResolution: {
|
|
3623
|
+
value: ["node", "bundler", "node16", "nodenext"],
|
|
3624
|
+
reason: "SibuJS requires a module resolution strategy that supports package.json exports."
|
|
3625
|
+
}
|
|
3626
|
+
};
|
|
3627
|
+
var SUGGESTED_OPTIONS = {
|
|
3628
|
+
declarationMap: {
|
|
3629
|
+
value: true,
|
|
3630
|
+
reason: 'Enables "Go to Definition" to navigate to SibuJS source files in your IDE.'
|
|
3631
|
+
},
|
|
3632
|
+
sourceMap: {
|
|
3633
|
+
value: true,
|
|
3634
|
+
reason: "Enables source map debugging for SibuJS components."
|
|
3635
|
+
},
|
|
3636
|
+
noUncheckedIndexedAccess: {
|
|
3637
|
+
value: true,
|
|
3638
|
+
reason: "Improves type safety when accessing reactive state objects."
|
|
3639
|
+
},
|
|
3640
|
+
isolatedModules: {
|
|
3641
|
+
value: true,
|
|
3642
|
+
reason: "Required for compatibility with esbuild/swc transpilers used by Vite."
|
|
3643
|
+
}
|
|
3644
|
+
};
|
|
3645
|
+
function generateTsConfig(options) {
|
|
3646
|
+
const { target = "ES2020", outDir = "dist", declarationMap = true, paths } = options || {};
|
|
3647
|
+
const compilerOptions = {
|
|
3648
|
+
...RECOMMENDED_OPTIONS,
|
|
3649
|
+
target,
|
|
3650
|
+
outDir,
|
|
3651
|
+
declarationMap
|
|
3652
|
+
};
|
|
3653
|
+
if (paths && Object.keys(paths).length > 0) {
|
|
3654
|
+
compilerOptions.baseUrl = ".";
|
|
3655
|
+
compilerOptions.paths = {
|
|
3656
|
+
// Default sibu alias
|
|
3657
|
+
sibu: ["node_modules/sibu/dist/index.d.ts"],
|
|
3658
|
+
"sibu/*": ["node_modules/sibu/dist/*"],
|
|
3659
|
+
// User-provided paths
|
|
3660
|
+
...paths
|
|
3661
|
+
};
|
|
3662
|
+
}
|
|
3663
|
+
return {
|
|
3664
|
+
compilerOptions,
|
|
3665
|
+
include: ["src/**/*.ts", "src/**/*.tsx"],
|
|
3666
|
+
exclude: ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"]
|
|
3667
|
+
};
|
|
3668
|
+
}
|
|
3669
|
+
function validateTsConfig(config) {
|
|
3670
|
+
const warnings = [];
|
|
3671
|
+
const suggestions = [];
|
|
3672
|
+
const compilerOptions = config.compilerOptions || {};
|
|
3673
|
+
for (const [option2, requirement] of Object.entries(REQUIRED_OPTIONS)) {
|
|
3674
|
+
const currentValue = compilerOptions[option2];
|
|
3675
|
+
if (Array.isArray(requirement.value)) {
|
|
3676
|
+
if (currentValue === void 0) {
|
|
3677
|
+
warnings.push(
|
|
3678
|
+
`Missing required option "${option2}". ${requirement.reason} Recommended value: one of ${requirement.value.map((v) => `"${v}"`).join(", ")}.`
|
|
3679
|
+
);
|
|
3680
|
+
} else if (!requirement.value.includes(currentValue)) {
|
|
3681
|
+
warnings.push(
|
|
3682
|
+
`Option "${option2}" is set to "${currentValue}" which may not be compatible with SibuJS. ${requirement.reason} Recommended: one of ${requirement.value.map((v) => `"${v}"`).join(", ")}.`
|
|
3683
|
+
);
|
|
3684
|
+
}
|
|
3685
|
+
} else {
|
|
3686
|
+
if (currentValue === void 0) {
|
|
3687
|
+
warnings.push(
|
|
3688
|
+
`Missing required option "${option2}". ${requirement.reason} Recommended value: ${JSON.stringify(requirement.value)}.`
|
|
3689
|
+
);
|
|
3690
|
+
} else if (currentValue !== requirement.value) {
|
|
3691
|
+
warnings.push(
|
|
3692
|
+
`Option "${option2}" is set to ${JSON.stringify(currentValue)} but SibuJS recommends ${JSON.stringify(requirement.value)}. ${requirement.reason}`
|
|
3693
|
+
);
|
|
3694
|
+
}
|
|
3695
|
+
}
|
|
3696
|
+
}
|
|
3697
|
+
for (const [option2, suggestion] of Object.entries(SUGGESTED_OPTIONS)) {
|
|
3698
|
+
const currentValue = compilerOptions[option2];
|
|
3699
|
+
if (currentValue === void 0 || currentValue !== suggestion.value) {
|
|
3700
|
+
suggestions.push(`Consider setting "${option2}" to ${JSON.stringify(suggestion.value)}. ${suggestion.reason}`);
|
|
3701
|
+
}
|
|
3702
|
+
}
|
|
3703
|
+
const target = typeof compilerOptions.target === "string" ? compilerOptions.target.toUpperCase() : void 0;
|
|
3704
|
+
if (target) {
|
|
3705
|
+
const es2020Plus = ["ES2020", "ES2021", "ES2022", "ES2023", "ES2024", "ESNEXT"];
|
|
3706
|
+
if (!es2020Plus.includes(target)) {
|
|
3707
|
+
warnings.push(
|
|
3708
|
+
`Target "${target}" may not support all features used by SibuJS. Recommended: "ES2020" or newer. SibuJS uses optional chaining, nullish coalescing, and other ES2020+ features.`
|
|
3709
|
+
);
|
|
3710
|
+
}
|
|
3711
|
+
}
|
|
3712
|
+
const module2 = typeof compilerOptions.module === "string" ? compilerOptions.module.toLowerCase() : void 0;
|
|
3713
|
+
if (module2 && !["esnext", "es2020", "es2022", "node16", "nodenext"].includes(module2)) {
|
|
3714
|
+
suggestions.push(
|
|
3715
|
+
`Module "${compilerOptions.module}" may not provide optimal results with SibuJS. Consider using "ESNext" for best tree-shaking and bundle optimization.`
|
|
3716
|
+
);
|
|
3717
|
+
}
|
|
3718
|
+
const lib = compilerOptions.lib;
|
|
3719
|
+
if (Array.isArray(lib)) {
|
|
3720
|
+
const hasDom = lib.some((l) => l.toUpperCase() === "DOM" || l.toUpperCase() === "DOM.ITERABLE");
|
|
3721
|
+
if (!hasDom) {
|
|
3722
|
+
suggestions.push(
|
|
3723
|
+
'The "lib" array does not include "DOM". SibuJS requires DOM types for component rendering. Add "DOM" and "DOM.Iterable" to your lib array.'
|
|
3724
|
+
);
|
|
3725
|
+
}
|
|
3726
|
+
}
|
|
3727
|
+
if (Array.isArray(config.include)) {
|
|
3728
|
+
const includesTs = config.include.some(
|
|
3729
|
+
(pattern2) => pattern2.includes(".ts") || pattern2.includes("*")
|
|
3730
|
+
);
|
|
3731
|
+
if (!includesTs) {
|
|
3732
|
+
suggestions.push(
|
|
3733
|
+
'Your "include" patterns may not capture TypeScript files. Ensure patterns like "src/**/*.ts" are included.'
|
|
3734
|
+
);
|
|
3735
|
+
}
|
|
3736
|
+
}
|
|
3737
|
+
return {
|
|
3738
|
+
valid: warnings.length === 0,
|
|
3739
|
+
warnings,
|
|
3740
|
+
suggestions
|
|
3741
|
+
};
|
|
3742
|
+
}
|
|
3743
|
+
|
|
3744
|
+
// src/build/analyzer.ts
|
|
3745
|
+
var moduleSizes = {
|
|
3746
|
+
// Core modules
|
|
3747
|
+
"core/html": 1800,
|
|
3748
|
+
"core/mount": 120,
|
|
3749
|
+
"core/each": 450,
|
|
3750
|
+
"core/slots": 200,
|
|
3751
|
+
"core/fragment": 180,
|
|
3752
|
+
"core/catch": 280,
|
|
3753
|
+
"core/portal": 350,
|
|
3754
|
+
"core/directives": 520,
|
|
3755
|
+
"core/dynamic": 380,
|
|
3756
|
+
"core/head": 300,
|
|
3757
|
+
"core/ssr": 1200,
|
|
3758
|
+
"core/customElement": 650,
|
|
3759
|
+
"core/scopedStyle": 480,
|
|
3760
|
+
"core/domRecycler": 420,
|
|
3761
|
+
"core/bundleOptimize": 200,
|
|
3762
|
+
"core/compiled": 350,
|
|
3763
|
+
"core/normalize": 280,
|
|
3764
|
+
"core/reactiveAttr": 320,
|
|
3765
|
+
"core/componentProps": 400,
|
|
3766
|
+
"core/contracts": 350,
|
|
3767
|
+
"core/worker": 550,
|
|
3768
|
+
"core/wasm": 480,
|
|
3769
|
+
"core/concurrent": 600,
|
|
3770
|
+
"core/microfrontend": 700,
|
|
3771
|
+
"core/chunkLoader": 450,
|
|
3772
|
+
"core/versioning": 300,
|
|
3773
|
+
"core/ecosystem": 250,
|
|
3774
|
+
// Signals
|
|
3775
|
+
"core/signal": 280,
|
|
3776
|
+
"core/effect": 350,
|
|
3777
|
+
"core/derived": 250,
|
|
3778
|
+
"core/watch": 300,
|
|
3779
|
+
"core/store": 380,
|
|
3780
|
+
"core/ref": 150,
|
|
3781
|
+
"core/memo": 180,
|
|
3782
|
+
"core/memoFn": 160,
|
|
3783
|
+
"core/array": 420,
|
|
3784
|
+
"core/deepSignal": 500,
|
|
3785
|
+
"core/lifecycle": 300,
|
|
3786
|
+
"core/context": 350,
|
|
3787
|
+
"core/persist": 400,
|
|
3788
|
+
"core/primitives": 200,
|
|
3789
|
+
"core/hoc": 280,
|
|
3790
|
+
"core/transition": 600,
|
|
3791
|
+
"core/form": 750,
|
|
3792
|
+
"core/globalStore": 450,
|
|
3793
|
+
"core/machine": 550,
|
|
3794
|
+
"core/optimistic": 380,
|
|
3795
|
+
"core/timeTravel": 500,
|
|
3796
|
+
"core/scheduler": 350,
|
|
3797
|
+
"core/plugin": 300,
|
|
3798
|
+
"core/virtualList": 800,
|
|
3799
|
+
"core/intersection": 350,
|
|
3800
|
+
"core/inputMask": 450,
|
|
3801
|
+
"core/a11y": 500,
|
|
3802
|
+
"core/debug": 400,
|
|
3803
|
+
"core/serviceWorker": 350,
|
|
3804
|
+
"core/composable": 280,
|
|
3805
|
+
// Reactivity
|
|
3806
|
+
"reactivity/signal": 100,
|
|
3807
|
+
"reactivity/track": 250,
|
|
3808
|
+
"reactivity/batch": 200,
|
|
3809
|
+
"reactivity/bindAttribute": 300,
|
|
3810
|
+
"reactivity/bindChildNode": 250,
|
|
3811
|
+
"reactivity/bindTextNode": 200,
|
|
3812
|
+
// Components
|
|
3813
|
+
"components/ErrorBoundary": 350,
|
|
3814
|
+
"components/Loading": 250,
|
|
3815
|
+
// Plugins
|
|
3816
|
+
"plugins/i18n": 600,
|
|
3817
|
+
"plugins/router": 900,
|
|
3818
|
+
"plugins/routerSSR": 500,
|
|
3819
|
+
// Build utilities
|
|
3820
|
+
"build/vite": 800,
|
|
3821
|
+
"build/webpack": 750,
|
|
3822
|
+
"build/cdn": 400,
|
|
3823
|
+
"build/declarations": 500,
|
|
3824
|
+
"build/analyzer": 600,
|
|
3825
|
+
// Testing
|
|
3826
|
+
"testing/index": 700,
|
|
3827
|
+
"testing/e2e": 500
|
|
3828
|
+
};
|
|
3829
|
+
function formatBytes(bytes) {
|
|
3830
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
3831
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(2)} KB`;
|
|
3832
|
+
return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
|
|
3833
|
+
}
|
|
3834
|
+
function analyzeBundle(modules) {
|
|
3835
|
+
const sizes = {};
|
|
3836
|
+
let totalSize = 0;
|
|
3837
|
+
for (const [name, source2] of Object.entries(modules)) {
|
|
3838
|
+
let byteLength;
|
|
3839
|
+
if (typeof TextEncoder !== "undefined") {
|
|
3840
|
+
byteLength = new TextEncoder().encode(source2).length;
|
|
3841
|
+
} else {
|
|
3842
|
+
byteLength = source2.length;
|
|
3843
|
+
}
|
|
3844
|
+
sizes[name] = byteLength;
|
|
3845
|
+
totalSize += byteLength;
|
|
3846
|
+
}
|
|
3847
|
+
const sorted = Object.entries(sizes).map(([name, size]) => ({
|
|
3848
|
+
name,
|
|
3849
|
+
size,
|
|
3850
|
+
percentage: totalSize > 0 ? size / totalSize * 100 : 0
|
|
3851
|
+
})).sort((a2, b2) => b2.size - a2.size);
|
|
3852
|
+
return {
|
|
3853
|
+
totalSize,
|
|
3854
|
+
moduleSizes: sizes,
|
|
3855
|
+
sorted,
|
|
3856
|
+
report() {
|
|
3857
|
+
const lines = [
|
|
3858
|
+
"=== SibuJS Bundle Analysis ===",
|
|
3859
|
+
"",
|
|
3860
|
+
`Total size: ${formatBytes(totalSize)}`,
|
|
3861
|
+
`Modules: ${sorted.length}`,
|
|
3862
|
+
"",
|
|
3863
|
+
"Module breakdown:",
|
|
3864
|
+
"-".repeat(60)
|
|
3865
|
+
];
|
|
3866
|
+
for (const entry of sorted) {
|
|
3867
|
+
const sizeStr = formatBytes(entry.size).padStart(10);
|
|
3868
|
+
const pctStr = `${entry.percentage.toFixed(1)}%`.padStart(6);
|
|
3869
|
+
const bar = generateBar(entry.percentage, 20);
|
|
3870
|
+
lines.push(` ${sizeStr} ${pctStr} ${bar} ${entry.name}`);
|
|
3871
|
+
}
|
|
3872
|
+
lines.push("-".repeat(60));
|
|
3873
|
+
return lines.join("\n");
|
|
3874
|
+
}
|
|
3875
|
+
};
|
|
3876
|
+
}
|
|
3877
|
+
function generateBar(percentage, width) {
|
|
3878
|
+
const filled = Math.round(percentage / 100 * width);
|
|
3879
|
+
const empty = width - filled;
|
|
3880
|
+
return `[${"#".repeat(filled)}${".".repeat(empty)}]`;
|
|
3881
|
+
}
|
|
3882
|
+
function estimateImportSize(imports) {
|
|
3883
|
+
const breakdown = {};
|
|
3884
|
+
let estimated = 0;
|
|
3885
|
+
const implicitDeps = ["reactivity/signal", "reactivity/track"];
|
|
3886
|
+
const allImports = [.../* @__PURE__ */ new Set([...implicitDeps, ...imports])];
|
|
3887
|
+
for (const importPath of allImports) {
|
|
3888
|
+
const size = moduleSizes[importPath];
|
|
3889
|
+
if (size !== void 0) {
|
|
3890
|
+
breakdown[importPath] = size;
|
|
3891
|
+
estimated += size;
|
|
3892
|
+
} else {
|
|
3893
|
+
const avgSize = 350;
|
|
3894
|
+
breakdown[importPath] = avgSize;
|
|
3895
|
+
estimated += avgSize;
|
|
3896
|
+
}
|
|
3897
|
+
}
|
|
3898
|
+
const sortedEntries = Object.entries(breakdown).sort(([, a2], [, b2]) => b2 - a2);
|
|
3899
|
+
const lines = [`Estimated bundle size: ${formatBytes(estimated)} (minified + gzipped)`, ""];
|
|
3900
|
+
for (const [modulePath, size] of sortedEntries) {
|
|
3901
|
+
const known = moduleSizes[modulePath] !== void 0;
|
|
3902
|
+
lines.push(` ${modulePath}: ${formatBytes(size)}${known ? "" : " (estimated)"}`);
|
|
3903
|
+
}
|
|
3904
|
+
if (imports.length > 0) {
|
|
3905
|
+
lines.push("");
|
|
3906
|
+
lines.push("Note: Actual sizes may vary based on tree-shaking and build configuration.");
|
|
3907
|
+
lines.push("Implicit dependencies (reactivity/signal, reactivity/track) are included.");
|
|
3908
|
+
}
|
|
3909
|
+
return {
|
|
3910
|
+
estimated,
|
|
3911
|
+
breakdown,
|
|
3912
|
+
formatted: lines.join("\n")
|
|
3913
|
+
};
|
|
3914
|
+
}
|
|
3915
|
+
|
|
3916
|
+
// src/build/linting.ts
|
|
3917
|
+
function getLineNumber(source2, index) {
|
|
3918
|
+
let line2 = 1;
|
|
3919
|
+
for (let i2 = 0; i2 < index && i2 < source2.length; i2++) {
|
|
3920
|
+
if (source2[i2] === "\n") line2++;
|
|
3921
|
+
}
|
|
3922
|
+
return line2;
|
|
3923
|
+
}
|
|
3924
|
+
function getColumnNumber(source2, index) {
|
|
3925
|
+
let col2 = 1;
|
|
3926
|
+
for (let i2 = index - 1; i2 >= 0; i2--) {
|
|
3927
|
+
if (source2[i2] === "\n") break;
|
|
3928
|
+
col2++;
|
|
3929
|
+
}
|
|
3930
|
+
return col2;
|
|
3931
|
+
}
|
|
3932
|
+
var lintRules = {
|
|
3933
|
+
/** Detect signal inside loops or conditionals */
|
|
3934
|
+
"no-signals-in-conditionals": {
|
|
3935
|
+
name: "no-signals-in-conditionals",
|
|
3936
|
+
description: "Signal functions should not be called inside conditionals, loops, or nested functions",
|
|
3937
|
+
check(source2) {
|
|
3938
|
+
const violations = [];
|
|
3939
|
+
const hookNames = ["signal", "effect", "derived", "memo", "memoFn", "ref", "watch", "store"];
|
|
3940
|
+
const hookPattern = new RegExp(`\\b(${hookNames.join("|")})\\s*\\(`, "g");
|
|
3941
|
+
const lines = source2.split("\n");
|
|
3942
|
+
for (let lineIdx = 0; lineIdx < lines.length; lineIdx++) {
|
|
3943
|
+
const line2 = lines[lineIdx];
|
|
3944
|
+
const trimmed = line2.trim();
|
|
3945
|
+
if (trimmed.startsWith("import ")) continue;
|
|
3946
|
+
hookPattern.lastIndex = 0;
|
|
3947
|
+
const hookMatch = hookPattern.exec(line2);
|
|
3948
|
+
if (!hookMatch) continue;
|
|
3949
|
+
const hookName = hookMatch[1];
|
|
3950
|
+
let braceDepth = 0;
|
|
3951
|
+
let insideConditionalOrLoop = false;
|
|
3952
|
+
let insideNestedFunction = false;
|
|
3953
|
+
let functionDepth = 0;
|
|
3954
|
+
for (let i2 = 0; i2 <= lineIdx; i2++) {
|
|
3955
|
+
const scanLine = lines[i2].trim();
|
|
3956
|
+
if (/\b(function\s+\w+|function\s*\(|=>\s*\{)/.test(scanLine) && i2 < lineIdx) {
|
|
3957
|
+
functionDepth++;
|
|
3958
|
+
}
|
|
3959
|
+
if (i2 < lineIdx && /^\s*(if|else\s+if|else|for|while|do|switch)\s*[({]/.test(lines[i2])) {
|
|
3960
|
+
insideConditionalOrLoop = true;
|
|
3961
|
+
}
|
|
3962
|
+
for (const ch of lines[i2]) {
|
|
3963
|
+
if (ch === "{") braceDepth++;
|
|
3964
|
+
if (ch === "}") {
|
|
3965
|
+
braceDepth--;
|
|
3966
|
+
if (braceDepth <= 1) {
|
|
3967
|
+
insideConditionalOrLoop = false;
|
|
3968
|
+
}
|
|
3969
|
+
}
|
|
3970
|
+
}
|
|
3971
|
+
}
|
|
3972
|
+
const beforeHook = line2.substring(0, line2.indexOf(hookMatch[0]));
|
|
3973
|
+
const inlineConditional = /\b(if|else|for|while|switch)\s*\(/.test(beforeHook) || /\?\s*$/.test(beforeHook.trim());
|
|
3974
|
+
if (insideConditionalOrLoop || inlineConditional) {
|
|
3975
|
+
violations.push({
|
|
3976
|
+
rule: "no-signals-in-conditionals",
|
|
3977
|
+
message: `"${hookName}" should not be called inside a conditional or loop. Signal functions must be called at the top level of a component.`,
|
|
3978
|
+
severity: "error",
|
|
3979
|
+
line: lineIdx + 1,
|
|
3980
|
+
column: (hookMatch.index || 0) + 1
|
|
3981
|
+
});
|
|
3982
|
+
}
|
|
3983
|
+
if (functionDepth > 1) {
|
|
3984
|
+
insideNestedFunction = true;
|
|
3985
|
+
}
|
|
3986
|
+
if (insideNestedFunction) {
|
|
3987
|
+
violations.push({
|
|
3988
|
+
rule: "no-signals-in-conditionals",
|
|
3989
|
+
message: `"${hookName}" should not be called inside a nested function. Signal functions must be called at the top level of a component.`,
|
|
3990
|
+
severity: "error",
|
|
3991
|
+
line: lineIdx + 1,
|
|
3992
|
+
column: (hookMatch.index || 0) + 1
|
|
3993
|
+
});
|
|
3994
|
+
}
|
|
3995
|
+
}
|
|
3996
|
+
return violations;
|
|
3997
|
+
}
|
|
3998
|
+
},
|
|
3999
|
+
/** Detect missing cleanup in effect */
|
|
4000
|
+
"effect-cleanup": {
|
|
4001
|
+
name: "effect-cleanup",
|
|
4002
|
+
description: "effect with subscriptions or timers should return a cleanup function",
|
|
4003
|
+
check(source2) {
|
|
4004
|
+
const violations = [];
|
|
4005
|
+
const subscriptionPatterns = [
|
|
4006
|
+
"addEventListener",
|
|
4007
|
+
"setTimeout",
|
|
4008
|
+
"setInterval",
|
|
4009
|
+
"requestAnimationFrame",
|
|
4010
|
+
"subscribe",
|
|
4011
|
+
"observe",
|
|
4012
|
+
"WebSocket",
|
|
4013
|
+
"EventSource"
|
|
4014
|
+
];
|
|
4015
|
+
const effectRegex = /\beffect\s*\(\s*((?:function\s*\(?\)?\s*\{|\(\s*\)\s*=>\s*\{|(?=\(\))))/g;
|
|
4016
|
+
let match2;
|
|
4017
|
+
while ((match2 = effectRegex.exec(source2)) !== null) {
|
|
4018
|
+
const startIndex = match2.index;
|
|
4019
|
+
const line2 = getLineNumber(source2, startIndex);
|
|
4020
|
+
const column = getColumnNumber(source2, startIndex);
|
|
4021
|
+
const bodyStart = source2.indexOf("{", match2.index + match2[0].length - 1);
|
|
4022
|
+
if (bodyStart === -1) continue;
|
|
4023
|
+
let depth = 0;
|
|
4024
|
+
let bodyEnd = bodyStart;
|
|
4025
|
+
for (let i2 = bodyStart; i2 < source2.length; i2++) {
|
|
4026
|
+
if (source2[i2] === "{") depth++;
|
|
4027
|
+
if (source2[i2] === "}") {
|
|
4028
|
+
depth--;
|
|
4029
|
+
if (depth === 0) {
|
|
4030
|
+
bodyEnd = i2;
|
|
4031
|
+
break;
|
|
4032
|
+
}
|
|
4033
|
+
}
|
|
4034
|
+
}
|
|
4035
|
+
const effectBody = source2.substring(bodyStart, bodyEnd + 1);
|
|
4036
|
+
const hasSubscription = subscriptionPatterns.some((p2) => effectBody.includes(p2));
|
|
4037
|
+
if (hasSubscription) {
|
|
4038
|
+
const hasRemoveListener = effectBody.includes("removeEventListener");
|
|
4039
|
+
const hasClearTimeout = effectBody.includes("clearTimeout");
|
|
4040
|
+
const hasClearInterval = effectBody.includes("clearInterval");
|
|
4041
|
+
const hasCancelRAF = effectBody.includes("cancelAnimationFrame");
|
|
4042
|
+
const hasUnsubscribe = effectBody.includes("unsubscribe") || effectBody.includes("disconnect") || effectBody.includes(".close(");
|
|
4043
|
+
const hasReturnCleanup = /return\s+/.test(effectBody);
|
|
4044
|
+
const hasCleanup = hasRemoveListener || hasClearTimeout || hasClearInterval || hasCancelRAF || hasUnsubscribe || hasReturnCleanup;
|
|
4045
|
+
if (!hasCleanup) {
|
|
4046
|
+
const foundSubscriptions = [];
|
|
4047
|
+
for (const pattern2 of subscriptionPatterns) {
|
|
4048
|
+
if (effectBody.includes(pattern2)) {
|
|
4049
|
+
foundSubscriptions.push(pattern2);
|
|
4050
|
+
}
|
|
4051
|
+
}
|
|
4052
|
+
violations.push({
|
|
4053
|
+
rule: "effect-cleanup",
|
|
4054
|
+
message: `effect uses ${foundSubscriptions.join(", ")} but does not appear to clean up. Consider returning a cleanup function.`,
|
|
4055
|
+
severity: "warning",
|
|
4056
|
+
line: line2,
|
|
4057
|
+
column
|
|
4058
|
+
});
|
|
4059
|
+
}
|
|
4060
|
+
}
|
|
4061
|
+
}
|
|
4062
|
+
return violations;
|
|
4063
|
+
}
|
|
4064
|
+
},
|
|
4065
|
+
/** Detect direct DOM mutation outside of reactive context */
|
|
4066
|
+
"no-direct-dom-mutation": {
|
|
4067
|
+
name: "no-direct-dom-mutation",
|
|
4068
|
+
description: "Avoid direct DOM mutations; use reactive bindings instead",
|
|
4069
|
+
check(source2) {
|
|
4070
|
+
const violations = [];
|
|
4071
|
+
const mutationPatterns = [
|
|
4072
|
+
{
|
|
4073
|
+
pattern: /\.innerHTML\s*=/g,
|
|
4074
|
+
name: "innerHTML assignment",
|
|
4075
|
+
suggestion: "Use reactive nodes or bindChildNode instead"
|
|
4076
|
+
},
|
|
4077
|
+
{
|
|
4078
|
+
pattern: /\.outerHTML\s*=/g,
|
|
4079
|
+
name: "outerHTML assignment",
|
|
4080
|
+
suggestion: "Use reactive component rendering instead"
|
|
4081
|
+
},
|
|
4082
|
+
{
|
|
4083
|
+
pattern: /document\.write\s*\(/g,
|
|
4084
|
+
name: "document.write()",
|
|
4085
|
+
suggestion: "Use mount() or component rendering instead"
|
|
4086
|
+
},
|
|
4087
|
+
{
|
|
4088
|
+
pattern: /\.insertAdjacentHTML\s*\(/g,
|
|
4089
|
+
name: "insertAdjacentHTML()",
|
|
4090
|
+
suggestion: "Use reactive nodes or each() instead"
|
|
4091
|
+
}
|
|
4092
|
+
];
|
|
4093
|
+
const lines = source2.split("\n");
|
|
4094
|
+
for (let lineIdx = 0; lineIdx < lines.length; lineIdx++) {
|
|
4095
|
+
const line2 = lines[lineIdx];
|
|
4096
|
+
const trimmed = line2.trim();
|
|
4097
|
+
if (trimmed.startsWith("//") || trimmed.startsWith("*")) continue;
|
|
4098
|
+
for (const { pattern: pattern2, name, suggestion } of mutationPatterns) {
|
|
4099
|
+
pattern2.lastIndex = 0;
|
|
4100
|
+
const match2 = pattern2.exec(line2);
|
|
4101
|
+
if (match2) {
|
|
4102
|
+
violations.push({
|
|
4103
|
+
rule: "no-direct-dom-mutation",
|
|
4104
|
+
message: `Direct DOM mutation via ${name} detected. ${suggestion}.`,
|
|
4105
|
+
severity: "warning",
|
|
4106
|
+
line: lineIdx + 1,
|
|
4107
|
+
column: (match2.index || 0) + 1
|
|
4108
|
+
});
|
|
4109
|
+
}
|
|
4110
|
+
}
|
|
4111
|
+
}
|
|
4112
|
+
return violations;
|
|
4113
|
+
}
|
|
4114
|
+
},
|
|
4115
|
+
/** Detect missing key prop in each() calls */
|
|
4116
|
+
"each-requires-key": {
|
|
4117
|
+
name: "each-requires-key",
|
|
4118
|
+
description: "each() should include a key function for efficient reconciliation",
|
|
4119
|
+
check(source2) {
|
|
4120
|
+
const violations = [];
|
|
4121
|
+
const eachCallRegex = /\beach\s*\(/g;
|
|
4122
|
+
let match2;
|
|
4123
|
+
while ((match2 = eachCallRegex.exec(source2)) !== null) {
|
|
4124
|
+
const startIndex = match2.index;
|
|
4125
|
+
const line2 = getLineNumber(source2, startIndex);
|
|
4126
|
+
const column = getColumnNumber(source2, startIndex);
|
|
4127
|
+
const parenStart = source2.indexOf("(", startIndex);
|
|
4128
|
+
if (parenStart === -1) continue;
|
|
4129
|
+
let depth = 0;
|
|
4130
|
+
let parenEnd = parenStart;
|
|
4131
|
+
for (let i2 = parenStart; i2 < source2.length; i2++) {
|
|
4132
|
+
if (source2[i2] === "(") depth++;
|
|
4133
|
+
if (source2[i2] === ")") {
|
|
4134
|
+
depth--;
|
|
4135
|
+
if (depth === 0) {
|
|
4136
|
+
parenEnd = i2;
|
|
4137
|
+
break;
|
|
4138
|
+
}
|
|
4139
|
+
}
|
|
4140
|
+
}
|
|
4141
|
+
const callBody = source2.substring(parenStart, parenEnd + 1);
|
|
4142
|
+
const hasKey = /\bkey\s*:/.test(callBody);
|
|
4143
|
+
if (!hasKey) {
|
|
4144
|
+
violations.push({
|
|
4145
|
+
rule: "each-requires-key",
|
|
4146
|
+
message: "each() should include a key function in the options argument (e.g., { key: item => item.id }) for efficient list reconciliation.",
|
|
4147
|
+
severity: "warning",
|
|
4148
|
+
line: line2,
|
|
4149
|
+
column
|
|
4150
|
+
});
|
|
4151
|
+
}
|
|
4152
|
+
}
|
|
4153
|
+
return violations;
|
|
4154
|
+
}
|
|
4155
|
+
},
|
|
4156
|
+
/** Detect unused reactive state */
|
|
4157
|
+
"no-unused-state": {
|
|
4158
|
+
name: "no-unused-state",
|
|
4159
|
+
description: "signal variables should be used in the component",
|
|
4160
|
+
check(source2) {
|
|
4161
|
+
const violations = [];
|
|
4162
|
+
const signalDeclRegex = /\bconst\s+\[\s*(\w+)\s*,\s*(\w+)\s*\]\s*=\s*signal\s*\(/g;
|
|
4163
|
+
let match2;
|
|
4164
|
+
while ((match2 = signalDeclRegex.exec(source2)) !== null) {
|
|
4165
|
+
const getterName = match2[1];
|
|
4166
|
+
const setterName = match2[2];
|
|
4167
|
+
const line2 = getLineNumber(source2, match2.index);
|
|
4168
|
+
const column = getColumnNumber(source2, match2.index);
|
|
4169
|
+
const declarationLine = source2.substring(match2.index, source2.indexOf("\n", match2.index));
|
|
4170
|
+
const restOfSource = source2.replace(declarationLine, "");
|
|
4171
|
+
const getterUsageRegex = new RegExp(`\\b${escapeRegex(getterName)}\\b`, "g");
|
|
4172
|
+
const getterUsages = restOfSource.match(getterUsageRegex);
|
|
4173
|
+
const getterUsed = getterUsages !== null && getterUsages.length > 0;
|
|
4174
|
+
const setterUsageRegex = new RegExp(`\\b${escapeRegex(setterName)}\\b`, "g");
|
|
4175
|
+
const setterUsages = restOfSource.match(setterUsageRegex);
|
|
4176
|
+
const setterUsed = setterUsages !== null && setterUsages.length > 0;
|
|
4177
|
+
if (!getterUsed && !setterUsed) {
|
|
4178
|
+
violations.push({
|
|
4179
|
+
rule: "no-unused-state",
|
|
4180
|
+
message: `signal variable "${getterName}" and setter "${setterName}" are declared but never used. Remove unused state or use the values.`,
|
|
4181
|
+
severity: "warning",
|
|
4182
|
+
line: line2,
|
|
4183
|
+
column
|
|
4184
|
+
});
|
|
4185
|
+
} else if (!getterUsed) {
|
|
4186
|
+
violations.push({
|
|
4187
|
+
rule: "no-unused-state",
|
|
4188
|
+
message: `signal getter "${getterName}" is declared but never read. If the value is not needed, consider using a simple variable instead of reactive state.`,
|
|
4189
|
+
severity: "warning",
|
|
4190
|
+
line: line2,
|
|
4191
|
+
column
|
|
4192
|
+
});
|
|
4193
|
+
} else if (!setterUsed) {
|
|
4194
|
+
violations.push({
|
|
4195
|
+
rule: "no-unused-state",
|
|
4196
|
+
message: `signal setter "${setterName}" is declared but never called. If the state never changes, consider using a plain constant instead.`,
|
|
4197
|
+
severity: "warning",
|
|
4198
|
+
line: line2,
|
|
4199
|
+
column
|
|
4200
|
+
});
|
|
4201
|
+
}
|
|
4202
|
+
}
|
|
4203
|
+
return violations;
|
|
4204
|
+
}
|
|
4205
|
+
}
|
|
4206
|
+
};
|
|
4207
|
+
function escapeRegex(str) {
|
|
4208
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
4209
|
+
}
|
|
4210
|
+
function lintSource(source2, rules) {
|
|
4211
|
+
const violations = [];
|
|
4212
|
+
const ruleEntries = Object.entries(lintRules);
|
|
4213
|
+
for (const [ruleName, rule] of ruleEntries) {
|
|
4214
|
+
if (rules && rules.length > 0 && !rules.includes(ruleName)) {
|
|
4215
|
+
continue;
|
|
4216
|
+
}
|
|
4217
|
+
const ruleViolations = rule.check(source2);
|
|
4218
|
+
violations.push(...ruleViolations);
|
|
4219
|
+
}
|
|
4220
|
+
violations.sort((a2, b2) => {
|
|
4221
|
+
const lineDiff = (a2.line || 0) - (b2.line || 0);
|
|
4222
|
+
if (lineDiff !== 0) return lineDiff;
|
|
4223
|
+
return (a2.column || 0) - (b2.column || 0);
|
|
4224
|
+
});
|
|
4225
|
+
return violations;
|
|
4226
|
+
}
|
|
4227
|
+
function generateEslintConfig(options) {
|
|
4228
|
+
const severity = options?.severity || "warning";
|
|
4229
|
+
const rulePrefix = "sibujs";
|
|
4230
|
+
const rulesConfig = {};
|
|
4231
|
+
for (const ruleName of Object.keys(lintRules)) {
|
|
4232
|
+
rulesConfig[`${rulePrefix}/${ruleName}`] = severity;
|
|
4233
|
+
}
|
|
4234
|
+
return {
|
|
4235
|
+
plugins: [rulePrefix],
|
|
4236
|
+
rules: rulesConfig,
|
|
4237
|
+
settings: {
|
|
4238
|
+
sibujs: {
|
|
4239
|
+
version: "detect"
|
|
4240
|
+
}
|
|
4241
|
+
},
|
|
4242
|
+
overrides: [
|
|
4243
|
+
{
|
|
4244
|
+
files: ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
|
4245
|
+
rules: rulesConfig
|
|
4246
|
+
}
|
|
4247
|
+
]
|
|
4248
|
+
};
|
|
4249
|
+
}
|
|
4250
|
+
|
|
4251
|
+
// src/build/ide.ts
|
|
4252
|
+
function getComponentMetadata() {
|
|
4253
|
+
return [
|
|
4254
|
+
// ── Reactive Primitives ──────────────────────────────────────────
|
|
4255
|
+
{
|
|
4256
|
+
name: "signal",
|
|
4257
|
+
description: "Creates a reactive signal that holds a value. Returns a [getter, setter] tuple. The getter registers reactive dependencies when called.",
|
|
4258
|
+
props: [
|
|
4259
|
+
{
|
|
4260
|
+
name: "initial",
|
|
4261
|
+
type: "T",
|
|
4262
|
+
required: true,
|
|
4263
|
+
description: "The initial value of the state"
|
|
4264
|
+
}
|
|
4265
|
+
]
|
|
4266
|
+
},
|
|
4267
|
+
{
|
|
4268
|
+
name: "effect",
|
|
4269
|
+
description: "Runs a side effect function immediately and re-runs it whenever any reactive dependency changes. Returns a cleanup function.",
|
|
4270
|
+
props: [
|
|
4271
|
+
{
|
|
4272
|
+
name: "effectFn",
|
|
4273
|
+
type: "() => void",
|
|
4274
|
+
required: true,
|
|
4275
|
+
description: "The effect function to run. It is tracked for reactive dependencies."
|
|
4276
|
+
}
|
|
4277
|
+
]
|
|
4278
|
+
},
|
|
4279
|
+
{
|
|
4280
|
+
name: "derived",
|
|
4281
|
+
description: "Creates a derived reactive signal whose value updates automatically when dependencies change. Returns a getter function.",
|
|
4282
|
+
props: [
|
|
4283
|
+
{
|
|
4284
|
+
name: "getter",
|
|
4285
|
+
type: "() => T",
|
|
4286
|
+
required: true,
|
|
4287
|
+
description: "Function returning the computed value based on reactive signals"
|
|
4288
|
+
}
|
|
4289
|
+
]
|
|
4290
|
+
},
|
|
4291
|
+
{
|
|
4292
|
+
name: "memo",
|
|
4293
|
+
description: "Returns a memoized value that only recomputes when its reactive dependencies change. Alias for derived.",
|
|
4294
|
+
props: [
|
|
4295
|
+
{
|
|
4296
|
+
name: "factory",
|
|
4297
|
+
type: "() => T",
|
|
4298
|
+
required: true,
|
|
4299
|
+
description: "Function that computes the memoized value"
|
|
4300
|
+
}
|
|
4301
|
+
]
|
|
4302
|
+
},
|
|
4303
|
+
{
|
|
4304
|
+
name: "memoFn",
|
|
4305
|
+
description: "Returns a memoized callback that only updates when its reactive dependencies change.",
|
|
4306
|
+
props: [
|
|
4307
|
+
{
|
|
4308
|
+
name: "callback",
|
|
4309
|
+
type: "() => T",
|
|
4310
|
+
required: true,
|
|
4311
|
+
description: "The callback factory function to memoize"
|
|
4312
|
+
}
|
|
4313
|
+
]
|
|
4314
|
+
},
|
|
4315
|
+
{
|
|
4316
|
+
name: "ref",
|
|
4317
|
+
description: "Creates a mutable reference object that persists across renders. Updating a ref does NOT trigger re-renders.",
|
|
4318
|
+
props: [
|
|
4319
|
+
{
|
|
4320
|
+
name: "initial",
|
|
4321
|
+
type: "T",
|
|
4322
|
+
required: false,
|
|
4323
|
+
default: "undefined",
|
|
4324
|
+
description: "Optional initial value for the ref"
|
|
4325
|
+
}
|
|
4326
|
+
]
|
|
4327
|
+
},
|
|
4328
|
+
{
|
|
4329
|
+
name: "watch",
|
|
4330
|
+
description: "Watches a reactive getter and calls a callback with (newValue, oldValue) when the watched value changes. Returns a teardown function.",
|
|
4331
|
+
props: [
|
|
4332
|
+
{
|
|
4333
|
+
name: "getter",
|
|
4334
|
+
type: "() => T",
|
|
4335
|
+
required: true,
|
|
4336
|
+
description: "Function that returns the value to watch"
|
|
4337
|
+
},
|
|
4338
|
+
{
|
|
4339
|
+
name: "callback",
|
|
4340
|
+
type: "(value: T, prev: T | undefined) => void",
|
|
4341
|
+
required: true,
|
|
4342
|
+
description: "Function called when the watched value changes"
|
|
4343
|
+
}
|
|
4344
|
+
]
|
|
4345
|
+
},
|
|
4346
|
+
{
|
|
4347
|
+
name: "store",
|
|
4348
|
+
description: "Creates a global store with reactive properties and subscription support. Returns a [store, actions] tuple.",
|
|
4349
|
+
props: [
|
|
4350
|
+
{
|
|
4351
|
+
name: "initialState",
|
|
4352
|
+
type: "T extends object",
|
|
4353
|
+
required: true,
|
|
4354
|
+
description: "Initial state object for the store"
|
|
4355
|
+
}
|
|
4356
|
+
]
|
|
4357
|
+
},
|
|
4358
|
+
// ── SolidJS-style Primitives ─────────────────────────────────────
|
|
4359
|
+
{
|
|
4360
|
+
name: "createSignal",
|
|
4361
|
+
description: "Creates a reactive signal. SolidJS-style alias for signal. Returns [getter, setter].",
|
|
4362
|
+
props: [
|
|
4363
|
+
{
|
|
4364
|
+
name: "value",
|
|
4365
|
+
type: "T",
|
|
4366
|
+
required: true,
|
|
4367
|
+
description: "Initial value"
|
|
4368
|
+
}
|
|
4369
|
+
]
|
|
4370
|
+
},
|
|
4371
|
+
{
|
|
4372
|
+
name: "createMemo",
|
|
4373
|
+
description: "Creates a derived/computed reactive value. SolidJS-style alias for derived.",
|
|
4374
|
+
props: [
|
|
4375
|
+
{
|
|
4376
|
+
name: "fn",
|
|
4377
|
+
type: "() => T",
|
|
4378
|
+
required: true,
|
|
4379
|
+
description: "Computation function that reads other signals"
|
|
4380
|
+
}
|
|
4381
|
+
]
|
|
4382
|
+
},
|
|
4383
|
+
{
|
|
4384
|
+
name: "createEffect",
|
|
4385
|
+
description: "Creates a reactive side effect. SolidJS-style alias for effect.",
|
|
4386
|
+
props: [
|
|
4387
|
+
{
|
|
4388
|
+
name: "fn",
|
|
4389
|
+
type: "() => void",
|
|
4390
|
+
required: true,
|
|
4391
|
+
description: "Effect function that reads reactive signals"
|
|
4392
|
+
}
|
|
4393
|
+
]
|
|
4394
|
+
},
|
|
4395
|
+
// ── Lifecycle ────────────────────────────────────────────────────
|
|
4396
|
+
{
|
|
4397
|
+
name: "onMount",
|
|
4398
|
+
description: "Runs a callback once the component element has been inserted into the DOM. Uses queueMicrotask for deferred execution.",
|
|
4399
|
+
props: [
|
|
4400
|
+
{
|
|
4401
|
+
name: "callback",
|
|
4402
|
+
type: "() => void | CleanupFn",
|
|
4403
|
+
required: true,
|
|
4404
|
+
description: "Function to run after mount. May return a cleanup function."
|
|
4405
|
+
},
|
|
4406
|
+
{
|
|
4407
|
+
name: "element",
|
|
4408
|
+
type: "HTMLElement",
|
|
4409
|
+
required: false,
|
|
4410
|
+
description: "Optional element to observe; if provided, waits until it is connected."
|
|
4411
|
+
}
|
|
4412
|
+
]
|
|
4413
|
+
},
|
|
4414
|
+
{
|
|
4415
|
+
name: "onUnmount",
|
|
4416
|
+
description: "Runs a callback when the given element is removed from the DOM. Uses MutationObserver to watch for disconnection.",
|
|
4417
|
+
props: [
|
|
4418
|
+
{
|
|
4419
|
+
name: "callback",
|
|
4420
|
+
type: "() => void",
|
|
4421
|
+
required: true,
|
|
4422
|
+
description: "Function to run on unmount"
|
|
4423
|
+
},
|
|
4424
|
+
{
|
|
4425
|
+
name: "element",
|
|
4426
|
+
type: "HTMLElement",
|
|
4427
|
+
required: true,
|
|
4428
|
+
description: "The element to watch for removal"
|
|
4429
|
+
}
|
|
4430
|
+
]
|
|
4431
|
+
},
|
|
4432
|
+
// ── Rendering ────────────────────────────────────────────────────
|
|
4433
|
+
{
|
|
4434
|
+
name: "mount",
|
|
4435
|
+
description: "Mounts a root component into a DOM element. Returns an object with the mounted node and an unmount function.",
|
|
4436
|
+
props: [
|
|
4437
|
+
{
|
|
4438
|
+
name: "component",
|
|
4439
|
+
type: "(() => HTMLElement) | HTMLElement | Node",
|
|
4440
|
+
required: true,
|
|
4441
|
+
description: "Function returning HTMLElement, or an HTMLElement directly"
|
|
4442
|
+
},
|
|
4443
|
+
{
|
|
4444
|
+
name: "container",
|
|
4445
|
+
type: "HTMLElement",
|
|
4446
|
+
required: true,
|
|
4447
|
+
description: "Target DOM element to append the result"
|
|
4448
|
+
}
|
|
4449
|
+
]
|
|
4450
|
+
},
|
|
4451
|
+
{
|
|
4452
|
+
name: "each",
|
|
4453
|
+
description: "Renders a list of nodes efficiently with key-based diffing and LIS-based move minimization.",
|
|
4454
|
+
props: [
|
|
4455
|
+
{
|
|
4456
|
+
name: "getArray",
|
|
4457
|
+
type: "() => T[]",
|
|
4458
|
+
required: true,
|
|
4459
|
+
description: "A reactive getter returning an array"
|
|
4460
|
+
},
|
|
4461
|
+
{
|
|
4462
|
+
name: "render",
|
|
4463
|
+
type: "(item: T, index: number) => NodeChild",
|
|
4464
|
+
required: true,
|
|
4465
|
+
description: "A function that returns a NodeChild for each item"
|
|
4466
|
+
},
|
|
4467
|
+
{
|
|
4468
|
+
name: "options",
|
|
4469
|
+
type: "{ key: (item: T) => string | number }",
|
|
4470
|
+
required: true,
|
|
4471
|
+
description: "A key function for unique identity of items"
|
|
4472
|
+
}
|
|
4473
|
+
]
|
|
4474
|
+
},
|
|
4475
|
+
{
|
|
4476
|
+
name: "lazy",
|
|
4477
|
+
description: "Enables code-splitting by deferring the import of a component until it is first rendered.",
|
|
4478
|
+
props: [
|
|
4479
|
+
{
|
|
4480
|
+
name: "importFn",
|
|
4481
|
+
type: "() => Promise<{ default: Component }>",
|
|
4482
|
+
required: true,
|
|
4483
|
+
description: "Dynamic import function returning { default: Component }"
|
|
4484
|
+
}
|
|
4485
|
+
]
|
|
4486
|
+
},
|
|
4487
|
+
{
|
|
4488
|
+
name: "Suspense",
|
|
4489
|
+
description: "Provides a fallback UI while lazy or async nodes are loading.",
|
|
4490
|
+
props: [
|
|
4491
|
+
{
|
|
4492
|
+
name: "nodes",
|
|
4493
|
+
type: "() => HTMLElement",
|
|
4494
|
+
required: true,
|
|
4495
|
+
description: "Function that returns the async/lazy component"
|
|
4496
|
+
},
|
|
4497
|
+
{
|
|
4498
|
+
name: "fallback",
|
|
4499
|
+
type: "() => HTMLElement",
|
|
4500
|
+
required: true,
|
|
4501
|
+
description: "Function that returns the loading UI"
|
|
4502
|
+
}
|
|
4503
|
+
]
|
|
4504
|
+
},
|
|
4505
|
+
// ── Context ──────────────────────────────────────────────────────
|
|
4506
|
+
{
|
|
4507
|
+
name: "context",
|
|
4508
|
+
description: "Creates a context for dependency injection across component trees without prop drilling. Returns a Context object with provide, use, get, and set methods.",
|
|
4509
|
+
props: [
|
|
4510
|
+
{
|
|
4511
|
+
name: "defaultValue",
|
|
4512
|
+
type: "T",
|
|
4513
|
+
required: true,
|
|
4514
|
+
description: "The fallback value when no provider is found"
|
|
4515
|
+
}
|
|
4516
|
+
]
|
|
4517
|
+
},
|
|
4518
|
+
// ── Dynamic Components ───────────────────────────────────────────
|
|
4519
|
+
{
|
|
4520
|
+
name: "DynamicComponent",
|
|
4521
|
+
description: "Reactively switches between components based on a reactive getter returning a component name or function.",
|
|
4522
|
+
props: [
|
|
4523
|
+
{
|
|
4524
|
+
name: "is",
|
|
4525
|
+
type: "() => string | Component",
|
|
4526
|
+
required: true,
|
|
4527
|
+
description: "Reactive getter returning component name (string) or component function"
|
|
4528
|
+
}
|
|
4529
|
+
]
|
|
4530
|
+
},
|
|
4531
|
+
{
|
|
4532
|
+
name: "registerComponent",
|
|
4533
|
+
description: "Registers a component by name for dynamic resolution via DynamicComponent or resolveComponent.",
|
|
4534
|
+
props: [
|
|
4535
|
+
{
|
|
4536
|
+
name: "name",
|
|
4537
|
+
type: "string",
|
|
4538
|
+
required: true,
|
|
4539
|
+
description: "Unique component identifier"
|
|
4540
|
+
},
|
|
4541
|
+
{
|
|
4542
|
+
name: "component",
|
|
4543
|
+
type: "() => HTMLElement",
|
|
4544
|
+
required: true,
|
|
4545
|
+
description: "The component function"
|
|
4546
|
+
}
|
|
4547
|
+
]
|
|
4548
|
+
},
|
|
4549
|
+
// ── HTML Tag Factories ───────────────────────────────────────────
|
|
4550
|
+
{
|
|
4551
|
+
name: "div",
|
|
4552
|
+
description: "Creates a reactive <div> element. Accepts TagProps including class, style, on, nodes, and arbitrary attributes.",
|
|
4553
|
+
props: [
|
|
4554
|
+
{
|
|
4555
|
+
name: "props",
|
|
4556
|
+
type: "TagProps",
|
|
4557
|
+
required: false,
|
|
4558
|
+
default: "{}",
|
|
4559
|
+
description: "Props object with id, class, style, ref, nodes, on, and other attributes"
|
|
4560
|
+
}
|
|
4561
|
+
],
|
|
4562
|
+
events: [
|
|
4563
|
+
{
|
|
4564
|
+
name: "click",
|
|
4565
|
+
description: "Fires when the element is clicked"
|
|
4566
|
+
},
|
|
4567
|
+
{
|
|
4568
|
+
name: "input",
|
|
4569
|
+
description: "Fires when user input is received"
|
|
4570
|
+
}
|
|
4571
|
+
]
|
|
4572
|
+
}
|
|
4573
|
+
];
|
|
4574
|
+
}
|
|
4575
|
+
function generateVSCodeSnippets() {
|
|
4576
|
+
return {
|
|
4577
|
+
"SibuJS Component": {
|
|
4578
|
+
prefix: "sibu-component",
|
|
4579
|
+
body: [
|
|
4580
|
+
"import { div } from 'sibujs';",
|
|
4581
|
+
"",
|
|
4582
|
+
"export function ${1:ComponentName}(): HTMLElement {",
|
|
4583
|
+
" return div({",
|
|
4584
|
+
" class: '${2:component-class}',",
|
|
4585
|
+
" nodes: [",
|
|
4586
|
+
" ${3:// nodes here}",
|
|
4587
|
+
" ],",
|
|
4588
|
+
" });",
|
|
4589
|
+
"}"
|
|
4590
|
+
],
|
|
4591
|
+
description: "Create a basic SibuJS component"
|
|
4592
|
+
},
|
|
4593
|
+
"SibuJS Component with State": {
|
|
4594
|
+
prefix: "sibu-component-state",
|
|
4595
|
+
body: [
|
|
4596
|
+
"import { div, span } from 'sibujs';",
|
|
4597
|
+
"import { signal } from 'sibujs';",
|
|
4598
|
+
"",
|
|
4599
|
+
"export function ${1:ComponentName}(): HTMLElement {",
|
|
4600
|
+
" const [${2:value}, ${3:setValue}] = signal(${4:initialValue});",
|
|
4601
|
+
"",
|
|
4602
|
+
" return div({",
|
|
4603
|
+
" class: '${5:component-class}',",
|
|
4604
|
+
" nodes: [",
|
|
4605
|
+
" () => span({ nodes: String(${2:value}()) }),",
|
|
4606
|
+
" ],",
|
|
4607
|
+
" });",
|
|
4608
|
+
"}"
|
|
4609
|
+
],
|
|
4610
|
+
description: "Create a SibuJS component with reactive state"
|
|
4611
|
+
},
|
|
4612
|
+
"SibuJS signal": {
|
|
4613
|
+
prefix: "sibu-state",
|
|
4614
|
+
body: ["const [${1:value}, ${2:setValue}] = signal(${3:initialValue});"],
|
|
4615
|
+
description: "Create a reactive state with signal"
|
|
4616
|
+
},
|
|
4617
|
+
"SibuJS effect": {
|
|
4618
|
+
prefix: "sibu-effect",
|
|
4619
|
+
body: ["const cleanup = effect(() => {", " ${1:// effect logic}", "});"],
|
|
4620
|
+
description: "Create a reactive side effect with effect"
|
|
4621
|
+
},
|
|
4622
|
+
"SibuJS derived": {
|
|
4623
|
+
prefix: "sibu-computed",
|
|
4624
|
+
body: ["const ${1:computed} = derived(() => {", " return ${2:// derived value};", "});"],
|
|
4625
|
+
description: "Create a derived reactive value with derived"
|
|
4626
|
+
},
|
|
4627
|
+
"SibuJS watch": {
|
|
4628
|
+
prefix: "sibu-watch",
|
|
4629
|
+
body: [
|
|
4630
|
+
"const teardown = watch(",
|
|
4631
|
+
" () => ${1:watchedValue}(),",
|
|
4632
|
+
" (newVal, oldVal) => {",
|
|
4633
|
+
" ${2:// handle change}",
|
|
4634
|
+
" }",
|
|
4635
|
+
");"
|
|
4636
|
+
],
|
|
4637
|
+
description: "Watch a reactive value for changes"
|
|
4638
|
+
},
|
|
4639
|
+
"SibuJS each": {
|
|
4640
|
+
prefix: "sibu-each",
|
|
4641
|
+
body: [
|
|
4642
|
+
"each(",
|
|
4643
|
+
" () => ${1:items}(),",
|
|
4644
|
+
" (item, index) => {",
|
|
4645
|
+
" return ${2:div({ nodes: String(item) })};",
|
|
4646
|
+
" },",
|
|
4647
|
+
" { key: (item) => ${3:item.id} }",
|
|
4648
|
+
")"
|
|
4649
|
+
],
|
|
4650
|
+
description: "Create a reactive list with each()"
|
|
4651
|
+
},
|
|
4652
|
+
"SibuJS Context": {
|
|
4653
|
+
prefix: "sibu-context",
|
|
4654
|
+
body: [
|
|
4655
|
+
"const ${1:MyContext} = context(${2:defaultValue});",
|
|
4656
|
+
"",
|
|
4657
|
+
"// In provider component:",
|
|
4658
|
+
"// ${1:MyContext}.provide(value);",
|
|
4659
|
+
"",
|
|
4660
|
+
"// In consumer component:",
|
|
4661
|
+
"// const ${3:value} = ${1:MyContext}.use();"
|
|
4662
|
+
],
|
|
4663
|
+
description: "Create a context for dependency injection"
|
|
4664
|
+
},
|
|
4665
|
+
"SibuJS store": {
|
|
4666
|
+
prefix: "sibu-store",
|
|
4667
|
+
body: [
|
|
4668
|
+
"const [${1:store}, { setState: ${2:setStore}, reset, subscribe }] = store({",
|
|
4669
|
+
" ${3:key}: ${4:value},",
|
|
4670
|
+
"});"
|
|
4671
|
+
],
|
|
4672
|
+
description: "Create a reactive global store"
|
|
4673
|
+
},
|
|
4674
|
+
"SibuJS Lazy Component": {
|
|
4675
|
+
prefix: "sibu-lazy",
|
|
4676
|
+
body: ["const ${1:LazyComponent} = lazy(() => import('./${2:ComponentPath}'));"],
|
|
4677
|
+
description: "Create a lazy-loaded component"
|
|
4678
|
+
},
|
|
4679
|
+
"SibuJS Suspense": {
|
|
4680
|
+
prefix: "sibu-suspense",
|
|
4681
|
+
body: [
|
|
4682
|
+
"Suspense({",
|
|
4683
|
+
" nodes: () => ${1:LazyComponent}(),",
|
|
4684
|
+
" fallback: () => div({ nodes: '${2:Loading...}' }),",
|
|
4685
|
+
"})"
|
|
4686
|
+
],
|
|
4687
|
+
description: "Wrap a lazy component with a loading fallback"
|
|
4688
|
+
},
|
|
4689
|
+
"SibuJS onMount": {
|
|
4690
|
+
prefix: "sibu-mount",
|
|
4691
|
+
body: ["onMount(() => {", " ${1:// runs after component enters the DOM}", "});"],
|
|
4692
|
+
description: "Schedule a callback to run after mount"
|
|
4693
|
+
},
|
|
4694
|
+
"SibuJS onUnmount": {
|
|
4695
|
+
prefix: "sibu-unmount",
|
|
4696
|
+
body: ["onUnmount(() => {", " ${1:// cleanup when removed from DOM}", "}, ${2:element});"],
|
|
4697
|
+
description: "Schedule a callback to run on unmount"
|
|
4698
|
+
},
|
|
4699
|
+
"SibuJS Event Handler": {
|
|
4700
|
+
prefix: "sibu-event",
|
|
4701
|
+
body: [
|
|
4702
|
+
"div({",
|
|
4703
|
+
" on: {",
|
|
4704
|
+
" ${1:click}: (e) => {",
|
|
4705
|
+
" ${2:// handle event}",
|
|
4706
|
+
" },",
|
|
4707
|
+
" },",
|
|
4708
|
+
" nodes: '${3:Click me}',",
|
|
4709
|
+
"})"
|
|
4710
|
+
],
|
|
4711
|
+
description: "Create an element with event handlers"
|
|
4712
|
+
},
|
|
4713
|
+
"SibuJS Form": {
|
|
4714
|
+
prefix: "sibu-form",
|
|
4715
|
+
body: [
|
|
4716
|
+
"const form = form({",
|
|
4717
|
+
" ${1:fieldName}: {",
|
|
4718
|
+
" initial: '${2:}',",
|
|
4719
|
+
" validators: [",
|
|
4720
|
+
" (value) => !value ? '${3:Required}' : null,",
|
|
4721
|
+
" ],",
|
|
4722
|
+
" },",
|
|
4723
|
+
"});"
|
|
4724
|
+
],
|
|
4725
|
+
description: "Create a reactive form with validation"
|
|
4726
|
+
},
|
|
4727
|
+
"SibuJS createSignal": {
|
|
4728
|
+
prefix: "sibu-signal",
|
|
4729
|
+
body: ["const [${1:value}, ${2:setValue}] = createSignal(${3:initialValue});"],
|
|
4730
|
+
description: "Create a reactive signal (SolidJS-style alias for signal)"
|
|
4731
|
+
}
|
|
4732
|
+
};
|
|
4733
|
+
}
|
|
4734
|
+
function generateLanguageConfig() {
|
|
4735
|
+
return {
|
|
4736
|
+
comments: {
|
|
4737
|
+
lineComment: "//",
|
|
4738
|
+
blockComment: ["/*", "*/"]
|
|
4739
|
+
},
|
|
4740
|
+
brackets: [
|
|
4741
|
+
["{", "}"],
|
|
4742
|
+
["[", "]"],
|
|
4743
|
+
["(", ")"],
|
|
4744
|
+
["<", ">"]
|
|
4745
|
+
],
|
|
4746
|
+
autoClosingPairs: [
|
|
4747
|
+
{ open: "{", close: "}" },
|
|
4748
|
+
{ open: "[", close: "]" },
|
|
4749
|
+
{ open: "(", close: ")" },
|
|
4750
|
+
{ open: "<", close: ">" },
|
|
4751
|
+
{ open: "'", close: "'" },
|
|
4752
|
+
{ open: '"', close: '"' },
|
|
4753
|
+
{ open: "`", close: "`" }
|
|
4754
|
+
]
|
|
4755
|
+
};
|
|
4756
|
+
}
|
|
4757
|
+
function generateTypeStubs() {
|
|
4758
|
+
return {
|
|
4759
|
+
signal: ["declare function signal<T>(initial: T): [() => T, (next: T | ((prev: T) => T)) => void];"].join("\n"),
|
|
4760
|
+
effect: ["declare function effect(effectFn: () => void): () => void;"].join("\n"),
|
|
4761
|
+
derived: ["declare function derived<T>(getter: () => T): () => T;"].join("\n"),
|
|
4762
|
+
memo: ["declare function memo<T>(factory: () => T): () => T;"].join("\n"),
|
|
4763
|
+
memoFn: ["declare function memoFn<T extends (...args: unknown[]) => unknown>(callback: () => T): () => T;"].join(
|
|
4764
|
+
"\n"
|
|
4765
|
+
),
|
|
4766
|
+
ref: [
|
|
4767
|
+
"interface Ref<T> { current: T; }",
|
|
4768
|
+
"declare function ref<T>(initial: T): Ref<T>;",
|
|
4769
|
+
"declare function ref<T = undefined>(): Ref<T | undefined>;"
|
|
4770
|
+
].join("\n"),
|
|
4771
|
+
watch: [
|
|
4772
|
+
"declare function watch<T>(getter: () => T, callback: (value: T, prev: T | undefined) => void): () => void;"
|
|
4773
|
+
].join("\n"),
|
|
4774
|
+
store: [
|
|
4775
|
+
"interface StoreActions<T> {",
|
|
4776
|
+
" setState: (patch: Partial<T> | ((state: T) => T)) => void;",
|
|
4777
|
+
" reset: () => void;",
|
|
4778
|
+
" subscribe: (callback: (state: T) => void) => () => void;",
|
|
4779
|
+
" subscribeKey: <K extends keyof T>(key: K, callback: (value: T[K], prev: T[K]) => void) => () => void;",
|
|
4780
|
+
" getSnapshot: () => T;",
|
|
4781
|
+
"}",
|
|
4782
|
+
"declare function store<T extends object>(initialState: T): [{ readonly [K in keyof T]: T[K] }, StoreActions<T>];"
|
|
4783
|
+
].join("\n"),
|
|
4784
|
+
createSignal: ["declare function createSignal<T>(value: T): [() => T, (next: T | ((prev: T) => T)) => void];"].join(
|
|
4785
|
+
"\n"
|
|
4786
|
+
),
|
|
4787
|
+
createMemo: ["declare function createMemo<T>(fn: () => T): () => T;"].join("\n"),
|
|
4788
|
+
createEffect: ["declare function createEffect(fn: () => void): () => void;"].join("\n"),
|
|
4789
|
+
mount: [
|
|
4790
|
+
"declare function mount(component: (() => HTMLElement) | HTMLElement | Node, container: HTMLElement | null): { node: Node; unmount: () => void };"
|
|
4791
|
+
].join("\n"),
|
|
4792
|
+
each: [
|
|
4793
|
+
"declare function each<T>(getArray: () => T[], render: (item: T, index: number) => NodeChild, options: { key: (item: T) => string | number }): Comment;"
|
|
4794
|
+
].join("\n"),
|
|
4795
|
+
onMount: ["declare function onMount(callback: () => void | (() => void), element?: HTMLElement): void;"].join("\n"),
|
|
4796
|
+
onUnmount: ["declare function onUnmount(callback: () => void, element: HTMLElement): void;"].join("\n"),
|
|
4797
|
+
context: [
|
|
4798
|
+
"interface Context<T> {",
|
|
4799
|
+
" provide(value: T): void;",
|
|
4800
|
+
" use(): () => T;",
|
|
4801
|
+
" get(): T;",
|
|
4802
|
+
" set(value: T): void;",
|
|
4803
|
+
"}",
|
|
4804
|
+
"declare function context<T>(defaultValue: T): Context<T>;"
|
|
4805
|
+
].join("\n"),
|
|
4806
|
+
lazy: ["declare function lazy(importFn: () => Promise<{ default: () => HTMLElement }>): () => HTMLElement;"].join(
|
|
4807
|
+
"\n"
|
|
4808
|
+
),
|
|
4809
|
+
Suspense: [
|
|
4810
|
+
"interface SuspenseProps { nodes: () => HTMLElement; fallback: () => HTMLElement; }",
|
|
4811
|
+
"declare function Suspense(props: SuspenseProps): HTMLElement;"
|
|
4812
|
+
].join("\n"),
|
|
4813
|
+
tagFactory: [
|
|
4814
|
+
"interface TagProps {",
|
|
4815
|
+
" id?: string;",
|
|
4816
|
+
" class?: string | (() => string) | Record<string, boolean | (() => boolean)>;",
|
|
4817
|
+
" style?: Record<string, string | number | (() => string | number)> | string | (() => string);",
|
|
4818
|
+
" ref?: { current: unknown };",
|
|
4819
|
+
" nodes?: NodeChildren;",
|
|
4820
|
+
" on?: Record<string, (ev: Event) => void>;",
|
|
4821
|
+
" [attr: string]: unknown;",
|
|
4822
|
+
"}",
|
|
4823
|
+
"declare function tagFactory(tag: string, ns?: string): (first?: TagProps | NodeChildren, second?: NodeChildren) => Element;"
|
|
4824
|
+
].join("\n"),
|
|
4825
|
+
DynamicComponent: ["declare function DynamicComponent(is: () => string | (() => HTMLElement)): HTMLElement;"].join(
|
|
4826
|
+
"\n"
|
|
4827
|
+
),
|
|
4828
|
+
registerComponent: ["declare function registerComponent(name: string, component: () => HTMLElement): void;"].join(
|
|
4829
|
+
"\n"
|
|
4830
|
+
)
|
|
4831
|
+
};
|
|
4832
|
+
}
|
|
4833
|
+
|
|
4834
|
+
// src/build/routeSplitting.ts
|
|
4835
|
+
function fileToRoute(relativePath) {
|
|
4836
|
+
const basename = relativePath.split("/").pop() || "";
|
|
4837
|
+
if (basename.startsWith("_")) return null;
|
|
4838
|
+
let route = relativePath.replace(/\.(ts|tsx|js|jsx)$/, "");
|
|
4839
|
+
route = route.replace(/\/index$/, "").replace(/^index$/, "");
|
|
4840
|
+
route = route.replace(/\[\.\.\.(\w+)\]/g, "*");
|
|
4841
|
+
route = route.replace(/\[(\w+)\]/g, ":$1");
|
|
4842
|
+
return `/${route}`;
|
|
4843
|
+
}
|
|
4844
|
+
async function scanRoutes(routesDir, exclude, fs) {
|
|
4845
|
+
const entries = await fs.readdir(routesDir, { withFileTypes: true, recursive: true });
|
|
4846
|
+
const files = [];
|
|
4847
|
+
for (const entry of entries) {
|
|
4848
|
+
if (!entry.isFile()) continue;
|
|
4849
|
+
if (!/\.(ts|tsx|js|jsx)$/.test(entry.name)) continue;
|
|
4850
|
+
const dir = (entry.parentPath || entry.path || routesDir).replace(/\\/g, "/");
|
|
4851
|
+
const routesDirNorm = routesDir.replace(/\\/g, "/");
|
|
4852
|
+
const relative = `${dir}/${entry.name}`.replace(`${routesDirNorm}/`, "").replace(/\\/g, "/");
|
|
4853
|
+
const excluded = exclude.some((pattern2) => {
|
|
4854
|
+
const regex = pattern2.replace(/\*/g, ".*");
|
|
4855
|
+
return new RegExp(regex).test(relative);
|
|
4856
|
+
});
|
|
4857
|
+
if (!excluded) {
|
|
4858
|
+
files.push(relative);
|
|
4859
|
+
}
|
|
4860
|
+
}
|
|
4861
|
+
return files.sort();
|
|
4862
|
+
}
|
|
4863
|
+
function buildRouteEntries(files, chunkPrefix) {
|
|
4864
|
+
const entries = [];
|
|
4865
|
+
for (const file of files) {
|
|
4866
|
+
const path2 = fileToRoute(file);
|
|
4867
|
+
if (path2 === null) continue;
|
|
4868
|
+
const chunkName = `${chunkPrefix}${file.replace(/\.(ts|tsx|js|jsx)$/, "").replace(/[/\\[\].]/g, "-").replace(/^-+|-+$/g, "").toLowerCase()}`;
|
|
4869
|
+
entries.push({
|
|
4870
|
+
path: path2,
|
|
4871
|
+
importPath: file,
|
|
4872
|
+
chunkName,
|
|
4873
|
+
isDynamic: path2.includes(":") || path2.includes("*")
|
|
4874
|
+
});
|
|
4875
|
+
}
|
|
4876
|
+
return entries.sort((a2, b2) => {
|
|
4877
|
+
if (a2.path.includes("*") && !b2.path.includes("*")) return 1;
|
|
4878
|
+
if (!a2.path.includes("*") && b2.path.includes("*")) return -1;
|
|
4879
|
+
if (a2.isDynamic && !b2.isDynamic) return 1;
|
|
4880
|
+
if (!a2.isDynamic && b2.isDynamic) return -1;
|
|
4881
|
+
return a2.path.localeCompare(b2.path);
|
|
4882
|
+
});
|
|
4883
|
+
}
|
|
4884
|
+
function generateRouteModule(entries, routesDir) {
|
|
4885
|
+
const imports = entries.map(
|
|
4886
|
+
(e, i2) => `const route${i2} = () => import(/* webpackChunkName: "${e.chunkName}" */ "${routesDir}/${e.importPath}");`
|
|
4887
|
+
).join("\n");
|
|
4888
|
+
const routes = entries.map((e, i2) => ` { path: "${e.path}", component: lazy(route${i2}) }`).join(",\n");
|
|
4889
|
+
return `import { lazy } from "sibu";
|
|
4890
|
+
|
|
4891
|
+
${imports}
|
|
4892
|
+
|
|
4893
|
+
export const routes = [
|
|
4894
|
+
${routes}
|
|
4895
|
+
];
|
|
4896
|
+
`;
|
|
4897
|
+
}
|
|
4898
|
+
var VIRTUAL_ID = "virtual:sibu-routes";
|
|
4899
|
+
var RESOLVED_VIRTUAL_ID = `\0${VIRTUAL_ID}`;
|
|
4900
|
+
function sibuRouteSplitting(options = {}) {
|
|
4901
|
+
const { routesDir = "src/routes", exclude = [], chunkPrefix = "route-" } = options;
|
|
4902
|
+
let projectRoot = "";
|
|
4903
|
+
return {
|
|
4904
|
+
name: "sibu-route-splitting",
|
|
4905
|
+
enforce: "pre",
|
|
4906
|
+
resolveId(id) {
|
|
4907
|
+
if (id === VIRTUAL_ID) {
|
|
4908
|
+
return RESOLVED_VIRTUAL_ID;
|
|
4909
|
+
}
|
|
4910
|
+
return void 0;
|
|
4911
|
+
},
|
|
4912
|
+
async load(id) {
|
|
4913
|
+
if (id !== RESOLVED_VIRTUAL_ID) return void 0;
|
|
4914
|
+
const { readdir } = await import("fs/promises");
|
|
4915
|
+
const { resolve } = await import("path");
|
|
4916
|
+
if (!projectRoot) {
|
|
4917
|
+
projectRoot = process.cwd();
|
|
4918
|
+
}
|
|
4919
|
+
const fullRoutesDir = resolve(projectRoot, routesDir);
|
|
4920
|
+
try {
|
|
4921
|
+
const files = await scanRoutes(fullRoutesDir, exclude, {
|
|
4922
|
+
readdir
|
|
4923
|
+
});
|
|
4924
|
+
const entries = buildRouteEntries(files, chunkPrefix);
|
|
4925
|
+
return generateRouteModule(entries, routesDir.startsWith("/") ? routesDir : `./${routesDir}`);
|
|
4926
|
+
} catch {
|
|
4927
|
+
return "export const routes = [];\n";
|
|
4928
|
+
}
|
|
4929
|
+
},
|
|
4930
|
+
handleHotUpdate(ctx) {
|
|
4931
|
+
const normalizedRoutesDir = routesDir.replace(/\\/g, "/");
|
|
4932
|
+
if (ctx.file.replace(/\\/g, "/").includes(normalizedRoutesDir)) {
|
|
4933
|
+
const mod = ctx.server.moduleGraph.getModuleById(RESOLVED_VIRTUAL_ID);
|
|
4934
|
+
if (mod) {
|
|
4935
|
+
ctx.server.moduleGraph.invalidateModule(mod);
|
|
4936
|
+
ctx.server.ws.send({ type: "full-reload" });
|
|
4937
|
+
}
|
|
4938
|
+
}
|
|
4939
|
+
}
|
|
4940
|
+
};
|
|
4941
|
+
}
|
|
4942
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
4943
|
+
0 && (module.exports = {
|
|
4944
|
+
analyzeBundle,
|
|
4945
|
+
analyzeStaticTemplates,
|
|
4946
|
+
buildRouteEntries,
|
|
4947
|
+
cdnUrls,
|
|
4948
|
+
compileHtmlTemplates,
|
|
4949
|
+
createPureAnnotationsLoader,
|
|
4950
|
+
createViteConfig,
|
|
4951
|
+
createWebpackConfig,
|
|
4952
|
+
estimateImportSize,
|
|
4953
|
+
fileToRoute,
|
|
4954
|
+
generateEslintConfig,
|
|
4955
|
+
generateImportMap,
|
|
4956
|
+
generateLanguageConfig,
|
|
4957
|
+
generateTsConfig,
|
|
4958
|
+
generateTypeStubs,
|
|
4959
|
+
generateVSCodeSnippets,
|
|
4960
|
+
getComponentMetadata,
|
|
4961
|
+
lintRules,
|
|
4962
|
+
lintSource,
|
|
4963
|
+
moduleSizes,
|
|
4964
|
+
registerGlobal,
|
|
4965
|
+
sibuRouteSplitting,
|
|
4966
|
+
sibuVitePlugin,
|
|
4967
|
+
sibuWebpackPlugin,
|
|
4968
|
+
umdWrapper,
|
|
4969
|
+
validateTsConfig
|
|
4970
|
+
});
|