sibujs 4.6.0 → 4.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/README.md +1 -1
  2. package/dist/browser.cjs +18 -5
  3. package/dist/browser.js +4 -4
  4. package/dist/build.cjs +1956 -1007
  5. package/dist/build.d.cts +133 -44
  6. package/dist/build.d.ts +133 -44
  7. package/dist/build.js +1368 -569
  8. package/dist/cdn.dev.global.js +12 -12
  9. package/dist/cdn.full.dev.global.js +11 -11
  10. package/dist/cdn.full.global.js +10 -10
  11. package/dist/cdn.global.js +12 -12
  12. package/dist/{chunk-SXXVZMKZ.js → chunk-2BPG2XDA.js} +5 -5
  13. package/dist/{chunk-BAAG6ZTI.js → chunk-3QWBSL5R.js} +4 -4
  14. package/dist/{chunk-5MT6SJ3P.js → chunk-4AWA2PVD.js} +2 -2
  15. package/dist/{chunk-JSXPZCET.js → chunk-7LUJQAOJ.js} +1 -1
  16. package/dist/{chunk-3ISI6ACU.js → chunk-BC2SECJD.js} +1 -1
  17. package/dist/{chunk-DKGBBKOF.js → chunk-BSY63EM6.js} +2 -2
  18. package/dist/{chunk-7NCARGJW.js → chunk-DKXRACVN.js} +3 -3
  19. package/dist/{chunk-47M47FOM.js → chunk-FNJXNGYZ.js} +1 -1
  20. package/dist/{chunk-D33YTSX5.js → chunk-FQRUXCEE.js} +5 -4
  21. package/dist/{chunk-5Q4R7HCL.js → chunk-JWKYU5GV.js} +11 -2
  22. package/dist/{chunk-QE4TTDU3.js → chunk-RUSSKG6G.js} +12 -11
  23. package/dist/{chunk-UZQ6ALFS.js → chunk-SLM3IA34.js} +1 -1
  24. package/dist/{chunk-XRRZKZYX.js → chunk-UNWRJRKC.js} +1 -1
  25. package/dist/{chunk-VVWPJ543.js → chunk-UOL2ECCS.js} +40 -11
  26. package/dist/{chunk-ORMZXBKQ.js → chunk-VZSG24LS.js} +3 -3
  27. package/dist/{chunk-XC4MEKGA.js → chunk-WEQ3DMVL.js} +8 -2
  28. package/dist/{chunk-PK6FK2G2.js → chunk-WOLJZUFQ.js} +176 -27
  29. package/dist/{chunk-7GQCWFOE.js → chunk-XYV3EDB7.js} +143 -74
  30. package/dist/{chunk-AIF3Z2T7.js → chunk-XZR4PXRE.js} +3 -3
  31. package/dist/{chunk-HYXDKS4N.js → chunk-Z3OHK6QT.js} +4 -4
  32. package/dist/{chunk-OXUY2A6L.js → chunk-ZVL7TY4K.js} +2 -2
  33. package/dist/{contracts-DRIuclVT.d.ts → contracts-CLqzJnOV.d.ts} +28 -17
  34. package/dist/{contracts-DRIuclVT.d.cts → contracts-CTOJXu-x.d.cts} +28 -17
  35. package/dist/data.cjs +198 -39
  36. package/dist/data.d.cts +119 -3
  37. package/dist/data.d.ts +119 -3
  38. package/dist/data.js +5 -5
  39. package/dist/devtools.cjs +18 -5
  40. package/dist/devtools.js +4 -4
  41. package/dist/ecosystem.cjs +64 -23
  42. package/dist/ecosystem.d.cts +2 -1
  43. package/dist/ecosystem.d.ts +2 -1
  44. package/dist/ecosystem.js +7 -7
  45. package/dist/extras.cjs +236 -49
  46. package/dist/extras.d.cts +3 -2
  47. package/dist/extras.d.ts +3 -2
  48. package/dist/extras.js +20 -20
  49. package/dist/index.cjs +259 -108
  50. package/dist/index.d.cts +193 -168
  51. package/dist/index.d.ts +193 -168
  52. package/dist/index.js +10 -10
  53. package/dist/motion.cjs +12 -4
  54. package/dist/motion.js +3 -3
  55. package/dist/patterns.cjs +28 -15
  56. package/dist/patterns.d.cts +2 -1
  57. package/dist/patterns.d.ts +2 -1
  58. package/dist/patterns.js +5 -5
  59. package/dist/performance.cjs +18 -5
  60. package/dist/performance.js +4 -4
  61. package/dist/plugins.cjs +118 -34
  62. package/dist/plugins.d.cts +124 -11
  63. package/dist/plugins.d.ts +124 -11
  64. package/dist/plugins.js +68 -26
  65. package/dist/ssr.cjs +54 -13
  66. package/dist/ssr.js +7 -7
  67. package/dist/{tagFactory-DFstCLQV.d.cts → tagFactory-8qL9LCIx.d.cts} +58 -19
  68. package/dist/{tagFactory-DkaNVUNV.d.ts → tagFactory-BL2fymez.d.ts} +58 -19
  69. package/dist/testing.cjs +15 -2
  70. package/dist/testing.js +2 -2
  71. package/dist/types-CJFViL6Q.d.cts +26 -0
  72. package/dist/types-CJFViL6Q.d.ts +26 -0
  73. package/dist/ui.cjs +28 -15
  74. package/dist/ui.d.cts +2 -1
  75. package/dist/ui.d.ts +2 -1
  76. package/dist/ui.js +7 -7
  77. package/dist/widgets.cjs +22 -14
  78. package/dist/widgets.js +6 -6
  79. package/package.json +4 -2
package/dist/build.js CHANGED
@@ -1,24 +1,938 @@
1
1
  import {
2
2
  index_exports
3
- } from "./chunk-7GQCWFOE.js";
4
- import "./chunk-JSXPZCET.js";
3
+ } from "./chunk-XYV3EDB7.js";
4
+ import "./chunk-7LUJQAOJ.js";
5
5
  import "./chunk-HURREPU2.js";
6
- import "./chunk-UZQ6ALFS.js";
7
- import "./chunk-3ISI6ACU.js";
8
- import "./chunk-VVWPJ543.js";
9
- import "./chunk-47M47FOM.js";
10
- import "./chunk-QE4TTDU3.js";
11
- import "./chunk-2INLLLMZ.js";
6
+ import "./chunk-SLM3IA34.js";
7
+ import "./chunk-BC2SECJD.js";
8
+ import "./chunk-UOL2ECCS.js";
9
+ import "./chunk-FNJXNGYZ.js";
10
+ import "./chunk-RUSSKG6G.js";
11
+ import {
12
+ isEventHandlerAttr,
13
+ isHtmlContentAttribute,
14
+ isUrlAttribute
15
+ } from "./chunk-2INLLLMZ.js";
12
16
  import "./chunk-7ZHH77QA.js";
13
- import "./chunk-XC4MEKGA.js";
17
+ import "./chunk-WEQ3DMVL.js";
14
18
  import "./chunk-7XHATCIH.js";
15
19
  import "./chunk-5HZXGZ6T.js";
16
- import "./chunk-D33YTSX5.js";
17
- import "./chunk-5Q4R7HCL.js";
20
+ import "./chunk-FQRUXCEE.js";
21
+ import "./chunk-JWKYU5GV.js";
18
22
  import "./chunk-NYNYSPK7.js";
19
23
 
