@fluixi/compiler 1.0.0-alpha.83 → 1.0.0-alpha.85

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 (241) hide show
  1. package/dist/analyze/expr-shape.cjs +62 -1
  2. package/dist/analyze/expr-shape.d.cts +14 -0
  3. package/dist/analyze/expr-shape.d.ts +2 -2
  4. package/dist/analyze/expr-shape.js +1 -1
  5. package/dist/analyze/expr-shape.mjs +41 -1
  6. package/dist/analyze/intrinsics.cjs +80 -1
  7. package/dist/analyze/intrinsics.d.cts +66 -0
  8. package/dist/analyze/intrinsics.d.ts +7 -7
  9. package/dist/analyze/intrinsics.d.ts.map +1 -1
  10. package/dist/analyze/intrinsics.js +3 -3
  11. package/dist/analyze/intrinsics.mjs +59 -1
  12. package/dist/analyze/paren.cjs +134 -0
  13. package/dist/analyze/paren.d.cts +23 -0
  14. package/dist/analyze/paren.d.ts +24 -0
  15. package/dist/analyze/paren.d.ts.map +1 -0
  16. package/dist/analyze/paren.js +168 -0
  17. package/dist/analyze/paren.mjs +113 -0
  18. package/dist/analyze/props-destructure.cjs +226 -1
  19. package/dist/analyze/props-destructure.d.cts +83 -0
  20. package/dist/analyze/props-destructure.d.ts +3 -3
  21. package/dist/analyze/props-destructure.d.ts.map +1 -1
  22. package/dist/analyze/props-destructure.js +4 -4
  23. package/dist/analyze/props-destructure.mjs +205 -1
  24. package/dist/analyze/reactive-bindings.cjs +190 -1
  25. package/dist/analyze/reactive-bindings.d.cts +42 -0
  26. package/dist/analyze/reactive-bindings.d.ts +1 -1
  27. package/dist/analyze/reactive-bindings.js +2 -2
  28. package/dist/analyze/reactive-bindings.mjs +167 -1
  29. package/dist/analyze/reactive-expr.cjs +38 -1
  30. package/dist/analyze/reactive-expr.d.cts +38 -0
  31. package/dist/analyze/reactive-expr.d.ts +4 -4
  32. package/dist/analyze/reactive-expr.d.ts.map +1 -1
  33. package/dist/analyze/reactive-expr.js +2 -2
  34. package/dist/analyze/reactive-expr.mjs +17 -1
  35. package/dist/analyze/static-graph.cjs +811 -1
  36. package/dist/analyze/static-graph.d.cts +102 -0
  37. package/dist/analyze/static-graph.d.ts +1 -1
  38. package/dist/analyze/static-graph.d.ts.map +1 -1
  39. package/dist/analyze/static-graph.js +11 -11
  40. package/dist/analyze/static-graph.mjs +793 -1
  41. package/dist/babel-TGY76XJ7.mjs +636 -0
  42. package/dist/chunk-4PLHS2FP.mjs +158 -0
  43. package/dist/chunk-6DB5FXS4.mjs +1718 -0
  44. package/dist/chunk-F74GFKSL.mjs +16 -0
  45. package/dist/chunk-G6QC2WRJ.mjs +11 -0
  46. package/dist/chunk-RUDJDZAA.mjs +1078 -0
  47. package/dist/codegen/backend.cjs +18 -1
  48. package/dist/codegen/backend.d.cts +35 -0
  49. package/dist/codegen/backends/imperative.cjs +542 -1
  50. package/dist/codegen/backends/imperative.d.cts +11 -0
  51. package/dist/codegen/backends/imperative.d.ts +1 -1
  52. package/dist/codegen/backends/imperative.d.ts.map +1 -1
  53. package/dist/codegen/backends/imperative.js +24 -20
  54. package/dist/codegen/backends/imperative.mjs +519 -1
  55. package/dist/codegen/contract.cjs +52 -1
  56. package/dist/codegen/contract.d.cts +24 -0
  57. package/dist/codegen/contract.d.ts +2 -2
  58. package/dist/codegen/contract.js +2 -2
  59. package/dist/codegen/contract.mjs +31 -1
  60. package/dist/codegen/partial-template.cjs +176 -1
  61. package/dist/codegen/partial-template.d.cts +61 -0
  62. package/dist/codegen/partial-template.d.ts +4 -4
  63. package/dist/codegen/partial-template.js +0 -0
  64. package/dist/codegen/partial-template.mjs +153 -1
  65. package/dist/codegen/serialize-static.cjs +125 -1
  66. package/dist/codegen/serialize-static.d.cts +38 -0
  67. package/dist/codegen/serialize-static.d.ts +3 -3
  68. package/dist/codegen/serialize-static.js +6 -6
  69. package/dist/codegen/serialize-static.mjs +104 -1
  70. package/dist/frontend/babel/build-ir-lit.cjs +1509 -1
  71. package/dist/frontend/babel/build-ir-lit.d.cts +26 -0
  72. package/dist/frontend/babel/build-ir-lit.d.ts +2 -2
  73. package/dist/frontend/babel/build-ir-lit.mjs +1478 -1
  74. package/dist/frontend/babel/build-ir.cjs +1524 -1
  75. package/dist/frontend/babel/build-ir.d.cts +35 -0
  76. package/dist/frontend/babel/build-ir.d.ts +2 -2
  77. package/dist/frontend/babel/build-ir.js +2 -2
  78. package/dist/frontend/babel/build-ir.mjs +1495 -1
  79. package/dist/frontend/babel/index.cjs +2186 -1
  80. package/dist/frontend/babel/index.d.cts +33 -0
  81. package/dist/frontend/babel/index.d.ts +1 -1
  82. package/dist/frontend/babel/index.js +1 -1
  83. package/dist/frontend/babel/index.mjs +2156 -1
  84. package/dist/frontend/babel/lower-template.cjs +1507 -1
  85. package/dist/frontend/babel/lower-template.d.cts +23 -0
  86. package/dist/frontend/babel/lower-template.d.ts +1 -1
  87. package/dist/frontend/babel/lower-template.js +2 -2
  88. package/dist/frontend/babel/lower-template.mjs +1478 -1
  89. package/dist/frontend/babel/plugin.cjs +2132 -1
  90. package/dist/frontend/babel/plugin.d.cts +95 -0
  91. package/dist/frontend/babel/plugin.d.ts +5 -5
  92. package/dist/frontend/babel/plugin.d.ts.map +1 -1
  93. package/dist/frontend/babel/plugin.js +14 -14
  94. package/dist/frontend/babel/plugin.mjs +2103 -1
  95. package/dist/frontend/babel/server-functions.cjs +110 -1
  96. package/dist/frontend/babel/server-functions.d.cts +10 -0
  97. package/dist/frontend/babel/server-functions.mjs +89 -1
  98. package/dist/frontend/babel/types.cjs +18 -1
  99. package/dist/frontend/babel/types.d.cts +33 -0
  100. package/dist/frontend/types.cjs +18 -1
  101. package/dist/frontend/types.d.cts +25 -0
  102. package/dist/frontend/vocabulary.cjs +98 -0
  103. package/dist/frontend/vocabulary.d.cts +79 -0
  104. package/dist/frontend/vocabulary.d.ts +80 -0
  105. package/dist/frontend/vocabulary.d.ts.map +1 -0
  106. package/dist/frontend/vocabulary.js +124 -0
  107. package/dist/frontend/vocabulary.mjs +77 -0
  108. package/dist/index.cjs +1595 -14
  109. package/dist/index.d.cts +27 -0
  110. package/dist/index.d.ts +1 -1
  111. package/dist/index.js +4 -4
  112. package/dist/index.mjs +1575 -14
  113. package/dist/integrations.cjs +4312 -26
  114. package/dist/integrations.d.cts +215 -0
  115. package/dist/integrations.d.ts +9 -9
  116. package/dist/integrations.d.ts.map +1 -1
  117. package/dist/integrations.js +29 -8
  118. package/dist/integrations.mjs +536 -18
  119. package/dist/ir/nodes.cjs +18 -1
  120. package/dist/ir/nodes.d.cts +168 -0
  121. package/dist/ir/nodes.d.ts +6 -6
  122. package/dist/lower/compile-template.cjs +1356 -1
  123. package/dist/lower/compile-template.d.cts +69 -0
  124. package/dist/lower/compile-template.d.ts +3 -3
  125. package/dist/lower/compile-template.js +1 -1
  126. package/dist/lower/compile-template.mjs +1336 -1
  127. package/dist/lower/jsx.cjs +529 -1
  128. package/dist/lower/jsx.d.cts +25 -0
  129. package/dist/lower/jsx.d.ts +1 -1
  130. package/dist/lower/jsx.d.ts.map +1 -1
  131. package/dist/lower/jsx.js +6 -5
  132. package/dist/lower/jsx.mjs +506 -1
  133. package/dist/lower/template.cjs +1061 -1
  134. package/dist/lower/template.d.cts +53 -0
  135. package/dist/lower/template.d.ts +3 -3
  136. package/dist/lower/template.d.ts.map +1 -1
  137. package/dist/lower/template.js +12 -11
  138. package/dist/lower/template.mjs +1042 -1
  139. package/dist/lower/text.cjs +42 -1
  140. package/dist/lower/text.d.cts +10 -0
  141. package/dist/lower/text.d.ts +2 -2
  142. package/dist/lower/text.d.ts.map +1 -1
  143. package/dist/lower/text.js +2 -2
  144. package/dist/lower/text.mjs +21 -1
  145. package/dist/optimize/analyze-static.cjs +112 -1
  146. package/dist/optimize/analyze-static.d.cts +39 -0
  147. package/dist/optimize/analyze-static.d.ts +2 -2
  148. package/dist/optimize/analyze-static.js +2 -2
  149. package/dist/optimize/analyze-static.mjs +91 -1
  150. package/dist/optimize/collapse-strategies.cjs +90 -1
  151. package/dist/optimize/collapse-strategies.d.cts +30 -0
  152. package/dist/optimize/collapse-strategies.d.ts +3 -3
  153. package/dist/optimize/collapse-strategies.mjs +67 -1
  154. package/dist/options.cjs +33 -1
  155. package/dist/options.d.cts +39 -0
  156. package/dist/options.d.ts +2 -2
  157. package/dist/options.mjs +12 -1
  158. package/dist/resolve/builtins.cjs +73 -1
  159. package/dist/resolve/builtins.d.cts +68 -0
  160. package/dist/resolve/builtins.d.ts +8 -8
  161. package/dist/resolve/builtins.d.ts.map +1 -1
  162. package/dist/resolve/builtins.js +4 -4
  163. package/dist/resolve/builtins.mjs +53 -1
  164. package/dist/resolve/component-globals.cjs +234 -14
  165. package/dist/resolve/component-globals.d.cts +80 -0
  166. package/dist/resolve/component-globals.d.ts +5 -5
  167. package/dist/resolve/component-globals.js +10 -10
  168. package/dist/resolve/component-globals.mjs +211 -14
  169. package/dist/resolve/component-resolver.cjs +80 -1
  170. package/dist/resolve/component-resolver.d.cts +68 -0
  171. package/dist/resolve/component-resolver.d.ts +3 -3
  172. package/dist/resolve/component-resolver.d.ts.map +1 -1
  173. package/dist/resolve/component-resolver.js +3 -3
  174. package/dist/resolve/component-resolver.mjs +59 -1
  175. package/dist/resolve/load-directive.cjs +93 -1
  176. package/dist/resolve/load-directive.d.cts +53 -0
  177. package/dist/resolve/load-directive.d.ts +5 -5
  178. package/dist/resolve/load-directive.js +6 -6
  179. package/dist/resolve/load-directive.mjs +72 -1
  180. package/dist/resolve/resolve-ir.cjs +108 -1
  181. package/dist/resolve/resolve-ir.d.cts +53 -0
  182. package/dist/resolve/resolve-ir.d.ts +6 -6
  183. package/dist/resolve/resolve-ir.d.ts.map +1 -1
  184. package/dist/resolve/resolve-ir.js +1 -1
  185. package/dist/resolve/resolve-ir.mjs +85 -1
  186. package/dist/resolve/write-globals.cjs +319 -14
  187. package/dist/resolve/write-globals.d.cts +30 -0
  188. package/dist/resolve/write-globals.js +2 -2
  189. package/dist/resolve/write-globals.mjs +298 -14
  190. package/dist/server-fns-ZYWQTSZU.mjs +78 -0
  191. package/dist/server-functions-PCERFA7A.mjs +82 -0
  192. package/dist/transform/bindings.cjs +71 -1
  193. package/dist/transform/bindings.d.cts +16 -0
  194. package/dist/transform/bindings.d.ts +1 -1
  195. package/dist/transform/bindings.js +1 -1
  196. package/dist/transform/bindings.mjs +50 -1
  197. package/dist/transform/index.cjs +2732 -8
  198. package/dist/transform/index.d.cts +15 -0
  199. package/dist/transform/index.mjs +3773 -17
  200. package/dist/transform/intrinsics.cjs +216 -3
  201. package/dist/transform/intrinsics.d.cts +21 -0
  202. package/dist/transform/intrinsics.js +1 -1
  203. package/dist/transform/intrinsics.mjs +193 -3
  204. package/dist/transform/props.cjs +441 -3
  205. package/dist/transform/props.d.cts +45 -0
  206. package/dist/transform/props.d.ts +1 -1
  207. package/dist/transform/props.d.ts.map +1 -1
  208. package/dist/transform/props.js +4 -4
  209. package/dist/transform/props.mjs +1482 -12
  210. package/dist/transform/server-fn-id.cjs +35 -1
  211. package/dist/transform/server-fn-id.d.cts +9 -0
  212. package/dist/transform/server-fn-id.d.ts +1 -1
  213. package/dist/transform/server-fn-id.js +2 -2
  214. package/dist/transform/server-fn-id.mjs +14 -1
  215. package/dist/transform/server-fns.cjs +114 -2
  216. package/dist/transform/server-fns.d.cts +12 -0
  217. package/dist/transform/server-fns.js +3 -3
  218. package/dist/transform/server-fns.mjs +1155 -11
  219. package/dist/transform/source-locations.cjs +330 -1
  220. package/dist/transform/source-locations.d.cts +43 -0
  221. package/dist/transform/source-locations.d.ts +1 -1
  222. package/dist/transform/source-locations.js +5 -5
  223. package/dist/transform/source-locations.mjs +307 -1
  224. package/dist/transform/templates.cjs +2701 -7
  225. package/dist/transform/templates.d.cts +69 -0
  226. package/dist/transform/templates.d.ts +2 -2
  227. package/dist/transform/templates.d.ts.map +1 -1
  228. package/dist/transform/templates.js +7 -7
  229. package/dist/transform/templates.mjs +3743 -16
  230. package/dist/transform-RWDTQUF5.mjs +893 -0
  231. package/dist/tsconfig.lib.tsbuildinfo +1 -1
  232. package/package.json +6 -5
  233. package/dist/babel-VXKH6MRQ.mjs +0 -1
  234. package/dist/chunk-3SAEGOMQ.mjs +0 -1
  235. package/dist/chunk-5KMMN5QP.mjs +0 -1
  236. package/dist/chunk-IBRM4W7I.mjs +0 -10
  237. package/dist/chunk-OHHZCYIQ.mjs +0 -1
  238. package/dist/chunk-YKZ54NVE.mjs +0 -1
  239. package/dist/server-fns-6QM243HC.mjs +0 -2
  240. package/dist/server-functions-E3LKCZ4R.mjs +0 -1
  241. package/dist/transform-C4ZXRVGP.mjs +0 -8
