@fluixi/compiler 1.0.0-alpha.92 → 1.0.0-alpha.93
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/intrinsics.cjs +18 -0
- package/dist/analyze/intrinsics.d.ts.map +1 -1
- package/dist/analyze/intrinsics.js +18 -0
- package/dist/analyze/intrinsics.mjs +18 -0
- package/dist/analyze/reactive-bindings.cjs +18 -0
- package/dist/analyze/reactive-bindings.mjs +18 -0
- package/dist/analyze/static-graph.cjs +22 -4
- package/dist/analyze/static-graph.d.ts.map +1 -1
- package/dist/analyze/static-graph.js +6 -4
- package/dist/analyze/static-graph.mjs +22 -4
- package/dist/{babel-GI375YZ2.mjs → babel-RJHJQVEM.mjs} +4 -4
- package/dist/{chunk-QZ4CJPYP.mjs → chunk-56QSOVVL.mjs} +1 -1
- package/dist/{chunk-XJ5H2MXY.mjs → chunk-OD53TMER.mjs} +19 -1
- package/dist/{chunk-DWNWN5RH.mjs → chunk-R7PPFBCL.mjs} +1 -1
- package/dist/{chunk-VOUI6XPV.mjs → chunk-TJIH7TLX.mjs} +1 -1
- package/dist/{chunk-VC6X44FS.mjs → chunk-U7HCFLZ2.mjs} +153 -48
- package/dist/codegen/backends/imperative.cjs +24 -6
- package/dist/codegen/backends/imperative.d.ts.map +1 -1
- package/dist/codegen/backends/imperative.js +19 -4
- package/dist/codegen/backends/imperative.mjs +24 -6
- package/dist/frontend/babel/build-ir-lit.cjs +120 -43
- package/dist/frontend/babel/build-ir-lit.mjs +120 -43
- package/dist/frontend/babel/build-ir.cjs +120 -43
- package/dist/frontend/babel/build-ir.mjs +120 -43
- package/dist/frontend/babel/index.cjs +121 -44
- package/dist/frontend/babel/index.mjs +121 -44
- package/dist/frontend/babel/lower-template.cjs +120 -43
- package/dist/frontend/babel/lower-template.mjs +120 -43
- package/dist/frontend/babel/plugin.cjs +120 -43
- package/dist/frontend/babel/plugin.mjs +120 -43
- package/dist/index.cjs +41 -38
- package/dist/index.mjs +41 -38
- package/dist/integrations.cjs +176 -52
- package/dist/integrations.mjs +8 -8
- package/dist/lower/compile-template.cjs +41 -38
- package/dist/lower/compile-template.mjs +41 -38
- package/dist/lower/jsx.cjs +509 -6
- package/dist/lower/jsx.d.ts.map +1 -1
- package/dist/lower/jsx.js +114 -6
- package/dist/lower/jsx.mjs +509 -6
- package/dist/lower/template.cjs +40 -37
- package/dist/lower/template.d.ts.map +1 -1
- package/dist/lower/template.js +22 -30
- package/dist/lower/template.mjs +40 -37
- package/dist/resolve/builtins.cjs +1 -1
- package/dist/resolve/builtins.mjs +1 -1
- package/dist/resolve/component-globals.cjs +14 -0
- package/dist/resolve/component-globals.mjs +14 -0
- package/dist/resolve/write-globals.cjs +14 -0
- package/dist/resolve/write-globals.mjs +14 -0
- package/dist/{server-fns-BBZRZUPP.mjs → server-fns-ZFRDIQ2X.mjs} +4 -4
- package/dist/{server-functions-VEGLIFCE.mjs → server-functions-CTDXX67X.mjs} +3 -3
- package/dist/transform/index.cjs +170 -47
- package/dist/transform/index.mjs +170 -47
- package/dist/transform/intrinsics.cjs +18 -0
- package/dist/transform/intrinsics.mjs +18 -0
- package/dist/transform/source-locations.cjs +64 -3
- package/dist/transform/source-locations.d.cts +7 -2
- package/dist/transform/source-locations.d.ts +7 -2
- package/dist/transform/source-locations.d.ts.map +1 -1
- package/dist/transform/source-locations.js +68 -3
- package/dist/transform/source-locations.mjs +64 -3
- package/dist/transform/templates.cjs +169 -46
- package/dist/transform/templates.js +2 -2
- package/dist/transform/templates.mjs +169 -46
- package/dist/{transform-UWZ7ZGJ2.mjs → transform-QWWQDCXE.mjs} +7 -7
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/package.json +9 -3
package/dist/transform/index.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @fluixi/compiler v1.0.0-alpha.
|
|
1
|
+
/*! @fluixi/compiler v1.0.0-alpha.93 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
|
|
2
2
|
"use strict";
|
|
3
3
|
var __create = Object.create;
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
@@ -489,6 +489,7 @@ var INTRINSICS = {
|
|
|
489
489
|
$effect: { export: "effect", module: REACTIVE_MODULE, returns: "effect" },
|
|
490
490
|
$store: { export: "store", module: "@fluixi/reactive/store", returns: "store-handle" },
|
|
491
491
|
$resource: { export: "resource", module: REACTIVE_MODULE, returns: "resource-handle" },
|
|
492
|
+
$cachedResource: { export: "cachedResource", module: "@fluixi/reactive/cached-resource", returns: "resource-handle" },
|
|
492
493
|
// No short runtime form for these yet, so the intrinsic stands for the `create*`
|
|
493
494
|
// name. Still worth having: no import to write, and when a shorter form is
|
|
494
495
|
// designed, the change is this line rather than a compiler pass.
|
|
@@ -499,6 +500,19 @@ var INTRINSICS = {
|
|
|
499
500
|
// dependency analysis must not guess at.
|
|
500
501
|
$untrack: { export: "untrack", module: REACTIVE_MODULE, returns: "plain" },
|
|
501
502
|
$untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" },
|
|
503
|
+
// Scopes, scheduling and lifecycle: no value to classify, but the same authoring promise,
|
|
504
|
+
// no import to write. `$cleanup` registers a callback on the current owner (`onCleanup`).
|
|
505
|
+
$batch: { export: "batch", module: REACTIVE_MODULE, returns: "plain" },
|
|
506
|
+
$cleanup: { export: "onCleanup", module: REACTIVE_MODULE, returns: "plain" },
|
|
507
|
+
$root: { export: "root", module: REACTIVE_MODULE, returns: "plain" },
|
|
508
|
+
$context: { export: "context", module: REACTIVE_MODULE, returns: "plain" },
|
|
509
|
+
$renderEffect: { export: "renderEffect", module: REACTIVE_MODULE, returns: "effect" },
|
|
510
|
+
$computed: { export: "computed", module: REACTIVE_MODULE, returns: "effect" },
|
|
511
|
+
// Storage for where the code runs, and a signal kept in it. `$persisted` is a signal
|
|
512
|
+
// handle as far as reads go: the same accessor with `set` on it.
|
|
513
|
+
$storage: { export: "useStorage", module: "@fluixi/core/storage", returns: "plain" },
|
|
514
|
+
$asyncStorage: { export: "useAsyncStorage", module: "@fluixi/core/storage", returns: "plain" },
|
|
515
|
+
$persisted: { export: "persisted", module: "@fluixi/core/storage", returns: "signal-handle" },
|
|
502
516
|
// An environment variable, public or server-only; the browser build refuses a secret.
|
|
503
517
|
$env: { export: "env", module: "@fluixi/start/env", returns: "plain" }
|
|
504
518
|
};
|
|
@@ -511,8 +525,11 @@ var RUNTIME_PRIMITIVES = {
|
|
|
511
525
|
createMemo: "memo-accessor",
|
|
512
526
|
createEffect: "effect",
|
|
513
527
|
createRenderEffect: "effect",
|
|
528
|
+
renderEffect: "effect",
|
|
529
|
+
computed: "effect",
|
|
514
530
|
createStore: "reactive-object",
|
|
515
531
|
resource: "resource-handle",
|
|
532
|
+
cachedResource: "resource-handle",
|
|
516
533
|
createResource: "reactive-object",
|
|
517
534
|
createSelector: "memo-accessor",
|
|
518
535
|
createDeferred: "memo-accessor"
|
|
@@ -521,6 +538,7 @@ var PRIMITIVE_MODULES = [
|
|
|
521
538
|
"@fluixi/reactive",
|
|
522
539
|
"@fluixi/reactive/signal",
|
|
523
540
|
"@fluixi/reactive/store",
|
|
541
|
+
"@fluixi/reactive/cached-resource",
|
|
524
542
|
"@fluixi/core"
|
|
525
543
|
];
|
|
526
544
|
var INTRINSIC_CALL = new RegExp(`\\$(?:${Object.keys(INTRINSICS).map((n) => n.slice(1)).join("|")})\\s*\\(`);
|
|
@@ -656,6 +674,7 @@ function resolveReactiveBindings(program) {
|
|
|
656
674
|
// src/transform/source-locations.ts
|
|
657
675
|
var SOURCE_MARKER = "__fx_source";
|
|
658
676
|
var COMPONENT_MARKER = "__fx_component";
|
|
677
|
+
var CLASS_MARKER = "__fx_class";
|
|
659
678
|
var HOLE_MARKER = "__fx_hole";
|
|
660
679
|
var markHole = (accessor, line, column, name) => `(globalThis.${HOLE_MARKER} ?? ((f) => f))(${accessor},${line},${column}${name === void 0 ? "" : `,${JSON.stringify(name)}`})`;
|
|
661
680
|
var PROPS_MARKER = "__fx_props";
|
|
@@ -673,11 +692,12 @@ var RUNTIME_PRIMITIVES2 = /* @__PURE__ */ new Set([
|
|
|
673
692
|
"createStore",
|
|
674
693
|
"createResource"
|
|
675
694
|
]);
|
|
676
|
-
function
|
|
695
|
+
function mayHaveSourceMarks(code) {
|
|
677
696
|
for (const name of RUNTIME_PRIMITIVES2) {
|
|
678
697
|
if (code.includes(name)) return true;
|
|
679
698
|
}
|
|
680
|
-
|
|
699
|
+
if (code.includes("$signal") || code.includes("$memo") || code.includes("$effect") || code.includes("$store")) return true;
|
|
700
|
+
return /\bclass\b[^{;]*\bextends\b/.test(code);
|
|
681
701
|
}
|
|
682
702
|
var SINGLE_STATEMENT_PARENTS = /* @__PURE__ */ new Set([
|
|
683
703
|
"IfStatement",
|
|
@@ -696,6 +716,7 @@ function isLoneBranch(statement, parent) {
|
|
|
696
716
|
function isExport(node) {
|
|
697
717
|
return node.type === "ExportNamedDeclaration" || node.type === "ExportDefaultDeclaration";
|
|
698
718
|
}
|
|
719
|
+
var CLASS_FIELDS = /* @__PURE__ */ new Set(["PropertyDefinition", "ClassProperty", "ClassPrivateProperty", "AccessorProperty"]);
|
|
699
720
|
function isStatement(node) {
|
|
700
721
|
return node.type.endsWith("Statement") || node.type === "VariableDeclaration";
|
|
701
722
|
}
|
|
@@ -716,6 +737,14 @@ function walk3(node, visit, stack = []) {
|
|
|
716
737
|
}
|
|
717
738
|
function nameFor(stack) {
|
|
718
739
|
const declarator = stack[stack.length - 1];
|
|
740
|
+
if (declarator && CLASS_FIELDS.has(declarator.type)) {
|
|
741
|
+
const key = declarator.key;
|
|
742
|
+
if (key?.type === "Identifier" || key?.type === "PrivateIdentifier" || key?.type === "PrivateName") {
|
|
743
|
+
const name = key.name ?? key.id?.name;
|
|
744
|
+
return name;
|
|
745
|
+
}
|
|
746
|
+
return void 0;
|
|
747
|
+
}
|
|
719
748
|
if (declarator?.type !== "VariableDeclarator") return void 0;
|
|
720
749
|
const id = declarator.id;
|
|
721
750
|
if (id?.type === "Identifier") return id.name;
|
|
@@ -764,6 +793,17 @@ function collectSourceEdits(program, filename) {
|
|
|
764
793
|
});
|
|
765
794
|
}
|
|
766
795
|
}
|
|
796
|
+
if ((node.type === "ClassDeclaration" || node.type === "ClassExpression") && node.superClass && !node.declare) {
|
|
797
|
+
const at = node.loc?.start;
|
|
798
|
+
const body = node.body;
|
|
799
|
+
if (at && body) {
|
|
800
|
+
edits.push({
|
|
801
|
+
start: body.start + 1,
|
|
802
|
+
end: body.start + 1,
|
|
803
|
+
code: `static{globalThis.${CLASS_MARKER}?.(this,${JSON.stringify(filename)},${at.line},${at.column});}`
|
|
804
|
+
});
|
|
805
|
+
}
|
|
806
|
+
}
|
|
767
807
|
if (node.type !== "CallExpression") return;
|
|
768
808
|
const callee = node.callee;
|
|
769
809
|
if (callee?.type !== "Identifier") return;
|
|
@@ -773,6 +813,26 @@ function collectSourceEdits(program, filename) {
|
|
|
773
813
|
if (!intrinsic && !imported) return;
|
|
774
814
|
const position = node.loc?.start;
|
|
775
815
|
if (!position) return;
|
|
816
|
+
for (let i = stack.length - 1; i >= 0; i--) {
|
|
817
|
+
const up = stack[i];
|
|
818
|
+
if (isStatement(up)) break;
|
|
819
|
+
if (CLASS_FIELDS.has(up.type)) {
|
|
820
|
+
if (claimed.has(node.start)) return;
|
|
821
|
+
claimed.add(node.start);
|
|
822
|
+
const label2 = nameFor(stack);
|
|
823
|
+
const own = !up.static;
|
|
824
|
+
const args2 = [
|
|
825
|
+
JSON.stringify(filename),
|
|
826
|
+
String(position.line),
|
|
827
|
+
String(position.column),
|
|
828
|
+
label2 ? JSON.stringify(label2) : own ? "undefined" : void 0,
|
|
829
|
+
own ? "this" : void 0
|
|
830
|
+
].filter((a) => a !== void 0).join(",");
|
|
831
|
+
edits.push({ start: node.start, end: node.start, code: `(globalThis.${SOURCE_MARKER}?.(${args2}),` });
|
|
832
|
+
edits.push({ start: node.end, end: node.end, code: ")" });
|
|
833
|
+
return;
|
|
834
|
+
}
|
|
835
|
+
}
|
|
776
836
|
let statement;
|
|
777
837
|
let parent;
|
|
778
838
|
let index = -1;
|
|
@@ -978,13 +1038,16 @@ function emitComponent(name, props, children, used, templates, at) {
|
|
|
978
1038
|
used.add("createComponent");
|
|
979
1039
|
const spreads = props.filter((p) => p.kind === "spread");
|
|
980
1040
|
const normal = props.filter((p) => p.kind !== "spread");
|
|
981
|
-
const
|
|
982
|
-
(p) => `get ${propKey(p.name)}() { return ${componentPropValue(p)}; }`
|
|
983
|
-
);
|
|
1041
|
+
const bodies = normal.map((p) => [p.name, componentPropValue(p)]);
|
|
984
1042
|
if (children.length > 0) {
|
|
985
|
-
|
|
1043
|
+
bodies.push(["children", emitChildren(children, used, templates)]);
|
|
1044
|
+
}
|
|
1045
|
+
let obj = `{ ${bodies.map(([name2, body]) => `get ${propKey(name2)}() { return ${body}; }`).join(", ")} }`;
|
|
1046
|
+
if (bodies.some(([, body]) => /\bthis\b/.test(body))) {
|
|
1047
|
+
const thunks = bodies.map(([name2, body]) => `${JSON.stringify(name2)}: () => ${body}`);
|
|
1048
|
+
const getters = bodies.map(([name2]) => `get ${propKey(name2)}() { return _$t[${JSON.stringify(name2)}](); }`);
|
|
1049
|
+
obj = `((_$t) => ({ ${getters.join(", ")} }))({ ${thunks.join(", ")} })`;
|
|
986
1050
|
}
|
|
987
|
-
let obj = `{ ${entries.join(", ")} }`;
|
|
988
1051
|
if (spreads.length > 0) {
|
|
989
1052
|
used.add("mergeProps");
|
|
990
1053
|
obj = `mergeProps(${spreads.map((s) => s.expr).join(", ")}, ${obj})`;
|
|
@@ -1066,7 +1129,8 @@ function emitNode(node, used, templates) {
|
|
|
1066
1129
|
} else {
|
|
1067
1130
|
used.add("spread");
|
|
1068
1131
|
const svgFlag = node.svg ? ", isSVG: true" : "";
|
|
1069
|
-
const
|
|
1132
|
+
const accessors = node.props.filter((p) => p.kind !== "spread" && p.expr !== void 0 && p.reactive && p.name !== "ref").map((p) => p.name);
|
|
1133
|
+
const customFlag = node.tag.includes("-") ? `, isCustomElement: true, accessors: ${JSON.stringify(accessors)}` : "";
|
|
1070
1134
|
parts.push(
|
|
1071
1135
|
`spread({ element: ${el}, props: ${emitProps(node.props, null, used)}${svgFlag}${customFlag} });`
|
|
1072
1136
|
);
|
|
@@ -1197,6 +1261,7 @@ var DELEGATED = /* @__PURE__ */ new Set([
|
|
|
1197
1261
|
function escapeTemplate(s) {
|
|
1198
1262
|
return s.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${");
|
|
1199
1263
|
}
|
|
1264
|
+
var CONTAINER = "container";
|
|
1200
1265
|
function capitalize(s) {
|
|
1201
1266
|
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
1202
1267
|
}
|
|
@@ -1251,10 +1316,6 @@ var Lowerer = class {
|
|
|
1251
1316
|
if (hasElse) i = elseIdx;
|
|
1252
1317
|
continue;
|
|
1253
1318
|
}
|
|
1254
|
-
if (child.attributes.some((a) => a.kind === "EachDirective")) {
|
|
1255
|
-
out.push(this.lowerEach(child));
|
|
1256
|
-
continue;
|
|
1257
|
-
}
|
|
1258
1319
|
}
|
|
1259
1320
|
const node = this.lowerNode(child);
|
|
1260
1321
|
if (node) out.push(node);
|
|
@@ -1296,13 +1357,16 @@ var Lowerer = class {
|
|
|
1296
1357
|
node.props.unshift({ name: "component", kind: "attr", expr: `() => ${paren(this.hole(isAttr.value.hole).code, "arrowBody")}` });
|
|
1297
1358
|
return node;
|
|
1298
1359
|
}
|
|
1360
|
+
const each = this.lowerEach(el);
|
|
1361
|
+
const children = each ? [each] : this.lowerChildren(el.children);
|
|
1362
|
+
if (el.tag === CONTAINER) return children.length === 1 ? children[0] : { kind: "fragment", children };
|
|
1299
1363
|
const at = this.tagAt(el);
|
|
1300
1364
|
return {
|
|
1301
1365
|
kind: "element",
|
|
1302
1366
|
tag: el.tag,
|
|
1303
1367
|
svg: el.namespace === "svg",
|
|
1304
1368
|
props: this.lowerAttributes(el.attributes),
|
|
1305
|
-
children
|
|
1369
|
+
children,
|
|
1306
1370
|
static: false,
|
|
1307
1371
|
...at ? { at } : {}
|
|
1308
1372
|
};
|
|
@@ -1374,10 +1438,14 @@ var Lowerer = class {
|
|
|
1374
1438
|
const at = this.tagAt(el);
|
|
1375
1439
|
return { kind: "component", name: "Show", props, children: [child], ...at ? { at } : {}, ...cond.at ? { bindAt: cond.at } : {} };
|
|
1376
1440
|
}
|
|
1377
|
-
/**
|
|
1441
|
+
/**
|
|
1442
|
+
* `<el each=${items} key?>${item => …}</el>` → `<el><For each>{item => …}</For></el>`: the
|
|
1443
|
+
* content is repeated per item. Content that is not a `${item => …}` arrow is repeated as
|
|
1444
|
+
* it is. Null when the element has no `each`.
|
|
1445
|
+
*/
|
|
1378
1446
|
lowerEach(el) {
|
|
1379
1447
|
const eachDir = el.attributes.find((a) => a.kind === "EachDirective");
|
|
1380
|
-
if (!eachDir || eachDir.kind !== "EachDirective") return
|
|
1448
|
+
if (!eachDir || eachDir.kind !== "EachDirective") return null;
|
|
1381
1449
|
const each = this.hole(eachDir.hole);
|
|
1382
1450
|
const props = [{ name: "each", kind: "attr", expr: each.code, reactive: each.reactive, ...each.at ? { at: each.at } : {} }];
|
|
1383
1451
|
if (eachDir.key) {
|
|
@@ -1387,12 +1455,12 @@ var Lowerer = class {
|
|
|
1387
1455
|
const arrow = this.itemArrow(el);
|
|
1388
1456
|
let childrenCode;
|
|
1389
1457
|
if (arrow) {
|
|
1390
|
-
const
|
|
1391
|
-
|
|
1392
|
-
childrenCode = `(${arrow.params.join(", ")}) => ${paren(this.emit(repeated), "arrowBody")}`;
|
|
1458
|
+
const body = arrow.bodyReactive ? `() => ${paren(arrow.body, "arrowBody")}` : paren(arrow.body, "arrowBody");
|
|
1459
|
+
childrenCode = `(${arrow.params.join(", ")}) => ${body}`;
|
|
1393
1460
|
} else {
|
|
1394
|
-
const
|
|
1395
|
-
|
|
1461
|
+
const content = this.lowerChildren(el.children);
|
|
1462
|
+
const ir = content.length === 1 ? content[0] : { kind: "fragment", children: content };
|
|
1463
|
+
childrenCode = `() => ${paren(this.emit(ir), "arrowBody")}`;
|
|
1396
1464
|
}
|
|
1397
1465
|
const children = [{ kind: "expr", code: childrenCode, reactive: false }];
|
|
1398
1466
|
const at = this.tagAt(el);
|
|
@@ -1409,25 +1477,6 @@ var Lowerer = class {
|
|
|
1409
1477
|
const clone = { ...el, attributes: el.attributes.filter((a) => !drop(a)) };
|
|
1410
1478
|
return clone.kind === "Element" ? this.lowerElement(clone) : this.lowerComponent(clone);
|
|
1411
1479
|
}
|
|
1412
|
-
/** Same element (minus each/key) but with explicit IR children. */
|
|
1413
|
-
rebuildWithChildren(el, children) {
|
|
1414
|
-
const props = this.lowerAttributes(
|
|
1415
|
-
el.attributes.filter((a) => a.kind !== "EachDirective")
|
|
1416
|
-
);
|
|
1417
|
-
if (el.kind === "Element") {
|
|
1418
|
-
const at = this.tagAt(el);
|
|
1419
|
-
return {
|
|
1420
|
-
kind: "element",
|
|
1421
|
-
tag: el.tag,
|
|
1422
|
-
svg: el.namespace === "svg",
|
|
1423
|
-
props,
|
|
1424
|
-
children,
|
|
1425
|
-
static: false,
|
|
1426
|
-
...at ? { at } : {}
|
|
1427
|
-
};
|
|
1428
|
-
}
|
|
1429
|
-
return { kind: "component", name: el.tag, props, children };
|
|
1430
|
-
}
|
|
1431
1480
|
// --- attributes ---------------------------------------------------------
|
|
1432
1481
|
lowerAttributes(attrs) {
|
|
1433
1482
|
const props = [];
|
|
@@ -1746,6 +1795,22 @@ var DELEGATED2 = /* @__PURE__ */ new Set([
|
|
|
1746
1795
|
"mouseup"
|
|
1747
1796
|
]);
|
|
1748
1797
|
var isReactive = (node) => isReactiveShape(shapeOf(node));
|
|
1798
|
+
var CONTAINER2 = "container";
|
|
1799
|
+
function directive(node, name) {
|
|
1800
|
+
if (node.type !== "JSXElement") return void 0;
|
|
1801
|
+
const opening = node.openingElement;
|
|
1802
|
+
if (opening.name.type !== "JSXIdentifier" || opening.name.name[0] !== opening.name.name[0].toLowerCase()) return void 0;
|
|
1803
|
+
return opening.attributes.find((a) => a.type === "JSXAttribute" && a.name.type === "JSXIdentifier" && a.name.name === name);
|
|
1804
|
+
}
|
|
1805
|
+
function directiveExpr(attr) {
|
|
1806
|
+
const v = attr.value;
|
|
1807
|
+
return v?.type === "JSXExpressionContainer" && v.expression?.type !== "JSXEmptyExpression" ? v.expression : void 0;
|
|
1808
|
+
}
|
|
1809
|
+
function emitIR(ir, ctx) {
|
|
1810
|
+
const { code, imports, templates } = imperativeBackend.emit(ir, {});
|
|
1811
|
+
for (const s of imports) ctx.used.add(s);
|
|
1812
|
+
return inlineTemplates(code, templates);
|
|
1813
|
+
}
|
|
1749
1814
|
var posOf = (node, ctx) => {
|
|
1750
1815
|
if (!ctx.sourceFile) return void 0;
|
|
1751
1816
|
const at = node.loc?.start;
|
|
@@ -1854,7 +1919,16 @@ function buildProps(attrs, ctx) {
|
|
|
1854
1919
|
}
|
|
1855
1920
|
function buildChildren(children, ctx) {
|
|
1856
1921
|
const out = [];
|
|
1857
|
-
for (
|
|
1922
|
+
for (let i = 0; i < children.length; i++) {
|
|
1923
|
+
const child = children[i];
|
|
1924
|
+
if (directive(child, "if")) {
|
|
1925
|
+
let next = i + 1;
|
|
1926
|
+
while (next < children.length && children[next].type === "JSXText" && !cleanTemplateText(children[next].value)) next++;
|
|
1927
|
+
const fallback = directive(children[next], "else") ? children[next] : null;
|
|
1928
|
+
out.push(buildIf(child, fallback, ctx));
|
|
1929
|
+
if (fallback) i = next;
|
|
1930
|
+
continue;
|
|
1931
|
+
}
|
|
1858
1932
|
if (child.type === "JSXText") {
|
|
1859
1933
|
const text = cleanTemplateText(child.value);
|
|
1860
1934
|
if (text) out.push({ kind: "text", value: text });
|
|
@@ -1891,19 +1965,68 @@ function readLoad(attrs) {
|
|
|
1891
1965
|
}
|
|
1892
1966
|
return void 0;
|
|
1893
1967
|
}
|
|
1968
|
+
function buildIf(node, fallback, ctx) {
|
|
1969
|
+
const cond = directiveExpr(directive(node, "if"));
|
|
1970
|
+
const props = [
|
|
1971
|
+
cond ? { name: "when", kind: "attr", expr: ctx.code(cond), reactive: isReactive(cond), at: posOf(cond, ctx) } : { name: "when", kind: "attr", literal: true }
|
|
1972
|
+
];
|
|
1973
|
+
if (fallback) {
|
|
1974
|
+
props.push({ name: "fallback", kind: "attr", expr: emitIR(buildElement(fallback, ctx, ["else"]), ctx), jsxElement: true });
|
|
1975
|
+
}
|
|
1976
|
+
return { kind: "component", name: "Show", props, children: [buildElement(node, ctx, ["if"])] };
|
|
1977
|
+
}
|
|
1978
|
+
function buildEach(node, ctx) {
|
|
1979
|
+
const attr = directive(node, "each");
|
|
1980
|
+
if (!attr) return null;
|
|
1981
|
+
const list = directiveExpr(attr);
|
|
1982
|
+
const props = [
|
|
1983
|
+
list ? { name: "each", kind: "attr", expr: ctx.code(list), reactive: isReactive(list), at: posOf(list, ctx) } : { name: "each", kind: "attr", expr: "[]" }
|
|
1984
|
+
];
|
|
1985
|
+
const key = directive(node, "key");
|
|
1986
|
+
if (key) {
|
|
1987
|
+
const keyExpr = directiveExpr(key);
|
|
1988
|
+
const by = isString(key.value) ? `(item) => item[${JSON.stringify(literalOf(key.value))}]` : keyExpr ? ctx.code(keyExpr) : void 0;
|
|
1989
|
+
if (by) props.push({ name: "by", kind: "attr", expr: by });
|
|
1990
|
+
}
|
|
1991
|
+
const content = node.children.filter((c) => !(c.type === "JSXText" && !cleanTemplateText(c.value)));
|
|
1992
|
+
const only = content.length === 1 && content[0].type === "JSXExpressionContainer" ? content[0].expression : null;
|
|
1993
|
+
let render;
|
|
1994
|
+
if (only && (only.type === "ArrowFunctionExpression" || only.type === "FunctionExpression")) {
|
|
1995
|
+
const fn = ctx.code(only);
|
|
1996
|
+
const live = only.type === "ArrowFunctionExpression" && only.body.type !== "BlockStatement" && isReactive(only.body);
|
|
1997
|
+
render = live ? `(...args) => () => (${fn})(...args)` : fn;
|
|
1998
|
+
} else {
|
|
1999
|
+
const built = buildChildren(node.children, ctx);
|
|
2000
|
+
const ir = built.length === 1 ? built[0] : { kind: "fragment", children: built };
|
|
2001
|
+
render = `() => ${paren(emitIR(ir, ctx), "arrowBody")}`;
|
|
2002
|
+
}
|
|
2003
|
+
return { kind: "component", name: "For", props, children: [{ kind: "expr", code: render, reactive: false }] };
|
|
2004
|
+
}
|
|
2005
|
+
function buildElement(node, ctx, handled) {
|
|
2006
|
+
const skip = new Set(handled);
|
|
2007
|
+
const directives = /* @__PURE__ */ new Set(["if", "else", "each", ...directive(node, "each") ? ["key"] : []]);
|
|
2008
|
+
const attributes = node.openingElement.attributes.filter(
|
|
2009
|
+
(a) => !(a.type === "JSXAttribute" && a.name.type === "JSXIdentifier" && (skip.has(a.name.name) || directives.has(a.name.name)))
|
|
2010
|
+
);
|
|
2011
|
+
const { tag } = tagInfo(node.openingElement.name, ctx);
|
|
2012
|
+
const each = buildEach(node, ctx);
|
|
2013
|
+
const children = each ? [each] : buildChildren(node.children, ctx);
|
|
2014
|
+
if (tag === CONTAINER2) return children.length === 1 ? children[0] : { kind: "fragment", children };
|
|
2015
|
+
const at = ctx.sourceFile && node.loc?.start ? { file: ctx.sourceFile, line: node.loc.start.line, column: node.loc.start.column } : void 0;
|
|
2016
|
+
return { kind: "element", tag, svg: SVG_TAGS.has(tag), props: buildProps(attributes, ctx), children, static: false, ...at ? { at } : {} };
|
|
2017
|
+
}
|
|
1894
2018
|
function buildNode(node, ctx) {
|
|
1895
2019
|
if (node.type === "JSXFragment") {
|
|
1896
2020
|
return { kind: "fragment", children: buildChildren(node.children, ctx) };
|
|
1897
2021
|
}
|
|
2022
|
+
if (directive(node, "if")) return buildIf(node, null, ctx);
|
|
1898
2023
|
const { tag, component } = tagInfo(node.openingElement.name, ctx);
|
|
2024
|
+
if (!component) return buildElement(node, ctx, []);
|
|
1899
2025
|
const props = buildProps(node.openingElement.attributes, ctx);
|
|
1900
2026
|
const children = buildChildren(node.children, ctx);
|
|
1901
2027
|
const at = ctx.sourceFile && node.loc?.start ? { file: ctx.sourceFile, line: node.loc.start.line, column: node.loc.start.column } : void 0;
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
return { kind: "component", name: tag, props, children, ...load ? { load } : {}, ...at ? { at } : {} };
|
|
1905
|
-
}
|
|
1906
|
-
return { kind: "element", tag, svg: SVG_TAGS.has(tag), props, children, static: false, ...at ? { at } : {} };
|
|
2028
|
+
const load = readLoad(node.openingElement.attributes);
|
|
2029
|
+
return { kind: "component", name: tag, props, children, ...load ? { load } : {}, ...at ? { at } : {} };
|
|
1907
2030
|
}
|
|
1908
2031
|
function buildJsxIR(node, ctx) {
|
|
1909
2032
|
const ir = buildNode(node, ctx);
|
|
@@ -2572,7 +2695,7 @@ function transformTemplates(code, id, options = {}) {
|
|
|
2572
2695
|
const wantsJsx = format !== "lit";
|
|
2573
2696
|
const mayHaveTemplate = wantsLit && (code.includes(`${litTag}\``) || code.includes("svg`"));
|
|
2574
2697
|
const wantsIntrinsics = options.intrinsics !== false && mayHaveIntrinsic(code);
|
|
2575
|
-
const wantsSources = options.sourceLocations === true &&
|
|
2698
|
+
const wantsSources = options.sourceLocations === true && mayHaveSourceMarks(code);
|
|
2576
2699
|
const sourceName = relativeToRoot(id, options.sourceRoot);
|
|
2577
2700
|
if (!mayHaveTemplate && !(wantsJsx && code.includes("<")) && !wantsIntrinsics && !wantsSources) return null;
|
|
2578
2701
|
const ast = (0, import_parser2.parse)(code, {
|