@fluixi/compiler 1.0.0-alpha.73 → 1.0.0-alpha.75

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 (109) hide show
  1. package/README.md +41 -16
  2. package/dist/analyze/expr-shape.cjs +1 -0
  3. package/dist/analyze/expr-shape.d.ts +15 -0
  4. package/dist/analyze/expr-shape.d.ts.map +1 -0
  5. package/dist/analyze/expr-shape.js +37 -0
  6. package/dist/analyze/expr-shape.mjs +1 -0
  7. package/dist/analyze/reactive-expr.cjs +1 -0
  8. package/dist/analyze/reactive-expr.d.ts +39 -0
  9. package/dist/analyze/reactive-expr.d.ts.map +1 -0
  10. package/dist/analyze/reactive-expr.js +31 -0
  11. package/dist/analyze/reactive-expr.mjs +1 -0
  12. package/dist/babel-GXO3KAVI.mjs +1 -0
  13. package/dist/chunk-3SAEGOMQ.mjs +1 -0
  14. package/dist/chunk-E2PW2OZU.mjs +1 -0
  15. package/dist/chunk-IBRM4W7I.mjs +10 -0
  16. package/dist/chunk-OHHZCYIQ.mjs +1 -0
  17. package/dist/chunk-TIE4XNAM.mjs +1 -0
  18. package/dist/frontend/babel/build-ir-lit.cjs +1 -1
  19. package/dist/frontend/babel/build-ir-lit.d.ts +1 -0
  20. package/dist/frontend/babel/build-ir-lit.d.ts.map +1 -1
  21. package/dist/frontend/babel/build-ir-lit.mjs +1 -1
  22. package/dist/frontend/babel/build-ir.cjs +1 -1
  23. package/dist/frontend/babel/build-ir.d.ts +13 -11
  24. package/dist/frontend/babel/build-ir.d.ts.map +1 -1
  25. package/dist/frontend/babel/build-ir.js +27 -217
  26. package/dist/frontend/babel/build-ir.mjs +1 -1
  27. package/dist/frontend/babel/index.cjs +1 -2
  28. package/dist/frontend/babel/index.mjs +1 -2
  29. package/dist/frontend/babel/lower-template.cjs +1 -1
  30. package/dist/frontend/babel/lower-template.d.ts +12 -9
  31. package/dist/frontend/babel/lower-template.d.ts.map +1 -1
  32. package/dist/frontend/babel/lower-template.js +33 -445
  33. package/dist/frontend/babel/lower-template.mjs +1 -1
  34. package/dist/frontend/babel/plugin.cjs +1 -2
  35. package/dist/frontend/babel/plugin.d.ts +24 -85
  36. package/dist/frontend/babel/plugin.d.ts.map +1 -1
  37. package/dist/frontend/babel/plugin.js +52 -1285
  38. package/dist/frontend/babel/plugin.mjs +1 -2
  39. package/dist/frontend/babel/server-functions.cjs +1 -1
  40. package/dist/frontend/babel/server-functions.d.ts.map +1 -1
  41. package/dist/frontend/babel/server-functions.js +2 -9
  42. package/dist/frontend/babel/server-functions.mjs +1 -1
  43. package/dist/index.cjs +8 -8
  44. package/dist/index.d.ts +4 -0
  45. package/dist/index.d.ts.map +1 -1
  46. package/dist/index.js +8 -0
  47. package/dist/index.mjs +9 -9
  48. package/dist/integrations.cjs +15 -19
  49. package/dist/integrations.d.ts +39 -151
  50. package/dist/integrations.d.ts.map +1 -1
  51. package/dist/integrations.js +79 -491
  52. package/dist/integrations.mjs +11 -17
  53. package/dist/lower/compile-template.cjs +1 -0
  54. package/dist/lower/compile-template.d.ts +57 -0
  55. package/dist/lower/compile-template.d.ts.map +1 -0
  56. package/dist/lower/compile-template.js +72 -0
  57. package/dist/lower/compile-template.mjs +1 -0
  58. package/dist/lower/jsx.cjs +1 -0
  59. package/dist/lower/jsx.d.ts +24 -0
  60. package/dist/lower/jsx.d.ts.map +1 -0
  61. package/dist/lower/jsx.js +193 -0
  62. package/dist/lower/jsx.mjs +1 -0
  63. package/dist/lower/template.cjs +1 -0
  64. package/dist/lower/template.d.ts +41 -0
  65. package/dist/lower/template.d.ts.map +1 -0
  66. package/dist/lower/template.js +445 -0
  67. package/dist/lower/template.mjs +1 -0
  68. package/dist/lower/text.cjs +1 -0
  69. package/dist/lower/text.d.ts +11 -0
  70. package/dist/lower/text.d.ts.map +1 -0
  71. package/dist/lower/text.js +31 -0
  72. package/dist/lower/text.mjs +1 -0
  73. package/dist/options.cjs +1 -1
  74. package/dist/options.d.ts +0 -2
  75. package/dist/options.d.ts.map +1 -1
  76. package/dist/options.js +0 -1
  77. package/dist/options.mjs +1 -1
  78. package/dist/server-fns-6QM243HC.mjs +2 -0
  79. package/dist/server-functions-E3LKCZ4R.mjs +1 -0
  80. package/dist/transform/bindings.cjs +1 -0
  81. package/dist/transform/bindings.d.ts +17 -0
  82. package/dist/transform/bindings.d.ts.map +1 -0
  83. package/dist/transform/bindings.js +69 -0
  84. package/dist/transform/bindings.mjs +1 -0
  85. package/dist/transform/index.cjs +3 -0
  86. package/dist/transform/index.d.ts +12 -0
  87. package/dist/transform/index.d.ts.map +1 -0
  88. package/dist/transform/index.js +10 -0
  89. package/dist/transform/index.mjs +12 -0
  90. package/dist/transform/server-fn-id.cjs +1 -0
  91. package/dist/transform/server-fn-id.d.ts +10 -0
  92. package/dist/transform/server-fn-id.d.ts.map +1 -0
  93. package/dist/transform/server-fn-id.js +18 -0
  94. package/dist/transform/server-fn-id.mjs +1 -0
  95. package/dist/transform/server-fns.cjs +2 -0
  96. package/dist/transform/server-fns.d.ts +13 -0
  97. package/dist/transform/server-fns.d.ts.map +1 -0
  98. package/dist/transform/server-fns.js +94 -0
  99. package/dist/transform/server-fns.mjs +11 -0
  100. package/dist/transform/templates.cjs +3 -0
  101. package/dist/transform/templates.d.ts +26 -0
  102. package/dist/transform/templates.d.ts.map +1 -0
  103. package/dist/transform/templates.js +347 -0
  104. package/dist/transform/templates.mjs +12 -0
  105. package/dist/transform-PJX2GNSV.mjs +3 -0
  106. package/dist/tsconfig.lib.tsbuildinfo +1 -1
  107. package/package.json +30 -8
  108. package/dist/babel-E7EQLX36.mjs +0 -2
  109. package/dist/chunk-EF6V4GTD.mjs +0 -1