20
- // src/build/compileTemplates.ts
21
- var VOID_ELEMENTS = /* @__PURE__ */ new Set([
24
+ // src/build/sourceEdit.ts
25
+ function isLineBreak(c) {
26
+ return c === 10 || c === 13 || c === 8232 || c === 8233;
27
+ }
28
+ function lineBreaksIn(code, start, end) {
29
+ let out = "";
30
+ for (let i = start; i < end; i++) {
31
+ if (isLineBreak(code.charCodeAt(i))) out += code[i];
32
+ }
33
+ return out;
34
+ }
35
+ var LINE_SEPARATOR = String.fromCharCode(8232);
36
+ var PARAGRAPH_SEPARATOR = String.fromCharCode(8233);
37
+ function jsStringLiteral(value) {
38
+ const json = JSON.stringify(value);
39
+ if (!json.includes(LINE_SEPARATOR) && !json.includes(PARAGRAPH_SEPARATOR)) return json;
40
+ const bs = "\\";
41
+ return json.split(LINE_SEPARATOR).join(`${bs}u2028`).split(PARAGRAPH_SEPARATOR).join(`${bs}u2029`);
42
+ }
43
+ function normalizeEdits(edits) {
44
+ const sorted = edits.map((edit, order) => ({ edit, order })).sort(
45
+ (a, b) => a.edit.start - b.edit.start || a.edit.end - a.edit.start - (b.edit.end - b.edit.start) || a.order - b.order
46
+ ).map((x) => x.edit);
47
+ for (let i = 1; i < sorted.length; i++) {
48
+ if (sorted[i].start < sorted[i - 1].end) return null;
49
+ }
50
+ return sorted;
51
+ }
52
+ function applyEdits(code, edits, append = "") {
53
+ let out = "";
54
+ let pos = 0;
55
+ for (const edit of edits) {
56
+ out += code.slice(pos, edit.start) + edit.text;
57
+ pos = edit.end;
58
+ }
59
+ return out + code.slice(pos) + append;
60
+ }
61
+ var BASE64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
62
+ function vlq(value) {
63
+ let v = value < 0 ? -value << 1 | 1 : value << 1;
64
+ let out = "";
65
+ do {
66
+ let digit = v & 31;
67
+ v >>>= 5;
68
+ if (v > 0) digit |= 32;
69
+ out += BASE64[digit];
70
+ } while (v > 0);
71
+ return out;
72
+ }
73
+ function isWordStart(c) {
74
+ return c >= 97 && c <= 122 || c >= 65 && c <= 90 || c === 95 || c === 36 || c > 127 || c >= 48 && c <= 57;
75
+ }
76
+ function editsSourceMap(code, edits, append, source) {
77
+ const lineStarts = [0];
78
+ for (let i = 0; i < code.length; i++) if (code.charCodeAt(i) === 10) lineStarts.push(i + 1);
79
+ const origLine = (offset) => {
80
+ let lo = 0;
81
+ let hi = lineStarts.length - 1;
82
+ while (lo < hi) {
83
+ const mid = lo + hi + 1 >> 1;
84
+ if (lineStarts[mid] <= offset) lo = mid;
85
+ else hi = mid - 1;
86
+ }
87
+ return lo;
88
+ };
89
+ const lines = [[]];
90
+ let col = 0;
91
+ const mark = (offset) => {
92
+ const line = lines[lines.length - 1];
93
+ const last = line[line.length - 1];
94
+ if (last && last[0] === col) return;
95
+ const ol = origLine(offset);
96
+ line.push([col, ol, offset - lineStarts[ol]]);
97
+ };
98
+ const newline = () => {
99
+ lines.push([]);
100
+ col = 0;
101
+ };
102
+ const emitOriginal = (from, to) => {
103
+ for (let i = from; i < to; i++) {
104
+ const c = code.charCodeAt(i);
105
+ if (c === 10) {
106
+ newline();
107
+ continue;
108
+ }
109
+ if (i === from || col === 0 || isWordStart(c) && !isWordStart(code.charCodeAt(i - 1))) mark(i);
110
+ col++;
111
+ }
112
+ };
113
+ const emitReplacement = (edit) => {
114
+ let origOffset = edit.start;
115
+ let pending = true;
116
+ for (let i = 0; i < edit.text.length; i++) {
117
+ if (edit.text.charCodeAt(i) === 10) {
118
+ newline();
119
+ const nl = code.indexOf("\n", origOffset);
120
+ if (nl !== -1 && nl < edit.end) {
121
+ origOffset = nl + 1;
122
+ pending = true;
123
+ } else {
124
+ pending = false;
125
+ }
126
+ continue;
127
+ }
128
+ if (pending) {
129
+ mark(origOffset);
130
+ pending = false;
131
+ }
132
+ col++;
133
+ }
134
+ };
135
+ let pos = 0;
136
+ for (const edit of edits) {
137
+ emitOriginal(pos, edit.start);
138
+ emitReplacement(edit);
139
+ pos = edit.end;
140
+ }
141
+ emitOriginal(pos, code.length);
142
+ for (let i = 0; i < append.length; i++) {
143
+ if (append.charCodeAt(i) === 10) newline();
144
+ }
145
+ let prevLine = 0;
146
+ let prevCol = 0;
147
+ let prevSource = 0;
148
+ const mappings = lines.map((segments) => {
149
+ let prevGen = 0;
150
+ return segments.map(([gen, ol, oc]) => {
151
+ const s = vlq(gen - prevGen) + vlq(0 - prevSource) + vlq(ol - prevLine) + vlq(oc - prevCol);
152
+ prevGen = gen;
153
+ prevSource = 0;
154
+ prevLine = ol;
155
+ prevCol = oc;
156
+ return s;
157
+ }).join(",");
158
+ }).join(";");
159
+ return { version: 3, sources: [source], sourcesContent: [code], names: [], mappings };
160
+ }
161
+
162
+ // src/build/sourceScan.ts
163
+ var REGEX_AFTER_KEYWORD = /* @__PURE__ */ new Set([
164
+ "return",
165
+ "typeof",
166
+ "instanceof",
167
+ "in",
168
+ "of",
169
+ "new",
170
+ "delete",
171
+ "void",
172
+ "throw",
173
+ "case",
174
+ "do",
175
+ "else",
176
+ "yield",
177
+ "await"
178
+ ]);
179
+ function isIdentStart(c) {
180
+ return c >= 97 && c <= 122 || c >= 65 && c <= 90 || c === 95 || c === 36 || c > 127;
181
+ }
182
+ function isIdentPart(c) {
183
+ return isIdentStart(c) || c >= 48 && c <= 57;
184
+ }
185
+ function isDigit(c) {
186
+ return c >= 48 && c <= 57;
187
+ }
188
+ var ScanError = class extends Error {
189
+ };
190
+ var scanStats = { tokenize: 0 };
191
+ function tokenize(code) {
192
+ scanStats.tokenize++;
193
+ let pos = 0;
194
+ const len = code.length;
195
+ if (code.startsWith("#!")) {
196
+ const nl = code.indexOf("\n");
197
+ pos = nl === -1 ? len : nl;
198
+ }
199
+ function regexAllowed(prev) {
200
+ if (!prev) return true;
201
+ switch (prev.type) {
202
+ case "number":
203
+ case "string":
204
+ case "regex":
205
+ case "template":
206
+ return false;
207
+ case "ident":
208
+ return REGEX_AFTER_KEYWORD.has(prev.value);
209
+ case "punct":
210
+ return prev.value !== ")" && prev.value !== "]";
211
+ }
212
+ }
213
+ function skipTrivia() {
214
+ while (pos < len) {
215
+ const c = code.charCodeAt(pos);
216
+ if (c === 32 || c === 9 || c === 10 || c === 13 || c === 11 || c === 12 || c === 160 || c === 65279) {
217
+ pos++;
218
+ } else if (c === 8232 || c === 8233) {
219
+ pos++;
220
+ } else if (c === 47 && code.charCodeAt(pos + 1) === 47) {
221
+ pos += 2;
222
+ while (pos < len) {
223
+ const d = code.charCodeAt(pos);
224
+ if (d === 10 || d === 13 || d === 8232 || d === 8233) break;
225
+ pos++;
226
+ }
227
+ } else if (c === 47 && code.charCodeAt(pos + 1) === 42) {
228
+ const end = code.indexOf("*/", pos + 2);
229
+ if (end === -1) throw new ScanError("unterminated comment");
230
+ pos = end + 2;
231
+ } else {
232
+ break;
233
+ }
234
+ }
235
+ }
236
+ function readString() {
237
+ const start = pos;
238
+ const quote = code[pos];
239
+ pos++;
240
+ while (pos < len) {
241
+ const c = code[pos];
242
+ if (c === "\\") {
243
+ pos += 2;
244
+ continue;
245
+ }
246
+ if (c === quote) {
247
+ pos++;
248
+ return { type: "string", start, end: pos };
249
+ }
250
+ if (c === "\n" || c === "\r") throw new ScanError("line break in string");
251
+ pos++;
252
+ }
253
+ throw new ScanError("unterminated string");
254
+ }
255
+ function readRegex() {
256
+ const start = pos;
257
+ pos++;
258
+ let inClass = false;
259
+ while (pos < len) {
260
+ const c = code[pos];
261
+ if (c === "\\") {
262
+ pos += 2;
263
+ continue;
264
+ }
265
+ if (c === "\n" || c === "\r") throw new ScanError("line break in regex");
266
+ if (inClass) {
267
+ if (c === "]") inClass = false;
268
+ } else if (c === "[") {
269
+ inClass = true;
270
+ } else if (c === "/") {
271
+ pos++;
272
+ while (pos < len && isIdentPart(code.charCodeAt(pos))) pos++;
273
+ return { type: "regex", start, end: pos };
274
+ }
275
+ pos++;
276
+ }
277
+ throw new ScanError("unterminated regex");
278
+ }
279
+ function readTemplate() {
280
+ const start = pos;
281
+ pos++;
282
+ const quasis = [];
283
+ const exprs = [];
284
+ let quasiStart = pos;
285
+ while (pos < len) {
286
+ const c = code[pos];
287
+ if (c === "\\") {
288
+ pos += 2;
289
+ continue;
290
+ }
291
+ if (c === "`") {
292
+ quasis.push({ start: quasiStart, end: pos });
293
+ pos++;
294
+ return { type: "template", start, end: pos, quasis, exprs };
295
+ }
296
+ if (c === "$" && code[pos + 1] === "{") {
297
+ quasis.push({ start: quasiStart, end: pos });
298
+ pos += 2;
299
+ const exprStart = pos;
300
+ const tokens = readList(true);
301
+ exprs.push({ start: exprStart, end: pos, tokens });
302
+ pos++;
303
+ quasiStart = pos;
304
+ continue;
305
+ }
306
+ pos++;
307
+ }
308
+ throw new ScanError("unterminated template");
309
+ }
310
+ function readList(inTemplateExpr) {
311
+ const tokens = [];
312
+ let depth = 0;
313
+ for (; ; ) {
314
+ skipTrivia();
315
+ if (pos >= len) {
316
+ if (inTemplateExpr || depth !== 0) throw new ScanError("unexpected end of input");
317
+ return tokens;
318
+ }
319
+ const c = code.charCodeAt(pos);
320
+ const prev = tokens[tokens.length - 1];
321
+ if (c === 34 || c === 39) {
322
+ tokens.push(readString());
323
+ } else if (c === 96) {
324
+ tokens.push(readTemplate());
325
+ } else if (isIdentStart(c) || c === 92) {
326
+ const start = pos;
327
+ pos++;
328
+ while (pos < len) {
329
+ const d = code.charCodeAt(pos);
330
+ if (isIdentPart(d)) pos++;
331
+ else if (d === 92) pos += 2;
332
+ else break;
333
+ }
334
+ tokens.push({ type: "ident", start, end: pos, value: code.slice(start, pos) });
335
+ } else if (isDigit(c) || c === 46 && isDigit(code.charCodeAt(pos + 1))) {
336
+ const start = pos;
337
+ pos++;
338
+ while (pos < len) {
339
+ const d = code.charCodeAt(pos);
340
+ if (isIdentPart(d) || d === 46) pos++;
341
+ else break;
342
+ }
343
+ tokens.push({ type: "number", start, end: pos, value: code.slice(start, pos) });
344
+ } else if (c === 47 && regexAllowed(prev)) {
345
+ tokens.push(readRegex());
346
+ } else {
347
+ const start = pos;
348
+ let value = code[pos];
349
+ if (code.startsWith("...", pos)) value = "...";
350
+ else if (code.startsWith("?.", pos) && !isDigit(code.charCodeAt(pos + 2))) value = "?.";
351
+ else if (code.startsWith("=>", pos)) value = "=>";
352
+ pos += value.length;
353
+ if (value === "{") {
354
+ depth++;
355
+ } else if (value === "}") {
356
+ if (depth === 0) {
357
+ if (inTemplateExpr) {
358
+ pos = start;
359
+ return tokens;
360
+ }
361
+ throw new ScanError("unbalanced brace");
362
+ }
363
+ depth--;
364
+ }
365
+ tokens.push({ type: "punct", start, end: pos, value });
366
+ }
367
+ }
368
+ }
369
+ try {
370
+ return readList(false);
371
+ } catch (err) {
372
+ if (err instanceof ScanError) return null;
373
+ throw err;
374
+ }
375
+ }
376
+ function cookEscapes(raw) {
377
+ let out = "";
378
+ let i = 0;
379
+ const n = raw.length;
380
+ while (i < n) {
381
+ const ch = raw[i];
382
+ if (ch === "\r") {
383
+ out += "\n";
384
+ i += raw[i + 1] === "\n" ? 2 : 1;
385
+ continue;
386
+ }
387
+ if (ch !== "\\") {
388
+ out += ch;
389
+ i++;
390
+ continue;
391
+ }
392
+ const e = raw[i + 1];
393
+ i += 2;
394
+ switch (e) {
395
+ case "n":
396
+ out += "\n";
397
+ break;
398
+ case "t":
399
+ out += " ";
400
+ break;
401
+ case "r":
402
+ out += "\r";
403
+ break;
404
+ case "b":
405
+ out += "\b";
406
+ break;
407
+ case "f":
408
+ out += "\f";
409
+ break;
410
+ case "v":
411
+ out += "\v";
412
+ break;
413
+ case "0":
414
+ if (i < n && isDigit(raw.charCodeAt(i))) return null;
415
+ out += "\0";
416
+ break;
417
+ case "x": {
418
+ const hex = raw.slice(i, i + 2);
419
+ if (!/^[0-9a-fA-F]{2}$/.test(hex)) return null;
420
+ out += String.fromCharCode(Number.parseInt(hex, 16));
421
+ i += 2;
422
+ break;
423
+ }
424
+ case "u": {
425
+ if (raw[i] === "{") {
426
+ const close = raw.indexOf("}", i);
427
+ if (close === -1) return null;
428
+ const hex = raw.slice(i + 1, close);
429
+ if (!/^[0-9a-fA-F]+$/.test(hex)) return null;
430
+ const cp = Number.parseInt(hex, 16);
431
+ if (cp > 1114111) return null;
432
+ out += String.fromCodePoint(cp);
433
+ i = close + 1;
434
+ } else {
435
+ const hex = raw.slice(i, i + 4);
436
+ if (!/^[0-9a-fA-F]{4}$/.test(hex)) return null;
437
+ out += String.fromCharCode(Number.parseInt(hex, 16));
438
+ i += 4;
439
+ }
440
+ break;
441
+ }
442
+ case "\r":
443
+ if (raw[i] === "\n") i++;
444
+ break;
445
+ case "\n":
446
+ case "\u2028":
447
+ case "\u2029":
448
+ break;
449
+ case void 0:
450
+ return null;
451
+ default:
452
+ if (isDigit(e.charCodeAt(0))) return null;
453
+ out += e;
454
+ }
455
+ }
456
+ return out;
457
+ }
458
+ function stringTokenValue(code, tok) {
459
+ if (tok.type !== "string") return null;
460
+ return cookEscapes(code.slice(tok.start + 1, tok.end - 1));
461
+ }
462
+ function collectImports(code, tokens) {
463
+ const decls = [];
464
+ for (let i = 0; i < tokens.length; i++) {
465
+ const tok = tokens[i];
466
+ if (tok.type !== "ident" || tok.value !== "import") continue;
467
+ const prev = tokens[i - 1];
468
+ if (prev && prev.type === "punct" && (prev.value === "." || prev.value === "?.")) continue;
469
+ const next = tokens[i + 1];
470
+ if (!next) return null;
471
+ if (next.type === "punct" && (next.value === "(" || next.value === ".")) continue;
472
+ let j = i + 1;
473
+ const bindings = [];
474
+ let typeOnly = false;
475
+ if (next.type === "string") {
476
+ const source2 = stringTokenValue(code, next);
477
+ if (source2 === null) return null;
478
+ let end2 = next.end;
479
+ const semi = tokens[j + 1];
480
+ if (semi && semi.type === "punct" && semi.value === ";") end2 = semi.end;
481
+ decls.push({ source: source2, bindings, start: tok.start, end: end2 });
482
+ continue;
483
+ }
484
+ const at = (k) => tokens[k];
485
+ const isPunct = (k, v) => {
486
+ const t = at(k);
487
+ return !!t && t.type === "punct" && t.value === v;
488
+ };
489
+ const isIdent = (k, v) => {
490
+ const t = at(k);
491
+ return !!t && t.type === "ident" && (v === void 0 || t.value === v);
492
+ };
493
+ if (isIdent(j, "type") && !isIdent(j + 1, "from") && !isPunct(j + 1, ",")) {
494
+ typeOnly = true;
495
+ j++;
496
+ }
497
+ if (isIdent(j) && !isIdent(j, "from")) {
498
+ bindings.push({ imported: "default", local: at(j).value });
499
+ j++;
500
+ if (isPunct(j, ",")) j++;
501
+ }
502
+ if (isPunct(j, "*")) {
503
+ if (!isIdent(j + 1, "as") || !isIdent(j + 2)) return null;
504
+ bindings.push({ imported: "*", local: at(j + 2).value });
505
+ j += 3;
506
+ } else if (isPunct(j, "{")) {
507
+ j++;
508
+ while (!isPunct(j, "}")) {
509
+ const t = at(j);
510
+ if (!t) return null;
511
+ let specTypeOnly = false;
512
+ if (isIdent(j, "type") && (isIdent(j + 1) || at(j + 1)?.type === "string") && !isIdent(j + 1, "as")) {
513
+ specTypeOnly = true;
514
+ j++;
515
+ }
516
+ const nameTok = at(j);
517
+ let imported = null;
518
+ if (nameTok?.type === "ident") imported = nameTok.value;
519
+ else if (nameTok?.type === "string") imported = stringTokenValue(code, nameTok);
520
+ if (imported === null) return null;
521
+ j++;
522
+ let local = imported;
523
+ if (isIdent(j, "as")) {
524
+ if (!isIdent(j + 1)) return null;
525
+ local = at(j + 1).value;
526
+ j += 2;
527
+ }
528
+ if (!specTypeOnly) bindings.push({ imported, local });
529
+ if (isPunct(j, ",")) j++;
530
+ else if (!isPunct(j, "}")) return null;
531
+ }
532
+ j++;
533
+ }
534
+ if (!isIdent(j, "from")) return null;
535
+ const srcTok = at(j + 1);
536
+ if (!srcTok || srcTok.type !== "string") return null;
537
+ const source = stringTokenValue(code, srcTok);
538
+ if (source === null) return null;
539
+ let end = srcTok.end;
540
+ j += 2;
541
+ if (isIdent(j, "with") || isIdent(j, "assert")) {
542
+ if (!isPunct(j + 1, "{")) return null;
543
+ let k = j + 2;
544
+ while (at(k) && !isPunct(k, "}")) k++;
545
+ if (!at(k)) return null;
546
+ end = at(k).end;
547
+ j = k + 1;
548
+ }
549
+ if (isPunct(j, ";")) end = at(j).end;
550
+ decls.push({ source, bindings: typeOnly ? [] : bindings, start: tok.start, end });
551
+ i = j;
552
+ }
553
+ return decls;
554
+ }
555
+ var SCAN_CACHE_SIZE = 4;
556
+ var scanCache = /* @__PURE__ */ new Map();
557
+ function scanModule(code) {
558
+ const hit = scanCache.get(code);
559
+ if (hit !== void 0) return hit;
560
+ const tokens = tokenize(code);
561
+ const imports = tokens && collectImports(code, tokens);
562
+ const scan = tokens && imports ? { tokens, imports } : null;
563
+ if (scanCache.size >= SCAN_CACHE_SIZE) scanCache.delete(scanCache.keys().next().value);
564
+ scanCache.set(code, scan);
565
+ return scan;
566
+ }
567
+ function isSibuSource(source) {
568
+ return source === "sibujs" || source.startsWith("sibujs/");
569
+ }
570
+ function sibuBindings(imports, mainOnly = false) {
571
+ const out = /* @__PURE__ */ new Map();
572
+ for (const decl of imports) {
573
+ if (mainOnly ? decl.source !== "sibujs" : !isSibuSource(decl.source)) continue;
574
+ for (const b of decl.bindings) {
575
+ if (b.imported === "*" || b.imported === "default") continue;
576
+ out.set(b.local, b.imported);
577
+ }
578
+ }
579
+ return out;
580
+ }
581
+ function forEachBindingRef(tokens, imports, visit) {
582
+ const inImport = (offset) => imports.some((d) => offset >= d.start && offset < d.end);
583
+ const walk = (list) => {
584
+ for (let i = 0; i < list.length; i++) {
585
+ const tok = list[i];
586
+ if (tok.type === "template") {
587
+ for (const e of tok.exprs) walk(e.tokens);
588
+ continue;
589
+ }
590
+ if (tok.type !== "ident") continue;
591
+ const prev = list[i - 1];
592
+ if (prev && prev.type === "punct" && (prev.value === "." || prev.value === "?." || prev.value === "#")) continue;
593
+ if (inImport(tok.start)) continue;
594
+ visit({ tok, list, index: i });
595
+ }
596
+ };
597
+ walk(tokens);
598
+ }
599
+ var EXPRESSION_KEYWORDS = /* @__PURE__ */ new Set([...REGEX_AFTER_KEYWORD, "default", "extends"]);
600
+ function isLineTerminator(c) {
601
+ return c === 10 || c === 13 || c === 8232 || c === 8233;
602
+ }
603
+ function lineBreakBetween(code, from, to) {
604
+ for (let i = from; i < to; i++) if (isLineTerminator(code.charCodeAt(i))) return true;
605
+ return false;
606
+ }
607
+ function endsValue(tok) {
608
+ if (!tok) return false;
609
+ switch (tok.type) {
610
+ case "number":
611
+ case "string":
612
+ case "regex":
613
+ case "template":
614
+ return true;
615
+ case "ident":
616
+ return !EXPRESSION_KEYWORDS.has(tok.value);
617
+ case "punct":
618
+ return tok.value === ")" || tok.value === "]";
619
+ }
620
+ }
621
+ function isDeclarationHead(code, list, index) {
622
+ const tok = list[index];
623
+ const prev = list[index - 1];
624
+ if (prev?.type === "ident") {
625
+ if (prev.value === "function") return true;
626
+ if (!EXPRESSION_KEYWORDS.has(prev.value) && !lineBreakBetween(code, prev.end, tok.start)) return true;
627
+ } else if (prev?.type === "punct") {
628
+ const before = list[index - 2];
629
+ if (prev.value === "*" && !endsValue(before) && !(before?.type === "ident" && before.value === "yield"))
630
+ return true;
631
+ if (prev.value === "@") return true;
632
+ }
633
+ let depth = 0;
634
+ let close = -1;
635
+ for (let k = index + 1; k < list.length; k++) {
636
+ const t = list[k];
637
+ if (t.type !== "punct") continue;
638
+ if (t.value === "(") depth++;
639
+ else if (t.value === ")" && --depth === 0) {
640
+ close = k;
641
+ break;
642
+ }
643
+ }
644
+ if (close === -1) return true;
645
+ const after = list[close + 1];
646
+ if (after?.type !== "punct") return false;
647
+ if (after.value === "{") return true;
648
+ if (after.value === ":") {
649
+ if (!prev) return true;
650
+ if (prev.type === "punct") return ["{", "}", ";", ",", "*"].includes(prev.value);
651
+ return prev.type === "ident" && !EXPRESSION_KEYWORDS.has(prev.value);
652
+ }
653
+ return false;
654
+ }
655
+ function bindingUses(code, scan, names) {
656
+ const shadowed = /* @__PURE__ */ new Set();
657
+ const bound = /* @__PURE__ */ new Map();
658
+ for (const decl of scan.imports) {
659
+ for (const b of decl.bindings) bound.set(b.local, (bound.get(b.local) ?? 0) + 1);
660
+ }
661
+ for (const name of names) if ((bound.get(name) ?? 0) > 1) shadowed.add(name);
662
+ const calls = [];
663
+ const tagged = [];
664
+ forEachBindingRef(scan.tokens, scan.imports, (ref) => {
665
+ const { tok, list, index } = ref;
666
+ if (!names.has(tok.value)) return;
667
+ const next = list[index + 1];
668
+ if (next && next.type === "punct" && next.value === "(") {
669
+ if (isDeclarationHead(code, list, index)) shadowed.add(tok.value);
670
+ else calls.push(ref);
671
+ } else if (next && next.type === "template") {
672
+ const prev = list[index - 1];
673
+ if (prev?.type === "punct" && prev.value === "@") shadowed.add(tok.value);
674
+ else tagged.push(ref);
675
+ } else {
676
+ shadowed.add(tok.value);
677
+ }
678
+ });
679
+ return {
680
+ calls: calls.filter((r) => !shadowed.has(r.tok.value)),
681
+ tagged: tagged.filter((r) => !shadowed.has(r.tok.value)),
682
+ shadowed
683
+ };
684
+ }
685
+ function uniquePrefix(code, base = "__sibujs") {
686
+ let prefix = `${base}$`;
687
+ for (let n = 1; code.includes(prefix); n++) prefix = `${base}${n}$`;
688
+ return prefix;
689
+ }
690
+ var PURE_FACTORIES = /* @__PURE__ */ new Set([
691
+ "tagFactory",
692
+ "context",
693
+ "defineComponent",
694
+ "withProps",
695
+ "withDefaults",
696
+ "pure",
697
+ "noSideEffect"
698
+ ]);
699
+ var PURE_COMMENT = "/*#__PURE__*/ ";
700
+ function pureAnnotationEdits(code) {
701
+ if (!code.includes("sibujs")) return [];
702
+ const scan = scanModule(code);
703
+ if (!scan) return [];
704
+ const candidates = /* @__PURE__ */ new Set();
705
+ for (const [local, imported] of sibuBindings(scan.imports)) if (PURE_FACTORIES.has(imported)) candidates.add(local);
706
+ if (candidates.size === 0) return [];
707
+ const uses = bindingUses(code, scan, candidates);
708
+ const unsafe = new Set(uses.shadowed);
709
+ for (const ref of uses.tagged) unsafe.add(ref.tok.value);
710
+ return uses.calls.filter(({ tok }) => {
711
+ if (unsafe.has(tok.value)) return false;
712
+ return !/\/\*\s*[#@]__PURE__\s*\*\/\s*$/.test(code.slice(Math.max(0, tok.start - 40), tok.start));
713
+ }).map(({ tok }) => ({ start: tok.start, end: tok.start, text: PURE_COMMENT }));
714
+ }
715
+ function injectPureAnnotations(code) {
716
+ const edits = normalizeEdits(pureAnnotationEdits(code));
717
+ return edits && edits.length > 0 ? applyEdits(code, edits) : code;
718
+ }
719
+ function importsSibu(code) {
720
+ if (!code.includes("sibujs")) return false;
721
+ const scan = scanModule(code);
722
+ return !!scan?.imports.some((d) => isSibuSource(d.source));
723
+ }
724
+
725
+ // src/build/staticAnalysis.ts
726
+ var STATIC_TAGS = /* @__PURE__ */ new Set([
727
+ "div",
728
+ "span",
729
+ "section",
730
+ "article",
731
+ "header",
732
+ "footer",
733
+ "nav",
734
+ "main",
735
+ "aside",
736
+ "p",
737
+ "h1",
738
+ "h2",
739
+ "h3",
740
+ "h4",
741
+ "h5",
742
+ "h6",
743
+ "blockquote",
744
+ "li",
745
+ "ol",
746
+ "ul",
747
+ "a",
748
+ "b",
749
+ "em",
750
+ "i",
751
+ "strong",
752
+ "small",
753
+ "code",
754
+ "mark",
755
+ "img",
756
+ "br",
757
+ "hr",
758
+ "input",
759
+ "button",
760
+ "form",
761
+ "label",
762
+ "details",
763
+ "summary",
764
+ "dialog"
765
+ ]);
766
+ var VOID_ELEMENTS = /* @__PURE__ */ new Set([
767
+ "br",
768
+ "hr",
769
+ "img",
770
+ "input",
771
+ "meta",
772
+ "link",
773
+ "area",
774
+ "base",
775
+ "col",
776
+ "embed",
777
+ "param",
778
+ "source",
779
+ "track",
780
+ "wbr"
781
+ ]);
782
+ var SPECIAL_PROPS = /* @__PURE__ */ new Set(["style", "ref", "on", "onElement"]);
783
+ var NON_REFLECTING_BOOLEANS = /* @__PURE__ */ new Set(["checked", "selected"]);
784
+ function readLiteral(code, tok) {
785
+ if (!tok) return null;
786
+ if (tok.type === "string") {
787
+ const value = stringTokenValue(code, tok);
788
+ return value === null ? null : { kind: "string", value };
789
+ }
790
+ if (tok.type === "number" && /^(0|[1-9]\d*)(\.\d+)?$/.test(tok.value)) {
791
+ return { kind: "number", value: String(Number(tok.value)) };
792
+ }
793
+ if (tok.type === "ident" && ["true", "false", "null", "undefined"].includes(tok.value)) {
794
+ return { kind: "keyword", value: tok.value };
795
+ }
796
+ return null;
797
+ }
798
+ function parserSafeText(s) {
799
+ return !s.includes("\r") && !s.includes("\0");
800
+ }
801
+ function escapeHtml(str) {
802
+ return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
803
+ }
804
+ function escapeAttr(str) {
805
+ return str.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
806
+ }
807
+ function attributeHtml(name, lit) {
808
+ if (!/^[a-zA-Z][a-zA-Z0-9-]*$/.test(name)) return null;
809
+ const lower = name.toLowerCase();
810
+ if (SPECIAL_PROPS.has(name) || lower === "style" || lower === "srcset") return null;
811
+ if (isEventHandlerAttr(name) || isUrlAttribute(name) || isHtmlContentAttribute(name)) return null;
812
+ if (lit.kind === "keyword") {
813
+ if (lit.value === "null" || lit.value === "undefined") return "";
814
+ const on = lit.value === "true";
815
+ if (lower.startsWith("aria-")) return `${lower}="${on}"`;
816
+ if (NON_REFLECTING_BOOLEANS.has(lower)) return null;
817
+ return on ? `${lower}=""` : "";
818
+ }
819
+ if (!parserSafeText(lit.value)) return null;
820
+ return `${lower}="${escapeAttr(lit.value)}"`;
821
+ }
822
+ function parseCall(code, list, i) {
823
+ const at = (k2) => list[k2];
824
+ const isPunct = (k2, v) => {
825
+ const t = at(k2);
826
+ return !!t && t.type === "punct" && t.value === v;
827
+ };
828
+ let k = i + 1;
829
+ const result = { end: 0, cls: null, id: null, attrs: [], text: null };
830
+ let nodesText = null;
831
+ if (isPunct(k, "{")) {
832
+ k++;
833
+ const seen = /* @__PURE__ */ new Set();
834
+ while (!isPunct(k, "}")) {
835
+ const keyTok = at(k);
836
+ let key = null;
837
+ if (keyTok?.type === "ident") key = keyTok.value;
838
+ else if (keyTok?.type === "string") key = stringTokenValue(code, keyTok);
839
+ if (key === null || !isPunct(k + 1, ":")) return null;
840
+ if (seen.has(key.toLowerCase())) return null;
841
+ seen.add(key.toLowerCase());
842
+ const lit = readLiteral(code, at(k + 2));
843
+ if (lit === null) return null;
844
+ k += 3;
845
+ if (isPunct(k, ",")) k++;
846
+ else if (!isPunct(k, "}")) return null;
847
+ if (key === "class" || key === "id") {
848
+ if (lit.kind !== "string" || !parserSafeText(lit.value)) return null;
849
+ if (key === "class") result.cls = lit.value;
850
+ else result.id = lit.value;
851
+ } else if (key === "nodes") {
852
+ if (lit.kind !== "string" || !parserSafeText(lit.value)) return null;
853
+ nodesText = lit.value;
854
+ } else {
855
+ const html = attributeHtml(key, lit);
856
+ if (html === null) return null;
857
+ if (html) result.attrs.push(html);
858
+ }
859
+ }
860
+ k++;
861
+ if (isPunct(k, ",")) {
862
+ const second = readLiteral(code, at(k + 1));
863
+ if (second === null) {
864
+ if (!isPunct(k + 1, ")")) return null;
865
+ k++;
866
+ } else {
867
+ if (second.kind !== "string" || !parserSafeText(second.value)) return null;
868
+ result.text = second.value;
869
+ k += 2;
870
+ if (isPunct(k, ",")) k++;
871
+ }
872
+ }
873
+ if (result.text === null) result.text = nodesText;
874
+ } else {
875
+ const first = readLiteral(code, at(k));
876
+ if (first === null || first.kind !== "string" || !parserSafeText(first.value)) return null;
877
+ k++;
878
+ if (isPunct(k, ",") && at(k + 1)?.type === "string") {
879
+ const second = readLiteral(code, at(k + 1));
880
+ if (second === null || second.kind !== "string" || !parserSafeText(second.value)) return null;
881
+ result.cls = first.value;
882
+ result.text = second.value;
883
+ k += 2;
884
+ } else {
885
+ result.text = first.value;
886
+ }
887
+ if (isPunct(k, ",")) k++;
888
+ }
889
+ if (!isPunct(k, ")")) return null;
890
+ result.end = at(k).end;
891
+ return result;
892
+ }
893
+ function toHtml(tag, call) {
894
+ const attrs = [];
895
+ if (call.cls !== null) attrs.push(`class="${escapeAttr(call.cls)}"`);
896
+ if (call.id !== null) attrs.push(`id="${escapeAttr(call.id)}"`);
897
+ attrs.push(...call.attrs);
898
+ const attrStr = attrs.length > 0 ? ` ${attrs.join(" ")}` : "";
899
+ if (VOID_ELEMENTS.has(tag)) {
900
+ if (call.text) return null;
901
+ return `<${tag}${attrStr} />`;
902
+ }
903
+ return `<${tag}${attrStr}>${escapeHtml(call.text ?? "")}</${tag}>`;
904
+ }
905
+ function analyzeStaticTemplates(code) {
906
+ const none = { hasStaticPatterns: false, patterns: [] };
907
+ if (!code.includes("sibujs")) return none;
908
+ const scan = scanModule(code);
909
+ if (!scan) return none;
910
+ const factories = /* @__PURE__ */ new Map();
911
+ for (const decl of scan.imports) {
912
+ if (decl.source !== "sibujs") continue;
913
+ for (const b of decl.bindings) if (STATIC_TAGS.has(b.imported)) factories.set(b.local, b.imported);
914
+ }
915
+ if (factories.size === 0) return none;
916
+ const uses = bindingUses(code, scan, new Set(factories.keys()));
917
+ const unsafe = new Set(uses.shadowed);
918
+ for (const ref of uses.tagged) unsafe.add(ref.tok.value);
919
+ const patterns = [];
920
+ for (const { tok, list, index } of uses.calls) {
921
+ if (unsafe.has(tok.value)) continue;
922
+ const tag = factories.get(tok.value);
923
+ const call = parseCall(code, list, index + 1);
924
+ if (!call) continue;
925
+ const templateHtml = toHtml(tag, call);
926
+ if (templateHtml === null) continue;
927
+ const start = list[index].start;
928
+ patterns.push({ original: code.slice(start, call.end), tag, templateHtml, start, end: call.end });
929
+ }
930
+ return { hasStaticPatterns: patterns.length > 0, patterns };
931
+ }
932
+
933
+ // src/build/templateCompiler.ts
934
+ var RAW_TEXT_TAGS = /* @__PURE__ */ new Set(["script", "style"]);
935
+ var VOID_ELEMENTS2 = /* @__PURE__ */ new Set([
22
936
  "area",
23
937
  "base",
24
938
  "br",
@@ -57,96 +971,10 @@ var SVG_TAGS = /* @__PURE__ */ new Set([
57
971
  "symbol",
58
972
  "marker"
59
973
  ]);
60
- function findHtmlTemplates(code) {
61
- const results = [];
62
- const tagRegex = /\bhtml\s*`/g;
63
- let match;
64
- while ((match = tagRegex.exec(code)) !== null) {
65
- const start = match.index;
66
- const backtickStart = code.indexOf("`", start + 4);
67
- if (backtickStart === -1) continue;
68
- const parsed = parseTemplateLiteral(code, backtickStart);
69
- if (!parsed) continue;
70
- results.push({
71
- start,
72
- end: parsed.end,
73
- strings: parsed.strings,
74
- exprCount: parsed.exprCount
75
- });
76
- tagRegex.lastIndex = parsed.end;
77
- }
78
- return results;
79
- }
80
- function parseTemplateLiteral(code, openBacktick) {
81
- const strings = [];
82
- let exprCount = 0;
83
- let pos = openBacktick + 1;
84
- let current = "";
85
- while (pos < code.length) {
86
- const ch = code[pos];
87
- if (ch === "`") {
88
- strings.push(current);
89
- return { end: pos + 1, strings, exprCount };
90
- }
91
- if (ch === "$" && pos + 1 < code.length && code[pos + 1] === "{") {
92
- strings.push(current);
93
- current = "";
94
- exprCount++;
95
- pos += 2;
96
- let depth = 1;
97
- while (pos < code.length && depth > 0) {
98
- const c = code[pos];
99
- if (c === "{") depth++;
100
- else if (c === "}") depth--;
101
- else if (c === '"' || c === "'" || c === "`") {
102
- pos = skipString(code, pos);
103
- continue;
104
- }
105
- if (depth > 0) pos++;
106
- }
107
- if (depth !== 0) return null;
108
- pos++;
109
- continue;
110
- }
111
- if (ch === "\\") {
112
- current += code[pos] + (code[pos + 1] || "");
113
- pos += 2;
114
- continue;
115
- }
116
- current += ch;
117
- pos++;
118
- }
119
- return null;
120
- }
121
- function skipString(code, start) {
122
- const quote = code[start];
123
- let pos = start + 1;
124
- while (pos < code.length) {
125
- if (code[pos] === "\\") {
126
- pos += 2;
127
- continue;
128
- }
129
- if (code[pos] === quote) return pos + 1;
130
- if (quote === "`" && code[pos] === "$" && code[pos + 1] === "{") {
131
- pos += 2;
132
- let depth = 1;
133
- while (pos < code.length && depth > 0) {
134
- if (code[pos] === "{") depth++;
135
- else if (code[pos] === "}") depth--;
136
- else if (code[pos] === '"' || code[pos] === "'" || code[pos] === "`") {
137
- pos = skipString(code, pos);
138
- continue;
139
- }
140
- if (depth > 0) pos++;
141
- }
142
- pos++;
143
- continue;
144
- }
145
- pos++;
146
- }
147
- return pos;
148
- }
149
- function parseTemplateToAST(strings) {
974
+ var SVG_NS = "http://www.w3.org/2000/svg";
975
+ var RuntimeParseError = class extends Error {
976
+ };
977
+ function parseTemplate(strings) {
150
978
  const exprCount = strings.length - 1;
151
979
  let template = strings[0];
152
980
  for (let i = 0; i < exprCount; i++) {
@@ -155,26 +983,34 @@ function parseTemplateToAST(strings) {
155
983
  let pos = 0;
156
984
  const len = template.length;
157
985
  function skipWs() {
158
- while (pos < len && /\s/.test(template[pos])) pos++;
986
+ while (pos < len && (template[pos] === " " || template[pos] === " " || template[pos] === "\n" || template[pos] === "\r"))
987
+ pos++;
159
988
  }
160
989
  function tryExprIdx() {
161
- if (template[pos] !== "\0") return -1;
990
+ if (template.charCodeAt(pos) !== 0) return -1;
162
991
  const start = pos;
163
992
  pos++;
164
- let idxStr = "";
165
- while (pos < len && template[pos] !== "\0") idxStr += template[pos++];
993
+ let idx = 0;
994
+ while (pos < len && template.charCodeAt(pos) !== 0) {
995
+ idx = idx * 10 + (template.charCodeAt(pos) - 48);
996
+ pos++;
997
+ }
166
998
  if (pos < len) pos++;
167
- const idx = Number.parseInt(idxStr, 10);
168
- if (Number.isNaN(idx) || idx < 0 || idx >= exprCount) {
999
+ if (idx < 0 || idx >= exprCount) {
169
1000
  pos = start;
170
1001
  return -1;
171
1002
  }
172
1003
  return idx;
173
1004
  }
174
1005
  function readTagName() {
175
- let name = "";
176
- while (pos < len && /[a-zA-Z0-9-]/.test(template[pos])) name += template[pos++];
177
- return name;
1006
+ const start = pos;
1007
+ while (pos < len) {
1008
+ const c = template.charCodeAt(pos);
1009
+ if (c >= 97 && c <= 122 || c >= 65 && c <= 90 || c >= 48 && c <= 57 || c === 45) {
1010
+ pos++;
1011
+ } else break;
1012
+ }
1013
+ return template.slice(start, pos);
178
1014
  }
179
1015
  function parseAttrValue() {
180
1016
  skipWs();
@@ -182,51 +1018,72 @@ function parseTemplateToAST(strings) {
182
1018
  pos++;
183
1019
  skipWs();
184
1020
  const exprIdx = tryExprIdx();
185
- if (exprIdx >= 0) return { kind: "expr", index: exprIdx };
1021
+ if (exprIdx >= 0) return { kind: "expr", idx: exprIdx };
186
1022
  const quote = template[pos];
187
1023
  if (quote === '"' || quote === "'") {
188
1024
  pos++;
189
- const parts = [];
190
- let current = "";
1025
+ const statics2 = [];
1026
+ const exprs2 = [];
1027
+ let current2 = "";
191
1028
  while (pos < len && template[pos] !== quote) {
192
1029
  const innerIdx = tryExprIdx();
193
1030
  if (innerIdx >= 0) {
194
- if (current) parts.push({ kind: "static", value: current });
195
- current = "";
196
- parts.push({ kind: "expr", index: innerIdx });
1031
+ statics2.push(current2);
1032
+ current2 = "";
1033
+ exprs2.push(innerIdx);
197
1034
  } else {
198
- current += template[pos++];
1035
+ current2 += template[pos++];
199
1036
  }
200
1037
  }
201
1038
  if (pos < len) pos++;
202
- if (current) parts.push({ kind: "static", value: current });
203
- if (parts.length === 1 && parts[0].kind === "static") {
204
- return { kind: "static", value: parts[0].value };
205
- }
206
- if (parts.some((p) => p.kind === "expr")) {
207
- return { kind: "mixed", parts };
1039
+ statics2.push(current2);
1040
+ if (exprs2.length === 0) return { kind: "static", value: statics2[0] };
1041
+ return { kind: "mixed", statics: statics2, exprs: exprs2 };
1042
+ }
1043
+ const statics = [];
1044
+ const exprs = [];
1045
+ let current = "";
1046
+ while (pos < len) {
1047
+ const c = template.charCodeAt(pos);
1048
+ if (c === 32 || c === 9 || c === 10 || c === 13 || c === 62) break;
1049
+ const innerIdx = tryExprIdx();
1050
+ if (innerIdx >= 0) {
1051
+ statics.push(current);
1052
+ current = "";
1053
+ exprs.push(innerIdx);
1054
+ } else {
1055
+ current += template[pos++];
208
1056
  }
209
- return { kind: "static", value: parts.map((p) => p.value).join("") };
210
1057
  }
211
- let val = "";
212
- while (pos < len && !/[\s>/]/.test(template[pos])) val += template[pos++];
213
- return { kind: "static", value: val };
1058
+ statics.push(current);
1059
+ if (exprs.length === 0) return { kind: "static", value: statics[0] };
1060
+ return { kind: "mixed", statics, exprs };
214
1061
  }
215
1062
  function parseAttrs() {
216
1063
  const attrs = [];
217
1064
  while (pos < len) {
218
1065
  skipWs();
219
1066
  if (template[pos] === ">" || template[pos] === "/") break;
220
- let attrName = "";
221
- while (pos < len && /[a-zA-Z0-9\-:_.]/.test(template[pos])) attrName += template[pos++];
1067
+ const attrStart = pos;
1068
+ while (pos < len) {
1069
+ const c = template.charCodeAt(pos);
1070
+ if (c >= 97 && c <= 122 || c >= 65 && c <= 90 || c >= 48 && c <= 57 || c === 45 || c === 58 || c === 95 || c === 46) {
1071
+ pos++;
1072
+ } else break;
1073
+ }
1074
+ const attrName = template.slice(attrStart, pos);
222
1075
  if (!attrName) break;
223
1076
  const val = parseAttrValue();
224
1077
  if (attrName.startsWith("on:")) {
225
- if (val.kind === "expr") {
226
- attrs.push({ name: attrName.slice(3), value: { kind: "event", index: val.index } });
227
- }
1078
+ if (val.kind === "expr") attrs.push({ t: 3, name: attrName.slice(3), idx: val.idx });
1079
+ } else if (val.kind === "bool") {
1080
+ attrs.push({ t: 4, name: attrName });
1081
+ } else if (val.kind === "static") {
1082
+ attrs.push({ t: 0, name: attrName, value: val.value });
1083
+ } else if (val.kind === "expr") {
1084
+ attrs.push({ t: 1, name: attrName, idx: val.idx });
228
1085
  } else {
229
- attrs.push({ name: attrName, value: val });
1086
+ attrs.push({ t: 2, name: attrName, statics: val.statics, exprs: val.exprs });
230
1087
  }
231
1088
  }
232
1089
  return attrs;
@@ -240,40 +1097,67 @@ function parseTemplateToAST(strings) {
240
1097
  const idx = tryExprIdx();
241
1098
  if (idx >= 0) {
242
1099
  const collapsed2 = collapseWs(text);
243
- if (collapsed2) children.push({ kind: "text", value: collapsed2 });
1100
+ if (collapsed2) children.push({ t: 1, value: collapsed2 });
244
1101
  text = "";
245
- children.push({ kind: "expr", index: idx });
1102
+ children.push({ t: 2, idx });
246
1103
  } else {
247
1104
  text += template[pos++];
248
1105
  }
249
1106
  }
250
1107
  const collapsed = collapseWs(text);
251
- if (collapsed) children.push({ kind: "text", value: collapsed });
1108
+ if (collapsed) children.push({ t: 1, value: collapsed });
252
1109
  }
253
1110
  function parseChildren() {
254
1111
  const children = [];
255
1112
  while (pos < len) {
256
1113
  if (template[pos] === "<" && pos + 1 < len && template[pos + 1] === "/") break;
257
1114
  if (template[pos] === "<") {
1115
+ const next = template[pos + 1];
1116
+ if (next === "!") {
1117
+ if (template.startsWith("<!--", pos)) {
1118
+ const end = template.indexOf("-->", pos + 4);
1119
+ pos = end === -1 ? len : end + 3;
1120
+ } else if (template.startsWith("<![CDATA[", pos)) {
1121
+ const end = template.indexOf("]]>", pos + 9);
1122
+ pos = end === -1 ? len : end + 3;
1123
+ } else {
1124
+ const end = template.indexOf(">", pos);
1125
+ pos = end === -1 ? len : end + 1;
1126
+ }
1127
+ continue;
1128
+ }
1129
+ if (next === "?") {
1130
+ const end = template.indexOf(">", pos);
1131
+ pos = end === -1 ? len : end + 1;
1132
+ continue;
1133
+ }
1134
+ if (!(next >= "a" && next <= "z") && !(next >= "A" && next <= "Z")) {
1135
+ children.push({ t: 1, value: "<" });
1136
+ pos++;
1137
+ continue;
1138
+ }
258
1139
  pos++;
259
1140
  const tag = readTagName();
260
1141
  const attrs = parseAttrs();
261
1142
  skipWs();
262
- const isVoid = VOID_ELEMENTS.has(tag);
1143
+ const isVoid = VOID_ELEMENTS2.has(tag);
263
1144
  const isSelfClosing = template[pos] === "/";
264
1145
  if (isSelfClosing) pos++;
265
1146
  if (pos < len) pos++;
266
1147
  if (isVoid || isSelfClosing) {
267
- children.push({ kind: "element", el: { tag, attrs, children: [] } });
1148
+ children.push({ t: 0, el: { tag, svg: SVG_TAGS.has(tag), attrs, children: [] } });
268
1149
  } else {
269
1150
  const inner = parseChildren();
1151
+ if (RAW_TEXT_TAGS.has(tag.toLowerCase()) && inner.some((c) => c.t === 2)) {
1152
+ throw new RuntimeParseError(tag);
1153
+ }
270
1154
  if (template[pos] === "<" && pos + 1 < len && template[pos + 1] === "/") {
271
1155
  pos += 2;
272
1156
  readTagName();
273
1157
  skipWs();
274
1158
  if (pos < len && template[pos] === ">") pos++;
275
1159
  }
276
- children.push({ kind: "element", el: { tag, attrs, children: inner } });
1160
+ children.push({ t: 0, el: { tag, svg: SVG_TAGS.has(tag), attrs, children: inner } });
277
1161
  }
278
1162
  } else {
279
1163
  parseTextChildren(children);
@@ -283,303 +1167,230 @@ function parseTemplateToAST(strings) {
283
1167
  }
284
1168
  return parseChildren();
285
1169
  }
286
- function generateElement(el, valuesVar) {
287
- const tag = el.tag;
288
- const isSvg = SVG_TAGS.has(tag);
289
- const parts = [];
290
- for (const attr of el.attrs) {
291
- const v = attr.value;
292
- switch (v.kind) {
293
- case "static":
294
- parts.push(`${JSON.stringify(attr.name)}: ${JSON.stringify(v.value)}`);
295
- break;
296
- case "expr":
297
- parts.push(`${JSON.stringify(attr.name)}: ${valuesVar}[${v.index}]`);
298
- break;
299
- case "mixed": {
300
- const concat = v.parts.map((p) => p.kind === "static" ? JSON.stringify(p.value) : `String(${valuesVar}[${p.index}])`).join(" + ");
301
- parts.push(`${JSON.stringify(attr.name)}: ${concat}`);
302
- break;
1170
+ var IDL_SYNCED_ATTRS = /* @__PURE__ */ new Set(["value", "checked"]);
1171
+ function generateBody(roots, h) {
1172
+ const lines = [];
1173
+ let n = 0;
1174
+ const q = jsStringLiteral;
1175
+ const P = h.prefix;
1176
+ function genElement(el) {
1177
+ const v = `e${n++}`;
1178
+ h.tags.add(el.tag);
1179
+ if (el.svg) h.svg = true;
1180
+ lines.push(
1181
+ el.svg ? `const ${v} = document.createElementNS(${q(SVG_NS)}, ${q(el.tag)});` : `const ${v} = document.createElement(${q(el.tag)});`
1182
+ );
1183
+ for (const attr of el.attrs) {
1184
+ switch (attr.t) {
1185
+ case 0:
1186
+ lines.push(`${v}.setAttribute(${q(attr.name)}, ${q(attr.value)});`);
1187
+ break;
1188
+ case 4:
1189
+ lines.push(`${v}.setAttribute(${q(attr.name)}, "");`);
1190
+ break;
1191
+ case 1:
1192
+ case 2: {
1193
+ if (IDL_SYNCED_ATTRS.has(attr.name.toLowerCase())) return null;
1194
+ h.used.add("attr");
1195
+ if (attr.t === 1) {
1196
+ lines.push(`${P}attr(${v}, ${q(attr.name)}, v${attr.idx});`);
1197
+ } else {
1198
+ h.used.add("str");
1199
+ let expr = q(attr.statics[0]);
1200
+ for (let j = 0; j < attr.exprs.length; j++) {
1201
+ expr += ` + ${P}str(v${attr.exprs[j]}) + ${q(attr.statics[j + 1])}`;
1202
+ }
1203
+ lines.push(`${P}attr(${v}, ${q(attr.name)}, ${expr});`);
1204
+ }
1205
+ break;
1206
+ }
1207
+ case 3:
1208
+ h.used.add("on");
1209
+ lines.push(`${P}on(${v}, ${q(attr.name)}, v${attr.idx});`);
1210
+ break;
1211
+ }
1212
+ }
1213
+ for (const child of el.children) {
1214
+ if (child.t === 0) {
1215
+ const c = genElement(child.el);
1216
+ if (c === null) return null;
1217
+ lines.push(`${v}.appendChild(${c});`);
1218
+ } else if (child.t === 1) {
1219
+ lines.push(`${v}.appendChild(document.createTextNode(${q(child.value)}));`);
1220
+ } else {
1221
+ h.used.add("child");
1222
+ lines.push(`${P}child(${v}, v${child.idx});`);
303
1223
  }
304
- case "bool":
305
- parts.push(`${JSON.stringify(attr.name)}: true`);
306
- break;
307
- case "event":
308
- break;
309
1224
  }
1225
+ return v;
310
1226
  }
311
- const events = el.attrs.filter((a) => a.value.kind === "event");
312
- if (events.length > 0) {
313
- const eventEntries = events.map((a) => {
314
- const v = a.value;
315
- return `${JSON.stringify(a.name)}: ${valuesVar}[${v.index}]`;
316
- });
317
- parts.push(`on: { ${eventEntries.join(", ")} }`);
1227
+ if (roots.length === 1 && roots[0].t === 0) {
1228
+ const root = genElement(roots[0].el);
1229
+ if (root === null) return null;
1230
+ lines.push(`return ${root};`);
1231
+ return lines.join("\n ");
318
1232
  }
319
- if (el.children.length > 0) {
320
- const childExprs = el.children.map((c) => generateChild(c, valuesVar));
321
- if (childExprs.length === 1) {
322
- parts.push(`nodes: ${childExprs[0]}`);
1233
+ lines.push(`const w = document.createElement("div");`);
1234
+ for (const root of roots) {
1235
+ if (root.t === 0) {
1236
+ const c = genElement(root.el);
1237
+ if (c === null) return null;
1238
+ lines.push(`w.appendChild(${c});`);
1239
+ } else if (root.t === 1) {
1240
+ lines.push(`w.appendChild(document.createTextNode(${q(root.value)}));`);
323
1241
  } else {
324
- parts.push(`nodes: [${childExprs.join(", ")}]`);
1242
+ return null;
325
1243
  }
326
1244
  }
327
- const propsStr = parts.length > 0 ? `{ ${parts.join(", ")} }` : void 0;
328
- if (isSvg) {
329
- return propsStr ? `__sbTagFactory(${JSON.stringify(tag)}, __sbSVG_NS)(${propsStr})` : `__sbTagFactory(${JSON.stringify(tag)}, __sbSVG_NS)({})`;
330
- }
331
- return propsStr ? `${tag}(${propsStr})` : `${tag}({})`;
1245
+ lines.push("return w;");
1246
+ return lines.join("\n ");
332
1247
  }
333
- function generateChild(child, valuesVar) {
334
- switch (child.kind) {
335
- case "element":
336
- return generateElement(child.el, valuesVar);
337
- case "text":
338
- return JSON.stringify(child.value);
339
- case "expr":
340
- return `${valuesVar}[${child.index}]`;
1248
+ function helperSource(h) {
1249
+ const P = h.prefix;
1250
+ const out = [];
1251
+ if (h.used.has("attr")) {
1252
+ out.push(
1253
+ `function ${P}attr(el, name, value) {
1254
+ const teardown = ${P}bindAttrs(el, { [name]: value });
1255
+ if (typeof value === "function") ${P}registerDisposer(el, teardown);
1256
+ }`
1257
+ );
341
1258
  }
342
- }
343
- function compileHtmlTemplates(code) {
344
- const templates = findHtmlTemplates(code);
345
- if (templates.length === 0) {
346
- return { code: null, usedTags: /* @__PURE__ */ new Set(), usesSvg: false, compiledCount: 0 };
347
- }
348
- const usedTags = /* @__PURE__ */ new Set();
349
- let usesSvg = false;
350
- let result = code;
351
- for (let i = templates.length - 1; i >= 0; i--) {
352
- const tmpl = templates[i];
353
- const ast = parseTemplateToAST(tmpl.strings);
354
- collectTags(ast, usedTags);
355
- if (ast.length > 1) usedTags.add("div");
356
- if (Array.from(usedTags).some((t) => SVG_TAGS.has(t))) usesSvg = true;
357
- const valuesVar = "__v";
358
- const childExprs = ast.map((c) => generateChild(c, valuesVar));
359
- const rootExpr = childExprs.length === 1 ? childExprs[0] : `div([${childExprs.join(", ")}])`;
360
- let compiled;
361
- if (tmpl.exprCount === 0) {
362
- compiled = rootExpr;
363
- } else {
364
- const body = rootExpr;
365
- const exprSource = extractExpressions(code, tmpl.start, tmpl.end, tmpl.exprCount);
366
- compiled = `((${valuesVar}) => ${body})([${exprSource.join(", ")}])`;
367
- }
368
- result = result.slice(0, tmpl.start) + compiled + result.slice(tmpl.end);
1259
+ if (h.used.has("str")) {
1260
+ out.push(`function ${P}str(value) {
1261
+ return value == null ? "" : String(value);
1262
+ }`);
369
1263
  }
370
- return { code: result, usedTags, usesSvg, compiledCount: templates.length };
371
- }
372
- function collectTags(children, tags) {
373
- for (const child of children) {
374
- if (child.kind === "element") {
375
- tags.add(child.el.tag);
376
- collectTags(child.el.children, tags);
377
- }
1264
+ if (h.used.has("on")) {
1265
+ out.push(
1266
+ `function ${P}on(el, name, handler) {
1267
+ if (typeof handler === "function") el.addEventListener(name, handler);
1268
+ }`
1269
+ );
378
1270
  }
379
- }
380
- function extractExpressions(code, templateStart, templateEnd, count) {
381
- const exprs = [];
382
- const backtickStart = code.indexOf("`", templateStart + 4);
383
- let pos = backtickStart + 1;
384
- for (let i = 0; i < count; i++) {
385
- while (pos < templateEnd) {
386
- if (code[pos] === "$" && code[pos + 1] === "{") {
387
- pos += 2;
388
- break;
389
- }
390
- if (code[pos] === "\\") {
391
- pos += 2;
392
- continue;
393
- }
394
- pos++;
395
- }
396
- const exprStart = pos;
397
- let depth = 1;
398
- while (pos < templateEnd && depth > 0) {
399
- const c = code[pos];
400
- if (c === "{") depth++;
401
- else if (c === "}") {
402
- depth--;
403
- if (depth === 0) break;
404
- } else if (c === '"' || c === "'" || c === "`") {
405
- pos = skipString(code, pos);
406
- continue;
407
- }
408
- pos++;
1271
+ if (h.used.has("child")) {
1272
+ out.push(
1273
+ `function ${P}child(el, value) {
1274
+ if (typeof value === "function") {
1275
+ el.appendChild(${P}Fragment([value]));
1276
+ } else if (value instanceof Node) {
1277
+ el.appendChild(value);
1278
+ } else if (Array.isArray(value)) {
1279
+ for (let i = 0; i < value.length; i++) {
1280
+ const item = value[i];
1281
+ if (item instanceof Node) el.appendChild(item);
1282
+ else if (item != null && typeof item !== "boolean") el.appendChild(document.createTextNode(String(item)));
409
1283
  }
410
- exprs.push(code.slice(exprStart, pos).trim());
411
- pos++;
1284
+ } else if (value != null && typeof value !== "boolean") {
1285
+ el.appendChild(document.createTextNode(String(value)));
412
1286
  }
413
- return exprs;
414
- }
415
-
416
- // src/build/staticAnalysis.ts
417
- var HTML_TAGS = /* @__PURE__ */ new Set([
418
- "div",
419
- "span",
420
- "section",
421
- "article",
422
- "header",
423
- "footer",
424
- "nav",
425
- "main",
426
- "aside",
427
- "p",
428
- "h1",
429
- "h2",
430
- "h3",
431
- "h4",
432
- "h5",
433
- "h6",
434
- "blockquote",
435
- "li",
436
- "ol",
437
- "ul",
438
- "pre",
439
- "a",
440
- "b",
441
- "em",
442
- "i",
443
- "strong",
444
- "small",
445
- "code",
446
- "mark",
447
- "img",
448
- "br",
449
- "hr",
450
- "input",
451
- "button",
452
- "form",
453
- "label",
454
- "select",
455
- "textarea",
456
- "option",
457
- "table",
458
- "tbody",
459
- "thead",
460
- "tfoot",
461
- "tr",
462
- "td",
463
- "th",
464
- "details",
465
- "summary",
466
- "dialog"
467
- ]);
468
- var VOID_ELEMENTS2 = /* @__PURE__ */ new Set([
469
- "br",
470
- "hr",
471
- "img",
472
- "input",
473
- "meta",
474
- "link",
475
- "area",
476
- "base",
477
- "col",
478
- "embed",
479
- "param",
480
- "source",
481
- "track",
482
- "wbr"
483
- ]);
484
- function analyzeStaticTemplates(code) {
485
- const patterns = [];
486
- const tagCallRegex = new RegExp(`\\b(${Array.from(HTML_TAGS).join("|")})\\s*\\(\\s*\\{([^}]*)\\}\\s*\\)`, "g");
487
- let match;
488
- while ((match = tagCallRegex.exec(code)) !== null) {
489
- const [fullMatch, tag, propsContent] = match;
490
- const start = match.index;
491
- const end = start + fullMatch.length;
492
- if (isStaticPropsContent(propsContent)) {
493
- const templateHtml = propsToHtml(tag, propsContent);
494
- if (templateHtml) {
495
- patterns.push({ original: fullMatch, tag, templateHtml, start, end });
496
- }
497
- }
1287
+ }`
1288
+ );
498
1289
  }
499
- return {
500
- hasStaticPatterns: patterns.length > 0,
501
- patterns
502
- };
1290
+ return out.join("\n");
1291
+ }
1292
+ function importSource(h) {
1293
+ const P = h.prefix;
1294
+ const core = [];
1295
+ if (h.used.has("child")) core.push(`Fragment as ${P}Fragment`);
1296
+ if (h.used.has("attr")) core.push(`registerDisposer as ${P}registerDisposer`);
1297
+ const lines = [];
1298
+ if (core.length > 0) lines.push(`import { ${core.join(", ")} } from "sibujs";`);
1299
+ if (h.used.has("attr")) lines.push(`import { bindAttrs as ${P}bindAttrs } from "sibujs/ui";`);
1300
+ return lines.join("\n");
503
1301
  }
504
- function isStaticPropsContent(propsContent) {
505
- if (/=>|function\s*\(|\bref\b|\bon\s*:/.test(propsContent)) {
506
- return false;
1302
+ function planHtmlTemplates(code) {
1303
+ const plan = {
1304
+ edits: [],
1305
+ append: "",
1306
+ usedTags: /* @__PURE__ */ new Set(),
1307
+ usesSvg: false,
1308
+ compiledCount: 0,
1309
+ skippedCount: 0
1310
+ };
1311
+ if (!code.includes("`") || !code.includes("sibujs")) return plan;
1312
+ const scan = scanModule(code);
1313
+ if (!scan) return plan;
1314
+ const tagNames = /* @__PURE__ */ new Set();
1315
+ for (const decl of scan.imports) {
1316
+ if (!isSibuSource(decl.source)) continue;
1317
+ for (const b of decl.bindings) if (b.imported === "html") tagNames.add(b.local);
507
1318
  }
508
- const props = propsContent.split(",").map((p) => p.trim()).filter(Boolean);
509
- for (const prop of props) {
510
- const colonIndex = prop.indexOf(":");
511
- if (colonIndex === -1) continue;
512
- const value = prop.substring(colonIndex + 1).trim();
513
- if (!isStaticValue(value)) {
514
- return false;
1319
+ if (tagNames.size === 0) return plan;
1320
+ const uses = bindingUses(code, scan, tagNames);
1321
+ if (uses.shadowed.size > 0 || uses.calls.length > 0 || uses.tagged.length === 0) return plan;
1322
+ const sites = new Set(uses.tagged.map((ref) => ref.tok));
1323
+ const h = { prefix: uniquePrefix(code), used: /* @__PURE__ */ new Set(), tags: /* @__PURE__ */ new Set(), svg: false };
1324
+ const functions = [];
1325
+ const compileTemplate = (tmpl) => {
1326
+ const strings = [];
1327
+ for (const qs of tmpl.quasis) {
1328
+ const cooked = cookEscapes(code.slice(qs.start, qs.end));
1329
+ if (cooked === null) return null;
1330
+ strings.push(cooked);
515
1331
  }
516
- }
517
- return true;
518
- }
519
- function isStaticValue(value) {
520
- if (/^["'].*["']$/.test(value)) return true;
521
- if (/^-?\d+(\.\d+)?$/.test(value)) return true;
522
- if (value === "true" || value === "false") return true;
523
- if (value === "null" || value === "undefined") return true;
524
- return false;
525
- }
526
- function propsToHtml(tag, propsContent) {
527
- const attrs = [];
528
- let nodesContent = "";
529
- const props = propsContent.split(",").map((p) => p.trim()).filter(Boolean);
530
- for (const prop of props) {
531
- const colonIndex = prop.indexOf(":");
532
- if (colonIndex === -1) continue;
533
- const key = prop.substring(0, colonIndex).trim();
534
- let value = prop.substring(colonIndex + 1).trim();
535
- if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
536
- value = value.slice(1, -1);
537
- }
538
- if (key === "nodes") {
539
- nodesContent = escapeHtml(value);
540
- } else if (key === "class" || key === "id") {
541
- attrs.push(`${key}="${escapeAttr(value)}"`);
542
- } else if (key !== "on" && key !== "ref" && key !== "style") {
543
- attrs.push(`${key}="${escapeAttr(String(value))}"`);
1332
+ let roots;
1333
+ try {
1334
+ roots = parseTemplate(strings);
1335
+ } catch (err) {
1336
+ if (err instanceof RuntimeParseError) return null;
1337
+ throw err;
544
1338
  }
545
- }
546
- const attrStr = attrs.length > 0 ? ` ${attrs.join(" ")}` : "";
547
- if (VOID_ELEMENTS2.has(tag)) {
548
- return `<${tag}${attrStr} />`;
549
- }
550
- return `<${tag}${attrStr}>${nodesContent}</${tag}>`;
551
- }
552
- function escapeHtml(str) {
553
- return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
554
- }
555
- function escapeAttr(str) {
556
- return str.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
1339
+ const scratch = { prefix: h.prefix, used: /* @__PURE__ */ new Set(), tags: /* @__PURE__ */ new Set(), svg: false };
1340
+ const body = generateBody(roots, scratch);
1341
+ if (body === null) return null;
1342
+ for (const u of scratch.used) h.used.add(u);
1343
+ for (const t of scratch.tags) h.tags.add(t);
1344
+ if (scratch.svg) h.svg = true;
1345
+ const name = `${h.prefix}t${functions.length}`;
1346
+ const params = tmpl.exprs.map((_, i) => `v${i}`).join(", ");
1347
+ functions.push(`function ${name}(${params}) {
1348
+ ${body}
1349
+ }`);
1350
+ return name;
1351
+ };
1352
+ const replaceSite = (tag, tmpl, name) => {
1353
+ const edit = (start, end, before, after) => plan.edits.push({ start, end, text: `${before}${lineBreaksIn(code, start, end)}${after}` });
1354
+ const exprs = tmpl.exprs;
1355
+ if (exprs.length === 0) {
1356
+ edit(tag.start, tmpl.end, `${name}(`, ")");
1357
+ return;
1358
+ }
1359
+ edit(tag.start, exprs[0].start, `${name}((`, "");
1360
+ for (let i = 1; i < exprs.length; i++) edit(exprs[i - 1].end, exprs[i].start, ")", ", (");
1361
+ edit(exprs[exprs.length - 1].end, tmpl.end, "", "))");
1362
+ };
1363
+ const visit = (list) => {
1364
+ for (let i = 0; i < list.length; i++) {
1365
+ const tok = list[i];
1366
+ if (sites.has(tok)) {
1367
+ const tmpl = list[i + 1];
1368
+ for (const e of tmpl.exprs) visit(e.tokens);
1369
+ const name = compileTemplate(tmpl);
1370
+ if (name !== null) {
1371
+ plan.compiledCount++;
1372
+ replaceSite(tok, tmpl, name);
1373
+ } else {
1374
+ plan.skippedCount++;
1375
+ }
1376
+ i++;
1377
+ } else if (tok.type === "template") {
1378
+ for (const e of tok.exprs) visit(e.tokens);
1379
+ }
1380
+ }
1381
+ };
1382
+ visit(scan.tokens);
1383
+ if (plan.compiledCount === 0) return { ...plan, edits: [] };
1384
+ const trailer = [importSource(h), helperSource(h), ...functions].filter(Boolean).join("\n");
1385
+ plan.append = `
1386
+ ${trailer}
1387
+ `;
1388
+ plan.usedTags = h.tags;
1389
+ plan.usesSvg = h.svg;
1390
+ return plan;
557
1391
  }
558
1392
 
559
1393
  // src/build/vite.ts
560
- var SVG_TAGS_SET = /* @__PURE__ */ new Set([
561
- "svg",
562
- "circle",
563
- "ellipse",
564
- "g",
565
- "line",
566
- "path",
567
- "polygon",
568
- "polyline",
569
- "rect",
570
- "text",
571
- "tspan",
572
- "defs",
573
- "clipPath",
574
- "mask",
575
- "pattern",
576
- "linearGradient",
577
- "radialGradient",
578
- "stop",
579
- "use",
580
- "symbol",
581
- "marker"
582
- ]);
583
1394
  var DEFAULT_INCLUDE = ["**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx"];
584
1395
  var DEFAULT_EXCLUDE = ["node_modules/**", "dist/**", "**/*.test.*", "**/*.spec.*"];
585
1396
  function matchesPattern(filePath, patterns) {
@@ -589,30 +1400,42 @@ function matchesPattern(filePath, patterns) {
589
1400
  return new RegExp(regexStr).test(normalized);
590
1401
  });
591
1402
  }
592
- function injectPureAnnotations(code) {
593
- const sibuFactories = [
594
- "tagFactory",
595
- "context",
596
- "defineComponent",
597
- "withProps",
598
- "withDefaults",
599
- "pure",
600
- "noSideEffect"
601
- ];
602
- let result = code;
603
- for (const factory of sibuFactories) {
604
- const pattern = new RegExp(`(?<!/\\*#__PURE__\\*/\\s*)\\b(${factory})\\s*\\(`, "g");
605
- result = result.replace(pattern, "/*#__PURE__*/ $1(");
1403
+ function devPrologueEdit(code) {
1404
+ let at = 0;
1405
+ if (code.startsWith("#!")) {
1406
+ const nl = code.indexOf("\n");
1407
+ if (nl === -1) return null;
1408
+ at = nl + 1;
606
1409
  }
607
- return result;
1410
+ return {
1411
+ start: at,
1412
+ end: at,
1413
+ text: '/* SibuJS Dev Mode */ if (typeof globalThis !== "undefined") { globalThis.__SIBU_DEV__ = true; } '
1414
+ };
608
1415
  }
609
- function injectDevHelpers(code) {
610
- if (code.includes('from "sibu"') || code.includes("from 'sibu'") || code.includes('from "sibu/') || code.includes("from 'sibu/")) {
611
- return `/* SibuJS Dev Mode */
612
- if (typeof globalThis !== 'undefined') { (globalThis as unknown as Record<string, unknown>).__SIBU_DEV__ = true; }
613
- ${code}`;
614
- }
615
- return code;
1416
+ function staticOptimizationEdits(code) {
1417
+ const analysis = analyzeStaticTemplates(code);
1418
+ if (!analysis.hasStaticPatterns) return null;
1419
+ const P = uniquePrefix(code);
1420
+ const edits = analysis.patterns.map((pattern) => ({
1421
+ start: pattern.start,
1422
+ end: pattern.end,
1423
+ // A call spanning several lines keeps its line breaks.
1424
+ text: `${P}static(${jsStringLiteral(pattern.templateHtml)}${lineBreaksIn(code, pattern.start, pattern.end)})`
1425
+ }));
1426
+ const append = `
1427
+ import { staticTemplate as ${P}staticTemplate } from "sibujs/performance";
1428
+ function ${P}static(markup) {
1429
+ return document.adoptNode(${P}staticTemplate(markup));
1430
+ }
1431
+ `;
1432
+ return { edits, append };
1433
+ }
1434
+ function resolveDevMode(explicit, info) {
1435
+ if (explicit !== void 0) return explicit;
1436
+ if (info?.command === "build") return info.mode === "development";
1437
+ if (info?.command === "serve") return true;
1438
+ return typeof process !== "undefined" && process.env?.NODE_ENV !== "production";
616
1439
  }
617
1440
  function sibuVitePlugin(options = {}) {
618
1441
  const {
@@ -621,22 +1444,23 @@ function sibuVitePlugin(options = {}) {
621
1444
  include = DEFAULT_INCLUDE,
622
1445
  exclude = DEFAULT_EXCLUDE,
623
1446
  devMode,
624
- staticOptimize,
1447
+ staticOptimize = false,
625
1448
  compileTemplates
626
1449
  } = options;
627
- const isDevMode = devMode ?? (typeof process !== "undefined" && process.env?.NODE_ENV !== "production");
1450
+ let isDevMode = resolveDevMode(devMode, void 0);
628
1451
  return {
629
1452
  name: "sibu-vite-plugin",
630
1453
  enforce: "pre",
631
- config() {
1454
+ config(_userConfig, env) {
1455
+ isDevMode = resolveDevMode(devMode, env);
632
1456
  return {
633
- // Optimize dependency pre-bundling for sibu
1457
+ // Optimize dependency pre-bundling for sibujs
634
1458
  optimizeDeps: {
635
- include: ["sibu"]
1459
+ include: ["sibujs"]
636
1460
  },
637
- // Ensure sibu is treated correctly for SSR
1461
+ // Ensure sibujs is treated correctly for SSR
638
1462
  ssr: {
639
- noExternal: ["sibu"]
1463
+ noExternal: ["sibujs"]
640
1464
  },
641
1465
  // Define global constants for dead code elimination
642
1466
  define: {
@@ -649,69 +1473,47 @@ function sibuVitePlugin(options = {}) {
649
1473
  }
650
1474
  };
651
1475
  },
1476
+ configResolved(config) {
1477
+ isDevMode = resolveDevMode(devMode, config);
1478
+ },
652
1479
  transform(code, id) {
653
1480
  if (!matchesPattern(id, include) || matchesPattern(id, exclude)) {
654
1481
  return null;
655
1482
  }
656
- let transformed = code;
657
- let modified = false;
658
- if (pureAnnotations) {
659
- const annotated = injectPureAnnotations(transformed);
660
- if (annotated !== transformed) {
661
- transformed = annotated;
662
- modified = true;
663
- }
1483
+ if (!code.includes("sibujs")) return null;
1484
+ if (!scanModule(code)) return null;
1485
+ const edits = [];
1486
+ let append = "";
1487
+ if (isDevMode && importsSibu(code)) {
1488
+ const prologue = devPrologueEdit(code);
1489
+ if (prologue) edits.push(prologue);
664
1490
  }
665
- if (isDevMode) {
666
- const withDevHelpers = injectDevHelpers(transformed);
667
- if (withDevHelpers !== transformed) {
668
- transformed = withDevHelpers;
669
- modified = true;
670
- }
1491
+ if (pureAnnotations) {
1492
+ edits.push(...pureAnnotationEdits(code));
671
1493
  }
672
1494
  const shouldCompile = compileTemplates ?? !isDevMode;
673
- if (shouldCompile && transformed.includes("html`")) {
674
- const compiled = compileHtmlTemplates(transformed);
675
- if (compiled.code) {
676
- const tagImports = Array.from(compiled.usedTags).filter((t) => !SVG_TAGS_SET.has(t));
677
- const needsSvg = compiled.usesSvg;
678
- const imports = [];
679
- if (tagImports.length > 0) {
680
- imports.push(`import { ${tagImports.join(", ")} } from "sibu";`);
681
- }
682
- if (needsSvg) {
683
- imports.push(`import { tagFactory as __sbTagFactory, SVG_NS as __sbSVG_NS } from "sibu";`);
684
- }
685
- const newImports = imports.filter((imp) => !transformed.includes(imp));
686
- if (newImports.length > 0) {
687
- compiled.code = `${newImports.join("\n")}
688
- ${compiled.code}`;
689
- }
690
- transformed = compiled.code;
691
- modified = true;
1495
+ if (shouldCompile) {
1496
+ const plan = planHtmlTemplates(code);
1497
+ if (plan.compiledCount > 0) {
1498
+ edits.push(...plan.edits);
1499
+ append += plan.append;
692
1500
  }
693
1501
  }
694
- const shouldOptimize = staticOptimize ?? !isDevMode;
695
- if (shouldOptimize) {
696
- const analysis = analyzeStaticTemplates(transformed);
697
- if (analysis.hasStaticPatterns) {
698
- const sorted = [...analysis.patterns].sort((a, b) => b.start - a.start);
699
- for (const pattern of sorted) {
700
- const replacement = `staticTemplate(${JSON.stringify(pattern.templateHtml)})`;
701
- transformed = transformed.slice(0, pattern.start) + replacement + transformed.slice(pattern.end);
702
- }
703
- if (!transformed.includes("import") || !transformed.includes("staticTemplate")) {
704
- transformed = `import { staticTemplate } from "sibu";
705
- ${transformed}`;
706
- }
707
- modified = true;
1502
+ if (staticOptimize) {
1503
+ const optimized = staticOptimizationEdits(code);
1504
+ if (optimized) {
1505
+ edits.push(...optimized.edits);
1506
+ append += optimized.append;
708
1507
  }
709
1508
  }
710
- if (!modified) return null;
1509
+ if (edits.length === 0 && append === "") return null;
1510
+ const sorted = normalizeEdits(edits);
1511
+ if (!sorted) return null;
1512
+ const transformed = applyEdits(code, sorted, append);
1513
+ if (transformed === code) return null;
711
1514
  return {
712
1515
  code: transformed,
713
- map: void 0
714
- // Let Vite handle source maps
1516
+ map: editsSourceMap(code, sorted, append, id)
715
1517
  };
716
1518
  },
717
1519
  handleHotUpdate(ctx) {
@@ -770,7 +1572,7 @@ function createViteConfig(options = {}) {
770
1572
  // SSR configuration
771
1573
  ...ssr ? {
772
1574
  ssr: {
773
- noExternal: ["sibu"],
1575
+ noExternal: ["sibujs"],
774
1576
  target: "node"
775
1577
  },
776
1578
  build: {
@@ -787,8 +1589,8 @@ function createViteConfig(options = {}) {
787
1589
  } : {},
788
1590
  // Optimize dependency handling
789
1591
  optimizeDeps: {
790
- include: ["sibu"],
791
- // Force pre-bundling of sibu for faster dev startup
1592
+ include: ["sibujs"],
1593
+ // Force pre-bundling of sibujs for faster dev startup
792
1594
  force: false
793
1595
  },
794
1596
  // Environment variable handling
@@ -811,26 +1613,11 @@ function deepMerge(target, source) {
811
1613
  }
812
1614
 
813
1615
  // src/build/webpack.ts
814
- var PURE_FACTORIES = [
815
- "tagFactory",
816
- "context",
817
- "defineComponent",
818
- "withProps",
819
- "withDefaults",
820
- "pure",
821
- "noSideEffect"
822
- ];
823
1616
  function addPureAnnotations(source) {
824
- let result = source;
825
- for (const factory of PURE_FACTORIES) {
826
- const pattern = new RegExp(`(?<!/\\*#__PURE__\\*/\\s*)\\b(${factory})\\s*\\(`, "g");
827
- result = result.replace(pattern, "/*#__PURE__*/ $1(");
828
- }
829
- return result;
1617
+ return injectPureAnnotations(source);
830
1618
  }
831
1619
  function sibuWebpackPlugin(options = {}) {
832
- const { pureAnnotations = true, devMode } = options;
833
- const isDevMode = devMode ?? (typeof process !== "undefined" && process.env?.NODE_ENV !== "production");
1620
+ const { devMode } = options;
834
1621
  return {
835
1622
  name: "SibuWebpackPlugin",
836
1623
  apply(compiler) {
@@ -841,31 +1628,6 @@ function sibuWebpackPlugin(options = {}) {
841
1628
  });
842
1629
  }
843
1630
  });
844
- if (pureAnnotations) {
845
- compiler.hooks?.afterEnvironment?.tap("SibuWebpackPlugin", () => {
846
- if (!compiler.options.module) {
847
- compiler.options.module = { rules: [] };
848
- }
849
- if (!compiler.options.module.rules) {
850
- compiler.options.module.rules = [];
851
- }
852
- compiler.options.module.rules.push({
853
- test: /\.[jt]sx?$/,
854
- exclude: /node_modules/,
855
- enforce: "pre",
856
- use: [
857
- {
858
- loader: {
859
- // Inline loader function
860
- ident: "sibu-pure-annotations-loader",
861
- loader: "__sibu_inline_loader__",
862
- options: {}
863
- }
864
- }
865
- ]
866
- });
867
- });
868
- }
869
1631
  compiler.hooks?.afterResolvers?.tap("SibuWebpackPlugin", () => {
870
1632
  if (!compiler.options.resolve) {
871
1633
  compiler.options.resolve = {};
@@ -877,20 +1639,21 @@ function sibuWebpackPlugin(options = {}) {
877
1639
  compiler.options.resolve.mainFields.unshift("module");
878
1640
  }
879
1641
  });
880
- if (isDevMode) {
881
- compiler.hooks?.done?.tap("SibuWebpackPlugin", (stats) => {
882
- const statsObj = stats;
883
- const info = statsObj?.toJson?.({ modules: false, chunks: false });
884
- if (info) {
885
- console.log(`[SibuWebpackPlugin] Build completed in ${info.time || 0}ms`);
886
- const warnings = info.warnings;
887
- if (warnings?.length) {
888
- console.log(`[SibuWebpackPlugin] ${warnings.length} warning(s)`);
889
- }
1642
+ const tapDoneLogger = () => compiler.hooks?.done?.tap("SibuWebpackPlugin", (stats) => {
1643
+ const statsObj = stats;
1644
+ const info = statsObj?.toJson?.({ modules: false, chunks: false });
1645
+ if (info) {
1646
+ console.log(`[SibuWebpackPlugin] Build completed in ${info.time || 0}ms`);
1647
+ const warnings = info.warnings;
1648
+ if (warnings?.length) {
1649
+ console.log(`[SibuWebpackPlugin] ${warnings.length} warning(s)`);
890
1650
  }
891
- });
892
- }
1651
+ }
1652
+ });
1653
+ if (devMode === true) tapDoneLogger();
893
1654
  compiler.hooks?.environment?.tap("SibuWebpackPlugin", () => {
1655
+ const isDevMode = devMode ?? resolveWebpackDevMode(compiler.options);
1656
+ if (devMode === void 0 && isDevMode) tapDoneLogger();
894
1657
  if (!compiler.options.plugins) {
895
1658
  compiler.options.plugins = [];
896
1659
  }
@@ -898,10 +1661,20 @@ function sibuWebpackPlugin(options = {}) {
898
1661
  __SIBU_DEV__: JSON.stringify(isDevMode)
899
1662
  };
900
1663
  compiler.__sibuDefines = defines;
1664
+ const DefinePlugin = compiler.webpack?.DefinePlugin;
1665
+ if (DefinePlugin) {
1666
+ new DefinePlugin(defines).apply(compiler);
1667
+ }
901
1668
  });
902
1669
  }
903
1670
  };
904
1671
  }
1672
+ function resolveWebpackDevMode(options) {
1673
+ const mode = options.mode;
1674
+ if (mode === "development") return true;
1675
+ if (mode === "production" || mode === void 0) return false;
1676
+ return typeof process !== "undefined" && process.env?.NODE_ENV !== "production";
1677
+ }
905
1678
  function createPureAnnotationsLoader() {
906
1679
  return function sibuPureAnnotationsLoader(source) {
907
1680
  return addPureAnnotations(source);
@@ -970,9 +1743,10 @@ function createWebpackConfig(options = {}) {
970
1743
  splitChunks: isDev ? false : {
971
1744
  chunks: "all",
972
1745
  cacheGroups: {
973
- // Separate sibu framework code into its own chunk
1746
+ // Separate sibujs framework code into its own chunk (the package
1747
+ // directory is `sibujs`; matching `sibu` never selected anything)
974
1748
  sibu: {
975
- test: /[\\/]node_modules[\\/]sibu[\\/]/,
1749
+ test: /[\\/]node_modules[\\/]sibujs[\\/]/,
976
1750
  name: "sibu",
977
1751
  chunks: "all",
978
1752
  priority: 20
@@ -1013,7 +1787,23 @@ function createWebpackConfig(options = {}) {
1013
1787
  }
1014
1788
 
1015
1789
  // src/build/cdn.ts
1016
- var PACKAGE_NAME = "sibu";
1790
+ var PACKAGE_NAME = "sibujs";
1791
+ var SUBPATH_ENTRIES = [
1792
+ "data",
1793
+ "browser",
1794
+ "patterns",
1795
+ "motion",
1796
+ "ui",
1797
+ "widgets",
1798
+ "ssr",
1799
+ "devtools",
1800
+ "performance",
1801
+ "ecosystem",
1802
+ "plugins",
1803
+ "build",
1804
+ "testing",
1805
+ "extras"
1806
+ ];
1017
1807
  function registerGlobal() {
1018
1808
  if (typeof window === "undefined") return;
1019
1809
  window.Sibu = { ...index_exports };
@@ -1059,7 +1849,7 @@ var cdnUrls = {
1059
1849
  * @example
1060
1850
  * ```ts
1061
1851
  * cdnUrls.scriptTag('jsdelivr', '1.0.0')
1062
- * // => '<script src="https://cdn.jsdelivr.net/npm/sibu@1.0.0/dist/cdn.global.js"></script>'
1852
+ * // => '<script src="https://cdn.jsdelivr.net/npm/sibujs@1.0.0/dist/cdn.global.js"></script>'
1063
1853
  * ```
1064
1854
  */
1065
1855
  scriptTag: (provider = "jsdelivr", version) => {
@@ -1077,15 +1867,11 @@ function generateImportMap(baseUrl) {
1077
1867
  const base = baseUrl || `https://cdn.jsdelivr.net/npm/${PACKAGE_NAME}@latest`;
1078
1868
  const imports = {
1079
1869
  // Main package entry
1080
- [PACKAGE_NAME]: `${base}/dist/index.js`,
1081
- // Sub-path imports for tree-shaking in browsers
1082
- [`${PACKAGE_NAME}/core`]: `${base}/dist/core/index.js`,
1083
- [`${PACKAGE_NAME}/reactivity`]: `${base}/dist/reactivity/index.js`,
1084
- [`${PACKAGE_NAME}/plugins`]: `${base}/dist/plugins/index.js`,
1085
- [`${PACKAGE_NAME}/components`]: `${base}/dist/components/index.js`,
1086
- [`${PACKAGE_NAME}/testing`]: `${base}/dist/testing/index.js`,
1087
- [`${PACKAGE_NAME}/build`]: `${base}/dist/build/index.js`
1870
+ [PACKAGE_NAME]: `${base}/dist/index.js`
1088
1871
  };
1872
+ for (const entry of SUBPATH_ENTRIES) {
1873
+ imports[`${PACKAGE_NAME}/${entry}`] = `${base}/dist/${entry}.js`;
1874
+ }
1089
1875
  return {
1090
1876
  imports,
1091
1877
  /**
@@ -1168,9 +1954,9 @@ function generateTsConfig(options) {
1168
1954
  if (paths && Object.keys(paths).length > 0) {
1169
1955
  compilerOptions.baseUrl = ".";
1170
1956
  compilerOptions.paths = {
1171
- // Default sibu alias
1172
- sibu: ["node_modules/sibu/dist/index.d.ts"],
1173
- "sibu/*": ["node_modules/sibu/dist/*"],
1957
+ // Default sibujs alias
1958
+ sibujs: ["node_modules/sibujs/dist/index.d.ts"],
1959
+ "sibujs/*": ["node_modules/sibujs/dist/*"],
1174
1960
  // User-provided paths
1175
1961
  ...paths
1176
1962
  };
@@ -2284,6 +3070,19 @@ function generateTypeStubs() {
2284
3070
  };
2285
3071
  }
2286
3072
 
3073
+ // src/build/compileTemplates.ts
3074
+ function compileHtmlTemplates(code) {
3075
+ const plan = planHtmlTemplates(code);
3076
+ const edits = plan.compiledCount > 0 ? normalizeEdits(plan.edits) : null;
3077
+ return {
3078
+ code: edits ? applyEdits(code, edits, plan.append) : null,
3079
+ usedTags: plan.usedTags,
3080
+ usesSvg: plan.usesSvg,
3081
+ compiledCount: edits ? plan.compiledCount : 0,
3082
+ skippedCount: plan.skippedCount
3083
+ };
3084
+ }
3085
+
2287
3086
  // src/build/routeSplitting.ts
2288
3087
  function fileToRoute(relativePath) {
2289
3088
  const basename = relativePath.split("/").pop() || "";
@@ -2339,7 +3138,7 @@ function generateRouteModule(entries, routesDir) {
2339
3138
  (e, i) => `const route${i} = () => import(/* webpackChunkName: "${e.chunkName}" */ "${routesDir}/${e.importPath}");`
2340
3139
  ).join("\n");
2341
3140
  const routes = entries.map((e, i) => ` { path: "${e.path}", component: lazy(route${i}) }`).join(",\n");
2342
- return `import { lazy } from "sibu";
3141
+ return `import { lazy } from "sibujs";
2343
3142
 
2344
3143
  ${imports}
2345
3144