@fluixi/compiler 1.0.0-alpha.105 → 1.0.0-alpha.106
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.
- package/dist/analyze/static-graph.cjs +1 -1
- package/dist/analyze/static-graph.mjs +1 -1
- package/dist/{babel-USPHNEJF.mjs → babel-HJY4RVAV.mjs} +33 -20
- package/dist/{chunk-OQYQ7UTD.mjs → chunk-4XEOMQ57.mjs} +1 -1
- package/dist/{chunk-EK4OMGTU.mjs → chunk-JUFI6IR3.mjs} +1 -1
- package/dist/{chunk-5GAYDAAC.mjs → chunk-LCQHL2VQ.mjs} +132 -10
- package/dist/{chunk-XBAQME2V.mjs → chunk-LGUZRHYN.mjs} +2 -2
- package/dist/{chunk-O6OBEV4V.mjs → chunk-TDN5MYWI.mjs} +1 -1
- package/dist/{chunk-EQIIWIEU.mjs → chunk-W7DYOMXJ.mjs} +2 -2
- package/dist/{chunk-FMIIK5UM.mjs → chunk-WHEDRMNR.mjs} +1 -1
- package/dist/codegen/backends/imperative.cjs +130 -8
- package/dist/codegen/backends/imperative.d.ts.map +1 -1
- package/dist/codegen/backends/imperative.js +62 -0
- package/dist/codegen/backends/imperative.mjs +130 -8
- package/dist/codegen/partial-template.cjs +80 -8
- package/dist/codegen/partial-template.d.cts +21 -4
- package/dist/codegen/partial-template.d.ts +21 -4
- package/dist/codegen/partial-template.d.ts.map +1 -1
- package/dist/codegen/partial-template.js +0 -0
- package/dist/codegen/partial-template.mjs +80 -8
- package/dist/codegen/serialize-static.cjs +1 -0
- package/dist/codegen/serialize-static.d.cts +8 -0
- package/dist/codegen/serialize-static.d.ts +8 -0
- package/dist/codegen/serialize-static.d.ts.map +1 -1
- package/dist/codegen/serialize-static.js +1 -1
- package/dist/codegen/serialize-static.mjs +1 -0
- package/dist/frontend/babel/build-ir-html.cjs +149 -21
- package/dist/frontend/babel/build-ir-html.d.cts +3 -1
- package/dist/frontend/babel/build-ir-html.d.ts +3 -1
- package/dist/frontend/babel/build-ir-html.d.ts.map +1 -1
- package/dist/frontend/babel/build-ir-html.mjs +149 -21
- package/dist/frontend/babel/build-ir.cjs +149 -21
- package/dist/frontend/babel/build-ir.d.cts +11 -2
- package/dist/frontend/babel/build-ir.d.ts +11 -2
- package/dist/frontend/babel/build-ir.d.ts.map +1 -1
- package/dist/frontend/babel/build-ir.js +15 -9
- package/dist/frontend/babel/build-ir.mjs +149 -21
- package/dist/frontend/babel/index.cjs +160 -25
- package/dist/frontend/babel/index.mjs +160 -25
- package/dist/frontend/babel/lower-template.cjs +149 -21
- package/dist/frontend/babel/lower-template.d.cts +2 -1
- package/dist/frontend/babel/lower-template.d.ts +2 -1
- package/dist/frontend/babel/lower-template.d.ts.map +1 -1
- package/dist/frontend/babel/lower-template.js +4 -4
- package/dist/frontend/babel/lower-template.mjs +149 -21
- package/dist/frontend/babel/plugin.cjs +158 -23
- package/dist/frontend/babel/plugin.js +9 -2
- package/dist/frontend/babel/plugin.mjs +158 -23
- package/dist/index.cjs +131 -9
- package/dist/index.mjs +131 -9
- package/dist/integrations.cjs +165 -33
- package/dist/integrations.mjs +11 -11
- package/dist/lower/compile-template.cjs +131 -9
- package/dist/lower/compile-template.mjs +131 -9
- package/dist/lower/jsx.cjs +130 -8
- package/dist/lower/jsx.mjs +130 -8
- package/dist/lower/template.cjs +130 -8
- package/dist/lower/template.mjs +130 -8
- package/dist/resolve/builtins.cjs +1 -1
- package/dist/resolve/builtins.mjs +1 -1
- package/dist/{server-fns-7Y25MR3B.mjs → server-fns-WZJK4BJE.mjs} +5 -5
- package/dist/{server-functions-43CFKXY3.mjs → server-functions-4KTFFEO3.mjs} +3 -3
- package/dist/transform/index.cjs +135 -16
- package/dist/transform/index.mjs +135 -16
- package/dist/transform/templates.cjs +134 -15
- package/dist/transform/templates.d.ts.map +1 -1
- package/dist/transform/templates.js +4 -8
- package/dist/transform/templates.mjs +134 -15
- package/dist/{transform-YUDW7K4J.mjs → transform-NO46NFQH.mjs} +11 -14
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/package.json +4 -4
|
@@ -77,10 +77,64 @@ function isHole(node) {
|
|
|
77
77
|
function isTemplateChild(node) {
|
|
78
78
|
return node.kind === "text" || node.kind === "element" && isTemplateElement(node);
|
|
79
79
|
}
|
|
80
|
+
var PROPERTY_BINDS = /* @__PURE__ */ new Set(["indeterminate"]);
|
|
81
|
+
function disposition(prop) {
|
|
82
|
+
if (prop.kind === "spread") return null;
|
|
83
|
+
if (prop.name === "ref") return "ref";
|
|
84
|
+
if (prop.name === "use") return "use";
|
|
85
|
+
if (prop.kind === "event") return prop.event ? "event" : null;
|
|
86
|
+
if (prop.kind === "prop") return "property";
|
|
87
|
+
if (prop.kind !== "attr") return null;
|
|
88
|
+
const name = prop.name;
|
|
89
|
+
if (name.startsWith("on:")) return "nativeEvent";
|
|
90
|
+
if (name.startsWith("prop:")) return "property";
|
|
91
|
+
if (name.startsWith("attr:")) return "attr";
|
|
92
|
+
if (name.startsWith("bool:")) return "boolAttr";
|
|
93
|
+
if (name === "className" || name === "class") {
|
|
94
|
+
return isPlainLiteralAttr(prop) ? "serialize" : "class";
|
|
95
|
+
}
|
|
96
|
+
if (name === "classList") {
|
|
97
|
+
if (isPlainLiteralAttr(prop)) return "serialize";
|
|
98
|
+
return prop.reactive ? "classListDynamic" : "classList";
|
|
99
|
+
}
|
|
100
|
+
if (name === "style") {
|
|
101
|
+
if (isPlainLiteralAttr(prop)) return "serialize";
|
|
102
|
+
return prop.reactive ? "styleDynamic" : "style";
|
|
103
|
+
}
|
|
104
|
+
if (name.includes(":")) return null;
|
|
105
|
+
if (PROPERTY_ONLY.has(name)) return null;
|
|
106
|
+
if (PROPERTY_BINDS.has(name)) return "property";
|
|
107
|
+
if (prop.expr === void 0) return isPlainLiteralAttr(prop) ? "serialize" : null;
|
|
108
|
+
return "attr";
|
|
109
|
+
}
|
|
110
|
+
function effectiveProps(el) {
|
|
111
|
+
const order = [];
|
|
112
|
+
const byName = /* @__PURE__ */ new Map();
|
|
113
|
+
for (const prop of el.props) {
|
|
114
|
+
if (!byName.has(prop.name)) order.push(prop.name);
|
|
115
|
+
byName.set(prop.name, prop);
|
|
116
|
+
}
|
|
117
|
+
return order.map((name) => byName.get(name));
|
|
118
|
+
}
|
|
119
|
+
function propPlan(el) {
|
|
120
|
+
const custom = el.tag.includes("-");
|
|
121
|
+
const plan = { serialize: [], bindings: [] };
|
|
122
|
+
for (const prop of effectiveProps(el)) {
|
|
123
|
+
const kind = disposition(prop);
|
|
124
|
+
if (kind === null) return null;
|
|
125
|
+
if (kind === "serialize") {
|
|
126
|
+
plan.serialize.push(prop);
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
if (custom) return null;
|
|
130
|
+
plan.bindings.push({ prop, kind });
|
|
131
|
+
}
|
|
132
|
+
return plan;
|
|
133
|
+
}
|
|
80
134
|
function isTemplateElement(node) {
|
|
81
135
|
if (node.svg) return false;
|
|
82
136
|
if (isRawTextElement(node.tag)) return false;
|
|
83
|
-
if (!node
|
|
137
|
+
if (!propPlan(node)) return false;
|
|
84
138
|
return node.children.every((c) => isTemplateChild(c) || isHole(c));
|
|
85
139
|
}
|
|
86
140
|
function containsHole(node) {
|
|
@@ -88,6 +142,15 @@ function containsHole(node) {
|
|
|
88
142
|
const children = node.children;
|
|
89
143
|
return children ? children.some(containsHole) : false;
|
|
90
144
|
}
|
|
145
|
+
function containsBinding(node) {
|
|
146
|
+
if (node.kind !== "element") return false;
|
|
147
|
+
const plan = propPlan(node);
|
|
148
|
+
if (plan && plan.bindings.length > 0) return true;
|
|
149
|
+
return node.children.some(containsBinding);
|
|
150
|
+
}
|
|
151
|
+
function interesting(node) {
|
|
152
|
+
return containsHole(node) || containsBinding(node);
|
|
153
|
+
}
|
|
91
154
|
function addressable(el) {
|
|
92
155
|
for (let i = 0; i < el.children.length; i++) {
|
|
93
156
|
const child = el.children[i];
|
|
@@ -101,9 +164,10 @@ function addressable(el) {
|
|
|
101
164
|
function planPartialTemplate(root) {
|
|
102
165
|
if (!isTemplateElement(root)) return null;
|
|
103
166
|
if (!addressable(root)) return null;
|
|
104
|
-
if (!root
|
|
167
|
+
if (!interesting(root)) return null;
|
|
105
168
|
const steps = [];
|
|
106
169
|
const holes = [];
|
|
170
|
+
const bindings = [];
|
|
107
171
|
let refCount = 0;
|
|
108
172
|
const declare = (expr) => {
|
|
109
173
|
const ref = `_n$${refCount++}`;
|
|
@@ -111,11 +175,17 @@ function planPartialTemplate(root) {
|
|
|
111
175
|
return ref;
|
|
112
176
|
};
|
|
113
177
|
walk(root, "_el$");
|
|
114
|
-
return { html: serializeWithMarkers(root), tag: root.tag, steps, holes };
|
|
178
|
+
return { html: serializeWithMarkers(root), tag: root.tag, steps, holes, bindings };
|
|
115
179
|
function walk(el, elementRef) {
|
|
180
|
+
const plan = propPlan(el);
|
|
181
|
+
if (plan) {
|
|
182
|
+
for (const binding of plan.bindings) {
|
|
183
|
+
bindings.push({ ref: elementRef, prop: binding.prop, kind: binding.kind });
|
|
184
|
+
}
|
|
185
|
+
}
|
|
116
186
|
let last = -1;
|
|
117
187
|
el.children.forEach((child, i) => {
|
|
118
|
-
if (
|
|
188
|
+
if (interesting(child)) last = i;
|
|
119
189
|
});
|
|
120
190
|
let previous = null;
|
|
121
191
|
for (let i = 0; i <= last; i++) {
|
|
@@ -129,19 +199,21 @@ function planPartialTemplate(root) {
|
|
|
129
199
|
continue;
|
|
130
200
|
}
|
|
131
201
|
const ref = declare(expr);
|
|
132
|
-
if (child.kind === "element" &&
|
|
202
|
+
if (child.kind === "element" && interesting(child)) walk(child, ref);
|
|
133
203
|
previous = ref;
|
|
134
204
|
}
|
|
135
205
|
}
|
|
136
206
|
}
|
|
137
207
|
function serializeWithMarkers(el) {
|
|
138
|
-
return serializeStatic(
|
|
208
|
+
return serializeStatic(templateTree(el)).split(SENTINEL).join(HOLE_START + HOLE_END);
|
|
139
209
|
}
|
|
140
|
-
function
|
|
210
|
+
function templateTree(el) {
|
|
211
|
+
const plan = propPlan(el);
|
|
141
212
|
return {
|
|
142
213
|
...el,
|
|
214
|
+
props: plan ? plan.serialize : [],
|
|
143
215
|
children: el.children.map(
|
|
144
|
-
(child) => isHole(child) ? { kind: "text", value: SENTINEL } : child.kind === "element" ?
|
|
216
|
+
(child) => isHole(child) ? { kind: "text", value: SENTINEL } : child.kind === "element" ? templateTree(child) : child
|
|
145
217
|
)
|
|
146
218
|
};
|
|
147
219
|
}
|
|
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/codegen/serialize-static.ts
|
|
21
21
|
var serialize_static_exports = {};
|
|
22
22
|
__export(serialize_static_exports, {
|
|
23
|
+
PROPERTY_ONLY: () => PROPERTY_ONLY,
|
|
23
24
|
htmlAttrName: () => htmlAttrName,
|
|
24
25
|
isPlainLiteralAttr: () => isPlainLiteralAttr,
|
|
25
26
|
isRawTextElement: () => isRawTextElement,
|
|
@@ -7,6 +7,14 @@
|
|
|
7
7
|
* guess, and anything it cannot represent is a bug in the analysis, not a fallback.
|
|
8
8
|
*/
|
|
9
9
|
import type { IRElement, IRProp } from '../ir/nodes.cjs';
|
|
10
|
+
/**
|
|
11
|
+
* Names the runtime assigns as DOM properties, whatever they look like.
|
|
12
|
+
*
|
|
13
|
+
* `innerHTML="<b>x</b>"` in a template would be escaped into visible text, and `value`
|
|
14
|
+
* as an attribute sets the *default* value rather than the current one. Serializing any
|
|
15
|
+
* of these changes what the code means, so they stay on the imperative path.
|
|
16
|
+
*/
|
|
17
|
+
export declare const PROPERTY_ONLY: Set<string>;
|
|
10
18
|
/** True when this element's content must not be entity-escaped. */
|
|
11
19
|
export declare function isRawTextElement(tag: string): boolean;
|
|
12
20
|
/** The HTML spelling of an IR prop name. */
|
|
@@ -7,6 +7,14 @@
|
|
|
7
7
|
* guess, and anything it cannot represent is a bug in the analysis, not a fallback.
|
|
8
8
|
*/
|
|
9
9
|
import type { IRElement, IRProp } from '../ir/nodes.js';
|
|
10
|
+
/**
|
|
11
|
+
* Names the runtime assigns as DOM properties, whatever they look like.
|
|
12
|
+
*
|
|
13
|
+
* `innerHTML="<b>x</b>"` in a template would be escaped into visible text, and `value`
|
|
14
|
+
* as an attribute sets the *default* value rather than the current one. Serializing any
|
|
15
|
+
* of these changes what the code means, so they stay on the imperative path.
|
|
16
|
+
*/
|
|
17
|
+
export declare const PROPERTY_ONLY: Set<string>;
|
|
10
18
|
/** True when this element's content must not be entity-escaped. */
|
|
11
19
|
export declare function isRawTextElement(tag: string): boolean;
|
|
12
20
|
/** The HTML spelling of an IR prop name. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serialize-static.d.ts","sourceRoot":"","sources":["../../src/codegen/serialize-static.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,SAAS,EAAU,MAAM,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"serialize-static.d.ts","sourceRoot":"","sources":["../../src/codegen/serialize-static.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,SAAS,EAAU,MAAM,EAAE,MAAM,gBAAgB,CAAC;AA8BhE;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,aAaxB,CAAC;AAWH,mEAAmE;AACnE,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAErD;AAED,4CAA4C;AAC5C,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAKxD;AAED,0EAA0E;AAC1E,wBAAgB,cAAc,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAgBvD;AAED,2BAA2B;AAC3B,wBAAgB,eAAe,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAKvD;AAmCD;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,SAAS,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,SAAS,CAU9F"}
|
|
@@ -31,7 +31,7 @@ const HTML_NAME = {
|
|
|
31
31
|
* as an attribute sets the *default* value rather than the current one. Serializing any
|
|
32
32
|
* of these changes what the code means, so they stay on the imperative path.
|
|
33
33
|
*/
|
|
34
|
-
const PROPERTY_ONLY = new Set([
|
|
34
|
+
export const PROPERTY_ONLY = new Set([
|
|
35
35
|
'innerHTML',
|
|
36
36
|
'outerHTML',
|
|
37
37
|
'innerText',
|
|
@@ -196,10 +196,64 @@ function isHole(node) {
|
|
|
196
196
|
function isTemplateChild(node) {
|
|
197
197
|
return node.kind === "text" || node.kind === "element" && isTemplateElement(node);
|
|
198
198
|
}
|
|
199
|
+
var PROPERTY_BINDS = /* @__PURE__ */ new Set(["indeterminate"]);
|
|
200
|
+
function disposition(prop) {
|
|
201
|
+
if (prop.kind === "spread") return null;
|
|
202
|
+
if (prop.name === "ref") return "ref";
|
|
203
|
+
if (prop.name === "use") return "use";
|
|
204
|
+
if (prop.kind === "event") return prop.event ? "event" : null;
|
|
205
|
+
if (prop.kind === "prop") return "property";
|
|
206
|
+
if (prop.kind !== "attr") return null;
|
|
207
|
+
const name = prop.name;
|
|
208
|
+
if (name.startsWith("on:")) return "nativeEvent";
|
|
209
|
+
if (name.startsWith("prop:")) return "property";
|
|
210
|
+
if (name.startsWith("attr:")) return "attr";
|
|
211
|
+
if (name.startsWith("bool:")) return "boolAttr";
|
|
212
|
+
if (name === "className" || name === "class") {
|
|
213
|
+
return isPlainLiteralAttr(prop) ? "serialize" : "class";
|
|
214
|
+
}
|
|
215
|
+
if (name === "classList") {
|
|
216
|
+
if (isPlainLiteralAttr(prop)) return "serialize";
|
|
217
|
+
return prop.reactive ? "classListDynamic" : "classList";
|
|
218
|
+
}
|
|
219
|
+
if (name === "style") {
|
|
220
|
+
if (isPlainLiteralAttr(prop)) return "serialize";
|
|
221
|
+
return prop.reactive ? "styleDynamic" : "style";
|
|
222
|
+
}
|
|
223
|
+
if (name.includes(":")) return null;
|
|
224
|
+
if (PROPERTY_ONLY.has(name)) return null;
|
|
225
|
+
if (PROPERTY_BINDS.has(name)) return "property";
|
|
226
|
+
if (prop.expr === void 0) return isPlainLiteralAttr(prop) ? "serialize" : null;
|
|
227
|
+
return "attr";
|
|
228
|
+
}
|
|
229
|
+
function effectiveProps(el) {
|
|
230
|
+
const order = [];
|
|
231
|
+
const byName = /* @__PURE__ */ new Map();
|
|
232
|
+
for (const prop of el.props) {
|
|
233
|
+
if (!byName.has(prop.name)) order.push(prop.name);
|
|
234
|
+
byName.set(prop.name, prop);
|
|
235
|
+
}
|
|
236
|
+
return order.map((name) => byName.get(name));
|
|
237
|
+
}
|
|
238
|
+
function propPlan(el) {
|
|
239
|
+
const custom = el.tag.includes("-");
|
|
240
|
+
const plan = { serialize: [], bindings: [] };
|
|
241
|
+
for (const prop of effectiveProps(el)) {
|
|
242
|
+
const kind = disposition(prop);
|
|
243
|
+
if (kind === null) return null;
|
|
244
|
+
if (kind === "serialize") {
|
|
245
|
+
plan.serialize.push(prop);
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
if (custom) return null;
|
|
249
|
+
plan.bindings.push({ prop, kind });
|
|
250
|
+
}
|
|
251
|
+
return plan;
|
|
252
|
+
}
|
|
199
253
|
function isTemplateElement(node) {
|
|
200
254
|
if (node.svg) return false;
|
|
201
255
|
if (isRawTextElement(node.tag)) return false;
|
|
202
|
-
if (!node
|
|
256
|
+
if (!propPlan(node)) return false;
|
|
203
257
|
return node.children.every((c) => isTemplateChild(c) || isHole(c));
|
|
204
258
|
}
|
|
205
259
|
function containsHole(node) {
|
|
@@ -207,6 +261,15 @@ function containsHole(node) {
|
|
|
207
261
|
const children = node.children;
|
|
208
262
|
return children ? children.some(containsHole) : false;
|
|
209
263
|
}
|
|
264
|
+
function containsBinding(node) {
|
|
265
|
+
if (node.kind !== "element") return false;
|
|
266
|
+
const plan = propPlan(node);
|
|
267
|
+
if (plan && plan.bindings.length > 0) return true;
|
|
268
|
+
return node.children.some(containsBinding);
|
|
269
|
+
}
|
|
270
|
+
function interesting(node) {
|
|
271
|
+
return containsHole(node) || containsBinding(node);
|
|
272
|
+
}
|
|
210
273
|
function addressable(el) {
|
|
211
274
|
for (let i = 0; i < el.children.length; i++) {
|
|
212
275
|
const child = el.children[i];
|
|
@@ -220,9 +283,10 @@ function addressable(el) {
|
|
|
220
283
|
function planPartialTemplate(root) {
|
|
221
284
|
if (!isTemplateElement(root)) return null;
|
|
222
285
|
if (!addressable(root)) return null;
|
|
223
|
-
if (!root
|
|
286
|
+
if (!interesting(root)) return null;
|
|
224
287
|
const steps = [];
|
|
225
288
|
const holes = [];
|
|
289
|
+
const bindings = [];
|
|
226
290
|
let refCount = 0;
|
|
227
291
|
const declare = (expr) => {
|
|
228
292
|
const ref = `_n$${refCount++}`;
|
|
@@ -230,11 +294,17 @@ function planPartialTemplate(root) {
|
|
|
230
294
|
return ref;
|
|
231
295
|
};
|
|
232
296
|
walk(root, "_el$");
|
|
233
|
-
return { html: serializeWithMarkers(root), tag: root.tag, steps, holes };
|
|
297
|
+
return { html: serializeWithMarkers(root), tag: root.tag, steps, holes, bindings };
|
|
234
298
|
function walk(el, elementRef) {
|
|
299
|
+
const plan = propPlan(el);
|
|
300
|
+
if (plan) {
|
|
301
|
+
for (const binding of plan.bindings) {
|
|
302
|
+
bindings.push({ ref: elementRef, prop: binding.prop, kind: binding.kind });
|
|
303
|
+
}
|
|
304
|
+
}
|
|
235
305
|
let last = -1;
|
|
236
306
|
el.children.forEach((child, i) => {
|
|
237
|
-
if (
|
|
307
|
+
if (interesting(child)) last = i;
|
|
238
308
|
});
|
|
239
309
|
let previous = null;
|
|
240
310
|
for (let i = 0; i <= last; i++) {
|
|
@@ -248,19 +318,21 @@ function planPartialTemplate(root) {
|
|
|
248
318
|
continue;
|
|
249
319
|
}
|
|
250
320
|
const ref = declare(expr);
|
|
251
|
-
if (child.kind === "element" &&
|
|
321
|
+
if (child.kind === "element" && interesting(child)) walk(child, ref);
|
|
252
322
|
previous = ref;
|
|
253
323
|
}
|
|
254
324
|
}
|
|
255
325
|
}
|
|
256
326
|
function serializeWithMarkers(el) {
|
|
257
|
-
return serializeStatic(
|
|
327
|
+
return serializeStatic(templateTree(el)).split(SENTINEL).join(HOLE_START + HOLE_END);
|
|
258
328
|
}
|
|
259
|
-
function
|
|
329
|
+
function templateTree(el) {
|
|
330
|
+
const plan = propPlan(el);
|
|
260
331
|
return {
|
|
261
332
|
...el,
|
|
333
|
+
props: plan ? plan.serialize : [],
|
|
262
334
|
children: el.children.map(
|
|
263
|
-
(child) => isHole(child) ? { kind: "text", value: SENTINEL } : child.kind === "element" ?
|
|
335
|
+
(child) => isHole(child) ? { kind: "text", value: SENTINEL } : child.kind === "element" ? templateTree(child) : child
|
|
264
336
|
)
|
|
265
337
|
};
|
|
266
338
|
}
|
|
@@ -533,6 +605,55 @@ function emitComponent(name, props, children, used, templates, at) {
|
|
|
533
605
|
const mark = at ? `globalThis.${SOURCE_MARKER}?.(${JSON.stringify(at.file)},${at.line},${at.column},${JSON.stringify(name)}), ` : "";
|
|
534
606
|
return `createMemo(${paren(`${mark}() => createComponent(${name}, ${obj})`, "value")})`;
|
|
535
607
|
}
|
|
608
|
+
function bindingTarget(binding) {
|
|
609
|
+
const name = binding.prop.name;
|
|
610
|
+
if (binding.kind === "boolAttr") return name.slice("bool:".length);
|
|
611
|
+
if (name.startsWith("prop:")) return name.slice("prop:".length);
|
|
612
|
+
if (name.startsWith("attr:")) return name.slice("attr:".length);
|
|
613
|
+
return htmlAttrName(name);
|
|
614
|
+
}
|
|
615
|
+
function bindingStatement(binding, used) {
|
|
616
|
+
const { ref, prop, kind } = binding;
|
|
617
|
+
const value = propValue(prop);
|
|
618
|
+
switch (kind) {
|
|
619
|
+
case "class":
|
|
620
|
+
used.add("setClassName");
|
|
621
|
+
return `setClassName(${ref}, ${value});`;
|
|
622
|
+
case "classList":
|
|
623
|
+
used.add("setClassList");
|
|
624
|
+
return `setClassList(${ref}, ${value}, []);`;
|
|
625
|
+
case "classListDynamic":
|
|
626
|
+
used.add("setDynamicClassList");
|
|
627
|
+
return `setDynamicClassList(${ref}, ${value});`;
|
|
628
|
+
case "style":
|
|
629
|
+
used.add("setStyle");
|
|
630
|
+
return `setStyle(${ref}, ${value}, []);`;
|
|
631
|
+
case "styleDynamic":
|
|
632
|
+
used.add("setDynamicStyle");
|
|
633
|
+
return `setDynamicStyle(${ref}, ${value});`;
|
|
634
|
+
case "attr":
|
|
635
|
+
used.add("setDynamicAttribute");
|
|
636
|
+
return `setDynamicAttribute(${ref}, ${JSON.stringify(bindingTarget(binding))}, ${value});`;
|
|
637
|
+
case "property":
|
|
638
|
+
used.add("setDynamicProperty");
|
|
639
|
+
return `setDynamicProperty(${ref}, ${JSON.stringify(bindingTarget(binding))}, ${value});`;
|
|
640
|
+
case "boolAttr":
|
|
641
|
+
used.add("setDynamicBoolAttribute");
|
|
642
|
+
return `setDynamicBoolAttribute(${ref}, ${JSON.stringify(bindingTarget(binding))}, ${value});`;
|
|
643
|
+
case "event":
|
|
644
|
+
used.add("addDelegatedEventListener");
|
|
645
|
+
return `addDelegatedEventListener(${ref}, ${JSON.stringify(prop.event.name)}, ${value});`;
|
|
646
|
+
case "nativeEvent":
|
|
647
|
+
used.add("addNativeEventListener");
|
|
648
|
+
return `addNativeEventListener(${ref}, ${JSON.stringify(prop.name.slice(3))}, ${value});`;
|
|
649
|
+
case "ref":
|
|
650
|
+
used.add("handleRef");
|
|
651
|
+
return `handleRef(${value}, ${ref});`;
|
|
652
|
+
case "use":
|
|
653
|
+
used.add("applyUse");
|
|
654
|
+
return `applyUse(${ref}, ${value});`;
|
|
655
|
+
}
|
|
656
|
+
}
|
|
536
657
|
function staticAttrAssignment(el, prop) {
|
|
537
658
|
const name = htmlAttrName(prop.name);
|
|
538
659
|
const value = prop.literal;
|
|
@@ -583,6 +704,7 @@ function emitNode(node, used, templates) {
|
|
|
583
704
|
`const _el$ = templateNode(${id}, ${JSON.stringify(plan.tag)}, true${at ? `, false, ${JSON.stringify(at)}` : ""});`
|
|
584
705
|
];
|
|
585
706
|
for (const step of plan.steps) lines.push(`const ${step.ref} = ${step.expr};`);
|
|
707
|
+
for (const binding of plan.bindings) lines.push(bindingStatement(binding, used));
|
|
586
708
|
for (const hole of plan.holes) {
|
|
587
709
|
lines.push(
|
|
588
710
|
`insert(${hole.parentRef}, holeScope(${hole.startRef}, () => ${paren(emitNode(hole.node, used, templates), "arrowBody")}), ${hole.endRef}, holeContent(${hole.startRef}, ${hole.endRef}));`
|
|
@@ -1841,7 +1963,7 @@ var generate = import_generator.default.default ?? import_generator.default;
|
|
|
1841
1963
|
function gen(node) {
|
|
1842
1964
|
return generate(node, { concise: true }).code;
|
|
1843
1965
|
}
|
|
1844
|
-
function transformNestedJSX(node, used, onNested) {
|
|
1966
|
+
function transformNestedJSX(node, used, onNested, emit) {
|
|
1845
1967
|
const clone = import_core.types.cloneNode(node, true);
|
|
1846
1968
|
const file = import_core.types.file(import_core.types.program([import_core.types.expressionStatement(clone)]));
|
|
1847
1969
|
let changed = false;
|
|
@@ -1854,9 +1976,12 @@ function transformNestedJSX(node, used, onNested) {
|
|
|
1854
1976
|
(0, import_core.traverse)(file, {
|
|
1855
1977
|
"JSXElement|JSXFragment"(path) {
|
|
1856
1978
|
const jsx = path.node;
|
|
1857
|
-
const nestedIR = buildIR(jsx, used, onNested);
|
|
1979
|
+
const nestedIR = buildIR(jsx, used, onNested, emit);
|
|
1858
1980
|
onNested?.(nestedIR);
|
|
1859
|
-
const { code, imports, templates } = imperativeBackend.emit(nestedIR, {
|
|
1981
|
+
const { code, imports, templates } = imperativeBackend.emit(nestedIR, {
|
|
1982
|
+
templateClone: emit?.templateClone,
|
|
1983
|
+
partialTemplates: emit?.partialTemplates ?? true
|
|
1984
|
+
});
|
|
1860
1985
|
emitInto(path, inlineTemplates(code, templates), imports);
|
|
1861
1986
|
},
|
|
1862
1987
|
// Nested html templates compose: ${cond ? html`...` : html`...`},
|
|
@@ -1864,26 +1989,29 @@ function transformNestedJSX(node, used, onNested) {
|
|
|
1864
1989
|
TaggedTemplateExpression(path) {
|
|
1865
1990
|
const tag = path.node.tag;
|
|
1866
1991
|
if (!import_core.types.isIdentifier(tag) || tag.name !== "html" && tag.name !== "svg") return;
|
|
1867
|
-
const ir = buildIRFromHtml(path.node, used, { svg: tag.name === "svg", onNested });
|
|
1992
|
+
const ir = buildIRFromHtml(path.node, used, { svg: tag.name === "svg", onNested, emit });
|
|
1868
1993
|
onNested?.(ir);
|
|
1869
|
-
const { code, imports, templates } = imperativeBackend.emit(ir, {
|
|
1994
|
+
const { code, imports, templates } = imperativeBackend.emit(ir, {
|
|
1995
|
+
templateClone: emit?.templateClone,
|
|
1996
|
+
partialTemplates: emit?.partialTemplates ?? true
|
|
1997
|
+
});
|
|
1870
1998
|
emitInto(path, inlineTemplates(code, templates), imports);
|
|
1871
1999
|
}
|
|
1872
2000
|
});
|
|
1873
2001
|
return changed ? file.program.body[0].expression : node;
|
|
1874
2002
|
}
|
|
1875
|
-
function genExpr(node, used, onNested) {
|
|
1876
|
-
return gen(transformNestedJSX(node, used, onNested));
|
|
2003
|
+
function genExpr(node, used, onNested, emit) {
|
|
2004
|
+
return gen(transformNestedJSX(node, used, onNested, emit));
|
|
1877
2005
|
}
|
|
1878
2006
|
function isReactiveExpr(node) {
|
|
1879
2007
|
return isReactiveShape(shapeOf(node));
|
|
1880
2008
|
}
|
|
1881
|
-
function buildIR(node, used = /* @__PURE__ */ new Set(), onNested) {
|
|
2009
|
+
function buildIR(node, used = /* @__PURE__ */ new Set(), onNested, emit) {
|
|
1882
2010
|
const ir = buildJsxIR(node, {
|
|
1883
2011
|
code: (n) => (
|
|
1884
2012
|
// A member-expression tag (`<ns.Foo/>`) is not an Expression, so it cannot go
|
|
1885
2013
|
// through the nested-JSX compile: it only ever needs printing.
|
|
1886
|
-
n.type === "JSXMemberExpression" ? gen(n) : genExpr(n, used, onNested)
|
|
2014
|
+
n.type === "JSXMemberExpression" ? gen(n) : genExpr(n, used, onNested, emit)
|
|
1887
2015
|
),
|
|
1888
2016
|
used
|
|
1889
2017
|
});
|
|
@@ -1895,16 +2023,16 @@ var generate2 = import_generator2.default.default ?? import_generator2.default;
|
|
|
1895
2023
|
function gen2(node) {
|
|
1896
2024
|
return generate2(node, { concise: true }).code;
|
|
1897
2025
|
}
|
|
1898
|
-
function bindHole(expr, used, onNested) {
|
|
2026
|
+
function bindHole(expr, used, onNested, emit) {
|
|
1899
2027
|
const hole = {
|
|
1900
|
-
code: genExpr(expr, used, onNested),
|
|
2028
|
+
code: genExpr(expr, used, onNested, emit),
|
|
1901
2029
|
reactive: isReactiveExpr(expr)
|
|
1902
2030
|
};
|
|
1903
2031
|
if (import_core2.types.isArrowFunctionExpression(expr) && !import_core2.types.isBlockStatement(expr.body)) {
|
|
1904
2032
|
const body = expr.body;
|
|
1905
2033
|
hole.arrow = {
|
|
1906
2034
|
params: expr.params.map((p) => gen2(p)),
|
|
1907
|
-
body: genExpr(body, used, onNested),
|
|
2035
|
+
body: genExpr(body, used, onNested, emit),
|
|
1908
2036
|
bodyReactive: isReactiveExpr(body)
|
|
1909
2037
|
};
|
|
1910
2038
|
}
|
|
@@ -1913,7 +2041,7 @@ function bindHole(expr, used, onNested) {
|
|
|
1913
2041
|
}
|
|
1914
2042
|
function lowerHtmlTemplate(node, used, opts = {}) {
|
|
1915
2043
|
const quasi = node.quasi;
|
|
1916
|
-
const holes = quasi.expressions.map((e) => bindHole(e, used, opts.onNested));
|
|
2044
|
+
const holes = quasi.expressions.map((e) => bindHole(e, used, opts.onNested, opts.emit));
|
|
1917
2045
|
return lowerTemplate(buildPieces(quasi), holes, used, opts);
|
|
1918
2046
|
}
|
|
1919
2047
|
function buildPieces(quasi) {
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
*/
|
|
16
16
|
import type { types as t } from '@babel/core';
|
|
17
17
|
import type { IRNode } from '../../ir/nodes.cjs';
|
|
18
|
+
import type { NestedEmitOptions, NestedHook } from './build-ir.cjs';
|
|
18
19
|
/**
|
|
19
20
|
* Build IR from an `` html`...` `` (or `` svg`...` ``) TaggedTemplateExpression.
|
|
20
21
|
* `used` collects runtime symbols emitted for anything nested inside a hole.
|
|
@@ -22,5 +23,6 @@ import type { IRNode } from '../../ir/nodes.cjs';
|
|
|
22
23
|
*/
|
|
23
24
|
export declare function buildIRFromHtml(node: t.TaggedTemplateExpression, used?: Set<string>, opts?: {
|
|
24
25
|
svg?: boolean;
|
|
25
|
-
onNested?:
|
|
26
|
+
onNested?: NestedHook;
|
|
27
|
+
emit?: NestedEmitOptions;
|
|
26
28
|
}): IRNode;
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
*/
|
|
16
16
|
import type { types as t } from '@babel/core';
|
|
17
17
|
import type { IRNode } from '../../ir/nodes.js';
|
|
18
|
+
import type { NestedEmitOptions, NestedHook } from './build-ir.js';
|
|
18
19
|
/**
|
|
19
20
|
* Build IR from an `` html`...` `` (or `` svg`...` ``) TaggedTemplateExpression.
|
|
20
21
|
* `used` collects runtime symbols emitted for anything nested inside a hole.
|
|
@@ -22,6 +23,7 @@ import type { IRNode } from '../../ir/nodes.js';
|
|
|
22
23
|
*/
|
|
23
24
|
export declare function buildIRFromHtml(node: t.TaggedTemplateExpression, used?: Set<string>, opts?: {
|
|
24
25
|
svg?: boolean;
|
|
25
|
-
onNested?:
|
|
26
|
+
onNested?: NestedHook;
|
|
27
|
+
emit?: NestedEmitOptions;
|
|
26
28
|
}): IRNode;
|
|
27
29
|
//# sourceMappingURL=build-ir-html.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-ir-html.d.ts","sourceRoot":"","sources":["../../../src/frontend/babel/build-ir-html.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,EAAE,KAAK,IAAI,CAAC,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"build-ir-html.d.ts","sourceRoot":"","sources":["../../../src/frontend/babel/build-ir-html.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,EAAE,KAAK,IAAI,CAAC,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAGhD,OAAO,KAAK,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEnE;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,CAAC,CAAC,wBAAwB,EAChC,IAAI,GAAE,GAAG,CAAC,MAAM,CAAa,EAC7B,IAAI,GAAE;IAAE,GAAG,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,UAAU,CAAC;IAAC,IAAI,CAAC,EAAE,iBAAiB,CAAA;CAAO,GAC5E,MAAM,CAKR"}
|