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.
Files changed (302) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1630 -0
  3. package/dist/browser.cjs +815 -0
  4. package/dist/browser.d.cts +174 -0
  5. package/dist/browser.d.ts +174 -0
  6. package/dist/browser.js +458 -0
  7. package/dist/build.cjs +4970 -0
  8. package/dist/build.d.cts +630 -0
  9. package/dist/build.d.ts +630 -0
  10. package/dist/build.js +2478 -0
  11. package/dist/cdn.global.js +115 -0
  12. package/dist/chunk-27QC4FPL.js +67 -0
  13. package/dist/chunk-2ABBWCGC.js +65 -0
  14. package/dist/chunk-2MUNQYZ7.js +26 -0
  15. package/dist/chunk-2PSPKNUI.js +1711 -0
  16. package/dist/chunk-35CDLDX5.js +1758 -0
  17. package/dist/chunk-36MU4CFV.js +41 -0
  18. package/dist/chunk-3FIQOFI6.js +182 -0
  19. package/dist/chunk-3GHNC2BN.js +28 -0
  20. package/dist/chunk-3HLWWEPU.js +909 -0
  21. package/dist/chunk-3IVI3J54.js +252 -0
  22. package/dist/chunk-3KZ72WNW.js +944 -0
  23. package/dist/chunk-4AU64SQV.js +182 -0
  24. package/dist/chunk-4MOK7HAR.js +84 -0
  25. package/dist/chunk-4QK6FBDH.js +1429 -0
  26. package/dist/chunk-566Z7HXB.js +737 -0
  27. package/dist/chunk-5CRBB7XP.js +358 -0
  28. package/dist/chunk-5G67D3IZ.js +168 -0
  29. package/dist/chunk-5NCPAWBE.js +99 -0
  30. package/dist/chunk-5O2RKXR3.js +1444 -0
  31. package/dist/chunk-6BTBDO6A.js +633 -0
  32. package/dist/chunk-6IWEHW57.js +43 -0
  33. package/dist/chunk-6JGMNCD6.js +282 -0
  34. package/dist/chunk-6QRLJNXR.js +1425 -0
  35. package/dist/chunk-7HM5UE5T.js +270 -0
  36. package/dist/chunk-7JOLTGUH.js +58 -0
  37. package/dist/chunk-7MCWJCQK.js +909 -0
  38. package/dist/chunk-7RIIFP3E.js +1758 -0
  39. package/dist/chunk-7UASYN3G.js +254 -0
  40. package/dist/chunk-7W2WYHDI.js +741 -0
  41. package/dist/chunk-7Y35RDSJ.js +872 -0
  42. package/dist/chunk-A65GFJBL.js +65 -0
  43. package/dist/chunk-AD6ZIEDK.js +67 -0
  44. package/dist/chunk-AK5Y72F3.js +1426 -0
  45. package/dist/chunk-APOMMWH4.js +282 -0
  46. package/dist/chunk-ARZVTWIQ.js +1750 -0
  47. package/dist/chunk-AWWBM2BI.js +664 -0
  48. package/dist/chunk-AX5VEQTY.js +58 -0
  49. package/dist/chunk-AYTXVOW3.js +1708 -0
  50. package/dist/chunk-BG4A246G.js +1746 -0
  51. package/dist/chunk-BNFJJA2L.js +1425 -0
  52. package/dist/chunk-BPKPBVU5.js +59 -0
  53. package/dist/chunk-BPKPPSXC.js +282 -0
  54. package/dist/chunk-BPWKKK7F.js +1711 -0
  55. package/dist/chunk-CCKX6YTC.js +1735 -0
  56. package/dist/chunk-CIF5Z3MP.js +58 -0
  57. package/dist/chunk-CSXYU7IO.js +457 -0
  58. package/dist/chunk-D6JD4FDC.js +26 -0
  59. package/dist/chunk-E7NGA7X2.js +59 -0
  60. package/dist/chunk-EEPPJKAE.js +443 -0
  61. package/dist/chunk-EJMYGAGQ.js +717 -0
  62. package/dist/chunk-EL6Z5MDY.js +55 -0
  63. package/dist/chunk-EP7VRLEB.js +41 -0
  64. package/dist/chunk-ETMEC6FH.js +99 -0
  65. package/dist/chunk-EZ2WHYVL.js +65 -0
  66. package/dist/chunk-EZRVMSZK.js +67 -0
  67. package/dist/chunk-F2TRGINX.js +254 -0
  68. package/dist/chunk-F5JCIH3Q.js +642 -0
  69. package/dist/chunk-FGK3JKMN.js +909 -0
  70. package/dist/chunk-FQWPKSTD.js +1437 -0
  71. package/dist/chunk-FWHVLMCI.js +26 -0
  72. package/dist/chunk-GBEYQRO2.js +303 -0
  73. package/dist/chunk-GBLES3NK.js +248 -0
  74. package/dist/chunk-GQVGUQW6.js +1436 -0
  75. package/dist/chunk-HCV2T76T.js +457 -0
  76. package/dist/chunk-HS7ZKVPR.js +182 -0
  77. package/dist/chunk-HXDVV7HZ.js +909 -0
  78. package/dist/chunk-IB23VMO3.js +1746 -0
  79. package/dist/chunk-IEMZ7RTT.js +99 -0
  80. package/dist/chunk-IPGRSN42.js +1750 -0
  81. package/dist/chunk-IVMOK2QN.js +1750 -0
  82. package/dist/chunk-JCLGQO7T.js +443 -0
  83. package/dist/chunk-JDXL7KDB.js +1436 -0
  84. package/dist/chunk-JIIFW636.js +270 -0
  85. package/dist/chunk-JWGEEH7H.js +944 -0
  86. package/dist/chunk-K2BESAG7.js +1688 -0
  87. package/dist/chunk-K2U5YGF4.js +877 -0
  88. package/dist/chunk-K45FQ4Y4.js +175 -0
  89. package/dist/chunk-K7BPE427.js +1432 -0
  90. package/dist/chunk-KL3266RS.js +26 -0
  91. package/dist/chunk-KNN4P7DZ.js +84 -0
  92. package/dist/chunk-KP2DZH5Q.js +254 -0
  93. package/dist/chunk-KZHAJSQR.js +1636 -0
  94. package/dist/chunk-LBKGHMQV.js +1750 -0
  95. package/dist/chunk-LBTEPL7A.js +1731 -0
  96. package/dist/chunk-LEBBPTDB.js +1444 -0
  97. package/dist/chunk-LLH63WVQ.js +98 -0
  98. package/dist/chunk-LWVR2C4G.js +1711 -0
  99. package/dist/chunk-M3MDTVV2.js +896 -0
  100. package/dist/chunk-M5GNLDEO.js +303 -0
  101. package/dist/chunk-MFHVGKET.js +267 -0
  102. package/dist/chunk-MGWSG3PM.js +358 -0
  103. package/dist/chunk-MJNB47HB.js +19 -0
  104. package/dist/chunk-MLKGABMK.js +9 -0
  105. package/dist/chunk-MQWTY3JY.js +944 -0
  106. package/dist/chunk-MZZOQHNI.js +642 -0
  107. package/dist/chunk-NIHWGZS4.js +1426 -0
  108. package/dist/chunk-NSVVHQK5.js +41 -0
  109. package/dist/chunk-NVI2WE7D.js +443 -0
  110. package/dist/chunk-O7QBO3PH.js +58 -0
  111. package/dist/chunk-OAUPQBO2.js +270 -0
  112. package/dist/chunk-OB2LMD7C.js +297 -0
  113. package/dist/chunk-OHEYBWQU.js +58 -0
  114. package/dist/chunk-OI6OXUHJ.js +443 -0
  115. package/dist/chunk-OX2VMRMV.js +633 -0
  116. package/dist/chunk-P4FYE5TX.js +866 -0
  117. package/dist/chunk-P5KFWM4H.js +98 -0
  118. package/dist/chunk-PUMLE7RJ.js +1711 -0
  119. package/dist/chunk-Q4MFANBF.js +282 -0
  120. package/dist/chunk-QLEKZMMU.js +282 -0
  121. package/dist/chunk-RGGNGVO3.js +98 -0
  122. package/dist/chunk-RKJDRVV6.js +443 -0
  123. package/dist/chunk-S5BHU353.js +43 -0
  124. package/dist/chunk-SHQUSFH7.js +1426 -0
  125. package/dist/chunk-SMB4DBMD.js +182 -0
  126. package/dist/chunk-SNYHQP3D.js +743 -0
  127. package/dist/chunk-T24L3TBF.js +1717 -0
  128. package/dist/chunk-TAQNSOKT.js +692 -0
  129. package/dist/chunk-TDNY4SUA.js +41 -0
  130. package/dist/chunk-TNNF56IQ.js +1750 -0
  131. package/dist/chunk-TR7E6LYX.js +457 -0
  132. package/dist/chunk-URWUFH45.js +98 -0
  133. package/dist/chunk-UUSIH3XH.js +1429 -0
  134. package/dist/chunk-UYFNXLKR.js +1436 -0
  135. package/dist/chunk-V6F7KUWD.js +270 -0
  136. package/dist/chunk-VCZLXRMR.js +254 -0
  137. package/dist/chunk-VDHXSSBT.js +1426 -0
  138. package/dist/chunk-VM4QMKVK.js +254 -0
  139. package/dist/chunk-VWGYKYL2.js +737 -0
  140. package/dist/chunk-VX2OFBJN.js +1426 -0
  141. package/dist/chunk-VXVIE6DG.js +84 -0
  142. package/dist/chunk-W4OH7HG4.js +40 -0
  143. package/dist/chunk-WBVJX4GZ.js +98 -0
  144. package/dist/chunk-WDU2ZV4I.js +1426 -0
  145. package/dist/chunk-X6VUCICU.js +457 -0
  146. package/dist/chunk-XAY7FM7Y.js +618 -0
  147. package/dist/chunk-XJZ5Z2CM.js +642 -0
  148. package/dist/chunk-XKVFQTJJ.js +254 -0
  149. package/dist/chunk-XRLFASCY.js +22 -0
  150. package/dist/chunk-XYU6TZOW.js +182 -0
  151. package/dist/chunk-Y745CBVB.js +944 -0
  152. package/dist/chunk-YLBJSXYY.js +944 -0
  153. package/dist/chunk-YQJIKVPZ.js +1429 -0
  154. package/dist/chunk-YRM2VCZF.js +457 -0
  155. package/dist/chunk-YS33KBVJ.js +944 -0
  156. package/dist/chunk-Z27DZPDG.js +41 -0
  157. package/dist/chunk-ZXQ5NAEN.js +32 -0
  158. package/dist/contracts-B552GopR.d.cts +245 -0
  159. package/dist/contracts-B552GopR.d.ts +245 -0
  160. package/dist/contracts-Bg1ECISC.d.cts +245 -0
  161. package/dist/contracts-Bg1ECISC.d.ts +245 -0
  162. package/dist/contracts-CMriKJ6P.d.cts +245 -0
  163. package/dist/contracts-CMriKJ6P.d.ts +245 -0
  164. package/dist/contracts-DOrhwbke.d.cts +245 -0
  165. package/dist/contracts-DOrhwbke.d.ts +245 -0
  166. package/dist/data.cjs +1373 -0
  167. package/dist/data.d.cts +434 -0
  168. package/dist/data.d.ts +434 -0
  169. package/dist/data.js +945 -0
  170. package/dist/devtools.cjs +1357 -0
  171. package/dist/devtools.d.cts +473 -0
  172. package/dist/devtools.d.ts +473 -0
  173. package/dist/devtools.js +1084 -0
  174. package/dist/ecosystem.cjs +1046 -0
  175. package/dist/ecosystem.d.cts +247 -0
  176. package/dist/ecosystem.d.ts +247 -0
  177. package/dist/ecosystem.js +369 -0
  178. package/dist/extras.cjs +8457 -0
  179. package/dist/extras.d.cts +2356 -0
  180. package/dist/extras.d.ts +2356 -0
  181. package/dist/extras.js +5152 -0
  182. package/dist/index.cjs +2648 -0
  183. package/dist/index.d.cts +869 -0
  184. package/dist/index.d.ts +869 -0
  185. package/dist/index.js +386 -0
  186. package/dist/motion.cjs +604 -0
  187. package/dist/motion.d.cts +146 -0
  188. package/dist/motion.d.ts +146 -0
  189. package/dist/motion.js +346 -0
  190. package/dist/patterns.cjs +815 -0
  191. package/dist/patterns.d.cts +163 -0
  192. package/dist/patterns.d.ts +163 -0
  193. package/dist/patterns.js +296 -0
  194. package/dist/performance.cjs +927 -0
  195. package/dist/performance.d.cts +416 -0
  196. package/dist/performance.d.ts +416 -0
  197. package/dist/performance.js +654 -0
  198. package/dist/plugins.cjs +2487 -0
  199. package/dist/plugins.d.cts +393 -0
  200. package/dist/plugins.d.ts +393 -0
  201. package/dist/plugins.js +1504 -0
  202. package/dist/signal-BnWpq6WB.d.cts +5 -0
  203. package/dist/signal-BnWpq6WB.d.ts +5 -0
  204. package/dist/src/components/ErrorBoundary.d.ts +15 -0
  205. package/dist/src/components/ErrorBoundary.js +119 -0
  206. package/dist/src/core/catch.d.ts +11 -0
  207. package/dist/src/core/catch.js +28 -0
  208. package/dist/src/core/each.d.ts +13 -0
  209. package/dist/src/core/each.js +68 -0
  210. package/dist/src/core/for.d.ts +12 -0
  211. package/dist/src/core/for.js +67 -0
  212. package/dist/src/core/html.d.ts +137 -0
  213. package/dist/src/core/html.js +155 -0
  214. package/dist/src/core/htmlIf.d.ts +11 -0
  215. package/dist/src/core/htmlIf.js +18 -0
  216. package/dist/src/core/lazy.d.ts +7 -0
  217. package/dist/src/core/lazy.js +16 -0
  218. package/dist/src/core/mount.d.ts +7 -0
  219. package/dist/src/core/mount.js +12 -0
  220. package/dist/src/core/slots.d.ts +3 -0
  221. package/dist/src/core/slots.js +3 -0
  222. package/dist/src/core/suspense.d.ts +10 -0
  223. package/dist/src/core/suspense.js +33 -0
  224. package/dist/src/core/tagFactory.d.ts +13 -0
  225. package/dist/src/core/tagFactory.js +86 -0
  226. package/dist/src/core/test.d.ts +11 -0
  227. package/dist/src/core/test.js +28 -0
  228. package/dist/src/core/types.d.ts +2 -0
  229. package/dist/src/core/types.js +1 -0
  230. package/dist/src/core/useComputed.d.ts +6 -0
  231. package/dist/src/core/useComputed.js +30 -0
  232. package/dist/src/core/useEffect.d.ts +6 -0
  233. package/dist/src/core/useEffect.js +23 -0
  234. package/dist/src/core/useState.d.ts +10 -0
  235. package/dist/src/core/useState.js +34 -0
  236. package/dist/src/core/useStore.d.ts +19 -0
  237. package/dist/src/core/useStore.js +53 -0
  238. package/dist/src/core/useWatch.d.ts +8 -0
  239. package/dist/src/core/useWatch.js +23 -0
  240. package/dist/src/plugins/i18n.d.ts +6 -0
  241. package/dist/src/plugins/i18n.js +16 -0
  242. package/dist/src/plugins/router.d.ts +188 -0
  243. package/dist/src/plugins/router.js +1178 -0
  244. package/dist/src/reactivity/bindAttribute.d.ts +5 -0
  245. package/dist/src/reactivity/bindAttribute.js +31 -0
  246. package/dist/src/reactivity/bindChildNode.d.ts +10 -0
  247. package/dist/src/reactivity/bindChildNode.js +46 -0
  248. package/dist/src/reactivity/bindTextNode.d.ts +10 -0
  249. package/dist/src/reactivity/bindTextNode.js +27 -0
  250. package/dist/src/reactivity/signal.d.ts +3 -0
  251. package/dist/src/reactivity/signal.js +1 -0
  252. package/dist/src/reactivity/track.d.ts +18 -0
  253. package/dist/src/reactivity/track.js +73 -0
  254. package/dist/src/reactivity/useComputed.d.ts +6 -0
  255. package/dist/src/reactivity/useComputed.js +30 -0
  256. package/dist/src/reactivity/useEffect.d.ts +6 -0
  257. package/dist/src/reactivity/useEffect.js +23 -0
  258. package/dist/src/reactivity/useState.d.ts +10 -0
  259. package/dist/src/reactivity/useState.js +34 -0
  260. package/dist/src/reactivity/useStore.d.ts +19 -0
  261. package/dist/src/reactivity/useStore.js +53 -0
  262. package/dist/src/reactivity/useWatch.d.ts +8 -0
  263. package/dist/src/reactivity/useWatch.js +23 -0
  264. package/dist/src/utils/sanitize.d.ts +1 -0
  265. package/dist/src/utils/sanitize.js +8 -0
  266. package/dist/ssr-27FOM46T.js +35 -0
  267. package/dist/ssr-GFUTTSJD.js +22 -0
  268. package/dist/ssr-K7DCR6BZ.js +35 -0
  269. package/dist/ssr-O6LFMRFP.js +35 -0
  270. package/dist/ssr-QZEVGMMK.js +35 -0
  271. package/dist/ssr-SGVBCAGC.js +35 -0
  272. package/dist/ssr-UB2IXCYX.js +35 -0
  273. package/dist/ssr-XBZQNV4O.js +22 -0
  274. package/dist/ssr-Y76FSXDU.js +35 -0
  275. package/dist/ssr-YQJ4AYBD.js +35 -0
  276. package/dist/ssr.cjs +1757 -0
  277. package/dist/ssr.d.cts +478 -0
  278. package/dist/ssr.d.ts +478 -0
  279. package/dist/ssr.js +743 -0
  280. package/dist/tagFactory-CZPO4RXF.d.cts +34 -0
  281. package/dist/tagFactory-CZPO4RXF.d.ts +34 -0
  282. package/dist/tagFactory-CgImPVMY.d.cts +22 -0
  283. package/dist/tagFactory-CgImPVMY.d.ts +22 -0
  284. package/dist/tagFactory-Cw1iv5if.d.cts +22 -0
  285. package/dist/tagFactory-Cw1iv5if.d.ts +22 -0
  286. package/dist/tagFactory-DeAXq9ef.d.cts +30 -0
  287. package/dist/tagFactory-DeAXq9ef.d.ts +30 -0
  288. package/dist/tagFactory-SkY0a7L1.d.cts +22 -0
  289. package/dist/tagFactory-SkY0a7L1.d.ts +22 -0
  290. package/dist/testing.cjs +1919 -0
  291. package/dist/testing.d.cts +491 -0
  292. package/dist/testing.d.ts +491 -0
  293. package/dist/testing.js +1862 -0
  294. package/dist/ui.cjs +1497 -0
  295. package/dist/ui.d.cts +264 -0
  296. package/dist/ui.d.ts +264 -0
  297. package/dist/ui.js +900 -0
  298. package/dist/widgets.cjs +919 -0
  299. package/dist/widgets.d.cts +165 -0
  300. package/dist/widgets.d.ts +165 -0
  301. package/dist/widgets.js +545 -0
  302. package/package.json +134 -0
