@fluixi/compiler 1.0.0-alpha.92 → 1.0.0-alpha.94

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 (102) hide show
  1. package/dist/analyze/intrinsics.cjs +31 -1
  2. package/dist/analyze/intrinsics.d.cts +14 -0
  3. package/dist/analyze/intrinsics.d.ts +14 -0
  4. package/dist/analyze/intrinsics.d.ts.map +1 -1
  5. package/dist/analyze/intrinsics.js +35 -0
  6. package/dist/analyze/intrinsics.mjs +31 -1
  7. package/dist/analyze/reactive-bindings.cjs +18 -0
  8. package/dist/analyze/reactive-bindings.mjs +18 -0
  9. package/dist/analyze/static-graph.cjs +22 -4
  10. package/dist/analyze/static-graph.d.ts.map +1 -1
  11. package/dist/analyze/static-graph.js +6 -4
  12. package/dist/analyze/static-graph.mjs +22 -4
  13. package/dist/{babel-GI375YZ2.mjs → babel-RJFQVFJW.mjs} +4 -4
  14. package/dist/{chunk-QZ4CJPYP.mjs → chunk-DP2QDWWH.mjs} +1 -1
  15. package/dist/{chunk-DWNWN5RH.mjs → chunk-E2RWTIYE.mjs} +21 -15
  16. package/dist/{chunk-XJ5H2MXY.mjs → chunk-HCCBEJEZ.mjs} +31 -1
  17. package/dist/{chunk-VOUI6XPV.mjs → chunk-HIZU7WI2.mjs} +1 -1
  18. package/dist/{chunk-VC6X44FS.mjs → chunk-ZR2QHTEX.mjs} +505 -68
  19. package/dist/codegen/backends/imperative.cjs +24 -6
  20. package/dist/codegen/backends/imperative.d.ts.map +1 -1
  21. package/dist/codegen/backends/imperative.js +20 -4
  22. package/dist/codegen/backends/imperative.mjs +24 -6
  23. package/dist/frontend/babel/build-ir-lit.cjs +470 -63
  24. package/dist/frontend/babel/build-ir-lit.mjs +470 -63
  25. package/dist/frontend/babel/build-ir.cjs +470 -63
  26. package/dist/frontend/babel/build-ir.mjs +470 -63
  27. package/dist/frontend/babel/index.cjs +471 -64
  28. package/dist/frontend/babel/index.mjs +471 -64
  29. package/dist/frontend/babel/lower-template.cjs +470 -63
  30. package/dist/frontend/babel/lower-template.mjs +470 -63
  31. package/dist/frontend/babel/plugin.cjs +470 -63
  32. package/dist/frontend/babel/plugin.mjs +470 -63
  33. package/dist/index.cjs +360 -58
  34. package/dist/index.mjs +372 -58
  35. package/dist/integrations.cjs +1347 -98
  36. package/dist/integrations.d.ts.map +1 -1
  37. package/dist/integrations.js +44 -2
  38. package/dist/integrations.mjs +205 -19
  39. package/dist/lower/compile-template.cjs +354 -57
  40. package/dist/lower/compile-template.d.cts +13 -0
  41. package/dist/lower/compile-template.d.ts +13 -0
  42. package/dist/lower/compile-template.d.ts.map +1 -1
  43. package/dist/lower/compile-template.js +3 -0
  44. package/dist/lower/compile-template.mjs +366 -57
  45. package/dist/lower/entities.cjs +288 -0
  46. package/dist/lower/entities.d.cts +1 -0
  47. package/dist/lower/entities.d.ts +2 -0
  48. package/dist/lower/entities.d.ts.map +1 -0
  49. package/dist/lower/entities.js +54 -0
  50. package/dist/lower/entities.mjs +267 -0
  51. package/dist/lower/jsx.cjs +567 -7
  52. package/dist/lower/jsx.d.cts +8 -0
  53. package/dist/lower/jsx.d.ts +8 -0
  54. package/dist/lower/jsx.d.ts.map +1 -1
  55. package/dist/lower/jsx.js +205 -7
  56. package/dist/lower/jsx.mjs +567 -7
  57. package/dist/lower/template.cjs +332 -56
  58. package/dist/lower/template.d.ts.map +1 -1
  59. package/dist/lower/template.js +57 -49
  60. package/dist/lower/template.mjs +332 -56
  61. package/dist/resolve/builtins.cjs +1 -1
  62. package/dist/resolve/builtins.mjs +1 -1
  63. package/dist/resolve/component-globals.cjs +20 -1
  64. package/dist/resolve/component-globals.js +2 -2
  65. package/dist/resolve/component-globals.mjs +20 -1
  66. package/dist/resolve/write-globals.cjs +20 -1
  67. package/dist/resolve/write-globals.mjs +20 -1
  68. package/dist/{server-fns-BBZRZUPP.mjs → server-fns-JLSTKWPS.mjs} +4 -4
  69. package/dist/{server-functions-VEGLIFCE.mjs → server-functions-BGY3RD4R.mjs} +3 -3
  70. package/dist/transform/index.cjs +1123 -77
  71. package/dist/transform/index.mjs +1141 -91
  72. package/dist/transform/intrinsics.cjs +18 -0
  73. package/dist/transform/intrinsics.mjs +18 -0
  74. package/dist/transform/props.mjs +19 -14
  75. package/dist/transform/server-fns.mjs +19 -14
  76. package/dist/transform/source-locations.cjs +64 -3
  77. package/dist/transform/source-locations.d.cts +7 -2
  78. package/dist/transform/source-locations.d.ts +7 -2
  79. package/dist/transform/source-locations.d.ts.map +1 -1
  80. package/dist/transform/source-locations.js +68 -3
  81. package/dist/transform/source-locations.mjs +64 -3
  82. package/dist/transform/styles.cjs +588 -0
  83. package/dist/transform/styles.d.cts +211 -0
  84. package/dist/transform/styles.d.ts +212 -0
  85. package/dist/transform/styles.d.ts.map +1 -0
  86. package/dist/transform/styles.js +714 -0
  87. package/dist/transform/styles.mjs +653 -0
  88. package/dist/transform/templates.cjs +1122 -76
  89. package/dist/transform/templates.d.cts +13 -0
  90. package/dist/transform/templates.d.ts +13 -0
  91. package/dist/transform/templates.d.ts.map +1 -1
  92. package/dist/transform/templates.js +51 -14
  93. package/dist/transform/templates.mjs +1140 -90
  94. package/dist/{transform-UWZ7ZGJ2.mjs → transform-GBP6Y4UI.mjs} +603 -19
  95. package/dist/tsconfig.lib.tsbuildinfo +1 -1
  96. package/dist/vite-styles.cjs +180 -0
  97. package/dist/vite-styles.d.cts +59 -0
  98. package/dist/vite-styles.d.ts +60 -0
  99. package/dist/vite-styles.d.ts.map +1 -0
  100. package/dist/vite-styles.js +198 -0
  101. package/dist/vite-styles.mjs +159 -0
  102. package/package.json +10 -3
