@fluixi/compiler 1.0.0-alpha.104 → 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-5SX36G76.mjs → babel-HJY4RVAV.mjs} +33 -20
- package/dist/{chunk-NWF66YTU.mjs → chunk-4XEOMQ57.mjs} +1 -1
- package/dist/{chunk-FMQPBKTW.mjs → chunk-JUFI6IR3.mjs} +1 -1
- package/dist/{chunk-NUET3BJB.mjs → chunk-LCQHL2VQ.mjs} +132 -10
- package/dist/{chunk-2O2YW5ZO.mjs → chunk-LGUZRHYN.mjs} +2 -2
- package/dist/{chunk-RBIYCE6M.mjs → chunk-TDN5MYWI.mjs} +1 -1
- package/dist/{chunk-ZDZKJQ5N.mjs → chunk-W7DYOMXJ.mjs} +2 -2
- package/dist/{chunk-DN33T5GJ.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-3Z3ZKJLB.mjs → server-fns-WZJK4BJE.mjs} +5 -5
- package/dist/{server-functions-DB7AHWE6.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-VMK2URDB.mjs → transform-NO46NFQH.mjs} +11 -14
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/package.json +4 -4
package/dist/transform/index.cjs
CHANGED
|
@@ -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
|
"use strict";
|
|
3
3
|
var __create = Object.create;
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
@@ -957,10 +957,64 @@ function isHole(node) {
|
|
|
957
957
|
function isTemplateChild(node) {
|
|
958
958
|
return node.kind === "text" || node.kind === "element" && isTemplateElement(node);
|
|
959
959
|
}
|
|
960
|
+
var PROPERTY_BINDS = /* @__PURE__ */ new Set(["indeterminate"]);
|
|
961
|
+
function disposition(prop) {
|
|
962
|
+
if (prop.kind === "spread") return null;
|
|
963
|
+
if (prop.name === "ref") return "ref";
|
|
964
|
+
if (prop.name === "use") return "use";
|
|
965
|
+
if (prop.kind === "event") return prop.event ? "event" : null;
|
|
966
|
+
if (prop.kind === "prop") return "property";
|
|
967
|
+
if (prop.kind !== "attr") return null;
|
|
968
|
+
const name = prop.name;
|
|
969
|
+
if (name.startsWith("on:")) return "nativeEvent";
|
|
970
|
+
if (name.startsWith("prop:")) return "property";
|
|
971
|
+
if (name.startsWith("attr:")) return "attr";
|
|
972
|
+
if (name.startsWith("bool:")) return "boolAttr";
|
|
973
|
+
if (name === "className" || name === "class") {
|
|
974
|
+
return isPlainLiteralAttr(prop) ? "serialize" : "class";
|
|
975
|
+
}
|
|
976
|
+
if (name === "classList") {
|
|
977
|
+
if (isPlainLiteralAttr(prop)) return "serialize";
|
|
978
|
+
return prop.reactive ? "classListDynamic" : "classList";
|
|
979
|
+
}
|
|
980
|
+
if (name === "style") {
|
|
981
|
+
if (isPlainLiteralAttr(prop)) return "serialize";
|
|
982
|
+
return prop.reactive ? "styleDynamic" : "style";
|
|
983
|
+
}
|
|
984
|
+
if (name.includes(":")) return null;
|
|
985
|
+
if (PROPERTY_ONLY.has(name)) return null;
|
|
986
|
+
if (PROPERTY_BINDS.has(name)) return "property";
|
|
987
|
+
if (prop.expr === void 0) return isPlainLiteralAttr(prop) ? "serialize" : null;
|
|
988
|
+
return "attr";
|
|
989
|
+
}
|
|
990
|
+
function effectiveProps(el) {
|
|
991
|
+
const order = [];
|
|
992
|
+
const byName = /* @__PURE__ */ new Map();
|
|
993
|
+
for (const prop of el.props) {
|
|
994
|
+
if (!byName.has(prop.name)) order.push(prop.name);
|
|
995
|
+
byName.set(prop.name, prop);
|
|
996
|
+
}
|
|
997
|
+
return order.map((name) => byName.get(name));
|
|
998
|
+
}
|
|
999
|
+
function propPlan(el) {
|
|
1000
|
+
const custom = el.tag.includes("-");
|
|
1001
|
+
const plan = { serialize: [], bindings: [] };
|
|
1002
|
+
for (const prop of effectiveProps(el)) {
|
|
1003
|
+
const kind = disposition(prop);
|
|
1004
|
+
if (kind === null) return null;
|
|
1005
|
+
if (kind === "serialize") {
|
|
1006
|
+
plan.serialize.push(prop);
|
|
1007
|
+
continue;
|
|
1008
|
+
}
|
|
1009
|
+
if (custom) return null;
|
|
1010
|
+
plan.bindings.push({ prop, kind });
|
|
1011
|
+
}
|
|
1012
|
+
return plan;
|
|
1013
|
+
}
|
|
960
1014
|
function isTemplateElement(node) {
|
|
961
1015
|
if (node.svg) return false;
|
|
962
1016
|
if (isRawTextElement(node.tag)) return false;
|
|
963
|
-
if (!node
|
|
1017
|
+
if (!propPlan(node)) return false;
|
|
964
1018
|
return node.children.every((c) => isTemplateChild(c) || isHole(c));
|
|
965
1019
|
}
|
|
966
1020
|
function containsHole(node) {
|
|
@@ -968,6 +1022,15 @@ function containsHole(node) {
|
|
|
968
1022
|
const children = node.children;
|
|
969
1023
|
return children ? children.some(containsHole) : false;
|
|
970
1024
|
}
|
|
1025
|
+
function containsBinding(node) {
|
|
1026
|
+
if (node.kind !== "element") return false;
|
|
1027
|
+
const plan = propPlan(node);
|
|
1028
|
+
if (plan && plan.bindings.length > 0) return true;
|
|
1029
|
+
return node.children.some(containsBinding);
|
|
1030
|
+
}
|
|
1031
|
+
function interesting(node) {
|
|
1032
|
+
return containsHole(node) || containsBinding(node);
|
|
1033
|
+
}
|
|
971
1034
|
function addressable(el) {
|
|
972
1035
|
for (let i = 0; i < el.children.length; i++) {
|
|
973
1036
|
const child = el.children[i];
|
|
@@ -981,9 +1044,10 @@ function addressable(el) {
|
|
|
981
1044
|
function planPartialTemplate(root) {
|
|
982
1045
|
if (!isTemplateElement(root)) return null;
|
|
983
1046
|
if (!addressable(root)) return null;
|
|
984
|
-
if (!root
|
|
1047
|
+
if (!interesting(root)) return null;
|
|
985
1048
|
const steps = [];
|
|
986
1049
|
const holes = [];
|
|
1050
|
+
const bindings = [];
|
|
987
1051
|
let refCount = 0;
|
|
988
1052
|
const declare = (expr) => {
|
|
989
1053
|
const ref = `_n$${refCount++}`;
|
|
@@ -991,11 +1055,17 @@ function planPartialTemplate(root) {
|
|
|
991
1055
|
return ref;
|
|
992
1056
|
};
|
|
993
1057
|
walk8(root, "_el$");
|
|
994
|
-
return { html: serializeWithMarkers(root), tag: root.tag, steps, holes };
|
|
1058
|
+
return { html: serializeWithMarkers(root), tag: root.tag, steps, holes, bindings };
|
|
995
1059
|
function walk8(el, elementRef) {
|
|
1060
|
+
const plan = propPlan(el);
|
|
1061
|
+
if (plan) {
|
|
1062
|
+
for (const binding of plan.bindings) {
|
|
1063
|
+
bindings.push({ ref: elementRef, prop: binding.prop, kind: binding.kind });
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
996
1066
|
let last = -1;
|
|
997
1067
|
el.children.forEach((child, i) => {
|
|
998
|
-
if (
|
|
1068
|
+
if (interesting(child)) last = i;
|
|
999
1069
|
});
|
|
1000
1070
|
let previous = null;
|
|
1001
1071
|
for (let i = 0; i <= last; i++) {
|
|
@@ -1009,19 +1079,21 @@ function planPartialTemplate(root) {
|
|
|
1009
1079
|
continue;
|
|
1010
1080
|
}
|
|
1011
1081
|
const ref = declare(expr);
|
|
1012
|
-
if (child.kind === "element" &&
|
|
1082
|
+
if (child.kind === "element" && interesting(child)) walk8(child, ref);
|
|
1013
1083
|
previous = ref;
|
|
1014
1084
|
}
|
|
1015
1085
|
}
|
|
1016
1086
|
}
|
|
1017
1087
|
function serializeWithMarkers(el) {
|
|
1018
|
-
return serializeStatic(
|
|
1088
|
+
return serializeStatic(templateTree(el)).split(SENTINEL).join(HOLE_START + HOLE_END);
|
|
1019
1089
|
}
|
|
1020
|
-
function
|
|
1090
|
+
function templateTree(el) {
|
|
1091
|
+
const plan = propPlan(el);
|
|
1021
1092
|
return {
|
|
1022
1093
|
...el,
|
|
1094
|
+
props: plan ? plan.serialize : [],
|
|
1023
1095
|
children: el.children.map(
|
|
1024
|
-
(child) => isHole(child) ? { kind: "text", value: SENTINEL } : child.kind === "element" ?
|
|
1096
|
+
(child) => isHole(child) ? { kind: "text", value: SENTINEL } : child.kind === "element" ? templateTree(child) : child
|
|
1025
1097
|
)
|
|
1026
1098
|
};
|
|
1027
1099
|
}
|
|
@@ -1652,6 +1724,55 @@ function emitComponent(name, props, children, used, templates, at) {
|
|
|
1652
1724
|
const mark = at ? `globalThis.${SOURCE_MARKER}?.(${JSON.stringify(at.file)},${at.line},${at.column},${JSON.stringify(name)}), ` : "";
|
|
1653
1725
|
return `createMemo(${paren(`${mark}() => createComponent(${name}, ${obj})`, "value")})`;
|
|
1654
1726
|
}
|
|
1727
|
+
function bindingTarget(binding) {
|
|
1728
|
+
const name = binding.prop.name;
|
|
1729
|
+
if (binding.kind === "boolAttr") return name.slice("bool:".length);
|
|
1730
|
+
if (name.startsWith("prop:")) return name.slice("prop:".length);
|
|
1731
|
+
if (name.startsWith("attr:")) return name.slice("attr:".length);
|
|
1732
|
+
return htmlAttrName(name);
|
|
1733
|
+
}
|
|
1734
|
+
function bindingStatement(binding, used) {
|
|
1735
|
+
const { ref, prop, kind } = binding;
|
|
1736
|
+
const value = propValue(prop);
|
|
1737
|
+
switch (kind) {
|
|
1738
|
+
case "class":
|
|
1739
|
+
used.add("setClassName");
|
|
1740
|
+
return `setClassName(${ref}, ${value});`;
|
|
1741
|
+
case "classList":
|
|
1742
|
+
used.add("setClassList");
|
|
1743
|
+
return `setClassList(${ref}, ${value}, []);`;
|
|
1744
|
+
case "classListDynamic":
|
|
1745
|
+
used.add("setDynamicClassList");
|
|
1746
|
+
return `setDynamicClassList(${ref}, ${value});`;
|
|
1747
|
+
case "style":
|
|
1748
|
+
used.add("setStyle");
|
|
1749
|
+
return `setStyle(${ref}, ${value}, []);`;
|
|
1750
|
+
case "styleDynamic":
|
|
1751
|
+
used.add("setDynamicStyle");
|
|
1752
|
+
return `setDynamicStyle(${ref}, ${value});`;
|
|
1753
|
+
case "attr":
|
|
1754
|
+
used.add("setDynamicAttribute");
|
|
1755
|
+
return `setDynamicAttribute(${ref}, ${JSON.stringify(bindingTarget(binding))}, ${value});`;
|
|
1756
|
+
case "property":
|
|
1757
|
+
used.add("setDynamicProperty");
|
|
1758
|
+
return `setDynamicProperty(${ref}, ${JSON.stringify(bindingTarget(binding))}, ${value});`;
|
|
1759
|
+
case "boolAttr":
|
|
1760
|
+
used.add("setDynamicBoolAttribute");
|
|
1761
|
+
return `setDynamicBoolAttribute(${ref}, ${JSON.stringify(bindingTarget(binding))}, ${value});`;
|
|
1762
|
+
case "event":
|
|
1763
|
+
used.add("addDelegatedEventListener");
|
|
1764
|
+
return `addDelegatedEventListener(${ref}, ${JSON.stringify(prop.event.name)}, ${value});`;
|
|
1765
|
+
case "nativeEvent":
|
|
1766
|
+
used.add("addNativeEventListener");
|
|
1767
|
+
return `addNativeEventListener(${ref}, ${JSON.stringify(prop.name.slice(3))}, ${value});`;
|
|
1768
|
+
case "ref":
|
|
1769
|
+
used.add("handleRef");
|
|
1770
|
+
return `handleRef(${value}, ${ref});`;
|
|
1771
|
+
case "use":
|
|
1772
|
+
used.add("applyUse");
|
|
1773
|
+
return `applyUse(${ref}, ${value});`;
|
|
1774
|
+
}
|
|
1775
|
+
}
|
|
1655
1776
|
function staticAttrAssignment(el, prop) {
|
|
1656
1777
|
const name = htmlAttrName(prop.name);
|
|
1657
1778
|
const value = prop.literal;
|
|
@@ -1702,6 +1823,7 @@ function emitNode(node, used, templates) {
|
|
|
1702
1823
|
`const _el$ = templateNode(${id}, ${JSON.stringify(plan.tag)}, true${at ? `, false, ${JSON.stringify(at)}` : ""});`
|
|
1703
1824
|
];
|
|
1704
1825
|
for (const step of plan.steps) lines.push(`const ${step.ref} = ${step.expr};`);
|
|
1826
|
+
for (const binding of plan.bindings) lines.push(bindingStatement(binding, used));
|
|
1705
1827
|
for (const hole of plan.holes) {
|
|
1706
1828
|
lines.push(
|
|
1707
1829
|
`insert(${hole.parentRef}, holeScope(${hole.startRef}, () => ${paren(emitNode(hole.node, used, templates), "arrowBody")}), ${hole.endRef}, holeContent(${hole.startRef}, ${hole.endRef}));`
|
|
@@ -3665,11 +3787,8 @@ function transformTemplates(code, id, options = {}) {
|
|
|
3665
3787
|
const hoisted = /* @__PURE__ */ new Map();
|
|
3666
3788
|
const edits = [...props.edits, ...intrinsics.edits, ...sources.edits, ...styles?.edits ?? []];
|
|
3667
3789
|
for (const node of found) {
|
|
3668
|
-
const nested = found.some(
|
|
3669
|
-
(o) => o !== node && o.start <= node.start && o.end >= node.end && o.end - o.start > node.end - node.start
|
|
3670
|
-
);
|
|
3671
3790
|
if (isJsx(node)) {
|
|
3672
|
-
edits.push({ start: node.start, end: node.end, code: compileJsx(code, node, edits,
|
|
3791
|
+
edits.push({ start: node.start, end: node.end, code: compileJsx(code, node, edits, used, needs, hoisted, options, sourceName, styles) });
|
|
3673
3792
|
continue;
|
|
3674
3793
|
}
|
|
3675
3794
|
const holes = node.quasi.expressions.map(
|
|
@@ -3696,7 +3815,7 @@ function transformTemplates(code, id, options = {}) {
|
|
|
3696
3815
|
...options.sourceLocations === true ? { sourceFile: sourceName, positionAt: positionsIn(code) } : {},
|
|
3697
3816
|
// Same defaults as the plugin, so moving a build over is not a rendering change.
|
|
3698
3817
|
templateClone: options.templateClone ?? true,
|
|
3699
|
-
partialTemplates:
|
|
3818
|
+
partialTemplates: options.partialTemplates ?? true,
|
|
3700
3819
|
svg: templateTags.get(node.tag.name) === "svg"
|
|
3701
3820
|
});
|
|
3702
3821
|
for (const symbol of result.imports) used.add(symbol);
|
|
@@ -3768,7 +3887,7 @@ function transformTemplates(code, id, options = {}) {
|
|
|
3768
3887
|
...styles?.references.length ? { styleReferences: styles.references } : {}
|
|
3769
3888
|
};
|
|
3770
3889
|
}
|
|
3771
|
-
function compileJsx(code, node, edits,
|
|
3890
|
+
function compileJsx(code, node, edits, used, needs, hoisted, options, sourceFile, styles) {
|
|
3772
3891
|
const ir = buildJsxIR(node, {
|
|
3773
3892
|
code: (n) => slice(code, n.start, n.end, edits),
|
|
3774
3893
|
used,
|
|
@@ -3793,7 +3912,7 @@ function compileJsx(code, node, edits, nested, used, needs, hoisted, options, so
|
|
|
3793
3912
|
collapseStrategies(ir);
|
|
3794
3913
|
const emitted = imperativeBackend.emit(ir, {
|
|
3795
3914
|
templateClone: options.templateClone ?? true,
|
|
3796
|
-
partialTemplates:
|
|
3915
|
+
partialTemplates: options.partialTemplates ?? true
|
|
3797
3916
|
});
|
|
3798
3917
|
for (const symbol of emitted.imports) used.add(symbol);
|
|
3799
3918
|
collectNeeds(ir, needs);
|
package/dist/transform/index.mjs
CHANGED
|
@@ -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
|
// src/transform/templates.ts
|
|
4
4
|
import { parse as parse2 } from "@babel/parser";
|
|
@@ -1993,10 +1993,64 @@ function isHole(node) {
|
|
|
1993
1993
|
function isTemplateChild(node) {
|
|
1994
1994
|
return node.kind === "text" || node.kind === "element" && isTemplateElement(node);
|
|
1995
1995
|
}
|
|
1996
|
+
var PROPERTY_BINDS = /* @__PURE__ */ new Set(["indeterminate"]);
|
|
1997
|
+
function disposition(prop) {
|
|
1998
|
+
if (prop.kind === "spread") return null;
|
|
1999
|
+
if (prop.name === "ref") return "ref";
|
|
2000
|
+
if (prop.name === "use") return "use";
|
|
2001
|
+
if (prop.kind === "event") return prop.event ? "event" : null;
|
|
2002
|
+
if (prop.kind === "prop") return "property";
|
|
2003
|
+
if (prop.kind !== "attr") return null;
|
|
2004
|
+
const name = prop.name;
|
|
2005
|
+
if (name.startsWith("on:")) return "nativeEvent";
|
|
2006
|
+
if (name.startsWith("prop:")) return "property";
|
|
2007
|
+
if (name.startsWith("attr:")) return "attr";
|
|
2008
|
+
if (name.startsWith("bool:")) return "boolAttr";
|
|
2009
|
+
if (name === "className" || name === "class") {
|
|
2010
|
+
return isPlainLiteralAttr(prop) ? "serialize" : "class";
|
|
2011
|
+
}
|
|
2012
|
+
if (name === "classList") {
|
|
2013
|
+
if (isPlainLiteralAttr(prop)) return "serialize";
|
|
2014
|
+
return prop.reactive ? "classListDynamic" : "classList";
|
|
2015
|
+
}
|
|
2016
|
+
if (name === "style") {
|
|
2017
|
+
if (isPlainLiteralAttr(prop)) return "serialize";
|
|
2018
|
+
return prop.reactive ? "styleDynamic" : "style";
|
|
2019
|
+
}
|
|
2020
|
+
if (name.includes(":")) return null;
|
|
2021
|
+
if (PROPERTY_ONLY.has(name)) return null;
|
|
2022
|
+
if (PROPERTY_BINDS.has(name)) return "property";
|
|
2023
|
+
if (prop.expr === void 0) return isPlainLiteralAttr(prop) ? "serialize" : null;
|
|
2024
|
+
return "attr";
|
|
2025
|
+
}
|
|
2026
|
+
function effectiveProps(el) {
|
|
2027
|
+
const order = [];
|
|
2028
|
+
const byName = /* @__PURE__ */ new Map();
|
|
2029
|
+
for (const prop of el.props) {
|
|
2030
|
+
if (!byName.has(prop.name)) order.push(prop.name);
|
|
2031
|
+
byName.set(prop.name, prop);
|
|
2032
|
+
}
|
|
2033
|
+
return order.map((name) => byName.get(name));
|
|
2034
|
+
}
|
|
2035
|
+
function propPlan(el) {
|
|
2036
|
+
const custom = el.tag.includes("-");
|
|
2037
|
+
const plan = { serialize: [], bindings: [] };
|
|
2038
|
+
for (const prop of effectiveProps(el)) {
|
|
2039
|
+
const kind = disposition(prop);
|
|
2040
|
+
if (kind === null) return null;
|
|
2041
|
+
if (kind === "serialize") {
|
|
2042
|
+
plan.serialize.push(prop);
|
|
2043
|
+
continue;
|
|
2044
|
+
}
|
|
2045
|
+
if (custom) return null;
|
|
2046
|
+
plan.bindings.push({ prop, kind });
|
|
2047
|
+
}
|
|
2048
|
+
return plan;
|
|
2049
|
+
}
|
|
1996
2050
|
function isTemplateElement(node) {
|
|
1997
2051
|
if (node.svg) return false;
|
|
1998
2052
|
if (isRawTextElement(node.tag)) return false;
|
|
1999
|
-
if (!node
|
|
2053
|
+
if (!propPlan(node)) return false;
|
|
2000
2054
|
return node.children.every((c) => isTemplateChild(c) || isHole(c));
|
|
2001
2055
|
}
|
|
2002
2056
|
function containsHole(node) {
|
|
@@ -2004,6 +2058,15 @@ function containsHole(node) {
|
|
|
2004
2058
|
const children = node.children;
|
|
2005
2059
|
return children ? children.some(containsHole) : false;
|
|
2006
2060
|
}
|
|
2061
|
+
function containsBinding(node) {
|
|
2062
|
+
if (node.kind !== "element") return false;
|
|
2063
|
+
const plan = propPlan(node);
|
|
2064
|
+
if (plan && plan.bindings.length > 0) return true;
|
|
2065
|
+
return node.children.some(containsBinding);
|
|
2066
|
+
}
|
|
2067
|
+
function interesting(node) {
|
|
2068
|
+
return containsHole(node) || containsBinding(node);
|
|
2069
|
+
}
|
|
2007
2070
|
function addressable(el) {
|
|
2008
2071
|
for (let i = 0; i < el.children.length; i++) {
|
|
2009
2072
|
const child = el.children[i];
|
|
@@ -2017,9 +2080,10 @@ function addressable(el) {
|
|
|
2017
2080
|
function planPartialTemplate(root) {
|
|
2018
2081
|
if (!isTemplateElement(root)) return null;
|
|
2019
2082
|
if (!addressable(root)) return null;
|
|
2020
|
-
if (!root
|
|
2083
|
+
if (!interesting(root)) return null;
|
|
2021
2084
|
const steps = [];
|
|
2022
2085
|
const holes = [];
|
|
2086
|
+
const bindings = [];
|
|
2023
2087
|
let refCount = 0;
|
|
2024
2088
|
const declare = (expr) => {
|
|
2025
2089
|
const ref = `_n$${refCount++}`;
|
|
@@ -2027,11 +2091,17 @@ function planPartialTemplate(root) {
|
|
|
2027
2091
|
return ref;
|
|
2028
2092
|
};
|
|
2029
2093
|
walk8(root, "_el$");
|
|
2030
|
-
return { html: serializeWithMarkers(root), tag: root.tag, steps, holes };
|
|
2094
|
+
return { html: serializeWithMarkers(root), tag: root.tag, steps, holes, bindings };
|
|
2031
2095
|
function walk8(el, elementRef) {
|
|
2096
|
+
const plan = propPlan(el);
|
|
2097
|
+
if (plan) {
|
|
2098
|
+
for (const binding of plan.bindings) {
|
|
2099
|
+
bindings.push({ ref: elementRef, prop: binding.prop, kind: binding.kind });
|
|
2100
|
+
}
|
|
2101
|
+
}
|
|
2032
2102
|
let last = -1;
|
|
2033
2103
|
el.children.forEach((child, i) => {
|
|
2034
|
-
if (
|
|
2104
|
+
if (interesting(child)) last = i;
|
|
2035
2105
|
});
|
|
2036
2106
|
let previous = null;
|
|
2037
2107
|
for (let i = 0; i <= last; i++) {
|
|
@@ -2045,19 +2115,21 @@ function planPartialTemplate(root) {
|
|
|
2045
2115
|
continue;
|
|
2046
2116
|
}
|
|
2047
2117
|
const ref = declare(expr);
|
|
2048
|
-
if (child.kind === "element" &&
|
|
2118
|
+
if (child.kind === "element" && interesting(child)) walk8(child, ref);
|
|
2049
2119
|
previous = ref;
|
|
2050
2120
|
}
|
|
2051
2121
|
}
|
|
2052
2122
|
}
|
|
2053
2123
|
function serializeWithMarkers(el) {
|
|
2054
|
-
return serializeStatic(
|
|
2124
|
+
return serializeStatic(templateTree(el)).split(SENTINEL).join(HOLE_START + HOLE_END);
|
|
2055
2125
|
}
|
|
2056
|
-
function
|
|
2126
|
+
function templateTree(el) {
|
|
2127
|
+
const plan = propPlan(el);
|
|
2057
2128
|
return {
|
|
2058
2129
|
...el,
|
|
2130
|
+
props: plan ? plan.serialize : [],
|
|
2059
2131
|
children: el.children.map(
|
|
2060
|
-
(child) => isHole(child) ? { kind: "text", value: SENTINEL } : child.kind === "element" ?
|
|
2132
|
+
(child) => isHole(child) ? { kind: "text", value: SENTINEL } : child.kind === "element" ? templateTree(child) : child
|
|
2061
2133
|
)
|
|
2062
2134
|
};
|
|
2063
2135
|
}
|
|
@@ -2688,6 +2760,55 @@ function emitComponent(name, props, children, used, templates, at) {
|
|
|
2688
2760
|
const mark = at ? `globalThis.${SOURCE_MARKER}?.(${JSON.stringify(at.file)},${at.line},${at.column},${JSON.stringify(name)}), ` : "";
|
|
2689
2761
|
return `createMemo(${paren(`${mark}() => createComponent(${name}, ${obj})`, "value")})`;
|
|
2690
2762
|
}
|
|
2763
|
+
function bindingTarget(binding) {
|
|
2764
|
+
const name = binding.prop.name;
|
|
2765
|
+
if (binding.kind === "boolAttr") return name.slice("bool:".length);
|
|
2766
|
+
if (name.startsWith("prop:")) return name.slice("prop:".length);
|
|
2767
|
+
if (name.startsWith("attr:")) return name.slice("attr:".length);
|
|
2768
|
+
return htmlAttrName(name);
|
|
2769
|
+
}
|
|
2770
|
+
function bindingStatement(binding, used) {
|
|
2771
|
+
const { ref, prop, kind } = binding;
|
|
2772
|
+
const value = propValue(prop);
|
|
2773
|
+
switch (kind) {
|
|
2774
|
+
case "class":
|
|
2775
|
+
used.add("setClassName");
|
|
2776
|
+
return `setClassName(${ref}, ${value});`;
|
|
2777
|
+
case "classList":
|
|
2778
|
+
used.add("setClassList");
|
|
2779
|
+
return `setClassList(${ref}, ${value}, []);`;
|
|
2780
|
+
case "classListDynamic":
|
|
2781
|
+
used.add("setDynamicClassList");
|
|
2782
|
+
return `setDynamicClassList(${ref}, ${value});`;
|
|
2783
|
+
case "style":
|
|
2784
|
+
used.add("setStyle");
|
|
2785
|
+
return `setStyle(${ref}, ${value}, []);`;
|
|
2786
|
+
case "styleDynamic":
|
|
2787
|
+
used.add("setDynamicStyle");
|
|
2788
|
+
return `setDynamicStyle(${ref}, ${value});`;
|
|
2789
|
+
case "attr":
|
|
2790
|
+
used.add("setDynamicAttribute");
|
|
2791
|
+
return `setDynamicAttribute(${ref}, ${JSON.stringify(bindingTarget(binding))}, ${value});`;
|
|
2792
|
+
case "property":
|
|
2793
|
+
used.add("setDynamicProperty");
|
|
2794
|
+
return `setDynamicProperty(${ref}, ${JSON.stringify(bindingTarget(binding))}, ${value});`;
|
|
2795
|
+
case "boolAttr":
|
|
2796
|
+
used.add("setDynamicBoolAttribute");
|
|
2797
|
+
return `setDynamicBoolAttribute(${ref}, ${JSON.stringify(bindingTarget(binding))}, ${value});`;
|
|
2798
|
+
case "event":
|
|
2799
|
+
used.add("addDelegatedEventListener");
|
|
2800
|
+
return `addDelegatedEventListener(${ref}, ${JSON.stringify(prop.event.name)}, ${value});`;
|
|
2801
|
+
case "nativeEvent":
|
|
2802
|
+
used.add("addNativeEventListener");
|
|
2803
|
+
return `addNativeEventListener(${ref}, ${JSON.stringify(prop.name.slice(3))}, ${value});`;
|
|
2804
|
+
case "ref":
|
|
2805
|
+
used.add("handleRef");
|
|
2806
|
+
return `handleRef(${value}, ${ref});`;
|
|
2807
|
+
case "use":
|
|
2808
|
+
used.add("applyUse");
|
|
2809
|
+
return `applyUse(${ref}, ${value});`;
|
|
2810
|
+
}
|
|
2811
|
+
}
|
|
2691
2812
|
function staticAttrAssignment(el, prop) {
|
|
2692
2813
|
const name = htmlAttrName(prop.name);
|
|
2693
2814
|
const value = prop.literal;
|
|
@@ -2738,6 +2859,7 @@ function emitNode(node, used, templates) {
|
|
|
2738
2859
|
`const _el$ = templateNode(${id}, ${JSON.stringify(plan.tag)}, true${at ? `, false, ${JSON.stringify(at)}` : ""});`
|
|
2739
2860
|
];
|
|
2740
2861
|
for (const step of plan.steps) lines.push(`const ${step.ref} = ${step.expr};`);
|
|
2862
|
+
for (const binding of plan.bindings) lines.push(bindingStatement(binding, used));
|
|
2741
2863
|
for (const hole of plan.holes) {
|
|
2742
2864
|
lines.push(
|
|
2743
2865
|
`insert(${hole.parentRef}, holeScope(${hole.startRef}, () => ${paren(emitNode(hole.node, used, templates), "arrowBody")}), ${hole.endRef}, holeContent(${hole.startRef}, ${hole.endRef}));`
|
|
@@ -4702,11 +4824,8 @@ function transformTemplates(code, id, options = {}) {
|
|
|
4702
4824
|
const hoisted = /* @__PURE__ */ new Map();
|
|
4703
4825
|
const edits = [...props.edits, ...intrinsics.edits, ...sources.edits, ...styles?.edits ?? []];
|
|
4704
4826
|
for (const node of found) {
|
|
4705
|
-
const nested = found.some(
|
|
4706
|
-
(o) => o !== node && o.start <= node.start && o.end >= node.end && o.end - o.start > node.end - node.start
|
|
4707
|
-
);
|
|
4708
4827
|
if (isJsx(node)) {
|
|
4709
|
-
edits.push({ start: node.start, end: node.end, code: compileJsx(code, node, edits,
|
|
4828
|
+
edits.push({ start: node.start, end: node.end, code: compileJsx(code, node, edits, used, needs, hoisted, options, sourceName, styles) });
|
|
4710
4829
|
continue;
|
|
4711
4830
|
}
|
|
4712
4831
|
const holes = node.quasi.expressions.map(
|
|
@@ -4733,7 +4852,7 @@ function transformTemplates(code, id, options = {}) {
|
|
|
4733
4852
|
...options.sourceLocations === true ? { sourceFile: sourceName, positionAt: positionsIn(code) } : {},
|
|
4734
4853
|
// Same defaults as the plugin, so moving a build over is not a rendering change.
|
|
4735
4854
|
templateClone: options.templateClone ?? true,
|
|
4736
|
-
partialTemplates:
|
|
4855
|
+
partialTemplates: options.partialTemplates ?? true,
|
|
4737
4856
|
svg: templateTags.get(node.tag.name) === "svg"
|
|
4738
4857
|
});
|
|
4739
4858
|
for (const symbol of result.imports) used.add(symbol);
|
|
@@ -4805,7 +4924,7 @@ function transformTemplates(code, id, options = {}) {
|
|
|
4805
4924
|
...styles?.references.length ? { styleReferences: styles.references } : {}
|
|
4806
4925
|
};
|
|
4807
4926
|
}
|
|
4808
|
-
function compileJsx(code, node, edits,
|
|
4927
|
+
function compileJsx(code, node, edits, used, needs, hoisted, options, sourceFile, styles) {
|
|
4809
4928
|
const ir = buildJsxIR(node, {
|
|
4810
4929
|
code: (n2) => slice(code, n2.start, n2.end, edits),
|
|
4811
4930
|
used,
|
|
@@ -4830,7 +4949,7 @@ function compileJsx(code, node, edits, nested, used, needs, hoisted, options, so
|
|
|
4830
4949
|
collapseStrategies(ir);
|
|
4831
4950
|
const emitted = imperativeBackend.emit(ir, {
|
|
4832
4951
|
templateClone: options.templateClone ?? true,
|
|
4833
|
-
partialTemplates:
|
|
4952
|
+
partialTemplates: options.partialTemplates ?? true
|
|
4834
4953
|
});
|
|
4835
4954
|
for (const symbol of emitted.imports) used.add(symbol);
|
|
4836
4955
|
collectNeeds(ir, needs);
|