@fluixi/compiler 1.0.0-alpha.83 → 1.0.0-alpha.84

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 (163) hide show
  1. package/dist/analyze/expr-shape.cjs +62 -1
  2. package/dist/analyze/expr-shape.d.cts +14 -0
  3. package/dist/analyze/expr-shape.mjs +41 -1
  4. package/dist/analyze/intrinsics.cjs +80 -1
  5. package/dist/analyze/intrinsics.d.cts +66 -0
  6. package/dist/analyze/intrinsics.mjs +59 -1
  7. package/dist/analyze/paren.cjs +134 -0
  8. package/dist/analyze/paren.d.cts +23 -0
  9. package/dist/analyze/paren.d.ts +24 -0
  10. package/dist/analyze/paren.d.ts.map +1 -0
  11. package/dist/analyze/paren.js +168 -0
  12. package/dist/analyze/paren.mjs +113 -0
  13. package/dist/analyze/props-destructure.cjs +226 -1
  14. package/dist/analyze/props-destructure.d.cts +83 -0
  15. package/dist/analyze/props-destructure.mjs +205 -1
  16. package/dist/analyze/reactive-bindings.cjs +190 -1
  17. package/dist/analyze/reactive-bindings.d.cts +42 -0
  18. package/dist/analyze/reactive-bindings.mjs +167 -1
  19. package/dist/analyze/reactive-expr.cjs +38 -1
  20. package/dist/analyze/reactive-expr.d.cts +38 -0
  21. package/dist/analyze/reactive-expr.mjs +17 -1
  22. package/dist/analyze/static-graph.cjs +811 -1
  23. package/dist/analyze/static-graph.d.cts +102 -0
  24. package/dist/analyze/static-graph.mjs +793 -1
  25. package/dist/babel-NRW4EFTG.mjs +636 -0
  26. package/dist/chunk-3YKZ4GNH.mjs +11 -0
  27. package/dist/chunk-EZR7NZOY.mjs +1718 -0
  28. package/dist/chunk-FSSWUXUR.mjs +16 -0
  29. package/dist/chunk-MJV3UXIL.mjs +158 -0
  30. package/dist/chunk-R2VHAZAX.mjs +1078 -0
  31. package/dist/codegen/backend.cjs +18 -1
  32. package/dist/codegen/backend.d.cts +35 -0
  33. package/dist/codegen/backends/imperative.cjs +542 -1
  34. package/dist/codegen/backends/imperative.d.cts +11 -0
  35. package/dist/codegen/backends/imperative.d.ts.map +1 -1
  36. package/dist/codegen/backends/imperative.js +12 -8
  37. package/dist/codegen/backends/imperative.mjs +519 -1
  38. package/dist/codegen/contract.cjs +52 -1
  39. package/dist/codegen/contract.d.cts +24 -0
  40. package/dist/codegen/contract.mjs +31 -1
  41. package/dist/codegen/partial-template.cjs +176 -1
  42. package/dist/codegen/partial-template.d.cts +61 -0
  43. package/dist/codegen/partial-template.mjs +153 -1
  44. package/dist/codegen/serialize-static.cjs +125 -1
  45. package/dist/codegen/serialize-static.d.cts +38 -0
  46. package/dist/codegen/serialize-static.mjs +104 -1
  47. package/dist/frontend/babel/build-ir-lit.cjs +1509 -1
  48. package/dist/frontend/babel/build-ir-lit.d.cts +26 -0
  49. package/dist/frontend/babel/build-ir-lit.mjs +1478 -1
  50. package/dist/frontend/babel/build-ir.cjs +1524 -1
  51. package/dist/frontend/babel/build-ir.d.cts +35 -0
  52. package/dist/frontend/babel/build-ir.mjs +1495 -1
  53. package/dist/frontend/babel/index.cjs +2186 -1
  54. package/dist/frontend/babel/index.d.cts +33 -0
  55. package/dist/frontend/babel/index.mjs +2156 -1
  56. package/dist/frontend/babel/lower-template.cjs +1507 -1
  57. package/dist/frontend/babel/lower-template.d.cts +23 -0
  58. package/dist/frontend/babel/lower-template.mjs +1478 -1
  59. package/dist/frontend/babel/plugin.cjs +2132 -1
  60. package/dist/frontend/babel/plugin.d.cts +95 -0
  61. package/dist/frontend/babel/plugin.mjs +2103 -1
  62. package/dist/frontend/babel/server-functions.cjs +110 -1
  63. package/dist/frontend/babel/server-functions.d.cts +10 -0
  64. package/dist/frontend/babel/server-functions.mjs +89 -1
  65. package/dist/frontend/babel/types.cjs +18 -1
  66. package/dist/frontend/babel/types.d.cts +33 -0
  67. package/dist/frontend/types.cjs +18 -1
  68. package/dist/frontend/types.d.cts +25 -0
  69. package/dist/frontend/vocabulary.cjs +98 -0
  70. package/dist/frontend/vocabulary.d.cts +79 -0
  71. package/dist/frontend/vocabulary.d.ts +80 -0
  72. package/dist/frontend/vocabulary.d.ts.map +1 -0
  73. package/dist/frontend/vocabulary.js +124 -0
  74. package/dist/frontend/vocabulary.mjs +77 -0
  75. package/dist/index.cjs +1594 -13
  76. package/dist/index.d.cts +27 -0
  77. package/dist/index.mjs +1574 -13
  78. package/dist/integrations.cjs +4307 -25
  79. package/dist/integrations.d.cts +215 -0
  80. package/dist/integrations.mjs +531 -17
  81. package/dist/ir/nodes.cjs +18 -1
  82. package/dist/ir/nodes.d.cts +168 -0
  83. package/dist/lower/compile-template.cjs +1356 -1
  84. package/dist/lower/compile-template.d.cts +69 -0
  85. package/dist/lower/compile-template.mjs +1336 -1
  86. package/dist/lower/jsx.cjs +529 -1
  87. package/dist/lower/jsx.d.cts +25 -0
  88. package/dist/lower/jsx.d.ts.map +1 -1
  89. package/dist/lower/jsx.js +2 -1
  90. package/dist/lower/jsx.mjs +506 -1
  91. package/dist/lower/template.cjs +1061 -1
  92. package/dist/lower/template.d.cts +53 -0
  93. package/dist/lower/template.d.ts.map +1 -1
  94. package/dist/lower/template.js +5 -4
  95. package/dist/lower/template.mjs +1042 -1
  96. package/dist/lower/text.cjs +42 -1
  97. package/dist/lower/text.d.cts +10 -0
  98. package/dist/lower/text.mjs +21 -1
  99. package/dist/optimize/analyze-static.cjs +112 -1
  100. package/dist/optimize/analyze-static.d.cts +39 -0
  101. package/dist/optimize/analyze-static.mjs +91 -1
  102. package/dist/optimize/collapse-strategies.cjs +90 -1
  103. package/dist/optimize/collapse-strategies.d.cts +30 -0
  104. package/dist/optimize/collapse-strategies.mjs +67 -1
  105. package/dist/options.cjs +33 -1
  106. package/dist/options.d.cts +39 -0
  107. package/dist/options.mjs +12 -1
  108. package/dist/resolve/builtins.cjs +73 -1
  109. package/dist/resolve/builtins.d.cts +68 -0
  110. package/dist/resolve/builtins.mjs +53 -1
  111. package/dist/resolve/component-globals.cjs +233 -13
  112. package/dist/resolve/component-globals.d.cts +80 -0
  113. package/dist/resolve/component-globals.mjs +210 -13
  114. package/dist/resolve/component-resolver.cjs +80 -1
  115. package/dist/resolve/component-resolver.d.cts +68 -0
  116. package/dist/resolve/component-resolver.mjs +59 -1
  117. package/dist/resolve/load-directive.cjs +93 -1
  118. package/dist/resolve/load-directive.d.cts +53 -0
  119. package/dist/resolve/load-directive.mjs +72 -1
  120. package/dist/resolve/resolve-ir.cjs +108 -1
  121. package/dist/resolve/resolve-ir.d.cts +53 -0
  122. package/dist/resolve/resolve-ir.mjs +85 -1
  123. package/dist/resolve/write-globals.cjs +318 -13
  124. package/dist/resolve/write-globals.d.cts +30 -0
  125. package/dist/resolve/write-globals.mjs +297 -13
  126. package/dist/server-fns-4ZXN6DYU.mjs +78 -0
  127. package/dist/server-functions-V6D6DRIA.mjs +82 -0
  128. package/dist/transform/bindings.cjs +71 -1
  129. package/dist/transform/bindings.d.cts +16 -0
  130. package/dist/transform/bindings.mjs +50 -1
  131. package/dist/transform/index.cjs +2732 -8
  132. package/dist/transform/index.d.cts +15 -0
  133. package/dist/transform/index.mjs +3773 -17
  134. package/dist/transform/intrinsics.cjs +216 -3
  135. package/dist/transform/intrinsics.d.cts +21 -0
  136. package/dist/transform/intrinsics.mjs +193 -3
  137. package/dist/transform/props.cjs +441 -3
  138. package/dist/transform/props.d.cts +45 -0
  139. package/dist/transform/props.mjs +1482 -12
  140. package/dist/transform/server-fn-id.cjs +35 -1
  141. package/dist/transform/server-fn-id.d.cts +9 -0
  142. package/dist/transform/server-fn-id.mjs +14 -1
  143. package/dist/transform/server-fns.cjs +114 -2
  144. package/dist/transform/server-fns.d.cts +12 -0
  145. package/dist/transform/server-fns.mjs +1155 -11
  146. package/dist/transform/source-locations.cjs +330 -1
  147. package/dist/transform/source-locations.d.cts +43 -0
  148. package/dist/transform/source-locations.mjs +307 -1
  149. package/dist/transform/templates.cjs +2701 -7
  150. package/dist/transform/templates.d.cts +69 -0
  151. package/dist/transform/templates.mjs +3743 -16
  152. package/dist/transform-BT4MMASR.mjs +893 -0
  153. package/dist/tsconfig.lib.tsbuildinfo +1 -1
  154. package/package.json +6 -5
  155. package/dist/babel-VXKH6MRQ.mjs +0 -1
  156. package/dist/chunk-3SAEGOMQ.mjs +0 -1
  157. package/dist/chunk-5KMMN5QP.mjs +0 -1
  158. package/dist/chunk-IBRM4W7I.mjs +0 -10
  159. package/dist/chunk-OHHZCYIQ.mjs +0 -1
  160. package/dist/chunk-YKZ54NVE.mjs +0 -1
  161. package/dist/server-fns-6QM243HC.mjs +0 -2
  162. package/dist/server-functions-E3LKCZ4R.mjs +0 -1
  163. package/dist/transform-C4ZXRVGP.mjs +0 -8
