@fluixi/compiler 1.0.0-alpha.105 → 1.0.0-alpha.106
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/analyze/static-graph.cjs +1 -1
- package/dist/analyze/static-graph.mjs +1 -1
- package/dist/{babel-USPHNEJF.mjs → babel-HJY4RVAV.mjs} +33 -20
- package/dist/{chunk-OQYQ7UTD.mjs → chunk-4XEOMQ57.mjs} +1 -1
- package/dist/{chunk-EK4OMGTU.mjs → chunk-JUFI6IR3.mjs} +1 -1
- package/dist/{chunk-5GAYDAAC.mjs → chunk-LCQHL2VQ.mjs} +132 -10
- package/dist/{chunk-XBAQME2V.mjs → chunk-LGUZRHYN.mjs} +2 -2
- package/dist/{chunk-O6OBEV4V.mjs → chunk-TDN5MYWI.mjs} +1 -1
- package/dist/{chunk-EQIIWIEU.mjs → chunk-W7DYOMXJ.mjs} +2 -2
- package/dist/{chunk-FMIIK5UM.mjs → chunk-WHEDRMNR.mjs} +1 -1
- package/dist/codegen/backends/imperative.cjs +130 -8
- package/dist/codegen/backends/imperative.d.ts.map +1 -1
- package/dist/codegen/backends/imperative.js +62 -0
- package/dist/codegen/backends/imperative.mjs +130 -8
- package/dist/codegen/partial-template.cjs +80 -8
- package/dist/codegen/partial-template.d.cts +21 -4
- package/dist/codegen/partial-template.d.ts +21 -4
- package/dist/codegen/partial-template.d.ts.map +1 -1
- package/dist/codegen/partial-template.js +0 -0
- package/dist/codegen/partial-template.mjs +80 -8
- package/dist/codegen/serialize-static.cjs +1 -0
- package/dist/codegen/serialize-static.d.cts +8 -0
- package/dist/codegen/serialize-static.d.ts +8 -0
- package/dist/codegen/serialize-static.d.ts.map +1 -1
- package/dist/codegen/serialize-static.js +1 -1
- package/dist/codegen/serialize-static.mjs +1 -0
- package/dist/frontend/babel/build-ir-html.cjs +149 -21
- package/dist/frontend/babel/build-ir-html.d.cts +3 -1
- package/dist/frontend/babel/build-ir-html.d.ts +3 -1
- package/dist/frontend/babel/build-ir-html.d.ts.map +1 -1
- package/dist/frontend/babel/build-ir-html.mjs +149 -21
- package/dist/frontend/babel/build-ir.cjs +149 -21
- package/dist/frontend/babel/build-ir.d.cts +11 -2
- package/dist/frontend/babel/build-ir.d.ts +11 -2
- package/dist/frontend/babel/build-ir.d.ts.map +1 -1
- package/dist/frontend/babel/build-ir.js +15 -9
- package/dist/frontend/babel/build-ir.mjs +149 -21
- package/dist/frontend/babel/index.cjs +160 -25
- package/dist/frontend/babel/index.mjs +160 -25
- package/dist/frontend/babel/lower-template.cjs +149 -21
- package/dist/frontend/babel/lower-template.d.cts +2 -1
- package/dist/frontend/babel/lower-template.d.ts +2 -1
- package/dist/frontend/babel/lower-template.d.ts.map +1 -1
- package/dist/frontend/babel/lower-template.js +4 -4
- package/dist/frontend/babel/lower-template.mjs +149 -21
- package/dist/frontend/babel/plugin.cjs +158 -23
- package/dist/frontend/babel/plugin.js +9 -2
- package/dist/frontend/babel/plugin.mjs +158 -23
- package/dist/index.cjs +131 -9
- package/dist/index.mjs +131 -9
- package/dist/integrations.cjs +165 -33
- package/dist/integrations.mjs +11 -11
- package/dist/lower/compile-template.cjs +131 -9
- package/dist/lower/compile-template.mjs +131 -9
- package/dist/lower/jsx.cjs +130 -8
- package/dist/lower/jsx.mjs +130 -8
- package/dist/lower/template.cjs +130 -8
- package/dist/lower/template.mjs +130 -8
- package/dist/resolve/builtins.cjs +1 -1
- package/dist/resolve/builtins.mjs +1 -1
- package/dist/{server-fns-7Y25MR3B.mjs → server-fns-WZJK4BJE.mjs} +5 -5
- package/dist/{server-functions-43CFKXY3.mjs → server-functions-4KTFFEO3.mjs} +3 -3
- package/dist/transform/index.cjs +135 -16
- package/dist/transform/index.mjs +135 -16
- package/dist/transform/templates.cjs +134 -15
- package/dist/transform/templates.d.ts.map +1 -1
- package/dist/transform/templates.js +4 -8
- package/dist/transform/templates.mjs +134 -15
- package/dist/{transform-YUDW7K4J.mjs → transform-NO46NFQH.mjs} +11 -14
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/package.json +4 -4
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @fluixi/compiler v1.0.0-alpha.
|
|
1
|
+
/*! @fluixi/compiler v1.0.0-alpha.106 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
|
|
2
2
|
|
|
3
3
|
// ../../node_modules/.pnpm/@jridgewell+sourcemap-codec@1.6.0/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.mjs
|
|
4
4
|
var comma = ",".charCodeAt(0);
|
|
@@ -368,10 +368,64 @@ function isHole(node) {
|
|
|
368
368
|
function isTemplateChild(node) {
|
|
369
369
|
return node.kind === "text" || node.kind === "element" && isTemplateElement(node);
|
|
370
370
|
}
|
|
371
|
+
var PROPERTY_BINDS = /* @__PURE__ */ new Set(["indeterminate"]);
|
|
372
|
+
function disposition(prop) {
|
|
373
|
+
if (prop.kind === "spread") return null;
|
|
374
|
+
if (prop.name === "ref") return "ref";
|
|
375
|
+
if (prop.name === "use") return "use";
|
|
376
|
+
if (prop.kind === "event") return prop.event ? "event" : null;
|
|
377
|
+
if (prop.kind === "prop") return "property";
|
|
378
|
+
if (prop.kind !== "attr") return null;
|
|
379
|
+
const name = prop.name;
|
|
380
|
+
if (name.startsWith("on:")) return "nativeEvent";
|
|
381
|
+
if (name.startsWith("prop:")) return "property";
|
|
382
|
+
if (name.startsWith("attr:")) return "attr";
|
|
383
|
+
if (name.startsWith("bool:")) return "boolAttr";
|
|
384
|
+
if (name === "className" || name === "class") {
|
|
385
|
+
return isPlainLiteralAttr(prop) ? "serialize" : "class";
|
|
386
|
+
}
|
|
387
|
+
if (name === "classList") {
|
|
388
|
+
if (isPlainLiteralAttr(prop)) return "serialize";
|
|
389
|
+
return prop.reactive ? "classListDynamic" : "classList";
|
|
390
|
+
}
|
|
391
|
+
if (name === "style") {
|
|
392
|
+
if (isPlainLiteralAttr(prop)) return "serialize";
|
|
393
|
+
return prop.reactive ? "styleDynamic" : "style";
|
|
394
|
+
}
|
|
395
|
+
if (name.includes(":")) return null;
|
|
396
|
+
if (PROPERTY_ONLY.has(name)) return null;
|
|
397
|
+
if (PROPERTY_BINDS.has(name)) return "property";
|
|
398
|
+
if (prop.expr === void 0) return isPlainLiteralAttr(prop) ? "serialize" : null;
|
|
399
|
+
return "attr";
|
|
400
|
+
}
|
|
401
|
+
function effectiveProps(el) {
|
|
402
|
+
const order = [];
|
|
403
|
+
const byName = /* @__PURE__ */ new Map();
|
|
404
|
+
for (const prop of el.props) {
|
|
405
|
+
if (!byName.has(prop.name)) order.push(prop.name);
|
|
406
|
+
byName.set(prop.name, prop);
|
|
407
|
+
}
|
|
408
|
+
return order.map((name) => byName.get(name));
|
|
409
|
+
}
|
|
410
|
+
function propPlan(el) {
|
|
411
|
+
const custom = el.tag.includes("-");
|
|
412
|
+
const plan = { serialize: [], bindings: [] };
|
|
413
|
+
for (const prop of effectiveProps(el)) {
|
|
414
|
+
const kind = disposition(prop);
|
|
415
|
+
if (kind === null) return null;
|
|
416
|
+
if (kind === "serialize") {
|
|
417
|
+
plan.serialize.push(prop);
|
|
418
|
+
continue;
|
|
419
|
+
}
|
|
420
|
+
if (custom) return null;
|
|
421
|
+
plan.bindings.push({ prop, kind });
|
|
422
|
+
}
|
|
423
|
+
return plan;
|
|
424
|
+
}
|
|
371
425
|
function isTemplateElement(node) {
|
|
372
426
|
if (node.svg) return false;
|
|
373
427
|
if (isRawTextElement(node.tag)) return false;
|
|
374
|
-
if (!node
|
|
428
|
+
if (!propPlan(node)) return false;
|
|
375
429
|
return node.children.every((c) => isTemplateChild(c) || isHole(c));
|
|
376
430
|
}
|
|
377
431
|
function containsHole(node) {
|
|
@@ -379,6 +433,15 @@ function containsHole(node) {
|
|
|
379
433
|
const children = node.children;
|
|
380
434
|
return children ? children.some(containsHole) : false;
|
|
381
435
|
}
|
|
436
|
+
function containsBinding(node) {
|
|
437
|
+
if (node.kind !== "element") return false;
|
|
438
|
+
const plan = propPlan(node);
|
|
439
|
+
if (plan && plan.bindings.length > 0) return true;
|
|
440
|
+
return node.children.some(containsBinding);
|
|
441
|
+
}
|
|
442
|
+
function interesting(node) {
|
|
443
|
+
return containsHole(node) || containsBinding(node);
|
|
444
|
+
}
|
|
382
445
|
function addressable(el) {
|
|
383
446
|
for (let i = 0; i < el.children.length; i++) {
|
|
384
447
|
const child = el.children[i];
|
|
@@ -392,9 +455,10 @@ function addressable(el) {
|
|
|
392
455
|
function planPartialTemplate(root) {
|
|
393
456
|
if (!isTemplateElement(root)) return null;
|
|
394
457
|
if (!addressable(root)) return null;
|
|
395
|
-
if (!root
|
|
458
|
+
if (!interesting(root)) return null;
|
|
396
459
|
const steps = [];
|
|
397
460
|
const holes = [];
|
|
461
|
+
const bindings = [];
|
|
398
462
|
let refCount = 0;
|
|
399
463
|
const declare = (expr) => {
|
|
400
464
|
const ref = `_n$${refCount++}`;
|
|
@@ -402,11 +466,17 @@ function planPartialTemplate(root) {
|
|
|
402
466
|
return ref;
|
|
403
467
|
};
|
|
404
468
|
walk2(root, "_el$");
|
|
405
|
-
return { html: serializeWithMarkers(root), tag: root.tag, steps, holes };
|
|
469
|
+
return { html: serializeWithMarkers(root), tag: root.tag, steps, holes, bindings };
|
|
406
470
|
function walk2(el, elementRef) {
|
|
471
|
+
const plan = propPlan(el);
|
|
472
|
+
if (plan) {
|
|
473
|
+
for (const binding of plan.bindings) {
|
|
474
|
+
bindings.push({ ref: elementRef, prop: binding.prop, kind: binding.kind });
|
|
475
|
+
}
|
|
476
|
+
}
|
|
407
477
|
let last = -1;
|
|
408
478
|
el.children.forEach((child, i) => {
|
|
409
|
-
if (
|
|
479
|
+
if (interesting(child)) last = i;
|
|
410
480
|
});
|
|
411
481
|
let previous = null;
|
|
412
482
|
for (let i = 0; i <= last; i++) {
|
|
@@ -420,19 +490,21 @@ function planPartialTemplate(root) {
|
|
|
420
490
|
continue;
|
|
421
491
|
}
|
|
422
492
|
const ref = declare(expr);
|
|
423
|
-
if (child.kind === "element" &&
|
|
493
|
+
if (child.kind === "element" && interesting(child)) walk2(child, ref);
|
|
424
494
|
previous = ref;
|
|
425
495
|
}
|
|
426
496
|
}
|
|
427
497
|
}
|
|
428
498
|
function serializeWithMarkers(el) {
|
|
429
|
-
return serializeStatic(
|
|
499
|
+
return serializeStatic(templateTree(el)).split(SENTINEL).join(HOLE_START + HOLE_END);
|
|
430
500
|
}
|
|
431
|
-
function
|
|
501
|
+
function templateTree(el) {
|
|
502
|
+
const plan = propPlan(el);
|
|
432
503
|
return {
|
|
433
504
|
...el,
|
|
505
|
+
props: plan ? plan.serialize : [],
|
|
434
506
|
children: el.children.map(
|
|
435
|
-
(child) => isHole(child) ? { kind: "text", value: SENTINEL } : child.kind === "element" ?
|
|
507
|
+
(child) => isHole(child) ? { kind: "text", value: SENTINEL } : child.kind === "element" ? templateTree(child) : child
|
|
436
508
|
)
|
|
437
509
|
};
|
|
438
510
|
}
|
|
@@ -705,6 +777,55 @@ function emitComponent(name, props, children, used, templates, at) {
|
|
|
705
777
|
const mark = at ? `globalThis.${SOURCE_MARKER}?.(${JSON.stringify(at.file)},${at.line},${at.column},${JSON.stringify(name)}), ` : "";
|
|
706
778
|
return `createMemo(${paren(`${mark}() => createComponent(${name}, ${obj})`, "value")})`;
|
|
707
779
|
}
|
|
780
|
+
function bindingTarget(binding) {
|
|
781
|
+
const name = binding.prop.name;
|
|
782
|
+
if (binding.kind === "boolAttr") return name.slice("bool:".length);
|
|
783
|
+
if (name.startsWith("prop:")) return name.slice("prop:".length);
|
|
784
|
+
if (name.startsWith("attr:")) return name.slice("attr:".length);
|
|
785
|
+
return htmlAttrName(name);
|
|
786
|
+
}
|
|
787
|
+
function bindingStatement(binding, used) {
|
|
788
|
+
const { ref, prop, kind } = binding;
|
|
789
|
+
const value = propValue(prop);
|
|
790
|
+
switch (kind) {
|
|
791
|
+
case "class":
|
|
792
|
+
used.add("setClassName");
|
|
793
|
+
return `setClassName(${ref}, ${value});`;
|
|
794
|
+
case "classList":
|
|
795
|
+
used.add("setClassList");
|
|
796
|
+
return `setClassList(${ref}, ${value}, []);`;
|
|
797
|
+
case "classListDynamic":
|
|
798
|
+
used.add("setDynamicClassList");
|
|
799
|
+
return `setDynamicClassList(${ref}, ${value});`;
|
|
800
|
+
case "style":
|
|
801
|
+
used.add("setStyle");
|
|
802
|
+
return `setStyle(${ref}, ${value}, []);`;
|
|
803
|
+
case "styleDynamic":
|
|
804
|
+
used.add("setDynamicStyle");
|
|
805
|
+
return `setDynamicStyle(${ref}, ${value});`;
|
|
806
|
+
case "attr":
|
|
807
|
+
used.add("setDynamicAttribute");
|
|
808
|
+
return `setDynamicAttribute(${ref}, ${JSON.stringify(bindingTarget(binding))}, ${value});`;
|
|
809
|
+
case "property":
|
|
810
|
+
used.add("setDynamicProperty");
|
|
811
|
+
return `setDynamicProperty(${ref}, ${JSON.stringify(bindingTarget(binding))}, ${value});`;
|
|
812
|
+
case "boolAttr":
|
|
813
|
+
used.add("setDynamicBoolAttribute");
|
|
814
|
+
return `setDynamicBoolAttribute(${ref}, ${JSON.stringify(bindingTarget(binding))}, ${value});`;
|
|
815
|
+
case "event":
|
|
816
|
+
used.add("addDelegatedEventListener");
|
|
817
|
+
return `addDelegatedEventListener(${ref}, ${JSON.stringify(prop.event.name)}, ${value});`;
|
|
818
|
+
case "nativeEvent":
|
|
819
|
+
used.add("addNativeEventListener");
|
|
820
|
+
return `addNativeEventListener(${ref}, ${JSON.stringify(prop.name.slice(3))}, ${value});`;
|
|
821
|
+
case "ref":
|
|
822
|
+
used.add("handleRef");
|
|
823
|
+
return `handleRef(${value}, ${ref});`;
|
|
824
|
+
case "use":
|
|
825
|
+
used.add("applyUse");
|
|
826
|
+
return `applyUse(${ref}, ${value});`;
|
|
827
|
+
}
|
|
828
|
+
}
|
|
708
829
|
function staticAttrAssignment(el, prop) {
|
|
709
830
|
const name = htmlAttrName(prop.name);
|
|
710
831
|
const value = prop.literal;
|
|
@@ -755,6 +876,7 @@ function emitNode(node, used, templates) {
|
|
|
755
876
|
`const _el$ = templateNode(${id}, ${JSON.stringify(plan.tag)}, true${at ? `, false, ${JSON.stringify(at)}` : ""});`
|
|
756
877
|
];
|
|
757
878
|
for (const step of plan.steps) lines.push(`const ${step.ref} = ${step.expr};`);
|
|
879
|
+
for (const binding of plan.bindings) lines.push(bindingStatement(binding, used));
|
|
758
880
|
for (const hole of plan.holes) {
|
|
759
881
|
lines.push(
|
|
760
882
|
`insert(${hole.parentRef}, holeScope(${hole.startRef}, () => ${paren(emitNode(hole.node, used, templates), "arrowBody")}), ${hole.endRef}, holeContent(${hole.startRef}, ${hole.endRef}));`
|
package/dist/lower/jsx.cjs
CHANGED
|
@@ -482,10 +482,64 @@ function isHole(node) {
|
|
|
482
482
|
function isTemplateChild(node) {
|
|
483
483
|
return node.kind === "text" || node.kind === "element" && isTemplateElement(node);
|
|
484
484
|
}
|
|
485
|
+
var PROPERTY_BINDS = /* @__PURE__ */ new Set(["indeterminate"]);
|
|
486
|
+
function disposition(prop) {
|
|
487
|
+
if (prop.kind === "spread") return null;
|
|
488
|
+
if (prop.name === "ref") return "ref";
|
|
489
|
+
if (prop.name === "use") return "use";
|
|
490
|
+
if (prop.kind === "event") return prop.event ? "event" : null;
|
|
491
|
+
if (prop.kind === "prop") return "property";
|
|
492
|
+
if (prop.kind !== "attr") return null;
|
|
493
|
+
const name = prop.name;
|
|
494
|
+
if (name.startsWith("on:")) return "nativeEvent";
|
|
495
|
+
if (name.startsWith("prop:")) return "property";
|
|
496
|
+
if (name.startsWith("attr:")) return "attr";
|
|
497
|
+
if (name.startsWith("bool:")) return "boolAttr";
|
|
498
|
+
if (name === "className" || name === "class") {
|
|
499
|
+
return isPlainLiteralAttr(prop) ? "serialize" : "class";
|
|
500
|
+
}
|
|
501
|
+
if (name === "classList") {
|
|
502
|
+
if (isPlainLiteralAttr(prop)) return "serialize";
|
|
503
|
+
return prop.reactive ? "classListDynamic" : "classList";
|
|
504
|
+
}
|
|
505
|
+
if (name === "style") {
|
|
506
|
+
if (isPlainLiteralAttr(prop)) return "serialize";
|
|
507
|
+
return prop.reactive ? "styleDynamic" : "style";
|
|
508
|
+
}
|
|
509
|
+
if (name.includes(":")) return null;
|
|
510
|
+
if (PROPERTY_ONLY.has(name)) return null;
|
|
511
|
+
if (PROPERTY_BINDS.has(name)) return "property";
|
|
512
|
+
if (prop.expr === void 0) return isPlainLiteralAttr(prop) ? "serialize" : null;
|
|
513
|
+
return "attr";
|
|
514
|
+
}
|
|
515
|
+
function effectiveProps(el) {
|
|
516
|
+
const order = [];
|
|
517
|
+
const byName = /* @__PURE__ */ new Map();
|
|
518
|
+
for (const prop of el.props) {
|
|
519
|
+
if (!byName.has(prop.name)) order.push(prop.name);
|
|
520
|
+
byName.set(prop.name, prop);
|
|
521
|
+
}
|
|
522
|
+
return order.map((name) => byName.get(name));
|
|
523
|
+
}
|
|
524
|
+
function propPlan(el) {
|
|
525
|
+
const custom = el.tag.includes("-");
|
|
526
|
+
const plan = { serialize: [], bindings: [] };
|
|
527
|
+
for (const prop of effectiveProps(el)) {
|
|
528
|
+
const kind = disposition(prop);
|
|
529
|
+
if (kind === null) return null;
|
|
530
|
+
if (kind === "serialize") {
|
|
531
|
+
plan.serialize.push(prop);
|
|
532
|
+
continue;
|
|
533
|
+
}
|
|
534
|
+
if (custom) return null;
|
|
535
|
+
plan.bindings.push({ prop, kind });
|
|
536
|
+
}
|
|
537
|
+
return plan;
|
|
538
|
+
}
|
|
485
539
|
function isTemplateElement(node) {
|
|
486
540
|
if (node.svg) return false;
|
|
487
541
|
if (isRawTextElement(node.tag)) return false;
|
|
488
|
-
if (!node
|
|
542
|
+
if (!propPlan(node)) return false;
|
|
489
543
|
return node.children.every((c) => isTemplateChild(c) || isHole(c));
|
|
490
544
|
}
|
|
491
545
|
function containsHole(node) {
|
|
@@ -493,6 +547,15 @@ function containsHole(node) {
|
|
|
493
547
|
const children = node.children;
|
|
494
548
|
return children ? children.some(containsHole) : false;
|
|
495
549
|
}
|
|
550
|
+
function containsBinding(node) {
|
|
551
|
+
if (node.kind !== "element") return false;
|
|
552
|
+
const plan = propPlan(node);
|
|
553
|
+
if (plan && plan.bindings.length > 0) return true;
|
|
554
|
+
return node.children.some(containsBinding);
|
|
555
|
+
}
|
|
556
|
+
function interesting(node) {
|
|
557
|
+
return containsHole(node) || containsBinding(node);
|
|
558
|
+
}
|
|
496
559
|
function addressable(el) {
|
|
497
560
|
for (let i = 0; i < el.children.length; i++) {
|
|
498
561
|
const child = el.children[i];
|
|
@@ -506,9 +569,10 @@ function addressable(el) {
|
|
|
506
569
|
function planPartialTemplate(root) {
|
|
507
570
|
if (!isTemplateElement(root)) return null;
|
|
508
571
|
if (!addressable(root)) return null;
|
|
509
|
-
if (!root
|
|
572
|
+
if (!interesting(root)) return null;
|
|
510
573
|
const steps = [];
|
|
511
574
|
const holes = [];
|
|
575
|
+
const bindings = [];
|
|
512
576
|
let refCount = 0;
|
|
513
577
|
const declare = (expr) => {
|
|
514
578
|
const ref = `_n$${refCount++}`;
|
|
@@ -516,11 +580,17 @@ function planPartialTemplate(root) {
|
|
|
516
580
|
return ref;
|
|
517
581
|
};
|
|
518
582
|
walk(root, "_el$");
|
|
519
|
-
return { html: serializeWithMarkers(root), tag: root.tag, steps, holes };
|
|
583
|
+
return { html: serializeWithMarkers(root), tag: root.tag, steps, holes, bindings };
|
|
520
584
|
function walk(el, elementRef) {
|
|
585
|
+
const plan = propPlan(el);
|
|
586
|
+
if (plan) {
|
|
587
|
+
for (const binding of plan.bindings) {
|
|
588
|
+
bindings.push({ ref: elementRef, prop: binding.prop, kind: binding.kind });
|
|
589
|
+
}
|
|
590
|
+
}
|
|
521
591
|
let last = -1;
|
|
522
592
|
el.children.forEach((child, i) => {
|
|
523
|
-
if (
|
|
593
|
+
if (interesting(child)) last = i;
|
|
524
594
|
});
|
|
525
595
|
let previous = null;
|
|
526
596
|
for (let i = 0; i <= last; i++) {
|
|
@@ -534,19 +604,21 @@ function planPartialTemplate(root) {
|
|
|
534
604
|
continue;
|
|
535
605
|
}
|
|
536
606
|
const ref = declare(expr);
|
|
537
|
-
if (child.kind === "element" &&
|
|
607
|
+
if (child.kind === "element" && interesting(child)) walk(child, ref);
|
|
538
608
|
previous = ref;
|
|
539
609
|
}
|
|
540
610
|
}
|
|
541
611
|
}
|
|
542
612
|
function serializeWithMarkers(el) {
|
|
543
|
-
return serializeStatic(
|
|
613
|
+
return serializeStatic(templateTree(el)).split(SENTINEL).join(HOLE_START + HOLE_END);
|
|
544
614
|
}
|
|
545
|
-
function
|
|
615
|
+
function templateTree(el) {
|
|
616
|
+
const plan = propPlan(el);
|
|
546
617
|
return {
|
|
547
618
|
...el,
|
|
619
|
+
props: plan ? plan.serialize : [],
|
|
548
620
|
children: el.children.map(
|
|
549
|
-
(child) => isHole(child) ? { kind: "text", value: SENTINEL } : child.kind === "element" ?
|
|
621
|
+
(child) => isHole(child) ? { kind: "text", value: SENTINEL } : child.kind === "element" ? templateTree(child) : child
|
|
550
622
|
)
|
|
551
623
|
};
|
|
552
624
|
}
|
|
@@ -665,6 +737,55 @@ function emitComponent(name, props, children, used, templates, at) {
|
|
|
665
737
|
const mark = at ? `globalThis.${SOURCE_MARKER}?.(${JSON.stringify(at.file)},${at.line},${at.column},${JSON.stringify(name)}), ` : "";
|
|
666
738
|
return `createMemo(${paren(`${mark}() => createComponent(${name}, ${obj})`, "value")})`;
|
|
667
739
|
}
|
|
740
|
+
function bindingTarget(binding) {
|
|
741
|
+
const name = binding.prop.name;
|
|
742
|
+
if (binding.kind === "boolAttr") return name.slice("bool:".length);
|
|
743
|
+
if (name.startsWith("prop:")) return name.slice("prop:".length);
|
|
744
|
+
if (name.startsWith("attr:")) return name.slice("attr:".length);
|
|
745
|
+
return htmlAttrName(name);
|
|
746
|
+
}
|
|
747
|
+
function bindingStatement(binding, used) {
|
|
748
|
+
const { ref, prop, kind } = binding;
|
|
749
|
+
const value = propValue(prop);
|
|
750
|
+
switch (kind) {
|
|
751
|
+
case "class":
|
|
752
|
+
used.add("setClassName");
|
|
753
|
+
return `setClassName(${ref}, ${value});`;
|
|
754
|
+
case "classList":
|
|
755
|
+
used.add("setClassList");
|
|
756
|
+
return `setClassList(${ref}, ${value}, []);`;
|
|
757
|
+
case "classListDynamic":
|
|
758
|
+
used.add("setDynamicClassList");
|
|
759
|
+
return `setDynamicClassList(${ref}, ${value});`;
|
|
760
|
+
case "style":
|
|
761
|
+
used.add("setStyle");
|
|
762
|
+
return `setStyle(${ref}, ${value}, []);`;
|
|
763
|
+
case "styleDynamic":
|
|
764
|
+
used.add("setDynamicStyle");
|
|
765
|
+
return `setDynamicStyle(${ref}, ${value});`;
|
|
766
|
+
case "attr":
|
|
767
|
+
used.add("setDynamicAttribute");
|
|
768
|
+
return `setDynamicAttribute(${ref}, ${JSON.stringify(bindingTarget(binding))}, ${value});`;
|
|
769
|
+
case "property":
|
|
770
|
+
used.add("setDynamicProperty");
|
|
771
|
+
return `setDynamicProperty(${ref}, ${JSON.stringify(bindingTarget(binding))}, ${value});`;
|
|
772
|
+
case "boolAttr":
|
|
773
|
+
used.add("setDynamicBoolAttribute");
|
|
774
|
+
return `setDynamicBoolAttribute(${ref}, ${JSON.stringify(bindingTarget(binding))}, ${value});`;
|
|
775
|
+
case "event":
|
|
776
|
+
used.add("addDelegatedEventListener");
|
|
777
|
+
return `addDelegatedEventListener(${ref}, ${JSON.stringify(prop.event.name)}, ${value});`;
|
|
778
|
+
case "nativeEvent":
|
|
779
|
+
used.add("addNativeEventListener");
|
|
780
|
+
return `addNativeEventListener(${ref}, ${JSON.stringify(prop.name.slice(3))}, ${value});`;
|
|
781
|
+
case "ref":
|
|
782
|
+
used.add("handleRef");
|
|
783
|
+
return `handleRef(${value}, ${ref});`;
|
|
784
|
+
case "use":
|
|
785
|
+
used.add("applyUse");
|
|
786
|
+
return `applyUse(${ref}, ${value});`;
|
|
787
|
+
}
|
|
788
|
+
}
|
|
668
789
|
function staticAttrAssignment(el, prop) {
|
|
669
790
|
const name = htmlAttrName(prop.name);
|
|
670
791
|
const value = prop.literal;
|
|
@@ -715,6 +836,7 @@ function emitNode(node, used, templates) {
|
|
|
715
836
|
`const _el$ = templateNode(${id}, ${JSON.stringify(plan.tag)}, true${at ? `, false, ${JSON.stringify(at)}` : ""});`
|
|
716
837
|
];
|
|
717
838
|
for (const step of plan.steps) lines.push(`const ${step.ref} = ${step.expr};`);
|
|
839
|
+
for (const binding of plan.bindings) lines.push(bindingStatement(binding, used));
|
|
718
840
|
for (const hole of plan.holes) {
|
|
719
841
|
lines.push(
|
|
720
842
|
`insert(${hole.parentRef}, holeScope(${hole.startRef}, () => ${paren(emitNode(hole.node, used, templates), "arrowBody")}), ${hole.endRef}, holeContent(${hole.startRef}, ${hole.endRef}));`
|
package/dist/lower/jsx.mjs
CHANGED
|
@@ -455,10 +455,64 @@ function isHole(node) {
|
|
|
455
455
|
function isTemplateChild(node) {
|
|
456
456
|
return node.kind === "text" || node.kind === "element" && isTemplateElement(node);
|
|
457
457
|
}
|
|
458
|
+
var PROPERTY_BINDS = /* @__PURE__ */ new Set(["indeterminate"]);
|
|
459
|
+
function disposition(prop) {
|
|
460
|
+
if (prop.kind === "spread") return null;
|
|
461
|
+
if (prop.name === "ref") return "ref";
|
|
462
|
+
if (prop.name === "use") return "use";
|
|
463
|
+
if (prop.kind === "event") return prop.event ? "event" : null;
|
|
464
|
+
if (prop.kind === "prop") return "property";
|
|
465
|
+
if (prop.kind !== "attr") return null;
|
|
466
|
+
const name = prop.name;
|
|
467
|
+
if (name.startsWith("on:")) return "nativeEvent";
|
|
468
|
+
if (name.startsWith("prop:")) return "property";
|
|
469
|
+
if (name.startsWith("attr:")) return "attr";
|
|
470
|
+
if (name.startsWith("bool:")) return "boolAttr";
|
|
471
|
+
if (name === "className" || name === "class") {
|
|
472
|
+
return isPlainLiteralAttr(prop) ? "serialize" : "class";
|
|
473
|
+
}
|
|
474
|
+
if (name === "classList") {
|
|
475
|
+
if (isPlainLiteralAttr(prop)) return "serialize";
|
|
476
|
+
return prop.reactive ? "classListDynamic" : "classList";
|
|
477
|
+
}
|
|
478
|
+
if (name === "style") {
|
|
479
|
+
if (isPlainLiteralAttr(prop)) return "serialize";
|
|
480
|
+
return prop.reactive ? "styleDynamic" : "style";
|
|
481
|
+
}
|
|
482
|
+
if (name.includes(":")) return null;
|
|
483
|
+
if (PROPERTY_ONLY.has(name)) return null;
|
|
484
|
+
if (PROPERTY_BINDS.has(name)) return "property";
|
|
485
|
+
if (prop.expr === void 0) return isPlainLiteralAttr(prop) ? "serialize" : null;
|
|
486
|
+
return "attr";
|
|
487
|
+
}
|
|
488
|
+
function effectiveProps(el) {
|
|
489
|
+
const order = [];
|
|
490
|
+
const byName = /* @__PURE__ */ new Map();
|
|
491
|
+
for (const prop of el.props) {
|
|
492
|
+
if (!byName.has(prop.name)) order.push(prop.name);
|
|
493
|
+
byName.set(prop.name, prop);
|
|
494
|
+
}
|
|
495
|
+
return order.map((name) => byName.get(name));
|
|
496
|
+
}
|
|
497
|
+
function propPlan(el) {
|
|
498
|
+
const custom = el.tag.includes("-");
|
|
499
|
+
const plan = { serialize: [], bindings: [] };
|
|
500
|
+
for (const prop of effectiveProps(el)) {
|
|
501
|
+
const kind = disposition(prop);
|
|
502
|
+
if (kind === null) return null;
|
|
503
|
+
if (kind === "serialize") {
|
|
504
|
+
plan.serialize.push(prop);
|
|
505
|
+
continue;
|
|
506
|
+
}
|
|
507
|
+
if (custom) return null;
|
|
508
|
+
plan.bindings.push({ prop, kind });
|
|
509
|
+
}
|
|
510
|
+
return plan;
|
|
511
|
+
}
|
|
458
512
|
function isTemplateElement(node) {
|
|
459
513
|
if (node.svg) return false;
|
|
460
514
|
if (isRawTextElement(node.tag)) return false;
|
|
461
|
-
if (!node
|
|
515
|
+
if (!propPlan(node)) return false;
|
|
462
516
|
return node.children.every((c) => isTemplateChild(c) || isHole(c));
|
|
463
517
|
}
|
|
464
518
|
function containsHole(node) {
|
|
@@ -466,6 +520,15 @@ function containsHole(node) {
|
|
|
466
520
|
const children = node.children;
|
|
467
521
|
return children ? children.some(containsHole) : false;
|
|
468
522
|
}
|
|
523
|
+
function containsBinding(node) {
|
|
524
|
+
if (node.kind !== "element") return false;
|
|
525
|
+
const plan = propPlan(node);
|
|
526
|
+
if (plan && plan.bindings.length > 0) return true;
|
|
527
|
+
return node.children.some(containsBinding);
|
|
528
|
+
}
|
|
529
|
+
function interesting(node) {
|
|
530
|
+
return containsHole(node) || containsBinding(node);
|
|
531
|
+
}
|
|
469
532
|
function addressable(el) {
|
|
470
533
|
for (let i = 0; i < el.children.length; i++) {
|
|
471
534
|
const child = el.children[i];
|
|
@@ -479,9 +542,10 @@ function addressable(el) {
|
|
|
479
542
|
function planPartialTemplate(root) {
|
|
480
543
|
if (!isTemplateElement(root)) return null;
|
|
481
544
|
if (!addressable(root)) return null;
|
|
482
|
-
if (!root
|
|
545
|
+
if (!interesting(root)) return null;
|
|
483
546
|
const steps = [];
|
|
484
547
|
const holes = [];
|
|
548
|
+
const bindings = [];
|
|
485
549
|
let refCount = 0;
|
|
486
550
|
const declare = (expr) => {
|
|
487
551
|
const ref = `_n$${refCount++}`;
|
|
@@ -489,11 +553,17 @@ function planPartialTemplate(root) {
|
|
|
489
553
|
return ref;
|
|
490
554
|
};
|
|
491
555
|
walk(root, "_el$");
|
|
492
|
-
return { html: serializeWithMarkers(root), tag: root.tag, steps, holes };
|
|
556
|
+
return { html: serializeWithMarkers(root), tag: root.tag, steps, holes, bindings };
|
|
493
557
|
function walk(el, elementRef) {
|
|
558
|
+
const plan = propPlan(el);
|
|
559
|
+
if (plan) {
|
|
560
|
+
for (const binding of plan.bindings) {
|
|
561
|
+
bindings.push({ ref: elementRef, prop: binding.prop, kind: binding.kind });
|
|
562
|
+
}
|
|
563
|
+
}
|
|
494
564
|
let last = -1;
|
|
495
565
|
el.children.forEach((child, i) => {
|
|
496
|
-
if (
|
|
566
|
+
if (interesting(child)) last = i;
|
|
497
567
|
});
|
|
498
568
|
let previous = null;
|
|
499
569
|
for (let i = 0; i <= last; i++) {
|
|
@@ -507,19 +577,21 @@ function planPartialTemplate(root) {
|
|
|
507
577
|
continue;
|
|
508
578
|
}
|
|
509
579
|
const ref = declare(expr);
|
|
510
|
-
if (child.kind === "element" &&
|
|
580
|
+
if (child.kind === "element" && interesting(child)) walk(child, ref);
|
|
511
581
|
previous = ref;
|
|
512
582
|
}
|
|
513
583
|
}
|
|
514
584
|
}
|
|
515
585
|
function serializeWithMarkers(el) {
|
|
516
|
-
return serializeStatic(
|
|
586
|
+
return serializeStatic(templateTree(el)).split(SENTINEL).join(HOLE_START + HOLE_END);
|
|
517
587
|
}
|
|
518
|
-
function
|
|
588
|
+
function templateTree(el) {
|
|
589
|
+
const plan = propPlan(el);
|
|
519
590
|
return {
|
|
520
591
|
...el,
|
|
592
|
+
props: plan ? plan.serialize : [],
|
|
521
593
|
children: el.children.map(
|
|
522
|
-
(child) => isHole(child) ? { kind: "text", value: SENTINEL } : child.kind === "element" ?
|
|
594
|
+
(child) => isHole(child) ? { kind: "text", value: SENTINEL } : child.kind === "element" ? templateTree(child) : child
|
|
523
595
|
)
|
|
524
596
|
};
|
|
525
597
|
}
|
|
@@ -638,6 +710,55 @@ function emitComponent(name, props, children, used, templates, at) {
|
|
|
638
710
|
const mark = at ? `globalThis.${SOURCE_MARKER}?.(${JSON.stringify(at.file)},${at.line},${at.column},${JSON.stringify(name)}), ` : "";
|
|
639
711
|
return `createMemo(${paren(`${mark}() => createComponent(${name}, ${obj})`, "value")})`;
|
|
640
712
|
}
|
|
713
|
+
function bindingTarget(binding) {
|
|
714
|
+
const name = binding.prop.name;
|
|
715
|
+
if (binding.kind === "boolAttr") return name.slice("bool:".length);
|
|
716
|
+
if (name.startsWith("prop:")) return name.slice("prop:".length);
|
|
717
|
+
if (name.startsWith("attr:")) return name.slice("attr:".length);
|
|
718
|
+
return htmlAttrName(name);
|
|
719
|
+
}
|
|
720
|
+
function bindingStatement(binding, used) {
|
|
721
|
+
const { ref, prop, kind } = binding;
|
|
722
|
+
const value = propValue(prop);
|
|
723
|
+
switch (kind) {
|
|
724
|
+
case "class":
|
|
725
|
+
used.add("setClassName");
|
|
726
|
+
return `setClassName(${ref}, ${value});`;
|
|
727
|
+
case "classList":
|
|
728
|
+
used.add("setClassList");
|
|
729
|
+
return `setClassList(${ref}, ${value}, []);`;
|
|
730
|
+
case "classListDynamic":
|
|
731
|
+
used.add("setDynamicClassList");
|
|
732
|
+
return `setDynamicClassList(${ref}, ${value});`;
|
|
733
|
+
case "style":
|
|
734
|
+
used.add("setStyle");
|
|
735
|
+
return `setStyle(${ref}, ${value}, []);`;
|
|
736
|
+
case "styleDynamic":
|
|
737
|
+
used.add("setDynamicStyle");
|
|
738
|
+
return `setDynamicStyle(${ref}, ${value});`;
|
|
739
|
+
case "attr":
|
|
740
|
+
used.add("setDynamicAttribute");
|
|
741
|
+
return `setDynamicAttribute(${ref}, ${JSON.stringify(bindingTarget(binding))}, ${value});`;
|
|
742
|
+
case "property":
|
|
743
|
+
used.add("setDynamicProperty");
|
|
744
|
+
return `setDynamicProperty(${ref}, ${JSON.stringify(bindingTarget(binding))}, ${value});`;
|
|
745
|
+
case "boolAttr":
|
|
746
|
+
used.add("setDynamicBoolAttribute");
|
|
747
|
+
return `setDynamicBoolAttribute(${ref}, ${JSON.stringify(bindingTarget(binding))}, ${value});`;
|
|
748
|
+
case "event":
|
|
749
|
+
used.add("addDelegatedEventListener");
|
|
750
|
+
return `addDelegatedEventListener(${ref}, ${JSON.stringify(prop.event.name)}, ${value});`;
|
|
751
|
+
case "nativeEvent":
|
|
752
|
+
used.add("addNativeEventListener");
|
|
753
|
+
return `addNativeEventListener(${ref}, ${JSON.stringify(prop.name.slice(3))}, ${value});`;
|
|
754
|
+
case "ref":
|
|
755
|
+
used.add("handleRef");
|
|
756
|
+
return `handleRef(${value}, ${ref});`;
|
|
757
|
+
case "use":
|
|
758
|
+
used.add("applyUse");
|
|
759
|
+
return `applyUse(${ref}, ${value});`;
|
|
760
|
+
}
|
|
761
|
+
}
|
|
641
762
|
function staticAttrAssignment(el, prop) {
|
|
642
763
|
const name = htmlAttrName(prop.name);
|
|
643
764
|
const value = prop.literal;
|
|
@@ -688,6 +809,7 @@ function emitNode(node, used, templates) {
|
|
|
688
809
|
`const _el$ = templateNode(${id}, ${JSON.stringify(plan.tag)}, true${at ? `, false, ${JSON.stringify(at)}` : ""});`
|
|
689
810
|
];
|
|
690
811
|
for (const step of plan.steps) lines.push(`const ${step.ref} = ${step.expr};`);
|
|
812
|
+
for (const binding of plan.bindings) lines.push(bindingStatement(binding, used));
|
|
691
813
|
for (const hole of plan.holes) {
|
|
692
814
|
lines.push(
|
|
693
815
|
`insert(${hole.parentRef}, holeScope(${hole.startRef}, () => ${paren(emitNode(hole.node, used, templates), "arrowBody")}), ${hole.endRef}, holeContent(${hole.startRef}, ${hole.endRef}));`
|