@@ -283,6 +283,7 @@ var INTRINSICS = {
283
283
  $effect: { export: "effect", module: REACTIVE_MODULE, returns: "effect" },
284
284
  $store: { export: "store", module: "@fluixi/reactive/store", returns: "store-handle" },
285
285
  $resource: { export: "resource", module: REACTIVE_MODULE, returns: "resource-handle" },
286
+ $cachedResource: { export: "cachedResource", module: "@fluixi/reactive/cached-resource", returns: "resource-handle" },
286
287
  // No short runtime form for these yet, so the intrinsic stands for the `create*`
287
288
  // name. Still worth having: no import to write, and when a shorter form is
288
289
  // designed, the change is this line rather than a compiler pass.
@@ -293,6 +294,19 @@ var INTRINSICS = {
293
294
  // dependency analysis must not guess at.
294
295
  $untrack: { export: "untrack", module: REACTIVE_MODULE, returns: "plain" },
295
296
  $untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" },
297
+ // Scopes, scheduling and lifecycle: no value to classify, but the same authoring promise,
298
+ // no import to write. `$cleanup` registers a callback on the current owner (`onCleanup`).
299
+ $batch: { export: "batch", module: REACTIVE_MODULE, returns: "plain" },
300
+ $cleanup: { export: "onCleanup", module: REACTIVE_MODULE, returns: "plain" },
301
+ $root: { export: "root", module: REACTIVE_MODULE, returns: "plain" },
302
+ $context: { export: "context", module: REACTIVE_MODULE, returns: "plain" },
303
+ $renderEffect: { export: "renderEffect", module: REACTIVE_MODULE, returns: "effect" },
304
+ $computed: { export: "computed", module: REACTIVE_MODULE, returns: "effect" },
305
+ // Storage for where the code runs, and a signal kept in it. `$persisted` is a signal
306
+ // handle as far as reads go: the same accessor with `set` on it.
307
+ $storage: { export: "useStorage", module: "@fluixi/core/storage", returns: "plain" },
308
+ $asyncStorage: { export: "useAsyncStorage", module: "@fluixi/core/storage", returns: "plain" },
309
+ $persisted: { export: "persisted", module: "@fluixi/core/storage", returns: "signal-handle" },
296
310
  // An environment variable, public or server-only; the browser build refuses a secret.
297
311
  $env: { export: "env", module: "@fluixi/start/env", returns: "plain" }
298
312
  };
@@ -470,13 +484,16 @@ function emitComponent(name, props, children, used, templates, at) {
470
484
  used.add("createComponent");
471
485
  const spreads = props.filter((p) => p.kind === "spread");
472
486
  const normal = props.filter((p) => p.kind !== "spread");
473
- const entries = normal.map(
474
- (p) => `get ${propKey(p.name)}() { return ${componentPropValue(p)}; }`
475
- );
487
+ const bodies = normal.map((p) => [p.name, componentPropValue(p)]);
476
488
  if (children.length > 0) {
477
- entries.push(`get children() { return ${emitChildren(children, used, templates)}; }`);
489
+ bodies.push(["children", emitChildren(children, used, templates)]);
490
+ }
491
+ let obj = `{ ${bodies.map(([name2, body]) => `get ${propKey(name2)}() { return ${body}; }`).join(", ")} }`;
492
+ if (bodies.some(([, body]) => /\bthis\b/.test(body))) {
493
+ const thunks = bodies.map(([name2, body]) => `${JSON.stringify(name2)}: () => (${body})`);
494
+ const getters = bodies.map(([name2]) => `get ${propKey(name2)}() { return _$t[${JSON.stringify(name2)}](); }`);
495
+ obj = `((_$t) => ({ ${getters.join(", ")} }))({ ${thunks.join(", ")} })`;
478
496
  }
479
- let obj = `{ ${entries.join(", ")} }`;
480
497
  if (spreads.length > 0) {
481
498
  used.add("mergeProps");
482
499
  obj = `mergeProps(${spreads.map((s) => s.expr).join(", ")}, ${obj})`;
@@ -558,7 +575,8 @@ function emitNode(node, used, templates) {
558
575
  } else {
559
576
  used.add("spread");
560
577
  const svgFlag = node.svg ? ", isSVG: true" : "";
561
- const customFlag = node.tag.includes("-") ? ", isCustomElement: true" : "";
578
+ const accessors = node.props.filter((p) => p.kind !== "spread" && p.expr !== void 0 && p.reactive && p.name !== "ref").map((p) => p.name);
579
+ const customFlag = node.tag.includes("-") ? `, isCustomElement: true, accessors: ${JSON.stringify(accessors)}` : "";
562
580
  parts.push(
563
581
  `spread({ element: ${el}, props: ${emitProps(node.props, null, used)}${svgFlag}${customFlag} });`
564
582
  );
@@ -611,6 +629,271 @@ function cleanTemplateText(value) {
611
629
  return out;
612
630
  }
613
631
 
632
+ // src/lower/entities.ts
633
+ var NAMED = {
634
+ quot: 34,
635
+ amp: 38,
636
+ apos: 39,
637
+ lt: 60,
638
+ gt: 62,
639
+ nbsp: 160,
640
+ iexcl: 161,
641
+ cent: 162,
642
+ pound: 163,
643
+ curren: 164,
644
+ yen: 165,
645
+ brvbar: 166,
646
+ sect: 167,
647
+ uml: 168,
648
+ copy: 169,
649
+ ordf: 170,
650
+ laquo: 171,
651
+ not: 172,
652
+ shy: 173,
653
+ reg: 174,
654
+ macr: 175,
655
+ deg: 176,
656
+ plusmn: 177,
657
+ sup2: 178,
658
+ sup3: 179,
659
+ acute: 180,
660
+ micro: 181,
661
+ para: 182,
662
+ middot: 183,
663
+ cedil: 184,
664
+ sup1: 185,
665
+ ordm: 186,
666
+ raquo: 187,
667
+ frac14: 188,
668
+ frac12: 189,
669
+ frac34: 190,
670
+ iquest: 191,
671
+ Agrave: 192,
672
+ Aacute: 193,
673
+ Acirc: 194,
674
+ Atilde: 195,
675
+ Auml: 196,
676
+ Aring: 197,
677
+ AElig: 198,
678
+ Ccedil: 199,
679
+ Egrave: 200,
680
+ Eacute: 201,
681
+ Ecirc: 202,
682
+ Euml: 203,
683
+ Igrave: 204,
684
+ Iacute: 205,
685
+ Icirc: 206,
686
+ Iuml: 207,
687
+ ETH: 208,
688
+ Ntilde: 209,
689
+ Ograve: 210,
690
+ Oacute: 211,
691
+ Ocirc: 212,
692
+ Otilde: 213,
693
+ Ouml: 214,
694
+ times: 215,
695
+ Oslash: 216,
696
+ Ugrave: 217,
697
+ Uacute: 218,
698
+ Ucirc: 219,
699
+ Uuml: 220,
700
+ Yacute: 221,
701
+ THORN: 222,
702
+ szlig: 223,
703
+ agrave: 224,
704
+ aacute: 225,
705
+ acirc: 226,
706
+ atilde: 227,
707
+ auml: 228,
708
+ aring: 229,
709
+ aelig: 230,
710
+ ccedil: 231,
711
+ egrave: 232,
712
+ eacute: 233,
713
+ ecirc: 234,
714
+ euml: 235,
715
+ igrave: 236,
716
+ iacute: 237,
717
+ icirc: 238,
718
+ iuml: 239,
719
+ eth: 240,
720
+ ntilde: 241,
721
+ ograve: 242,
722
+ oacute: 243,
723
+ ocirc: 244,
724
+ otilde: 245,
725
+ ouml: 246,
726
+ divide: 247,
727
+ oslash: 248,
728
+ ugrave: 249,
729
+ uacute: 250,
730
+ ucirc: 251,
731
+ uuml: 252,
732
+ yacute: 253,
733
+ thorn: 254,
734
+ yuml: 255,
735
+ OElig: 338,
736
+ oelig: 339,
737
+ Scaron: 352,
738
+ scaron: 353,
739
+ Yuml: 376,
740
+ fnof: 402,
741
+ circ: 710,
742
+ tilde: 732,
743
+ Alpha: 913,
744
+ Beta: 914,
745
+ Gamma: 915,
746
+ Delta: 916,
747
+ Epsilon: 917,
748
+ Zeta: 918,
749
+ Eta: 919,
750
+ Theta: 920,
751
+ Iota: 921,
752
+ Kappa: 922,
753
+ Lambda: 923,
754
+ Mu: 924,
755
+ Nu: 925,
756
+ Xi: 926,
757
+ Omicron: 927,
758
+ Pi: 928,
759
+ Rho: 929,
760
+ Sigma: 931,
761
+ Tau: 932,
762
+ Upsilon: 933,
763
+ Phi: 934,
764
+ Chi: 935,
765
+ Psi: 936,
766
+ Omega: 937,
767
+ alpha: 945,
768
+ beta: 946,
769
+ gamma: 947,
770
+ delta: 948,
771
+ epsilon: 949,
772
+ zeta: 950,
773
+ eta: 951,
774
+ theta: 952,
775
+ iota: 953,
776
+ kappa: 954,
777
+ lambda: 955,
778
+ mu: 956,
779
+ nu: 957,
780
+ xi: 958,
781
+ omicron: 959,
782
+ pi: 960,
783
+ rho: 961,
784
+ sigmaf: 962,
785
+ sigma: 963,
786
+ tau: 964,
787
+ upsilon: 965,
788
+ phi: 966,
789
+ chi: 967,
790
+ psi: 968,
791
+ omega: 969,
792
+ thetasym: 977,
793
+ upsih: 978,
794
+ piv: 982,
795
+ ensp: 8194,
796
+ emsp: 8195,
797
+ thinsp: 8201,
798
+ zwnj: 8204,
799
+ zwj: 8205,
800
+ lrm: 8206,
801
+ rlm: 8207,
802
+ ndash: 8211,
803
+ mdash: 8212,
804
+ lsquo: 8216,
805
+ rsquo: 8217,
806
+ sbquo: 8218,
807
+ ldquo: 8220,
808
+ rdquo: 8221,
809
+ bdquo: 8222,
810
+ dagger: 8224,
811
+ Dagger: 8225,
812
+ bull: 8226,
813
+ hellip: 8230,
814
+ permil: 8240,
815
+ prime: 8242,
816
+ Prime: 8243,
817
+ lsaquo: 8249,
818
+ rsaquo: 8250,
819
+ oline: 8254,
820
+ frasl: 8260,
821
+ euro: 8364,
822
+ image: 8465,
823
+ weierp: 8472,
824
+ real: 8476,
825
+ trade: 8482,
826
+ alefsym: 8501,
827
+ larr: 8592,
828
+ uarr: 8593,
829
+ rarr: 8594,
830
+ darr: 8595,
831
+ harr: 8596,
832
+ crarr: 8629,
833
+ lArr: 8656,
834
+ uArr: 8657,
835
+ rArr: 8658,
836
+ dArr: 8659,
837
+ hArr: 8660,
838
+ forall: 8704,
839
+ part: 8706,
840
+ exist: 8707,
841
+ empty: 8709,
842
+ nabla: 8711,
843
+ isin: 8712,
844
+ notin: 8713,
845
+ ni: 8715,
846
+ prod: 8719,
847
+ sum: 8721,
848
+ minus: 8722,
849
+ lowast: 8727,
850
+ radic: 8730,
851
+ prop: 8733,
852
+ infin: 8734,
853
+ ang: 8736,
854
+ and: 8743,
855
+ or: 8744,
856
+ cap: 8745,
857
+ cup: 8746,
858
+ int: 8747,
859
+ there4: 8756,
860
+ sim: 8764,
861
+ cong: 8773,
862
+ asymp: 8776,
863
+ ne: 8800,
864
+ equiv: 8801,
865
+ le: 8804,
866
+ ge: 8805,
867
+ sub: 8834,
868
+ sup: 8835,
869
+ nsub: 8836,
870
+ sube: 8838,
871
+ supe: 8839,
872
+ oplus: 8853,
873
+ otimes: 8855,
874
+ perp: 8869,
875
+ sdot: 8901,
876
+ lceil: 8968,
877
+ rceil: 8969,
878
+ lfloor: 8970,
879
+ rfloor: 8971,
880
+ lang: 9001,
881
+ rang: 9002,
882
+ loz: 9674,
883
+ spades: 9824,
884
+ clubs: 9827,
885
+ hearts: 9829,
886
+ diams: 9830
887
+ };
888
+ var REFERENCE = /&(?:#[xX]([0-9a-fA-F]{1,6})|#([0-9]{1,7})|([a-zA-Z][a-zA-Z0-9]{1,31}));/g;
889
+ function decodeEntities(value) {
890
+ if (!value.includes("&")) return value;
891
+ return value.replace(REFERENCE, (match, hex, dec, name) => {
892
+ const code = hex ? parseInt(hex, 16) : dec ? parseInt(dec, 10) : Object.prototype.hasOwnProperty.call(NAMED, name) ? NAMED[name] : void 0;
893
+ return code !== void 0 && code <= 1114111 ? String.fromCodePoint(code) : match;
894
+ });
895
+ }
896
+
614
897
  // src/lower/template.ts
615
898
  var DELEGATED = /* @__PURE__ */ new Set([
616
899
  "click",
@@ -629,6 +912,7 @@ var DELEGATED = /* @__PURE__ */ new Set([
629
912
  function escapeTemplate(s) {
630
913
  return s.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${");
631
914
  }
915
+ var CONTAINER = "container";
632
916
  function capitalize(s) {
633
917
  return s.charAt(0).toUpperCase() + s.slice(1);
634
918
  }
@@ -683,10 +967,6 @@ var Lowerer = class {
683
967
  if (hasElse) i = elseIdx;
684
968
  continue;
685
969
  }
686
- if (child.attributes.some((a) => a.kind === "EachDirective")) {
687
- out.push(this.lowerEach(child));
688
- continue;
689
- }
690
970
  }
691
971
  const node = this.lowerNode(child);
692
972
  if (node) out.push(node);
@@ -700,7 +980,7 @@ var Lowerer = class {
700
980
  switch (node.kind) {
701
981
  case "Text": {
702
982
  if (node.raw) return { kind: "text", value: node.value };
703
- const cleaned = cleanTemplateText(node.value);
983
+ const cleaned = decodeEntities(cleanTemplateText(node.value));
704
984
  return cleaned ? { kind: "text", value: cleaned } : null;
705
985
  }
706
986
  case "Comment":
@@ -728,13 +1008,16 @@ var Lowerer = class {
728
1008
  node.props.unshift({ name: "component", kind: "attr", expr: `() => ${paren(this.hole(isAttr.value.hole).code, "arrowBody")}` });
729
1009
  return node;
730
1010
  }
1011
+ const each = this.lowerEach(el);
1012
+ const children = each ? [each] : this.lowerChildren(el.children);
1013
+ if (el.tag === CONTAINER) return children.length === 1 ? children[0] : { kind: "fragment", children };
731
1014
  const at = this.tagAt(el);
732
1015
  return {
733
1016
  kind: "element",
734
1017
  tag: el.tag,
735
1018
  svg: el.namespace === "svg",
736
- props: this.lowerAttributes(el.attributes),
737
- children: this.lowerChildren(el.children),
1019
+ props: this.lowerAttributes(el.attributes, true),
1020
+ children,
738
1021
  static: false,
739
1022
  ...at ? { at } : {}
740
1023
  };
@@ -806,10 +1089,14 @@ var Lowerer = class {
806
1089
  const at = this.tagAt(el);
807
1090
  return { kind: "component", name: "Show", props, children: [child], ...at ? { at } : {}, ...cond.at ? { bindAt: cond.at } : {} };
808
1091
  }
809
- /** `<el each=${items} key?>${item => …}</el>` → `<For each>{item => <el>…</el>}</For>`. */
1092
+ /**
1093
+ * `<el each=${items} key?>${item => …}</el>` → `<el><For each>{item => …}</For></el>`: the
1094
+ * content is repeated per item. Content that is not a `${item => …}` arrow is repeated as
1095
+ * it is. Null when the element has no `each`.
1096
+ */
810
1097
  lowerEach(el) {
811
1098
  const eachDir = el.attributes.find((a) => a.kind === "EachDirective");
812
- if (!eachDir || eachDir.kind !== "EachDirective") return this.lowerNode(el);
1099
+ if (!eachDir || eachDir.kind !== "EachDirective") return null;
813
1100
  const each = this.hole(eachDir.hole);
814
1101
  const props = [{ name: "each", kind: "attr", expr: each.code, reactive: each.reactive, ...each.at ? { at: each.at } : {} }];
815
1102
  if (eachDir.key) {
@@ -819,12 +1106,12 @@ var Lowerer = class {
819
1106
  const arrow = this.itemArrow(el);
820
1107
  let childrenCode;
821
1108
  if (arrow) {
822
- const bodyIR = { kind: "expr", code: arrow.body, reactive: arrow.bodyReactive };
823
- const repeated = this.rebuildWithChildren(el, [bodyIR]);
824
- childrenCode = `(${arrow.params.join(", ")}) => ${paren(this.emit(repeated), "arrowBody")}`;
1109
+ const body = arrow.bodyReactive ? `() => ${paren(arrow.body, "arrowBody")}` : paren(arrow.body, "arrowBody");
1110
+ childrenCode = `(${arrow.params.join(", ")}) => ${body}`;
825
1111
  } else {
826
- const repeated = this.stripAndLower(el, (a) => a.kind === "EachDirective");
827
- childrenCode = `() => ${paren(this.emit(repeated), "arrowBody")}`;
1112
+ const content = this.lowerChildren(el.children);
1113
+ const ir = content.length === 1 ? content[0] : { kind: "fragment", children: content };
1114
+ childrenCode = `() => ${paren(this.emit(ir), "arrowBody")}`;
828
1115
  }
829
1116
  const children = [{ kind: "expr", code: childrenCode, reactive: false }];
830
1117
  const at = this.tagAt(el);
@@ -841,33 +1128,23 @@ var Lowerer = class {
841
1128
  const clone = { ...el, attributes: el.attributes.filter((a) => !drop(a)) };
842
1129
  return clone.kind === "Element" ? this.lowerElement(clone) : this.lowerComponent(clone);
843
1130
  }
844
- /** Same element (minus each/key) but with explicit IR children. */
845
- rebuildWithChildren(el, children) {
846
- const props = this.lowerAttributes(
847
- el.attributes.filter((a) => a.kind !== "EachDirective")
848
- );
849
- if (el.kind === "Element") {
850
- const at = this.tagAt(el);
851
- return {
852
- kind: "element",
853
- tag: el.tag,
854
- svg: el.namespace === "svg",
855
- props,
856
- children,
857
- static: false,
858
- ...at ? { at } : {}
859
- };
860
- }
861
- return { kind: "component", name: el.tag, props, children };
862
- }
863
1131
  // --- attributes ---------------------------------------------------------
864
- lowerAttributes(attrs) {
1132
+ /**
1133
+ * `element`: a DOM element, where each class:/style: value that moves is its own accessor.
1134
+ * A component gets the object as before, rebuilt whole when any value moves.
1135
+ */
1136
+ lowerAttributes(attrs, element = false) {
1137
+ let anyReactive = false;
1138
+ const entry = (name, h) => {
1139
+ anyReactive ||= h.reactive;
1140
+ if (!element || !h.reactive) return `${JSON.stringify(name)}: ${h.code}`;
1141
+ const accessor = `() => ${paren(h.code, "arrowBody")}`;
1142
+ return `${JSON.stringify(name)}: ${h.at ? markHole(accessor, h.at.line, h.at.column) : accessor}`;
1143
+ };
865
1144
  const props = [];
866
1145
  const classEntries = [];
867
- let classReactive = false;
868
1146
  let classAt;
869
1147
  const styleEntries = [];
870
- let styleReactive = false;
871
1148
  let styleAt;
872
1149
  const usePairs = [];
873
1150
  for (const a of attrs) {
@@ -907,15 +1184,13 @@ var Lowerer = class {
907
1184
  break;
908
1185
  case "ClassDirective": {
909
1186
  const h = this.hole(a.hole);
910
- classEntries.push(`${JSON.stringify(a.name)}: ${h.code}`);
911
- classReactive = classReactive || h.reactive;
1187
+ classEntries.push(entry(a.name, h));
912
1188
  classAt ??= h.at;
913
1189
  break;
914
1190
  }
915
1191
  case "StyleDirective": {
916
1192
  const h = this.hole(a.hole);
917
- styleEntries.push(`${JSON.stringify(a.name)}: ${h.code}`);
918
- styleReactive = styleReactive || h.reactive;
1193
+ styleEntries.push(entry(a.name, h));
919
1194
  styleAt ??= h.at;
920
1195
  break;
921
1196
  }
@@ -935,18 +1210,19 @@ var Lowerer = class {
935
1210
  name: "classList",
936
1211
  kind: "attr",
937
1212
  expr: `{ ${classEntries.join(", ")} }`,
938
- reactive: classReactive,
1213
+ reactive: !element && anyReactive,
939
1214
  ...classAt ? { at: classAt } : {}
940
1215
  });
941
1216
  }
942
1217
  if (styleEntries.length > 0) {
943
- props.push({
944
- name: "style",
945
- kind: "attr",
946
- expr: `{ ${styleEntries.join(", ")} }`,
947
- reactive: styleReactive,
948
- ...styleAt ? { at: styleAt } : {}
949
- });
1218
+ const entries = `{ ${styleEntries.join(", ")} }`;
1219
+ const base = props.findIndex((p) => p.name === "style");
1220
+ if (base === -1) props.push({ name: "style", kind: "attr", expr: entries, reactive: !element && anyReactive, ...styleAt ? { at: styleAt } : {} });
1221
+ else {
1222
+ const prop = props[base];
1223
+ const value = prop.expr === void 0 ? JSON.stringify(prop.literal) : prop.reactive ? `() => ${paren(prop.expr, "arrowBody")}` : prop.expr;
1224
+ props[base] = { name: "style", kind: "attr", expr: `[${value}, ${entries}]`, reactive: false, ...prop.at ? { at: prop.at } : {} };
1225
+ }
950
1226
  }
951
1227
  if (usePairs.length > 0) {
952
1228
  props.push({ name: "use", kind: "attr", expr: `[${usePairs.join(", ")}]` });
@@ -1035,7 +1311,7 @@ var Lowerer = class {
1035
1311
  return base;
1036
1312
  }
1037
1313
  if (v.kind === "static") {
1038
- base.literal = v.value;
1314
+ base.literal = decodeEntities(v.value);
1039
1315
  return base;
1040
1316
  }
1041
1317
  if (v.kind === "hole") {
@@ -1048,7 +1324,7 @@ var Lowerer = class {
1048
1324
  let reactive = false;
1049
1325
  let at;
1050
1326
  const body = v.parts.map((p) => {
1051
- if ("text" in p) return escapeTemplate(p.text);
1327
+ if ("text" in p) return escapeTemplate(decodeEntities(p.text));
1052
1328
  const h = this.hole(p.hole);
1053
1329
  reactive = reactive || h.reactive;
1054
1330
  at ??= h.at;
@@ -1 +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,YAAY,EAAE,MAAM,EAAsB,MAAM,gBAAgB,CAAC;AAM/E;;;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,iFAAiF;IACjF,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;;;;OAMG;IACH,EAAE,CAAC,EAAE,YAAY,CAAC;CACnB;AAmhBD;;;;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,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;CAAO,GACnH,MAAM,CAGR"}
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,YAAY,EAAE,MAAM,EAAsB,MAAM,gBAAgB,CAAC;AAQ/E;;;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,iFAAiF;IACjF,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;;;;OAMG;IACH,EAAE,CAAC,EAAE,YAAY,CAAC;CACnB;AAohBD;;;;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,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;CAAO,GACnH,MAAM,CAGR"}