@@ -1 +1,31 @@
1
- var e={version:1,module:"@fluixi/dom",symbols:["createNativeElement","insert","spread","setAttribute","delegateEvents","createComponent","createMemo","untrack","Show","For","Index","Switch","Match","Dynamic","ErrorBoundary"]},t={version:2,module:"@fluixi/dom",symbols:[...e.symbols,"template","cloneTemplate","walk"]};export{e as RUNTIME_CONTRACT_V1,t as RUNTIME_CONTRACT_V2};
1
+ // src/codegen/contract.ts
2
+ var RUNTIME_CONTRACT_V1 = {
3
+ version: 1,
4
+ module: "@fluixi/dom",
5
+ symbols: [
6
+ "createNativeElement",
7
+ "insert",
8
+ "spread",
9
+ "setAttribute",
10
+ "delegateEvents",
11
+ "createComponent",
12
+ "createMemo",
13
+ "untrack",
14
+ "Show",
15
+ "For",
16
+ "Index",
17
+ "Switch",
18
+ "Match",
19
+ "Dynamic",
20
+ "ErrorBoundary"
21
+ ]
22
+ };
23
+ var RUNTIME_CONTRACT_V2 = {
24
+ version: 2,
25
+ module: "@fluixi/dom",
26
+ symbols: [...RUNTIME_CONTRACT_V1.symbols, "template", "cloneTemplate", "walk"]
27
+ };
28
+ export {
29
+ RUNTIME_CONTRACT_V1,
30
+ RUNTIME_CONTRACT_V2
31
+ };
@@ -1 +1,176 @@
1
- "use strict";var p=Object.defineProperty;var v=Object.getOwnPropertyDescriptor;var w=Object.getOwnPropertyNames;var L=Object.prototype.hasOwnProperty;var H=(e,t)=>{for(var n in t)p(e,n,{get:t[n],enumerable:!0})},_=(e,t,n,a)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of w(t))!L.call(e,r)&&r!==n&&p(e,r,{get:()=>t[r],enumerable:!(a=v(t,r))||a.enumerable});return e};var z=e=>_(p({},"__esModule",{value:!0}),e);var B={};H(B,{HOLE_END:()=>N,HOLE_START:()=>T,planPartialTemplate:()=>Y});module.exports=z(B);var A=new Set(["area","base","br","col","embed","hr","img","input","link","meta","param","source","track","wbr"]),M={className:"class",htmlFor:"for"},y=new Set(["innerHTML","outerHTML","innerText","textContent","value","checked","selected","muted","defaultValue","defaultChecked","children","ref"]),C=new Set(["script","style","textarea","title"]);function I(e){return C.has(e)}function k(e){return e.kind!=="attr"||e.expr!==void 0||e.name.includes(":")?!1:!y.has(e.name)}function m(e){let t=e.props.map(O).filter(Boolean).join(""),n=`<${e.tag}${t}>`;return A.has(e.tag)?n:`${n}${e.children.map(j).join("")}</${e.tag}>`}function j(e){if(e.kind==="text")return D(e.value);if(e.kind!=="element")throw new Error(`serializeStatic: unexpected ${e.kind}`);return m(e)}function O(e){let t=M[e.name]??e.name,n=e.literal;return n===!0||n===void 0?` ${t}`:n===!1||n===null?"":` ${t}="${W(String(n))}"`}function W(e){return e.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function D(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}var T="<!--fx-->",N="<!--fx/-->";function c(e){return e.kind==="expr"||e.kind==="component"||e.kind==="control"}function V(e){return e.kind==="text"||e.kind==="element"&&b(e)}function b(e){return e.svg||I(e.tag)||!e.props.every(t=>k(t))?!1:e.children.every(t=>V(t)||c(t))}function u(e){if(c(e))return!0;let t=e.children;return t?t.some(u):!1}function S(e){for(let t=0;t<e.children.length;t++){let n=e.children[t];if(n.kind==="text"&&(n.value===""||e.children[t+1]?.kind==="text"))return!1}return e.children.every(t=>t.kind!=="element"||S(t))}function Y(e){if(!b(e)||!S(e)||!e.children.some(u))return null;let t=[],n=[],a=0,r=o=>{let l=`_n$${a++}`;return t.push({ref:l,expr:o}),l};return d(e,"_el$"),{html:q(e),tag:e.tag,steps:t,holes:n};function d(o,l){let g=-1;o.children.forEach((s,i)=>{u(s)&&(g=i)});let f=null;for(let s=0;s<=g;s++){let i=o.children[s],h=f?`${f}.nextSibling`:`${l}.firstChild`;if(c(i)){let x=r(h),E=r(`holeEnd(${x})`);n.push({parentRef:l,startRef:x,endRef:E,node:i}),f=E;continue}let R=r(h);i.kind==="element"&&u(i)&&d(i,R),f=R}}}function q(e){return m($(e)).split(P).join(T+N)}function $(e){return{...e,children:e.children.map(t=>c(t)?{kind:"text",value:P}:t.kind==="element"?$(t):t)}}var P="\0fx-hole\0";
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/codegen/partial-template.ts
21
+ var partial_template_exports = {};
22
+ __export(partial_template_exports, {
23
+ HOLE_END: () => HOLE_END,
24
+ HOLE_START: () => HOLE_START,
25
+ planPartialTemplate: () => planPartialTemplate
26
+ });
27
+ module.exports = __toCommonJS(partial_template_exports);
28
+
29
+ // src/codegen/serialize-static.ts
30
+ var VOID_ELEMENTS = /* @__PURE__ */ new Set([
31
+ "area",
32
+ "base",
33
+ "br",
34
+ "col",
35
+ "embed",
36
+ "hr",
37
+ "img",
38
+ "input",
39
+ "link",
40
+ "meta",
41
+ "param",
42
+ "source",
43
+ "track",
44
+ "wbr"
45
+ ]);
46
+ var HTML_NAME = {
47
+ className: "class",
48
+ htmlFor: "for"
49
+ };
50
+ var PROPERTY_ONLY = /* @__PURE__ */ new Set([
51
+ "innerHTML",
52
+ "outerHTML",
53
+ "innerText",
54
+ "textContent",
55
+ "value",
56
+ "checked",
57
+ "selected",
58
+ "muted",
59
+ "defaultValue",
60
+ "defaultChecked",
61
+ "children",
62
+ "ref"
63
+ ]);
64
+ var RAW_TEXT_ELEMENTS = /* @__PURE__ */ new Set(["script", "style", "textarea", "title"]);
65
+ function isRawTextElement(tag) {
66
+ return RAW_TEXT_ELEMENTS.has(tag);
67
+ }
68
+ function isPlainLiteralAttr(prop) {
69
+ if (prop.kind !== "attr") return false;
70
+ if (prop.expr !== void 0) return false;
71
+ if (prop.name.includes(":")) return false;
72
+ return !PROPERTY_ONLY.has(prop.name);
73
+ }
74
+ function serializeStatic(node) {
75
+ const attrs = node.props.map(serializeProp).filter(Boolean).join("");
76
+ const open = `<${node.tag}${attrs}>`;
77
+ if (VOID_ELEMENTS.has(node.tag)) return open;
78
+ return `${open}${node.children.map(serializeChild).join("")}</${node.tag}>`;
79
+ }
80
+ function serializeChild(child) {
81
+ if (child.kind === "text") return escapeText(child.value);
82
+ if (child.kind !== "element") throw new Error(`serializeStatic: unexpected ${child.kind}`);
83
+ return serializeStatic(child);
84
+ }
85
+ function serializeProp(prop) {
86
+ const name = HTML_NAME[prop.name] ?? prop.name;
87
+ const value = prop.literal;
88
+ if (value === true || value === void 0) return ` ${name}`;
89
+ if (value === false || value === null) return "";
90
+ return ` ${name}="${escapeAttr(String(value))}"`;
91
+ }
92
+ function escapeAttr(value) {
93
+ return value.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
94
+ }
95
+ function escapeText(value) {
96
+ return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
97
+ }
98
+
99
+ // src/codegen/partial-template.ts
100
+ var HOLE_START = "<!--fx-->";
101
+ var HOLE_END = "<!--fx/-->";
102
+ function isHole(node) {
103
+ return node.kind === "expr" || node.kind === "component" || node.kind === "control";
104
+ }
105
+ function isTemplateChild(node) {
106
+ return node.kind === "text" || node.kind === "element" && isTemplateElement(node);
107
+ }
108
+ function isTemplateElement(node) {
109
+ if (node.svg) return false;
110
+ if (isRawTextElement(node.tag)) return false;
111
+ if (!node.props.every((p) => isPlainLiteralAttr(p))) return false;
112
+ return node.children.every((c) => isTemplateChild(c) || isHole(c));
113
+ }
114
+ function containsHole(node) {
115
+ if (isHole(node)) return true;
116
+ const children = node.children;
117
+ return children ? children.some(containsHole) : false;
118
+ }
119
+ function addressable(el) {
120
+ for (let i = 0; i < el.children.length; i++) {
121
+ const child = el.children[i];
122
+ if (child.kind === "text") {
123
+ if (child.value === "") return false;
124
+ if (el.children[i + 1]?.kind === "text") return false;
125
+ }
126
+ }
127
+ return el.children.every((c) => c.kind !== "element" || addressable(c));
128
+ }
129
+ function planPartialTemplate(root) {
130
+ if (!isTemplateElement(root)) return null;
131
+ if (!addressable(root)) return null;
132
+ if (!root.children.some(containsHole)) return null;
133
+ const steps = [];
134
+ const holes = [];
135
+ let refCount = 0;
136
+ const declare = (expr) => {
137
+ const ref = `_n$${refCount++}`;
138
+ steps.push({ ref, expr });
139
+ return ref;
140
+ };
141
+ walk(root, "_el$");
142
+ return { html: serializeWithMarkers(root), tag: root.tag, steps, holes };
143
+ function walk(el, elementRef) {
144
+ let last = -1;
145
+ el.children.forEach((child, i) => {
146
+ if (containsHole(child)) last = i;
147
+ });
148
+ let previous = null;
149
+ for (let i = 0; i <= last; i++) {
150
+ const child = el.children[i];
151
+ const expr = previous ? `${previous}.nextSibling` : `${elementRef}.firstChild`;
152
+ if (isHole(child)) {
153
+ const startRef = declare(expr);
154
+ const endRef = declare(`holeEnd(${startRef})`);
155
+ holes.push({ parentRef: elementRef, startRef, endRef, node: child });
156
+ previous = endRef;
157
+ continue;
158
+ }
159
+ const ref = declare(expr);
160
+ if (child.kind === "element" && containsHole(child)) walk(child, ref);
161
+ previous = ref;
162
+ }
163
+ }
164
+ }
165
+ function serializeWithMarkers(el) {
166
+ return serializeStatic(withSentinels(el)).split(SENTINEL).join(HOLE_START + HOLE_END);
167
+ }
168
+ function withSentinels(el) {
169
+ return {
170
+ ...el,
171
+ children: el.children.map(
172
+ (child) => isHole(child) ? { kind: "text", value: SENTINEL } : child.kind === "element" ? withSentinels(child) : child
173
+ )
174
+ };
175
+ }
176
+ var SENTINEL = "\0fx-hole\0";
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Cloning a subtree whose *structure* is static but which contains dynamic holes.
3
+ *
4
+ * The fully-static case is easy: serialize, clone, done. The common case is not static —
5
+ * a card wrapper with one reactive value inside — and a single hole used to send the
6
+ * whole subtree back to being built an element at a time. This plans the middle ground:
7
+ * the structure becomes one template, and each hole is filled through a reference into
8
+ * the cloned tree.
9
+ *
10
+ * Three things make it correct in all three environments — fresh client render, server
11
+ * render, and hydration:
12
+ *
13
+ * - **Each hole is bracketed by a marker pair.** A hole's content is then, by
14
+ * definition, the nodes between its own two markers. That is what lets hydration
15
+ * *adopt* what the server rendered rather than rebuild it, with no dependence on where
16
+ * a hydration cursor happens to be.
17
+ * - **The walk is sequential, not positional.** Index arithmetic against the template
18
+ * only describes a fresh clone: the server's DOM has the rendered content sitting
19
+ * between the markers, so every position after a hole is shifted. Each node is reached
20
+ * from the previous sibling instead, and a hole's end marker is found at runtime.
21
+ * - **Every reference is read before any insertion**, since inserting shifts what
22
+ * follows.
23
+ */
24
+ import type { IRElement, IRNode } from '../ir/nodes.cjs';
25
+ /**
26
+ * The comments bracketing a hole.
27
+ *
28
+ * Named rather than anonymous so they are recognisable in devtools and in a page's
29
+ * source — an unexplained `<!---->` is a support question.
30
+ */
31
+ export declare const HOLE_START = "<!--fx-->";
32
+ export declare const HOLE_END = "<!--fx/-->";
33
+ /** `const <ref> = <expr>;`, emitted before any insertion happens. */
34
+ export interface WalkStep {
35
+ ref: string;
36
+ expr: string;
37
+ }
38
+ /** A dynamic child, and the markers its content lives between. */
39
+ export interface TemplateHole {
40
+ /** Reference to the hole's parent element. */
41
+ parentRef: string;
42
+ /** Reference to the opening marker. */
43
+ startRef: string;
44
+ /** Reference to the closing marker, resolved at runtime by scanning from the start. */
45
+ endRef: string;
46
+ node: IRNode;
47
+ }
48
+ export interface PartialTemplate {
49
+ html: string;
50
+ tag: string;
51
+ /** Declarations to emit in order, before the inserts. */
52
+ steps: WalkStep[];
53
+ holes: TemplateHole[];
54
+ }
55
+ /**
56
+ * Plan a partial template for `root`, or null when it does not qualify.
57
+ *
58
+ * Returns null for a subtree with no holes: that is the fully-static case, which has a
59
+ * cheaper path of its own and must not be routed through this one.
60
+ */
61
+ export declare function planPartialTemplate(root: IRElement): PartialTemplate | null;
@@ -1 +1,153 @@
1
- var S=new Set(["area","base","br","col","embed","hr","img","input","link","meta","param","source","track","wbr"]),$={className:"class",htmlFor:"for"},P=new Set(["innerHTML","outerHTML","innerText","textContent","value","checked","selected","muted","defaultValue","defaultChecked","children","ref"]),v=new Set(["script","style","textarea","title"]);function x(e){return v.has(e)}function E(e){return e.kind!=="attr"||e.expr!==void 0||e.name.includes(":")?!1:!P.has(e.name)}function c(e){let t=e.props.map(L).filter(Boolean).join(""),n=`<${e.tag}${t}>`;return S.has(e.tag)?n:`${n}${e.children.map(w).join("")}</${e.tag}>`}function w(e){if(e.kind==="text")return _(e.value);if(e.kind!=="element")throw new Error(`serializeStatic: unexpected ${e.kind}`);return c(e)}function L(e){let t=$[e.name]??e.name,n=e.literal;return n===!0||n===void 0?` ${t}`:n===!1||n===null?"":` ${t}="${H(String(n))}"`}function H(e){return e.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function _(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}var z="<!--fx-->",A="<!--fx/-->";function f(e){return e.kind==="expr"||e.kind==="component"||e.kind==="control"}function M(e){return e.kind==="text"||e.kind==="element"&&I(e)}function I(e){return e.svg||x(e.tag)||!e.props.every(t=>E(t))?!1:e.children.every(t=>M(t)||f(t))}function o(e){if(f(e))return!0;let t=e.children;return t?t.some(o):!1}function k(e){for(let t=0;t<e.children.length;t++){let n=e.children[t];if(n.kind==="text"&&(n.value===""||e.children[t+1]?.kind==="text"))return!1}return e.children.every(t=>t.kind!=="element"||k(t))}function O(e){if(!I(e)||!k(e)||!e.children.some(o))return null;let t=[],n=[],b=0,u=s=>{let i=`_n$${b++}`;return t.push({ref:i,expr:s}),i};return p(e,"_el$"),{html:y(e),tag:e.tag,steps:t,holes:n};function p(s,i){let m=-1;s.children.forEach((l,r)=>{o(l)&&(m=r)});let a=null;for(let l=0;l<=m;l++){let r=s.children[l],d=a?`${a}.nextSibling`:`${i}.firstChild`;if(f(r)){let h=u(d),R=u(`holeEnd(${h})`);n.push({parentRef:i,startRef:h,endRef:R,node:r}),a=R;continue}let g=u(d);r.kind==="element"&&o(r)&&p(r,g),a=g}}}function y(e){return c(T(e)).split(N).join(z+A)}function T(e){return{...e,children:e.children.map(t=>f(t)?{kind:"text",value:N}:t.kind==="element"?T(t):t)}}var N="\0fx-hole\0";export{A as HOLE_END,z as HOLE_START,O as planPartialTemplate};
1
+ // src/codegen/serialize-static.ts
2
+ var VOID_ELEMENTS = /* @__PURE__ */ new Set([
3
+ "area",
4
+ "base",
5
+ "br",
6
+ "col",
7
+ "embed",
8
+ "hr",
9
+ "img",
10
+ "input",
11
+ "link",
12
+ "meta",
13
+ "param",
14
+ "source",
15
+ "track",
16
+ "wbr"
17
+ ]);
18
+ var HTML_NAME = {
19
+ className: "class",
20
+ htmlFor: "for"
21
+ };
22
+ var PROPERTY_ONLY = /* @__PURE__ */ new Set([
23
+ "innerHTML",
24
+ "outerHTML",
25
+ "innerText",
26
+ "textContent",
27
+ "value",
28
+ "checked",
29
+ "selected",
30
+ "muted",
31
+ "defaultValue",
32
+ "defaultChecked",
33
+ "children",
34
+ "ref"
35
+ ]);
36
+ var RAW_TEXT_ELEMENTS = /* @__PURE__ */ new Set(["script", "style", "textarea", "title"]);
37
+ function isRawTextElement(tag) {
38
+ return RAW_TEXT_ELEMENTS.has(tag);
39
+ }
40
+ function isPlainLiteralAttr(prop) {
41
+ if (prop.kind !== "attr") return false;
42
+ if (prop.expr !== void 0) return false;
43
+ if (prop.name.includes(":")) return false;
44
+ return !PROPERTY_ONLY.has(prop.name);
45
+ }
46
+ function serializeStatic(node) {
47
+ const attrs = node.props.map(serializeProp).filter(Boolean).join("");
48
+ const open = `<${node.tag}${attrs}>`;
49
+ if (VOID_ELEMENTS.has(node.tag)) return open;
50
+ return `${open}${node.children.map(serializeChild).join("")}</${node.tag}>`;
51
+ }
52
+ function serializeChild(child) {
53
+ if (child.kind === "text") return escapeText(child.value);
54
+ if (child.kind !== "element") throw new Error(`serializeStatic: unexpected ${child.kind}`);
55
+ return serializeStatic(child);
56
+ }
57
+ function serializeProp(prop) {
58
+ const name = HTML_NAME[prop.name] ?? prop.name;
59
+ const value = prop.literal;
60
+ if (value === true || value === void 0) return ` ${name}`;
61
+ if (value === false || value === null) return "";
62
+ return ` ${name}="${escapeAttr(String(value))}"`;
63
+ }
64
+ function escapeAttr(value) {
65
+ return value.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
66
+ }
67
+ function escapeText(value) {
68
+ return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
69
+ }
70
+
71
+ // src/codegen/partial-template.ts
72
+ var HOLE_START = "<!--fx-->";
73
+ var HOLE_END = "<!--fx/-->";
74
+ function isHole(node) {
75
+ return node.kind === "expr" || node.kind === "component" || node.kind === "control";
76
+ }
77
+ function isTemplateChild(node) {
78
+ return node.kind === "text" || node.kind === "element" && isTemplateElement(node);
79
+ }
80
+ function isTemplateElement(node) {
81
+ if (node.svg) return false;
82
+ if (isRawTextElement(node.tag)) return false;
83
+ if (!node.props.every((p) => isPlainLiteralAttr(p))) return false;
84
+ return node.children.every((c) => isTemplateChild(c) || isHole(c));
85
+ }
86
+ function containsHole(node) {
87
+ if (isHole(node)) return true;
88
+ const children = node.children;
89
+ return children ? children.some(containsHole) : false;
90
+ }
91
+ function addressable(el) {
92
+ for (let i = 0; i < el.children.length; i++) {
93
+ const child = el.children[i];
94
+ if (child.kind === "text") {
95
+ if (child.value === "") return false;
96
+ if (el.children[i + 1]?.kind === "text") return false;
97
+ }
98
+ }
99
+ return el.children.every((c) => c.kind !== "element" || addressable(c));
100
+ }
101
+ function planPartialTemplate(root) {
102
+ if (!isTemplateElement(root)) return null;
103
+ if (!addressable(root)) return null;
104
+ if (!root.children.some(containsHole)) return null;
105
+ const steps = [];
106
+ const holes = [];
107
+ let refCount = 0;
108
+ const declare = (expr) => {
109
+ const ref = `_n$${refCount++}`;
110
+ steps.push({ ref, expr });
111
+ return ref;
112
+ };
113
+ walk(root, "_el$");
114
+ return { html: serializeWithMarkers(root), tag: root.tag, steps, holes };
115
+ function walk(el, elementRef) {
116
+ let last = -1;
117
+ el.children.forEach((child, i) => {
118
+ if (containsHole(child)) last = i;
119
+ });
120
+ let previous = null;
121
+ for (let i = 0; i <= last; i++) {
122
+ const child = el.children[i];
123
+ const expr = previous ? `${previous}.nextSibling` : `${elementRef}.firstChild`;
124
+ if (isHole(child)) {
125
+ const startRef = declare(expr);
126
+ const endRef = declare(`holeEnd(${startRef})`);
127
+ holes.push({ parentRef: elementRef, startRef, endRef, node: child });
128
+ previous = endRef;
129
+ continue;
130
+ }
131
+ const ref = declare(expr);
132
+ if (child.kind === "element" && containsHole(child)) walk(child, ref);
133
+ previous = ref;
134
+ }
135
+ }
136
+ }
137
+ function serializeWithMarkers(el) {
138
+ return serializeStatic(withSentinels(el)).split(SENTINEL).join(HOLE_START + HOLE_END);
139
+ }
140
+ function withSentinels(el) {
141
+ return {
142
+ ...el,
143
+ children: el.children.map(
144
+ (child) => isHole(child) ? { kind: "text", value: SENTINEL } : child.kind === "element" ? withSentinels(child) : child
145
+ )
146
+ };
147
+ }
148
+ var SENTINEL = "\0fx-hole\0";
149
+ export {
150
+ HOLE_END,
151
+ HOLE_START,
152
+ planPartialTemplate
153
+ };
@@ -1 +1,125 @@
1
- "use strict";var a=Object.defineProperty;var m=Object.getOwnPropertyDescriptor;var p=Object.getOwnPropertyNames;var g=Object.prototype.hasOwnProperty;var d=(e,t)=>{for(var n in t)a(e,n,{get:t[n],enumerable:!0})},E=(e,t,n,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of p(t))!g.call(e,r)&&r!==n&&a(e,r,{get:()=>t[r],enumerable:!(i=m(t,r))||i.enumerable});return e};var x=e=>E(a({},"__esModule",{value:!0}),e);var N={};d(N,{htmlAttrName:()=>I,isPlainLiteralAttr:()=>u,isRawTextElement:()=>o,isSerializable:()=>c,serializeStatic:()=>f,templatePositions:()=>w});module.exports=x(N);var R=new Set(["area","base","br","col","embed","hr","img","input","link","meta","param","source","track","wbr"]),l={className:"class",htmlFor:"for"},h=new Set(["innerHTML","outerHTML","innerText","textContent","value","checked","selected","muted","defaultValue","defaultChecked","children","ref"]),k=new Set(["script","style","textarea","title"]);function o(e){return k.has(e)}function I(e){return l[e]??e}function u(e){return e.kind!=="attr"||e.expr!==void 0||e.name.includes(":")?!1:!h.has(e.name)}function c(e){if(!e.static||o(e.tag))return!1;for(let t of e.props)if(!u(t))return!1;for(let t of e.children)if(t.kind!=="text"&&!(t.kind==="element"&&c(t)))return!1;return!0}function f(e){let t=e.props.map(b).filter(Boolean).join(""),n=`<${e.tag}${t}>`;return R.has(e.tag)?n:`${n}${e.children.map(T).join("")}</${e.tag}>`}function T(e){if(e.kind==="text")return $(e.value);if(e.kind!=="element")throw new Error(`serializeStatic: unexpected ${e.kind}`);return f(e)}function b(e){let t=l[e.name]??e.name,n=e.literal;return n===!0||n===void 0?` ${t}`:n===!1||n===null?"":` ${t}="${S(String(n))}"`}function S(e){return e.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function $(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function w(e){let t=[],n,i=r=>{n??=r.at?.file,t.push(r.at?.line??0,r.at?.column??0);for(let s of r.children)s.kind==="element"&&i(s)};return i(e),n&&t.some(r=>r!==0)?{file:n,pos:t}:void 0}
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/codegen/serialize-static.ts
21
+ var serialize_static_exports = {};
22
+ __export(serialize_static_exports, {
23
+ htmlAttrName: () => htmlAttrName,
24
+ isPlainLiteralAttr: () => isPlainLiteralAttr,
25
+ isRawTextElement: () => isRawTextElement,
26
+ isSerializable: () => isSerializable,
27
+ serializeStatic: () => serializeStatic,
28
+ templatePositions: () => templatePositions
29
+ });
30
+ module.exports = __toCommonJS(serialize_static_exports);
31
+ var VOID_ELEMENTS = /* @__PURE__ */ new Set([
32
+ "area",
33
+ "base",
34
+ "br",
35
+ "col",
36
+ "embed",
37
+ "hr",
38
+ "img",
39
+ "input",
40
+ "link",
41
+ "meta",
42
+ "param",
43
+ "source",
44
+ "track",
45
+ "wbr"
46
+ ]);
47
+ var HTML_NAME = {
48
+ className: "class",
49
+ htmlFor: "for"
50
+ };
51
+ var PROPERTY_ONLY = /* @__PURE__ */ new Set([
52
+ "innerHTML",
53
+ "outerHTML",
54
+ "innerText",
55
+ "textContent",
56
+ "value",
57
+ "checked",
58
+ "selected",
59
+ "muted",
60
+ "defaultValue",
61
+ "defaultChecked",
62
+ "children",
63
+ "ref"
64
+ ]);
65
+ var RAW_TEXT_ELEMENTS = /* @__PURE__ */ new Set(["script", "style", "textarea", "title"]);
66
+ function isRawTextElement(tag) {
67
+ return RAW_TEXT_ELEMENTS.has(tag);
68
+ }
69
+ function htmlAttrName(name) {
70
+ return HTML_NAME[name] ?? name;
71
+ }
72
+ function isPlainLiteralAttr(prop) {
73
+ if (prop.kind !== "attr") return false;
74
+ if (prop.expr !== void 0) return false;
75
+ if (prop.name.includes(":")) return false;
76
+ return !PROPERTY_ONLY.has(prop.name);
77
+ }
78
+ function isSerializable(node) {
79
+ if (!node.static) return false;
80
+ if (isRawTextElement(node.tag)) return false;
81
+ for (const prop of node.props) {
82
+ if (!isPlainLiteralAttr(prop)) return false;
83
+ }
84
+ for (const child of node.children) {
85
+ if (child.kind === "text") continue;
86
+ if (child.kind === "element" && isSerializable(child)) continue;
87
+ return false;
88
+ }
89
+ return true;
90
+ }
91
+ function serializeStatic(node) {
92
+ const attrs = node.props.map(serializeProp).filter(Boolean).join("");
93
+ const open = `<${node.tag}${attrs}>`;
94
+ if (VOID_ELEMENTS.has(node.tag)) return open;
95
+ return `${open}${node.children.map(serializeChild).join("")}</${node.tag}>`;
96
+ }
97
+ function serializeChild(child) {
98
+ if (child.kind === "text") return escapeText(child.value);
99
+ if (child.kind !== "element") throw new Error(`serializeStatic: unexpected ${child.kind}`);
100
+ return serializeStatic(child);
101
+ }
102
+ function serializeProp(prop) {
103
+ const name = HTML_NAME[prop.name] ?? prop.name;
104
+ const value = prop.literal;
105
+ if (value === true || value === void 0) return ` ${name}`;
106
+ if (value === false || value === null) return "";
107
+ return ` ${name}="${escapeAttr(String(value))}"`;
108
+ }
109
+ function escapeAttr(value) {
110
+ return value.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
111
+ }
112
+ function escapeText(value) {
113
+ return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
114
+ }
115
+ function templatePositions(root) {
116
+ const pos = [];
117
+ let file;
118
+ const walk = (el) => {
119
+ file ??= el.at?.file;
120
+ pos.push(el.at?.line ?? 0, el.at?.column ?? 0);
121
+ for (const child of el.children) if (child.kind === "element") walk(child);
122
+ };
123
+ walk(root);
124
+ return file && pos.some((n) => n !== 0) ? { file, pos } : void 0;
125
+ }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Serialize a static IR subtree to the HTML a `<template>` can be built from.
3
+ *
4
+ * Only called for nodes `analyzeStatic` marked static, so every prop is a literal and
5
+ * every child is text or another static element — there is nothing here that could need
6
+ * an expression. That invariant is what makes this safe: the serializer never has to
7
+ * guess, and anything it cannot represent is a bug in the analysis, not a fallback.
8
+ */
9
+ import type { IRElement, IRProp } from '../ir/nodes.cjs';
10
+ /** True when this element's content must not be entity-escaped. */
11
+ export declare function isRawTextElement(tag: string): boolean;
12
+ /** The HTML spelling of an IR prop name. */
13
+ export declare function htmlAttrName(name: string): string;
14
+ /**
15
+ * True for a prop that is a plain HTML attribute with a compile-time constant value —
16
+ * safe to write straight onto the element, with no runtime interpretation.
17
+ */
18
+ export declare function isPlainLiteralAttr(prop: IRProp): boolean;
19
+ /** True when the subtree can be represented as HTML text with no loss. */
20
+ export declare function isSerializable(node: IRElement): boolean;
21
+ /** The subtree as HTML. */
22
+ export declare function serializeStatic(node: IRElement): string;
23
+ /**
24
+ * Where each element of a template was written, in the order a clone walks them.
25
+ *
26
+ * A template is emitted as one string, so a source map traces everything in it back to the
27
+ * line the root opens at — every element in a component reports the same place. The order
28
+ * is pre-order over the elements the template contains, which is what
29
+ * `[root, ...root.querySelectorAll('*')]` gives back on the clone, since holes are filled
30
+ * only after it is built.
31
+ *
32
+ * Undefined when the transform was not asked for source locations, so a production build
33
+ * emits nothing and pays nothing.
34
+ */
35
+ export declare function templatePositions(root: IRElement): {
36
+ file: string;
37
+ pos: number[];
38
+ } | undefined;