@@ -0,0 +1 @@
1
+ var b={kind:"eager"},w=["pointerdown","focusin","keydown"],h=new Set(["eager","idle","visible","interaction","media","never"]),c=class extends Error{};function d(e){return e.startsWith("load:")}function E(e,t){let n=e.slice(5);if(!h.has(n))throw new c(`Unknown load strategy 'load:${n}'. Expected one of ${[...h].join(", ")}.`);switch(n){case"eager":return b;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?J(t):[...w]};case"media":if(!t)throw new c(`'load:media' needs a query, e.g. load:media="(min-width: 1024px)".`);return{kind:"media",query:t};default:throw new c(`Unhandled load strategy '${n}'.`)}}function J(e){let t=e.split(/[\s,]+/).map(n=>n.trim()).filter(Boolean);if(t.length===0)throw new c("'load:interaction' was given no event names.");return t}var L="children";function f(e){switch(e.kind){case"call":return!0;case"member":return e.property!==L;case"compound":return e.parts.some(f);case"opaque":return!1}}var C=new Set(["CallExpression","OptionalCallExpression"]),X=new Set(["MemberExpression","OptionalMemberExpression"]);function m(e){if(!e)return{kind:"opaque"};if(C.has(e.type))return{kind:"call"};if(X.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(l)}:e.type==="LogicalExpression"||e.type==="BinaryExpression"?{kind:"compound",parts:[e.left,e.right].map(l)}:e.type==="TemplateLiteral"?{kind:"compound",parts:e.expressions.map(l)}:e.type==="ObjectExpression"?{kind:"compound",parts:e.properties.filter(n=>(n.type==="ObjectProperty"||n.type==="Property")&&n.computed!==!0).map(n=>l(n.value))}:e.type==="ArrayExpression"?{kind:"compound",parts:e.elements.filter(n=>n!=null&&n.type!=="SpreadElement").map(l)}:{kind:"opaque"}}var l=e=>m(e);function A(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 k(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 s of r.children)o(s);return!1;case"fragment":for(let s of r.children)o(s);return!1;case"element":{let s=!0;for(let a of r.children)o(a)||(s=!1);let i;for(let a of r.props)if(i=A(a),i)break;return!i&&!s&&(i=$(r)),r.static=!i,i?n.set(r,i):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 $(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 v(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 s=t[r].replace(/\t/g," ");r!==0&&(s=s.replace(/^ +/,"")),r!==t.length-1&&(s=s.replace(/ +$/,"")),s&&(r!==n&&(s+=" "),o+=s)}return o}var T=new Set(["svg","path","circle","rect","line","polygon","polyline","ellipse","g","defs","clipPath","text"]),D=/^on[A-Z]/,P=new Set(["click","dblclick","input","change","submit","focus","blur","keydown","keyup","keypress","mousedown","mouseup"]),N=e=>f(m(e));function u(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 y=e=>!!e&&typeof u(e)=="string";function M(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 x(e){return e.type==="JSXIdentifier"?e.name==="class"?"className":e.name:e.type==="JSXNamespacedName"?`${e.namespace.name}:${e.name.name}`:"unknown"}function j(e,t){let n=x(e.name),o=D.test(n),r=o||n.startsWith("on:")||n==="ref",i={name:n,kind:o?"event":"attr"};if(o){let p=n.slice(2).toLowerCase();i.event={name:p,delegated:P.has(p)}}let a=e.value;if(a==null)return i.literal=!0,i;if(y(a))return i.literal=u(a),i;if(a.type==="JSXExpressionContainer"&&a.expression?.type!=="JSXEmptyExpression"){let p=a.expression,g=u(p);return g!==void 0?(i.literal=g,i):(i.expr=t.code(p),i.reactive=r?!1:N(p),(p.type==="JSXElement"||p.type==="JSXFragment")&&(i.jsxElement=!0),i)}return i.literal=!0,i}function S(e,t){let n=e.value;return n==null?null:y(n)?JSON.stringify(u(n)):n.type==="JSXExpressionContainer"&&n.expression?.type!=="JSXEmptyExpression"?t.code(n.expression):null}function q(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"||d(x(r.name)))continue;let s=r.name.type==="JSXNamespacedName"?r.name.namespace.name:null;if(s==="use"){let i=r.name.name.name;t.used.add(i);let a=S(r,t);o.push(a!=null?`[${i}, () => (${a})]`:`[${i}]`);continue}if(s==="oncapture"){let i=r.name.name.name.toLowerCase(),a=S(r,t)??"undefined";n.push({name:"on:"+i,kind:"attr",expr:`[${a}, { capture: true }]`});continue}n.push(j(r,t))}return o.length>0&&n.push({name:"use",kind:"attr",expr:`[${o.join(", ")}]`}),n}function R(e,t){let n=[];for(let o of e)if(o.type==="JSXText"){let r=v(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:N(r)})}}else o.type==="JSXElement"||o.type==="JSXFragment"?n.push(I(o,t)):o.type==="JSXSpreadChild"&&n.push({kind:"expr",code:t.code(o.expression),reactive:!1});return n}function O(e){for(let t of e){if(t.type!=="JSXAttribute")continue;let n=x(t.name);if(d(n)){if(t.value&&!y(t.value))throw new c(`'${n}' needs a literal value, not an expression — the strategy is compile-time.`);return E(n,t.value?u(t.value):null)}}}function I(e,t){if(e.type==="JSXFragment")return{kind:"fragment",children:R(e.children,t)};let{tag:n,component:o}=M(e.openingElement.name,t),r=q(e.openingElement.attributes,t),s=R(e.children,t);if(o){let i=O(e.openingElement.attributes);return{kind:"component",name:n,props:r,children:s,...i?{load:i}:{}}}return{kind:"element",tag:n,svg:T.has(n),props:r,children:s,static:!1}}function Z(e,t){let n=I(e,t);return k(n),n}export{T as SVG_TAGS,Z as buildJsxIR};
@@ -0,0 +1 @@
1
+ "use strict";var R=Object.defineProperty;var W=Object.getOwnPropertyDescriptor;var q=Object.getOwnPropertyNames;var G=Object.prototype.hasOwnProperty;var K=(t,e)=>{for(var n in e)R(t,n,{get:e[n],enumerable:!0})},Y=(t,e,n,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of q(e))!G.call(t,i)&&i!==n&&R(t,i,{get:()=>e[i],enumerable:!(r=W(e,i))||r.enumerable});return t};var Z=t=>Y(R({},"__esModule",{value:!0}),t);var Re={};K(Re,{lowerTemplate:()=>Ne});module.exports=Z(Re);var U=require("@fluixi/template-parser");var X={kind:"eager"},Q=["pointerdown","focusin","keydown"],T=new Set(["eager","idle","visible","interaction","media","never"]),u=class extends Error{};function S(t,e){let n=t.slice(5);if(!T.has(n))throw new u(`Unknown load strategy 'load:${n}'. Expected one of ${[...T].join(", ")}.`);switch(n){case"eager":return X;case"idle":return{kind:"idle"};case"never":return{kind:"never"};case"visible":return e?{kind:"visible",rootMargin:e}:{kind:"visible"};case"interaction":return{kind:"interaction",events:e?ee(e):[...Q]};case"media":if(!e)throw new u(`'load:media' needs a query, e.g. load:media="(min-width: 1024px)".`);return{kind:"media",query:e};default:throw new u(`Unhandled load strategy '${n}'.`)}}function ee(t){let e=t.split(/[\s,]+/).map(n=>n.trim()).filter(Boolean);if(e.length===0)throw new u("'load:interaction' was given no event names.");return e}var te=new Set(["area","base","br","col","embed","hr","img","input","link","meta","param","source","track","wbr"]),C={className:"class",htmlFor:"for"},ne=new Set(["innerHTML","outerHTML","innerText","textContent","value","checked","selected","muted","defaultValue","defaultChecked","children","ref"]),re=new Set(["script","style","textarea","title"]);function $(t){return re.has(t)}function A(t){return C[t]??t}function h(t){return t.kind!=="attr"||t.expr!==void 0||t.name.includes(":")?!1:!ne.has(t.name)}function b(t){if(!t.static||$(t.tag))return!1;for(let e of t.props)if(!h(e))return!1;for(let e of t.children)if(e.kind!=="text"&&!(e.kind==="element"&&b(e)))return!1;return!0}function f(t){let e=t.props.map(oe).filter(Boolean).join(""),n=`<${t.tag}${e}>`;return te.has(t.tag)?n:`${n}${t.children.map(ie).join("")}</${t.tag}>`}function ie(t){if(t.kind==="text")return ae(t.value);if(t.kind!=="element")throw new Error(`serializeStatic: unexpected ${t.kind}`);return f(t)}function oe(t){let e=C[t.name]??t.name,n=t.literal;return n===!0||n===void 0?` ${e}`:n===!1||n===null?"":` ${e}="${se(String(n))}"`}function se(t){return t.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function ae(t){return t.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}var le="<!--fx-->",ce="<!--fx/-->";function N(t){return t.kind==="expr"||t.kind==="component"||t.kind==="control"}function de(t){return t.kind==="text"||t.kind==="element"&&P(t)}function P(t){return t.svg||$(t.tag)||!t.props.every(e=>h(e))?!1:t.children.every(e=>de(e)||N(e))}function k(t){if(N(t))return!0;let e=t.children;return e?e.some(k):!1}function L(t){for(let e=0;e<t.children.length;e++){let n=t.children[e];if(n.kind==="text"&&(n.value===""||t.children[e+1]?.kind==="text"))return!1}return t.children.every(e=>e.kind!=="element"||L(e))}function D(t){if(!P(t)||!L(t)||!t.children.some(k))return null;let e=[],n=[],r=0,i=c=>{let s=`_n$${r++}`;return e.push({ref:s,expr:c}),s};return o(t,"_el$"),{html:pe(t),tag:t.tag,steps:e,holes:n};function o(c,s){let a=-1;c.children.forEach((d,p)=>{k(d)&&(a=p)});let l=null;for(let d=0;d<=a;d++){let p=c.children[d],m=l?`${l}.nextSibling`:`${s}.firstChild`;if(N(p)){let w=i(m),y=i(`holeEnd(${w})`);n.push({parentRef:s,startRef:w,endRef:y,node:p}),l=y;continue}let v=i(m);p.kind==="element"&&k(p)&&o(p,v),l=v}}}function pe(t){return f(j(t)).split(O).join(le+ce)}function j(t){return{...t,children:t.children.map(e=>N(e)?{kind:"text",value:O}:e.kind==="element"?j(e):e)}}var O="\0fx-hole\0";var x={version:1,module:"@fluixi/dom",symbols:["createNativeElement","insert","spread","setAttribute","delegateEvents","createComponent","createMemo","untrack","Show","For","Index","Switch","Match","Dynamic","ErrorBoundary"]},we={version:2,module:"@fluixi/dom",symbols:[...x.symbols,"template","cloneTemplate","walk"]};var ue={show:"Show",for:"For",index:"Index",switch:"Switch",match:"Match",dynamic:"Dynamic",errorBoundary:"ErrorBoundary",suspense:"Suspense"};function me(t){return/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(t)}function M(t){return me(t)?t:JSON.stringify(t)}function he(t){return t.expr!==void 0?t.reactive?`() => (${t.expr})`:`(${t.expr})`:JSON.stringify(t.literal??!0)}function fe(t){return t.expr!==void 0?`(${t.expr})`:JSON.stringify(t.literal??!0)}function ge(t,e,n){let r=t.filter(s=>s.kind==="spread"),o=t.filter(s=>s.kind!=="spread").map(s=>`${M(s.name)}: ${he(s)}`);e!=null&&o.push(`children: ${e}`);let c=`{ ${o.join(", ")} }`;return r.length>0?(n.add("mergeProps"),`mergeProps(${r.map(s=>s.expr).join(", ")}, ${c})`):c}function H(t,e,n){return t.length===1?g(t[0],e,n):`[${t.map(r=>g(r,e,n)).join(", ")}]`}function _(t,e,n,r,i){r.add("createMemo"),r.add("createComponent");let o=e.filter(l=>l.kind==="spread"),s=e.filter(l=>l.kind!=="spread").map(l=>`get ${M(l.name)}() { return ${fe(l)}; }`);n.length>0&&s.push(`get children() { return ${H(n,r,i)}; }`);let a=`{ ${s.join(", ")} }`;return o.length>0&&(r.add("mergeProps"),a=`mergeProps(${o.map(l=>l.expr).join(", ")}, ${a})`),`createMemo(() => createComponent(${t}, ${a}))`}function ve(t,e){let n=A(e.name),r=e.literal;return r===!0||r===void 0?`${t}.setAttribute(${JSON.stringify(n)}, "");`:r===!1||r===null?"":`${t}.setAttribute(${JSON.stringify(n)}, ${JSON.stringify(String(r))});`}var B=!1;function g(t,e,n){switch(t.kind){case"text":return JSON.stringify(t.value);case"expr":return t.reactive?`() => (${t.code})`:`(${t.code})`;case"fragment":return t.children.length===0?"null":H(t.children,e,n);case"component":return _(t.name,t.props,t.children,e,n);case"control":{let r=ue[t.control]??t.control;return e.add(r),_(r,t.props,t.children,e,n)}case"element":{if(n&&t.static&&!t.svg&&b(t)){e.add("templateNode");let s=`_tmpl$${n.length}`;return n.push({id:s,html:f(t),tag:t.tag,svg:!1}),`templateNode(${s}, ${JSON.stringify(t.tag)})`}if(n&&B){let s=D(t);if(s){e.add("templateNode"),e.add("insert"),e.add("holeEnd"),e.add("holeContent"),e.add("holeScope");let a=`_tmpl$${n.length}`;n.push({id:a,html:s.html,tag:s.tag,svg:!1});let l=[`const _el$ = templateNode(${a}, ${JSON.stringify(s.tag)}, true);`];for(let d of s.steps)l.push(`const ${d.ref} = ${d.expr};`);for(let d of s.holes)l.push(`insert(${d.parentRef}, holeScope(${d.startRef}, () => (${g(d.node,e,n)})), ${d.endRef}, holeContent(${d.startRef}, ${d.endRef}));`);return l.push("return _el$;"),`(() => { ${l.join(" ")} })()`}}e.add("createNativeElement");let r=JSON.stringify(t.tag),i="_el$",o=[],c=t.svg?`${r}, true`:r;if(o.push(`const ${i} = createNativeElement(${c});`),t.props.length>0)if(!t.svg&&t.props.every(h))for(let s of t.props)o.push(ve(i,s));else{e.add("spread");let s=t.svg?", isSVG: true":"";o.push(`spread({ element: ${i}, props: ${ge(t.props,null,e)}${s} });`)}for(let s of t.children){e.add("insert");let a=g(s,e,n),l=s.kind==="expr"&&s.reactive||s.kind==="component"||s.kind==="control";o.push(l?`insert(${i}, ${a}, null);`:`insert(${i}, ${a});`)}return o.push(`return ${i};`),`(() => { ${o.join(" ")} })()`}}}function J(t,e){if(!e||e.length===0)return t;let n=new Map(e.map(r=>[r.id,JSON.stringify(r.html)]));return t.replace(/_tmpl\$\d+/g,r=>n.get(r)??r)}var z={name:"imperative",contract:x,emit(t,e){let n=new Set,r=e?.templateClone!==!1?[]:void 0;return B=e?.partialTemplates===!0,{code:g(t,n,r),imports:Array.from(n),templates:r}}};function E(t){let e=t.split(/\r\n|\n|\r/),n=0;for(let i=0;i<e.length;i++)/[^ \t]/.test(e[i])&&(n=i);let r="";for(let i=0;i<e.length;i++){let o=e[i].replace(/\t/g," ");i!==0&&(o=o.replace(/^ +/,"")),i!==e.length-1&&(o=o.replace(/ +$/,"")),o&&(i!==n&&(o+=" "),r+=o)}return r}var V=new Set(["click","dblclick","input","change","submit","focus","blur","keydown","keyup","keypress","mousedown","mouseup"]);function ke(t){return t.replace(/\\/g,"\\\\").replace(/`/g,"\\`").replace(/\$\{/g,"\\${")}function F(t){return t.charAt(0).toUpperCase()+t.slice(1)}var I=class{constructor(e,n){this.holes=e;this.used=n}hole(e){return this.holes[e]??{code:"undefined",reactive:!1}}emit(e){let{code:n,imports:r,templates:i}=z.emit(e,{});for(let o of r)this.used.add(o);return J(n,i)}lowerRoot(e){let n=this.lowerChildren(e);return n.length===1?n[0]:{kind:"fragment",children:n}}lowerChildren(e){let n=[];for(let r=0;r<e.length;r++){let i=e[r];if(i.kind==="Element"||i.kind==="Component"){let c=i.attributes.find(s=>s.kind==="IfDirective");if(c&&c.kind==="IfDirective"){let s=r+1;s<e.length&&this.isBlankText(e[s])&&s++;let a=e[s],l=a&&(a.kind==="Element"||a.kind==="Component")&&a.attributes.some(d=>d.kind==="ElseDirective");n.push(this.lowerIf(i,c.hole,l?a:null)),l&&(r=s);continue}if(i.attributes.some(s=>s.kind==="EachDirective")){n.push(this.lowerEach(i));continue}}let o=this.lowerNode(i);o&&n.push(o)}return n}isBlankText(e){return e.kind==="Text"&&!e.raw&&E(e.value)===""}lowerNode(e){switch(e.kind){case"Text":{if(e.raw)return{kind:"text",value:e.value};let n=E(e.value);return n?{kind:"text",value:n}:null}case"Comment":return null;case"Expression":{let n=this.hole(e.hole);return{kind:"expr",code:n.code,reactive:n.reactive}}case"Fragment":return{kind:"fragment",children:this.lowerChildren(e.children)};case"Element":return this.lowerElement(e);case"Component":return this.lowerComponent(e);default:return null}}lowerElement(e){let n=e.attributes.find(r=>r.kind==="Attribute"&&r.name==="is");if(e.tag==="component"&&n&&n.value&&n.value.kind==="hole"){let r=e.attributes.filter(o=>o!==n),i=this.lowerComponent({...e,kind:"Component",tag:"Dynamic",tagHole:null,attributes:r});return i.props.unshift({name:"component",kind:"attr",expr:`() => (${this.hole(n.value.hole).code})`}),i}return{kind:"element",tag:e.tag,svg:e.namespace==="svg",props:this.lowerAttributes(e.attributes),children:this.lowerChildren(e.children),static:!1}}lowerComponent(e){let n=e.tagHole!=null?this.hole(e.tagHole).code:e.tag,r=this.lowerAttributes(e.attributes),{slots:i,rest:o}=this.partitionSlots(e.children);for(let[a,l]of i){let d=l.length===1?l[0]:{kind:"fragment",children:l},p={name:a,kind:"attr",expr:this.emit(d),jsxElement:!0},m=r.findIndex(v=>v.name===a);m>=0?r[m]=p:r.push(p)}let c=e.attributes.find(a=>a.kind==="LoadDirective"),s=c?S(`load:${c.strategy}`,c.modifier):void 0;return{kind:"component",name:n,props:r,children:this.lowerChildren(o),...s?{load:s}:{}}}partitionSlots(e){let n=new Map,r=[];for(let i of e){if(i.kind==="Element"||i.kind==="Component"){let o=i.attributes.find(c=>c.kind==="Attribute"&&c.name==="slot");if(o&&o.value&&o.value.kind==="static"){let c={...i,attributes:i.attributes.filter(l=>l!==o)},s=c.kind==="Element"?this.lowerElement(c):this.lowerComponent(c),a=n.get(o.value.value)??[];a.push(s),n.set(o.value.value,a);continue}}r.push(i)}return{slots:n,rest:r}}lowerIf(e,n,r){let i=this.hole(n),o=[{name:"when",kind:"attr",expr:i.code,reactive:i.reactive}];if(r){let s=this.stripAndLower(r,a=>a.kind==="ElseDirective");o.push({name:"fallback",kind:"attr",expr:this.emit(s),jsxElement:!0})}let c=this.stripAndLower(e,s=>s.kind==="IfDirective");return{kind:"component",name:"Show",props:o,children:[c]}}lowerEach(e){let n=e.attributes.find(a=>a.kind==="EachDirective");if(!n||n.kind!=="EachDirective")return this.lowerNode(e);let r=this.hole(n.hole),i=[{name:"each",kind:"attr",expr:r.code,reactive:r.reactive}];if(n.key){let a="static"in n.key?`(item) => item[${JSON.stringify(n.key.static)}]`:this.hole(n.key.hole).code;i.push({name:"by",kind:"attr",expr:a})}let o=this.itemArrow(e),c;if(o){let a={kind:"expr",code:o.body,reactive:o.bodyReactive},l=this.rebuildWithChildren(e,[a]);c=`(${o.params.join(", ")}) => (${this.emit(l)})`}else{let a=this.stripAndLower(e,l=>l.kind==="EachDirective");c=`() => (${this.emit(a)})`}return{kind:"component",name:"For",props:i,children:[{kind:"expr",code:c,reactive:!1}]}}itemArrow(e){let n=e.children.filter(r=>!this.isBlankText(r));return n.length!==1||n[0].kind!=="Expression"?null:this.hole(n[0].hole).arrow??null}stripAndLower(e,n){let r={...e,attributes:e.attributes.filter(i=>!n(i))};return r.kind==="Element"?this.lowerElement(r):this.lowerComponent(r)}rebuildWithChildren(e,n){let r=this.lowerAttributes(e.attributes.filter(i=>i.kind!=="EachDirective"));return e.kind==="Element"?{kind:"element",tag:e.tag,svg:e.namespace==="svg",props:r,children:n,static:!1}:{kind:"component",name:e.tag,props:r,children:n}}lowerAttributes(e){let n=[],r=[],i=!1,o=[],c=!1,s=[];for(let a of e)switch(a.kind){case"IfDirective":case"EachDirective":case"ElseDirective":break;case"Attribute":n.push(this.plainAttr(a));break;case"PropertyBinding":n.push({name:a.name,kind:"prop",expr:this.hole(a.hole).code,reactive:this.hole(a.hole).reactive});break;case"EventBinding":n.push(this.eventProp(a));break;case"RefBinding":n.push({name:"ref",kind:"ref",expr:this.hole(a.hole).code,reactive:this.hole(a.hole).reactive});break;case"Spread":n.push({name:"",kind:"spread",expr:this.hole(a.hole).code});break;case"ClassDirective":{let l=this.hole(a.hole);r.push(`${JSON.stringify(a.name)}: ${l.code}`),i=i||l.reactive;break}case"StyleDirective":{let l=this.hole(a.hole);o.push(`${JSON.stringify(a.name)}: ${l.code}`),c=c||l.reactive;break}case"BindDirective":n.push(...this.bindProps(a.name,this.hole(a.hole).code));break;case"UseDirective":{let l=a.name??(a.hole!=null?this.hole(a.hole).code:null);if(!l)break;s.push(a.name!=null&&a.hole!=null?`[${l}, () => (${this.hole(a.hole).code})]`:`[${l}]`);break}}return r.length>0&&n.push({name:"classList",kind:"attr",expr:`{ ${r.join(", ")} }`,reactive:i}),o.length>0&&n.push({name:"style",kind:"attr",expr:`{ ${o.join(", ")} }`,reactive:c}),s.length>0&&n.push({name:"use",kind:"attr",expr:`[${s.join(", ")}]`}),n}eventProp(e){let n=e.name.toLowerCase(),r=this.hole(e.hole).code;if(!(e.syntax==="colon"||e.modifiers.length>0))return{name:"on"+F(e.name),kind:"event",event:{name:n,delegated:V.has(n)},expr:r};let o=this.wrapHandler(r,e.modifiers),c=this.eventOptions(e.modifiers),s=c?`[${o}, ${c}]`:o;return{name:"on:"+n,kind:"attr",expr:s}}wrapHandler(e,n){let r=n.includes("self")?"if (e.target !== e.currentTarget) return; ":"",i=[];return n.includes("prevent")&&i.push("e.preventDefault();"),n.includes("stop")&&i.push("e.stopPropagation();"),!r&&i.length===0?e:`(e) => { ${r}${i.join(" ")} return (${e})(e); }`}eventOptions(e){let n=[];return e.includes("capture")&&n.push("capture: true"),e.includes("once")&&n.push("once: true"),e.includes("passive")&&n.push("passive: true"),n.length?`{ ${n.join(", ")} }`:null}bindProps(e,n){let r=e==="checked",i=r?"change":"input",o=r?"checked":"value",c=`(${n})`;return[{name:e,kind:"attr",expr:`${c}[0]()`,reactive:!0},{name:"on"+F(i),kind:"event",event:{name:i,delegated:V.has(i)},expr:`(e) => ${c}[1](e.target.${o})`}]}plainAttr(e){let n=e.value,r=e.name;e.name==="class"?r=n&&n.kind==="hole"&&this.hole(n.hole).object?"classList":"className":e.name==="html"&&(r="innerHTML");let o={name:r,kind:"attr"};if(n==null)return o.literal=!0,o;if(n.kind==="static")return o.literal=n.value,o;if(n.kind==="hole"){let a=this.hole(n.hole);return o.expr=a.code,o.reactive=a.reactive,o}let c=!1,s=n.parts.map(a=>{if("text"in a)return ke(a.text);let l=this.hole(a.hole);return c=c||l.reactive,"${"+l.code+"}"}).join("");return o.expr="`"+s+"`",o.reactive=c,o}};function Ne(t,e,n,r={}){let{root:i}=(0,U.parseTemplate)(t,{svg:r.svg});return new I(e,n).lowerRoot(i.children)}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Lower a parsed Template AST (`@fluixi/template-parser`) into the host-agnostic IR.
3
+ *
4
+ * No parser in here: the `${…}` holes arrive already described as `TemplateHole`,
5
+ * since reading them means reading JavaScript and that belongs to a front-end.
6
+ *
7
+ * Pipeline: pieces → parseTemplate → Template AST → lowerTemplate → IRNode
8
+ */
9
+ import { type Piece } from '@fluixi/template-parser';
10
+ import type { IRNode } from '../ir/nodes.js';
11
+ /**
12
+ * One `${…}` slot, as the front-end describes it. Conclusions about the
13
+ * expression only — never a syntax tree, or the parser dependency creeps back.
14
+ */
15
+ export interface TemplateHole {
16
+ /** The expression source, verbatim. Anything nested inside it is already compiled. */
17
+ code: string;
18
+ /** Whether it must be wired reactively (see analyze/reactive-expr.ts). */
19
+ reactive: boolean;
20
+ /**
21
+ * Set when the hole is a single-expression arrow — `${item => …}`. `each` turns
22
+ * that into `For`'s render function, so it needs the parameters and the body
23
+ * separately rather than the arrow as written.
24
+ */
25
+ arrow?: {
26
+ params: string[];
27
+ body: string;
28
+ bodyReactive: boolean;
29
+ };
30
+ /** Whether the hole is an object literal — `class=${{…}}` lowers to classList. */
31
+ object?: boolean;
32
+ }
33
+ /**
34
+ * Lower a parsed template to IR. `pieces` are the static runs and hole slots as
35
+ * the parser wants them; `holes` describes each `${…}` in the same order. `used`
36
+ * collects the runtime symbols the emitted code imports.
37
+ */
38
+ export declare function lowerTemplate(pieces: Piece[], holes: TemplateHole[], used: Set<string>, opts?: {
39
+ svg?: boolean;
40
+ }): IRNode;
41
+ //# sourceMappingURL=template.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../../src/lower/template.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAML,KAAK,KAAK,EAGX,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,MAAM,EAAsB,MAAM,gBAAgB,CAAC;AAKjE;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,sFAAsF;IACtF,IAAI,EAAE,MAAM,CAAC;IACb,0EAA0E;IAC1E,QAAQ,EAAE,OAAO,CAAC;IAClB;;;;OAIG;IACH,KAAK,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,OAAO,CAAA;KAAE,CAAC;IAClE,kFAAkF;IAClF,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AA0bD;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,KAAK,EAAE,EACf,KAAK,EAAE,YAAY,EAAE,EACrB,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,EACjB,IAAI,GAAE;IAAE,GAAG,CAAC,EAAE,OAAO,CAAA;CAAO,GAC3B,MAAM,CAGR"}
@@ -0,0 +1,445 @@
1
+ /**
2
+ * Lower a parsed Template AST (`@fluixi/template-parser`) into the host-agnostic IR.
3
+ *
4
+ * No parser in here: the `${…}` holes arrive already described as `TemplateHole`,
5
+ * since reading them means reading JavaScript and that belongs to a front-end.
6
+ *
7
+ * Pipeline: pieces → parseTemplate → Template AST → lowerTemplate → IRNode
8
+ */
9
+ import { parseTemplate, } from '@fluixi/template-parser';
10
+ import { parseLoadDirective } from '../resolve/load-directive.js';
11
+ import { imperativeBackend, inlineTemplates } from '../codegen/backends/imperative.js';
12
+ import { cleanTemplateText } from './text.js';
13
+ const DELEGATED = new Set([
14
+ 'click', 'dblclick', 'input', 'change', 'submit', 'focus', 'blur',
15
+ 'keydown', 'keyup', 'keypress', 'mousedown', 'mouseup',
16
+ ]);
17
+ /** Escape a static text run for embedding in a template literal. */
18
+ function escapeTemplate(s) {
19
+ return s.replace(/\\/g, '\\\\').replace(/`/g, '\\`').replace(/\$\{/g, '\\${');
20
+ }
21
+ function capitalize(s) {
22
+ return s.charAt(0).toUpperCase() + s.slice(1);
23
+ }
24
+ class Lowerer {
25
+ holes;
26
+ used;
27
+ constructor(holes, used) {
28
+ this.holes = holes;
29
+ this.used = used;
30
+ }
31
+ hole(i) {
32
+ // -1 marks a recovered-from missing binding; emit a harmless undefined.
33
+ return this.holes[i] ?? { code: 'undefined', reactive: false };
34
+ }
35
+ /** Emit a nested IR subtree to code (for `Show` fallback / `For` children). */
36
+ emit(node) {
37
+ const { code, imports, templates } = imperativeBackend.emit(node, {});
38
+ for (const s of imports)
39
+ this.used.add(s);
40
+ // No module scope reachable from a nested subtree, so templates are inlined;
41
+ // `createTemplate` caches by HTML, so this is a lookup rather than a re-parse.
42
+ return inlineTemplates(code, templates);
43
+ }
44
+ // --- content ------------------------------------------------------------
45
+ lowerRoot(children) {
46
+ const nodes = this.lowerChildren(children);
47
+ if (nodes.length === 1)
48
+ return nodes[0];
49
+ return { kind: 'fragment', children: nodes };
50
+ }
51
+ /** Lower a sibling list, handling text-drop and if/else/each restructuring. */
52
+ lowerChildren(children) {
53
+ const out = [];
54
+ for (let i = 0; i < children.length; i++) {
55
+ const child = children[i];
56
+ if (child.kind === 'Element' || child.kind === 'Component') {
57
+ const ifDir = child.attributes.find((a) => a.kind === 'IfDirective');
58
+ if (ifDir && ifDir.kind === 'IfDirective') {
59
+ // Pair with a following `else` sibling (skipping a whitespace-only text).
60
+ let elseIdx = i + 1;
61
+ if (elseIdx < children.length && this.isBlankText(children[elseIdx]))
62
+ elseIdx++;
63
+ const elseNode = children[elseIdx];
64
+ const hasElse = elseNode &&
65
+ (elseNode.kind === 'Element' || elseNode.kind === 'Component') &&
66
+ elseNode.attributes.some((a) => a.kind === 'ElseDirective');
67
+ out.push(this.lowerIf(child, ifDir.hole, hasElse ? elseNode : null));
68
+ if (hasElse)
69
+ i = elseIdx;
70
+ continue;
71
+ }
72
+ if (child.attributes.some((a) => a.kind === 'EachDirective')) {
73
+ out.push(this.lowerEach(child));
74
+ continue;
75
+ }
76
+ }
77
+ const node = this.lowerNode(child);
78
+ if (node)
79
+ out.push(node);
80
+ }
81
+ return out;
82
+ }
83
+ isBlankText(n) {
84
+ return n.kind === 'Text' && !n.raw && cleanTemplateText(n.value) === '';
85
+ }
86
+ lowerNode(node) {
87
+ switch (node.kind) {
88
+ case 'Text': {
89
+ if (node.raw)
90
+ return { kind: 'text', value: node.value };
91
+ const cleaned = cleanTemplateText(node.value);
92
+ return cleaned ? { kind: 'text', value: cleaned } : null;
93
+ }
94
+ case 'Comment':
95
+ return null; // dropped, like JSX comments
96
+ case 'Expression': {
97
+ const h = this.hole(node.hole);
98
+ return { kind: 'expr', code: h.code, reactive: h.reactive };
99
+ }
100
+ case 'Fragment':
101
+ return { kind: 'fragment', children: this.lowerChildren(node.children) };
102
+ case 'Element':
103
+ return this.lowerElement(node);
104
+ case 'Component':
105
+ return this.lowerComponent(node);
106
+ default:
107
+ return null;
108
+ }
109
+ }
110
+ lowerElement(el) {
111
+ // `<component is=${C} …>…</component>` → `<Dynamic component=${C} …>` (a
112
+ // reactive component swap). Dynamic reads `component` via normalizeAccessor,
113
+ // so it must be an ACCESSOR `() => C` (a bare function would be mis-called).
114
+ const isAttr = el.attributes.find((a) => a.kind === 'Attribute' && a.name === 'is');
115
+ if (el.tag === 'component' && isAttr && isAttr.value && isAttr.value.kind === 'hole') {
116
+ const rest = el.attributes.filter((a) => a !== isAttr);
117
+ const node = this.lowerComponent({ ...el, kind: 'Component', tag: 'Dynamic', tagHole: null, attributes: rest });
118
+ node.props.unshift({ name: 'component', kind: 'attr', expr: `() => (${this.hole(isAttr.value.hole).code})` });
119
+ return node;
120
+ }
121
+ return {
122
+ kind: 'element',
123
+ tag: el.tag,
124
+ svg: el.namespace === 'svg',
125
+ props: this.lowerAttributes(el.attributes),
126
+ children: this.lowerChildren(el.children),
127
+ static: false,
128
+ };
129
+ }
130
+ lowerComponent(el) {
131
+ // `<${Comp} />`: the tag is an interpolated expression — use the hole's code
132
+ // as the component identity, so `createComponent(<expr>, …)` is emitted.
133
+ const name = el.tagHole != null ? this.hole(el.tagHole).code : el.tag;
134
+ const props = this.lowerAttributes(el.attributes);
135
+ // Named slots: a child with `slot="header"` becomes `props.header` (a lazy
136
+ // getter, like `children`); the rest stay the default `children`. This is the
137
+ // Solid convention — the component reads `props.header` / `props.children`.
138
+ const { slots, rest } = this.partitionSlots(el.children);
139
+ for (const [slotName, nodes] of slots) {
140
+ const ir = nodes.length === 1 ? nodes[0] : { kind: 'fragment', children: nodes };
141
+ const slotProp = {
142
+ name: slotName,
143
+ kind: 'attr',
144
+ expr: this.emit(ir),
145
+ jsxElement: true,
146
+ };
147
+ // A slot replaces a same-named attribute rather than joining it. `<Card header>`
148
+ // alongside `<span slot="header">` otherwise emits the key twice — valid JS where
149
+ // the last wins, but the first is dead code and esbuild warns on it. Content is
150
+ // the more specific intent, so the slot is what survives.
151
+ const clash = props.findIndex((p) => p.name === slotName);
152
+ if (clash >= 0)
153
+ props[clash] = slotProp;
154
+ else
155
+ props.push(slotProp);
156
+ }
157
+ // `load:` is a directive, not a prop: it says when this component's module is
158
+ // fetched. Parsed with the same helper the JSX path uses so the two cannot drift.
159
+ const loadAttr = el.attributes.find((a) => a.kind === 'LoadDirective');
160
+ const load = loadAttr
161
+ ? parseLoadDirective(`load:${loadAttr.strategy}`, loadAttr.modifier)
162
+ : undefined;
163
+ return {
164
+ kind: 'component',
165
+ name,
166
+ props,
167
+ children: this.lowerChildren(rest),
168
+ ...(load ? { load } : {}),
169
+ };
170
+ }
171
+ /** Split a component's children into named slots (`slot="x"`) and the rest. */
172
+ partitionSlots(children) {
173
+ const slots = new Map();
174
+ const rest = [];
175
+ for (const child of children) {
176
+ if (child.kind === 'Element' || child.kind === 'Component') {
177
+ const slot = child.attributes.find((a) => a.kind === 'Attribute' && a.name === 'slot');
178
+ if (slot && slot.value && slot.value.kind === 'static') {
179
+ const stripped = { ...child, attributes: child.attributes.filter((a) => a !== slot) };
180
+ const ir = stripped.kind === 'Element' ? this.lowerElement(stripped) : this.lowerComponent(stripped);
181
+ const bucket = slots.get(slot.value.value) ?? [];
182
+ bucket.push(ir);
183
+ slots.set(slot.value.value, bucket);
184
+ continue;
185
+ }
186
+ }
187
+ rest.push(child);
188
+ }
189
+ return { slots, rest };
190
+ }
191
+ // --- control-flow sugar -------------------------------------------------
192
+ /** `<el if=${cond}>…</el>` (+ optional `<el else>`) → `<Show when fallback>`. */
193
+ lowerIf(el, condHole, elseEl) {
194
+ const cond = this.hole(condHole);
195
+ const props = [
196
+ { name: 'when', kind: 'attr', expr: cond.code, reactive: cond.reactive },
197
+ ];
198
+ if (elseEl) {
199
+ const elseIR = this.stripAndLower(elseEl, (a) => a.kind === 'ElseDirective');
200
+ props.push({ name: 'fallback', kind: 'attr', expr: this.emit(elseIR), jsxElement: true });
201
+ }
202
+ const child = this.stripAndLower(el, (a) => a.kind === 'IfDirective');
203
+ return { kind: 'component', name: 'Show', props, children: [child] };
204
+ }
205
+ /** `<el each=${items} key?>${item => …}</el>` → `<For each>{item => <el>…</el>}</For>`. */
206
+ lowerEach(el) {
207
+ const eachDir = el.attributes.find((a) => a.kind === 'EachDirective');
208
+ if (!eachDir || eachDir.kind !== 'EachDirective')
209
+ return this.lowerNode(el);
210
+ const each = this.hole(eachDir.hole);
211
+ const props = [{ name: 'each', kind: 'attr', expr: each.code, reactive: each.reactive }];
212
+ if (eachDir.key) {
213
+ // `<For by>` wants a KEY FUNCTION, not a string. `key="id"` selects the
214
+ // `id` field: `(item) => item["id"]`; `key=${fn}` passes the function.
215
+ const by = 'static' in eachDir.key
216
+ ? `(item) => item[${JSON.stringify(eachDir.key.static)}]`
217
+ : this.hole(eachDir.key.hole).code;
218
+ props.push({ name: 'by', kind: 'attr', expr: by });
219
+ }
220
+ // The element minus its each/key, repeated per item.
221
+ const arrow = this.itemArrow(el);
222
+ let childrenCode;
223
+ if (arrow) {
224
+ const bodyIR = { kind: 'expr', code: arrow.body, reactive: arrow.bodyReactive };
225
+ const repeated = this.rebuildWithChildren(el, [bodyIR]);
226
+ childrenCode = `(${arrow.params.join(', ')}) => (${this.emit(repeated)})`;
227
+ }
228
+ else {
229
+ const repeated = this.stripAndLower(el, (a) => a.kind === 'EachDirective');
230
+ childrenCode = `() => (${this.emit(repeated)})`;
231
+ }
232
+ const children = [{ kind: 'expr', code: childrenCode, reactive: false }];
233
+ return { kind: 'component', name: 'For', props, children };
234
+ }
235
+ /** The single `${item => expr}` child arrow, if that's the element's content. */
236
+ itemArrow(el) {
237
+ const kids = el.children.filter((c) => !this.isBlankText(c));
238
+ if (kids.length !== 1 || kids[0].kind !== 'Expression')
239
+ return null;
240
+ return this.hole(kids[0].hole).arrow ?? null;
241
+ }
242
+ /** Lower an element to IR, dropping the directive attribute matched by `drop`. */
243
+ stripAndLower(el, drop) {
244
+ const clone = { ...el, attributes: el.attributes.filter((a) => !drop(a)) };
245
+ return clone.kind === 'Element' ? this.lowerElement(clone) : this.lowerComponent(clone);
246
+ }
247
+ /** Same element (minus each/key) but with explicit IR children. */
248
+ rebuildWithChildren(el, children) {
249
+ const props = this.lowerAttributes(el.attributes.filter((a) => a.kind !== 'EachDirective'));
250
+ if (el.kind === 'Element') {
251
+ return { kind: 'element', tag: el.tag, svg: el.namespace === 'svg', props, children, static: false };
252
+ }
253
+ return { kind: 'component', name: el.tag, props, children };
254
+ }
255
+ // --- attributes ---------------------------------------------------------
256
+ lowerAttributes(attrs) {
257
+ const props = [];
258
+ const classEntries = [];
259
+ let classReactive = false;
260
+ const styleEntries = [];
261
+ let styleReactive = false;
262
+ const usePairs = [];
263
+ for (const a of attrs) {
264
+ switch (a.kind) {
265
+ case 'IfDirective':
266
+ case 'EachDirective':
267
+ case 'ElseDirective':
268
+ break; // handled as control-flow at the parent level
269
+ case 'Attribute':
270
+ props.push(this.plainAttr(a));
271
+ break;
272
+ case 'PropertyBinding':
273
+ props.push({ name: a.name, kind: 'prop', expr: this.hole(a.hole).code, reactive: this.hole(a.hole).reactive });
274
+ break;
275
+ case 'EventBinding':
276
+ props.push(this.eventProp(a));
277
+ break;
278
+ case 'RefBinding':
279
+ props.push({ name: 'ref', kind: 'ref', expr: this.hole(a.hole).code, reactive: this.hole(a.hole).reactive });
280
+ break;
281
+ case 'Spread':
282
+ props.push({ name: '', kind: 'spread', expr: this.hole(a.hole).code });
283
+ break;
284
+ case 'ClassDirective': {
285
+ const h = this.hole(a.hole);
286
+ classEntries.push(`${JSON.stringify(a.name)}: ${h.code}`);
287
+ classReactive = classReactive || h.reactive;
288
+ break;
289
+ }
290
+ case 'StyleDirective': {
291
+ const h = this.hole(a.hole);
292
+ styleEntries.push(`${JSON.stringify(a.name)}: ${h.code}`);
293
+ styleReactive = styleReactive || h.reactive;
294
+ break;
295
+ }
296
+ case 'BindDirective':
297
+ props.push(...this.bindProps(a.name, this.hole(a.hole).code));
298
+ break;
299
+ case 'UseDirective': {
300
+ // `use=${dir}` → [dir]; `use:name` → [name]; `use:name=${opts}` →
301
+ // [name, () => opts]. `name` is an in-scope identifier (like Solid).
302
+ const dir = a.name ?? (a.hole != null ? this.hole(a.hole).code : null);
303
+ if (!dir)
304
+ break;
305
+ // parens so an object literal opts isn't read as a block body
306
+ usePairs.push(a.name != null && a.hole != null ? `[${dir}, () => (${this.hole(a.hole).code})]` : `[${dir}]`);
307
+ break;
308
+ }
309
+ }
310
+ }
311
+ // Merge all class:/style: directives into one classList/style prop so they
312
+ // don't collide as duplicate keys in the emitted props object.
313
+ if (classEntries.length > 0) {
314
+ props.push({ name: 'classList', kind: 'attr', expr: `{ ${classEntries.join(', ')} }`, reactive: classReactive });
315
+ }
316
+ if (styleEntries.length > 0) {
317
+ props.push({ name: 'style', kind: 'attr', expr: `{ ${styleEntries.join(', ')} }`, reactive: styleReactive });
318
+ }
319
+ // All use: directives normalize to one `use` prop = an array of [dir, accessor?] pairs.
320
+ if (usePairs.length > 0) {
321
+ props.push({ name: 'use', kind: 'attr', expr: `[${usePairs.join(', ')}]` });
322
+ }
323
+ return props;
324
+ }
325
+ /**
326
+ * Lower an event binding. Plain `@click`/`onClick` (no modifiers) stays a
327
+ * DELEGATED handler (unchanged, byte-identical with JSX). `on:click` or any
328
+ * modifier (`.capture`/`.once`/`.passive`/`.prevent`/`.stop`/`.self`) emits a
329
+ * NATIVE `on:name` prop the runtime attaches via addEventListener.
330
+ */
331
+ eventProp(a) {
332
+ const dom = a.name.toLowerCase();
333
+ const handler = this.hole(a.hole).code;
334
+ const native = a.syntax === 'colon' || a.modifiers.length > 0;
335
+ if (!native) {
336
+ return {
337
+ name: 'on' + capitalize(a.name),
338
+ kind: 'event',
339
+ event: { name: dom, delegated: DELEGATED.has(dom) },
340
+ expr: handler,
341
+ };
342
+ }
343
+ const wrapped = this.wrapHandler(handler, a.modifiers);
344
+ const options = this.eventOptions(a.modifiers);
345
+ const value = options ? `[${wrapped}, ${options}]` : wrapped;
346
+ return { name: 'on:' + dom, kind: 'attr', expr: value };
347
+ }
348
+ /** Wrap a handler for `.prevent`/`.stop`/`.self` (no wrap when none apply). */
349
+ wrapHandler(handler, mods) {
350
+ const guard = mods.includes('self') ? 'if (e.target !== e.currentTarget) return; ' : '';
351
+ const pre = [];
352
+ if (mods.includes('prevent'))
353
+ pre.push('e.preventDefault();');
354
+ if (mods.includes('stop'))
355
+ pre.push('e.stopPropagation();');
356
+ if (!guard && pre.length === 0)
357
+ return handler;
358
+ return `(e) => { ${guard}${pre.join(' ')} return (${handler})(e); }`;
359
+ }
360
+ /** addEventListener options object from `.capture`/`.once`/`.passive`, or null. */
361
+ eventOptions(mods) {
362
+ const opts = [];
363
+ if (mods.includes('capture'))
364
+ opts.push('capture: true');
365
+ if (mods.includes('once'))
366
+ opts.push('once: true');
367
+ if (mods.includes('passive'))
368
+ opts.push('passive: true');
369
+ return opts.length ? `{ ${opts.join(', ')} }` : null;
370
+ }
371
+ /** `bind:value=${sig}` → `value={sig[0]()}` + `onInput={e => sig[1](e…value)}`. */
372
+ bindProps(prop, sigCode) {
373
+ const checked = prop === 'checked';
374
+ const evt = checked ? 'change' : 'input';
375
+ const accessor = checked ? 'checked' : 'value';
376
+ // Parenthesize the signal expression — it may be more than an identifier
377
+ // (`[get, set] as const`, `props.model`, a call), and `expr[0]()` would then
378
+ // mis-parse (e.g. `[...] as const[0]`).
379
+ const sig = `(${sigCode})`;
380
+ return [
381
+ { name: prop, kind: 'attr', expr: `${sig}[0]()`, reactive: true },
382
+ {
383
+ name: 'on' + capitalize(evt),
384
+ kind: 'event',
385
+ event: { name: evt, delegated: DELEGATED.has(evt) },
386
+ // delegated handler: `target` is the bound element (currentTarget is the root)
387
+ expr: `(e) => ${sig}[1](e.target.${accessor})`,
388
+ },
389
+ ];
390
+ }
391
+ /** A plain attribute (incl. lit `?bool`, mixed values) — old `mkProp` behavior. */
392
+ plainAttr(a) {
393
+ const v = a.value;
394
+ // `class=${{...}}` (object literal) -> classList (Solid convention), so it
395
+ // doesn't collide with a static `class="box"` (which stays className) — both
396
+ // apply. `class` -> className; `style=${{...}}` stays `style` (runtime merges).
397
+ // `html=${x}` is the raw-HTML escape hatch -> innerHTML.
398
+ let name = a.name;
399
+ if (a.name === 'class') {
400
+ name = v && v.kind === 'hole' && this.hole(v.hole).object ? 'classList' : 'className';
401
+ }
402
+ else if (a.name === 'html') {
403
+ name = 'innerHTML';
404
+ }
405
+ const kind = 'attr';
406
+ const base = { name, kind };
407
+ if (v == null) {
408
+ base.literal = true;
409
+ return base;
410
+ }
411
+ if (v.kind === 'static') {
412
+ base.literal = v.value;
413
+ return base;
414
+ }
415
+ if (v.kind === 'hole') {
416
+ const h = this.hole(v.hole);
417
+ base.expr = h.code;
418
+ base.reactive = h.reactive;
419
+ return base;
420
+ }
421
+ // mixed: template literal, reactive if any hole is
422
+ let reactive = false;
423
+ const body = v.parts
424
+ .map((p) => {
425
+ if ('text' in p)
426
+ return escapeTemplate(p.text);
427
+ const h = this.hole(p.hole);
428
+ reactive = reactive || h.reactive;
429
+ return '${' + h.code + '}';
430
+ })
431
+ .join('');
432
+ base.expr = '`' + body + '`';
433
+ base.reactive = reactive;
434
+ return base;
435
+ }
436
+ }
437
+ /**
438
+ * Lower a parsed template to IR. `pieces` are the static runs and hole slots as
439
+ * the parser wants them; `holes` describes each `${…}` in the same order. `used`
440
+ * collects the runtime symbols the emitted code imports.
441
+ */
442
+ export function lowerTemplate(pieces, holes, used, opts = {}) {
443
+ const { root } = parseTemplate(pieces, { svg: opts.svg });
444
+ return new Lowerer(holes, used).lowerRoot(root.children);
445
+ }
@@ -0,0 +1 @@
1
+ import{parseTemplate as de}from"@fluixi/template-parser";var F={kind:"eager"},U=["pointerdown","focusin","keydown"],y=new Set(["eager","idle","visible","interaction","media","never"]),u=class extends Error{};function T(t,e){let n=t.slice(5);if(!y.has(n))throw new u(`Unknown load strategy 'load:${n}'. Expected one of ${[...y].join(", ")}.`);switch(n){case"eager":return F;case"idle":return{kind:"idle"};case"never":return{kind:"never"};case"visible":return e?{kind:"visible",rootMargin:e}:{kind:"visible"};case"interaction":return{kind:"interaction",events:e?W(e):[...U]};case"media":if(!e)throw new u(`'load:media' needs a query, e.g. load:media="(min-width: 1024px)".`);return{kind:"media",query:e};default:throw new u(`Unhandled load strategy '${n}'.`)}}function W(t){let e=t.split(/[\s,]+/).map(n=>n.trim()).filter(Boolean);if(e.length===0)throw new u("'load:interaction' was given no event names.");return e}var q=new Set(["area","base","br","col","embed","hr","img","input","link","meta","param","source","track","wbr"]),S={className:"class",htmlFor:"for"},G=new Set(["innerHTML","outerHTML","innerText","textContent","value","checked","selected","muted","defaultValue","defaultChecked","children","ref"]),K=new Set(["script","style","textarea","title"]);function R(t){return K.has(t)}function C(t){return S[t]??t}function h(t){return t.kind!=="attr"||t.expr!==void 0||t.name.includes(":")?!1:!G.has(t.name)}function $(t){if(!t.static||R(t.tag))return!1;for(let e of t.props)if(!h(e))return!1;for(let e of t.children)if(e.kind!=="text"&&!(e.kind==="element"&&$(e)))return!1;return!0}function f(t){let e=t.props.map(Z).filter(Boolean).join(""),n=`<${t.tag}${e}>`;return q.has(t.tag)?n:`${n}${t.children.map(Y).join("")}</${t.tag}>`}function Y(t){if(t.kind==="text")return Q(t.value);if(t.kind!=="element")throw new Error(`serializeStatic: unexpected ${t.kind}`);return f(t)}function Z(t){let e=S[t.name]??t.name,n=t.literal;return n===!0||n===void 0?` ${e}`:n===!1||n===null?"":` ${e}="${X(String(n))}"`}function X(t){return t.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function Q(t){return t.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}var ee="<!--fx-->",te="<!--fx/-->";function N(t){return t.kind==="expr"||t.kind==="component"||t.kind==="control"}function ne(t){return t.kind==="text"||t.kind==="element"&&A(t)}function A(t){return t.svg||R(t.tag)||!t.props.every(e=>h(e))?!1:t.children.every(e=>ne(e)||N(e))}function k(t){if(N(t))return!0;let e=t.children;return e?e.some(k):!1}function P(t){for(let e=0;e<t.children.length;e++){let n=t.children[e];if(n.kind==="text"&&(n.value===""||t.children[e+1]?.kind==="text"))return!1}return t.children.every(e=>e.kind!=="element"||P(e))}function L(t){if(!A(t)||!P(t)||!t.children.some(k))return null;let e=[],n=[],r=0,i=c=>{let s=`_n$${r++}`;return e.push({ref:s,expr:c}),s};return o(t,"_el$"),{html:re(t),tag:t.tag,steps:e,holes:n};function o(c,s){let a=-1;c.children.forEach((d,p)=>{k(d)&&(a=p)});let l=null;for(let d=0;d<=a;d++){let p=c.children[d],m=l?`${l}.nextSibling`:`${s}.firstChild`;if(N(p)){let I=i(m),w=i(`holeEnd(${I})`);n.push({parentRef:s,startRef:I,endRef:w,node:p}),l=w;continue}let v=i(m);p.kind==="element"&&k(p)&&o(p,v),l=v}}}function re(t){return f(D(t)).split(j).join(ee+te)}function D(t){return{...t,children:t.children.map(e=>N(e)?{kind:"text",value:j}:e.kind==="element"?D(e):e)}}var j="\0fx-hole\0";var b={version:1,module:"@fluixi/dom",symbols:["createNativeElement","insert","spread","setAttribute","delegateEvents","createComponent","createMemo","untrack","Show","For","Index","Switch","Match","Dynamic","ErrorBoundary"]},ge={version:2,module:"@fluixi/dom",symbols:[...b.symbols,"template","cloneTemplate","walk"]};var ie={show:"Show",for:"For",index:"Index",switch:"Switch",match:"Match",dynamic:"Dynamic",errorBoundary:"ErrorBoundary",suspense:"Suspense"};function oe(t){return/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(t)}function _(t){return oe(t)?t:JSON.stringify(t)}function se(t){return t.expr!==void 0?t.reactive?`() => (${t.expr})`:`(${t.expr})`:JSON.stringify(t.literal??!0)}function ae(t){return t.expr!==void 0?`(${t.expr})`:JSON.stringify(t.literal??!0)}function le(t,e,n){let r=t.filter(s=>s.kind==="spread"),o=t.filter(s=>s.kind!=="spread").map(s=>`${_(s.name)}: ${se(s)}`);e!=null&&o.push(`children: ${e}`);let c=`{ ${o.join(", ")} }`;return r.length>0?(n.add("mergeProps"),`mergeProps(${r.map(s=>s.expr).join(", ")}, ${c})`):c}function M(t,e,n){return t.length===1?g(t[0],e,n):`[${t.map(r=>g(r,e,n)).join(", ")}]`}function O(t,e,n,r,i){r.add("createMemo"),r.add("createComponent");let o=e.filter(l=>l.kind==="spread"),s=e.filter(l=>l.kind!=="spread").map(l=>`get ${_(l.name)}() { return ${ae(l)}; }`);n.length>0&&s.push(`get children() { return ${M(n,r,i)}; }`);let a=`{ ${s.join(", ")} }`;return o.length>0&&(r.add("mergeProps"),a=`mergeProps(${o.map(l=>l.expr).join(", ")}, ${a})`),`createMemo(() => createComponent(${t}, ${a}))`}function ce(t,e){let n=C(e.name),r=e.literal;return r===!0||r===void 0?`${t}.setAttribute(${JSON.stringify(n)}, "");`:r===!1||r===null?"":`${t}.setAttribute(${JSON.stringify(n)}, ${JSON.stringify(String(r))});`}var H=!1;function g(t,e,n){switch(t.kind){case"text":return JSON.stringify(t.value);case"expr":return t.reactive?`() => (${t.code})`:`(${t.code})`;case"fragment":return t.children.length===0?"null":M(t.children,e,n);case"component":return O(t.name,t.props,t.children,e,n);case"control":{let r=ie[t.control]??t.control;return e.add(r),O(r,t.props,t.children,e,n)}case"element":{if(n&&t.static&&!t.svg&&$(t)){e.add("templateNode");let s=`_tmpl$${n.length}`;return n.push({id:s,html:f(t),tag:t.tag,svg:!1}),`templateNode(${s}, ${JSON.stringify(t.tag)})`}if(n&&H){let s=L(t);if(s){e.add("templateNode"),e.add("insert"),e.add("holeEnd"),e.add("holeContent"),e.add("holeScope");let a=`_tmpl$${n.length}`;n.push({id:a,html:s.html,tag:s.tag,svg:!1});let l=[`const _el$ = templateNode(${a}, ${JSON.stringify(s.tag)}, true);`];for(let d of s.steps)l.push(`const ${d.ref} = ${d.expr};`);for(let d of s.holes)l.push(`insert(${d.parentRef}, holeScope(${d.startRef}, () => (${g(d.node,e,n)})), ${d.endRef}, holeContent(${d.startRef}, ${d.endRef}));`);return l.push("return _el$;"),`(() => { ${l.join(" ")} })()`}}e.add("createNativeElement");let r=JSON.stringify(t.tag),i="_el$",o=[],c=t.svg?`${r}, true`:r;if(o.push(`const ${i} = createNativeElement(${c});`),t.props.length>0)if(!t.svg&&t.props.every(h))for(let s of t.props)o.push(ce(i,s));else{e.add("spread");let s=t.svg?", isSVG: true":"";o.push(`spread({ element: ${i}, props: ${le(t.props,null,e)}${s} });`)}for(let s of t.children){e.add("insert");let a=g(s,e,n),l=s.kind==="expr"&&s.reactive||s.kind==="component"||s.kind==="control";o.push(l?`insert(${i}, ${a}, null);`:`insert(${i}, ${a});`)}return o.push(`return ${i};`),`(() => { ${o.join(" ")} })()`}}}function B(t,e){if(!e||e.length===0)return t;let n=new Map(e.map(r=>[r.id,JSON.stringify(r.html)]));return t.replace(/_tmpl\$\d+/g,r=>n.get(r)??r)}var J={name:"imperative",contract:b,emit(t,e){let n=new Set,r=e?.templateClone!==!1?[]:void 0;return H=e?.partialTemplates===!0,{code:g(t,n,r),imports:Array.from(n),templates:r}}};function x(t){let e=t.split(/\r\n|\n|\r/),n=0;for(let i=0;i<e.length;i++)/[^ \t]/.test(e[i])&&(n=i);let r="";for(let i=0;i<e.length;i++){let o=e[i].replace(/\t/g," ");i!==0&&(o=o.replace(/^ +/,"")),i!==e.length-1&&(o=o.replace(/ +$/,"")),o&&(i!==n&&(o+=" "),r+=o)}return r}var z=new Set(["click","dblclick","input","change","submit","focus","blur","keydown","keyup","keypress","mousedown","mouseup"]);function pe(t){return t.replace(/\\/g,"\\\\").replace(/`/g,"\\`").replace(/\$\{/g,"\\${")}function V(t){return t.charAt(0).toUpperCase()+t.slice(1)}var E=class{constructor(e,n){this.holes=e;this.used=n}hole(e){return this.holes[e]??{code:"undefined",reactive:!1}}emit(e){let{code:n,imports:r,templates:i}=J.emit(e,{});for(let o of r)this.used.add(o);return B(n,i)}lowerRoot(e){let n=this.lowerChildren(e);return n.length===1?n[0]:{kind:"fragment",children:n}}lowerChildren(e){let n=[];for(let r=0;r<e.length;r++){let i=e[r];if(i.kind==="Element"||i.kind==="Component"){let c=i.attributes.find(s=>s.kind==="IfDirective");if(c&&c.kind==="IfDirective"){let s=r+1;s<e.length&&this.isBlankText(e[s])&&s++;let a=e[s],l=a&&(a.kind==="Element"||a.kind==="Component")&&a.attributes.some(d=>d.kind==="ElseDirective");n.push(this.lowerIf(i,c.hole,l?a:null)),l&&(r=s);continue}if(i.attributes.some(s=>s.kind==="EachDirective")){n.push(this.lowerEach(i));continue}}let o=this.lowerNode(i);o&&n.push(o)}return n}isBlankText(e){return e.kind==="Text"&&!e.raw&&x(e.value)===""}lowerNode(e){switch(e.kind){case"Text":{if(e.raw)return{kind:"text",value:e.value};let n=x(e.value);return n?{kind:"text",value:n}:null}case"Comment":return null;case"Expression":{let n=this.hole(e.hole);return{kind:"expr",code:n.code,reactive:n.reactive}}case"Fragment":return{kind:"fragment",children:this.lowerChildren(e.children)};case"Element":return this.lowerElement(e);case"Component":return this.lowerComponent(e);default:return null}}lowerElement(e){let n=e.attributes.find(r=>r.kind==="Attribute"&&r.name==="is");if(e.tag==="component"&&n&&n.value&&n.value.kind==="hole"){let r=e.attributes.filter(o=>o!==n),i=this.lowerComponent({...e,kind:"Component",tag:"Dynamic",tagHole:null,attributes:r});return i.props.unshift({name:"component",kind:"attr",expr:`() => (${this.hole(n.value.hole).code})`}),i}return{kind:"element",tag:e.tag,svg:e.namespace==="svg",props:this.lowerAttributes(e.attributes),children:this.lowerChildren(e.children),static:!1}}lowerComponent(e){let n=e.tagHole!=null?this.hole(e.tagHole).code:e.tag,r=this.lowerAttributes(e.attributes),{slots:i,rest:o}=this.partitionSlots(e.children);for(let[a,l]of i){let d=l.length===1?l[0]:{kind:"fragment",children:l},p={name:a,kind:"attr",expr:this.emit(d),jsxElement:!0},m=r.findIndex(v=>v.name===a);m>=0?r[m]=p:r.push(p)}let c=e.attributes.find(a=>a.kind==="LoadDirective"),s=c?T(`load:${c.strategy}`,c.modifier):void 0;return{kind:"component",name:n,props:r,children:this.lowerChildren(o),...s?{load:s}:{}}}partitionSlots(e){let n=new Map,r=[];for(let i of e){if(i.kind==="Element"||i.kind==="Component"){let o=i.attributes.find(c=>c.kind==="Attribute"&&c.name==="slot");if(o&&o.value&&o.value.kind==="static"){let c={...i,attributes:i.attributes.filter(l=>l!==o)},s=c.kind==="Element"?this.lowerElement(c):this.lowerComponent(c),a=n.get(o.value.value)??[];a.push(s),n.set(o.value.value,a);continue}}r.push(i)}return{slots:n,rest:r}}lowerIf(e,n,r){let i=this.hole(n),o=[{name:"when",kind:"attr",expr:i.code,reactive:i.reactive}];if(r){let s=this.stripAndLower(r,a=>a.kind==="ElseDirective");o.push({name:"fallback",kind:"attr",expr:this.emit(s),jsxElement:!0})}let c=this.stripAndLower(e,s=>s.kind==="IfDirective");return{kind:"component",name:"Show",props:o,children:[c]}}lowerEach(e){let n=e.attributes.find(a=>a.kind==="EachDirective");if(!n||n.kind!=="EachDirective")return this.lowerNode(e);let r=this.hole(n.hole),i=[{name:"each",kind:"attr",expr:r.code,reactive:r.reactive}];if(n.key){let a="static"in n.key?`(item) => item[${JSON.stringify(n.key.static)}]`:this.hole(n.key.hole).code;i.push({name:"by",kind:"attr",expr:a})}let o=this.itemArrow(e),c;if(o){let a={kind:"expr",code:o.body,reactive:o.bodyReactive},l=this.rebuildWithChildren(e,[a]);c=`(${o.params.join(", ")}) => (${this.emit(l)})`}else{let a=this.stripAndLower(e,l=>l.kind==="EachDirective");c=`() => (${this.emit(a)})`}return{kind:"component",name:"For",props:i,children:[{kind:"expr",code:c,reactive:!1}]}}itemArrow(e){let n=e.children.filter(r=>!this.isBlankText(r));return n.length!==1||n[0].kind!=="Expression"?null:this.hole(n[0].hole).arrow??null}stripAndLower(e,n){let r={...e,attributes:e.attributes.filter(i=>!n(i))};return r.kind==="Element"?this.lowerElement(r):this.lowerComponent(r)}rebuildWithChildren(e,n){let r=this.lowerAttributes(e.attributes.filter(i=>i.kind!=="EachDirective"));return e.kind==="Element"?{kind:"element",tag:e.tag,svg:e.namespace==="svg",props:r,children:n,static:!1}:{kind:"component",name:e.tag,props:r,children:n}}lowerAttributes(e){let n=[],r=[],i=!1,o=[],c=!1,s=[];for(let a of e)switch(a.kind){case"IfDirective":case"EachDirective":case"ElseDirective":break;case"Attribute":n.push(this.plainAttr(a));break;case"PropertyBinding":n.push({name:a.name,kind:"prop",expr:this.hole(a.hole).code,reactive:this.hole(a.hole).reactive});break;case"EventBinding":n.push(this.eventProp(a));break;case"RefBinding":n.push({name:"ref",kind:"ref",expr:this.hole(a.hole).code,reactive:this.hole(a.hole).reactive});break;case"Spread":n.push({name:"",kind:"spread",expr:this.hole(a.hole).code});break;case"ClassDirective":{let l=this.hole(a.hole);r.push(`${JSON.stringify(a.name)}: ${l.code}`),i=i||l.reactive;break}case"StyleDirective":{let l=this.hole(a.hole);o.push(`${JSON.stringify(a.name)}: ${l.code}`),c=c||l.reactive;break}case"BindDirective":n.push(...this.bindProps(a.name,this.hole(a.hole).code));break;case"UseDirective":{let l=a.name??(a.hole!=null?this.hole(a.hole).code:null);if(!l)break;s.push(a.name!=null&&a.hole!=null?`[${l}, () => (${this.hole(a.hole).code})]`:`[${l}]`);break}}return r.length>0&&n.push({name:"classList",kind:"attr",expr:`{ ${r.join(", ")} }`,reactive:i}),o.length>0&&n.push({name:"style",kind:"attr",expr:`{ ${o.join(", ")} }`,reactive:c}),s.length>0&&n.push({name:"use",kind:"attr",expr:`[${s.join(", ")}]`}),n}eventProp(e){let n=e.name.toLowerCase(),r=this.hole(e.hole).code;if(!(e.syntax==="colon"||e.modifiers.length>0))return{name:"on"+V(e.name),kind:"event",event:{name:n,delegated:z.has(n)},expr:r};let o=this.wrapHandler(r,e.modifiers),c=this.eventOptions(e.modifiers),s=c?`[${o}, ${c}]`:o;return{name:"on:"+n,kind:"attr",expr:s}}wrapHandler(e,n){let r=n.includes("self")?"if (e.target !== e.currentTarget) return; ":"",i=[];return n.includes("prevent")&&i.push("e.preventDefault();"),n.includes("stop")&&i.push("e.stopPropagation();"),!r&&i.length===0?e:`(e) => { ${r}${i.join(" ")} return (${e})(e); }`}eventOptions(e){let n=[];return e.includes("capture")&&n.push("capture: true"),e.includes("once")&&n.push("once: true"),e.includes("passive")&&n.push("passive: true"),n.length?`{ ${n.join(", ")} }`:null}bindProps(e,n){let r=e==="checked",i=r?"change":"input",o=r?"checked":"value",c=`(${n})`;return[{name:e,kind:"attr",expr:`${c}[0]()`,reactive:!0},{name:"on"+V(i),kind:"event",event:{name:i,delegated:z.has(i)},expr:`(e) => ${c}[1](e.target.${o})`}]}plainAttr(e){let n=e.value,r=e.name;e.name==="class"?r=n&&n.kind==="hole"&&this.hole(n.hole).object?"classList":"className":e.name==="html"&&(r="innerHTML");let o={name:r,kind:"attr"};if(n==null)return o.literal=!0,o;if(n.kind==="static")return o.literal=n.value,o;if(n.kind==="hole"){let a=this.hole(n.hole);return o.expr=a.code,o.reactive=a.reactive,o}let c=!1,s=n.parts.map(a=>{if("text"in a)return pe(a.text);let l=this.hole(a.hole);return c=c||l.reactive,"${"+l.code+"}"}).join("");return o.expr="`"+s+"`",o.reactive=c,o}};function ye(t,e,n,r={}){let{root:i}=de(t,{svg:r.svg});return new E(e,n).lowerRoot(i.children)}export{ye as lowerTemplate};
@@ -0,0 +1 @@
1
+ "use strict";var f=Object.defineProperty;var o=Object.getOwnPropertyDescriptor;var c=Object.getOwnPropertyNames;var p=Object.prototype.hasOwnProperty;var s=(l,e)=>{for(var n in e)f(l,n,{get:e[n],enumerable:!0})},a=(l,e,n,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let t of c(e))!p.call(l,t)&&t!==n&&f(l,t,{get:()=>e[t],enumerable:!(r=o(e,t))||r.enumerable});return l};var g=l=>a(f({},"__esModule",{value:!0}),l);var h={};s(h,{cleanTemplateText:()=>u});module.exports=g(h);function u(l){let e=l.split(/\r\n|\n|\r/),n=0;for(let t=0;t<e.length;t++)/[^ \t]/.test(e[t])&&(n=t);let r="";for(let t=0;t<e.length;t++){let i=e[t].replace(/\t/g," ");t!==0&&(i=i.replace(/^ +/,"")),t!==e.length-1&&(i=i.replace(/ +$/,"")),i&&(t!==n&&(i+=" "),r+=i)}return r}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Whitespace handling for template text runs.
3
+ *
4
+ * JSX and `` html`...` `` collapse a text run the same way — the rule came from
5
+ * JSX and the template syntax adopted it so an author moving between the two
6
+ * gets the same output. It is pure string work with no parser in it, so it lives
7
+ * here rather than in a front-end, where both can reach it and neither owns it.
8
+ */
9
+ /** Canonical JSX text cleaning — kept identical to plugin.ts cleanTemplateText. */
10
+ export declare function cleanTemplateText(value: string): string;
11
+ //# sourceMappingURL=text.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../src/lower/text.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,mFAAmF;AACnF,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAgBvD"}