@@ -0,0 +1,636 @@
1
+ /*! @fluixi/compiler v1.0.0-alpha.85 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
2
+ import {
3
+ analyzeStatic,
4
+ buildJsxIR,
5
+ collapseStrategies,
6
+ imperativeBackend,
7
+ inlineTemplates,
8
+ isDeferred,
9
+ isReactiveShape,
10
+ lowerTemplate,
11
+ resolveComponentSources,
12
+ shapeOf
13
+ } from "./chunk-6DB5FXS4.mjs";
14
+ import {
15
+ CORE_CONTROL_FLOW,
16
+ ROUTER_COMPONENTS,
17
+ createComponentResolver
18
+ } from "./chunk-4PLHS2FP.mjs";
19
+ import "./chunk-G6QC2WRJ.mjs";
20
+
21
+ // src/frontend/babel/plugin.ts
22
+ import { declare } from "@babel/helper-plugin-utils";
23
+ import { types as t3, template as template2 } from "@babel/core";
24
+
25
+ // src/frontend/babel/build-ir.ts
26
+ import { types as t2, traverse, template } from "@babel/core";
27
+ import _generate2 from "@babel/generator";
28
+
29
+ // src/frontend/babel/lower-template.ts
30
+ import { types as t } from "@babel/core";
31
+ import _generate from "@babel/generator";
32
+ var generate = _generate.default ?? _generate;
33
+ function gen(node) {
34
+ return generate(node, { concise: true }).code;
35
+ }
36
+ function bindHole(expr, used, onNested) {
37
+ const hole = {
38
+ code: genExpr(expr, used, onNested),
39
+ reactive: isReactiveExpr(expr)
40
+ };
41
+ if (t.isArrowFunctionExpression(expr) && !t.isBlockStatement(expr.body)) {
42
+ const body = expr.body;
43
+ hole.arrow = {
44
+ params: expr.params.map((p) => gen(p)),
45
+ body: genExpr(body, used, onNested),
46
+ bodyReactive: isReactiveExpr(body)
47
+ };
48
+ }
49
+ if (t.isObjectExpression(expr)) hole.object = true;
50
+ return hole;
51
+ }
52
+ function lowerLitTemplate(node, used, opts = {}) {
53
+ const quasi = node.quasi;
54
+ const holes = quasi.expressions.map((e) => bindHole(e, used, opts.onNested));
55
+ return lowerTemplate(buildPieces(quasi), holes, used, opts);
56
+ }
57
+ function buildPieces(quasi) {
58
+ const pieces = [];
59
+ quasi.quasis.forEach((q, i) => {
60
+ const text = q.value.cooked ?? q.value.raw;
61
+ pieces.push({ kind: "static", text, start: q.start ?? 0 });
62
+ if (i < quasi.expressions.length) {
63
+ const e = quasi.expressions[i];
64
+ pieces.push({ kind: "hole", index: i, start: e.start ?? 0, end: e.end ?? 0 });
65
+ }
66
+ });
67
+ return pieces;
68
+ }
69
+
70
+ // src/frontend/babel/build-ir-lit.ts
71
+ function buildIRFromLit(node, used = /* @__PURE__ */ new Set(), opts = {}) {
72
+ const ir = lowerLitTemplate(node, used, opts);
73
+ analyzeStatic(ir);
74
+ return ir;
75
+ }
76
+
77
+ // src/frontend/babel/build-ir.ts
78
+ var generate2 = _generate2.default ?? _generate2;
79
+ function gen2(node) {
80
+ return generate2(node, { concise: true }).code;
81
+ }
82
+ function transformNestedJSX(node, used, onNested) {
83
+ const clone = t2.cloneNode(node, true);
84
+ const file = t2.file(t2.program([t2.expressionStatement(clone)]));
85
+ let changed = false;
86
+ const emitInto = (path, code, imports) => {
87
+ for (const s of imports) used.add(s);
88
+ path.replaceWith(template.expression(code, { placeholderPattern: false, plugins: ["typescript"] })());
89
+ path.skip();
90
+ changed = true;
91
+ };
92
+ traverse(file, {
93
+ "JSXElement|JSXFragment"(path) {
94
+ const jsx = path.node;
95
+ const nestedIR = buildIR(jsx, used, onNested);
96
+ onNested?.(nestedIR);
97
+ const { code, imports, templates } = imperativeBackend.emit(nestedIR, {});
98
+ emitInto(path, inlineTemplates(code, templates), imports);
99
+ },
100
+ // Nested lit templates compose: ${cond ? html`…` : html`…`},
101
+ // ${list.map(x => html`<li>${x}</li>`)}. Compile them the same way.
102
+ TaggedTemplateExpression(path) {
103
+ const tag = path.node.tag;
104
+ if (!t2.isIdentifier(tag) || tag.name !== "html" && tag.name !== "svg") return;
105
+ const ir = buildIRFromLit(path.node, used, { svg: tag.name === "svg", onNested });
106
+ onNested?.(ir);
107
+ const { code, imports, templates } = imperativeBackend.emit(ir, {});
108
+ emitInto(path, inlineTemplates(code, templates), imports);
109
+ }
110
+ });
111
+ return changed ? file.program.body[0].expression : node;
112
+ }
113
+ function genExpr(node, used, onNested) {
114
+ return gen2(transformNestedJSX(node, used, onNested));
115
+ }
116
+ function isReactiveExpr(node) {
117
+ return isReactiveShape(shapeOf(node));
118
+ }
119
+ function buildIR(node, used = /* @__PURE__ */ new Set(), onNested) {
120
+ const ir = buildJsxIR(node, {
121
+ code: (n) => (
122
+ // A member-expression tag (`<ns.Foo/>`) is not an Expression, so it cannot go
123
+ // through the nested-JSX compile: it only ever needs printing.
124
+ n.type === "JSXMemberExpression" ? gen2(n) : genExpr(n, used, onNested)
125
+ ),
126
+ used
127
+ });
128
+ return ir;
129
+ }
130
+
131
+ // src/frontend/babel/plugin.ts
132
+ var CORE_ONLY_CONTROL_FLOW = new Set(CORE_CONTROL_FLOW);
133
+ var ROUTER_COMPONENTS2 = new Set(ROUTER_COMPONENTS);
134
+ var plugin_default = declare((api, options = {}) => {
135
+ api.assertVersion(7);
136
+ const {
137
+ delegateEvents = true,
138
+ signalModule = "@fluixi/dom",
139
+ controlFlowModule = "@fluixi/dom",
140
+ routerModule = "@fluixi/core/router",
141
+ reactiveModule = "@fluixi/reactive/signal",
142
+ templateClone = true,
143
+ partialTemplates = true,
144
+ // `both` by default: JSX and html`` are compiled out of the box, so
145
+ // `fluixi()` needs no `format` option. Injected imports are deduped, so a
146
+ // file mixing the two styles won't redeclare a binding.
147
+ format = "both",
148
+ litTag = "html",
149
+ resolve: resolveRules = []
150
+ } = options;
151
+ const componentResolver = createComponentResolver(resolveRules);
152
+ const compileLit = format === "lit" || format === "both";
153
+ const pluginState = {
154
+ irImports: /* @__PURE__ */ new Set(),
155
+ libModule: "@fluixi/core",
156
+ controlFlowModule,
157
+ routerModule,
158
+ templateClone,
159
+ partialTemplates,
160
+ hasJSX: false,
161
+ hasLitHTML: false,
162
+ needsControlFlowImport: false,
163
+ needsCreateMemo: false,
164
+ controlFlowComponents: /* @__PURE__ */ new Set(),
165
+ resolvedComponents: /* @__PURE__ */ new Map(),
166
+ deferredComponents: /* @__PURE__ */ new Map(),
167
+ componentResolver,
168
+ delegatedEvents: /* @__PURE__ */ new Set(),
169
+ staticTemplates: /* @__PURE__ */ new Map(),
170
+ staticCounter: 0
171
+ };
172
+ return {
173
+ name: "@fluixi/babel-plugin-jsx",
174
+ manipulateOptions(opts, parserOpts) {
175
+ parserOpts.plugins.push("jsx", "typescript");
176
+ },
177
+ pre(state) {
178
+ Object.assign(state, pluginState);
179
+ },
180
+ visitor: {
181
+ Program: {
182
+ enter(path, state) {
183
+ Object.assign(state, {
184
+ hasJSX: false,
185
+ hasLitHTML: false,
186
+ hasLitIR: false,
187
+ needsControlFlowImport: false,
188
+ needsCreateMemo: false,
189
+ controlFlowComponents: /* @__PURE__ */ new Set(),
190
+ resolvedComponents: /* @__PURE__ */ new Map(),
191
+ deferredComponents: /* @__PURE__ */ new Map(),
192
+ componentResolver,
193
+ delegatedEvents: /* @__PURE__ */ new Set(),
194
+ staticTemplates: /* @__PURE__ */ new Map(),
195
+ staticCounter: 0,
196
+ libModule: "@fluixi/core",
197
+ controlFlowModule,
198
+ routerModule,
199
+ templateClone,
200
+ partialTemplates,
201
+ irImports: /* @__PURE__ */ new Set(),
202
+ needsCreateNativeElement: false,
203
+ needsInsert: false,
204
+ needsSpread: false,
205
+ needsCreateComponent: false,
206
+ needsMergeProps: false
207
+ });
208
+ },
209
+ exit(path, state) {
210
+ const imports = [];
211
+ if (state.hasJSX || state.hasLitIR) {
212
+ if (state.irImports.size > 0) {
213
+ const CF = /* @__PURE__ */ new Set([
214
+ "Show",
215
+ "For",
216
+ "Index",
217
+ "Switch",
218
+ "Match",
219
+ "Dynamic",
220
+ "ErrorBoundary",
221
+ "Portal",
222
+ "Suspense"
223
+ ]);
224
+ const REACTIVE = /* @__PURE__ */ new Set([
225
+ "createMemo",
226
+ "createEffect",
227
+ "createRenderEffect",
228
+ "createRoot",
229
+ "createSignal",
230
+ "onCleanup",
231
+ "batch",
232
+ "untrack"
233
+ ]);
234
+ const all = Array.from(state.irImports);
235
+ const spec = (n) => t3.importSpecifier(t3.identifier(n), t3.identifier(n));
236
+ const unbound = (s) => !path.scope.hasBinding(s);
237
+ const reactive = all.filter((s) => REACTIVE.has(s) && unbound(s));
238
+ const core = all.filter((s) => !CF.has(s) && !REACTIVE.has(s) && unbound(s));
239
+ const cf = all.filter((s) => CF.has(s) && unbound(s));
240
+ if (reactive.length > 0) {
241
+ imports.push(
242
+ t3.importDeclaration(reactive.map(spec), t3.stringLiteral(reactiveModule))
243
+ );
244
+ }
245
+ if (core.length > 0) {
246
+ imports.push(
247
+ t3.importDeclaration(core.map(spec), t3.stringLiteral(signalModule))
248
+ );
249
+ }
250
+ if (cf.length > 0) {
251
+ imports.push(
252
+ t3.importDeclaration(cf.map(spec), t3.stringLiteral(controlFlowModule))
253
+ );
254
+ }
255
+ }
256
+ if (state.needsCreateMemo && !path.scope.hasBinding("createMemo")) {
257
+ imports.push(
258
+ t3.importDeclaration(
259
+ [t3.importSpecifier(t3.identifier("createMemo"), t3.identifier("createMemo"))],
260
+ t3.stringLiteral(reactiveModule)
261
+ )
262
+ );
263
+ }
264
+ if (state.needsControlFlowImport && state.controlFlowComponents.size > 0) {
265
+ const unbound = Array.from(state.controlFlowComponents).filter(
266
+ (name) => !path.scope.hasBinding(name)
267
+ );
268
+ const coreModule = state.libModule ?? "@fluixi/core";
269
+ const fromRouter = unbound.filter((n) => ROUTER_COMPONENTS2.has(n));
270
+ const fromCore = unbound.filter((n) => CORE_ONLY_CONTROL_FLOW.has(n));
271
+ const fromDom = unbound.filter(
272
+ (n) => !CORE_ONLY_CONTROL_FLOW.has(n) && !ROUTER_COMPONENTS2.has(n)
273
+ );
274
+ const declFor = (names, mod) => t3.importDeclaration(
275
+ names.map((name) => t3.importSpecifier(t3.identifier(name), t3.identifier(name))),
276
+ t3.stringLiteral(mod)
277
+ );
278
+ if (fromDom.length > 0) imports.push(declFor(fromDom, controlFlowModule));
279
+ if (fromCore.length > 0) imports.push(declFor(fromCore, coreModule));
280
+ if (fromRouter.length > 0) imports.push(declFor(fromRouter, routerModule));
281
+ }
282
+ const deferredDecls = [];
283
+ if (state.deferredComponents.size > 0) {
284
+ for (const [local, entry] of state.deferredComponents) {
285
+ if (path.scope.hasBinding(local)) continue;
286
+ deferredDecls.push(
287
+ t3.variableDeclaration("const", [
288
+ t3.variableDeclarator(
289
+ t3.identifier(local),
290
+ t3.callExpression(t3.identifier("deferred"), [
291
+ t3.arrowFunctionExpression(
292
+ [],
293
+ t3.callExpression(t3.import(), [t3.stringLiteral(entry.module)])
294
+ ),
295
+ t3.objectExpression([
296
+ t3.objectProperty(
297
+ t3.identifier("strategy"),
298
+ strategyLiteral(entry.strategy)
299
+ ),
300
+ t3.objectProperty(
301
+ t3.identifier("export"),
302
+ t3.stringLiteral(entry.export)
303
+ )
304
+ ])
305
+ ])
306
+ )
307
+ ])
308
+ );
309
+ }
310
+ if (deferredDecls.length > 0 && !path.scope.hasBinding("deferred")) {
311
+ imports.push(
312
+ t3.importDeclaration(
313
+ [t3.importSpecifier(t3.identifier("deferred"), t3.identifier("deferred"))],
314
+ t3.stringLiteral(state.libModule ?? "@fluixi/core")
315
+ )
316
+ );
317
+ }
318
+ }
319
+ if (state.resolvedComponents.size > 0) {
320
+ const byModule = /* @__PURE__ */ new Map();
321
+ for (const [local, resolved] of state.resolvedComponents) {
322
+ if (path.scope.hasBinding(local)) continue;
323
+ const list = byModule.get(resolved.module) ?? [];
324
+ list.push({ local, exported: resolved.export });
325
+ byModule.set(resolved.module, list);
326
+ }
327
+ for (const [mod, entries] of byModule) {
328
+ imports.push(
329
+ t3.importDeclaration(
330
+ entries.map(
331
+ ({ local, exported }) => exported === "default" ? t3.importDefaultSpecifier(t3.identifier(local)) : t3.importSpecifier(t3.identifier(local), t3.identifier(exported))
332
+ ),
333
+ t3.stringLiteral(mod)
334
+ )
335
+ );
336
+ }
337
+ }
338
+ if (delegateEvents && state.delegatedEvents.size > 0) {
339
+ imports.push(
340
+ t3.importDeclaration(
341
+ [
342
+ t3.importSpecifier(
343
+ t3.identifier("delegateEvents"),
344
+ t3.identifier("delegateEvents")
345
+ )
346
+ ],
347
+ t3.stringLiteral(signalModule)
348
+ )
349
+ );
350
+ const eventsArray = t3.arrayExpression(
351
+ Array.from(state.delegatedEvents).map(
352
+ (event) => t3.stringLiteral(event)
353
+ )
354
+ );
355
+ const delegateCall = t3.expressionStatement(
356
+ t3.callExpression(t3.identifier("delegateEvents"), [eventsArray])
357
+ );
358
+ path.node.body.unshift(delegateCall);
359
+ }
360
+ if (deferredDecls.length > 0) {
361
+ path.node.body.unshift(...deferredDecls);
362
+ }
363
+ if (state.staticTemplates.size > 0) {
364
+ const decls = [];
365
+ for (const [key, name] of state.staticTemplates) {
366
+ const svg = key.startsWith("svg:");
367
+ const html = svg ? key.slice(4) : key;
368
+ decls.push(
369
+ t3.variableDeclaration("const", [
370
+ t3.variableDeclarator(
371
+ t3.identifier(name),
372
+ // Just the HTML. Parsing is deferred to `templateNode`, which
373
+ // knows whether this is a server render, a hydration or a fresh
374
+ // client render: a module-scope `createTemplate` would touch
375
+ // `document` at import time and break SSR outright.
376
+ t3.stringLiteral(html)
377
+ )
378
+ ])
379
+ );
380
+ }
381
+ path.node.body.unshift(...decls);
382
+ }
383
+ }
384
+ if (imports.length > 0) {
385
+ path.node.body.unshift(...dedupeImports(imports));
386
+ }
387
+ }
388
+ },
389
+ // Both JSX forms take the one path: build IR, run the imperative backend,
390
+ // splice the emitted code back in. It handles the whole subtree, so nothing
391
+ // below this node needs its own visitor.
392
+ JSXElement(path, state) {
393
+ state.hasJSX = true;
394
+ path.replaceWith(emitViaIR(path.node, state));
395
+ },
396
+ JSXFragment(path, state) {
397
+ state.hasJSX = true;
398
+ path.replaceWith(emitViaIR(path.node, state));
399
+ },
400
+ TaggedTemplateExpression(path, state) {
401
+ if (compileLit && t3.isIdentifier(path.node.tag) && (path.node.tag.name === litTag || path.node.tag.name === "svg")) {
402
+ path.replaceWith(emitLitViaIR(path.node, state));
403
+ }
404
+ }
405
+ }
406
+ };
407
+ });
408
+ function nestedHook(state) {
409
+ return (ir) => {
410
+ resolveComponentSources(ir, {
411
+ resolver: state.componentResolver,
412
+ modules: {
413
+ controlFlowModule: state.controlFlowModule,
414
+ coreModule: state.libModule,
415
+ routerModule: state.routerModule
416
+ },
417
+ strategyFor: (node) => node.load
418
+ });
419
+ collapseStrategies(ir);
420
+ collectRuntimeNeeds(ir, state);
421
+ };
422
+ }
423
+ function strategyLiteral(strategy) {
424
+ const props = [
425
+ t3.objectProperty(t3.identifier("kind"), t3.stringLiteral(strategy.kind))
426
+ ];
427
+ if (strategy.kind === "visible" && strategy.rootMargin) {
428
+ props.push(t3.objectProperty(t3.identifier("rootMargin"), t3.stringLiteral(strategy.rootMargin)));
429
+ }
430
+ if (strategy.kind === "interaction") {
431
+ props.push(
432
+ t3.objectProperty(
433
+ t3.identifier("events"),
434
+ t3.arrayExpression(strategy.events.map((e) => t3.stringLiteral(e)))
435
+ )
436
+ );
437
+ }
438
+ if (strategy.kind === "media") {
439
+ props.push(t3.objectProperty(t3.identifier("query"), t3.stringLiteral(strategy.query)));
440
+ }
441
+ return t3.objectExpression(props);
442
+ }
443
+ function adoptTemplates(code, templates, state) {
444
+ if (!templates || templates.length === 0) return code;
445
+ const rename = /* @__PURE__ */ new Map();
446
+ for (const tpl of templates) {
447
+ const key = `${tpl.svg ? "svg:" : ""}${tpl.html}`;
448
+ let name = state.staticTemplates.get(key);
449
+ if (!name) {
450
+ name = `_tmpl$${state.staticTemplates.size}`;
451
+ state.staticTemplates.set(key, name);
452
+ }
453
+ rename.set(tpl.id, name);
454
+ }
455
+ return code.replace(/_tmpl\$\d+/g, (id) => rename.get(id) ?? id);
456
+ }
457
+ function emitViaIR(node, state) {
458
+ const used = /* @__PURE__ */ new Set();
459
+ const ir = buildIR(node, used, nestedHook(state));
460
+ resolveComponentSources(ir, {
461
+ resolver: state.componentResolver,
462
+ modules: {
463
+ controlFlowModule: state.controlFlowModule,
464
+ coreModule: state.libModule,
465
+ routerModule: state.routerModule
466
+ },
467
+ strategyFor: (n) => n.load
468
+ });
469
+ collapseStrategies(ir);
470
+ const { code, imports, templates } = imperativeBackend.emit(ir, { templateClone: state.templateClone, partialTemplates: state.partialTemplates });
471
+ for (const s of imports) used.add(s);
472
+ for (const s of used) state.irImports.add(s);
473
+ collectRuntimeNeeds(ir, state);
474
+ const adopted = adoptTemplates(code, templates, state);
475
+ return template2.expression(adopted, { placeholderPattern: false, plugins: ["typescript"] })();
476
+ }
477
+ function dedupeImports(imports) {
478
+ const byModule = /* @__PURE__ */ new Map();
479
+ const out = [];
480
+ for (const decl of imports) {
481
+ const source = decl.source.value;
482
+ const allNamed = decl.specifiers.every((s) => t3.isImportSpecifier(s));
483
+ if (!allNamed) {
484
+ out.push(decl);
485
+ continue;
486
+ }
487
+ const existing = byModule.get(source);
488
+ if (!existing) {
489
+ const names = new Set(
490
+ decl.specifiers.map((s) => s.local.name)
491
+ );
492
+ byModule.set(source, { decl, names });
493
+ out.push(decl);
494
+ continue;
495
+ }
496
+ for (const s of decl.specifiers) {
497
+ if (!existing.names.has(s.local.name)) {
498
+ existing.names.add(s.local.name);
499
+ existing.decl.specifiers.push(s);
500
+ }
501
+ }
502
+ }
503
+ return out;
504
+ }
505
+ function emitLitViaIR(node, state) {
506
+ const used = /* @__PURE__ */ new Set();
507
+ const svg = t3.isIdentifier(node.tag) && node.tag.name === "svg";
508
+ const ir = buildIRFromLit(node, used, { svg, onNested: nestedHook(state) });
509
+ resolveComponentSources(ir, {
510
+ resolver: state.componentResolver,
511
+ modules: {
512
+ controlFlowModule: state.controlFlowModule,
513
+ coreModule: state.libModule,
514
+ routerModule: state.routerModule
515
+ },
516
+ strategyFor: (node2) => node2.load
517
+ });
518
+ collapseStrategies(ir);
519
+ const { code, imports, templates } = imperativeBackend.emit(ir, { templateClone: state.templateClone, partialTemplates: state.partialTemplates });
520
+ for (const s of imports) used.add(s);
521
+ for (const s of used) state.irImports.add(s);
522
+ collectRuntimeNeeds(ir, state);
523
+ state.hasLitIR = true;
524
+ const expression = template2.expression(adoptTemplates(code, templates, state), {
525
+ placeholderPattern: false,
526
+ plugins: ["typescript"]
527
+ })();
528
+ inheritLocation(expression, node);
529
+ return expression;
530
+ }
531
+ function inheritLocation(target, source) {
532
+ if (!source.loc) return;
533
+ const seen = /* @__PURE__ */ new Set();
534
+ const walk = (node) => {
535
+ if (seen.has(node)) return;
536
+ seen.add(node);
537
+ if (!node.loc) {
538
+ node.loc = source.loc;
539
+ node.start = source.start;
540
+ node.end = source.end;
541
+ }
542
+ for (const key of t3.VISITOR_KEYS[node.type] ?? []) {
543
+ const child = node[key];
544
+ if (Array.isArray(child)) {
545
+ for (const c of child) if (c && typeof c === "object" && "type" in c) walk(c);
546
+ } else if (child && typeof child === "object" && "type" in child) {
547
+ walk(child);
548
+ }
549
+ }
550
+ };
551
+ walk(target);
552
+ }
553
+ function collectRuntimeNeeds(node, state) {
554
+ if (node.kind === "component" && node.source) {
555
+ if (node.source.origin === "builtin") {
556
+ state.controlFlowComponents.add(node.name);
557
+ state.needsControlFlowImport = true;
558
+ } else if (isDeferred(node.source.loading) && !state.resolvedComponents.has(node.name)) {
559
+ state.deferredComponents.set(node.name, {
560
+ module: node.source.module,
561
+ export: node.source.export,
562
+ strategy: node.source.loading
563
+ });
564
+ } else {
565
+ state.deferredComponents.delete(node.name);
566
+ state.resolvedComponents.set(node.name, {
567
+ module: node.source.module,
568
+ export: node.source.export
569
+ });
570
+ }
571
+ }
572
+ if (node.kind === "element" || node.kind === "component" || node.kind === "control") {
573
+ if ("props" in node) {
574
+ for (const p of node.props) {
575
+ if (p.kind === "event" && p.event?.delegated) state.delegatedEvents.add(p.event.name);
576
+ }
577
+ }
578
+ }
579
+ if ("children" in node && node.children) {
580
+ for (const c of node.children) collectRuntimeNeeds(c, state);
581
+ }
582
+ }
583
+
584
+ // src/frontend/babel/index.ts
585
+ var babelPluginReactiveJSX = plugin_default;
586
+ function createPlugin(options) {
587
+ return [plugin_default, options];
588
+ }
589
+ function createPreset(options = {}) {
590
+ return {
591
+ plugins: [
592
+ [
593
+ plugin_default,
594
+ {
595
+ runtime: "automatic",
596
+ importSource: "@fluixi/jsx",
597
+ development: false,
598
+ detectReactivity: true,
599
+ useLitHTML: true,
600
+ hoistStatics: true,
601
+ delegateEvents: true,
602
+ optimizeControlFlow: true,
603
+ sourceMaps: true,
604
+ ...options
605
+ }
606
+ ]
607
+ ]
608
+ };
609
+ }
610
+ var presets = {
611
+ production: createPreset({
612
+ development: false,
613
+ hoistStatics: true,
614
+ delegateEvents: true,
615
+ optimizeControlFlow: true
616
+ }),
617
+ development: createPreset({
618
+ development: true,
619
+ hoistStatics: false,
620
+ sourceMaps: true
621
+ }),
622
+ minimal: createPreset({
623
+ detectReactivity: false,
624
+ useLitHTML: false,
625
+ hoistStatics: false,
626
+ delegateEvents: false,
627
+ optimizeControlFlow: false
628
+ })
629
+ };
630
+ export {
631
+ babelPluginReactiveJSX,
632
+ createPlugin,
633
+ createPreset,
634
+ plugin_default as default,
635
+ presets
636
+ };