@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
@@ -1,4 +1,4 @@
1
- /*! @fluixi/compiler v1.0.0-alpha.92 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
1
+ /*! @fluixi/compiler v1.0.0-alpha.94 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
2
2
  "use strict";
3
3
  var __defProp = Object.defineProperty;
4
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -26,6 +26,26 @@ __export(compile_template_exports, {
26
26
  });
27
27
  module.exports = __toCommonJS(compile_template_exports);
28
28
 
29
+ // src/transform/styles.ts
30
+ var import_sourcemap_codec = require("@jridgewell/sourcemap-codec");
31
+ var SCOPE_ATTR = "data-fx-s";
32
+ function applyTemplateStyles(ir, t) {
33
+ const walk2 = (node) => {
34
+ const children = node.children;
35
+ if (children) {
36
+ for (let i = children.length - 1; i >= 0; i--) {
37
+ const child = children[i];
38
+ if (child.kind === "element" && child.tag === "style" && t.owner) children.splice(i, 1);
39
+ else walk2(child);
40
+ }
41
+ }
42
+ if (t.scope && node.kind === "element" && node.tag !== "style" && node.props && !node.props.some((p) => p.name === SCOPE_ATTR)) {
43
+ node.props.unshift({ name: SCOPE_ATTR, kind: "attr", literal: t.scope });
44
+ }
45
+ };
46
+ walk2(ir);
47
+ }
48
+
29
49
  // src/optimize/analyze-static.ts
30
50
  function propReason(prop) {
31
51
  switch (prop.kind) {
@@ -468,6 +488,7 @@ var INTRINSICS = {
468
488
  $effect: { export: "effect", module: REACTIVE_MODULE, returns: "effect" },
469
489
  $store: { export: "store", module: "@fluixi/reactive/store", returns: "store-handle" },
470
490
  $resource: { export: "resource", module: REACTIVE_MODULE, returns: "resource-handle" },
491
+ $cachedResource: { export: "cachedResource", module: "@fluixi/reactive/cached-resource", returns: "resource-handle" },
471
492
  // No short runtime form for these yet, so the intrinsic stands for the `create*`
472
493
  // name. Still worth having: no import to write, and when a shorter form is
473
494
  // designed, the change is this line rather than a compiler pass.
@@ -478,6 +499,19 @@ var INTRINSICS = {
478
499
  // dependency analysis must not guess at.
479
500
  $untrack: { export: "untrack", module: REACTIVE_MODULE, returns: "plain" },
480
501
  $untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" },
502
+ // Scopes, scheduling and lifecycle: no value to classify, but the same authoring promise,
503
+ // no import to write. `$cleanup` registers a callback on the current owner (`onCleanup`).
504
+ $batch: { export: "batch", module: REACTIVE_MODULE, returns: "plain" },
505
+ $cleanup: { export: "onCleanup", module: REACTIVE_MODULE, returns: "plain" },
506
+ $root: { export: "root", module: REACTIVE_MODULE, returns: "plain" },
507
+ $context: { export: "context", module: REACTIVE_MODULE, returns: "plain" },
508
+ $renderEffect: { export: "renderEffect", module: REACTIVE_MODULE, returns: "effect" },
509
+ $computed: { export: "computed", module: REACTIVE_MODULE, returns: "effect" },
510
+ // Storage for where the code runs, and a signal kept in it. `$persisted` is a signal
511
+ // handle as far as reads go: the same accessor with `set` on it.
512
+ $storage: { export: "useStorage", module: "@fluixi/core/storage", returns: "plain" },
513
+ $asyncStorage: { export: "useAsyncStorage", module: "@fluixi/core/storage", returns: "plain" },
514
+ $persisted: { export: "persisted", module: "@fluixi/core/storage", returns: "signal-handle" },
481
515
  // An environment variable, public or server-only; the browser build refuses a secret.
482
516
  $env: { export: "env", module: "@fluixi/start/env", returns: "plain" }
483
517
  };
@@ -655,13 +689,16 @@ function emitComponent(name, props, children, used, templates, at) {
655
689
  used.add("createComponent");
656
690
  const spreads = props.filter((p) => p.kind === "spread");
657
691
  const normal = props.filter((p) => p.kind !== "spread");
658
- const entries = normal.map(
659
- (p) => `get ${propKey(p.name)}() { return ${componentPropValue(p)}; }`
660
- );
692
+ const bodies = normal.map((p) => [p.name, componentPropValue(p)]);
661
693
  if (children.length > 0) {
662
- entries.push(`get children() { return ${emitChildren(children, used, templates)}; }`);
694
+ bodies.push(["children", emitChildren(children, used, templates)]);
695
+ }
696
+ let obj = `{ ${bodies.map(([name2, body]) => `get ${propKey(name2)}() { return ${body}; }`).join(", ")} }`;
697
+ if (bodies.some(([, body]) => /\bthis\b/.test(body))) {
698
+ const thunks = bodies.map(([name2, body]) => `${JSON.stringify(name2)}: () => (${body})`);
699
+ const getters = bodies.map(([name2]) => `get ${propKey(name2)}() { return _$t[${JSON.stringify(name2)}](); }`);
700
+ obj = `((_$t) => ({ ${getters.join(", ")} }))({ ${thunks.join(", ")} })`;
663
701
  }
664
- let obj = `{ ${entries.join(", ")} }`;
665
702
  if (spreads.length > 0) {
666
703
  used.add("mergeProps");
667
704
  obj = `mergeProps(${spreads.map((s) => s.expr).join(", ")}, ${obj})`;
@@ -743,7 +780,8 @@ function emitNode(node, used, templates) {
743
780
  } else {
744
781
  used.add("spread");
745
782
  const svgFlag = node.svg ? ", isSVG: true" : "";
746
- const customFlag = node.tag.includes("-") ? ", isCustomElement: true" : "";
783
+ const accessors = node.props.filter((p) => p.kind !== "spread" && p.expr !== void 0 && p.reactive && p.name !== "ref").map((p) => p.name);
784
+ const customFlag = node.tag.includes("-") ? `, isCustomElement: true, accessors: ${JSON.stringify(accessors)}` : "";
747
785
  parts.push(
748
786
  `spread({ element: ${el}, props: ${emitProps(node.props, null, used)}${svgFlag}${customFlag} });`
749
787
  );
@@ -856,6 +894,271 @@ function cleanTemplateText(value) {
856
894
  return out;
857
895
  }
858
896
 
897
+ // src/lower/entities.ts
898
+ var NAMED = {
899
+ quot: 34,
900
+ amp: 38,
901
+ apos: 39,
902
+ lt: 60,
903
+ gt: 62,
904
+ nbsp: 160,
905
+ iexcl: 161,
906
+ cent: 162,
907
+ pound: 163,
908
+ curren: 164,
909
+ yen: 165,
910
+ brvbar: 166,
911
+ sect: 167,
912
+ uml: 168,
913
+ copy: 169,
914
+ ordf: 170,
915
+ laquo: 171,
916
+ not: 172,
917
+ shy: 173,
918
+ reg: 174,
919
+ macr: 175,
920
+ deg: 176,
921
+ plusmn: 177,
922
+ sup2: 178,
923
+ sup3: 179,
924
+ acute: 180,
925
+ micro: 181,
926
+ para: 182,
927
+ middot: 183,
928
+ cedil: 184,
929
+ sup1: 185,
930
+ ordm: 186,
931
+ raquo: 187,
932
+ frac14: 188,
933
+ frac12: 189,
934
+ frac34: 190,
935
+ iquest: 191,
936
+ Agrave: 192,
937
+ Aacute: 193,
938
+ Acirc: 194,
939
+ Atilde: 195,
940
+ Auml: 196,
941
+ Aring: 197,
942
+ AElig: 198,
943
+ Ccedil: 199,
944
+ Egrave: 200,
945
+ Eacute: 201,
946
+ Ecirc: 202,
947
+ Euml: 203,
948
+ Igrave: 204,
949
+ Iacute: 205,
950
+ Icirc: 206,
951
+ Iuml: 207,
952
+ ETH: 208,
953
+ Ntilde: 209,
954
+ Ograve: 210,
955
+ Oacute: 211,
956
+ Ocirc: 212,
957
+ Otilde: 213,
958
+ Ouml: 214,
959
+ times: 215,
960
+ Oslash: 216,
961
+ Ugrave: 217,
962
+ Uacute: 218,
963
+ Ucirc: 219,
964
+ Uuml: 220,
965
+ Yacute: 221,
966
+ THORN: 222,
967
+ szlig: 223,
968
+ agrave: 224,
969
+ aacute: 225,
970
+ acirc: 226,
971
+ atilde: 227,
972
+ auml: 228,
973
+ aring: 229,
974
+ aelig: 230,
975
+ ccedil: 231,
976
+ egrave: 232,
977
+ eacute: 233,
978
+ ecirc: 234,
979
+ euml: 235,
980
+ igrave: 236,
981
+ iacute: 237,
982
+ icirc: 238,
983
+ iuml: 239,
984
+ eth: 240,
985
+ ntilde: 241,
986
+ ograve: 242,
987
+ oacute: 243,
988
+ ocirc: 244,
989
+ otilde: 245,
990
+ ouml: 246,
991
+ divide: 247,
992
+ oslash: 248,
993
+ ugrave: 249,
994
+ uacute: 250,
995
+ ucirc: 251,
996
+ uuml: 252,
997
+ yacute: 253,
998
+ thorn: 254,
999
+ yuml: 255,
1000
+ OElig: 338,
1001
+ oelig: 339,
1002
+ Scaron: 352,
1003
+ scaron: 353,
1004
+ Yuml: 376,
1005
+ fnof: 402,
1006
+ circ: 710,
1007
+ tilde: 732,
1008
+ Alpha: 913,
1009
+ Beta: 914,
1010
+ Gamma: 915,
1011
+ Delta: 916,
1012
+ Epsilon: 917,
1013
+ Zeta: 918,
1014
+ Eta: 919,
1015
+ Theta: 920,
1016
+ Iota: 921,
1017
+ Kappa: 922,
1018
+ Lambda: 923,
1019
+ Mu: 924,
1020
+ Nu: 925,
1021
+ Xi: 926,
1022
+ Omicron: 927,
1023
+ Pi: 928,
1024
+ Rho: 929,
1025
+ Sigma: 931,
1026
+ Tau: 932,
1027
+ Upsilon: 933,
1028
+ Phi: 934,
1029
+ Chi: 935,
1030
+ Psi: 936,
1031
+ Omega: 937,
1032
+ alpha: 945,
1033
+ beta: 946,
1034
+ gamma: 947,
1035
+ delta: 948,
1036
+ epsilon: 949,
1037
+ zeta: 950,
1038
+ eta: 951,
1039
+ theta: 952,
1040
+ iota: 953,
1041
+ kappa: 954,
1042
+ lambda: 955,
1043
+ mu: 956,
1044
+ nu: 957,
1045
+ xi: 958,
1046
+ omicron: 959,
1047
+ pi: 960,
1048
+ rho: 961,
1049
+ sigmaf: 962,
1050
+ sigma: 963,
1051
+ tau: 964,
1052
+ upsilon: 965,
1053
+ phi: 966,
1054
+ chi: 967,
1055
+ psi: 968,
1056
+ omega: 969,
1057
+ thetasym: 977,
1058
+ upsih: 978,
1059
+ piv: 982,
1060
+ ensp: 8194,
1061
+ emsp: 8195,
1062
+ thinsp: 8201,
1063
+ zwnj: 8204,
1064
+ zwj: 8205,
1065
+ lrm: 8206,
1066
+ rlm: 8207,
1067
+ ndash: 8211,
1068
+ mdash: 8212,
1069
+ lsquo: 8216,
1070
+ rsquo: 8217,
1071
+ sbquo: 8218,
1072
+ ldquo: 8220,
1073
+ rdquo: 8221,
1074
+ bdquo: 8222,
1075
+ dagger: 8224,
1076
+ Dagger: 8225,
1077
+ bull: 8226,
1078
+ hellip: 8230,
1079
+ permil: 8240,
1080
+ prime: 8242,
1081
+ Prime: 8243,
1082
+ lsaquo: 8249,
1083
+ rsaquo: 8250,
1084
+ oline: 8254,
1085
+ frasl: 8260,
1086
+ euro: 8364,
1087
+ image: 8465,
1088
+ weierp: 8472,
1089
+ real: 8476,
1090
+ trade: 8482,
1091
+ alefsym: 8501,
1092
+ larr: 8592,
1093
+ uarr: 8593,
1094
+ rarr: 8594,
1095
+ darr: 8595,
1096
+ harr: 8596,
1097
+ crarr: 8629,
1098
+ lArr: 8656,
1099
+ uArr: 8657,
1100
+ rArr: 8658,
1101
+ dArr: 8659,
1102
+ hArr: 8660,
1103
+ forall: 8704,
1104
+ part: 8706,
1105
+ exist: 8707,
1106
+ empty: 8709,
1107
+ nabla: 8711,
1108
+ isin: 8712,
1109
+ notin: 8713,
1110
+ ni: 8715,
1111
+ prod: 8719,
1112
+ sum: 8721,
1113
+ minus: 8722,
1114
+ lowast: 8727,
1115
+ radic: 8730,
1116
+ prop: 8733,
1117
+ infin: 8734,
1118
+ ang: 8736,
1119
+ and: 8743,
1120
+ or: 8744,
1121
+ cap: 8745,
1122
+ cup: 8746,
1123
+ int: 8747,
1124
+ there4: 8756,
1125
+ sim: 8764,
1126
+ cong: 8773,
1127
+ asymp: 8776,
1128
+ ne: 8800,
1129
+ equiv: 8801,
1130
+ le: 8804,
1131
+ ge: 8805,
1132
+ sub: 8834,
1133
+ sup: 8835,
1134
+ nsub: 8836,
1135
+ sube: 8838,
1136
+ supe: 8839,
1137
+ oplus: 8853,
1138
+ otimes: 8855,
1139
+ perp: 8869,
1140
+ sdot: 8901,
1141
+ lceil: 8968,
1142
+ rceil: 8969,
1143
+ lfloor: 8970,
1144
+ rfloor: 8971,
1145
+ lang: 9001,
1146
+ rang: 9002,
1147
+ loz: 9674,
1148
+ spades: 9824,
1149
+ clubs: 9827,
1150
+ hearts: 9829,
1151
+ diams: 9830
1152
+ };
1153
+ var REFERENCE = /&(?:#[xX]([0-9a-fA-F]{1,6})|#([0-9]{1,7})|([a-zA-Z][a-zA-Z0-9]{1,31}));/g;
1154
+ function decodeEntities(value) {
1155
+ if (!value.includes("&")) return value;
1156
+ return value.replace(REFERENCE, (match, hex, dec, name) => {
1157
+ const code = hex ? parseInt(hex, 16) : dec ? parseInt(dec, 10) : Object.prototype.hasOwnProperty.call(NAMED, name) ? NAMED[name] : void 0;
1158
+ return code !== void 0 && code <= 1114111 ? String.fromCodePoint(code) : match;
1159
+ });
1160
+ }
1161
+
859
1162
  // src/lower/template.ts
860
1163
  var DELEGATED = /* @__PURE__ */ new Set([
861
1164
  "click",
@@ -874,6 +1177,7 @@ var DELEGATED = /* @__PURE__ */ new Set([
874
1177
  function escapeTemplate(s) {
875
1178
  return s.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${");
876
1179
  }
1180
+ var CONTAINER = "container";
877
1181
  function capitalize(s) {
878
1182
  return s.charAt(0).toUpperCase() + s.slice(1);
879
1183
  }
@@ -928,10 +1232,6 @@ var Lowerer = class {
928
1232
  if (hasElse) i = elseIdx;
929
1233
  continue;
930
1234
  }
931
- if (child.attributes.some((a) => a.kind === "EachDirective")) {
932
- out.push(this.lowerEach(child));
933
- continue;
934
- }
935
1235
  }
936
1236
  const node = this.lowerNode(child);
937
1237
  if (node) out.push(node);
@@ -945,7 +1245,7 @@ var Lowerer = class {
945
1245
  switch (node.kind) {
946
1246
  case "Text": {
947
1247
  if (node.raw) return { kind: "text", value: node.value };
948
- const cleaned = cleanTemplateText(node.value);
1248
+ const cleaned = decodeEntities(cleanTemplateText(node.value));
949
1249
  return cleaned ? { kind: "text", value: cleaned } : null;
950
1250
  }
951
1251
  case "Comment":
@@ -973,13 +1273,16 @@ var Lowerer = class {
973
1273
  node.props.unshift({ name: "component", kind: "attr", expr: `() => ${paren(this.hole(isAttr.value.hole).code, "arrowBody")}` });
974
1274
  return node;
975
1275
  }
1276
+ const each = this.lowerEach(el);
1277
+ const children = each ? [each] : this.lowerChildren(el.children);
1278
+ if (el.tag === CONTAINER) return children.length === 1 ? children[0] : { kind: "fragment", children };
976
1279
  const at = this.tagAt(el);
977
1280
  return {
978
1281
  kind: "element",
979
1282
  tag: el.tag,
980
1283
  svg: el.namespace === "svg",
981
- props: this.lowerAttributes(el.attributes),
982
- children: this.lowerChildren(el.children),
1284
+ props: this.lowerAttributes(el.attributes, true),
1285
+ children,
983
1286
  static: false,
984
1287
  ...at ? { at } : {}
985
1288
  };
@@ -1051,10 +1354,14 @@ var Lowerer = class {
1051
1354
  const at = this.tagAt(el);
1052
1355
  return { kind: "component", name: "Show", props, children: [child], ...at ? { at } : {}, ...cond.at ? { bindAt: cond.at } : {} };
1053
1356
  }
1054
- /** `<el each=${items} key?>${item => …}</el>` → `<For each>{item => <el>…</el>}</For>`. */
1357
+ /**
1358
+ * `<el each=${items} key?>${item => …}</el>` → `<el><For each>{item => …}</For></el>`: the
1359
+ * content is repeated per item. Content that is not a `${item => …}` arrow is repeated as
1360
+ * it is. Null when the element has no `each`.
1361
+ */
1055
1362
  lowerEach(el) {
1056
1363
  const eachDir = el.attributes.find((a) => a.kind === "EachDirective");
1057
- if (!eachDir || eachDir.kind !== "EachDirective") return this.lowerNode(el);
1364
+ if (!eachDir || eachDir.kind !== "EachDirective") return null;
1058
1365
  const each = this.hole(eachDir.hole);
1059
1366
  const props = [{ name: "each", kind: "attr", expr: each.code, reactive: each.reactive, ...each.at ? { at: each.at } : {} }];
1060
1367
  if (eachDir.key) {
@@ -1064,12 +1371,12 @@ var Lowerer = class {
1064
1371
  const arrow = this.itemArrow(el);
1065
1372
  let childrenCode;
1066
1373
  if (arrow) {
1067
- const bodyIR = { kind: "expr", code: arrow.body, reactive: arrow.bodyReactive };
1068
- const repeated = this.rebuildWithChildren(el, [bodyIR]);
1069
- childrenCode = `(${arrow.params.join(", ")}) => ${paren(this.emit(repeated), "arrowBody")}`;
1374
+ const body = arrow.bodyReactive ? `() => ${paren(arrow.body, "arrowBody")}` : paren(arrow.body, "arrowBody");
1375
+ childrenCode = `(${arrow.params.join(", ")}) => ${body}`;
1070
1376
  } else {
1071
- const repeated = this.stripAndLower(el, (a) => a.kind === "EachDirective");
1072
- childrenCode = `() => ${paren(this.emit(repeated), "arrowBody")}`;
1377
+ const content = this.lowerChildren(el.children);
1378
+ const ir = content.length === 1 ? content[0] : { kind: "fragment", children: content };
1379
+ childrenCode = `() => ${paren(this.emit(ir), "arrowBody")}`;
1073
1380
  }
1074
1381
  const children = [{ kind: "expr", code: childrenCode, reactive: false }];
1075
1382
  const at = this.tagAt(el);
@@ -1086,33 +1393,23 @@ var Lowerer = class {
1086
1393
  const clone = { ...el, attributes: el.attributes.filter((a) => !drop(a)) };
1087
1394
  return clone.kind === "Element" ? this.lowerElement(clone) : this.lowerComponent(clone);
1088
1395
  }
1089
- /** Same element (minus each/key) but with explicit IR children. */
1090
- rebuildWithChildren(el, children) {
1091
- const props = this.lowerAttributes(
1092
- el.attributes.filter((a) => a.kind !== "EachDirective")
1093
- );
1094
- if (el.kind === "Element") {
1095
- const at = this.tagAt(el);
1096
- return {
1097
- kind: "element",
1098
- tag: el.tag,
1099
- svg: el.namespace === "svg",
1100
- props,
1101
- children,
1102
- static: false,
1103
- ...at ? { at } : {}
1104
- };
1105
- }
1106
- return { kind: "component", name: el.tag, props, children };
1107
- }
1108
1396
  // --- attributes ---------------------------------------------------------
1109
- lowerAttributes(attrs) {
1397
+ /**
1398
+ * `element`: a DOM element, where each class:/style: value that moves is its own accessor.
1399
+ * A component gets the object as before, rebuilt whole when any value moves.
1400
+ */
1401
+ lowerAttributes(attrs, element = false) {
1402
+ let anyReactive = false;
1403
+ const entry = (name, h) => {
1404
+ anyReactive ||= h.reactive;
1405
+ if (!element || !h.reactive) return `${JSON.stringify(name)}: ${h.code}`;
1406
+ const accessor = `() => ${paren(h.code, "arrowBody")}`;
1407
+ return `${JSON.stringify(name)}: ${h.at ? markHole(accessor, h.at.line, h.at.column) : accessor}`;
1408
+ };
1110
1409
  const props = [];
1111
1410
  const classEntries = [];
1112
- let classReactive = false;
1113
1411
  let classAt;
1114
1412
  const styleEntries = [];
1115
- let styleReactive = false;
1116
1413
  let styleAt;
1117
1414
  const usePairs = [];
1118
1415
  for (const a of attrs) {
@@ -1152,15 +1449,13 @@ var Lowerer = class {
1152
1449
  break;
1153
1450
  case "ClassDirective": {
1154
1451
  const h = this.hole(a.hole);
1155
- classEntries.push(`${JSON.stringify(a.name)}: ${h.code}`);
1156
- classReactive = classReactive || h.reactive;
1452
+ classEntries.push(entry(a.name, h));
1157
1453
  classAt ??= h.at;
1158
1454
  break;
1159
1455
  }
1160
1456
  case "StyleDirective": {
1161
1457
  const h = this.hole(a.hole);
1162
- styleEntries.push(`${JSON.stringify(a.name)}: ${h.code}`);
1163
- styleReactive = styleReactive || h.reactive;
1458
+ styleEntries.push(entry(a.name, h));
1164
1459
  styleAt ??= h.at;
1165
1460
  break;
1166
1461
  }
@@ -1180,18 +1475,19 @@ var Lowerer = class {
1180
1475
  name: "classList",
1181
1476
  kind: "attr",
1182
1477
  expr: `{ ${classEntries.join(", ")} }`,
1183
- reactive: classReactive,
1478
+ reactive: !element && anyReactive,
1184
1479
  ...classAt ? { at: classAt } : {}
1185
1480
  });
1186
1481
  }
1187
1482
  if (styleEntries.length > 0) {
1188
- props.push({
1189
- name: "style",
1190
- kind: "attr",
1191
- expr: `{ ${styleEntries.join(", ")} }`,
1192
- reactive: styleReactive,
1193
- ...styleAt ? { at: styleAt } : {}
1194
- });
1483
+ const entries = `{ ${styleEntries.join(", ")} }`;
1484
+ const base = props.findIndex((p) => p.name === "style");
1485
+ if (base === -1) props.push({ name: "style", kind: "attr", expr: entries, reactive: !element && anyReactive, ...styleAt ? { at: styleAt } : {} });
1486
+ else {
1487
+ const prop = props[base];
1488
+ const value = prop.expr === void 0 ? JSON.stringify(prop.literal) : prop.reactive ? `() => ${paren(prop.expr, "arrowBody")}` : prop.expr;
1489
+ props[base] = { name: "style", kind: "attr", expr: `[${value}, ${entries}]`, reactive: false, ...prop.at ? { at: prop.at } : {} };
1490
+ }
1195
1491
  }
1196
1492
  if (usePairs.length > 0) {
1197
1493
  props.push({ name: "use", kind: "attr", expr: `[${usePairs.join(", ")}]` });
@@ -1280,7 +1576,7 @@ var Lowerer = class {
1280
1576
  return base;
1281
1577
  }
1282
1578
  if (v.kind === "static") {
1283
- base.literal = v.value;
1579
+ base.literal = decodeEntities(v.value);
1284
1580
  return base;
1285
1581
  }
1286
1582
  if (v.kind === "hole") {
@@ -1293,7 +1589,7 @@ var Lowerer = class {
1293
1589
  let reactive = false;
1294
1590
  let at;
1295
1591
  const body = v.parts.map((p) => {
1296
- if ("text" in p) return escapeTemplate(p.text);
1592
+ if ("text" in p) return escapeTemplate(decodeEntities(p.text));
1297
1593
  const h = this.hole(p.hole);
1298
1594
  reactive = reactive || h.reactive;
1299
1595
  at ??= h.at;
@@ -1340,6 +1636,7 @@ function compilePieces(pieces, holes, options = {}) {
1340
1636
  ...options.sourceFile ? { sourceFile: options.sourceFile } : {},
1341
1637
  ...options.positionAt ? { positionAt: options.positionAt } : {}
1342
1638
  });
1639
+ if (options.templateStyles) applyTemplateStyles(ir, options.templateStyles);
1343
1640
  analyzeStatic(ir);
1344
1641
  resolveComponentSources(ir, {
1345
1642
  resolver: createComponentResolver(options.resolve ?? []),
@@ -1,3 +1,14 @@
1
+ /**
2
+ * Compile a `` html`...` `` template to runtime calls, with no JS toolchain in
3
+ * the path.
4
+ *
5
+ * statics + holes → parseTemplate → IR → resolve → optimize → codegen → code
6
+ *
7
+ * Finding templates in a module and describing each hole still needs a front-end;
8
+ * everything after that point is here. Passes run in the same order as
9
+ * `emitLitViaIR`: compile-template.spec.ts compares the two.
10
+ */
11
+ import { type TemplateStyles } from '../transform/styles.cjs';
1
12
  import { type ComponentResolverRule } from '../resolve/component-resolver.cjs';
2
13
  import type { IRNode } from '../ir/nodes.cjs';
3
14
  import { type TemplateHole } from './template.cjs';
@@ -45,6 +56,8 @@ export interface CompileTemplateOptions {
45
56
  line: number;
46
57
  column: number;
47
58
  };
59
+ /** `<style>` blocks and scope stamping for this template (see transform/styles.ts). */
60
+ templateStyles?: TemplateStyles;
48
61
  }
49
62
  export interface CompileTemplateResult {
50
63
  /** A JavaScript expression that builds the DOM when evaluated. */
@@ -1,3 +1,14 @@
1
+ /**
2
+ * Compile a `` html`...` `` template to runtime calls, with no JS toolchain in
3
+ * the path.
4
+ *
5
+ * statics + holes → parseTemplate → IR → resolve → optimize → codegen → code
6
+ *
7
+ * Finding templates in a module and describing each hole still needs a front-end;
8
+ * everything after that point is here. Passes run in the same order as
9
+ * `emitLitViaIR`: compile-template.spec.ts compares the two.
10
+ */
11
+ import { type TemplateStyles } from '../transform/styles.js';
1
12
  import { type ComponentResolverRule } from '../resolve/component-resolver.js';
2
13
  import type { IRNode } from '../ir/nodes.js';
3
14
  import { type TemplateHole } from './template.js';
@@ -45,6 +56,8 @@ export interface CompileTemplateOptions {
45
56
  line: number;
46
57
  column: number;
47
58
  };
59
+ /** `<style>` blocks and scope stamping for this template (see transform/styles.ts). */
60
+ templateStyles?: TemplateStyles;
48
61
  }
49
62
  export interface CompileTemplateResult {
50
63
  /** A JavaScript expression that builds the DOM when evaluated. */
@@ -1 +1 @@
1
- {"version":3,"file":"compile-template.d.ts","sourceRoot":"","sources":["../../src/lower/compile-template.ts"],"names":[],"mappings":"AAcA,OAAO,EAA2B,KAAK,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACvG,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAiB,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AACjE,YAAY,EAAE,YAAY,EAAE,CAAC;AAC7B,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,kDAAkD;IAClD,KAAK,EAAE,SAAS,YAAY,EAAE,CAAC;CAChC;AAED,MAAM,WAAW,sBAAsB;IACrC,4EAA4E;IAC5E,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,yFAAyF;IACzF,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,6EAA6E;IAC7E,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,iEAAiE;IACjE,OAAO,CAAC,EAAE,SAAS,qBAAqB,EAAE,CAAC;IAC3C,8EAA8E;IAC9E,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,uFAAuF;IACvF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wEAAwE;IACxE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CACnE;AAED,MAAM,WAAW,qBAAqB;IACpC,kEAAkE;IAClE,IAAI,EAAE,MAAM,CAAC;IACb,oEAAoE;IACpE,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,sFAAsF;IACtF,EAAE,EAAE,MAAM,CAAC;IACX;;;;OAIG;IACH,SAAS,CAAC,EAAE,cAAc,EAAE,CAAC;CAC9B;AAqBD,wBAAgB,eAAe,CAC7B,MAAM,EAAE,cAAc,EACtB,OAAO,GAAE,sBAA2B,GACnC,qBAAqB,CASvB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,KAAK,EAAE,EACf,KAAK,EAAE,SAAS,YAAY,EAAE,EAC9B,OAAO,GAAE,sBAA2B,GACnC,qBAAqB,CA8BvB"}
1
+ {"version":3,"file":"compile-template.d.ts","sourceRoot":"","sources":["../../src/lower/compile-template.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAuB,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAKlF,OAAO,EAA2B,KAAK,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACvG,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAiB,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AACjE,YAAY,EAAE,YAAY,EAAE,CAAC;AAC7B,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,kDAAkD;IAClD,KAAK,EAAE,SAAS,YAAY,EAAE,CAAC;CAChC;AAED,MAAM,WAAW,sBAAsB;IACrC,4EAA4E;IAC5E,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,yFAAyF;IACzF,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,6EAA6E;IAC7E,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,iEAAiE;IACjE,OAAO,CAAC,EAAE,SAAS,qBAAqB,EAAE,CAAC;IAC3C,8EAA8E;IAC9E,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,uFAAuF;IACvF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wEAAwE;IACxE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAClE,uFAAuF;IACvF,cAAc,CAAC,EAAE,cAAc,CAAC;CACjC;AAED,MAAM,WAAW,qBAAqB;IACpC,kEAAkE;IAClE,IAAI,EAAE,MAAM,CAAC;IACb,oEAAoE;IACpE,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,sFAAsF;IACtF,EAAE,EAAE,MAAM,CAAC;IACX;;;;OAIG;IACH,SAAS,CAAC,EAAE,cAAc,EAAE,CAAC;CAC9B;AAqBD,wBAAgB,eAAe,CAC7B,MAAM,EAAE,cAAc,EACtB,OAAO,GAAE,sBAA2B,GACnC,qBAAqB,CASvB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,KAAK,EAAE,EACf,KAAK,EAAE,SAAS,YAAY,EAAE,EAC9B,OAAO,GAAE,sBAA2B,GACnC,qBAAqB,CA+BvB"}
@@ -8,6 +8,7 @@
8
8
  * everything after that point is here. Passes run in the same order as
9
9
  * `emitLitViaIR`: compile-template.spec.ts compares the two.
10
10
  */
11
+ import { applyTemplateStyles } from '../transform/styles.js';
11
12
  import { analyzeStatic } from '../optimize/analyze-static.js';
12
13
  import { collapseStrategies } from '../optimize/collapse-strategies.js';
13
14
  import { imperativeBackend, inlineTemplates } from '../codegen/backends/imperative.js';
@@ -51,6 +52,8 @@ export function compilePieces(pieces, holes, options = {}) {
51
52
  ...(options.sourceFile ? { sourceFile: options.sourceFile } : {}),
52
53
  ...(options.positionAt ? { positionAt: options.positionAt } : {}),
53
54
  });
55
+ if (options.templateStyles)
56
+ applyTemplateStyles(ir, options.templateStyles);
54
57
  analyzeStatic(ir);
55
58
  // Same order as the Babel front-end: decide where each component reference
56
59
  // comes from, then drop deferred boundaries around modules already in the chunk.