@fluixi/compiler 1.0.0-alpha.93 → 1.0.0-alpha.95

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 (93) hide show
  1. package/LICENSE +1 -1
  2. package/dist/analyze/intrinsics.cjs +13 -1
  3. package/dist/analyze/intrinsics.d.cts +14 -0
  4. package/dist/analyze/intrinsics.d.ts +14 -0
  5. package/dist/analyze/intrinsics.d.ts.map +1 -1
  6. package/dist/analyze/intrinsics.js +17 -0
  7. package/dist/analyze/intrinsics.mjs +13 -1
  8. package/dist/analyze/static-graph.cjs +1 -1
  9. package/dist/analyze/static-graph.mjs +1 -1
  10. package/dist/{babel-RJHJQVEM.mjs → babel-V33QLJBF.mjs} +4 -4
  11. package/dist/{chunk-56QSOVVL.mjs → chunk-62F2LLBM.mjs} +1 -1
  12. package/dist/{chunk-R7PPFBCL.mjs → chunk-7GNSGUHK.mjs} +4 -83
  13. package/dist/{chunk-U7HCFLZ2.mjs → chunk-B64LVPTU.mjs} +356 -24
  14. package/dist/{chunk-OD53TMER.mjs → chunk-C3AK5PBV.mjs} +13 -1
  15. package/dist/{chunk-TJIH7TLX.mjs → chunk-GLFUPZ27.mjs} +1 -1
  16. package/dist/chunk-HUABRVWB.mjs +92 -0
  17. package/dist/chunk-XCWP7WJG.mjs +584 -0
  18. package/dist/codegen/backends/imperative.cjs +1 -1
  19. package/dist/codegen/backends/imperative.d.ts.map +1 -1
  20. package/dist/codegen/backends/imperative.js +2 -1
  21. package/dist/codegen/backends/imperative.mjs +1 -1
  22. package/dist/frontend/babel/build-ir-lit.cjs +352 -22
  23. package/dist/frontend/babel/build-ir-lit.mjs +352 -22
  24. package/dist/frontend/babel/build-ir.cjs +352 -22
  25. package/dist/frontend/babel/build-ir.mjs +352 -22
  26. package/dist/frontend/babel/index.cjs +353 -23
  27. package/dist/frontend/babel/index.mjs +353 -23
  28. package/dist/frontend/babel/lower-template.cjs +352 -22
  29. package/dist/frontend/babel/lower-template.mjs +352 -22
  30. package/dist/frontend/babel/plugin.cjs +352 -22
  31. package/dist/frontend/babel/plugin.mjs +352 -22
  32. package/dist/index.cjs +321 -22
  33. package/dist/index.mjs +333 -22
  34. package/dist/integrations.cjs +1240 -56
  35. package/dist/integrations.d.ts.map +1 -1
  36. package/dist/integrations.js +62 -9
  37. package/dist/integrations.mjs +257 -26
  38. package/dist/lower/compile-template.cjs +315 -21
  39. package/dist/lower/compile-template.d.cts +13 -0
  40. package/dist/lower/compile-template.d.ts +13 -0
  41. package/dist/lower/compile-template.d.ts.map +1 -1
  42. package/dist/lower/compile-template.js +3 -0
  43. package/dist/lower/compile-template.mjs +327 -21
  44. package/dist/lower/entities.cjs +288 -0
  45. package/dist/lower/entities.d.cts +1 -0
  46. package/dist/lower/entities.d.ts +2 -0
  47. package/dist/lower/entities.d.ts.map +1 -0
  48. package/dist/lower/entities.js +54 -0
  49. package/dist/lower/entities.mjs +267 -0
  50. package/dist/lower/jsx.cjs +104 -47
  51. package/dist/lower/jsx.d.cts +8 -0
  52. package/dist/lower/jsx.d.ts +8 -0
  53. package/dist/lower/jsx.d.ts.map +1 -1
  54. package/dist/lower/jsx.js +92 -2
  55. package/dist/lower/jsx.mjs +104 -47
  56. package/dist/lower/template.cjs +293 -20
  57. package/dist/lower/template.d.ts.map +1 -1
  58. package/dist/lower/template.js +35 -19
  59. package/dist/lower/template.mjs +293 -20
  60. package/dist/resolve/builtins.cjs +1 -1
  61. package/dist/resolve/builtins.mjs +1 -1
  62. package/dist/resolve/component-globals.cjs +6 -1
  63. package/dist/resolve/component-globals.js +2 -2
  64. package/dist/resolve/component-globals.mjs +6 -1
  65. package/dist/resolve/write-globals.cjs +6 -1
  66. package/dist/resolve/write-globals.mjs +6 -1
  67. package/dist/{server-fns-ZFRDIQ2X.mjs → server-fns-N3SDJXA7.mjs} +5 -4
  68. package/dist/{server-functions-CTDXX67X.mjs → server-functions-LVS66Q4R.mjs} +3 -3
  69. package/dist/transform/index.cjs +973 -33
  70. package/dist/transform/index.mjs +991 -47
  71. package/dist/transform/props.mjs +19 -14
  72. package/dist/transform/server-fns.mjs +19 -14
  73. package/dist/transform/styles.cjs +606 -0
  74. package/dist/transform/styles.d.cts +237 -0
  75. package/dist/transform/styles.d.ts +238 -0
  76. package/dist/transform/styles.d.ts.map +1 -0
  77. package/dist/transform/styles.js +743 -0
  78. package/dist/transform/styles.mjs +671 -0
  79. package/dist/transform/templates.cjs +972 -32
  80. package/dist/transform/templates.d.cts +13 -0
  81. package/dist/transform/templates.d.ts +13 -0
  82. package/dist/transform/templates.d.ts.map +1 -1
  83. package/dist/transform/templates.js +49 -12
  84. package/dist/transform/templates.mjs +990 -46
  85. package/dist/{transform-QWWQDCXE.mjs → transform-P4AETYV4.mjs} +49 -16
  86. package/dist/tsconfig.lib.tsbuildinfo +1 -1
  87. package/dist/vite-styles.cjs +223 -0
  88. package/dist/vite-styles.d.cts +68 -0
  89. package/dist/vite-styles.d.ts +69 -0
  90. package/dist/vite-styles.d.ts.map +1 -0
  91. package/dist/vite-styles.js +241 -0
  92. package/dist/vite-styles.mjs +214 -0
  93. package/package.json +5 -4