package/dist/build.js ADDED
@@ -0,0 +1,2478 @@
1
+ import {
2
+ index_exports
3
+ } from "./chunk-7RIIFP3E.js";
4
+ import "./chunk-6JGMNCD6.js";
5
+ import "./chunk-FWHVLMCI.js";
6
+ import "./chunk-MFHVGKET.js";
7
+ import "./chunk-ETMEC6FH.js";
8
+ import "./chunk-2ABBWCGC.js";
9
+ import "./chunk-AX5VEQTY.js";
10
+ import "./chunk-MJNB47HB.js";
11
+ import "./chunk-M5GNLDEO.js";
12
+ import "./chunk-MLKGABMK.js";
13
+
14
+ // src/build/compileTemplates.ts
15
+ var VOID_ELEMENTS = /* @__PURE__ */ new Set([
16
+ "area",
17
+ "base",
18
+ "br",
19
+ "col",
20
+ "embed",
21
+ "hr",
22
+ "img",
23
+ "input",
24
+ "link",
25
+ "meta",
26
+ "param",
27
+ "source",
28
+ "track",
29
+ "wbr"
30
+ ]);
31
+ var SVG_TAGS = /* @__PURE__ */ new Set([
32
+ "svg",
33
+ "circle",
34
+ "ellipse",
35
+ "g",
36
+ "line",
37
+ "path",
38
+ "polygon",
39
+ "polyline",
40
+ "rect",
41
+ "text",
42
+ "tspan",
43
+ "defs",
44
+ "clipPath",
45
+ "mask",
46
+ "pattern",
47
+ "linearGradient",
48
+ "radialGradient",
49
+ "stop",
50
+ "use",
51
+ "symbol",
52
+ "marker"
53
+ ]);
54
+ function findHtmlTemplates(code) {
55
+ const results = [];
56
+ const tagRegex = /\bhtml\s*`/g;
57
+ let match;
58
+ while ((match = tagRegex.exec(code)) !== null) {
59
+ const start = match.index;
60
+ const backtickStart = code.indexOf("`", start + 4);
61
+ if (backtickStart === -1) continue;
62
+ const parsed = parseTemplateLiteral(code, backtickStart);
63
+ if (!parsed) continue;
64
+ results.push({
65
+ start,
66
+ end: parsed.end,
67
+ strings: parsed.strings,
68
+ exprCount: parsed.exprCount
69
+ });
70
+ tagRegex.lastIndex = parsed.end;
71
+ }
72
+ return results;
73
+ }
74
+ function parseTemplateLiteral(code, openBacktick) {
75
+ const strings = [];
76
+ let exprCount = 0;
77
+ let pos = openBacktick + 1;
78
+ let current = "";
79
+ while (pos < code.length) {
80
+ const ch = code[pos];
81
+ if (ch === "`") {
82
+ strings.push(current);
83
+ return { end: pos + 1, strings, exprCount };
84
+ }
85
+ if (ch === "$" && pos + 1 < code.length && code[pos + 1] === "{") {
86
+ strings.push(current);
87
+ current = "";
88
+ exprCount++;
89
+ pos += 2;
90
+ let depth = 1;
91
+ while (pos < code.length && depth > 0) {
92
+ const c = code[pos];
93
+ if (c === "{") depth++;
94
+ else if (c === "}") depth--;
95
+ else if (c === '"' || c === "'" || c === "`") {
96
+ pos = skipString(code, pos);
97
+ continue;
98
+ }
99
+ if (depth > 0) pos++;
100
+ }
101
+ if (depth !== 0) return null;
102
+ pos++;
103
+ continue;
104
+ }
105
+ if (ch === "\\") {
106
+ current += code[pos] + (code[pos + 1] || "");
107
+ pos += 2;
108
+ continue;
109
+ }
110
+ current += ch;
111
+ pos++;
112
+ }
113
+ return null;
114
+ }
115
+ function skipString(code, start) {
116
+ const quote = code[start];
117
+ let pos = start + 1;
118
+ while (pos < code.length) {
119
+ if (code[pos] === "\\") {
120
+ pos += 2;
121
+ continue;
122
+ }
123
+ if (code[pos] === quote) return pos + 1;
124
+ if (quote === "`" && code[pos] === "$" && code[pos + 1] === "{") {
125
+ pos += 2;
126
+ let depth = 1;
127
+ while (pos < code.length && depth > 0) {
128
+ if (code[pos] === "{") depth++;
129
+ else if (code[pos] === "}") depth--;
130
+ else if (code[pos] === '"' || code[pos] === "'" || code[pos] === "`") {
131
+ pos = skipString(code, pos);
132
+ continue;
133
+ }
134
+ if (depth > 0) pos++;
135
+ }
136
+ pos++;
137
+ continue;
138
+ }
139
+ pos++;
140
+ }
141
+ return pos;
142
+ }
143
+ function parseTemplateToAST(strings) {
144
+ const exprCount = strings.length - 1;
145
+ let template = strings[0];
146
+ for (let i = 0; i < exprCount; i++) {
147
+ template += `\0${i}\0${strings[i + 1]}`;
148
+ }
149
+ let pos = 0;
150
+ const len = template.length;
151
+ function skipWs() {
152
+ while (pos < len && /\s/.test(template[pos])) pos++;
153
+ }
154
+ function tryExprIdx() {
155
+ if (template[pos] !== "\0") return -1;
156
+ const start = pos;
157
+ pos++;
158
+ let idxStr = "";
159
+ while (pos < len && template[pos] !== "\0") idxStr += template[pos++];
160
+ if (pos < len) pos++;
161
+ const idx = Number.parseInt(idxStr, 10);
162
+ if (Number.isNaN(idx) || idx < 0 || idx >= exprCount) {
163
+ pos = start;
164
+ return -1;
165
+ }
166
+ return idx;
167
+ }
168
+ function readTagName() {
169
+ let name = "";
170
+ while (pos < len && /[a-zA-Z0-9-]/.test(template[pos])) name += template[pos++];
171
+ return name;
172
+ }
173
+ function parseAttrValue() {
174
+ skipWs();
175
+ if (template[pos] !== "=") return { kind: "bool" };
176
+ pos++;
177
+ skipWs();
178
+ const exprIdx = tryExprIdx();
179
+ if (exprIdx >= 0) return { kind: "expr", index: exprIdx };
180
+ const quote = template[pos];
181
+ if (quote === '"' || quote === "'") {
182
+ pos++;
183
+ const parts = [];
184
+ let current = "";
185
+ while (pos < len && template[pos] !== quote) {
186
+ const innerIdx = tryExprIdx();
187
+ if (innerIdx >= 0) {
188
+ if (current) parts.push({ kind: "static", value: current });
189
+ current = "";
190
+ parts.push({ kind: "expr", index: innerIdx });
191
+ } else {
192
+ current += template[pos++];
193
+ }
194
+ }
195
+ if (pos < len) pos++;
196
+ if (current) parts.push({ kind: "static", value: current });
197
+ if (parts.length === 1 && parts[0].kind === "static") {
198
+ return { kind: "static", value: parts[0].value };
199
+ }
200
+ if (parts.some((p) => p.kind === "expr")) {
201
+ return { kind: "mixed", parts };
202
+ }
203
+ return { kind: "static", value: parts.map((p) => p.value).join("") };
204
+ }
205
+ let val = "";
206
+ while (pos < len && !/[\s>/]/.test(template[pos])) val += template[pos++];
207
+ return { kind: "static", value: val };
208
+ }
209
+ function parseAttrs() {
210
+ const attrs = [];
211
+ while (pos < len) {
212
+ skipWs();
213
+ if (template[pos] === ">" || template[pos] === "/") break;
214
+ let attrName = "";
215
+ while (pos < len && /[a-zA-Z0-9\-:_.]/.test(template[pos])) attrName += template[pos++];
216
+ if (!attrName) break;
217
+ const val = parseAttrValue();
218
+ if (attrName.startsWith("on:")) {
219
+ if (val.kind === "expr") {
220
+ attrs.push({ name: attrName.slice(3), value: { kind: "event", index: val.index } });
221
+ }
222
+ } else {
223
+ attrs.push({ name: attrName, value: val });
224
+ }
225
+ }
226
+ return attrs;
227
+ }
228
+ function collapseWs(s) {
229
+ return s.replace(/\s+/g, " ");
230
+ }
231
+ function parseTextChildren(children) {
232
+ let text = "";
233
+ while (pos < len && template[pos] !== "<") {
234
+ const idx = tryExprIdx();
235
+ if (idx >= 0) {
236
+ const collapsed2 = collapseWs(text);
237
+ if (collapsed2) children.push({ kind: "text", value: collapsed2 });
238
+ text = "";
239
+ children.push({ kind: "expr", index: idx });
240
+ } else {
241
+ text += template[pos++];
242
+ }
243
+ }
244
+ const collapsed = collapseWs(text);
245
+ if (collapsed) children.push({ kind: "text", value: collapsed });
246
+ }
247
+ function parseChildren() {
248
+ const children = [];
249
+ while (pos < len) {
250
+ if (template[pos] === "<" && pos + 1 < len && template[pos + 1] === "/") break;
251
+ if (template[pos] === "<") {
252
+ pos++;
253
+ const tag = readTagName();
254
+ const attrs = parseAttrs();
255
+ skipWs();
256
+ const isVoid = VOID_ELEMENTS.has(tag);
257
+ const isSelfClosing = template[pos] === "/";
258
+ if (isSelfClosing) pos++;
259
+ if (pos < len) pos++;
260
+ if (isVoid || isSelfClosing) {
261
+ children.push({ kind: "element", el: { tag, attrs, children: [] } });
262
+ } else {
263
+ const inner = parseChildren();
264
+ if (template[pos] === "<" && pos + 1 < len && template[pos + 1] === "/") {
265
+ pos += 2;
266
+ readTagName();
267
+ skipWs();
268
+ if (pos < len && template[pos] === ">") pos++;
269
+ }
270
+ children.push({ kind: "element", el: { tag, attrs, children: inner } });
271
+ }
272
+ } else {
273
+ parseTextChildren(children);
274
+ }
275
+ }
276
+ return children;
277
+ }
278
+ return parseChildren();
279
+ }
280
+ function generateElement(el, valuesVar) {
281
+ const tag = el.tag;
282
+ const isSvg = SVG_TAGS.has(tag);
283
+ const parts = [];
284
+ for (const attr of el.attrs) {
285
+ const v = attr.value;
286
+ switch (v.kind) {
287
+ case "static":
288
+ parts.push(`${JSON.stringify(attr.name)}: ${JSON.stringify(v.value)}`);
289
+ break;
290
+ case "expr":
291
+ parts.push(`${JSON.stringify(attr.name)}: ${valuesVar}[${v.index}]`);
292
+ break;
293
+ case "mixed": {
294
+ const concat = v.parts.map((p) => p.kind === "static" ? JSON.stringify(p.value) : `String(${valuesVar}[${p.index}])`).join(" + ");
295
+ parts.push(`${JSON.stringify(attr.name)}: ${concat}`);
296
+ break;
297
+ }
298
+ case "bool":
299
+ parts.push(`${JSON.stringify(attr.name)}: true`);
300
+ break;
301
+ case "event":
302
+ break;
303
+ }
304
+ }
305
+ const events = el.attrs.filter((a) => a.value.kind === "event");
306
+ if (events.length > 0) {
307
+ const eventEntries = events.map((a) => {
308
+ const v = a.value;
309
+ return `${JSON.stringify(a.name)}: ${valuesVar}[${v.index}]`;
310
+ });
311
+ parts.push(`on: { ${eventEntries.join(", ")} }`);
312
+ }
313
+ if (el.children.length > 0) {
314
+ const childExprs = el.children.map((c) => generateChild(c, valuesVar));
315
+ if (childExprs.length === 1) {
316
+ parts.push(`nodes: ${childExprs[0]}`);
317
+ } else {
318
+ parts.push(`nodes: [${childExprs.join(", ")}]`);
319
+ }
320
+ }
321
+ const propsStr = parts.length > 0 ? `{ ${parts.join(", ")} }` : void 0;
322
+ if (isSvg) {
323
+ return propsStr ? `__sbTagFactory(${JSON.stringify(tag)}, __sbSVG_NS)(${propsStr})` : `__sbTagFactory(${JSON.stringify(tag)}, __sbSVG_NS)({})`;
324
+ }
325
+ return propsStr ? `${tag}(${propsStr})` : `${tag}({})`;
326
+ }
327
+ function generateChild(child, valuesVar) {
328
+ switch (child.kind) {
329
+ case "element":
330
+ return generateElement(child.el, valuesVar);
331
+ case "text":
332
+ return JSON.stringify(child.value);
333
+ case "expr":
334
+ return `${valuesVar}[${child.index}]`;
335
+ }
336
+ }
337
+ function compileHtmlTemplates(code) {
338
+ const templates = findHtmlTemplates(code);
339
+ if (templates.length === 0) {
340
+ return { code: null, usedTags: /* @__PURE__ */ new Set(), usesSvg: false, compiledCount: 0 };
341
+ }
342
+ const usedTags = /* @__PURE__ */ new Set();
343
+ let usesSvg = false;
344
+ let result = code;
345
+ for (let i = templates.length - 1; i >= 0; i--) {
346
+ const tmpl = templates[i];
347
+ const ast = parseTemplateToAST(tmpl.strings);
348
+ collectTags(ast, usedTags);
349
+ if (Array.from(usedTags).some((t) => SVG_TAGS.has(t))) usesSvg = true;
350
+ const valuesVar = "__v";
351
+ const childExprs = ast.map((c) => generateChild(c, valuesVar));
352
+ let compiled;
353
+ if (tmpl.exprCount === 0) {
354
+ compiled = childExprs.length === 1 ? childExprs[0] : childExprs[0];
355
+ } else {
356
+ const body = childExprs.length === 1 ? childExprs[0] : childExprs[0];
357
+ const exprSource = extractExpressions(code, tmpl.start, tmpl.end, tmpl.exprCount);
358
+ compiled = `((${valuesVar}) => ${body})([${exprSource.join(", ")}])`;
359
+ }
360
+ result = result.slice(0, tmpl.start) + compiled + result.slice(tmpl.end);
361
+ }
362
+ return { code: result, usedTags, usesSvg, compiledCount: templates.length };
363
+ }
364
+ function collectTags(children, tags) {
365
+ for (const child of children) {
366
+ if (child.kind === "element") {
367
+ tags.add(child.el.tag);
368
+ collectTags(child.el.children, tags);
369
+ }
370
+ }
371
+ }
372
+ function extractExpressions(code, templateStart, templateEnd, count) {
373
+ const exprs = [];
374
+ const backtickStart = code.indexOf("`", templateStart + 4);
375
+ let pos = backtickStart + 1;
376
+ for (let i = 0; i < count; i++) {
377
+ while (pos < templateEnd) {
378
+ if (code[pos] === "$" && code[pos + 1] === "{") {
379
+ pos += 2;
380
+ break;
381
+ }
382
+ if (code[pos] === "\\") {
383
+ pos += 2;
384
+ continue;
385
+ }
386
+ pos++;
387
+ }
388
+ const exprStart = pos;
389
+ let depth = 1;
390
+ while (pos < templateEnd && depth > 0) {
391
+ const c = code[pos];
392
+ if (c === "{") depth++;
393
+ else if (c === "}") {
394
+ depth--;
395
+ if (depth === 0) break;
396
+ } else if (c === '"' || c === "'" || c === "`") {
397
+ pos = skipString(code, pos);
398
+ continue;
399
+ }
400
+ pos++;
401
+ }
402
+ exprs.push(code.slice(exprStart, pos).trim());
403
+ pos++;
404
+ }
405
+ return exprs;
406
+ }
407
+
408
+ // src/build/staticAnalysis.ts
409
+ var HTML_TAGS = /* @__PURE__ */ new Set([
410
+ "div",
411
+ "span",
412
+ "section",
413
+ "article",
414
+ "header",
415
+ "footer",
416
+ "nav",
417
+ "main",
418
+ "aside",
419
+ "p",
420
+ "h1",
421
+ "h2",
422
+ "h3",
423
+ "h4",
424
+ "h5",
425
+ "h6",
426
+ "blockquote",
427
+ "li",
428
+ "ol",
429
+ "ul",
430
+ "pre",
431
+ "a",
432
+ "b",
433
+ "em",
434
+ "i",
435
+ "strong",
436
+ "small",
437
+ "code",
438
+ "mark",
439
+ "img",
440
+ "br",
441
+ "hr",
442
+ "input",
443
+ "button",
444
+ "form",
445
+ "label",
446
+ "select",
447
+ "textarea",
448
+ "option",
449
+ "table",
450
+ "tbody",
451
+ "thead",
452
+ "tfoot",
453
+ "tr",
454
+ "td",
455
+ "th",
456
+ "details",
457
+ "summary",
458
+ "dialog"
459
+ ]);
460
+ var VOID_ELEMENTS2 = /* @__PURE__ */ new Set([
461
+ "br",
462
+ "hr",
463
+ "img",
464
+ "input",
465
+ "meta",
466
+ "link",
467
+ "area",
468
+ "base",
469
+ "col",
470
+ "embed",
471
+ "param",
472
+ "source",
473
+ "track",
474
+ "wbr"
475
+ ]);
476
+ function analyzeStaticTemplates(code) {
477
+ const patterns = [];
478
+ const tagCallRegex = new RegExp(`\\b(${Array.from(HTML_TAGS).join("|")})\\s*\\(\\s*\\{([^}]*)\\}\\s*\\)`, "g");
479
+ let match;
480
+ while ((match = tagCallRegex.exec(code)) !== null) {
481
+ const [fullMatch, tag, propsContent] = match;
482
+ const start = match.index;
483
+ const end = start + fullMatch.length;
484
+ if (isStaticPropsContent(propsContent)) {
485
+ const templateHtml = propsToHtml(tag, propsContent);
486
+ if (templateHtml) {
487
+ patterns.push({ original: fullMatch, tag, templateHtml, start, end });
488
+ }
489
+ }
490
+ }
491
+ return {
492
+ hasStaticPatterns: patterns.length > 0,
493
+ patterns
494
+ };
495
+ }
496
+ function isStaticPropsContent(propsContent) {
497
+ if (/=>|function\s*\(|\bref\b|\bon\s*:/.test(propsContent)) {
498
+ return false;
499
+ }
500
+ const props = propsContent.split(",").map((p) => p.trim()).filter(Boolean);
501
+ for (const prop of props) {
502
+ const colonIndex = prop.indexOf(":");
503
+ if (colonIndex === -1) continue;
504
+ const value = prop.substring(colonIndex + 1).trim();
505
+ if (!isStaticValue(value)) {
506
+ return false;
507
+ }
508
+ }
509
+ return true;
510
+ }
511
+ function isStaticValue(value) {
512
+ if (/^["'].*["']$/.test(value)) return true;
513
+ if (/^-?\d+(\.\d+)?$/.test(value)) return true;
514
+ if (value === "true" || value === "false") return true;
515
+ if (value === "null" || value === "undefined") return true;
516
+ return false;
517
+ }
518
+ function propsToHtml(tag, propsContent) {
519
+ const attrs = [];
520
+ let nodesContent = "";
521
+ const props = propsContent.split(",").map((p) => p.trim()).filter(Boolean);
522
+ for (const prop of props) {
523
+ const colonIndex = prop.indexOf(":");
524
+ if (colonIndex === -1) continue;
525
+ const key = prop.substring(0, colonIndex).trim();
526
+ let value = prop.substring(colonIndex + 1).trim();
527
+ if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
528
+ value = value.slice(1, -1);
529
+ }
530
+ if (key === "nodes") {
531
+ nodesContent = escapeHtml(value);
532
+ } else if (key === "class" || key === "id") {
533
+ attrs.push(`${key}="${escapeAttr(value)}"`);
534
+ } else if (key !== "on" && key !== "ref" && key !== "style") {
535
+ attrs.push(`${key}="${escapeAttr(String(value))}"`);
536
+ }
537
+ }
538
+ const attrStr = attrs.length > 0 ? ` ${attrs.join(" ")}` : "";
539
+ if (VOID_ELEMENTS2.has(tag)) {
540
+ return `<${tag}${attrStr} />`;
541
+ }
542
+ return `<${tag}${attrStr}>${nodesContent}</${tag}>`;
543
+ }
544
+ function escapeHtml(str) {
545
+ return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
546
+ }
547
+ function escapeAttr(str) {
548
+ return str.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
549
+ }
550
+
551
+ // src/build/vite.ts
552
+ var SVG_TAGS_SET = /* @__PURE__ */ new Set([
553
+ "svg",
554
+ "circle",
555
+ "ellipse",
556
+ "g",
557
+ "line",
558
+ "path",
559
+ "polygon",
560
+ "polyline",
561
+ "rect",
562
+ "text",
563
+ "tspan",
564
+ "defs",
565
+ "clipPath",
566
+ "mask",
567
+ "pattern",
568
+ "linearGradient",
569
+ "radialGradient",
570
+ "stop",
571
+ "use",
572
+ "symbol",
573
+ "marker"
574
+ ]);
575
+ var DEFAULT_INCLUDE = ["**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx"];
576
+ var DEFAULT_EXCLUDE = ["node_modules/**", "dist/**", "**/*.test.*", "**/*.spec.*"];
577
+ function matchesPattern(filePath, patterns) {
578
+ const normalized = filePath.replace(/\\/g, "/");
579
+ return patterns.some((pattern) => {
580
+ const regexStr = pattern.replace(/\./g, "\\.").replace(/\*\*/g, "{{GLOBSTAR}}").replace(/\*/g, "[^/]*").replace(/\{\{GLOBSTAR\}\}/g, ".*");
581
+ return new RegExp(regexStr).test(normalized);
582
+ });
583
+ }
584
+ function injectPureAnnotations(code) {
585
+ const sibuFactories = [
586
+ "tagFactory",
587
+ "context",
588
+ "composable",
589
+ "defineComponent",
590
+ "withProps",
591
+ "withDefaults",
592
+ "pure",
593
+ "noSideEffect"
594
+ ];
595
+ let result = code;
596
+ for (const factory of sibuFactories) {
597
+ const pattern = new RegExp(`(?<!/\\*#__PURE__\\*/\\s*)\\b(${factory})\\s*\\(`, "g");
598
+ result = result.replace(pattern, "/*#__PURE__*/ $1(");
599
+ }
600
+ return result;
601
+ }
602
+ function injectDevHelpers(code) {
603
+ if (code.includes('from "sibu"') || code.includes("from 'sibu'") || code.includes('from "sibu/') || code.includes("from 'sibu/")) {
604
+ return `/* SibuJS Dev Mode */
605
+ if (typeof globalThis !== 'undefined') { (globalThis as unknown as Record<string, unknown>).__SIBU_DEV__ = true; }
606
+ ${code}`;
607
+ }
608
+ return code;
609
+ }
610
+ function sibuVitePlugin(options = {}) {
611
+ const {
612
+ hmr = true,
613
+ pureAnnotations = true,
614
+ include = DEFAULT_INCLUDE,
615
+ exclude = DEFAULT_EXCLUDE,
616
+ devMode,
617
+ staticOptimize,
618
+ compileTemplates
619
+ } = options;
620
+ const isDevMode = devMode ?? (typeof process !== "undefined" && process.env?.NODE_ENV !== "production");
621
+ return {
622
+ name: "sibu-vite-plugin",
623
+ enforce: "pre",
624
+ config() {
625
+ return {
626
+ // Optimize dependency pre-bundling for sibu
627
+ optimizeDeps: {
628
+ include: ["sibu"]
629
+ },
630
+ // Ensure sibu is treated correctly for SSR
631
+ ssr: {
632
+ noExternal: ["sibu"]
633
+ },
634
+ // Define global constants for dead code elimination
635
+ define: {
636
+ __SIBU_DEV__: JSON.stringify(isDevMode),
637
+ __SIBU_HMR__: JSON.stringify(hmr)
638
+ },
639
+ // Enable source maps in dev
640
+ build: {
641
+ sourcemap: isDevMode
642
+ }
643
+ };
644
+ },
645
+ transform(code, id) {
646
+ if (!matchesPattern(id, include) || matchesPattern(id, exclude)) {
647
+ return null;
648
+ }
649
+ let transformed = code;
650
+ let modified = false;
651
+ if (pureAnnotations) {
652
+ const annotated = injectPureAnnotations(transformed);
653
+ if (annotated !== transformed) {
654
+ transformed = annotated;
655
+ modified = true;
656
+ }
657
+ }
658
+ if (isDevMode) {
659
+ const withDevHelpers = injectDevHelpers(transformed);
660
+ if (withDevHelpers !== transformed) {
661
+ transformed = withDevHelpers;
662
+ modified = true;
663
+ }
664
+ }
665
+ const shouldCompile = compileTemplates ?? !isDevMode;
666
+ if (shouldCompile && transformed.includes("html`")) {
667
+ const compiled = compileHtmlTemplates(transformed);
668
+ if (compiled.code) {
669
+ const tagImports = Array.from(compiled.usedTags).filter((t) => !SVG_TAGS_SET.has(t));
670
+ const needsSvg = compiled.usesSvg;
671
+ const imports = [];
672
+ if (tagImports.length > 0) {
673
+ imports.push(`import { ${tagImports.join(", ")} } from "sibu";`);
674
+ }
675
+ if (needsSvg) {
676
+ imports.push(`import { tagFactory as __sbTagFactory, SVG_NS as __sbSVG_NS } from "sibu";`);
677
+ }
678
+ const newImports = imports.filter((imp) => !transformed.includes(imp));
679
+ if (newImports.length > 0) {
680
+ compiled.code = `${newImports.join("\n")}
681
+ ${compiled.code}`;
682
+ }
683
+ transformed = compiled.code;
684
+ modified = true;
685
+ }
686
+ }
687
+ const shouldOptimize = staticOptimize ?? !isDevMode;
688
+ if (shouldOptimize) {
689
+ const analysis = analyzeStaticTemplates(transformed);
690
+ if (analysis.hasStaticPatterns) {
691
+ const sorted = [...analysis.patterns].sort((a, b) => b.start - a.start);
692
+ for (const pattern of sorted) {
693
+ const replacement = `staticTemplate(${JSON.stringify(pattern.templateHtml)})`;
694
+ transformed = transformed.slice(0, pattern.start) + replacement + transformed.slice(pattern.end);
695
+ }
696
+ if (!transformed.includes("import") || !transformed.includes("staticTemplate")) {
697
+ transformed = `import { staticTemplate } from "sibu";
698
+ ${transformed}`;
699
+ }
700
+ modified = true;
701
+ }
702
+ }
703
+ if (!modified) return null;
704
+ return {
705
+ code: transformed,
706
+ map: void 0
707
+ // Let Vite handle source maps
708
+ };
709
+ },
710
+ handleHotUpdate(ctx) {
711
+ if (!hmr) return;
712
+ const { file } = ctx;
713
+ if (matchesPattern(file, include) && !matchesPattern(file, exclude)) {
714
+ if (isDevMode) {
715
+ console.log(`[sibu-vite-plugin] HMR update: ${file}`);
716
+ }
717
+ return;
718
+ }
719
+ }
720
+ };
721
+ }
722
+ function createViteConfig(options = {}) {
723
+ const { entry = "src/main.ts", outDir = "dist", ssr = false, overrides = {} } = options;
724
+ const baseConfig = {
725
+ // Use the SibuJS Vite plugin
726
+ plugins: [sibuVitePlugin()],
727
+ // Build configuration
728
+ build: {
729
+ outDir,
730
+ target: "es2020",
731
+ minify: "esbuild",
732
+ sourcemap: true,
733
+ // Library mode configuration when building a library
734
+ lib: ssr ? void 0 : {
735
+ entry,
736
+ formats: ["es", "cjs"]
737
+ },
738
+ // Rollup-specific options
739
+ rollupOptions: {
740
+ input: ssr ? entry : void 0,
741
+ output: {
742
+ // Ensure consistent chunk naming
743
+ chunkFileNames: "chunks/[name]-[hash].js",
744
+ // Preserve pure annotations
745
+ generatedCode: {
746
+ constBindings: true
747
+ }
748
+ },
749
+ // Tree-shaking configuration
750
+ treeshake: {
751
+ moduleSideEffects: false,
752
+ propertyReadSideEffects: false,
753
+ annotations: true
754
+ }
755
+ }
756
+ },
757
+ // Resolve configuration
758
+ resolve: {
759
+ // Prefer ESM versions of packages
760
+ mainFields: ["module", "jsnext:main", "jsnext", "main"],
761
+ extensions: [".ts", ".tsx", ".js", ".jsx", ".json"]
762
+ },
763
+ // SSR configuration
764
+ ...ssr ? {
765
+ ssr: {
766
+ noExternal: ["sibu"],
767
+ target: "node"
768
+ },
769
+ build: {
770
+ outDir,
771
+ target: "node18",
772
+ ssr: true,
773
+ rollupOptions: {
774
+ input: entry,
775
+ output: {
776
+ format: "esm"
777
+ }
778
+ }
779
+ }
780
+ } : {},
781
+ // Optimize dependency handling
782
+ optimizeDeps: {
783
+ include: ["sibu"],
784
+ // Force pre-bundling of sibu for faster dev startup
785
+ force: false
786
+ },
787
+ // Environment variable handling
788
+ define: {
789
+ __SIBU_SSR__: JSON.stringify(ssr)
790
+ }
791
+ };
792
+ return deepMerge(baseConfig, overrides);
793
+ }
794
+ function deepMerge(target, source) {
795
+ const result = { ...target };
796
+ for (const key of Object.keys(source)) {
797
+ if (source[key] && typeof source[key] === "object" && !Array.isArray(source[key]) && target[key] && typeof target[key] === "object" && !Array.isArray(target[key])) {
798
+ result[key] = deepMerge(target[key], source[key]);
799
+ } else {
800
+ result[key] = source[key];
801
+ }
802
+ }
803
+ return result;
804
+ }
805
+
806
+ // src/build/webpack.ts
807
+ var PURE_FACTORIES = [
808
+ "tagFactory",
809
+ "context",
810
+ "composable",
811
+ "defineComponent",
812
+ "withProps",
813
+ "withDefaults",
814
+ "pure",
815
+ "noSideEffect"
816
+ ];
817
+ function addPureAnnotations(source) {
818
+ let result = source;
819
+ for (const factory of PURE_FACTORIES) {
820
+ const pattern = new RegExp(`(?<!/\\*#__PURE__\\*/\\s*)\\b(${factory})\\s*\\(`, "g");
821
+ result = result.replace(pattern, "/*#__PURE__*/ $1(");
822
+ }
823
+ return result;
824
+ }
825
+ function sibuWebpackPlugin(options = {}) {
826
+ const { pureAnnotations = true, devMode } = options;
827
+ const isDevMode = devMode ?? (typeof process !== "undefined" && process.env?.NODE_ENV !== "production");
828
+ return {
829
+ name: "SibuWebpackPlugin",
830
+ apply(compiler) {
831
+ compiler.hooks?.compilation?.tap("SibuWebpackPlugin", (compilation) => {
832
+ const comp = compilation;
833
+ if (comp.hooks?.optimizeModules) {
834
+ comp.hooks.optimizeModules.tap("SibuWebpackPlugin", () => {
835
+ });
836
+ }
837
+ });
838
+ if (pureAnnotations) {
839
+ compiler.hooks?.afterEnvironment?.tap("SibuWebpackPlugin", () => {
840
+ if (!compiler.options.module) {
841
+ compiler.options.module = { rules: [] };
842
+ }
843
+ if (!compiler.options.module.rules) {
844
+ compiler.options.module.rules = [];
845
+ }
846
+ compiler.options.module.rules.push({
847
+ test: /\.[jt]sx?$/,
848
+ exclude: /node_modules/,
849
+ enforce: "pre",
850
+ use: [
851
+ {
852
+ loader: {
853
+ // Inline loader function
854
+ ident: "sibu-pure-annotations-loader",
855
+ loader: "__sibu_inline_loader__",
856
+ options: {}
857
+ }
858
+ }
859
+ ]
860
+ });
861
+ });
862
+ }
863
+ compiler.hooks?.afterResolvers?.tap("SibuWebpackPlugin", () => {
864
+ if (!compiler.options.resolve) {
865
+ compiler.options.resolve = {};
866
+ }
867
+ if (!compiler.options.resolve.mainFields) {
868
+ compiler.options.resolve.mainFields = ["module", "main"];
869
+ }
870
+ if (!compiler.options.resolve.mainFields.includes("module")) {
871
+ compiler.options.resolve.mainFields.unshift("module");
872
+ }
873
+ });
874
+ if (isDevMode) {
875
+ compiler.hooks?.done?.tap("SibuWebpackPlugin", (stats) => {
876
+ const statsObj = stats;
877
+ const info = statsObj?.toJson?.({ modules: false, chunks: false });
878
+ if (info) {
879
+ console.log(`[SibuWebpackPlugin] Build completed in ${info.time || 0}ms`);
880
+ const warnings = info.warnings;
881
+ if (warnings?.length) {
882
+ console.log(`[SibuWebpackPlugin] ${warnings.length} warning(s)`);
883
+ }
884
+ }
885
+ });
886
+ }
887
+ compiler.hooks?.environment?.tap("SibuWebpackPlugin", () => {
888
+ if (!compiler.options.plugins) {
889
+ compiler.options.plugins = [];
890
+ }
891
+ const defines = {
892
+ __SIBU_DEV__: JSON.stringify(isDevMode)
893
+ };
894
+ compiler.__sibuDefines = defines;
895
+ });
896
+ }
897
+ };
898
+ }
899
+ function createPureAnnotationsLoader() {
900
+ return function sibuPureAnnotationsLoader(source) {
901
+ return addPureAnnotations(source);
902
+ };
903
+ }
904
+ function createWebpackConfig(options = {}) {
905
+ const { entry = "./src/index.ts", outputPath = "dist", mode = "production" } = options;
906
+ const isDev = mode === "development";
907
+ return {
908
+ mode,
909
+ entry,
910
+ output: {
911
+ path: outputPath,
912
+ filename: isDev ? "[name].js" : "[name].[contenthash:8].js",
913
+ chunkFilename: isDev ? "[name].chunk.js" : "[name].[contenthash:8].chunk.js",
914
+ clean: true,
915
+ // Use ESM output
916
+ module: true,
917
+ library: {
918
+ type: "module"
919
+ }
920
+ },
921
+ // Enable experiments for ESM output
922
+ experiments: {
923
+ outputModule: true
924
+ },
925
+ resolve: {
926
+ extensions: [".ts", ".tsx", ".js", ".jsx", ".json"],
927
+ mainFields: ["module", "main"],
928
+ alias: {}
929
+ },
930
+ module: {
931
+ rules: [
932
+ // TypeScript/JavaScript handling
933
+ {
934
+ test: /\.[jt]sx?$/,
935
+ exclude: /node_modules/,
936
+ use: [
937
+ {
938
+ // Users should configure their preferred TS loader
939
+ // (ts-loader, babel-loader, esbuild-loader, swc-loader)
940
+ loader: "ts-loader",
941
+ options: {
942
+ transpileOnly: true,
943
+ compilerOptions: {
944
+ module: "esnext",
945
+ moduleResolution: "node",
946
+ target: "es2020"
947
+ }
948
+ }
949
+ }
950
+ ]
951
+ }
952
+ ]
953
+ },
954
+ plugins: [
955
+ // SibuJS plugin for optimizations
956
+ sibuWebpackPlugin({ devMode: isDev })
957
+ ],
958
+ optimization: {
959
+ minimize: !isDev,
960
+ // Enable tree-shaking
961
+ usedExports: true,
962
+ sideEffects: true,
963
+ // Split chunks for better caching
964
+ splitChunks: isDev ? false : {
965
+ chunks: "all",
966
+ cacheGroups: {
967
+ // Separate sibu framework code into its own chunk
968
+ sibu: {
969
+ test: /[\\/]node_modules[\\/]sibu[\\/]/,
970
+ name: "sibu",
971
+ chunks: "all",
972
+ priority: 20
973
+ },
974
+ // Separate other vendor code
975
+ vendor: {
976
+ test: /[\\/]node_modules[\\/]/,
977
+ name: "vendor",
978
+ chunks: "all",
979
+ priority: 10
980
+ }
981
+ }
982
+ }
983
+ },
984
+ // Source maps
985
+ devtool: isDev ? "eval-cheap-module-source-map" : "source-map",
986
+ // Dev server configuration
987
+ devServer: isDev ? {
988
+ hot: true,
989
+ open: true,
990
+ port: 3e3,
991
+ historyApiFallback: true
992
+ } : void 0,
993
+ // Performance hints
994
+ performance: {
995
+ hints: isDev ? false : "warning",
996
+ maxEntrypointSize: 25e4,
997
+ maxAssetSize: 25e4
998
+ },
999
+ // Cache for faster rebuilds
1000
+ cache: {
1001
+ type: "filesystem",
1002
+ buildDependencies: {
1003
+ config: []
1004
+ }
1005
+ }
1006
+ };
1007
+ }
1008
+
1009
+ // src/build/cdn.ts
1010
+ var PACKAGE_NAME = "sibu";
1011
+ function registerGlobal() {
1012
+ if (typeof window === "undefined") return;
1013
+ window.Sibu = { ...index_exports };
1014
+ }
1015
+ function umdWrapper(name, factory) {
1016
+ const factoryStr = factory.toString();
1017
+ return `(function (root, factory) {
1018
+ if (typeof define === 'function' && define.amd) {
1019
+ // AMD (RequireJS)
1020
+ define([], factory);
1021
+ } else if (typeof module === 'object' && module.exports) {
1022
+ // CommonJS (Node.js)
1023
+ module.exports = factory();
1024
+ } else {
1025
+ // Browser globals
1026
+ root.${name} = factory();
1027
+ }
1028
+ }(typeof self !== 'undefined' ? self : this, ${factoryStr}));`;
1029
+ }
1030
+ var cdnUrls = {
1031
+ /**
1032
+ * Generate an unpkg CDN URL.
1033
+ * @param version - Package version (defaults to 'latest')
1034
+ */
1035
+ unpkg: (version) => `https://unpkg.com/${PACKAGE_NAME}@${version || "latest"}/dist/cdn.global.js`,
1036
+ /**
1037
+ * Generate a jsDelivr CDN URL.
1038
+ * @param version - Package version (defaults to 'latest')
1039
+ */
1040
+ jsdelivr: (version) => `https://cdn.jsdelivr.net/npm/${PACKAGE_NAME}@${version || "latest"}/dist/cdn.global.js`,
1041
+ /**
1042
+ * Generate a Skypack CDN URL (ESM-native).
1043
+ * @param version - Package version (defaults to 'latest')
1044
+ */
1045
+ skypack: (version) => `https://cdn.skypack.dev/${PACKAGE_NAME}@${version || "latest"}`,
1046
+ /**
1047
+ * Generate a complete HTML script tag for including SibuJS from a CDN.
1048
+ *
1049
+ * @param provider - CDN provider to use (defaults to 'jsdelivr')
1050
+ * @param version - Package version (defaults to 'latest')
1051
+ * @returns An HTML script tag string
1052
+ *
1053
+ * @example
1054
+ * ```ts
1055
+ * cdnUrls.scriptTag('jsdelivr', '1.0.0')
1056
+ * // => '<script src="https://cdn.jsdelivr.net/npm/sibu@1.0.0/dist/cdn.global.js"></script>'
1057
+ * ```
1058
+ */
1059
+ scriptTag: (provider = "jsdelivr", version) => {
1060
+ const url = cdnUrls[provider](version);
1061
+ if (provider === "skypack") {
1062
+ return `<script type="module">
1063
+ import * as Sibu from '${url}';
1064
+ window.Sibu = Sibu;
1065
+ </script>`;
1066
+ }
1067
+ return `<script src="${url}"></script>`;
1068
+ }
1069
+ };
1070
+ function generateImportMap(baseUrl) {
1071
+ const base = baseUrl || `https://cdn.jsdelivr.net/npm/${PACKAGE_NAME}@latest`;
1072
+ const imports = {
1073
+ // Main package entry
1074
+ [PACKAGE_NAME]: `${base}/dist/index.js`,
1075
+ // Sub-path imports for tree-shaking in browsers
1076
+ [`${PACKAGE_NAME}/core`]: `${base}/dist/core/index.js`,
1077
+ [`${PACKAGE_NAME}/reactivity`]: `${base}/dist/reactivity/index.js`,
1078
+ [`${PACKAGE_NAME}/plugins`]: `${base}/dist/plugins/index.js`,
1079
+ [`${PACKAGE_NAME}/components`]: `${base}/dist/components/index.js`,
1080
+ [`${PACKAGE_NAME}/testing`]: `${base}/dist/testing/index.js`,
1081
+ [`${PACKAGE_NAME}/build`]: `${base}/dist/build/index.js`
1082
+ };
1083
+ return {
1084
+ imports,
1085
+ /**
1086
+ * Serialize the import map to a JSON string.
1087
+ */
1088
+ toJSON() {
1089
+ return JSON.stringify({ imports }, null, 2);
1090
+ },
1091
+ /**
1092
+ * Generate a complete `<script type="importmap">` tag.
1093
+ */
1094
+ toScriptTag() {
1095
+ return `<script type="importmap">
1096
+ ${JSON.stringify({ imports }, null, 2)}
1097
+ </script>`;
1098
+ }
1099
+ };
1100
+ }
1101
+
1102
+ // src/build/declarations.ts
1103
+ var RECOMMENDED_OPTIONS = {
1104
+ target: "ES2020",
1105
+ module: "ESNext",
1106
+ moduleResolution: "bundler",
1107
+ strict: true,
1108
+ esModuleInterop: true,
1109
+ skipLibCheck: true,
1110
+ declaration: true,
1111
+ declarationMap: true,
1112
+ sourceMap: true,
1113
+ jsx: "preserve",
1114
+ lib: ["ES2020", "DOM", "DOM.Iterable"],
1115
+ isolatedModules: true,
1116
+ resolveJsonModule: true,
1117
+ allowSyntheticDefaultImports: true,
1118
+ forceConsistentCasingInFileNames: true,
1119
+ noUncheckedIndexedAccess: true,
1120
+ noEmit: false
1121
+ };
1122
+ var REQUIRED_OPTIONS = {
1123
+ strict: {
1124
+ value: true,
1125
+ reason: "SibuJS relies on strict type checking for safe reactive state handling."
1126
+ },
1127
+ esModuleInterop: {
1128
+ value: true,
1129
+ reason: "Required for correct ESM interop with SibuJS module exports."
1130
+ },
1131
+ moduleResolution: {
1132
+ value: ["node", "bundler", "node16", "nodenext"],
1133
+ reason: "SibuJS requires a module resolution strategy that supports package.json exports."
1134
+ }
1135
+ };
1136
+ var SUGGESTED_OPTIONS = {
1137
+ declarationMap: {
1138
+ value: true,
1139
+ reason: 'Enables "Go to Definition" to navigate to SibuJS source files in your IDE.'
1140
+ },
1141
+ sourceMap: {
1142
+ value: true,
1143
+ reason: "Enables source map debugging for SibuJS components."
1144
+ },
1145
+ noUncheckedIndexedAccess: {
1146
+ value: true,
1147
+ reason: "Improves type safety when accessing reactive state objects."
1148
+ },
1149
+ isolatedModules: {
1150
+ value: true,
1151
+ reason: "Required for compatibility with esbuild/swc transpilers used by Vite."
1152
+ }
1153
+ };
1154
+ function generateTsConfig(options) {
1155
+ const { target = "ES2020", outDir = "dist", declarationMap = true, paths } = options || {};
1156
+ const compilerOptions = {
1157
+ ...RECOMMENDED_OPTIONS,
1158
+ target,
1159
+ outDir,
1160
+ declarationMap
1161
+ };
1162
+ if (paths && Object.keys(paths).length > 0) {
1163
+ compilerOptions.baseUrl = ".";
1164
+ compilerOptions.paths = {
1165
+ // Default sibu alias
1166
+ sibu: ["node_modules/sibu/dist/index.d.ts"],
1167
+ "sibu/*": ["node_modules/sibu/dist/*"],
1168
+ // User-provided paths
1169
+ ...paths
1170
+ };
1171
+ }
1172
+ return {
1173
+ compilerOptions,
1174
+ include: ["src/**/*.ts", "src/**/*.tsx"],
1175
+ exclude: ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"]
1176
+ };
1177
+ }
1178
+ function validateTsConfig(config) {
1179
+ const warnings = [];
1180
+ const suggestions = [];
1181
+ const compilerOptions = config.compilerOptions || {};
1182
+ for (const [option, requirement] of Object.entries(REQUIRED_OPTIONS)) {
1183
+ const currentValue = compilerOptions[option];
1184
+ if (Array.isArray(requirement.value)) {
1185
+ if (currentValue === void 0) {
1186
+ warnings.push(
1187
+ `Missing required option "${option}". ${requirement.reason} Recommended value: one of ${requirement.value.map((v) => `"${v}"`).join(", ")}.`
1188
+ );
1189
+ } else if (!requirement.value.includes(currentValue)) {
1190
+ warnings.push(
1191
+ `Option "${option}" is set to "${currentValue}" which may not be compatible with SibuJS. ${requirement.reason} Recommended: one of ${requirement.value.map((v) => `"${v}"`).join(", ")}.`
1192
+ );
1193
+ }
1194
+ } else {
1195
+ if (currentValue === void 0) {
1196
+ warnings.push(
1197
+ `Missing required option "${option}". ${requirement.reason} Recommended value: ${JSON.stringify(requirement.value)}.`
1198
+ );
1199
+ } else if (currentValue !== requirement.value) {
1200
+ warnings.push(
1201
+ `Option "${option}" is set to ${JSON.stringify(currentValue)} but SibuJS recommends ${JSON.stringify(requirement.value)}. ${requirement.reason}`
1202
+ );
1203
+ }
1204
+ }
1205
+ }
1206
+ for (const [option, suggestion] of Object.entries(SUGGESTED_OPTIONS)) {
1207
+ const currentValue = compilerOptions[option];
1208
+ if (currentValue === void 0 || currentValue !== suggestion.value) {
1209
+ suggestions.push(`Consider setting "${option}" to ${JSON.stringify(suggestion.value)}. ${suggestion.reason}`);
1210
+ }
1211
+ }
1212
+ const target = typeof compilerOptions.target === "string" ? compilerOptions.target.toUpperCase() : void 0;
1213
+ if (target) {
1214
+ const es2020Plus = ["ES2020", "ES2021", "ES2022", "ES2023", "ES2024", "ESNEXT"];
1215
+ if (!es2020Plus.includes(target)) {
1216
+ warnings.push(
1217
+ `Target "${target}" may not support all features used by SibuJS. Recommended: "ES2020" or newer. SibuJS uses optional chaining, nullish coalescing, and other ES2020+ features.`
1218
+ );
1219
+ }
1220
+ }
1221
+ const module = typeof compilerOptions.module === "string" ? compilerOptions.module.toLowerCase() : void 0;
1222
+ if (module && !["esnext", "es2020", "es2022", "node16", "nodenext"].includes(module)) {
1223
+ suggestions.push(
1224
+ `Module "${compilerOptions.module}" may not provide optimal results with SibuJS. Consider using "ESNext" for best tree-shaking and bundle optimization.`
1225
+ );
1226
+ }
1227
+ const lib = compilerOptions.lib;
1228
+ if (Array.isArray(lib)) {
1229
+ const hasDom = lib.some((l) => l.toUpperCase() === "DOM" || l.toUpperCase() === "DOM.ITERABLE");
1230
+ if (!hasDom) {
1231
+ suggestions.push(
1232
+ 'The "lib" array does not include "DOM". SibuJS requires DOM types for component rendering. Add "DOM" and "DOM.Iterable" to your lib array.'
1233
+ );
1234
+ }
1235
+ }
1236
+ if (Array.isArray(config.include)) {
1237
+ const includesTs = config.include.some(
1238
+ (pattern) => pattern.includes(".ts") || pattern.includes("*")
1239
+ );
1240
+ if (!includesTs) {
1241
+ suggestions.push(
1242
+ 'Your "include" patterns may not capture TypeScript files. Ensure patterns like "src/**/*.ts" are included.'
1243
+ );
1244
+ }
1245
+ }
1246
+ return {
1247
+ valid: warnings.length === 0,
1248
+ warnings,
1249
+ suggestions
1250
+ };
1251
+ }
1252
+
1253
+ // src/build/analyzer.ts
1254
+ var moduleSizes = {
1255
+ // Core modules
1256
+ "core/html": 1800,
1257
+ "core/mount": 120,
1258
+ "core/each": 450,
1259
+ "core/slots": 200,
1260
+ "core/fragment": 180,
1261
+ "core/catch": 280,
1262
+ "core/portal": 350,
1263
+ "core/directives": 520,
1264
+ "core/dynamic": 380,
1265
+ "core/head": 300,
1266
+ "core/ssr": 1200,
1267
+ "core/customElement": 650,
1268
+ "core/scopedStyle": 480,
1269
+ "core/domRecycler": 420,
1270
+ "core/bundleOptimize": 200,
1271
+ "core/compiled": 350,
1272
+ "core/normalize": 280,
1273
+ "core/reactiveAttr": 320,
1274
+ "core/componentProps": 400,
1275
+ "core/contracts": 350,
1276
+ "core/worker": 550,
1277
+ "core/wasm": 480,
1278
+ "core/concurrent": 600,
1279
+ "core/microfrontend": 700,
1280
+ "core/chunkLoader": 450,
1281
+ "core/versioning": 300,
1282
+ "core/ecosystem": 250,
1283
+ // Signals
1284
+ "core/signal": 280,
1285
+ "core/effect": 350,
1286
+ "core/derived": 250,
1287
+ "core/watch": 300,
1288
+ "core/store": 380,
1289
+ "core/ref": 150,
1290
+ "core/memo": 180,
1291
+ "core/memoFn": 160,
1292
+ "core/array": 420,
1293
+ "core/deepSignal": 500,
1294
+ "core/lifecycle": 300,
1295
+ "core/context": 350,
1296
+ "core/persist": 400,
1297
+ "core/primitives": 200,
1298
+ "core/hoc": 280,
1299
+ "core/transition": 600,
1300
+ "core/form": 750,
1301
+ "core/globalStore": 450,
1302
+ "core/machine": 550,
1303
+ "core/optimistic": 380,
1304
+ "core/timeTravel": 500,
1305
+ "core/scheduler": 350,
1306
+ "core/plugin": 300,
1307
+ "core/virtualList": 800,
1308
+ "core/intersection": 350,
1309
+ "core/inputMask": 450,
1310
+ "core/a11y": 500,
1311
+ "core/debug": 400,
1312
+ "core/serviceWorker": 350,
1313
+ "core/composable": 280,
1314
+ // Reactivity
1315
+ "reactivity/signal": 100,
1316
+ "reactivity/track": 250,
1317
+ "reactivity/batch": 200,
1318
+ "reactivity/bindAttribute": 300,
1319
+ "reactivity/bindChildNode": 250,
1320
+ "reactivity/bindTextNode": 200,
1321
+ // Components
1322
+ "components/ErrorBoundary": 350,
1323
+ "components/Loading": 250,
1324
+ // Plugins
1325
+ "plugins/i18n": 600,
1326
+ "plugins/router": 900,
1327
+ "plugins/routerSSR": 500,
1328
+ // Build utilities
1329
+ "build/vite": 800,
1330
+ "build/webpack": 750,
1331
+ "build/cdn": 400,
1332
+ "build/declarations": 500,
1333
+ "build/analyzer": 600,
1334
+ // Testing
1335
+ "testing/index": 700,
1336
+ "testing/e2e": 500
1337
+ };
1338
+ function formatBytes(bytes) {
1339
+ if (bytes < 1024) return `${bytes} B`;
1340
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(2)} KB`;
1341
+ return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
1342
+ }
1343
+ function analyzeBundle(modules) {
1344
+ const sizes = {};
1345
+ let totalSize = 0;
1346
+ for (const [name, source] of Object.entries(modules)) {
1347
+ let byteLength;
1348
+ if (typeof TextEncoder !== "undefined") {
1349
+ byteLength = new TextEncoder().encode(source).length;
1350
+ } else {
1351
+ byteLength = source.length;
1352
+ }
1353
+ sizes[name] = byteLength;
1354
+ totalSize += byteLength;
1355
+ }
1356
+ const sorted = Object.entries(sizes).map(([name, size]) => ({
1357
+ name,
1358
+ size,
1359
+ percentage: totalSize > 0 ? size / totalSize * 100 : 0
1360
+ })).sort((a, b) => b.size - a.size);
1361
+ return {
1362
+ totalSize,
1363
+ moduleSizes: sizes,
1364
+ sorted,
1365
+ report() {
1366
+ const lines = [
1367
+ "=== SibuJS Bundle Analysis ===",
1368
+ "",
1369
+ `Total size: ${formatBytes(totalSize)}`,
1370
+ `Modules: ${sorted.length}`,
1371
+ "",
1372
+ "Module breakdown:",
1373
+ "-".repeat(60)
1374
+ ];
1375
+ for (const entry of sorted) {
1376
+ const sizeStr = formatBytes(entry.size).padStart(10);
1377
+ const pctStr = `${entry.percentage.toFixed(1)}%`.padStart(6);
1378
+ const bar = generateBar(entry.percentage, 20);
1379
+ lines.push(` ${sizeStr} ${pctStr} ${bar} ${entry.name}`);
1380
+ }
1381
+ lines.push("-".repeat(60));
1382
+ return lines.join("\n");
1383
+ }
1384
+ };
1385
+ }
1386
+ function generateBar(percentage, width) {
1387
+ const filled = Math.round(percentage / 100 * width);
1388
+ const empty = width - filled;
1389
+ return `[${"#".repeat(filled)}${".".repeat(empty)}]`;
1390
+ }
1391
+ function estimateImportSize(imports) {
1392
+ const breakdown = {};
1393
+ let estimated = 0;
1394
+ const implicitDeps = ["reactivity/signal", "reactivity/track"];
1395
+ const allImports = [.../* @__PURE__ */ new Set([...implicitDeps, ...imports])];
1396
+ for (const importPath of allImports) {
1397
+ const size = moduleSizes[importPath];
1398
+ if (size !== void 0) {
1399
+ breakdown[importPath] = size;
1400
+ estimated += size;
1401
+ } else {
1402
+ const avgSize = 350;
1403
+ breakdown[importPath] = avgSize;
1404
+ estimated += avgSize;
1405
+ }
1406
+ }
1407
+ const sortedEntries = Object.entries(breakdown).sort(([, a], [, b]) => b - a);
1408
+ const lines = [`Estimated bundle size: ${formatBytes(estimated)} (minified + gzipped)`, ""];
1409
+ for (const [modulePath, size] of sortedEntries) {
1410
+ const known = moduleSizes[modulePath] !== void 0;
1411
+ lines.push(` ${modulePath}: ${formatBytes(size)}${known ? "" : " (estimated)"}`);
1412
+ }
1413
+ if (imports.length > 0) {
1414
+ lines.push("");
1415
+ lines.push("Note: Actual sizes may vary based on tree-shaking and build configuration.");
1416
+ lines.push("Implicit dependencies (reactivity/signal, reactivity/track) are included.");
1417
+ }
1418
+ return {
1419
+ estimated,
1420
+ breakdown,
1421
+ formatted: lines.join("\n")
1422
+ };
1423
+ }
1424
+
1425
+ // src/build/linting.ts
1426
+ function getLineNumber(source, index) {
1427
+ let line = 1;
1428
+ for (let i = 0; i < index && i < source.length; i++) {
1429
+ if (source[i] === "\n") line++;
1430
+ }
1431
+ return line;
1432
+ }
1433
+ function getColumnNumber(source, index) {
1434
+ let col = 1;
1435
+ for (let i = index - 1; i >= 0; i--) {
1436
+ if (source[i] === "\n") break;
1437
+ col++;
1438
+ }
1439
+ return col;
1440
+ }
1441
+ var lintRules = {
1442
+ /** Detect signal inside loops or conditionals */
1443
+ "no-signals-in-conditionals": {
1444
+ name: "no-signals-in-conditionals",
1445
+ description: "Signal functions should not be called inside conditionals, loops, or nested functions",
1446
+ check(source) {
1447
+ const violations = [];
1448
+ const hookNames = ["signal", "effect", "derived", "memo", "memoFn", "ref", "watch", "store"];
1449
+ const hookPattern = new RegExp(`\\b(${hookNames.join("|")})\\s*\\(`, "g");
1450
+ const lines = source.split("\n");
1451
+ for (let lineIdx = 0; lineIdx < lines.length; lineIdx++) {
1452
+ const line = lines[lineIdx];
1453
+ const trimmed = line.trim();
1454
+ if (trimmed.startsWith("import ")) continue;
1455
+ hookPattern.lastIndex = 0;
1456
+ const hookMatch = hookPattern.exec(line);
1457
+ if (!hookMatch) continue;
1458
+ const hookName = hookMatch[1];
1459
+ let braceDepth = 0;
1460
+ let insideConditionalOrLoop = false;
1461
+ let insideNestedFunction = false;
1462
+ let functionDepth = 0;
1463
+ for (let i = 0; i <= lineIdx; i++) {
1464
+ const scanLine = lines[i].trim();
1465
+ if (/\b(function\s+\w+|function\s*\(|=>\s*\{)/.test(scanLine) && i < lineIdx) {
1466
+ functionDepth++;
1467
+ }
1468
+ if (i < lineIdx && /^\s*(if|else\s+if|else|for|while|do|switch)\s*[({]/.test(lines[i])) {
1469
+ insideConditionalOrLoop = true;
1470
+ }
1471
+ for (const ch of lines[i]) {
1472
+ if (ch === "{") braceDepth++;
1473
+ if (ch === "}") {
1474
+ braceDepth--;
1475
+ if (braceDepth <= 1) {
1476
+ insideConditionalOrLoop = false;
1477
+ }
1478
+ }
1479
+ }
1480
+ }
1481
+ const beforeHook = line.substring(0, line.indexOf(hookMatch[0]));
1482
+ const inlineConditional = /\b(if|else|for|while|switch)\s*\(/.test(beforeHook) || /\?\s*$/.test(beforeHook.trim());
1483
+ if (insideConditionalOrLoop || inlineConditional) {
1484
+ violations.push({
1485
+ rule: "no-signals-in-conditionals",
1486
+ message: `"${hookName}" should not be called inside a conditional or loop. Signal functions must be called at the top level of a component.`,
1487
+ severity: "error",
1488
+ line: lineIdx + 1,
1489
+ column: (hookMatch.index || 0) + 1
1490
+ });
1491
+ }
1492
+ if (functionDepth > 1) {
1493
+ insideNestedFunction = true;
1494
+ }
1495
+ if (insideNestedFunction) {
1496
+ violations.push({
1497
+ rule: "no-signals-in-conditionals",
1498
+ message: `"${hookName}" should not be called inside a nested function. Signal functions must be called at the top level of a component.`,
1499
+ severity: "error",
1500
+ line: lineIdx + 1,
1501
+ column: (hookMatch.index || 0) + 1
1502
+ });
1503
+ }
1504
+ }
1505
+ return violations;
1506
+ }
1507
+ },
1508
+ /** Detect missing cleanup in effect */
1509
+ "effect-cleanup": {
1510
+ name: "effect-cleanup",
1511
+ description: "effect with subscriptions or timers should return a cleanup function",
1512
+ check(source) {
1513
+ const violations = [];
1514
+ const subscriptionPatterns = [
1515
+ "addEventListener",
1516
+ "setTimeout",
1517
+ "setInterval",
1518
+ "requestAnimationFrame",
1519
+ "subscribe",
1520
+ "observe",
1521
+ "WebSocket",
1522
+ "EventSource"
1523
+ ];
1524
+ const effectRegex = /\beffect\s*\(\s*((?:function\s*\(?\)?\s*\{|\(\s*\)\s*=>\s*\{|(?=\(\))))/g;
1525
+ let match;
1526
+ while ((match = effectRegex.exec(source)) !== null) {
1527
+ const startIndex = match.index;
1528
+ const line = getLineNumber(source, startIndex);
1529
+ const column = getColumnNumber(source, startIndex);
1530
+ const bodyStart = source.indexOf("{", match.index + match[0].length - 1);
1531
+ if (bodyStart === -1) continue;
1532
+ let depth = 0;
1533
+ let bodyEnd = bodyStart;
1534
+ for (let i = bodyStart; i < source.length; i++) {
1535
+ if (source[i] === "{") depth++;
1536
+ if (source[i] === "}") {
1537
+ depth--;
1538
+ if (depth === 0) {
1539
+ bodyEnd = i;
1540
+ break;
1541
+ }
1542
+ }
1543
+ }
1544
+ const effectBody = source.substring(bodyStart, bodyEnd + 1);
1545
+ const hasSubscription = subscriptionPatterns.some((p) => effectBody.includes(p));
1546
+ if (hasSubscription) {
1547
+ const hasRemoveListener = effectBody.includes("removeEventListener");
1548
+ const hasClearTimeout = effectBody.includes("clearTimeout");
1549
+ const hasClearInterval = effectBody.includes("clearInterval");
1550
+ const hasCancelRAF = effectBody.includes("cancelAnimationFrame");
1551
+ const hasUnsubscribe = effectBody.includes("unsubscribe") || effectBody.includes("disconnect") || effectBody.includes(".close(");
1552
+ const hasReturnCleanup = /return\s+/.test(effectBody);
1553
+ const hasCleanup = hasRemoveListener || hasClearTimeout || hasClearInterval || hasCancelRAF || hasUnsubscribe || hasReturnCleanup;
1554
+ if (!hasCleanup) {
1555
+ const foundSubscriptions = [];
1556
+ for (const pattern of subscriptionPatterns) {
1557
+ if (effectBody.includes(pattern)) {
1558
+ foundSubscriptions.push(pattern);
1559
+ }
1560
+ }
1561
+ violations.push({
1562
+ rule: "effect-cleanup",
1563
+ message: `effect uses ${foundSubscriptions.join(", ")} but does not appear to clean up. Consider returning a cleanup function.`,
1564
+ severity: "warning",
1565
+ line,
1566
+ column
1567
+ });
1568
+ }
1569
+ }
1570
+ }
1571
+ return violations;
1572
+ }
1573
+ },
1574
+ /** Detect direct DOM mutation outside of reactive context */
1575
+ "no-direct-dom-mutation": {
1576
+ name: "no-direct-dom-mutation",
1577
+ description: "Avoid direct DOM mutations; use reactive bindings instead",
1578
+ check(source) {
1579
+ const violations = [];
1580
+ const mutationPatterns = [
1581
+ {
1582
+ pattern: /\.innerHTML\s*=/g,
1583
+ name: "innerHTML assignment",
1584
+ suggestion: "Use reactive nodes or bindChildNode instead"
1585
+ },
1586
+ {
1587
+ pattern: /\.outerHTML\s*=/g,
1588
+ name: "outerHTML assignment",
1589
+ suggestion: "Use reactive component rendering instead"
1590
+ },
1591
+ {
1592
+ pattern: /document\.write\s*\(/g,
1593
+ name: "document.write()",
1594
+ suggestion: "Use mount() or component rendering instead"
1595
+ },
1596
+ {
1597
+ pattern: /\.insertAdjacentHTML\s*\(/g,
1598
+ name: "insertAdjacentHTML()",
1599
+ suggestion: "Use reactive nodes or each() instead"
1600
+ }
1601
+ ];
1602
+ const lines = source.split("\n");
1603
+ for (let lineIdx = 0; lineIdx < lines.length; lineIdx++) {
1604
+ const line = lines[lineIdx];
1605
+ const trimmed = line.trim();
1606
+ if (trimmed.startsWith("//") || trimmed.startsWith("*")) continue;
1607
+ for (const { pattern, name, suggestion } of mutationPatterns) {
1608
+ pattern.lastIndex = 0;
1609
+ const match = pattern.exec(line);
1610
+ if (match) {
1611
+ violations.push({
1612
+ rule: "no-direct-dom-mutation",
1613
+ message: `Direct DOM mutation via ${name} detected. ${suggestion}.`,
1614
+ severity: "warning",
1615
+ line: lineIdx + 1,
1616
+ column: (match.index || 0) + 1
1617
+ });
1618
+ }
1619
+ }
1620
+ }
1621
+ return violations;
1622
+ }
1623
+ },
1624
+ /** Detect missing key prop in each() calls */
1625
+ "each-requires-key": {
1626
+ name: "each-requires-key",
1627
+ description: "each() should include a key function for efficient reconciliation",
1628
+ check(source) {
1629
+ const violations = [];
1630
+ const eachCallRegex = /\beach\s*\(/g;
1631
+ let match;
1632
+ while ((match = eachCallRegex.exec(source)) !== null) {
1633
+ const startIndex = match.index;
1634
+ const line = getLineNumber(source, startIndex);
1635
+ const column = getColumnNumber(source, startIndex);
1636
+ const parenStart = source.indexOf("(", startIndex);
1637
+ if (parenStart === -1) continue;
1638
+ let depth = 0;
1639
+ let parenEnd = parenStart;
1640
+ for (let i = parenStart; i < source.length; i++) {
1641
+ if (source[i] === "(") depth++;
1642
+ if (source[i] === ")") {
1643
+ depth--;
1644
+ if (depth === 0) {
1645
+ parenEnd = i;
1646
+ break;
1647
+ }
1648
+ }
1649
+ }
1650
+ const callBody = source.substring(parenStart, parenEnd + 1);
1651
+ const hasKey = /\bkey\s*:/.test(callBody);
1652
+ if (!hasKey) {
1653
+ violations.push({
1654
+ rule: "each-requires-key",
1655
+ message: "each() should include a key function in the options argument (e.g., { key: item => item.id }) for efficient list reconciliation.",
1656
+ severity: "warning",
1657
+ line,
1658
+ column
1659
+ });
1660
+ }
1661
+ }
1662
+ return violations;
1663
+ }
1664
+ },
1665
+ /** Detect unused reactive state */
1666
+ "no-unused-state": {
1667
+ name: "no-unused-state",
1668
+ description: "signal variables should be used in the component",
1669
+ check(source) {
1670
+ const violations = [];
1671
+ const signalDeclRegex = /\bconst\s+\[\s*(\w+)\s*,\s*(\w+)\s*\]\s*=\s*signal\s*\(/g;
1672
+ let match;
1673
+ while ((match = signalDeclRegex.exec(source)) !== null) {
1674
+ const getterName = match[1];
1675
+ const setterName = match[2];
1676
+ const line = getLineNumber(source, match.index);
1677
+ const column = getColumnNumber(source, match.index);
1678
+ const declarationLine = source.substring(match.index, source.indexOf("\n", match.index));
1679
+ const restOfSource = source.replace(declarationLine, "");
1680
+ const getterUsageRegex = new RegExp(`\\b${escapeRegex(getterName)}\\b`, "g");
1681
+ const getterUsages = restOfSource.match(getterUsageRegex);
1682
+ const getterUsed = getterUsages !== null && getterUsages.length > 0;
1683
+ const setterUsageRegex = new RegExp(`\\b${escapeRegex(setterName)}\\b`, "g");
1684
+ const setterUsages = restOfSource.match(setterUsageRegex);
1685
+ const setterUsed = setterUsages !== null && setterUsages.length > 0;
1686
+ if (!getterUsed && !setterUsed) {
1687
+ violations.push({
1688
+ rule: "no-unused-state",
1689
+ message: `signal variable "${getterName}" and setter "${setterName}" are declared but never used. Remove unused state or use the values.`,
1690
+ severity: "warning",
1691
+ line,
1692
+ column
1693
+ });
1694
+ } else if (!getterUsed) {
1695
+ violations.push({
1696
+ rule: "no-unused-state",
1697
+ message: `signal getter "${getterName}" is declared but never read. If the value is not needed, consider using a simple variable instead of reactive state.`,
1698
+ severity: "warning",
1699
+ line,
1700
+ column
1701
+ });
1702
+ } else if (!setterUsed) {
1703
+ violations.push({
1704
+ rule: "no-unused-state",
1705
+ message: `signal setter "${setterName}" is declared but never called. If the state never changes, consider using a plain constant instead.`,
1706
+ severity: "warning",
1707
+ line,
1708
+ column
1709
+ });
1710
+ }
1711
+ }
1712
+ return violations;
1713
+ }
1714
+ }
1715
+ };
1716
+ function escapeRegex(str) {
1717
+ return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1718
+ }
1719
+ function lintSource(source, rules) {
1720
+ const violations = [];
1721
+ const ruleEntries = Object.entries(lintRules);
1722
+ for (const [ruleName, rule] of ruleEntries) {
1723
+ if (rules && rules.length > 0 && !rules.includes(ruleName)) {
1724
+ continue;
1725
+ }
1726
+ const ruleViolations = rule.check(source);
1727
+ violations.push(...ruleViolations);
1728
+ }
1729
+ violations.sort((a, b) => {
1730
+ const lineDiff = (a.line || 0) - (b.line || 0);
1731
+ if (lineDiff !== 0) return lineDiff;
1732
+ return (a.column || 0) - (b.column || 0);
1733
+ });
1734
+ return violations;
1735
+ }
1736
+ function generateEslintConfig(options) {
1737
+ const severity = options?.severity || "warning";
1738
+ const rulePrefix = "sibujs";
1739
+ const rulesConfig = {};
1740
+ for (const ruleName of Object.keys(lintRules)) {
1741
+ rulesConfig[`${rulePrefix}/${ruleName}`] = severity;
1742
+ }
1743
+ return {
1744
+ plugins: [rulePrefix],
1745
+ rules: rulesConfig,
1746
+ settings: {
1747
+ sibujs: {
1748
+ version: "detect"
1749
+ }
1750
+ },
1751
+ overrides: [
1752
+ {
1753
+ files: ["*.ts", "*.tsx", "*.js", "*.jsx"],
1754
+ rules: rulesConfig
1755
+ }
1756
+ ]
1757
+ };
1758
+ }
1759
+
1760
+ // src/build/ide.ts
1761
+ function getComponentMetadata() {
1762
+ return [
1763
+ // ── Reactive Primitives ──────────────────────────────────────────
1764
+ {
1765
+ name: "signal",
1766
+ description: "Creates a reactive signal that holds a value. Returns a [getter, setter] tuple. The getter registers reactive dependencies when called.",
1767
+ props: [
1768
+ {
1769
+ name: "initial",
1770
+ type: "T",
1771
+ required: true,
1772
+ description: "The initial value of the state"
1773
+ }
1774
+ ]
1775
+ },
1776
+ {
1777
+ name: "effect",
1778
+ description: "Runs a side effect function immediately and re-runs it whenever any reactive dependency changes. Returns a cleanup function.",
1779
+ props: [
1780
+ {
1781
+ name: "effectFn",
1782
+ type: "() => void",
1783
+ required: true,
1784
+ description: "The effect function to run. It is tracked for reactive dependencies."
1785
+ }
1786
+ ]
1787
+ },
1788
+ {
1789
+ name: "derived",
1790
+ description: "Creates a derived reactive signal whose value updates automatically when dependencies change. Returns a getter function.",
1791
+ props: [
1792
+ {
1793
+ name: "getter",
1794
+ type: "() => T",
1795
+ required: true,
1796
+ description: "Function returning the computed value based on reactive signals"
1797
+ }
1798
+ ]
1799
+ },
1800
+ {
1801
+ name: "memo",
1802
+ description: "Returns a memoized value that only recomputes when its reactive dependencies change. Alias for derived.",
1803
+ props: [
1804
+ {
1805
+ name: "factory",
1806
+ type: "() => T",
1807
+ required: true,
1808
+ description: "Function that computes the memoized value"
1809
+ }
1810
+ ]
1811
+ },
1812
+ {
1813
+ name: "memoFn",
1814
+ description: "Returns a memoized callback that only updates when its reactive dependencies change.",
1815
+ props: [
1816
+ {
1817
+ name: "callback",
1818
+ type: "() => T",
1819
+ required: true,
1820
+ description: "The callback factory function to memoize"
1821
+ }
1822
+ ]
1823
+ },
1824
+ {
1825
+ name: "ref",
1826
+ description: "Creates a mutable reference object that persists across renders. Updating a ref does NOT trigger re-renders.",
1827
+ props: [
1828
+ {
1829
+ name: "initial",
1830
+ type: "T",
1831
+ required: false,
1832
+ default: "undefined",
1833
+ description: "Optional initial value for the ref"
1834
+ }
1835
+ ]
1836
+ },
1837
+ {
1838
+ name: "watch",
1839
+ description: "Watches a reactive getter and calls a callback with (newValue, oldValue) when the watched value changes. Returns a teardown function.",
1840
+ props: [
1841
+ {
1842
+ name: "getter",
1843
+ type: "() => T",
1844
+ required: true,
1845
+ description: "Function that returns the value to watch"
1846
+ },
1847
+ {
1848
+ name: "callback",
1849
+ type: "(value: T, prev: T | undefined) => void",
1850
+ required: true,
1851
+ description: "Function called when the watched value changes"
1852
+ }
1853
+ ]
1854
+ },
1855
+ {
1856
+ name: "store",
1857
+ description: "Creates a global store with reactive properties and subscription support. Returns a [store, actions] tuple.",
1858
+ props: [
1859
+ {
1860
+ name: "initialState",
1861
+ type: "T extends object",
1862
+ required: true,
1863
+ description: "Initial state object for the store"
1864
+ }
1865
+ ]
1866
+ },
1867
+ // ── SolidJS-style Primitives ─────────────────────────────────────
1868
+ {
1869
+ name: "createSignal",
1870
+ description: "Creates a reactive signal. SolidJS-style alias for signal. Returns [getter, setter].",
1871
+ props: [
1872
+ {
1873
+ name: "value",
1874
+ type: "T",
1875
+ required: true,
1876
+ description: "Initial value"
1877
+ }
1878
+ ]
1879
+ },
1880
+ {
1881
+ name: "createMemo",
1882
+ description: "Creates a derived/computed reactive value. SolidJS-style alias for derived.",
1883
+ props: [
1884
+ {
1885
+ name: "fn",
1886
+ type: "() => T",
1887
+ required: true,
1888
+ description: "Computation function that reads other signals"
1889
+ }
1890
+ ]
1891
+ },
1892
+ {
1893
+ name: "createEffect",
1894
+ description: "Creates a reactive side effect. SolidJS-style alias for effect.",
1895
+ props: [
1896
+ {
1897
+ name: "fn",
1898
+ type: "() => void",
1899
+ required: true,
1900
+ description: "Effect function that reads reactive signals"
1901
+ }
1902
+ ]
1903
+ },
1904
+ // ── Lifecycle ────────────────────────────────────────────────────
1905
+ {
1906
+ name: "onMount",
1907
+ description: "Runs a callback once the component element has been inserted into the DOM. Uses queueMicrotask for deferred execution.",
1908
+ props: [
1909
+ {
1910
+ name: "callback",
1911
+ type: "() => void | CleanupFn",
1912
+ required: true,
1913
+ description: "Function to run after mount. May return a cleanup function."
1914
+ },
1915
+ {
1916
+ name: "element",
1917
+ type: "HTMLElement",
1918
+ required: false,
1919
+ description: "Optional element to observe; if provided, waits until it is connected."
1920
+ }
1921
+ ]
1922
+ },
1923
+ {
1924
+ name: "onUnmount",
1925
+ description: "Runs a callback when the given element is removed from the DOM. Uses MutationObserver to watch for disconnection.",
1926
+ props: [
1927
+ {
1928
+ name: "callback",
1929
+ type: "() => void",
1930
+ required: true,
1931
+ description: "Function to run on unmount"
1932
+ },
1933
+ {
1934
+ name: "element",
1935
+ type: "HTMLElement",
1936
+ required: true,
1937
+ description: "The element to watch for removal"
1938
+ }
1939
+ ]
1940
+ },
1941
+ // ── Rendering ────────────────────────────────────────────────────
1942
+ {
1943
+ name: "mount",
1944
+ description: "Mounts a root component into a DOM element. Returns an object with the mounted node and an unmount function.",
1945
+ props: [
1946
+ {
1947
+ name: "component",
1948
+ type: "(() => HTMLElement) | HTMLElement | Node",
1949
+ required: true,
1950
+ description: "Function returning HTMLElement, or an HTMLElement directly"
1951
+ },
1952
+ {
1953
+ name: "container",
1954
+ type: "HTMLElement",
1955
+ required: true,
1956
+ description: "Target DOM element to append the result"
1957
+ }
1958
+ ]
1959
+ },
1960
+ {
1961
+ name: "each",
1962
+ description: "Renders a list of nodes efficiently with key-based diffing and LIS-based move minimization.",
1963
+ props: [
1964
+ {
1965
+ name: "getArray",
1966
+ type: "() => T[]",
1967
+ required: true,
1968
+ description: "A reactive getter returning an array"
1969
+ },
1970
+ {
1971
+ name: "render",
1972
+ type: "(item: T, index: number) => NodeChild",
1973
+ required: true,
1974
+ description: "A function that returns a NodeChild for each item"
1975
+ },
1976
+ {
1977
+ name: "options",
1978
+ type: "{ key: (item: T) => string | number }",
1979
+ required: true,
1980
+ description: "A key function for unique identity of items"
1981
+ }
1982
+ ]
1983
+ },
1984
+ {
1985
+ name: "lazy",
1986
+ description: "Enables code-splitting by deferring the import of a component until it is first rendered.",
1987
+ props: [
1988
+ {
1989
+ name: "importFn",
1990
+ type: "() => Promise<{ default: Component }>",
1991
+ required: true,
1992
+ description: "Dynamic import function returning { default: Component }"
1993
+ }
1994
+ ]
1995
+ },
1996
+ {
1997
+ name: "Suspense",
1998
+ description: "Provides a fallback UI while lazy or async nodes are loading.",
1999
+ props: [
2000
+ {
2001
+ name: "nodes",
2002
+ type: "() => HTMLElement",
2003
+ required: true,
2004
+ description: "Function that returns the async/lazy component"
2005
+ },
2006
+ {
2007
+ name: "fallback",
2008
+ type: "() => HTMLElement",
2009
+ required: true,
2010
+ description: "Function that returns the loading UI"
2011
+ }
2012
+ ]
2013
+ },
2014
+ // ── Context ──────────────────────────────────────────────────────
2015
+ {
2016
+ name: "context",
2017
+ description: "Creates a context for dependency injection across component trees without prop drilling. Returns a Context object with provide, use, get, and set methods.",
2018
+ props: [
2019
+ {
2020
+ name: "defaultValue",
2021
+ type: "T",
2022
+ required: true,
2023
+ description: "The fallback value when no provider is found"
2024
+ }
2025
+ ]
2026
+ },
2027
+ // ── Dynamic Components ───────────────────────────────────────────
2028
+ {
2029
+ name: "DynamicComponent",
2030
+ description: "Reactively switches between components based on a reactive getter returning a component name or function.",
2031
+ props: [
2032
+ {
2033
+ name: "is",
2034
+ type: "() => string | Component",
2035
+ required: true,
2036
+ description: "Reactive getter returning component name (string) or component function"
2037
+ }
2038
+ ]
2039
+ },
2040
+ {
2041
+ name: "registerComponent",
2042
+ description: "Registers a component by name for dynamic resolution via DynamicComponent or resolveComponent.",
2043
+ props: [
2044
+ {
2045
+ name: "name",
2046
+ type: "string",
2047
+ required: true,
2048
+ description: "Unique component identifier"
2049
+ },
2050
+ {
2051
+ name: "component",
2052
+ type: "() => HTMLElement",
2053
+ required: true,
2054
+ description: "The component function"
2055
+ }
2056
+ ]
2057
+ },
2058
+ // ── HTML Tag Factories ───────────────────────────────────────────
2059
+ {
2060
+ name: "div",
2061
+ description: "Creates a reactive <div> element. Accepts TagProps including class, style, on, nodes, and arbitrary attributes.",
2062
+ props: [
2063
+ {
2064
+ name: "props",
2065
+ type: "TagProps",
2066
+ required: false,
2067
+ default: "{}",
2068
+ description: "Props object with id, class, style, ref, nodes, on, and other attributes"
2069
+ }
2070
+ ],
2071
+ events: [
2072
+ {
2073
+ name: "click",
2074
+ description: "Fires when the element is clicked"
2075
+ },
2076
+ {
2077
+ name: "input",
2078
+ description: "Fires when user input is received"
2079
+ }
2080
+ ]
2081
+ }
2082
+ ];
2083
+ }
2084
+ function generateVSCodeSnippets() {
2085
+ return {
2086
+ "SibuJS Component": {
2087
+ prefix: "sibu-component",
2088
+ body: [
2089
+ "import { div } from 'sibujs';",
2090
+ "",
2091
+ "export function ${1:ComponentName}(): HTMLElement {",
2092
+ " return div({",
2093
+ " class: '${2:component-class}',",
2094
+ " nodes: [",
2095
+ " ${3:// nodes here}",
2096
+ " ],",
2097
+ " });",
2098
+ "}"
2099
+ ],
2100
+ description: "Create a basic SibuJS component"
2101
+ },
2102
+ "SibuJS Component with State": {
2103
+ prefix: "sibu-component-state",
2104
+ body: [
2105
+ "import { div, span } from 'sibujs';",
2106
+ "import { signal } from 'sibujs';",
2107
+ "",
2108
+ "export function ${1:ComponentName}(): HTMLElement {",
2109
+ " const [${2:value}, ${3:setValue}] = signal(${4:initialValue});",
2110
+ "",
2111
+ " return div({",
2112
+ " class: '${5:component-class}',",
2113
+ " nodes: [",
2114
+ " () => span({ nodes: String(${2:value}()) }),",
2115
+ " ],",
2116
+ " });",
2117
+ "}"
2118
+ ],
2119
+ description: "Create a SibuJS component with reactive state"
2120
+ },
2121
+ "SibuJS signal": {
2122
+ prefix: "sibu-state",
2123
+ body: ["const [${1:value}, ${2:setValue}] = signal(${3:initialValue});"],
2124
+ description: "Create a reactive state with signal"
2125
+ },
2126
+ "SibuJS effect": {
2127
+ prefix: "sibu-effect",
2128
+ body: ["const cleanup = effect(() => {", " ${1:// effect logic}", "});"],
2129
+ description: "Create a reactive side effect with effect"
2130
+ },
2131
+ "SibuJS derived": {
2132
+ prefix: "sibu-computed",
2133
+ body: ["const ${1:computed} = derived(() => {", " return ${2:// derived value};", "});"],
2134
+ description: "Create a derived reactive value with derived"
2135
+ },
2136
+ "SibuJS watch": {
2137
+ prefix: "sibu-watch",
2138
+ body: [
2139
+ "const teardown = watch(",
2140
+ " () => ${1:watchedValue}(),",
2141
+ " (newVal, oldVal) => {",
2142
+ " ${2:// handle change}",
2143
+ " }",
2144
+ ");"
2145
+ ],
2146
+ description: "Watch a reactive value for changes"
2147
+ },
2148
+ "SibuJS each": {
2149
+ prefix: "sibu-each",
2150
+ body: [
2151
+ "each(",
2152
+ " () => ${1:items}(),",
2153
+ " (item, index) => {",
2154
+ " return ${2:div({ nodes: String(item) })};",
2155
+ " },",
2156
+ " { key: (item) => ${3:item.id} }",
2157
+ ")"
2158
+ ],
2159
+ description: "Create a reactive list with each()"
2160
+ },
2161
+ "SibuJS Context": {
2162
+ prefix: "sibu-context",
2163
+ body: [
2164
+ "const ${1:MyContext} = context(${2:defaultValue});",
2165
+ "",
2166
+ "// In provider component:",
2167
+ "// ${1:MyContext}.provide(value);",
2168
+ "",
2169
+ "// In consumer component:",
2170
+ "// const ${3:value} = ${1:MyContext}.use();"
2171
+ ],
2172
+ description: "Create a context for dependency injection"
2173
+ },
2174
+ "SibuJS store": {
2175
+ prefix: "sibu-store",
2176
+ body: [
2177
+ "const [${1:store}, { setState: ${2:setStore}, reset, subscribe }] = store({",
2178
+ " ${3:key}: ${4:value},",
2179
+ "});"
2180
+ ],
2181
+ description: "Create a reactive global store"
2182
+ },
2183
+ "SibuJS Lazy Component": {
2184
+ prefix: "sibu-lazy",
2185
+ body: ["const ${1:LazyComponent} = lazy(() => import('./${2:ComponentPath}'));"],
2186
+ description: "Create a lazy-loaded component"
2187
+ },
2188
+ "SibuJS Suspense": {
2189
+ prefix: "sibu-suspense",
2190
+ body: [
2191
+ "Suspense({",
2192
+ " nodes: () => ${1:LazyComponent}(),",
2193
+ " fallback: () => div({ nodes: '${2:Loading...}' }),",
2194
+ "})"
2195
+ ],
2196
+ description: "Wrap a lazy component with a loading fallback"
2197
+ },
2198
+ "SibuJS onMount": {
2199
+ prefix: "sibu-mount",
2200
+ body: ["onMount(() => {", " ${1:// runs after component enters the DOM}", "});"],
2201
+ description: "Schedule a callback to run after mount"
2202
+ },
2203
+ "SibuJS onUnmount": {
2204
+ prefix: "sibu-unmount",
2205
+ body: ["onUnmount(() => {", " ${1:// cleanup when removed from DOM}", "}, ${2:element});"],
2206
+ description: "Schedule a callback to run on unmount"
2207
+ },
2208
+ "SibuJS Event Handler": {
2209
+ prefix: "sibu-event",
2210
+ body: [
2211
+ "div({",
2212
+ " on: {",
2213
+ " ${1:click}: (e) => {",
2214
+ " ${2:// handle event}",
2215
+ " },",
2216
+ " },",
2217
+ " nodes: '${3:Click me}',",
2218
+ "})"
2219
+ ],
2220
+ description: "Create an element with event handlers"
2221
+ },
2222
+ "SibuJS Form": {
2223
+ prefix: "sibu-form",
2224
+ body: [
2225
+ "const form = form({",
2226
+ " ${1:fieldName}: {",
2227
+ " initial: '${2:}',",
2228
+ " validators: [",
2229
+ " (value) => !value ? '${3:Required}' : null,",
2230
+ " ],",
2231
+ " },",
2232
+ "});"
2233
+ ],
2234
+ description: "Create a reactive form with validation"
2235
+ },
2236
+ "SibuJS createSignal": {
2237
+ prefix: "sibu-signal",
2238
+ body: ["const [${1:value}, ${2:setValue}] = createSignal(${3:initialValue});"],
2239
+ description: "Create a reactive signal (SolidJS-style alias for signal)"
2240
+ }
2241
+ };
2242
+ }
2243
+ function generateLanguageConfig() {
2244
+ return {
2245
+ comments: {
2246
+ lineComment: "//",
2247
+ blockComment: ["/*", "*/"]
2248
+ },
2249
+ brackets: [
2250
+ ["{", "}"],
2251
+ ["[", "]"],
2252
+ ["(", ")"],
2253
+ ["<", ">"]
2254
+ ],
2255
+ autoClosingPairs: [
2256
+ { open: "{", close: "}" },
2257
+ { open: "[", close: "]" },
2258
+ { open: "(", close: ")" },
2259
+ { open: "<", close: ">" },
2260
+ { open: "'", close: "'" },
2261
+ { open: '"', close: '"' },
2262
+ { open: "`", close: "`" }
2263
+ ]
2264
+ };
2265
+ }
2266
+ function generateTypeStubs() {
2267
+ return {
2268
+ signal: ["declare function signal<T>(initial: T): [() => T, (next: T | ((prev: T) => T)) => void];"].join("\n"),
2269
+ effect: ["declare function effect(effectFn: () => void): () => void;"].join("\n"),
2270
+ derived: ["declare function derived<T>(getter: () => T): () => T;"].join("\n"),
2271
+ memo: ["declare function memo<T>(factory: () => T): () => T;"].join("\n"),
2272
+ memoFn: ["declare function memoFn<T extends (...args: unknown[]) => unknown>(callback: () => T): () => T;"].join(
2273
+ "\n"
2274
+ ),
2275
+ ref: [
2276
+ "interface Ref<T> { current: T; }",
2277
+ "declare function ref<T>(initial: T): Ref<T>;",
2278
+ "declare function ref<T = undefined>(): Ref<T | undefined>;"
2279
+ ].join("\n"),
2280
+ watch: [
2281
+ "declare function watch<T>(getter: () => T, callback: (value: T, prev: T | undefined) => void): () => void;"
2282
+ ].join("\n"),
2283
+ store: [
2284
+ "interface StoreActions<T> {",
2285
+ " setState: (patch: Partial<T> | ((state: T) => T)) => void;",
2286
+ " reset: () => void;",
2287
+ " subscribe: (callback: (state: T) => void) => () => void;",
2288
+ " subscribeKey: <K extends keyof T>(key: K, callback: (value: T[K], prev: T[K]) => void) => () => void;",
2289
+ " getSnapshot: () => T;",
2290
+ "}",
2291
+ "declare function store<T extends object>(initialState: T): [{ readonly [K in keyof T]: T[K] }, StoreActions<T>];"
2292
+ ].join("\n"),
2293
+ createSignal: ["declare function createSignal<T>(value: T): [() => T, (next: T | ((prev: T) => T)) => void];"].join(
2294
+ "\n"
2295
+ ),
2296
+ createMemo: ["declare function createMemo<T>(fn: () => T): () => T;"].join("\n"),
2297
+ createEffect: ["declare function createEffect(fn: () => void): () => void;"].join("\n"),
2298
+ mount: [
2299
+ "declare function mount(component: (() => HTMLElement) | HTMLElement | Node, container: HTMLElement | null): { node: Node; unmount: () => void };"
2300
+ ].join("\n"),
2301
+ each: [
2302
+ "declare function each<T>(getArray: () => T[], render: (item: T, index: number) => NodeChild, options: { key: (item: T) => string | number }): Comment;"
2303
+ ].join("\n"),
2304
+ onMount: ["declare function onMount(callback: () => void | (() => void), element?: HTMLElement): void;"].join("\n"),
2305
+ onUnmount: ["declare function onUnmount(callback: () => void, element: HTMLElement): void;"].join("\n"),
2306
+ context: [
2307
+ "interface Context<T> {",
2308
+ " provide(value: T): void;",
2309
+ " use(): () => T;",
2310
+ " get(): T;",
2311
+ " set(value: T): void;",
2312
+ "}",
2313
+ "declare function context<T>(defaultValue: T): Context<T>;"
2314
+ ].join("\n"),
2315
+ lazy: ["declare function lazy(importFn: () => Promise<{ default: () => HTMLElement }>): () => HTMLElement;"].join(
2316
+ "\n"
2317
+ ),
2318
+ Suspense: [
2319
+ "interface SuspenseProps { nodes: () => HTMLElement; fallback: () => HTMLElement; }",
2320
+ "declare function Suspense(props: SuspenseProps): HTMLElement;"
2321
+ ].join("\n"),
2322
+ tagFactory: [
2323
+ "interface TagProps {",
2324
+ " id?: string;",
2325
+ " class?: string | (() => string) | Record<string, boolean | (() => boolean)>;",
2326
+ " style?: Record<string, string | number | (() => string | number)> | string | (() => string);",
2327
+ " ref?: { current: unknown };",
2328
+ " nodes?: NodeChildren;",
2329
+ " on?: Record<string, (ev: Event) => void>;",
2330
+ " [attr: string]: unknown;",
2331
+ "}",
2332
+ "declare function tagFactory(tag: string, ns?: string): (first?: TagProps | NodeChildren, second?: NodeChildren) => Element;"
2333
+ ].join("\n"),
2334
+ DynamicComponent: ["declare function DynamicComponent(is: () => string | (() => HTMLElement)): HTMLElement;"].join(
2335
+ "\n"
2336
+ ),
2337
+ registerComponent: ["declare function registerComponent(name: string, component: () => HTMLElement): void;"].join(
2338
+ "\n"
2339
+ )
2340
+ };
2341
+ }
2342
+
2343
+ // src/build/routeSplitting.ts
2344
+ function fileToRoute(relativePath) {
2345
+ const basename = relativePath.split("/").pop() || "";
2346
+ if (basename.startsWith("_")) return null;
2347
+ let route = relativePath.replace(/\.(ts|tsx|js|jsx)$/, "");
2348
+ route = route.replace(/\/index$/, "").replace(/^index$/, "");
2349
+ route = route.replace(/\[\.\.\.(\w+)\]/g, "*");
2350
+ route = route.replace(/\[(\w+)\]/g, ":$1");
2351
+ return `/${route}`;
2352
+ }
2353
+ async function scanRoutes(routesDir, exclude, fs) {
2354
+ const entries = await fs.readdir(routesDir, { withFileTypes: true, recursive: true });
2355
+ const files = [];
2356
+ for (const entry of entries) {
2357
+ if (!entry.isFile()) continue;
2358
+ if (!/\.(ts|tsx|js|jsx)$/.test(entry.name)) continue;
2359
+ const dir = (entry.parentPath || entry.path || routesDir).replace(/\\/g, "/");
2360
+ const routesDirNorm = routesDir.replace(/\\/g, "/");
2361
+ const relative = `${dir}/${entry.name}`.replace(`${routesDirNorm}/`, "").replace(/\\/g, "/");
2362
+ const excluded = exclude.some((pattern) => {
2363
+ const regex = pattern.replace(/\*/g, ".*");
2364
+ return new RegExp(regex).test(relative);
2365
+ });
2366
+ if (!excluded) {
2367
+ files.push(relative);
2368
+ }
2369
+ }
2370
+ return files.sort();
2371
+ }
2372
+ function buildRouteEntries(files, chunkPrefix) {
2373
+ const entries = [];
2374
+ for (const file of files) {
2375
+ const path = fileToRoute(file);
2376
+ if (path === null) continue;
2377
+ const chunkName = `${chunkPrefix}${file.replace(/\.(ts|tsx|js|jsx)$/, "").replace(/[/\\[\].]/g, "-").replace(/^-+|-+$/g, "").toLowerCase()}`;
2378
+ entries.push({
2379
+ path,
2380
+ importPath: file,
2381
+ chunkName,
2382
+ isDynamic: path.includes(":") || path.includes("*")
2383
+ });
2384
+ }
2385
+ return entries.sort((a, b) => {
2386
+ if (a.path.includes("*") && !b.path.includes("*")) return 1;
2387
+ if (!a.path.includes("*") && b.path.includes("*")) return -1;
2388
+ if (a.isDynamic && !b.isDynamic) return 1;
2389
+ if (!a.isDynamic && b.isDynamic) return -1;
2390
+ return a.path.localeCompare(b.path);
2391
+ });
2392
+ }
2393
+ function generateRouteModule(entries, routesDir) {
2394
+ const imports = entries.map(
2395
+ (e, i) => `const route${i} = () => import(/* webpackChunkName: "${e.chunkName}" */ "${routesDir}/${e.importPath}");`
2396
+ ).join("\n");
2397
+ const routes = entries.map((e, i) => ` { path: "${e.path}", component: lazy(route${i}) }`).join(",\n");
2398
+ return `import { lazy } from "sibu";
2399
+
2400
+ ${imports}
2401
+
2402
+ export const routes = [
2403
+ ${routes}
2404
+ ];
2405
+ `;
2406
+ }
2407
+ var VIRTUAL_ID = "virtual:sibu-routes";
2408
+ var RESOLVED_VIRTUAL_ID = `\0${VIRTUAL_ID}`;
2409
+ function sibuRouteSplitting(options = {}) {
2410
+ const { routesDir = "src/routes", exclude = [], chunkPrefix = "route-" } = options;
2411
+ let projectRoot = "";
2412
+ return {
2413
+ name: "sibu-route-splitting",
2414
+ enforce: "pre",
2415
+ resolveId(id) {
2416
+ if (id === VIRTUAL_ID) {
2417
+ return RESOLVED_VIRTUAL_ID;
2418
+ }
2419
+ return void 0;
2420
+ },
2421
+ async load(id) {
2422
+ if (id !== RESOLVED_VIRTUAL_ID) return void 0;
2423
+ const { readdir } = await import("fs/promises");
2424
+ const { resolve } = await import("path");
2425
+ if (!projectRoot) {
2426
+ projectRoot = process.cwd();
2427
+ }
2428
+ const fullRoutesDir = resolve(projectRoot, routesDir);
2429
+ try {
2430
+ const files = await scanRoutes(fullRoutesDir, exclude, {
2431
+ readdir
2432
+ });
2433
+ const entries = buildRouteEntries(files, chunkPrefix);
2434
+ return generateRouteModule(entries, routesDir.startsWith("/") ? routesDir : `./${routesDir}`);
2435
+ } catch {
2436
+ return "export const routes = [];\n";
2437
+ }
2438
+ },
2439
+ handleHotUpdate(ctx) {
2440
+ const normalizedRoutesDir = routesDir.replace(/\\/g, "/");
2441
+ if (ctx.file.replace(/\\/g, "/").includes(normalizedRoutesDir)) {
2442
+ const mod = ctx.server.moduleGraph.getModuleById(RESOLVED_VIRTUAL_ID);
2443
+ if (mod) {
2444
+ ctx.server.moduleGraph.invalidateModule(mod);
2445
+ ctx.server.ws.send({ type: "full-reload" });
2446
+ }
2447
+ }
2448
+ }
2449
+ };
2450
+ }
2451
+ export {
2452
+ analyzeBundle,
2453
+ analyzeStaticTemplates,
2454
+ buildRouteEntries,
2455
+ cdnUrls,
2456
+ compileHtmlTemplates,
2457
+ createPureAnnotationsLoader,
2458
+ createViteConfig,
2459
+ createWebpackConfig,
2460
+ estimateImportSize,
2461
+ fileToRoute,
2462
+ generateEslintConfig,
2463
+ generateImportMap,
2464
+ generateLanguageConfig,
2465
+ generateTsConfig,
2466
+ generateTypeStubs,
2467
+ generateVSCodeSnippets,
2468
+ getComponentMetadata,
2469
+ lintRules,
2470
+ lintSource,
2471
+ moduleSizes,
2472
+ registerGlobal,
2473
+ sibuRouteSplitting,
2474
+ sibuVitePlugin,
2475
+ sibuWebpackPlugin,
2476
+ umdWrapper,
2477
+ validateTsConfig
2478
+ };