@fluixi/compiler 1.0.0-alpha.82 → 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 (188) 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 -0
  23. package/dist/analyze/static-graph.d.cts +102 -0
  24. package/dist/analyze/static-graph.d.ts +103 -0
  25. package/dist/analyze/static-graph.d.ts.map +1 -0
  26. package/dist/analyze/static-graph.js +869 -0
  27. package/dist/analyze/static-graph.mjs +793 -0
  28. package/dist/babel-NRW4EFTG.mjs +636 -0
  29. package/dist/chunk-3YKZ4GNH.mjs +11 -0
  30. package/dist/chunk-EZR7NZOY.mjs +1718 -0
  31. package/dist/chunk-FSSWUXUR.mjs +16 -0
  32. package/dist/chunk-MJV3UXIL.mjs +158 -0
  33. package/dist/chunk-R2VHAZAX.mjs +1078 -0
  34. package/dist/codegen/backend.cjs +18 -1
  35. package/dist/codegen/backend.d.cts +35 -0
  36. package/dist/codegen/backends/imperative.cjs +542 -1
  37. package/dist/codegen/backends/imperative.d.cts +11 -0
  38. package/dist/codegen/backends/imperative.d.ts.map +1 -1
  39. package/dist/codegen/backends/imperative.js +68 -13
  40. package/dist/codegen/backends/imperative.mjs +519 -1
  41. package/dist/codegen/contract.cjs +52 -1
  42. package/dist/codegen/contract.d.cts +24 -0
  43. package/dist/codegen/contract.mjs +31 -1
  44. package/dist/codegen/partial-template.cjs +176 -1
  45. package/dist/codegen/partial-template.d.cts +61 -0
  46. package/dist/codegen/partial-template.mjs +153 -1
  47. package/dist/codegen/serialize-static.cjs +125 -1
  48. package/dist/codegen/serialize-static.d.cts +38 -0
  49. package/dist/codegen/serialize-static.d.ts +16 -0
  50. package/dist/codegen/serialize-static.d.ts.map +1 -1
  51. package/dist/codegen/serialize-static.js +25 -0
  52. package/dist/codegen/serialize-static.mjs +104 -1
  53. package/dist/frontend/babel/build-ir-lit.cjs +1509 -1
  54. package/dist/frontend/babel/build-ir-lit.d.cts +26 -0
  55. package/dist/frontend/babel/build-ir-lit.mjs +1478 -1
  56. package/dist/frontend/babel/build-ir.cjs +1524 -1
  57. package/dist/frontend/babel/build-ir.d.cts +35 -0
  58. package/dist/frontend/babel/build-ir.mjs +1495 -1
  59. package/dist/frontend/babel/index.cjs +2186 -1
  60. package/dist/frontend/babel/index.d.cts +33 -0
  61. package/dist/frontend/babel/index.mjs +2156 -1
  62. package/dist/frontend/babel/lower-template.cjs +1507 -1
  63. package/dist/frontend/babel/lower-template.d.cts +23 -0
  64. package/dist/frontend/babel/lower-template.mjs +1478 -1
  65. package/dist/frontend/babel/plugin.cjs +2132 -1
  66. package/dist/frontend/babel/plugin.d.cts +95 -0
  67. package/dist/frontend/babel/plugin.mjs +2103 -1
  68. package/dist/frontend/babel/server-functions.cjs +110 -1
  69. package/dist/frontend/babel/server-functions.d.cts +10 -0
  70. package/dist/frontend/babel/server-functions.mjs +89 -1
  71. package/dist/frontend/babel/types.cjs +18 -1
  72. package/dist/frontend/babel/types.d.cts +33 -0
  73. package/dist/frontend/types.cjs +18 -1
  74. package/dist/frontend/types.d.cts +25 -0
  75. package/dist/frontend/vocabulary.cjs +98 -0
  76. package/dist/frontend/vocabulary.d.cts +79 -0
  77. package/dist/frontend/vocabulary.d.ts +80 -0
  78. package/dist/frontend/vocabulary.d.ts.map +1 -0
  79. package/dist/frontend/vocabulary.js +124 -0
  80. package/dist/frontend/vocabulary.mjs +77 -0
  81. package/dist/index.cjs +1594 -13
  82. package/dist/index.d.cts +27 -0
  83. package/dist/index.d.ts.map +1 -1
  84. package/dist/index.js +3 -0
  85. package/dist/index.mjs +1574 -13
  86. package/dist/integrations.cjs +4307 -25
  87. package/dist/integrations.d.cts +215 -0
  88. package/dist/integrations.d.ts +16 -0
  89. package/dist/integrations.d.ts.map +1 -1
  90. package/dist/integrations.js +21 -2
  91. package/dist/integrations.mjs +531 -17
  92. package/dist/ir/nodes.cjs +18 -1
  93. package/dist/ir/nodes.d.cts +168 -0
  94. package/dist/ir/nodes.d.ts +46 -0
  95. package/dist/ir/nodes.d.ts.map +1 -1
  96. package/dist/lower/compile-template.cjs +1356 -1
  97. package/dist/lower/compile-template.d.cts +69 -0
  98. package/dist/lower/compile-template.d.ts +12 -0
  99. package/dist/lower/compile-template.d.ts.map +1 -1
  100. package/dist/lower/compile-template.js +5 -1
  101. package/dist/lower/compile-template.mjs +1336 -1
  102. package/dist/lower/jsx.cjs +529 -1
  103. package/dist/lower/jsx.d.cts +25 -0
  104. package/dist/lower/jsx.d.ts +2 -0
  105. package/dist/lower/jsx.d.ts.map +1 -1
  106. package/dist/lower/jsx.js +27 -4
  107. package/dist/lower/jsx.mjs +506 -1
  108. package/dist/lower/template.cjs +1061 -1
  109. package/dist/lower/template.d.cts +53 -0
  110. package/dist/lower/template.d.ts +14 -1
  111. package/dist/lower/template.d.ts.map +1 -1
  112. package/dist/lower/template.js +106 -19
  113. package/dist/lower/template.mjs +1042 -1
  114. package/dist/lower/text.cjs +42 -1
  115. package/dist/lower/text.d.cts +10 -0
  116. package/dist/lower/text.mjs +21 -1
  117. package/dist/optimize/analyze-static.cjs +112 -1
  118. package/dist/optimize/analyze-static.d.cts +39 -0
  119. package/dist/optimize/analyze-static.mjs +91 -1
  120. package/dist/optimize/collapse-strategies.cjs +90 -1
  121. package/dist/optimize/collapse-strategies.d.cts +30 -0
  122. package/dist/optimize/collapse-strategies.mjs +67 -1
  123. package/dist/options.cjs +33 -1
  124. package/dist/options.d.cts +39 -0
  125. package/dist/options.mjs +12 -1
  126. package/dist/resolve/builtins.cjs +73 -1
  127. package/dist/resolve/builtins.d.cts +68 -0
  128. package/dist/resolve/builtins.mjs +53 -1
  129. package/dist/resolve/component-globals.cjs +233 -13
  130. package/dist/resolve/component-globals.d.cts +80 -0
  131. package/dist/resolve/component-globals.mjs +210 -13
  132. package/dist/resolve/component-resolver.cjs +80 -1
  133. package/dist/resolve/component-resolver.d.cts +68 -0
  134. package/dist/resolve/component-resolver.mjs +59 -1
  135. package/dist/resolve/load-directive.cjs +93 -1
  136. package/dist/resolve/load-directive.d.cts +53 -0
  137. package/dist/resolve/load-directive.mjs +72 -1
  138. package/dist/resolve/resolve-ir.cjs +108 -1
  139. package/dist/resolve/resolve-ir.d.cts +53 -0
  140. package/dist/resolve/resolve-ir.mjs +85 -1
  141. package/dist/resolve/write-globals.cjs +318 -13
  142. package/dist/resolve/write-globals.d.cts +30 -0
  143. package/dist/resolve/write-globals.mjs +297 -13
  144. package/dist/server-fns-4ZXN6DYU.mjs +78 -0
  145. package/dist/server-functions-V6D6DRIA.mjs +82 -0
  146. package/dist/transform/bindings.cjs +71 -1
  147. package/dist/transform/bindings.d.cts +16 -0
  148. package/dist/transform/bindings.mjs +50 -1
  149. package/dist/transform/index.cjs +2732 -8
  150. package/dist/transform/index.d.cts +15 -0
  151. package/dist/transform/index.mjs +3773 -17
  152. package/dist/transform/intrinsics.cjs +216 -3
  153. package/dist/transform/intrinsics.d.cts +21 -0
  154. package/dist/transform/intrinsics.mjs +193 -3
  155. package/dist/transform/props.cjs +441 -3
  156. package/dist/transform/props.d.cts +45 -0
  157. package/dist/transform/props.mjs +1482 -12
  158. package/dist/transform/server-fn-id.cjs +35 -1
  159. package/dist/transform/server-fn-id.d.cts +9 -0
  160. package/dist/transform/server-fn-id.mjs +14 -1
  161. package/dist/transform/server-fns.cjs +114 -2
  162. package/dist/transform/server-fns.d.cts +12 -0
  163. package/dist/transform/server-fns.mjs +1155 -11
  164. package/dist/transform/source-locations.cjs +330 -0
  165. package/dist/transform/source-locations.d.cts +43 -0
  166. package/dist/transform/source-locations.d.ts +44 -0
  167. package/dist/transform/source-locations.d.ts.map +1 -0
  168. package/dist/transform/source-locations.js +238 -0
  169. package/dist/transform/source-locations.mjs +307 -0
  170. package/dist/transform/templates.cjs +2701 -7
  171. package/dist/transform/templates.d.cts +69 -0
  172. package/dist/transform/templates.d.ts +12 -4
  173. package/dist/transform/templates.d.ts.map +1 -1
  174. package/dist/transform/templates.js +72 -7
  175. package/dist/transform/templates.mjs +3743 -16
  176. package/dist/transform-BT4MMASR.mjs +893 -0
  177. package/dist/tsconfig.lib.tsbuildinfo +1 -1
  178. package/package.json +6 -5
  179. package/dist/babel-4JUDAR2G.mjs +0 -1
  180. package/dist/chunk-3SAEGOMQ.mjs +0 -1
  181. package/dist/chunk-IBRM4W7I.mjs +0 -10
  182. package/dist/chunk-OHHZCYIQ.mjs +0 -1
  183. package/dist/chunk-PVR2SN3B.mjs +0 -1
  184. package/dist/chunk-QUIYULS2.mjs +0 -1
  185. package/dist/chunk-YR3SAEO7.mjs +0 -1
  186. package/dist/server-fns-6QM243HC.mjs +0 -2
  187. package/dist/server-functions-E3LKCZ4R.mjs +0 -1
  188. package/dist/transform-5WC4FWJE.mjs +0 -8