@@ -490,7 +490,7 @@ function emitComponent(name, props, children, used, templates, at) {
490
490
  }
491
491
  let obj = `{ ${bodies.map(([name2, body]) => `get ${propKey(name2)}() { return ${body}; }`).join(", ")} }`;
492
492
  if (bodies.some(([, body]) => /\bthis\b/.test(body))) {
493
- const thunks = bodies.map(([name2, body]) => `${JSON.stringify(name2)}: () => ${body}`);
493
+ const thunks = bodies.map(([name2, body]) => `${JSON.stringify(name2)}: () => (${body})`);
494
494
  const getters = bodies.map(([name2]) => `get ${propKey(name2)}() { return _$t[${JSON.stringify(name2)}](); }`);
495
495
  obj = `((_$t) => ({ ${getters.join(", ")} }))({ ${thunks.join(", ")} })`;
496
496
  }
@@ -629,6 +629,271 @@ function cleanTemplateText(value) {
629
629
  return out;
630
630
  }
631
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
+
632
897
  // src/lower/template.ts
633
898
  var DELEGATED = /* @__PURE__ */ new Set([
634
899
  "click",
@@ -715,7 +980,7 @@ var Lowerer = class {
715
980
  switch (node.kind) {
716
981
  case "Text": {
717
982
  if (node.raw) return { kind: "text", value: node.value };
718
- const cleaned = cleanTemplateText(node.value);
983
+ const cleaned = decodeEntities(cleanTemplateText(node.value));
719
984
  return cleaned ? { kind: "text", value: cleaned } : null;
720
985
  }
721
986
  case "Comment":
@@ -751,7 +1016,7 @@ var Lowerer = class {
751
1016
  kind: "element",
752
1017
  tag: el.tag,
753
1018
  svg: el.namespace === "svg",
754
- props: this.lowerAttributes(el.attributes),
1019
+ props: this.lowerAttributes(el.attributes, true),
755
1020
  children,
756
1021
  static: false,
757
1022
  ...at ? { at } : {}
@@ -864,13 +1129,22 @@ var Lowerer = class {
864
1129
  return clone.kind === "Element" ? this.lowerElement(clone) : this.lowerComponent(clone);
865
1130
  }
866
1131
  // --- attributes ---------------------------------------------------------
867
- 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
+ };
868
1144
  const props = [];
869
1145
  const classEntries = [];
870
- let classReactive = false;
871
1146
  let classAt;
872
1147
  const styleEntries = [];
873
- let styleReactive = false;
874
1148
  let styleAt;
875
1149
  const usePairs = [];
876
1150
  for (const a of attrs) {
@@ -910,15 +1184,13 @@ var Lowerer = class {
910
1184
  break;
911
1185
  case "ClassDirective": {
912
1186
  const h = this.hole(a.hole);
913
- classEntries.push(`${JSON.stringify(a.name)}: ${h.code}`);
914
- classReactive = classReactive || h.reactive;
1187
+ classEntries.push(entry(a.name, h));
915
1188
  classAt ??= h.at;
916
1189
  break;
917
1190
  }
918
1191
  case "StyleDirective": {
919
1192
  const h = this.hole(a.hole);
920
- styleEntries.push(`${JSON.stringify(a.name)}: ${h.code}`);
921
- styleReactive = styleReactive || h.reactive;
1193
+ styleEntries.push(entry(a.name, h));
922
1194
  styleAt ??= h.at;
923
1195
  break;
924
1196
  }
@@ -938,18 +1210,19 @@ var Lowerer = class {
938
1210
  name: "classList",
939
1211
  kind: "attr",
940
1212
  expr: `{ ${classEntries.join(", ")} }`,
941
- reactive: classReactive,
1213
+ reactive: !element && anyReactive,
942
1214
  ...classAt ? { at: classAt } : {}
943
1215
  });
944
1216
  }
945
1217
  if (styleEntries.length > 0) {
946
- props.push({
947
- name: "style",
948
- kind: "attr",
949
- expr: `{ ${styleEntries.join(", ")} }`,
950
- reactive: styleReactive,
951
- ...styleAt ? { at: styleAt } : {}
952
- });
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
+ }
953
1226
  }
954
1227
  if (usePairs.length > 0) {
955
1228
  props.push({ name: "use", kind: "attr", expr: `[${usePairs.join(", ")}]` });
@@ -1038,7 +1311,7 @@ var Lowerer = class {
1038
1311
  return base;
1039
1312
  }
1040
1313
  if (v.kind === "static") {
1041
- base.literal = v.value;
1314
+ base.literal = decodeEntities(v.value);
1042
1315
  return base;
1043
1316
  }
1044
1317
  if (v.kind === "hole") {
@@ -1051,7 +1324,7 @@ var Lowerer = class {
1051
1324
  let reactive = false;
1052
1325
  let at;
1053
1326
  const body = v.parts.map((p) => {
1054
- if ("text" in p) return escapeTemplate(p.text);
1327
+ if ("text" in p) return escapeTemplate(decodeEntities(p.text));
1055
1328
  const h = this.hole(p.hole);
1056
1329
  reactive = reactive || h.reactive;
1057
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;AAwgBD;;;;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"}
@@ -10,7 +10,9 @@ import { parseTemplate, } from '@fluixi/template-parser';
10
10
  import { parseLoadDirective } from '../resolve/load-directive.js';
11
11
  import { imperativeBackend, inlineTemplates } from '../codegen/backends/imperative.js';
12
12
  import { cleanTemplateText } from './text.js';
13
+ import { decodeEntities } from './entities.js';
13
14
  import { paren } from '../analyze/paren.js';
15
+ import { markHole } from '../transform/source-locations.js';
14
16
  const DELEGATED = new Set([
15
17
  'click', 'dblclick', 'input', 'change', 'submit', 'focus', 'blur',
16
18
  'keydown', 'keyup', 'keypress', 'mousedown', 'mouseup',
@@ -105,7 +107,8 @@ class Lowerer {
105
107
  case 'Text': {
106
108
  if (node.raw)
107
109
  return { kind: 'text', value: node.value };
108
- const cleaned = cleanTemplateText(node.value);
110
+ // Decoded after cleaning, so an entity written as a space is kept as written.
111
+ const cleaned = decodeEntities(cleanTemplateText(node.value));
109
112
  return cleaned ? { kind: 'text', value: cleaned } : null;
110
113
  }
111
114
  case 'Comment':
@@ -146,7 +149,7 @@ class Lowerer {
146
149
  kind: 'element',
147
150
  tag: el.tag,
148
151
  svg: el.namespace === 'svg',
149
- props: this.lowerAttributes(el.attributes),
152
+ props: this.lowerAttributes(el.attributes, true),
150
153
  children,
151
154
  static: false,
152
155
  ...(at ? { at } : {}),
@@ -286,13 +289,24 @@ class Lowerer {
286
289
  return clone.kind === 'Element' ? this.lowerElement(clone) : this.lowerComponent(clone);
287
290
  }
288
291
  // --- attributes ---------------------------------------------------------
289
- lowerAttributes(attrs) {
292
+ /**
293
+ * `element`: a DOM element, where each class:/style: value that moves is its own accessor.
294
+ * A component gets the object as before, rebuilt whole when any value moves.
295
+ */
296
+ lowerAttributes(attrs, element = false) {
297
+ let anyReactive = false;
298
+ const entry = (name, h) => {
299
+ anyReactive ||= h.reactive;
300
+ if (!element || !h.reactive)
301
+ return `${JSON.stringify(name)}: ${h.code}`;
302
+ const accessor = `() => ${paren(h.code, 'arrowBody')}`;
303
+ // Marked like any other binding hole when positions are on.
304
+ return `${JSON.stringify(name)}: ${h.at ? markHole(accessor, h.at.line, h.at.column) : accessor}`;
305
+ };
290
306
  const props = [];
291
307
  const classEntries = [];
292
- let classReactive = false;
293
308
  let classAt;
294
309
  const styleEntries = [];
295
- let styleReactive = false;
296
310
  let styleAt;
297
311
  const usePairs = [];
298
312
  for (const a of attrs) {
@@ -331,15 +345,13 @@ class Lowerer {
331
345
  break;
332
346
  case 'ClassDirective': {
333
347
  const h = this.hole(a.hole);
334
- classEntries.push(`${JSON.stringify(a.name)}: ${h.code}`);
335
- classReactive = classReactive || h.reactive;
348
+ classEntries.push(entry(a.name, h));
336
349
  classAt ??= h.at;
337
350
  break;
338
351
  }
339
352
  case 'StyleDirective': {
340
353
  const h = this.hole(a.hole);
341
- styleEntries.push(`${JSON.stringify(a.name)}: ${h.code}`);
342
- styleReactive = styleReactive || h.reactive;
354
+ styleEntries.push(entry(a.name, h));
343
355
  styleAt ??= h.at;
344
356
  break;
345
357
  }
@@ -368,18 +380,22 @@ class Lowerer {
368
380
  name: 'classList',
369
381
  kind: 'attr',
370
382
  expr: `{ ${classEntries.join(', ')} }`,
371
- reactive: classReactive,
383
+ reactive: !element && anyReactive,
372
384
  ...(classAt ? { at: classAt } : {}),
373
385
  });
374
386
  }
387
+ // Each entry that moves is its own accessor, so the runtime updates that key alone.
375
388
  if (styleEntries.length > 0) {
376
- props.push({
377
- name: 'style',
378
- kind: 'attr',
379
- expr: `{ ${styleEntries.join(', ')} }`,
380
- reactive: styleReactive,
381
- ...(styleAt ? { at: styleAt } : {}),
382
- });
389
+ const entries = `{ ${styleEntries.join(', ')} }`;
390
+ // `style=${…}` as well: it goes first, the keys after it, applied in order.
391
+ const base = props.findIndex((p) => p.name === 'style');
392
+ if (base === -1)
393
+ props.push({ name: 'style', kind: 'attr', expr: entries, reactive: !element && anyReactive, ...(styleAt ? { at: styleAt } : {}) });
394
+ else {
395
+ const prop = props[base];
396
+ const value = prop.expr === undefined ? JSON.stringify(prop.literal) : prop.reactive ? `() => ${paren(prop.expr, 'arrowBody')}` : prop.expr;
397
+ props[base] = { name: 'style', kind: 'attr', expr: `[${value}, ${entries}]`, reactive: false, ...(prop.at ? { at: prop.at } : {}) };
398
+ }
383
399
  }
384
400
  // All use: directives normalize to one `use` prop = an array of [dir, accessor?] pairs.
385
401
  if (usePairs.length > 0) {
@@ -484,7 +500,7 @@ class Lowerer {
484
500
  return base;
485
501
  }
486
502
  if (v.kind === 'static') {
487
- base.literal = v.value;
503
+ base.literal = decodeEntities(v.value);
488
504
  return base;
489
505
  }
490
506
  if (v.kind === 'hole') {
@@ -501,7 +517,7 @@ class Lowerer {
501
517
  const body = v.parts
502
518
  .map((p) => {
503
519
  if ('text' in p)
504
- return escapeTemplate(p.text);
520
+ return escapeTemplate(decodeEntities(p.text));
505
521
  const h = this.hole(p.hole);
506
522
  reactive = reactive || h.reactive;
507
523
  at ??= h.at;