@@ -1 +1,2103 @@
1
- import{declare as At}from"@babel/helper-plugin-utils";var We=e=>"components"in e;function me(e,t){return e.replace(/\$(\d+)/g,(n,o)=>t[Number(o)]??n)}function Ue(e,t){return typeof t=="string"?{module:t,export:e}:t}function fe(e=[]){let t=new Map,n=[],o=[];for(let s of e){if(!We(s)){o.push(s);continue}for(let[i,l]of Object.entries(s.components)){let p=Ue(i,l),u=t.get(i);if(u&&u.module!==p.module){let d=n.find(g=>g.name===i);d?d.modules.push(p.module):n.push({name:i,modules:[u.module,p.module]});continue}t.set(i,p)}}let r=new Map;return{resolve:s=>{if(r.has(s))return r.get(s);let i=t.get(s);if(!i)for(let l of o){let p=s.match(new RegExp(l.match.source,l.match.flags.replace("g","")));if(p){i={module:me(l.module,p),export:l.export?me(l.export,p):s};break}}return r.set(s,i),i},names:()=>[...t.keys()],conflicts:()=>n}}var te=["Show","For","Index","Switch","Match","Portal","Dynamic","ErrorBoundary"],M=["Suspense","SuspenseList","Await"],T=["Router","Outlet","Redirect","Link"],Xt=[...te,...M,...T],ne=new Set([...te,...M]);function ge(e={}){let{controlFlowModule:t="@fluixi/dom",coreModule:n="@fluixi/core",routerModule:o="@fluixi/core/router"}=e,r={};for(let a of te)r[a]=t;for(let a of M)r[a]=n;for(let a of T)r[a]=o;return r}var H={kind:"eager"},qe=["pointerdown","focusin","keydown"],he=new Set(["eager","idle","visible","interaction","media","never"]),S=class extends Error{};function re(e){return e.startsWith("load:")}function z(e,t){let n=e.slice(5);if(!he.has(n))throw new S(`Unknown load strategy 'load:${n}'. Expected one of ${[...he].join(", ")}.`);switch(n){case"eager":return H;case"idle":return{kind:"idle"};case"never":return{kind:"never"};case"visible":return t?{kind:"visible",rootMargin:t}:{kind:"visible"};case"interaction":return{kind:"interaction",events:t?Ge(t):[...qe]};case"media":if(!t)throw new S(`'load:media' needs a query, e.g. load:media="(min-width: 1024px)".`);return{kind:"media",query:t};default:throw new S(`Unhandled load strategy '${n}'.`)}}function Ge(e){let t=e.split(/[\s,]+/).map(n=>n.trim()).filter(Boolean);if(t.length===0)throw new S("'load:interaction' was given no event names.");return t}function V(e){return e.kind!=="eager"&&e.kind!=="never"}function W(e,t={}){let{resolver:n,isBound:o,modules:r,strategyFor:a}=t,s=ge(r),i=new Map,l=new Set,p=d=>{let{name:g}=d;if(!g||g.includes(".")||o?.(g))return;let k=u(g);if(!k){l.add(g);return}let C=k.origin==="builtin"&&ne.has(g)?H:a?.(d)??H;d.source={...k,loading:C},i.set(g,d.source)},u=d=>{if(ne.has(d))return{module:s[d],export:d,origin:"builtin"};let g=n?.resolve(d);if(g)return{module:g.module,export:g.export,origin:"rule"};if(T.includes(d))return{module:s[d],export:d,origin:"builtin"}};return U(e,d=>{d.kind==="component"&&p(d)}),{resolved:i,unresolved:[...l]}}function U(e,t){let n=Array.isArray(e)?e:[e];for(let o of n){t(o);let r=o.children;r&&U(r,t)}}function q(e){let t=[];U(e,a=>{a.kind==="component"&&a.source&&t.push(a)});let n=new Set,o=new Set;for(let a of t){let{module:s,loading:i}=a.source;i.kind==="eager"&&n.add(s),i.kind==="never"&&o.add(s)}let r=new Map;for(let a of t){let s=a.source;V(s.loading)&&n.has(s.module)&&(s.loading={kind:"eager"},r.set(s.module,(r.get(s.module)??0)+1))}return{collapsed:r,conflicted:[...o].filter(a=>n.has(a))}}import{types as c,template as He}from"@babel/core";import{types as _,traverse as $t,template as Lt}from"@babel/core";import je from"@babel/generator";var Ke=new Set(["area","base","br","col","embed","hr","img","input","link","meta","param","source","track","wbr"]),ve={className:"class",htmlFor:"for"},Ye=new Set(["innerHTML","outerHTML","innerText","textContent","value","checked","selected","muted","defaultValue","defaultChecked","children","ref"]),Ze=new Set(["script","style","textarea","title"]);function oe(e){return Ze.has(e)}function Re(e){return ve[e]??e}function $(e){return e.kind!=="attr"||e.expr!==void 0||e.name.includes(":")?!1:!Ye.has(e.name)}function ie(e){if(!e.static||oe(e.tag))return!1;for(let t of e.props)if(!$(t))return!1;for(let t of e.children)if(t.kind!=="text"&&!(t.kind==="element"&&ie(t)))return!1;return!0}function L(e){let t=e.props.map(et).filter(Boolean).join(""),n=`<${e.tag}${t}>`;return Ke.has(e.tag)?n:`${n}${e.children.map(Qe).join("")}</${e.tag}>`}function Qe(e){if(e.kind==="text")return nt(e.value);if(e.kind!=="element")throw new Error(`serializeStatic: unexpected ${e.kind}`);return L(e)}function et(e){let t=ve[e.name]??e.name,n=e.literal;return n===!0||n===void 0?` ${t}`:n===!1||n===null?"":` ${t}="${tt(String(n))}"`}function tt(e){return e.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function nt(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}var rt="<!--fx-->",ot="<!--fx/-->";function K(e){return e.kind==="expr"||e.kind==="component"||e.kind==="control"}function it(e){return e.kind==="text"||e.kind==="element"&&xe(e)}function xe(e){return e.svg||oe(e.tag)||!e.props.every(t=>$(t))?!1:e.children.every(t=>it(t)||K(t))}function G(e){if(K(e))return!0;let t=e.children;return t?t.some(G):!1}function ye(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"||ye(t))}function Ee(e){if(!xe(e)||!ye(e)||!e.children.some(G))return null;let t=[],n=[],o=0,r=s=>{let i=`_n$${o++}`;return t.push({ref:i,expr:s}),i};return a(e,"_el$"),{html:st(e),tag:e.tag,steps:t,holes:n};function a(s,i){let l=-1;s.children.forEach((u,d)=>{G(u)&&(l=d)});let p=null;for(let u=0;u<=l;u++){let d=s.children[u],g=p?`${p}.nextSibling`:`${i}.firstChild`;if(K(d)){let C=r(g),f=r(`holeEnd(${C})`);n.push({parentRef:i,startRef:C,endRef:f,node:d}),p=f;continue}let k=r(g);d.kind==="element"&&G(d)&&a(d,k),p=k}}}function st(e){return L(Ne(e)).split(be).join(rt+ot)}function Ne(e){return{...e,children:e.children.map(t=>K(t)?{kind:"text",value:be}:t.kind==="element"?Ne(t):t)}}var be="\0fx-hole\0";var se={version:1,module:"@fluixi/dom",symbols:["createNativeElement","insert","spread","setAttribute","delegateEvents","createComponent","createMemo","untrack","Show","For","Index","Switch","Match","Dynamic","ErrorBoundary"]},Qt={version:2,module:"@fluixi/dom",symbols:[...se.symbols,"template","cloneTemplate","walk"]};var at={show:"Show",for:"For",index:"Index",switch:"Switch",match:"Match",dynamic:"Dynamic",errorBoundary:"ErrorBoundary",suspense:"Suspense"};function lt(e){return/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(e)}function Se(e){return lt(e)?e:JSON.stringify(e)}function ct(e){return e.expr!==void 0?e.reactive?`() => (${e.expr})`:`(${e.expr})`:JSON.stringify(e.literal??!0)}function pt(e){return e.expr!==void 0?`(${e.expr})`:JSON.stringify(e.literal??!0)}function dt(e,t,n){let o=e.filter(i=>i.kind==="spread"),a=e.filter(i=>i.kind!=="spread").map(i=>`${Se(i.name)}: ${ct(i)}`);t!=null&&a.push(`children: ${t}`);let s=`{ ${a.join(", ")} }`;return o.length>0?(n.add("mergeProps"),`mergeProps(${o.map(i=>i.expr).join(", ")}, ${s})`):s}function Ie(e,t,n){return e.length===1?P(e[0],t,n):`[${e.map(o=>P(o,t,n)).join(", ")}]`}function ke(e,t,n,o,r){o.add("createMemo"),o.add("createComponent");let a=t.filter(p=>p.kind==="spread"),i=t.filter(p=>p.kind!=="spread").map(p=>`get ${Se(p.name)}() { return ${pt(p)}; }`);n.length>0&&i.push(`get children() { return ${Ie(n,o,r)}; }`);let l=`{ ${i.join(", ")} }`;return a.length>0&&(o.add("mergeProps"),l=`mergeProps(${a.map(p=>p.expr).join(", ")}, ${l})`),`createMemo(() => createComponent(${e}, ${l}))`}function ut(e,t){let n=Re(t.name),o=t.literal;return o===!0||o===void 0?`${e}.setAttribute(${JSON.stringify(n)}, "");`:o===!1||o===null?"":`${e}.setAttribute(${JSON.stringify(n)}, ${JSON.stringify(String(o))});`}var Ce=!1;function P(e,t,n){switch(e.kind){case"text":return JSON.stringify(e.value);case"expr":return e.reactive?`() => (${e.code})`:`(${e.code})`;case"fragment":return e.children.length===0?"null":Ie(e.children,t,n);case"component":return ke(e.name,e.props,e.children,t,n);case"control":{let o=at[e.control]??e.control;return t.add(o),ke(o,e.props,e.children,t,n)}case"element":{if(n&&e.static&&!e.svg&&ie(e)){t.add("templateNode");let i=`_tmpl$${n.length}`;return n.push({id:i,html:L(e),tag:e.tag,svg:!1}),`templateNode(${i}, ${JSON.stringify(e.tag)})`}if(n&&Ce){let i=Ee(e);if(i){t.add("templateNode"),t.add("insert"),t.add("holeEnd"),t.add("holeContent"),t.add("holeScope");let l=`_tmpl$${n.length}`;n.push({id:l,html:i.html,tag:i.tag,svg:!1});let p=[`const _el$ = templateNode(${l}, ${JSON.stringify(i.tag)}, true);`];for(let u of i.steps)p.push(`const ${u.ref} = ${u.expr};`);for(let u of i.holes)p.push(`insert(${u.parentRef}, holeScope(${u.startRef}, () => (${P(u.node,t,n)})), ${u.endRef}, holeContent(${u.startRef}, ${u.endRef}));`);return p.push("return _el$;"),`(() => { ${p.join(" ")} })()`}}t.add("createNativeElement");let o=JSON.stringify(e.tag),r="_el$",a=[],s=e.svg?`${o}, true`:o;if(a.push(`const ${r} = createNativeElement(${s});`),e.props.length>0)if(!e.svg&&e.props.every($))for(let i of e.props)a.push(ut(r,i));else{t.add("spread");let i=e.svg?", isSVG: true":"";a.push(`spread({ element: ${r}, props: ${dt(e.props,null,t)}${i} });`)}for(let i of e.children){t.add("insert");let l=P(i,t,n),p=i.kind==="expr"&&i.reactive||i.kind==="component"||i.kind==="control";a.push(p?`insert(${r}, ${l}, null);`:`insert(${r}, ${l});`)}return a.push(`return ${r};`),`(() => { ${a.join(" ")} })()`}}}function O(e,t){if(!t||t.length===0)return e;let n=new Map(t.map(o=>[o.id,JSON.stringify(o.html)]));return e.replace(/_tmpl\$\d+/g,o=>n.get(o)??o)}var I={name:"imperative",contract:se,emit(e,t){let n=new Set,o=t?.templateClone!==!1?[]:void 0;return Ce=t?.partialTemplates===!0,{code:P(e,n,o),imports:Array.from(n),templates:o}}};import{types as le}from"@babel/core";import $e from"@babel/generator";import{parseTemplate as mt}from"@fluixi/template-parser";function A(e){let t=e.split(/\r\n|\n|\r/),n=0;for(let r=0;r<t.length;r++)/[^ \t]/.test(t[r])&&(n=r);let o="";for(let r=0;r<t.length;r++){let a=t[r].replace(/\t/g," ");r!==0&&(a=a.replace(/^ +/,"")),r!==t.length-1&&(a=a.replace(/ +$/,"")),a&&(r!==n&&(a+=" "),o+=a)}return o}var we=new Set(["click","dblclick","input","change","submit","focus","blur","keydown","keyup","keypress","mousedown","mouseup"]);function ft(e){return e.replace(/\\/g,"\\\\").replace(/`/g,"\\`").replace(/\$\{/g,"\\${")}function Te(e){return e.charAt(0).toUpperCase()+e.slice(1)}var ae=class{constructor(t,n){this.holes=t;this.used=n}hole(t){return this.holes[t]??{code:"undefined",reactive:!1}}emit(t){let{code:n,imports:o,templates:r}=I.emit(t,{});for(let a of o)this.used.add(a);return O(n,r)}lowerRoot(t){let n=this.lowerChildren(t);return n.length===1?n[0]:{kind:"fragment",children:n}}lowerChildren(t){let n=[];for(let o=0;o<t.length;o++){let r=t[o];if(r.kind==="Element"||r.kind==="Component"){let s=r.attributes.find(i=>i.kind==="IfDirective");if(s&&s.kind==="IfDirective"){let i=o+1;i<t.length&&this.isBlankText(t[i])&&i++;let l=t[i],p=l&&(l.kind==="Element"||l.kind==="Component")&&l.attributes.some(u=>u.kind==="ElseDirective");n.push(this.lowerIf(r,s.hole,p?l:null)),p&&(o=i);continue}if(r.attributes.some(i=>i.kind==="EachDirective")){n.push(this.lowerEach(r));continue}}let a=this.lowerNode(r);a&&n.push(a)}return n}isBlankText(t){return t.kind==="Text"&&!t.raw&&A(t.value)===""}lowerNode(t){switch(t.kind){case"Text":{if(t.raw)return{kind:"text",value:t.value};let n=A(t.value);return n?{kind:"text",value:n}:null}case"Comment":return null;case"Expression":{let n=this.hole(t.hole);return{kind:"expr",code:n.code,reactive:n.reactive}}case"Fragment":return{kind:"fragment",children:this.lowerChildren(t.children)};case"Element":return this.lowerElement(t);case"Component":return this.lowerComponent(t);default:return null}}lowerElement(t){let n=t.attributes.find(o=>o.kind==="Attribute"&&o.name==="is");if(t.tag==="component"&&n&&n.value&&n.value.kind==="hole"){let o=t.attributes.filter(a=>a!==n),r=this.lowerComponent({...t,kind:"Component",tag:"Dynamic",tagHole:null,attributes:o});return r.props.unshift({name:"component",kind:"attr",expr:`() => (${this.hole(n.value.hole).code})`}),r}return{kind:"element",tag:t.tag,svg:t.namespace==="svg",props:this.lowerAttributes(t.attributes),children:this.lowerChildren(t.children),static:!1}}lowerComponent(t){let n=t.tagHole!=null?this.hole(t.tagHole).code:t.tag,o=this.lowerAttributes(t.attributes),{slots:r,rest:a}=this.partitionSlots(t.children);for(let[l,p]of r){let u=p.length===1?p[0]:{kind:"fragment",children:p},d={name:l,kind:"attr",expr:this.emit(u),jsxElement:!0},g=o.findIndex(k=>k.name===l);g>=0?o[g]=d:o.push(d)}let s=t.attributes.find(l=>l.kind==="LoadDirective"),i=s?z(`load:${s.strategy}`,s.modifier):void 0;return{kind:"component",name:n,props:o,children:this.lowerChildren(a),...i?{load:i}:{}}}partitionSlots(t){let n=new Map,o=[];for(let r of t){if(r.kind==="Element"||r.kind==="Component"){let a=r.attributes.find(s=>s.kind==="Attribute"&&s.name==="slot");if(a&&a.value&&a.value.kind==="static"){let s={...r,attributes:r.attributes.filter(p=>p!==a)},i=s.kind==="Element"?this.lowerElement(s):this.lowerComponent(s),l=n.get(a.value.value)??[];l.push(i),n.set(a.value.value,l);continue}}o.push(r)}return{slots:n,rest:o}}lowerIf(t,n,o){let r=this.hole(n),a=[{name:"when",kind:"attr",expr:r.code,reactive:r.reactive}];if(o){let i=this.stripAndLower(o,l=>l.kind==="ElseDirective");a.push({name:"fallback",kind:"attr",expr:this.emit(i),jsxElement:!0})}let s=this.stripAndLower(t,i=>i.kind==="IfDirective");return{kind:"component",name:"Show",props:a,children:[s]}}lowerEach(t){let n=t.attributes.find(l=>l.kind==="EachDirective");if(!n||n.kind!=="EachDirective")return this.lowerNode(t);let o=this.hole(n.hole),r=[{name:"each",kind:"attr",expr:o.code,reactive:o.reactive}];if(n.key){let l="static"in n.key?`(item) => item[${JSON.stringify(n.key.static)}]`:this.hole(n.key.hole).code;r.push({name:"by",kind:"attr",expr:l})}let a=this.itemArrow(t),s;if(a){let l={kind:"expr",code:a.body,reactive:a.bodyReactive},p=this.rebuildWithChildren(t,[l]);s=`(${a.params.join(", ")}) => (${this.emit(p)})`}else{let l=this.stripAndLower(t,p=>p.kind==="EachDirective");s=`() => (${this.emit(l)})`}return{kind:"component",name:"For",props:r,children:[{kind:"expr",code:s,reactive:!1}]}}itemArrow(t){let n=t.children.filter(o=>!this.isBlankText(o));return n.length!==1||n[0].kind!=="Expression"?null:this.hole(n[0].hole).arrow??null}stripAndLower(t,n){let o={...t,attributes:t.attributes.filter(r=>!n(r))};return o.kind==="Element"?this.lowerElement(o):this.lowerComponent(o)}rebuildWithChildren(t,n){let o=this.lowerAttributes(t.attributes.filter(r=>r.kind!=="EachDirective"));return t.kind==="Element"?{kind:"element",tag:t.tag,svg:t.namespace==="svg",props:o,children:n,static:!1}:{kind:"component",name:t.tag,props:o,children:n}}lowerAttributes(t){let n=[],o=[],r=!1,a=[],s=!1,i=[];for(let l of t)switch(l.kind){case"IfDirective":case"EachDirective":case"ElseDirective":break;case"Attribute":n.push(this.plainAttr(l));break;case"PropertyBinding":n.push({name:l.name,kind:"prop",expr:this.hole(l.hole).code,reactive:this.hole(l.hole).reactive});break;case"EventBinding":n.push(this.eventProp(l));break;case"RefBinding":n.push({name:"ref",kind:"ref",expr:this.hole(l.hole).code,reactive:this.hole(l.hole).reactive});break;case"Spread":n.push({name:"",kind:"spread",expr:this.hole(l.hole).code});break;case"ClassDirective":{let p=this.hole(l.hole);o.push(`${JSON.stringify(l.name)}: ${p.code}`),r=r||p.reactive;break}case"StyleDirective":{let p=this.hole(l.hole);a.push(`${JSON.stringify(l.name)}: ${p.code}`),s=s||p.reactive;break}case"BindDirective":n.push(...this.bindProps(l.name,this.hole(l.hole).code));break;case"UseDirective":{let p=l.name??(l.hole!=null?this.hole(l.hole).code:null);if(!p)break;i.push(l.name!=null&&l.hole!=null?`[${p}, () => (${this.hole(l.hole).code})]`:`[${p}]`);break}}return o.length>0&&n.push({name:"classList",kind:"attr",expr:`{ ${o.join(", ")} }`,reactive:r}),a.length>0&&n.push({name:"style",kind:"attr",expr:`{ ${a.join(", ")} }`,reactive:s}),i.length>0&&n.push({name:"use",kind:"attr",expr:`[${i.join(", ")}]`}),n}eventProp(t){let n=t.name.toLowerCase(),o=this.hole(t.hole).code;if(!(t.syntax==="colon"||t.modifiers.length>0))return{name:"on"+Te(t.name),kind:"event",event:{name:n,delegated:we.has(n)},expr:o};let a=this.wrapHandler(o,t.modifiers),s=this.eventOptions(t.modifiers),i=s?`[${a}, ${s}]`:a;return{name:"on:"+n,kind:"attr",expr:i}}wrapHandler(t,n){let o=n.includes("self")?"if (e.target !== e.currentTarget) return; ":"",r=[];return n.includes("prevent")&&r.push("e.preventDefault();"),n.includes("stop")&&r.push("e.stopPropagation();"),!o&&r.length===0?t:`(e) => { ${o}${r.join(" ")} return (${t})(e); }`}eventOptions(t){let n=[];return t.includes("capture")&&n.push("capture: true"),t.includes("once")&&n.push("once: true"),t.includes("passive")&&n.push("passive: true"),n.length?`{ ${n.join(", ")} }`:null}bindProps(t,n){let o=t==="checked",r=o?"change":"input",a=o?"checked":"value";this.used.add("bindPair");let s=`bindPair(${n})`;return[{name:t,kind:"attr",expr:`${s}[0]()`,reactive:!0},{name:"on"+Te(r),kind:"event",event:{name:r,delegated:we.has(r)},expr:`(e) => ${s}[1](e.target.${a})`}]}plainAttr(t){let n=t.value,o=t.name;t.name==="class"?o=n&&n.kind==="hole"&&this.hole(n.hole).object?"classList":"className":t.name==="html"&&(o="innerHTML");let a={name:o,kind:"attr"};if(n==null)return a.literal=!0,a;if(n.kind==="static")return a.literal=n.value,a;if(n.kind==="hole"){let l=this.hole(n.hole);return a.expr=l.code,a.reactive=l.reactive,a}let s=!1,i=n.parts.map(l=>{if("text"in l)return ft(l.text);let p=this.hole(l.hole);return s=s||p.reactive,"${"+p.code+"}"}).join("");return a.expr="`"+i+"`",a.reactive=s,a}};function Me(e,t,n,o={}){let{root:r}=mt(e,{svg:o.svg});return new ae(t,n).lowerRoot(r.children)}var gt=$e.default??$e;function ht(e){return gt(e,{concise:!0}).code}function vt(e,t,n){let o={code:Y(e,t,n),reactive:ce(e)};if(le.isArrowFunctionExpression(e)&&!le.isBlockStatement(e.body)){let r=e.body;o.arrow={params:e.params.map(a=>ht(a)),body:Y(r,t,n),bodyReactive:ce(r)}}return le.isObjectExpression(e)&&(o.object=!0),o}function Le(e,t,n={}){let o=e.quasi,r=o.expressions.map(a=>vt(a,t,n.onNested));return Me(Rt(o),r,t,n)}function Rt(e){let t=[];return e.quasis.forEach((n,o)=>{let r=n.value.cooked??n.value.raw;if(t.push({kind:"static",text:r,start:n.start??0}),o<e.expressions.length){let a=e.expressions[o];t.push({kind:"hole",index:o,start:a.start??0,end:a.end??0})}}),t}function xt(e){switch(e.kind){case"event":return"event";case"ref":return"ref";case"spread":return"spread";case"class":case"style":return"class-or-style-directive";case"attr":case"prop":return e.reactive?"reactive-prop":e.expr!==void 0?"expression-prop":void 0;default:return"expression-prop"}}function Z(e){let t=[],n=new Map,o=r=>{switch(r.kind){case"text":return!0;case"expr":return!1;case"component":case"control":for(let a of r.children)o(a);return!1;case"fragment":for(let a of r.children)o(a);return!1;case"element":{let a=!0;for(let i of r.children)o(i)||(a=!1);let s;for(let i of r.props)if(s=xt(i),s)break;return!s&&!a&&(s=yt(r)),r.static=!s,s?n.set(r,s):t.push(r),r.static}default:return!1}};for(let r of Array.isArray(e)?e:[e])o(r);return{staticElements:t,reasons:n}}function yt(e){for(let t of e.children){if(t.kind==="expr")return"expression-child";if(t.kind==="component")return"component-child";if(t.kind==="control")return"control-child";if(t.kind==="element"&&!t.static||t.kind==="fragment")return"expression-child"}return"expression-child"}function Q(e,t=new Set,n={}){let o=Le(e,t,n);return Z(o),o}var Et="children";function D(e){switch(e.kind){case"call":return!0;case"member":return e.property!==Et;case"compound":return e.parts.some(D);case"opaque":return!1}}var Nt=new Set(["CallExpression","OptionalCallExpression"]),bt=new Set(["MemberExpression","OptionalMemberExpression"]);function j(e){if(!e)return{kind:"opaque"};if(Nt.has(e.type))return{kind:"call"};if(bt.has(e.type)){let t=e.property;return{kind:"member",property:!(e.computed===!0)&&t?.type==="Identifier"?t.name:null}}return e.type==="ConditionalExpression"?{kind:"compound",parts:[e.test,e.consequent,e.alternate].map(J)}:e.type==="LogicalExpression"||e.type==="BinaryExpression"?{kind:"compound",parts:[e.left,e.right].map(J)}:e.type==="TemplateLiteral"?{kind:"compound",parts:e.expressions.map(J)}:e.type==="ObjectExpression"?{kind:"compound",parts:e.properties.filter(n=>(n.type==="ObjectProperty"||n.type==="Property")&&n.computed!==!0).map(n=>J(n.value))}:e.type==="ArrayExpression"?{kind:"compound",parts:e.elements.filter(n=>n!=null&&n.type!=="SpreadElement").map(J)}:{kind:"opaque"}}var J=e=>j(e);var kt=new Set(["svg","path","circle","rect","line","polygon","polyline","ellipse","g","defs","clipPath","text"]),St=/^on[A-Z]/,It=new Set(["click","dblclick","input","change","submit","focus","blur","keydown","keyup","keypress","mousedown","mouseup"]),Ae=e=>D(j(e));function F(e){if(e.type==="StringLiteral"||e.type==="NumericLiteral"||e.type==="BooleanLiteral"||e.type==="Literal"&&(typeof e.value=="string"||typeof e.value=="number"||typeof e.value=="boolean"))return e.value}var pe=e=>!!e&&typeof F(e)=="string";function Ct(e,t){return e.type==="JSXIdentifier"?{tag:e.name,component:e.name[0]!==e.name[0].toLowerCase()}:e.type==="JSXMemberExpression"?{tag:t.code(e),component:!0}:e.type==="JSXNamespacedName"?{tag:`${e.namespace.name}:${e.name.name}`,component:!1}:{tag:"div",component:!1}}function de(e){return e.type==="JSXIdentifier"?e.name==="class"?"className":e.name:e.type==="JSXNamespacedName"?`${e.namespace.name}:${e.name.name}`:"unknown"}function wt(e,t){let n=de(e.name),o=St.test(n),r=o||n.startsWith("on:")||n==="ref",s={name:n,kind:o?"event":"attr"};if(o){let l=n.slice(2).toLowerCase();s.event={name:l,delegated:It.has(l)}}let i=e.value;if(i==null)return s.literal=!0,s;if(pe(i))return s.literal=F(i),s;if(i.type==="JSXExpressionContainer"&&i.expression?.type!=="JSXEmptyExpression"){let l=i.expression,p=F(l);return p!==void 0?(s.literal=p,s):(s.expr=t.code(l),s.reactive=r?!1:Ae(l),(l.type==="JSXElement"||l.type==="JSXFragment")&&(s.jsxElement=!0),s)}return s.literal=!0,s}function Pe(e,t){let n=e.value;return n==null?null:pe(n)?JSON.stringify(F(n)):n.type==="JSXExpressionContainer"&&n.expression?.type!=="JSXEmptyExpression"?t.code(n.expression):null}function Tt(e,t){let n=[],o=[];for(let r of e){if(r.type==="JSXSpreadAttribute"){n.push({name:"",kind:"spread",expr:t.code(r.argument)});continue}if(r.type!=="JSXAttribute"||re(de(r.name)))continue;let a=r.name.type==="JSXNamespacedName"?r.name.namespace.name:null;if(a==="use"){let s=r.name.name.name;t.used.add(s);let i=Pe(r,t);o.push(i!=null?`[${s}, () => (${i})]`:`[${s}]`);continue}if(a==="oncapture"){let s=r.name.name.name.toLowerCase(),i=Pe(r,t)??"undefined";n.push({name:"on:"+s,kind:"attr",expr:`[${i}, { capture: true }]`});continue}n.push(wt(r,t))}return o.length>0&&n.push({name:"use",kind:"attr",expr:`[${o.join(", ")}]`}),n}function Oe(e,t){let n=[];for(let o of e)if(o.type==="JSXText"){let r=A(o.value);r&&n.push({kind:"text",value:r})}else if(o.type==="JSXExpressionContainer"){if(o.expression?.type!=="JSXEmptyExpression"){let r=o.expression;n.push({kind:"expr",code:t.code(r),reactive:Ae(r)})}}else o.type==="JSXElement"||o.type==="JSXFragment"?n.push(De(o,t)):o.type==="JSXSpreadChild"&&n.push({kind:"expr",code:t.code(o.expression),reactive:!1});return n}function Mt(e){for(let t of e){if(t.type!=="JSXAttribute")continue;let n=de(t.name);if(re(n)){if(t.value&&!pe(t.value))throw new S(`'${n}' needs a literal value, not an expression — the strategy is compile-time.`);return z(n,t.value?F(t.value):null)}}}function De(e,t){if(e.type==="JSXFragment")return{kind:"fragment",children:Oe(e.children,t)};let{tag:n,component:o}=Ct(e.openingElement.name,t),r=Tt(e.openingElement.attributes,t),a=Oe(e.children,t);if(o){let s=Mt(e.openingElement.attributes);return{kind:"component",name:n,props:r,children:a,...s?{load:s}:{}}}return{kind:"element",tag:n,svg:kt.has(n),props:r,children:a,static:!1}}function Je(e,t){let n=De(e,t);return Z(n),n}var Pt=je.default??je;function Fe(e){return Pt(e,{concise:!0}).code}function Ot(e,t,n){let o=_.cloneNode(e,!0),r=_.file(_.program([_.expressionStatement(o)])),a=!1,s=(i,l,p)=>{for(let u of p)t.add(u);i.replaceWith(Lt.expression(l,{placeholderPattern:!1,plugins:["typescript"]})()),i.skip(),a=!0};return $t(r,{"JSXElement|JSXFragment"(i){let l=i.node,p=ue(l,t,n);n?.(p);let{code:u,imports:d,templates:g}=I.emit(p,{});s(i,O(u,g),d)},TaggedTemplateExpression(i){let l=i.node.tag;if(!_.isIdentifier(l)||l.name!=="html"&&l.name!=="svg")return;let p=Q(i.node,t,{svg:l.name==="svg",onNested:n});n?.(p);let{code:u,imports:d,templates:g}=I.emit(p,{});s(i,O(u,g),d)}}),a?r.program.body[0].expression:e}function Y(e,t,n){return Fe(Ot(e,t,n))}function ce(e){return D(j(e))}function ue(e,t=new Set,n){return Je(e,{code:r=>r.type==="JSXMemberExpression"?Fe(r):Y(r,t,n),used:t})}var _e=new Set(M),Xe=new Set(T),Un=At((e,t={})=>{e.assertVersion(7);let{delegateEvents:n=!0,signalModule:o="@fluixi/dom",controlFlowModule:r="@fluixi/dom",routerModule:a="@fluixi/core/router",reactiveModule:s="@fluixi/reactive/signal",templateClone:i=!0,partialTemplates:l=!0,format:p="both",litTag:u="html",resolve:d=[]}=t,g=fe(d),k=p==="lit"||p==="both",C={irImports:new Set,libModule:"@fluixi/core",controlFlowModule:r,routerModule:a,templateClone:i,partialTemplates:l,hasJSX:!1,hasLitHTML:!1,needsControlFlowImport:!1,needsCreateMemo:!1,controlFlowComponents:new Set,resolvedComponents:new Map,deferredComponents:new Map,componentResolver:g,delegatedEvents:new Set,staticTemplates:new Map,staticCounter:0};return{name:"@fluixi/babel-plugin-jsx",manipulateOptions(f,m){m.plugins.push("jsx","typescript")},pre(f){Object.assign(f,C)},visitor:{Program:{enter(f,m){Object.assign(m,{hasJSX:!1,hasLitHTML:!1,hasLitIR:!1,needsControlFlowImport:!1,needsCreateMemo:!1,controlFlowComponents:new Set,resolvedComponents:new Map,deferredComponents:new Map,componentResolver:g,delegatedEvents:new Set,staticTemplates:new Map,staticCounter:0,libModule:"@fluixi/core",controlFlowModule:r,routerModule:a,templateClone:i,partialTemplates:l,irImports:new Set,needsCreateNativeElement:!1,needsInsert:!1,needsSpread:!1,needsCreateComponent:!1,needsMergeProps:!1})},exit(f,m){let N=[];if(m.hasJSX||m.hasLitIR){if(m.irImports.size>0){let v=new Set(["Show","For","Index","Switch","Match","Dynamic","ErrorBoundary","Portal","Suspense"]),h=new Set(["createMemo","createEffect","createRenderEffect","createRoot","createSignal","onCleanup","batch","untrack"]),x=Array.from(m.irImports),y=R=>c.importSpecifier(c.identifier(R),c.identifier(R)),b=R=>!f.scope.hasBinding(R),w=x.filter(R=>h.has(R)&&b(R)),E=x.filter(R=>!v.has(R)&&!h.has(R)&&b(R)),B=x.filter(R=>v.has(R)&&b(R));w.length>0&&N.push(c.importDeclaration(w.map(y),c.stringLiteral(s))),E.length>0&&N.push(c.importDeclaration(E.map(y),c.stringLiteral(o))),B.length>0&&N.push(c.importDeclaration(B.map(y),c.stringLiteral(r)))}if(m.needsCreateMemo&&!f.scope.hasBinding("createMemo")&&N.push(c.importDeclaration([c.importSpecifier(c.identifier("createMemo"),c.identifier("createMemo"))],c.stringLiteral(s))),m.needsControlFlowImport&&m.controlFlowComponents.size>0){let v=Array.from(m.controlFlowComponents).filter(E=>!f.scope.hasBinding(E)),h=m.libModule??"@fluixi/core",x=v.filter(E=>Xe.has(E)),y=v.filter(E=>_e.has(E)),b=v.filter(E=>!_e.has(E)&&!Xe.has(E)),w=(E,B)=>c.importDeclaration(E.map(R=>c.importSpecifier(c.identifier(R),c.identifier(R))),c.stringLiteral(B));b.length>0&&N.push(w(b,r)),y.length>0&&N.push(w(y,h)),x.length>0&&N.push(w(x,a))}let X=[];if(m.deferredComponents.size>0){for(let[v,h]of m.deferredComponents)f.scope.hasBinding(v)||X.push(c.variableDeclaration("const",[c.variableDeclarator(c.identifier(v),c.callExpression(c.identifier("deferred"),[c.arrowFunctionExpression([],c.callExpression(c.import(),[c.stringLiteral(h.module)])),c.objectExpression([c.objectProperty(c.identifier("strategy"),Dt(h.strategy)),c.objectProperty(c.identifier("export"),c.stringLiteral(h.export))])]))]));X.length>0&&!f.scope.hasBinding("deferred")&&N.push(c.importDeclaration([c.importSpecifier(c.identifier("deferred"),c.identifier("deferred"))],c.stringLiteral(m.libModule??"@fluixi/core")))}if(m.resolvedComponents.size>0){let v=new Map;for(let[h,x]of m.resolvedComponents){if(f.scope.hasBinding(h))continue;let y=v.get(x.module)??[];y.push({local:h,exported:x.export}),v.set(x.module,y)}for(let[h,x]of v)N.push(c.importDeclaration(x.map(({local:y,exported:b})=>b==="default"?c.importDefaultSpecifier(c.identifier(y)):c.importSpecifier(c.identifier(y),c.identifier(b))),c.stringLiteral(h)))}if(n&&m.delegatedEvents.size>0){N.push(c.importDeclaration([c.importSpecifier(c.identifier("delegateEvents"),c.identifier("delegateEvents"))],c.stringLiteral(o)));let v=c.arrayExpression(Array.from(m.delegatedEvents).map(x=>c.stringLiteral(x))),h=c.expressionStatement(c.callExpression(c.identifier("delegateEvents"),[v]));f.node.body.unshift(h)}if(X.length>0&&f.node.body.unshift(...X),m.staticTemplates.size>0){let v=[];for(let[h,x]of m.staticTemplates){let b=h.startsWith("svg:")?h.slice(4):h;v.push(c.variableDeclaration("const",[c.variableDeclarator(c.identifier(x),c.stringLiteral(b))]))}f.node.body.unshift(...v)}}N.length>0&&f.node.body.unshift(...Jt(N))}},JSXElement(f,m){m.hasJSX=!0,f.replaceWith(Be(f.node,m))},JSXFragment(f,m){m.hasJSX=!0,f.replaceWith(Be(f.node,m))},TaggedTemplateExpression(f,m){k&&c.isIdentifier(f.node.tag)&&(f.node.tag.name===u||f.node.tag.name==="svg")&&f.replaceWith(jt(f.node,m))}}}});function ze(e){return t=>{W(t,{resolver:e.componentResolver,modules:{controlFlowModule:e.controlFlowModule,coreModule:e.libModule,routerModule:e.routerModule},strategyFor:n=>n.load}),q(t),ee(t,e)}}function Dt(e){let t=[c.objectProperty(c.identifier("kind"),c.stringLiteral(e.kind))];return e.kind==="visible"&&e.rootMargin&&t.push(c.objectProperty(c.identifier("rootMargin"),c.stringLiteral(e.rootMargin))),e.kind==="interaction"&&t.push(c.objectProperty(c.identifier("events"),c.arrayExpression(e.events.map(n=>c.stringLiteral(n))))),e.kind==="media"&&t.push(c.objectProperty(c.identifier("query"),c.stringLiteral(e.query))),c.objectExpression(t)}function Ve(e,t,n){if(!t||t.length===0)return e;let o=new Map;for(let r of t){let a=`${r.svg?"svg:":""}${r.html}`,s=n.staticTemplates.get(a);s||(s=`_tmpl$${n.staticTemplates.size}`,n.staticTemplates.set(a,s)),o.set(r.id,s)}return e.replace(/_tmpl\$\d+/g,r=>o.get(r)??r)}function Be(e,t){let n=new Set,o=ue(e,n,ze(t));W(o,{resolver:t.componentResolver,modules:{controlFlowModule:t.controlFlowModule,coreModule:t.libModule,routerModule:t.routerModule},strategyFor:l=>l.load}),q(o);let{code:r,imports:a,templates:s}=I.emit(o,{templateClone:t.templateClone,partialTemplates:t.partialTemplates});for(let l of a)n.add(l);for(let l of n)t.irImports.add(l);ee(o,t);let i=Ve(r,s,t);return He.expression(i,{placeholderPattern:!1,plugins:["typescript"]})()}function Jt(e){let t=new Map,n=[];for(let o of e){let r=o.source.value;if(!o.specifiers.every(i=>c.isImportSpecifier(i))){n.push(o);continue}let s=t.get(r);if(!s){let i=new Set(o.specifiers.map(l=>l.local.name));t.set(r,{decl:o,names:i}),n.push(o);continue}for(let i of o.specifiers)s.names.has(i.local.name)||(s.names.add(i.local.name),s.decl.specifiers.push(i))}return n}function jt(e,t){let n=new Set,o=c.isIdentifier(e.tag)&&e.tag.name==="svg",r=Q(e,n,{svg:o,onNested:ze(t)});W(r,{resolver:t.componentResolver,modules:{controlFlowModule:t.controlFlowModule,coreModule:t.libModule,routerModule:t.routerModule},strategyFor:p=>p.load}),q(r);let{code:a,imports:s,templates:i}=I.emit(r,{templateClone:t.templateClone,partialTemplates:t.partialTemplates});for(let p of s)n.add(p);for(let p of n)t.irImports.add(p);ee(r,t),t.hasLitIR=!0;let l=He.expression(Ve(a,i,t),{placeholderPattern:!1,plugins:["typescript"]})();return Ft(l,e),l}function Ft(e,t){if(!t.loc)return;let n=new Set,o=r=>{if(!n.has(r)){n.add(r),r.loc||(r.loc=t.loc,r.start=t.start,r.end=t.end);for(let a of c.VISITOR_KEYS[r.type]??[]){let s=r[a];if(Array.isArray(s))for(let i of s)i&&typeof i=="object"&&"type"in i&&o(i);else s&&typeof s=="object"&&"type"in s&&o(s)}}};o(e)}function ee(e,t){if(e.kind==="component"&&e.source&&(e.source.origin==="builtin"?(t.controlFlowComponents.add(e.name),t.needsControlFlowImport=!0):V(e.source.loading)&&!t.resolvedComponents.has(e.name)?t.deferredComponents.set(e.name,{module:e.source.module,export:e.source.export,strategy:e.source.loading}):(t.deferredComponents.delete(e.name),t.resolvedComponents.set(e.name,{module:e.source.module,export:e.source.export}))),(e.kind==="element"||e.kind==="component"||e.kind==="control")&&"props"in e)for(let n of e.props)n.kind==="event"&&n.event?.delegated&&t.delegatedEvents.add(n.event.name);if("children"in e&&e.children)for(let n of e.children)ee(n,t)}export{Un as default};
1
+ // src/frontend/babel/plugin.ts
2
+ import { declare } from "@babel/helper-plugin-utils";
3
+
4
+ // src/resolve/component-resolver.ts
5
+ var isMapRule = (rule) => "components" in rule;
6
+ function substitute(template3, match) {
7
+ return template3.replace(/\$(\d+)/g, (whole, index) => {
8
+ const group = match[Number(index)];
9
+ return group ?? whole;
10
+ });
11
+ }
12
+ function normalise(name, entry) {
13
+ return typeof entry === "string" ? { module: entry, export: name } : entry;
14
+ }
15
+ function createComponentResolver(rules = []) {
16
+ const exact = /* @__PURE__ */ new Map();
17
+ const conflicts = [];
18
+ const patterns = [];
19
+ for (const rule of rules) {
20
+ if (!isMapRule(rule)) {
21
+ patterns.push(rule);
22
+ continue;
23
+ }
24
+ for (const [name, entry] of Object.entries(rule.components)) {
25
+ const resolved = normalise(name, entry);
26
+ const existing = exact.get(name);
27
+ if (existing && existing.module !== resolved.module) {
28
+ const conflict = conflicts.find((c) => c.name === name);
29
+ if (conflict) conflict.modules.push(resolved.module);
30
+ else conflicts.push({ name, modules: [existing.module, resolved.module] });
31
+ continue;
32
+ }
33
+ exact.set(name, resolved);
34
+ }
35
+ }
36
+ const cache = /* @__PURE__ */ new Map();
37
+ const resolve = (name) => {
38
+ if (cache.has(name)) return cache.get(name);
39
+ let result = exact.get(name);
40
+ if (!result) {
41
+ for (const rule of patterns) {
42
+ const match = name.match(new RegExp(rule.match.source, rule.match.flags.replace("g", "")));
43
+ if (!match) continue;
44
+ result = {
45
+ module: substitute(rule.module, match),
46
+ export: rule.export ? substitute(rule.export, match) : name
47
+ };
48
+ break;
49
+ }
50
+ }
51
+ cache.set(name, result);
52
+ return result;
53
+ };
54
+ return {
55
+ resolve,
56
+ names: () => [...exact.keys()],
57
+ conflicts: () => conflicts
58
+ };
59
+ }
60
+
61
+ // src/resolve/builtins.ts
62
+ var DOM_CONTROL_FLOW = [
63
+ "Show",
64
+ "For",
65
+ "Index",
66
+ "Switch",
67
+ "Match",
68
+ "Portal",
69
+ "Dynamic",
70
+ "ErrorBoundary"
71
+ ];
72
+ var CORE_CONTROL_FLOW = ["Suspense", "SuspenseList", "Await"];
73
+ var ROUTER_COMPONENTS = ["Router", "Outlet", "Redirect", "Link"];
74
+ var BUILTIN_COMPONENTS = [
75
+ ...DOM_CONTROL_FLOW,
76
+ ...CORE_CONTROL_FLOW,
77
+ ...ROUTER_COMPONENTS
78
+ ];
79
+ var RESERVED_COMPONENTS = /* @__PURE__ */ new Set([
80
+ ...DOM_CONTROL_FLOW,
81
+ ...CORE_CONTROL_FLOW
82
+ ]);
83
+ function builtinComponentMap(modules = {}) {
84
+ const {
85
+ controlFlowModule = "@fluixi/dom",
86
+ coreModule = "@fluixi/core",
87
+ routerModule = "@fluixi/core/router"
88
+ } = modules;
89
+ const map = {};
90
+ for (const name of DOM_CONTROL_FLOW) map[name] = controlFlowModule;
91
+ for (const name of CORE_CONTROL_FLOW) map[name] = coreModule;
92
+ for (const name of ROUTER_COMPONENTS) map[name] = routerModule;
93
+ return map;
94
+ }
95
+
96
+ // src/resolve/load-directive.ts
97
+ var EAGER = { kind: "eager" };
98
+ var DEFAULT_INTERACTION_EVENTS = ["pointerdown", "focusin", "keydown"];
99
+ var STRATEGIES = /* @__PURE__ */ new Set(["eager", "idle", "visible", "interaction", "media", "never"]);
100
+ var LoadDirectiveError = class extends Error {
101
+ };
102
+ function isLoadDirective(name) {
103
+ return name.startsWith("load:");
104
+ }
105
+ function parseLoadDirective(name, value) {
106
+ const strategy = name.slice("load:".length);
107
+ if (!STRATEGIES.has(strategy)) {
108
+ throw new LoadDirectiveError(
109
+ `Unknown load strategy 'load:${strategy}'. Expected one of ${[...STRATEGIES].join(", ")}.`
110
+ );
111
+ }
112
+ switch (strategy) {
113
+ case "eager":
114
+ return EAGER;
115
+ case "idle":
116
+ return { kind: "idle" };
117
+ case "never":
118
+ return { kind: "never" };
119
+ case "visible":
120
+ return value ? { kind: "visible", rootMargin: value } : { kind: "visible" };
121
+ case "interaction":
122
+ return {
123
+ kind: "interaction",
124
+ events: value ? splitEvents(value) : [...DEFAULT_INTERACTION_EVENTS]
125
+ };
126
+ case "media":
127
+ if (!value) {
128
+ throw new LoadDirectiveError(
129
+ `'load:media' needs a query, e.g. load:media="(min-width: 1024px)".`
130
+ );
131
+ }
132
+ return { kind: "media", query: value };
133
+ default:
134
+ throw new LoadDirectiveError(`Unhandled load strategy '${strategy}'.`);
135
+ }
136
+ }
137
+ function splitEvents(value) {
138
+ const events = value.split(/[\s,]+/).map((e) => e.trim()).filter(Boolean);
139
+ if (events.length === 0) {
140
+ throw new LoadDirectiveError(`'load:interaction' was given no event names.`);
141
+ }
142
+ return events;
143
+ }
144
+ function isDeferred(strategy) {
145
+ return strategy.kind !== "eager" && strategy.kind !== "never";
146
+ }
147
+
148
+ // src/resolve/resolve-ir.ts
149
+ function resolveComponentSources(root, options = {}) {
150
+ const { resolver, isBound, modules, strategyFor } = options;
151
+ const builtins = builtinComponentMap(modules);
152
+ const resolved = /* @__PURE__ */ new Map();
153
+ const unresolved = /* @__PURE__ */ new Set();
154
+ const annotate = (node) => {
155
+ const { name } = node;
156
+ if (!name || name.includes(".")) return;
157
+ if (isBound?.(name)) return;
158
+ const source = sourceFor(name);
159
+ if (!source) {
160
+ unresolved.add(name);
161
+ return;
162
+ }
163
+ const loading = source.origin === "builtin" && RESERVED_COMPONENTS.has(name) ? EAGER : strategyFor?.(node) ?? EAGER;
164
+ node.source = { ...source, loading };
165
+ resolved.set(name, node.source);
166
+ };
167
+ const sourceFor = (name) => {
168
+ if (RESERVED_COMPONENTS.has(name)) {
169
+ return { module: builtins[name], export: name, origin: "builtin" };
170
+ }
171
+ const rule = resolver?.resolve(name);
172
+ if (rule) return { module: rule.module, export: rule.export, origin: "rule" };
173
+ if (ROUTER_COMPONENTS.includes(name)) {
174
+ return { module: builtins[name], export: name, origin: "builtin" };
175
+ }
176
+ return void 0;
177
+ };
178
+ walk(root, (node) => {
179
+ if (node.kind === "component") annotate(node);
180
+ });
181
+ return { resolved, unresolved: [...unresolved] };
182
+ }
183
+ function walk(root, visit) {
184
+ const nodes = Array.isArray(root) ? root : [root];
185
+ for (const node of nodes) {
186
+ visit(node);
187
+ const children = node.children;
188
+ if (children) walk(children, visit);
189
+ }
190
+ }
191
+
192
+ // src/optimize/collapse-strategies.ts
193
+ function collapseStrategies(root) {
194
+ const components = [];
195
+ walk(root, (node) => {
196
+ if (node.kind === "component" && node.source) components.push(node);
197
+ });
198
+ const eager = /* @__PURE__ */ new Set();
199
+ const never = /* @__PURE__ */ new Set();
200
+ for (const node of components) {
201
+ const { module, loading } = node.source;
202
+ if (loading.kind === "eager") eager.add(module);
203
+ if (loading.kind === "never") never.add(module);
204
+ }
205
+ const collapsed = /* @__PURE__ */ new Map();
206
+ for (const node of components) {
207
+ const source = node.source;
208
+ if (!isDeferred(source.loading)) continue;
209
+ if (!eager.has(source.module)) continue;
210
+ source.loading = { kind: "eager" };
211
+ collapsed.set(source.module, (collapsed.get(source.module) ?? 0) + 1);
212
+ }
213
+ return {
214
+ collapsed,
215
+ conflicted: [...never].filter((m) => eager.has(m))
216
+ };
217
+ }
218
+
219
+ // src/frontend/babel/plugin.ts
220
+ import { types as t3, template as template2 } from "@babel/core";
221
+
222
+ // src/frontend/babel/build-ir.ts
223
+ import { types as t2, traverse, template } from "@babel/core";
224
+ import _generate2 from "@babel/generator";
225
+
226
+ // src/codegen/serialize-static.ts
227
+ var VOID_ELEMENTS = /* @__PURE__ */ new Set([
228
+ "area",
229
+ "base",
230
+ "br",
231
+ "col",
232
+ "embed",
233
+ "hr",
234
+ "img",
235
+ "input",
236
+ "link",
237
+ "meta",
238
+ "param",
239
+ "source",
240
+ "track",
241
+ "wbr"
242
+ ]);
243
+ var HTML_NAME = {
244
+ className: "class",
245
+ htmlFor: "for"
246
+ };
247
+ var PROPERTY_ONLY = /* @__PURE__ */ new Set([
248
+ "innerHTML",
249
+ "outerHTML",
250
+ "innerText",
251
+ "textContent",
252
+ "value",
253
+ "checked",
254
+ "selected",
255
+ "muted",
256
+ "defaultValue",
257
+ "defaultChecked",
258
+ "children",
259
+ "ref"
260
+ ]);
261
+ var RAW_TEXT_ELEMENTS = /* @__PURE__ */ new Set(["script", "style", "textarea", "title"]);
262
+ function isRawTextElement(tag) {
263
+ return RAW_TEXT_ELEMENTS.has(tag);
264
+ }
265
+ function htmlAttrName(name) {
266
+ return HTML_NAME[name] ?? name;
267
+ }
268
+ function isPlainLiteralAttr(prop) {
269
+ if (prop.kind !== "attr") return false;
270
+ if (prop.expr !== void 0) return false;
271
+ if (prop.name.includes(":")) return false;
272
+ return !PROPERTY_ONLY.has(prop.name);
273
+ }
274
+ function isSerializable(node) {
275
+ if (!node.static) return false;
276
+ if (isRawTextElement(node.tag)) return false;
277
+ for (const prop of node.props) {
278
+ if (!isPlainLiteralAttr(prop)) return false;
279
+ }
280
+ for (const child of node.children) {
281
+ if (child.kind === "text") continue;
282
+ if (child.kind === "element" && isSerializable(child)) continue;
283
+ return false;
284
+ }
285
+ return true;
286
+ }
287
+ function serializeStatic(node) {
288
+ const attrs = node.props.map(serializeProp).filter(Boolean).join("");
289
+ const open = `<${node.tag}${attrs}>`;
290
+ if (VOID_ELEMENTS.has(node.tag)) return open;
291
+ return `${open}${node.children.map(serializeChild).join("")}</${node.tag}>`;
292
+ }
293
+ function serializeChild(child) {
294
+ if (child.kind === "text") return escapeText(child.value);
295
+ if (child.kind !== "element") throw new Error(`serializeStatic: unexpected ${child.kind}`);
296
+ return serializeStatic(child);
297
+ }
298
+ function serializeProp(prop) {
299
+ const name = HTML_NAME[prop.name] ?? prop.name;
300
+ const value = prop.literal;
301
+ if (value === true || value === void 0) return ` ${name}`;
302
+ if (value === false || value === null) return "";
303
+ return ` ${name}="${escapeAttr(String(value))}"`;
304
+ }
305
+ function escapeAttr(value) {
306
+ return value.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
307
+ }
308
+ function escapeText(value) {
309
+ return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
310
+ }
311
+ function templatePositions(root) {
312
+ const pos = [];
313
+ let file;
314
+ const walk2 = (el) => {
315
+ file ??= el.at?.file;
316
+ pos.push(el.at?.line ?? 0, el.at?.column ?? 0);
317
+ for (const child of el.children) if (child.kind === "element") walk2(child);
318
+ };
319
+ walk2(root);
320
+ return file && pos.some((n) => n !== 0) ? { file, pos } : void 0;
321
+ }
322
+
323
+ // src/codegen/partial-template.ts
324
+ var HOLE_START = "<!--fx-->";
325
+ var HOLE_END = "<!--fx/-->";
326
+ function isHole(node) {
327
+ return node.kind === "expr" || node.kind === "component" || node.kind === "control";
328
+ }
329
+ function isTemplateChild(node) {
330
+ return node.kind === "text" || node.kind === "element" && isTemplateElement(node);
331
+ }
332
+ function isTemplateElement(node) {
333
+ if (node.svg) return false;
334
+ if (isRawTextElement(node.tag)) return false;
335
+ if (!node.props.every((p) => isPlainLiteralAttr(p))) return false;
336
+ return node.children.every((c) => isTemplateChild(c) || isHole(c));
337
+ }
338
+ function containsHole(node) {
339
+ if (isHole(node)) return true;
340
+ const children = node.children;
341
+ return children ? children.some(containsHole) : false;
342
+ }
343
+ function addressable(el) {
344
+ for (let i = 0; i < el.children.length; i++) {
345
+ const child = el.children[i];
346
+ if (child.kind === "text") {
347
+ if (child.value === "") return false;
348
+ if (el.children[i + 1]?.kind === "text") return false;
349
+ }
350
+ }
351
+ return el.children.every((c) => c.kind !== "element" || addressable(c));
352
+ }
353
+ function planPartialTemplate(root) {
354
+ if (!isTemplateElement(root)) return null;
355
+ if (!addressable(root)) return null;
356
+ if (!root.children.some(containsHole)) return null;
357
+ const steps = [];
358
+ const holes = [];
359
+ let refCount = 0;
360
+ const declare2 = (expr) => {
361
+ const ref = `_n$${refCount++}`;
362
+ steps.push({ ref, expr });
363
+ return ref;
364
+ };
365
+ walk2(root, "_el$");
366
+ return { html: serializeWithMarkers(root), tag: root.tag, steps, holes };
367
+ function walk2(el, elementRef) {
368
+ let last = -1;
369
+ el.children.forEach((child, i) => {
370
+ if (containsHole(child)) last = i;
371
+ });
372
+ let previous = null;
373
+ for (let i = 0; i <= last; i++) {
374
+ const child = el.children[i];
375
+ const expr = previous ? `${previous}.nextSibling` : `${elementRef}.firstChild`;
376
+ if (isHole(child)) {
377
+ const startRef = declare2(expr);
378
+ const endRef = declare2(`holeEnd(${startRef})`);
379
+ holes.push({ parentRef: elementRef, startRef, endRef, node: child });
380
+ previous = endRef;
381
+ continue;
382
+ }
383
+ const ref = declare2(expr);
384
+ if (child.kind === "element" && containsHole(child)) walk2(child, ref);
385
+ previous = ref;
386
+ }
387
+ }
388
+ }
389
+ function serializeWithMarkers(el) {
390
+ return serializeStatic(withSentinels(el)).split(SENTINEL).join(HOLE_START + HOLE_END);
391
+ }
392
+ function withSentinels(el) {
393
+ return {
394
+ ...el,
395
+ children: el.children.map(
396
+ (child) => isHole(child) ? { kind: "text", value: SENTINEL } : child.kind === "element" ? withSentinels(child) : child
397
+ )
398
+ };
399
+ }
400
+ var SENTINEL = "\0fx-hole\0";
401
+
402
+ // src/codegen/contract.ts
403
+ var RUNTIME_CONTRACT_V1 = {
404
+ version: 1,
405
+ module: "@fluixi/dom",
406
+ symbols: [
407
+ "createNativeElement",
408
+ "insert",
409
+ "spread",
410
+ "setAttribute",
411
+ "delegateEvents",
412
+ "createComponent",
413
+ "createMemo",
414
+ "untrack",
415
+ "Show",
416
+ "For",
417
+ "Index",
418
+ "Switch",
419
+ "Match",
420
+ "Dynamic",
421
+ "ErrorBoundary"
422
+ ]
423
+ };
424
+ var RUNTIME_CONTRACT_V2 = {
425
+ version: 2,
426
+ module: "@fluixi/dom",
427
+ symbols: [...RUNTIME_CONTRACT_V1.symbols, "template", "cloneTemplate", "walk"]
428
+ };
429
+
430
+ // src/analyze/intrinsics.ts
431
+ var REACTIVE_MODULE = "@fluixi/reactive/signal";
432
+ var INTRINSICS = {
433
+ $signal: { export: "signal", module: REACTIVE_MODULE, returns: "signal-handle" },
434
+ $memo: { export: "memo", module: REACTIVE_MODULE, returns: "memo-handle" },
435
+ $effect: { export: "effect", module: REACTIVE_MODULE, returns: "effect" },
436
+ $store: { export: "store", module: "@fluixi/reactive/store", returns: "store-handle" },
437
+ $resource: { export: "resource", module: REACTIVE_MODULE, returns: "resource-handle" },
438
+ // No short runtime form for these yet, so the intrinsic stands for the `create*`
439
+ // name. Still worth having — no import to write — and when a shorter form is
440
+ // designed, the change is this line rather than a compiler pass.
441
+ $selector: { export: "createSelector", module: REACTIVE_MODULE, returns: "memo-accessor" },
442
+ $deferred: { export: "createDeferred", module: REACTIVE_MODULE, returns: "memo-accessor" },
443
+ // Not value constructors, but the compiler has to know them: they change what a read
444
+ // does. `untrack` suppresses dependency collection, which is exactly the kind of thing
445
+ // dependency analysis must not guess at.
446
+ $untrack: { export: "untrack", module: REACTIVE_MODULE, returns: "plain" },
447
+ $untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" }
448
+ };
449
+ var INTRINSIC_CALL = new RegExp(`\\$(?:${Object.keys(INTRINSICS).map((n) => n.slice(1)).join("|")})\\s*\\(`);
450
+
451
+ // src/transform/source-locations.ts
452
+ var SOURCE_MARKER = "__fx_source";
453
+ var HOLE_MARKER = "__fx_hole";
454
+ var markHole = (accessor, line, column, name) => `(globalThis.${HOLE_MARKER} ?? ((f) => f))(${accessor},${line},${column}${name === void 0 ? "" : `,${JSON.stringify(name)}`})`;
455
+ var PROPS_MARKER = "__fx_props";
456
+ var markProps = (object, at) => `(globalThis.${PROPS_MARKER} ?? ((p) => p))(${object},${JSON.stringify(at)})`;
457
+
458
+ // src/analyze/paren.ts
459
+ function skipQuoted(src, start) {
460
+ const quote = src[start];
461
+ for (let i = start + 1; i < src.length; i++) {
462
+ const c = src[i];
463
+ if (c === "\\") i++;
464
+ else if (c === quote) return i + 1;
465
+ else if (c === "\n") return -1;
466
+ }
467
+ return -1;
468
+ }
469
+ function skipTemplate(src, start) {
470
+ let i = start + 1;
471
+ while (i < src.length) {
472
+ const c = src[i];
473
+ if (c === "\\") {
474
+ i += 2;
475
+ } else if (c === "`") {
476
+ return i + 1;
477
+ } else if (c === "$" && src[i + 1] === "{") {
478
+ let depth = 1;
479
+ i += 2;
480
+ while (i < src.length && depth > 0) {
481
+ const k = src[i];
482
+ if (k === "\\") i += 2;
483
+ else if (k === "`") {
484
+ const end = skipTemplate(src, i);
485
+ if (end < 0) return -1;
486
+ i = end;
487
+ } else if (k === '"' || k === "'") {
488
+ const end = skipQuoted(src, i);
489
+ if (end < 0) return -1;
490
+ i = end;
491
+ } else {
492
+ if (k === "{") depth++;
493
+ else if (k === "}") depth--;
494
+ i++;
495
+ }
496
+ }
497
+ } else {
498
+ i++;
499
+ }
500
+ }
501
+ return -1;
502
+ }
503
+ function skipRegex(src, start) {
504
+ let inClass = false;
505
+ for (let i = start + 1; i < src.length; i++) {
506
+ const c = src[i];
507
+ if (c === "\\") i++;
508
+ else if (c === "[") inClass = true;
509
+ else if (c === "]") inClass = false;
510
+ else if (c === "\n") return -1;
511
+ else if (c === "/" && !inClass) {
512
+ let end = i + 1;
513
+ while (end < src.length && /[a-z]/i.test(src[end])) end++;
514
+ return end;
515
+ }
516
+ }
517
+ return -1;
518
+ }
519
+ function divides(prev) {
520
+ return prev !== "" && /[A-Za-z0-9_$)\]]/.test(prev);
521
+ }
522
+ function topLevelComma(src) {
523
+ let depth = 0;
524
+ let prev = "";
525
+ let i = 0;
526
+ while (i < src.length) {
527
+ const c = src[i];
528
+ if (c === '"' || c === "'") {
529
+ const end = skipQuoted(src, i);
530
+ if (end < 0) return null;
531
+ i = end;
532
+ prev = c;
533
+ } else if (c === "`") {
534
+ const end = skipTemplate(src, i);
535
+ if (end < 0) return null;
536
+ i = end;
537
+ prev = c;
538
+ } else if (c === "/" && src[i + 1] === "/") {
539
+ return null;
540
+ } else if (c === "/" && src[i + 1] === "*") {
541
+ const end = src.indexOf("*/", i + 2);
542
+ if (end < 0) return null;
543
+ i = end + 2;
544
+ } else if (c === "/" && !divides(prev)) {
545
+ const end = skipRegex(src, i);
546
+ if (end < 0) return null;
547
+ i = end;
548
+ prev = "/";
549
+ } else {
550
+ if (c === "(" || c === "[" || c === "{") depth++;
551
+ else if (c === ")" || c === "]" || c === "}") {
552
+ depth--;
553
+ if (depth < 0) return null;
554
+ } else if (c === "," && depth === 0) return true;
555
+ if (!/\s/.test(c)) prev = c;
556
+ i++;
557
+ }
558
+ }
559
+ return depth === 0 ? false : null;
560
+ }
561
+ function paren(code, position) {
562
+ const src = code.trim();
563
+ if (src === "") return `(${code})`;
564
+ if (position === "arrowBody" && src[0] === "{") return `(${code})`;
565
+ return topLevelComma(src) === false ? code : `(${code})`;
566
+ }
567
+
568
+ // src/codegen/backends/imperative.ts
569
+ var CONTROL_COMPONENT = {
570
+ show: "Show",
571
+ for: "For",
572
+ index: "Index",
573
+ switch: "Switch",
574
+ match: "Match",
575
+ dynamic: "Dynamic",
576
+ errorBoundary: "ErrorBoundary",
577
+ suspense: "Suspense"
578
+ };
579
+ function isIdent(name) {
580
+ return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name);
581
+ }
582
+ function propKey(name) {
583
+ return isIdent(name) ? name : JSON.stringify(name);
584
+ }
585
+ function propValue(p) {
586
+ if (p.expr !== void 0) {
587
+ if (p.name === "ref" && p.at)
588
+ return markHole(paren(p.expr, "value"), p.at.line, p.at.column, p.expr);
589
+ if (!p.reactive) return paren(p.expr, "value");
590
+ const accessor = `() => ${paren(p.expr, "arrowBody")}`;
591
+ return p.at ? markHole(accessor, p.at.line, p.at.column, p.directive) : accessor;
592
+ }
593
+ return JSON.stringify(p.literal ?? true);
594
+ }
595
+ function componentPropValue(p) {
596
+ if (p.expr !== void 0) return paren(p.expr, "value");
597
+ return JSON.stringify(p.literal ?? true);
598
+ }
599
+ function emitProps(props, childrenExpr, used) {
600
+ const spreads = props.filter((p) => p.kind === "spread");
601
+ const normal = props.filter((p) => p.kind !== "spread");
602
+ const entries = normal.map((p) => `${propKey(p.name)}: ${propValue(p)}`);
603
+ if (childrenExpr != null) entries.push(`children: ${childrenExpr}`);
604
+ const obj = `{ ${entries.join(", ")} }`;
605
+ if (spreads.length > 0) {
606
+ used.add("mergeProps");
607
+ return `mergeProps(${spreads.map((s) => s.expr).join(", ")}, ${obj})`;
608
+ }
609
+ return obj;
610
+ }
611
+ function markBind(code, at) {
612
+ return at ? markHole(code, at.line, at.column) : code;
613
+ }
614
+ function emitChildren(children, used, templates) {
615
+ if (children.length === 1) return emitNode(children[0], used, templates);
616
+ return `[${children.map((c) => emitNode(c, used, templates)).join(", ")}]`;
617
+ }
618
+ function emitComponent(name, props, children, used, templates, at) {
619
+ used.add("createMemo");
620
+ used.add("createComponent");
621
+ const spreads = props.filter((p) => p.kind === "spread");
622
+ const normal = props.filter((p) => p.kind !== "spread");
623
+ const entries = normal.map(
624
+ (p) => `get ${propKey(p.name)}() { return ${componentPropValue(p)}; }`
625
+ );
626
+ if (children.length > 0) {
627
+ entries.push(`get children() { return ${emitChildren(children, used, templates)}; }`);
628
+ }
629
+ let obj = `{ ${entries.join(", ")} }`;
630
+ if (spreads.length > 0) {
631
+ used.add("mergeProps");
632
+ obj = `mergeProps(${spreads.map((s) => s.expr).join(", ")}, ${obj})`;
633
+ }
634
+ const propAt = {};
635
+ for (const p of normal) if (p.at) propAt[p.name] = [p.at.line, p.at.column];
636
+ if (Object.keys(propAt).length) obj = markProps(obj, propAt);
637
+ const mark = at ? `globalThis.${SOURCE_MARKER}?.(${JSON.stringify(at.file)},${at.line},${at.column},${JSON.stringify(name)}), ` : "";
638
+ return `createMemo(${paren(`${mark}() => createComponent(${name}, ${obj})`, "value")})`;
639
+ }
640
+ function staticAttrAssignment(el, prop) {
641
+ const name = htmlAttrName(prop.name);
642
+ const value = prop.literal;
643
+ if (value === true || value === void 0) return `${el}.setAttribute(${JSON.stringify(name)}, "");`;
644
+ if (value === false || value === null) return "";
645
+ return `${el}.setAttribute(${JSON.stringify(name)}, ${JSON.stringify(String(value))});`;
646
+ }
647
+ var partial = false;
648
+ function emitNode(node, used, templates) {
649
+ switch (node.kind) {
650
+ case "text":
651
+ return JSON.stringify(node.value);
652
+ case "expr": {
653
+ if (!node.reactive) return paren(node.code, "value");
654
+ const accessor = `() => ${paren(node.code, "arrowBody")}`;
655
+ return node.at ? markHole(accessor, node.at.line, node.at.column) : accessor;
656
+ }
657
+ case "fragment":
658
+ if (node.children.length === 0) return "null";
659
+ return emitChildren(node.children, used, templates);
660
+ case "component":
661
+ return markBind(emitComponent(node.name, node.props, node.children, used, templates, node.at), node.bindAt ?? node.at);
662
+ case "control": {
663
+ const name = CONTROL_COMPONENT[node.control] ?? node.control;
664
+ used.add(name);
665
+ return markBind(emitComponent(name, node.props, node.children, used, templates), node.bindAt);
666
+ }
667
+ case "element": {
668
+ if (templates && node.static && !node.svg && isSerializable(node)) {
669
+ used.add("templateNode");
670
+ const id = `_tmpl$${templates.length}`;
671
+ templates.push({ id, html: serializeStatic(node), tag: node.tag, svg: false });
672
+ const at = templatePositions(node);
673
+ return at ? `templateNode(${id}, ${JSON.stringify(node.tag)}, false, false, ${JSON.stringify(at)})` : `templateNode(${id}, ${JSON.stringify(node.tag)})`;
674
+ }
675
+ if (templates && partial) {
676
+ const plan = planPartialTemplate(node);
677
+ if (plan) {
678
+ used.add("templateNode");
679
+ used.add("insert");
680
+ used.add("holeEnd");
681
+ used.add("holeContent");
682
+ used.add("holeScope");
683
+ const id = `_tmpl$${templates.length}`;
684
+ templates.push({ id, html: plan.html, tag: plan.tag, svg: false });
685
+ const at = templatePositions(node);
686
+ const lines = [
687
+ `const _el$ = templateNode(${id}, ${JSON.stringify(plan.tag)}, true${at ? `, false, ${JSON.stringify(at)}` : ""});`
688
+ ];
689
+ for (const step of plan.steps) lines.push(`const ${step.ref} = ${step.expr};`);
690
+ for (const hole of plan.holes) {
691
+ lines.push(
692
+ `insert(${hole.parentRef}, holeScope(${hole.startRef}, () => ${paren(emitNode(hole.node, used, templates), "arrowBody")}), ${hole.endRef}, holeContent(${hole.startRef}, ${hole.endRef}));`
693
+ );
694
+ }
695
+ lines.push("return _el$;");
696
+ return `(() => { ${lines.join(" ")} })()`;
697
+ }
698
+ }
699
+ used.add("createNativeElement");
700
+ const tag = JSON.stringify(node.tag);
701
+ const el = "_el$";
702
+ const parts = [];
703
+ const createArgs = node.at ? `${tag}, ${node.svg}, ${JSON.stringify(node.at)}` : node.svg ? `${tag}, true` : tag;
704
+ parts.push(`const ${el} = createNativeElement(${createArgs});`);
705
+ if (node.props.length > 0) {
706
+ if (!node.svg && node.props.every(isPlainLiteralAttr)) {
707
+ for (const p of node.props) parts.push(staticAttrAssignment(el, p));
708
+ } else {
709
+ used.add("spread");
710
+ const svgFlag = node.svg ? ", isSVG: true" : "";
711
+ parts.push(`spread({ element: ${el}, props: ${emitProps(node.props, null, used)}${svgFlag} });`);
712
+ }
713
+ }
714
+ for (const child of node.children) {
715
+ used.add("insert");
716
+ const childCode = emitNode(child, used, templates);
717
+ const isFn = child.kind === "expr" && child.reactive || child.kind === "component" || child.kind === "control";
718
+ parts.push(isFn ? `insert(${el}, ${childCode}, null);` : `insert(${el}, ${childCode});`);
719
+ }
720
+ parts.push(`return ${el};`);
721
+ return `(() => { ${parts.join(" ")} })()`;
722
+ }
723
+ }
724
+ }
725
+ function inlineTemplates(code, templates) {
726
+ if (!templates || templates.length === 0) return code;
727
+ const byId = new Map(templates.map((t4) => [t4.id, JSON.stringify(t4.html)]));
728
+ return code.replace(/_tmpl\$\d+/g, (id) => byId.get(id) ?? id);
729
+ }
730
+ var imperativeBackend = {
731
+ name: "imperative",
732
+ contract: RUNTIME_CONTRACT_V1,
733
+ emit(node, options) {
734
+ const used = /* @__PURE__ */ new Set();
735
+ const templates = options?.templateClone !== false ? [] : void 0;
736
+ partial = options?.partialTemplates === true;
737
+ const code = emitNode(node, used, templates);
738
+ return { code, imports: Array.from(used), templates };
739
+ }
740
+ };
741
+
742
+ // src/frontend/babel/lower-template.ts
743
+ import { types as t } from "@babel/core";
744
+ import _generate from "@babel/generator";
745
+
746
+ // src/lower/template.ts
747
+ import {
748
+ parseTemplate
749
+ } from "@fluixi/template-parser";
750
+
751
+ // src/lower/text.ts
752
+ function cleanTemplateText(value) {
753
+ const lines = value.split(/\r\n|\n|\r/);
754
+ let lastNonEmpty = 0;
755
+ for (let i = 0; i < lines.length; i++) {
756
+ if (/[^ \t]/.test(lines[i])) lastNonEmpty = i;
757
+ }
758
+ let out = "";
759
+ for (let i = 0; i < lines.length; i++) {
760
+ let line = lines[i].replace(/\t/g, " ");
761
+ if (i !== 0) line = line.replace(/^ +/, "");
762
+ if (i !== lines.length - 1) line = line.replace(/ +$/, "");
763
+ if (!line) continue;
764
+ if (i !== lastNonEmpty) line += " ";
765
+ out += line;
766
+ }
767
+ return out;
768
+ }
769
+
770
+ // src/lower/template.ts
771
+ var DELEGATED = /* @__PURE__ */ new Set([
772
+ "click",
773
+ "dblclick",
774
+ "input",
775
+ "change",
776
+ "submit",
777
+ "focus",
778
+ "blur",
779
+ "keydown",
780
+ "keyup",
781
+ "keypress",
782
+ "mousedown",
783
+ "mouseup"
784
+ ]);
785
+ function escapeTemplate(s) {
786
+ return s.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${");
787
+ }
788
+ function capitalize(s) {
789
+ return s.charAt(0).toUpperCase() + s.slice(1);
790
+ }
791
+ var Lowerer = class {
792
+ constructor(holes, used, sourceFile, positionAt) {
793
+ this.holes = holes;
794
+ this.used = used;
795
+ this.sourceFile = sourceFile;
796
+ this.positionAt = positionAt;
797
+ }
798
+ /**
799
+ * Where a tag is written, for the mark a component node carries.
800
+ *
801
+ * The parser reports offsets, and they are offsets into the file: the pieces it was given
802
+ * carry the positions the front-end recorded. Only built when the host asked for source
803
+ * locations, which is the only time either of these is set.
804
+ */
805
+ tagAt(node) {
806
+ const start = node.loc?.start;
807
+ if (!this.sourceFile || !this.positionAt || start == null) return void 0;
808
+ const { line, column } = this.positionAt(start);
809
+ return { file: this.sourceFile, line, column };
810
+ }
811
+ hole(i) {
812
+ return this.holes[i] ?? { code: "undefined", reactive: false };
813
+ }
814
+ /** Emit a nested IR subtree to code (for `Show` fallback / `For` children). */
815
+ emit(node) {
816
+ const { code, imports, templates } = imperativeBackend.emit(node, {});
817
+ for (const s of imports) this.used.add(s);
818
+ return inlineTemplates(code, templates);
819
+ }
820
+ // --- content ------------------------------------------------------------
821
+ lowerRoot(children) {
822
+ const nodes = this.lowerChildren(children);
823
+ if (nodes.length === 1) return nodes[0];
824
+ return { kind: "fragment", children: nodes };
825
+ }
826
+ /** Lower a sibling list, handling text-drop and if/else/each restructuring. */
827
+ lowerChildren(children) {
828
+ const out = [];
829
+ for (let i = 0; i < children.length; i++) {
830
+ const child = children[i];
831
+ if (child.kind === "Element" || child.kind === "Component") {
832
+ const ifDir = child.attributes.find((a) => a.kind === "IfDirective");
833
+ if (ifDir && ifDir.kind === "IfDirective") {
834
+ let elseIdx = i + 1;
835
+ if (elseIdx < children.length && this.isBlankText(children[elseIdx])) elseIdx++;
836
+ const elseNode = children[elseIdx];
837
+ const hasElse = elseNode && (elseNode.kind === "Element" || elseNode.kind === "Component") && elseNode.attributes.some((a) => a.kind === "ElseDirective");
838
+ out.push(this.lowerIf(child, ifDir.hole, hasElse ? elseNode : null));
839
+ if (hasElse) i = elseIdx;
840
+ continue;
841
+ }
842
+ if (child.attributes.some((a) => a.kind === "EachDirective")) {
843
+ out.push(this.lowerEach(child));
844
+ continue;
845
+ }
846
+ }
847
+ const node = this.lowerNode(child);
848
+ if (node) out.push(node);
849
+ }
850
+ return out;
851
+ }
852
+ isBlankText(n) {
853
+ return n.kind === "Text" && !n.raw && cleanTemplateText(n.value) === "";
854
+ }
855
+ lowerNode(node) {
856
+ switch (node.kind) {
857
+ case "Text": {
858
+ if (node.raw) return { kind: "text", value: node.value };
859
+ const cleaned = cleanTemplateText(node.value);
860
+ return cleaned ? { kind: "text", value: cleaned } : null;
861
+ }
862
+ case "Comment":
863
+ return null;
864
+ // dropped, like JSX comments
865
+ case "Expression": {
866
+ const h = this.hole(node.hole);
867
+ return { kind: "expr", code: h.code, reactive: h.reactive, ...h.at ? { at: h.at } : {} };
868
+ }
869
+ case "Fragment":
870
+ return { kind: "fragment", children: this.lowerChildren(node.children) };
871
+ case "Element":
872
+ return this.lowerElement(node);
873
+ case "Component":
874
+ return this.lowerComponent(node);
875
+ default:
876
+ return null;
877
+ }
878
+ }
879
+ lowerElement(el) {
880
+ const isAttr = el.attributes.find((a) => a.kind === "Attribute" && a.name === "is");
881
+ if (el.tag === "component" && isAttr && isAttr.value && isAttr.value.kind === "hole") {
882
+ const rest = el.attributes.filter((a) => a !== isAttr);
883
+ const node = this.lowerComponent({ ...el, kind: "Component", tag: "Dynamic", tagHole: null, attributes: rest });
884
+ node.props.unshift({ name: "component", kind: "attr", expr: `() => ${paren(this.hole(isAttr.value.hole).code, "arrowBody")}` });
885
+ return node;
886
+ }
887
+ const at = this.tagAt(el);
888
+ return {
889
+ kind: "element",
890
+ tag: el.tag,
891
+ svg: el.namespace === "svg",
892
+ props: this.lowerAttributes(el.attributes),
893
+ children: this.lowerChildren(el.children),
894
+ static: false,
895
+ ...at ? { at } : {}
896
+ };
897
+ }
898
+ lowerComponent(el) {
899
+ const name = el.tagHole != null ? this.hole(el.tagHole).code : el.tag;
900
+ const props = this.lowerAttributes(el.attributes);
901
+ const { slots, rest } = this.partitionSlots(el.children);
902
+ for (const [slotName, nodes] of slots) {
903
+ const ir = nodes.length === 1 ? nodes[0] : { kind: "fragment", children: nodes };
904
+ const slotProp = {
905
+ name: slotName,
906
+ kind: "attr",
907
+ expr: this.emit(ir),
908
+ jsxElement: true
909
+ };
910
+ const clash = props.findIndex((p) => p.name === slotName);
911
+ if (clash >= 0) props[clash] = slotProp;
912
+ else props.push(slotProp);
913
+ }
914
+ const loadAttr = el.attributes.find((a) => a.kind === "LoadDirective");
915
+ const load = loadAttr ? parseLoadDirective(`load:${loadAttr.strategy}`, loadAttr.modifier) : void 0;
916
+ const bindAt = props.find((p) => p.at && p.reactive)?.at;
917
+ const at = this.tagAt(el);
918
+ return {
919
+ kind: "component",
920
+ name,
921
+ props,
922
+ children: this.lowerChildren(rest),
923
+ ...at ? { at } : {},
924
+ ...bindAt ? { bindAt } : {},
925
+ ...load ? { load } : {}
926
+ };
927
+ }
928
+ /** Split a component's children into named slots (`slot="x"`) and the rest. */
929
+ partitionSlots(children) {
930
+ const slots = /* @__PURE__ */ new Map();
931
+ const rest = [];
932
+ for (const child of children) {
933
+ if (child.kind === "Element" || child.kind === "Component") {
934
+ const slot = child.attributes.find(
935
+ (a) => a.kind === "Attribute" && a.name === "slot"
936
+ );
937
+ if (slot && slot.value && slot.value.kind === "static") {
938
+ const stripped = { ...child, attributes: child.attributes.filter((a) => a !== slot) };
939
+ const ir = stripped.kind === "Element" ? this.lowerElement(stripped) : this.lowerComponent(stripped);
940
+ const bucket = slots.get(slot.value.value) ?? [];
941
+ bucket.push(ir);
942
+ slots.set(slot.value.value, bucket);
943
+ continue;
944
+ }
945
+ }
946
+ rest.push(child);
947
+ }
948
+ return { slots, rest };
949
+ }
950
+ // --- control-flow sugar -------------------------------------------------
951
+ /** `<el if=${cond}>…</el>` (+ optional `<el else>`) → `<Show when fallback>`. */
952
+ lowerIf(el, condHole, elseEl) {
953
+ const cond = this.hole(condHole);
954
+ const props = [
955
+ { name: "when", kind: "attr", expr: cond.code, reactive: cond.reactive, ...cond.at ? { at: cond.at } : {} }
956
+ ];
957
+ if (elseEl) {
958
+ const elseIR = this.stripAndLower(elseEl, (a) => a.kind === "ElseDirective");
959
+ props.push({ name: "fallback", kind: "attr", expr: this.emit(elseIR), jsxElement: true });
960
+ }
961
+ const child = this.stripAndLower(el, (a) => a.kind === "IfDirective");
962
+ const at = this.tagAt(el);
963
+ return { kind: "component", name: "Show", props, children: [child], ...at ? { at } : {}, ...cond.at ? { bindAt: cond.at } : {} };
964
+ }
965
+ /** `<el each=${items} key?>${item => …}</el>` → `<For each>{item => <el>…</el>}</For>`. */
966
+ lowerEach(el) {
967
+ const eachDir = el.attributes.find((a) => a.kind === "EachDirective");
968
+ if (!eachDir || eachDir.kind !== "EachDirective") return this.lowerNode(el);
969
+ const each = this.hole(eachDir.hole);
970
+ const props = [{ name: "each", kind: "attr", expr: each.code, reactive: each.reactive, ...each.at ? { at: each.at } : {} }];
971
+ if (eachDir.key) {
972
+ const by = "static" in eachDir.key ? `(item) => item[${JSON.stringify(eachDir.key.static)}]` : this.hole(eachDir.key.hole).code;
973
+ props.push({ name: "by", kind: "attr", expr: by });
974
+ }
975
+ const arrow = this.itemArrow(el);
976
+ let childrenCode;
977
+ if (arrow) {
978
+ const bodyIR = { kind: "expr", code: arrow.body, reactive: arrow.bodyReactive };
979
+ const repeated = this.rebuildWithChildren(el, [bodyIR]);
980
+ childrenCode = `(${arrow.params.join(", ")}) => ${paren(this.emit(repeated), "arrowBody")}`;
981
+ } else {
982
+ const repeated = this.stripAndLower(el, (a) => a.kind === "EachDirective");
983
+ childrenCode = `() => ${paren(this.emit(repeated), "arrowBody")}`;
984
+ }
985
+ const children = [{ kind: "expr", code: childrenCode, reactive: false }];
986
+ const at = this.tagAt(el);
987
+ return { kind: "component", name: "For", props, children, ...at ? { at } : {}, ...each.at ? { bindAt: each.at } : {} };
988
+ }
989
+ /** The single `${item => expr}` child arrow, if that's the element's content. */
990
+ itemArrow(el) {
991
+ const kids = el.children.filter((c) => !this.isBlankText(c));
992
+ if (kids.length !== 1 || kids[0].kind !== "Expression") return null;
993
+ return this.hole(kids[0].hole).arrow ?? null;
994
+ }
995
+ /** Lower an element to IR, dropping the directive attribute matched by `drop`. */
996
+ stripAndLower(el, drop) {
997
+ const clone = { ...el, attributes: el.attributes.filter((a) => !drop(a)) };
998
+ return clone.kind === "Element" ? this.lowerElement(clone) : this.lowerComponent(clone);
999
+ }
1000
+ /** Same element (minus each/key) but with explicit IR children. */
1001
+ rebuildWithChildren(el, children) {
1002
+ const props = this.lowerAttributes(
1003
+ el.attributes.filter((a) => a.kind !== "EachDirective")
1004
+ );
1005
+ if (el.kind === "Element") {
1006
+ const at = this.tagAt(el);
1007
+ return {
1008
+ kind: "element",
1009
+ tag: el.tag,
1010
+ svg: el.namespace === "svg",
1011
+ props,
1012
+ children,
1013
+ static: false,
1014
+ ...at ? { at } : {}
1015
+ };
1016
+ }
1017
+ return { kind: "component", name: el.tag, props, children };
1018
+ }
1019
+ // --- attributes ---------------------------------------------------------
1020
+ lowerAttributes(attrs) {
1021
+ const props = [];
1022
+ const classEntries = [];
1023
+ let classReactive = false;
1024
+ let classAt;
1025
+ const styleEntries = [];
1026
+ let styleReactive = false;
1027
+ let styleAt;
1028
+ const usePairs = [];
1029
+ for (const a of attrs) {
1030
+ switch (a.kind) {
1031
+ case "IfDirective":
1032
+ case "EachDirective":
1033
+ case "ElseDirective":
1034
+ break;
1035
+ // handled as control-flow at the parent level
1036
+ case "Attribute":
1037
+ props.push(this.plainAttr(a));
1038
+ break;
1039
+ case "PropertyBinding":
1040
+ props.push({
1041
+ name: a.name,
1042
+ kind: "prop",
1043
+ expr: this.hole(a.hole).code,
1044
+ reactive: this.hole(a.hole).reactive,
1045
+ ...this.hole(a.hole).at ? { at: this.hole(a.hole).at } : {}
1046
+ });
1047
+ break;
1048
+ case "EventBinding":
1049
+ props.push(this.eventProp(a));
1050
+ break;
1051
+ case "RefBinding":
1052
+ props.push({
1053
+ name: "ref",
1054
+ kind: "ref",
1055
+ expr: this.hole(a.hole).code,
1056
+ reactive: this.hole(a.hole).reactive,
1057
+ // Which variable ends up holding the element, and where it was written.
1058
+ ...this.hole(a.hole).at ? { at: this.hole(a.hole).at } : {}
1059
+ });
1060
+ break;
1061
+ case "Spread":
1062
+ props.push({ name: "", kind: "spread", expr: this.hole(a.hole).code });
1063
+ break;
1064
+ case "ClassDirective": {
1065
+ const h = this.hole(a.hole);
1066
+ classEntries.push(`${JSON.stringify(a.name)}: ${h.code}`);
1067
+ classReactive = classReactive || h.reactive;
1068
+ classAt ??= h.at;
1069
+ break;
1070
+ }
1071
+ case "StyleDirective": {
1072
+ const h = this.hole(a.hole);
1073
+ styleEntries.push(`${JSON.stringify(a.name)}: ${h.code}`);
1074
+ styleReactive = styleReactive || h.reactive;
1075
+ styleAt ??= h.at;
1076
+ break;
1077
+ }
1078
+ case "BindDirective":
1079
+ props.push(...this.bindProps(a.name, this.hole(a.hole)));
1080
+ break;
1081
+ case "UseDirective": {
1082
+ const dir = a.name ?? (a.hole != null ? this.hole(a.hole).code : null);
1083
+ if (!dir) break;
1084
+ usePairs.push(a.name != null && a.hole != null ? `[${dir}, () => ${paren(this.hole(a.hole).code, "arrowBody")}]` : `[${dir}]`);
1085
+ break;
1086
+ }
1087
+ }
1088
+ }
1089
+ if (classEntries.length > 0) {
1090
+ props.push({
1091
+ name: "classList",
1092
+ kind: "attr",
1093
+ expr: `{ ${classEntries.join(", ")} }`,
1094
+ reactive: classReactive,
1095
+ ...classAt ? { at: classAt } : {}
1096
+ });
1097
+ }
1098
+ if (styleEntries.length > 0) {
1099
+ props.push({
1100
+ name: "style",
1101
+ kind: "attr",
1102
+ expr: `{ ${styleEntries.join(", ")} }`,
1103
+ reactive: styleReactive,
1104
+ ...styleAt ? { at: styleAt } : {}
1105
+ });
1106
+ }
1107
+ if (usePairs.length > 0) {
1108
+ props.push({ name: "use", kind: "attr", expr: `[${usePairs.join(", ")}]` });
1109
+ }
1110
+ return props;
1111
+ }
1112
+ /**
1113
+ * Lower an event binding. Plain `@click`/`onClick` (no modifiers) stays a
1114
+ * DELEGATED handler (unchanged, byte-identical with JSX). `on:click` or any
1115
+ * modifier (`.capture`/`.once`/`.passive`/`.prevent`/`.stop`/`.self`) emits a
1116
+ * NATIVE `on:name` prop the runtime attaches via addEventListener.
1117
+ */
1118
+ eventProp(a) {
1119
+ const dom = a.name.toLowerCase();
1120
+ const handler = this.hole(a.hole).code;
1121
+ const native = a.syntax === "colon" || a.modifiers.length > 0;
1122
+ if (!native) {
1123
+ return {
1124
+ name: "on" + capitalize(a.name),
1125
+ kind: "event",
1126
+ event: { name: dom, delegated: DELEGATED.has(dom) },
1127
+ expr: handler
1128
+ };
1129
+ }
1130
+ const wrapped = this.wrapHandler(handler, a.modifiers);
1131
+ const options = this.eventOptions(a.modifiers);
1132
+ const value = options ? `[${wrapped}, ${options}]` : wrapped;
1133
+ return { name: "on:" + dom, kind: "attr", expr: value };
1134
+ }
1135
+ /** Wrap a handler for `.prevent`/`.stop`/`.self` (no wrap when none apply). */
1136
+ wrapHandler(handler, mods) {
1137
+ const guard = mods.includes("self") ? "if (e.target !== e.currentTarget) return; " : "";
1138
+ const pre = [];
1139
+ if (mods.includes("prevent")) pre.push("e.preventDefault();");
1140
+ if (mods.includes("stop")) pre.push("e.stopPropagation();");
1141
+ if (!guard && pre.length === 0) return handler;
1142
+ return `(e) => { ${guard}${pre.join(" ")} return (${handler})(e); }`;
1143
+ }
1144
+ /** addEventListener options object from `.capture`/`.once`/`.passive`, or null. */
1145
+ eventOptions(mods) {
1146
+ const opts = [];
1147
+ if (mods.includes("capture")) opts.push("capture: true");
1148
+ if (mods.includes("once")) opts.push("once: true");
1149
+ if (mods.includes("passive")) opts.push("passive: true");
1150
+ return opts.length ? `{ ${opts.join(", ")} }` : null;
1151
+ }
1152
+ /** `bind:value=${sig}` → `value={read()}` + `onInput={e => write(e…value)}`. */
1153
+ bindProps(prop, h) {
1154
+ const sigCode = h.code;
1155
+ const checked = prop === "checked";
1156
+ const evt = checked ? "change" : "input";
1157
+ const accessor = checked ? "checked" : "value";
1158
+ this.used.add("bindPair");
1159
+ const sig = `bindPair(${sigCode})`;
1160
+ return [
1161
+ {
1162
+ name: prop,
1163
+ kind: "attr",
1164
+ expr: `${sig}[0]()`,
1165
+ reactive: true,
1166
+ directive: `bind:${prop}`,
1167
+ ...h.at ? { at: h.at } : {}
1168
+ },
1169
+ {
1170
+ name: "on" + capitalize(evt),
1171
+ kind: "event",
1172
+ event: { name: evt, delegated: DELEGATED.has(evt) },
1173
+ // delegated handler: `target` is the bound element (currentTarget is the root)
1174
+ expr: `(e) => ${sig}[1](e.target.${accessor})`
1175
+ }
1176
+ ];
1177
+ }
1178
+ /** A plain attribute (incl. lit `?bool`, mixed values) — old `mkProp` behavior. */
1179
+ plainAttr(a) {
1180
+ const v = a.value;
1181
+ let name = a.name;
1182
+ if (a.name === "class") {
1183
+ name = v && v.kind === "hole" && this.hole(v.hole).object ? "classList" : "className";
1184
+ } else if (a.name === "html") {
1185
+ name = "innerHTML";
1186
+ }
1187
+ const kind = "attr";
1188
+ const base = { name, kind };
1189
+ if (v == null) {
1190
+ base.literal = true;
1191
+ return base;
1192
+ }
1193
+ if (v.kind === "static") {
1194
+ base.literal = v.value;
1195
+ return base;
1196
+ }
1197
+ if (v.kind === "hole") {
1198
+ const h = this.hole(v.hole);
1199
+ base.expr = h.code;
1200
+ base.reactive = h.reactive;
1201
+ if (h.at) base.at = h.at;
1202
+ return base;
1203
+ }
1204
+ let reactive = false;
1205
+ let at;
1206
+ const body = v.parts.map((p) => {
1207
+ if ("text" in p) return escapeTemplate(p.text);
1208
+ const h = this.hole(p.hole);
1209
+ reactive = reactive || h.reactive;
1210
+ at ??= h.at;
1211
+ return "${" + h.code + "}";
1212
+ }).join("");
1213
+ base.expr = "`" + body + "`";
1214
+ base.reactive = reactive;
1215
+ if (at) base.at = at;
1216
+ return base;
1217
+ }
1218
+ };
1219
+ function lowerTemplate(pieces, holes, used, opts = {}) {
1220
+ const { root } = parseTemplate(pieces, { svg: opts.svg });
1221
+ return new Lowerer(holes, used, opts.sourceFile, opts.positionAt).lowerRoot(root.children);
1222
+ }
1223
+
1224
+ // src/frontend/babel/lower-template.ts
1225
+ var generate = _generate.default ?? _generate;
1226
+ function gen(node) {
1227
+ return generate(node, { concise: true }).code;
1228
+ }
1229
+ function bindHole(expr, used, onNested) {
1230
+ const hole = {
1231
+ code: genExpr(expr, used, onNested),
1232
+ reactive: isReactiveExpr(expr)
1233
+ };
1234
+ if (t.isArrowFunctionExpression(expr) && !t.isBlockStatement(expr.body)) {
1235
+ const body = expr.body;
1236
+ hole.arrow = {
1237
+ params: expr.params.map((p) => gen(p)),
1238
+ body: genExpr(body, used, onNested),
1239
+ bodyReactive: isReactiveExpr(body)
1240
+ };
1241
+ }
1242
+ if (t.isObjectExpression(expr)) hole.object = true;
1243
+ return hole;
1244
+ }
1245
+ function lowerLitTemplate(node, used, opts = {}) {
1246
+ const quasi = node.quasi;
1247
+ const holes = quasi.expressions.map((e) => bindHole(e, used, opts.onNested));
1248
+ return lowerTemplate(buildPieces(quasi), holes, used, opts);
1249
+ }
1250
+ function buildPieces(quasi) {
1251
+ const pieces = [];
1252
+ quasi.quasis.forEach((q, i) => {
1253
+ const text = q.value.cooked ?? q.value.raw;
1254
+ pieces.push({ kind: "static", text, start: q.start ?? 0 });
1255
+ if (i < quasi.expressions.length) {
1256
+ const e = quasi.expressions[i];
1257
+ pieces.push({ kind: "hole", index: i, start: e.start ?? 0, end: e.end ?? 0 });
1258
+ }
1259
+ });
1260
+ return pieces;
1261
+ }
1262
+
1263
+ // src/optimize/analyze-static.ts
1264
+ function propReason(prop) {
1265
+ switch (prop.kind) {
1266
+ case "event":
1267
+ return "event";
1268
+ case "ref":
1269
+ return "ref";
1270
+ case "spread":
1271
+ return "spread";
1272
+ case "class":
1273
+ case "style":
1274
+ return "class-or-style-directive";
1275
+ case "attr":
1276
+ case "prop":
1277
+ if (prop.reactive) return "reactive-prop";
1278
+ if (prop.expr !== void 0) return "expression-prop";
1279
+ return void 0;
1280
+ /* c8 ignore next 2 */
1281
+ default:
1282
+ return "expression-prop";
1283
+ }
1284
+ }
1285
+ function analyzeStatic(root) {
1286
+ const staticElements = [];
1287
+ const reasons = /* @__PURE__ */ new Map();
1288
+ const visit = (node) => {
1289
+ switch (node.kind) {
1290
+ case "text":
1291
+ return true;
1292
+ case "expr":
1293
+ return false;
1294
+ case "component":
1295
+ case "control":
1296
+ for (const child of node.children) visit(child);
1297
+ return false;
1298
+ case "fragment":
1299
+ for (const child of node.children) visit(child);
1300
+ return false;
1301
+ case "element": {
1302
+ let childrenStatic = true;
1303
+ for (const child of node.children) {
1304
+ if (!visit(child)) childrenStatic = false;
1305
+ }
1306
+ let reason;
1307
+ for (const prop of node.props) {
1308
+ reason = propReason(prop);
1309
+ if (reason) break;
1310
+ }
1311
+ if (!reason && !childrenStatic) {
1312
+ reason = childReason(node);
1313
+ }
1314
+ node.static = !reason;
1315
+ if (reason) reasons.set(node, reason);
1316
+ else staticElements.push(node);
1317
+ return node.static;
1318
+ }
1319
+ /* c8 ignore next 2 */
1320
+ default:
1321
+ return false;
1322
+ }
1323
+ };
1324
+ for (const node of Array.isArray(root) ? root : [root]) visit(node);
1325
+ return { staticElements, reasons };
1326
+ }
1327
+ function childReason(node) {
1328
+ for (const child of node.children) {
1329
+ if (child.kind === "expr") return "expression-child";
1330
+ if (child.kind === "component") return "component-child";
1331
+ if (child.kind === "control") return "control-child";
1332
+ if (child.kind === "element" && !child.static) return "expression-child";
1333
+ if (child.kind === "fragment") return "expression-child";
1334
+ }
1335
+ return "expression-child";
1336
+ }
1337
+
1338
+ // src/frontend/babel/build-ir-lit.ts
1339
+ function buildIRFromLit(node, used = /* @__PURE__ */ new Set(), opts = {}) {
1340
+ const ir = lowerLitTemplate(node, used, opts);
1341
+ analyzeStatic(ir);
1342
+ return ir;
1343
+ }
1344
+
1345
+ // src/analyze/reactive-expr.ts
1346
+ var STABLE_MEMBER = "children";
1347
+ function isReactiveShape(shape) {
1348
+ switch (shape.kind) {
1349
+ case "call":
1350
+ return true;
1351
+ case "member":
1352
+ return shape.property !== STABLE_MEMBER;
1353
+ case "compound":
1354
+ return shape.parts.some(isReactiveShape);
1355
+ case "opaque":
1356
+ return false;
1357
+ }
1358
+ }
1359
+
1360
+ // src/analyze/expr-shape.ts
1361
+ var CALL = /* @__PURE__ */ new Set(["CallExpression", "OptionalCallExpression"]);
1362
+ var MEMBER = /* @__PURE__ */ new Set(["MemberExpression", "OptionalMemberExpression"]);
1363
+ function shapeOf(node) {
1364
+ if (!node) return { kind: "opaque" };
1365
+ if (CALL.has(node.type)) return { kind: "call" };
1366
+ if (MEMBER.has(node.type)) {
1367
+ const property = node.property;
1368
+ const computed = node.computed === true;
1369
+ return {
1370
+ kind: "member",
1371
+ property: !computed && property?.type === "Identifier" ? property.name : null
1372
+ };
1373
+ }
1374
+ if (node.type === "ConditionalExpression") {
1375
+ return { kind: "compound", parts: [node.test, node.consequent, node.alternate].map(part) };
1376
+ }
1377
+ if (node.type === "LogicalExpression" || node.type === "BinaryExpression") {
1378
+ return { kind: "compound", parts: [node.left, node.right].map(part) };
1379
+ }
1380
+ if (node.type === "TemplateLiteral") {
1381
+ return { kind: "compound", parts: node.expressions.map(part) };
1382
+ }
1383
+ if (node.type === "ObjectExpression") {
1384
+ const props = node.properties.filter(
1385
+ (p) => (p.type === "ObjectProperty" || p.type === "Property") && p.computed !== true
1386
+ );
1387
+ return { kind: "compound", parts: props.map((p) => part(p.value)) };
1388
+ }
1389
+ if (node.type === "ArrayExpression") {
1390
+ const items = node.elements.filter(
1391
+ (e) => e != null && e.type !== "SpreadElement"
1392
+ );
1393
+ return { kind: "compound", parts: items.map(part) };
1394
+ }
1395
+ return { kind: "opaque" };
1396
+ }
1397
+ var part = (n) => shapeOf(n);
1398
+
1399
+ // src/lower/jsx.ts
1400
+ var SVG_TAGS = /* @__PURE__ */ new Set([
1401
+ "svg",
1402
+ "path",
1403
+ "circle",
1404
+ "rect",
1405
+ "line",
1406
+ "polygon",
1407
+ "polyline",
1408
+ "ellipse",
1409
+ "g",
1410
+ "defs",
1411
+ "clipPath",
1412
+ "text"
1413
+ ]);
1414
+ var EVENT_RE = /^on[A-Z]/;
1415
+ var DELEGATED2 = /* @__PURE__ */ new Set([
1416
+ "click",
1417
+ "dblclick",
1418
+ "input",
1419
+ "change",
1420
+ "submit",
1421
+ "focus",
1422
+ "blur",
1423
+ "keydown",
1424
+ "keyup",
1425
+ "keypress",
1426
+ "mousedown",
1427
+ "mouseup"
1428
+ ]);
1429
+ var isReactive = (node) => isReactiveShape(shapeOf(node));
1430
+ var posOf = (node, ctx) => {
1431
+ if (!ctx.sourceFile) return void 0;
1432
+ const at = node.loc?.start;
1433
+ return at ? { line: at.line, column: at.column } : void 0;
1434
+ };
1435
+ function literalOf(node) {
1436
+ if (node.type === "StringLiteral" || node.type === "NumericLiteral" || node.type === "BooleanLiteral") {
1437
+ return node.value;
1438
+ }
1439
+ if (node.type === "Literal" && (typeof node.value === "string" || typeof node.value === "number" || typeof node.value === "boolean")) {
1440
+ return node.value;
1441
+ }
1442
+ return void 0;
1443
+ }
1444
+ var isString = (node) => !!node && typeof literalOf(node) === "string";
1445
+ function tagInfo(name, ctx) {
1446
+ if (name.type === "JSXIdentifier") {
1447
+ return { tag: name.name, component: name.name[0] !== name.name[0].toLowerCase() };
1448
+ }
1449
+ if (name.type === "JSXMemberExpression") return { tag: ctx.code(name), component: true };
1450
+ if (name.type === "JSXNamespacedName") {
1451
+ return { tag: `${name.namespace.name}:${name.name.name}`, component: false };
1452
+ }
1453
+ return { tag: "div", component: false };
1454
+ }
1455
+ function attrName(name) {
1456
+ if (name.type === "JSXIdentifier") return name.name === "class" ? "className" : name.name;
1457
+ if (name.type === "JSXNamespacedName") return `${name.namespace.name}:${name.name.name}`;
1458
+ return "unknown";
1459
+ }
1460
+ function buildAttr(attr, ctx) {
1461
+ const name = attrName(attr.name);
1462
+ const isEvent = EVENT_RE.test(name);
1463
+ const isHandler = isEvent || name.startsWith("on:") || name === "ref";
1464
+ const kind = isEvent ? "event" : "attr";
1465
+ const base = { name, kind };
1466
+ if (isEvent) {
1467
+ const evt = name.slice(2).toLowerCase();
1468
+ base.event = { name: evt, delegated: DELEGATED2.has(evt) };
1469
+ }
1470
+ const v = attr.value;
1471
+ if (v == null) {
1472
+ base.literal = true;
1473
+ base.at = posOf(attr, ctx);
1474
+ return base;
1475
+ }
1476
+ if (isString(v)) {
1477
+ base.literal = literalOf(v);
1478
+ base.at = posOf(v, ctx);
1479
+ return base;
1480
+ }
1481
+ if (v.type === "JSXExpressionContainer" && v.expression?.type !== "JSXEmptyExpression") {
1482
+ const expr = v.expression;
1483
+ const literal = literalOf(expr);
1484
+ if (literal !== void 0) {
1485
+ base.literal = literal;
1486
+ base.at = posOf(expr, ctx);
1487
+ return base;
1488
+ }
1489
+ base.expr = ctx.code(expr);
1490
+ base.reactive = isHandler ? false : isReactive(expr);
1491
+ base.at = posOf(expr, ctx);
1492
+ if (expr.type === "JSXElement" || expr.type === "JSXFragment") base.jsxElement = true;
1493
+ return base;
1494
+ }
1495
+ base.literal = true;
1496
+ return base;
1497
+ }
1498
+ function attrExprCode(attr, ctx) {
1499
+ const v = attr.value;
1500
+ if (v == null) return null;
1501
+ if (isString(v)) return JSON.stringify(literalOf(v));
1502
+ if (v.type === "JSXExpressionContainer" && v.expression?.type !== "JSXEmptyExpression") {
1503
+ return ctx.code(v.expression);
1504
+ }
1505
+ return null;
1506
+ }
1507
+ function buildProps(attrs, ctx) {
1508
+ const props = [];
1509
+ const usePairs = [];
1510
+ for (const a of attrs) {
1511
+ if (a.type === "JSXSpreadAttribute") {
1512
+ props.push({ name: "", kind: "spread", expr: ctx.code(a.argument) });
1513
+ continue;
1514
+ }
1515
+ if (a.type !== "JSXAttribute") continue;
1516
+ if (isLoadDirective(attrName(a.name))) continue;
1517
+ const ns = a.name.type === "JSXNamespacedName" ? a.name.namespace.name : null;
1518
+ if (ns === "use") {
1519
+ const dir = a.name.name.name;
1520
+ ctx.used.add(dir);
1521
+ const opts = attrExprCode(a, ctx);
1522
+ usePairs.push(opts != null ? `[${dir}, () => ${paren(opts, "arrowBody")}]` : `[${dir}]`);
1523
+ continue;
1524
+ }
1525
+ if (ns === "oncapture") {
1526
+ const evt = a.name.name.name.toLowerCase();
1527
+ const h = attrExprCode(a, ctx) ?? "undefined";
1528
+ props.push({ name: "on:" + evt, kind: "attr", expr: `[${h}, { capture: true }]` });
1529
+ continue;
1530
+ }
1531
+ props.push(buildAttr(a, ctx));
1532
+ }
1533
+ if (usePairs.length > 0) props.push({ name: "use", kind: "attr", expr: `[${usePairs.join(", ")}]` });
1534
+ return props;
1535
+ }
1536
+ function buildChildren(children, ctx) {
1537
+ const out = [];
1538
+ for (const child of children) {
1539
+ if (child.type === "JSXText") {
1540
+ const text = cleanTemplateText(child.value);
1541
+ if (text) out.push({ kind: "text", value: text });
1542
+ } else if (child.type === "JSXExpressionContainer") {
1543
+ if (child.expression?.type !== "JSXEmptyExpression") {
1544
+ const expr = child.expression;
1545
+ const reactive = isReactive(expr);
1546
+ out.push({
1547
+ kind: "expr",
1548
+ code: ctx.code(expr),
1549
+ reactive,
1550
+ ...reactive ? { at: posOf(expr, ctx) } : {}
1551
+ });
1552
+ }
1553
+ } else if (child.type === "JSXElement" || child.type === "JSXFragment") {
1554
+ out.push(buildNode(child, ctx));
1555
+ } else if (child.type === "JSXSpreadChild") {
1556
+ out.push({ kind: "expr", code: ctx.code(child.expression), reactive: false });
1557
+ }
1558
+ }
1559
+ return out;
1560
+ }
1561
+ function readLoad(attrs) {
1562
+ for (const a of attrs) {
1563
+ if (a.type !== "JSXAttribute") continue;
1564
+ const name = attrName(a.name);
1565
+ if (!isLoadDirective(name)) continue;
1566
+ if (a.value && !isString(a.value)) {
1567
+ throw new LoadDirectiveError(
1568
+ `'${name}' needs a literal value, not an expression — the strategy is compile-time.`
1569
+ );
1570
+ }
1571
+ return parseLoadDirective(name, a.value ? literalOf(a.value) : null);
1572
+ }
1573
+ return void 0;
1574
+ }
1575
+ function buildNode(node, ctx) {
1576
+ if (node.type === "JSXFragment") {
1577
+ return { kind: "fragment", children: buildChildren(node.children, ctx) };
1578
+ }
1579
+ const { tag, component } = tagInfo(node.openingElement.name, ctx);
1580
+ const props = buildProps(node.openingElement.attributes, ctx);
1581
+ const children = buildChildren(node.children, ctx);
1582
+ const at = ctx.sourceFile && node.loc?.start ? { file: ctx.sourceFile, line: node.loc.start.line, column: node.loc.start.column } : void 0;
1583
+ if (component) {
1584
+ const load = readLoad(node.openingElement.attributes);
1585
+ return { kind: "component", name: tag, props, children, ...load ? { load } : {}, ...at ? { at } : {} };
1586
+ }
1587
+ return { kind: "element", tag, svg: SVG_TAGS.has(tag), props, children, static: false, ...at ? { at } : {} };
1588
+ }
1589
+ function buildJsxIR(node, ctx) {
1590
+ const ir = buildNode(node, ctx);
1591
+ analyzeStatic(ir);
1592
+ return ir;
1593
+ }
1594
+
1595
+ // src/frontend/babel/build-ir.ts
1596
+ var generate2 = _generate2.default ?? _generate2;
1597
+ function gen2(node) {
1598
+ return generate2(node, { concise: true }).code;
1599
+ }
1600
+ function transformNestedJSX(node, used, onNested) {
1601
+ const clone = t2.cloneNode(node, true);
1602
+ const file = t2.file(t2.program([t2.expressionStatement(clone)]));
1603
+ let changed = false;
1604
+ const emitInto = (path, code, imports) => {
1605
+ for (const s of imports) used.add(s);
1606
+ path.replaceWith(template.expression(code, { placeholderPattern: false, plugins: ["typescript"] })());
1607
+ path.skip();
1608
+ changed = true;
1609
+ };
1610
+ traverse(file, {
1611
+ "JSXElement|JSXFragment"(path) {
1612
+ const jsx = path.node;
1613
+ const nestedIR = buildIR(jsx, used, onNested);
1614
+ onNested?.(nestedIR);
1615
+ const { code, imports, templates } = imperativeBackend.emit(nestedIR, {});
1616
+ emitInto(path, inlineTemplates(code, templates), imports);
1617
+ },
1618
+ // Nested lit templates compose: ${cond ? html`…` : html`…`},
1619
+ // ${list.map(x => html`<li>${x}</li>`)}. Compile them the same way.
1620
+ TaggedTemplateExpression(path) {
1621
+ const tag = path.node.tag;
1622
+ if (!t2.isIdentifier(tag) || tag.name !== "html" && tag.name !== "svg") return;
1623
+ const ir = buildIRFromLit(path.node, used, { svg: tag.name === "svg", onNested });
1624
+ onNested?.(ir);
1625
+ const { code, imports, templates } = imperativeBackend.emit(ir, {});
1626
+ emitInto(path, inlineTemplates(code, templates), imports);
1627
+ }
1628
+ });
1629
+ return changed ? file.program.body[0].expression : node;
1630
+ }
1631
+ function genExpr(node, used, onNested) {
1632
+ return gen2(transformNestedJSX(node, used, onNested));
1633
+ }
1634
+ function isReactiveExpr(node) {
1635
+ return isReactiveShape(shapeOf(node));
1636
+ }
1637
+ function buildIR(node, used = /* @__PURE__ */ new Set(), onNested) {
1638
+ const ir = buildJsxIR(node, {
1639
+ code: (n) => (
1640
+ // A member-expression tag (`<ns.Foo/>`) is not an Expression, so it cannot go
1641
+ // through the nested-JSX compile — it only ever needs printing.
1642
+ n.type === "JSXMemberExpression" ? gen2(n) : genExpr(n, used, onNested)
1643
+ ),
1644
+ used
1645
+ });
1646
+ return ir;
1647
+ }
1648
+
1649
+ // src/frontend/babel/plugin.ts
1650
+ var CORE_ONLY_CONTROL_FLOW = new Set(CORE_CONTROL_FLOW);
1651
+ var ROUTER_COMPONENTS2 = new Set(ROUTER_COMPONENTS);
1652
+ var plugin_default = declare((api, options = {}) => {
1653
+ api.assertVersion(7);
1654
+ const {
1655
+ delegateEvents = true,
1656
+ signalModule = "@fluixi/dom",
1657
+ controlFlowModule = "@fluixi/dom",
1658
+ routerModule = "@fluixi/core/router",
1659
+ reactiveModule = "@fluixi/reactive/signal",
1660
+ templateClone = true,
1661
+ partialTemplates = true,
1662
+ // `both` by default: JSX and html`` are compiled out of the box, so
1663
+ // `fluixi()` needs no `format` option. Injected imports are deduped, so a
1664
+ // file mixing the two styles won't redeclare a binding.
1665
+ format = "both",
1666
+ litTag = "html",
1667
+ resolve: resolveRules = []
1668
+ } = options;
1669
+ const componentResolver = createComponentResolver(resolveRules);
1670
+ const compileLit = format === "lit" || format === "both";
1671
+ const pluginState = {
1672
+ irImports: /* @__PURE__ */ new Set(),
1673
+ libModule: "@fluixi/core",
1674
+ controlFlowModule,
1675
+ routerModule,
1676
+ templateClone,
1677
+ partialTemplates,
1678
+ hasJSX: false,
1679
+ hasLitHTML: false,
1680
+ needsControlFlowImport: false,
1681
+ needsCreateMemo: false,
1682
+ controlFlowComponents: /* @__PURE__ */ new Set(),
1683
+ resolvedComponents: /* @__PURE__ */ new Map(),
1684
+ deferredComponents: /* @__PURE__ */ new Map(),
1685
+ componentResolver,
1686
+ delegatedEvents: /* @__PURE__ */ new Set(),
1687
+ staticTemplates: /* @__PURE__ */ new Map(),
1688
+ staticCounter: 0
1689
+ };
1690
+ return {
1691
+ name: "@fluixi/babel-plugin-jsx",
1692
+ manipulateOptions(opts, parserOpts) {
1693
+ parserOpts.plugins.push("jsx", "typescript");
1694
+ },
1695
+ pre(state) {
1696
+ Object.assign(state, pluginState);
1697
+ },
1698
+ visitor: {
1699
+ Program: {
1700
+ enter(path, state) {
1701
+ Object.assign(state, {
1702
+ hasJSX: false,
1703
+ hasLitHTML: false,
1704
+ hasLitIR: false,
1705
+ needsControlFlowImport: false,
1706
+ needsCreateMemo: false,
1707
+ controlFlowComponents: /* @__PURE__ */ new Set(),
1708
+ resolvedComponents: /* @__PURE__ */ new Map(),
1709
+ deferredComponents: /* @__PURE__ */ new Map(),
1710
+ componentResolver,
1711
+ delegatedEvents: /* @__PURE__ */ new Set(),
1712
+ staticTemplates: /* @__PURE__ */ new Map(),
1713
+ staticCounter: 0,
1714
+ libModule: "@fluixi/core",
1715
+ controlFlowModule,
1716
+ routerModule,
1717
+ templateClone,
1718
+ partialTemplates,
1719
+ irImports: /* @__PURE__ */ new Set(),
1720
+ needsCreateNativeElement: false,
1721
+ needsInsert: false,
1722
+ needsSpread: false,
1723
+ needsCreateComponent: false,
1724
+ needsMergeProps: false
1725
+ });
1726
+ },
1727
+ exit(path, state) {
1728
+ const imports = [];
1729
+ if (state.hasJSX || state.hasLitIR) {
1730
+ if (state.irImports.size > 0) {
1731
+ const CF = /* @__PURE__ */ new Set([
1732
+ "Show",
1733
+ "For",
1734
+ "Index",
1735
+ "Switch",
1736
+ "Match",
1737
+ "Dynamic",
1738
+ "ErrorBoundary",
1739
+ "Portal",
1740
+ "Suspense"
1741
+ ]);
1742
+ const REACTIVE = /* @__PURE__ */ new Set([
1743
+ "createMemo",
1744
+ "createEffect",
1745
+ "createRenderEffect",
1746
+ "createRoot",
1747
+ "createSignal",
1748
+ "onCleanup",
1749
+ "batch",
1750
+ "untrack"
1751
+ ]);
1752
+ const all = Array.from(state.irImports);
1753
+ const spec = (n) => t3.importSpecifier(t3.identifier(n), t3.identifier(n));
1754
+ const unbound = (s) => !path.scope.hasBinding(s);
1755
+ const reactive = all.filter((s) => REACTIVE.has(s) && unbound(s));
1756
+ const core = all.filter((s) => !CF.has(s) && !REACTIVE.has(s) && unbound(s));
1757
+ const cf = all.filter((s) => CF.has(s) && unbound(s));
1758
+ if (reactive.length > 0) {
1759
+ imports.push(
1760
+ t3.importDeclaration(reactive.map(spec), t3.stringLiteral(reactiveModule))
1761
+ );
1762
+ }
1763
+ if (core.length > 0) {
1764
+ imports.push(
1765
+ t3.importDeclaration(core.map(spec), t3.stringLiteral(signalModule))
1766
+ );
1767
+ }
1768
+ if (cf.length > 0) {
1769
+ imports.push(
1770
+ t3.importDeclaration(cf.map(spec), t3.stringLiteral(controlFlowModule))
1771
+ );
1772
+ }
1773
+ }
1774
+ if (state.needsCreateMemo && !path.scope.hasBinding("createMemo")) {
1775
+ imports.push(
1776
+ t3.importDeclaration(
1777
+ [t3.importSpecifier(t3.identifier("createMemo"), t3.identifier("createMemo"))],
1778
+ t3.stringLiteral(reactiveModule)
1779
+ )
1780
+ );
1781
+ }
1782
+ if (state.needsControlFlowImport && state.controlFlowComponents.size > 0) {
1783
+ const unbound = Array.from(state.controlFlowComponents).filter(
1784
+ (name) => !path.scope.hasBinding(name)
1785
+ );
1786
+ const coreModule = state.libModule ?? "@fluixi/core";
1787
+ const fromRouter = unbound.filter((n) => ROUTER_COMPONENTS2.has(n));
1788
+ const fromCore = unbound.filter((n) => CORE_ONLY_CONTROL_FLOW.has(n));
1789
+ const fromDom = unbound.filter(
1790
+ (n) => !CORE_ONLY_CONTROL_FLOW.has(n) && !ROUTER_COMPONENTS2.has(n)
1791
+ );
1792
+ const declFor = (names, mod) => t3.importDeclaration(
1793
+ names.map((name) => t3.importSpecifier(t3.identifier(name), t3.identifier(name))),
1794
+ t3.stringLiteral(mod)
1795
+ );
1796
+ if (fromDom.length > 0) imports.push(declFor(fromDom, controlFlowModule));
1797
+ if (fromCore.length > 0) imports.push(declFor(fromCore, coreModule));
1798
+ if (fromRouter.length > 0) imports.push(declFor(fromRouter, routerModule));
1799
+ }
1800
+ const deferredDecls = [];
1801
+ if (state.deferredComponents.size > 0) {
1802
+ for (const [local, entry] of state.deferredComponents) {
1803
+ if (path.scope.hasBinding(local)) continue;
1804
+ deferredDecls.push(
1805
+ t3.variableDeclaration("const", [
1806
+ t3.variableDeclarator(
1807
+ t3.identifier(local),
1808
+ t3.callExpression(t3.identifier("deferred"), [
1809
+ t3.arrowFunctionExpression(
1810
+ [],
1811
+ t3.callExpression(t3.import(), [t3.stringLiteral(entry.module)])
1812
+ ),
1813
+ t3.objectExpression([
1814
+ t3.objectProperty(
1815
+ t3.identifier("strategy"),
1816
+ strategyLiteral(entry.strategy)
1817
+ ),
1818
+ t3.objectProperty(
1819
+ t3.identifier("export"),
1820
+ t3.stringLiteral(entry.export)
1821
+ )
1822
+ ])
1823
+ ])
1824
+ )
1825
+ ])
1826
+ );
1827
+ }
1828
+ if (deferredDecls.length > 0 && !path.scope.hasBinding("deferred")) {
1829
+ imports.push(
1830
+ t3.importDeclaration(
1831
+ [t3.importSpecifier(t3.identifier("deferred"), t3.identifier("deferred"))],
1832
+ t3.stringLiteral(state.libModule ?? "@fluixi/core")
1833
+ )
1834
+ );
1835
+ }
1836
+ }
1837
+ if (state.resolvedComponents.size > 0) {
1838
+ const byModule = /* @__PURE__ */ new Map();
1839
+ for (const [local, resolved] of state.resolvedComponents) {
1840
+ if (path.scope.hasBinding(local)) continue;
1841
+ const list = byModule.get(resolved.module) ?? [];
1842
+ list.push({ local, exported: resolved.export });
1843
+ byModule.set(resolved.module, list);
1844
+ }
1845
+ for (const [mod, entries] of byModule) {
1846
+ imports.push(
1847
+ t3.importDeclaration(
1848
+ entries.map(
1849
+ ({ local, exported }) => exported === "default" ? t3.importDefaultSpecifier(t3.identifier(local)) : t3.importSpecifier(t3.identifier(local), t3.identifier(exported))
1850
+ ),
1851
+ t3.stringLiteral(mod)
1852
+ )
1853
+ );
1854
+ }
1855
+ }
1856
+ if (delegateEvents && state.delegatedEvents.size > 0) {
1857
+ imports.push(
1858
+ t3.importDeclaration(
1859
+ [
1860
+ t3.importSpecifier(
1861
+ t3.identifier("delegateEvents"),
1862
+ t3.identifier("delegateEvents")
1863
+ )
1864
+ ],
1865
+ t3.stringLiteral(signalModule)
1866
+ )
1867
+ );
1868
+ const eventsArray = t3.arrayExpression(
1869
+ Array.from(state.delegatedEvents).map(
1870
+ (event) => t3.stringLiteral(event)
1871
+ )
1872
+ );
1873
+ const delegateCall = t3.expressionStatement(
1874
+ t3.callExpression(t3.identifier("delegateEvents"), [eventsArray])
1875
+ );
1876
+ path.node.body.unshift(delegateCall);
1877
+ }
1878
+ if (deferredDecls.length > 0) {
1879
+ path.node.body.unshift(...deferredDecls);
1880
+ }
1881
+ if (state.staticTemplates.size > 0) {
1882
+ const decls = [];
1883
+ for (const [key, name] of state.staticTemplates) {
1884
+ const svg = key.startsWith("svg:");
1885
+ const html = svg ? key.slice(4) : key;
1886
+ decls.push(
1887
+ t3.variableDeclaration("const", [
1888
+ t3.variableDeclarator(
1889
+ t3.identifier(name),
1890
+ // Just the HTML. Parsing is deferred to `templateNode`, which
1891
+ // knows whether this is a server render, a hydration or a fresh
1892
+ // client render — a module-scope `createTemplate` would touch
1893
+ // `document` at import time and break SSR outright.
1894
+ t3.stringLiteral(html)
1895
+ )
1896
+ ])
1897
+ );
1898
+ }
1899
+ path.node.body.unshift(...decls);
1900
+ }
1901
+ }
1902
+ if (imports.length > 0) {
1903
+ path.node.body.unshift(...dedupeImports(imports));
1904
+ }
1905
+ }
1906
+ },
1907
+ // Both JSX forms take the one path: build IR, run the imperative backend,
1908
+ // splice the emitted code back in. It handles the whole subtree, so nothing
1909
+ // below this node needs its own visitor.
1910
+ JSXElement(path, state) {
1911
+ state.hasJSX = true;
1912
+ path.replaceWith(emitViaIR(path.node, state));
1913
+ },
1914
+ JSXFragment(path, state) {
1915
+ state.hasJSX = true;
1916
+ path.replaceWith(emitViaIR(path.node, state));
1917
+ },
1918
+ TaggedTemplateExpression(path, state) {
1919
+ if (compileLit && t3.isIdentifier(path.node.tag) && (path.node.tag.name === litTag || path.node.tag.name === "svg")) {
1920
+ path.replaceWith(emitLitViaIR(path.node, state));
1921
+ }
1922
+ }
1923
+ }
1924
+ };
1925
+ });
1926
+ function nestedHook(state) {
1927
+ return (ir) => {
1928
+ resolveComponentSources(ir, {
1929
+ resolver: state.componentResolver,
1930
+ modules: {
1931
+ controlFlowModule: state.controlFlowModule,
1932
+ coreModule: state.libModule,
1933
+ routerModule: state.routerModule
1934
+ },
1935
+ strategyFor: (node) => node.load
1936
+ });
1937
+ collapseStrategies(ir);
1938
+ collectRuntimeNeeds(ir, state);
1939
+ };
1940
+ }
1941
+ function strategyLiteral(strategy) {
1942
+ const props = [
1943
+ t3.objectProperty(t3.identifier("kind"), t3.stringLiteral(strategy.kind))
1944
+ ];
1945
+ if (strategy.kind === "visible" && strategy.rootMargin) {
1946
+ props.push(t3.objectProperty(t3.identifier("rootMargin"), t3.stringLiteral(strategy.rootMargin)));
1947
+ }
1948
+ if (strategy.kind === "interaction") {
1949
+ props.push(
1950
+ t3.objectProperty(
1951
+ t3.identifier("events"),
1952
+ t3.arrayExpression(strategy.events.map((e) => t3.stringLiteral(e)))
1953
+ )
1954
+ );
1955
+ }
1956
+ if (strategy.kind === "media") {
1957
+ props.push(t3.objectProperty(t3.identifier("query"), t3.stringLiteral(strategy.query)));
1958
+ }
1959
+ return t3.objectExpression(props);
1960
+ }
1961
+ function adoptTemplates(code, templates, state) {
1962
+ if (!templates || templates.length === 0) return code;
1963
+ const rename = /* @__PURE__ */ new Map();
1964
+ for (const tpl of templates) {
1965
+ const key = `${tpl.svg ? "svg:" : ""}${tpl.html}`;
1966
+ let name = state.staticTemplates.get(key);
1967
+ if (!name) {
1968
+ name = `_tmpl$${state.staticTemplates.size}`;
1969
+ state.staticTemplates.set(key, name);
1970
+ }
1971
+ rename.set(tpl.id, name);
1972
+ }
1973
+ return code.replace(/_tmpl\$\d+/g, (id) => rename.get(id) ?? id);
1974
+ }
1975
+ function emitViaIR(node, state) {
1976
+ const used = /* @__PURE__ */ new Set();
1977
+ const ir = buildIR(node, used, nestedHook(state));
1978
+ resolveComponentSources(ir, {
1979
+ resolver: state.componentResolver,
1980
+ modules: {
1981
+ controlFlowModule: state.controlFlowModule,
1982
+ coreModule: state.libModule,
1983
+ routerModule: state.routerModule
1984
+ },
1985
+ strategyFor: (n) => n.load
1986
+ });
1987
+ collapseStrategies(ir);
1988
+ const { code, imports, templates } = imperativeBackend.emit(ir, { templateClone: state.templateClone, partialTemplates: state.partialTemplates });
1989
+ for (const s of imports) used.add(s);
1990
+ for (const s of used) state.irImports.add(s);
1991
+ collectRuntimeNeeds(ir, state);
1992
+ const adopted = adoptTemplates(code, templates, state);
1993
+ return template2.expression(adopted, { placeholderPattern: false, plugins: ["typescript"] })();
1994
+ }
1995
+ function dedupeImports(imports) {
1996
+ const byModule = /* @__PURE__ */ new Map();
1997
+ const out = [];
1998
+ for (const decl of imports) {
1999
+ const source = decl.source.value;
2000
+ const allNamed = decl.specifiers.every((s) => t3.isImportSpecifier(s));
2001
+ if (!allNamed) {
2002
+ out.push(decl);
2003
+ continue;
2004
+ }
2005
+ const existing = byModule.get(source);
2006
+ if (!existing) {
2007
+ const names = new Set(
2008
+ decl.specifiers.map((s) => s.local.name)
2009
+ );
2010
+ byModule.set(source, { decl, names });
2011
+ out.push(decl);
2012
+ continue;
2013
+ }
2014
+ for (const s of decl.specifiers) {
2015
+ if (!existing.names.has(s.local.name)) {
2016
+ existing.names.add(s.local.name);
2017
+ existing.decl.specifiers.push(s);
2018
+ }
2019
+ }
2020
+ }
2021
+ return out;
2022
+ }
2023
+ function emitLitViaIR(node, state) {
2024
+ const used = /* @__PURE__ */ new Set();
2025
+ const svg = t3.isIdentifier(node.tag) && node.tag.name === "svg";
2026
+ const ir = buildIRFromLit(node, used, { svg, onNested: nestedHook(state) });
2027
+ resolveComponentSources(ir, {
2028
+ resolver: state.componentResolver,
2029
+ modules: {
2030
+ controlFlowModule: state.controlFlowModule,
2031
+ coreModule: state.libModule,
2032
+ routerModule: state.routerModule
2033
+ },
2034
+ strategyFor: (node2) => node2.load
2035
+ });
2036
+ collapseStrategies(ir);
2037
+ const { code, imports, templates } = imperativeBackend.emit(ir, { templateClone: state.templateClone, partialTemplates: state.partialTemplates });
2038
+ for (const s of imports) used.add(s);
2039
+ for (const s of used) state.irImports.add(s);
2040
+ collectRuntimeNeeds(ir, state);
2041
+ state.hasLitIR = true;
2042
+ const expression = template2.expression(adoptTemplates(code, templates, state), {
2043
+ placeholderPattern: false,
2044
+ plugins: ["typescript"]
2045
+ })();
2046
+ inheritLocation(expression, node);
2047
+ return expression;
2048
+ }
2049
+ function inheritLocation(target, source) {
2050
+ if (!source.loc) return;
2051
+ const seen = /* @__PURE__ */ new Set();
2052
+ const walk2 = (node) => {
2053
+ if (seen.has(node)) return;
2054
+ seen.add(node);
2055
+ if (!node.loc) {
2056
+ node.loc = source.loc;
2057
+ node.start = source.start;
2058
+ node.end = source.end;
2059
+ }
2060
+ for (const key of t3.VISITOR_KEYS[node.type] ?? []) {
2061
+ const child = node[key];
2062
+ if (Array.isArray(child)) {
2063
+ for (const c of child) if (c && typeof c === "object" && "type" in c) walk2(c);
2064
+ } else if (child && typeof child === "object" && "type" in child) {
2065
+ walk2(child);
2066
+ }
2067
+ }
2068
+ };
2069
+ walk2(target);
2070
+ }
2071
+ function collectRuntimeNeeds(node, state) {
2072
+ if (node.kind === "component" && node.source) {
2073
+ if (node.source.origin === "builtin") {
2074
+ state.controlFlowComponents.add(node.name);
2075
+ state.needsControlFlowImport = true;
2076
+ } else if (isDeferred(node.source.loading) && !state.resolvedComponents.has(node.name)) {
2077
+ state.deferredComponents.set(node.name, {
2078
+ module: node.source.module,
2079
+ export: node.source.export,
2080
+ strategy: node.source.loading
2081
+ });
2082
+ } else {
2083
+ state.deferredComponents.delete(node.name);
2084
+ state.resolvedComponents.set(node.name, {
2085
+ module: node.source.module,
2086
+ export: node.source.export
2087
+ });
2088
+ }
2089
+ }
2090
+ if (node.kind === "element" || node.kind === "component" || node.kind === "control") {
2091
+ if ("props" in node) {
2092
+ for (const p of node.props) {
2093
+ if (p.kind === "event" && p.event?.delegated) state.delegatedEvents.add(p.event.name);
2094
+ }
2095
+ }
2096
+ }
2097
+ if ("children" in node && node.children) {
2098
+ for (const c of node.children) collectRuntimeNeeds(c, state);
2099
+ }
2100
+ }
2101
+ export {
2102
+ plugin_default as default
2103
+ };