@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.
- package/dist/analyze/intrinsics.cjs +31 -1
- package/dist/analyze/intrinsics.d.cts +14 -0
- package/dist/analyze/intrinsics.d.ts +14 -0
- package/dist/analyze/intrinsics.d.ts.map +1 -1
- package/dist/analyze/intrinsics.js +35 -0
- package/dist/analyze/intrinsics.mjs +31 -1
- 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-RJFQVFJW.mjs} +4 -4
- package/dist/{chunk-QZ4CJPYP.mjs → chunk-DP2QDWWH.mjs} +1 -1
- package/dist/{chunk-DWNWN5RH.mjs → chunk-E2RWTIYE.mjs} +21 -15
- package/dist/{chunk-XJ5H2MXY.mjs → chunk-HCCBEJEZ.mjs} +31 -1
- package/dist/{chunk-VOUI6XPV.mjs → chunk-HIZU7WI2.mjs} +1 -1
- package/dist/{chunk-VC6X44FS.mjs → chunk-ZR2QHTEX.mjs} +505 -68
- package/dist/codegen/backends/imperative.cjs +24 -6
- package/dist/codegen/backends/imperative.d.ts.map +1 -1
- package/dist/codegen/backends/imperative.js +20 -4
- package/dist/codegen/backends/imperative.mjs +24 -6
- package/dist/frontend/babel/build-ir-lit.cjs +470 -63
- package/dist/frontend/babel/build-ir-lit.mjs +470 -63
- package/dist/frontend/babel/build-ir.cjs +470 -63
- package/dist/frontend/babel/build-ir.mjs +470 -63
- package/dist/frontend/babel/index.cjs +471 -64
- package/dist/frontend/babel/index.mjs +471 -64
- package/dist/frontend/babel/lower-template.cjs +470 -63
- package/dist/frontend/babel/lower-template.mjs +470 -63
- package/dist/frontend/babel/plugin.cjs +470 -63
- package/dist/frontend/babel/plugin.mjs +470 -63
- package/dist/index.cjs +360 -58
- package/dist/index.mjs +372 -58
- package/dist/integrations.cjs +1347 -98
- package/dist/integrations.d.ts.map +1 -1
- package/dist/integrations.js +44 -2
- package/dist/integrations.mjs +205 -19
- package/dist/lower/compile-template.cjs +354 -57
- package/dist/lower/compile-template.d.cts +13 -0
- package/dist/lower/compile-template.d.ts +13 -0
- package/dist/lower/compile-template.d.ts.map +1 -1
- package/dist/lower/compile-template.js +3 -0
- package/dist/lower/compile-template.mjs +366 -57
- package/dist/lower/entities.cjs +288 -0
- package/dist/lower/entities.d.cts +1 -0
- package/dist/lower/entities.d.ts +2 -0
- package/dist/lower/entities.d.ts.map +1 -0
- package/dist/lower/entities.js +54 -0
- package/dist/lower/entities.mjs +267 -0
- package/dist/lower/jsx.cjs +567 -7
- package/dist/lower/jsx.d.cts +8 -0
- package/dist/lower/jsx.d.ts +8 -0
- package/dist/lower/jsx.d.ts.map +1 -1
- package/dist/lower/jsx.js +205 -7
- package/dist/lower/jsx.mjs +567 -7
- package/dist/lower/template.cjs +332 -56
- package/dist/lower/template.d.ts.map +1 -1
- package/dist/lower/template.js +57 -49
- package/dist/lower/template.mjs +332 -56
- package/dist/resolve/builtins.cjs +1 -1
- package/dist/resolve/builtins.mjs +1 -1
- package/dist/resolve/component-globals.cjs +20 -1
- package/dist/resolve/component-globals.js +2 -2
- package/dist/resolve/component-globals.mjs +20 -1
- package/dist/resolve/write-globals.cjs +20 -1
- package/dist/resolve/write-globals.mjs +20 -1
- package/dist/{server-fns-BBZRZUPP.mjs → server-fns-JLSTKWPS.mjs} +4 -4
- package/dist/{server-functions-VEGLIFCE.mjs → server-functions-BGY3RD4R.mjs} +3 -3
- package/dist/transform/index.cjs +1123 -77
- package/dist/transform/index.mjs +1141 -91
- package/dist/transform/intrinsics.cjs +18 -0
- package/dist/transform/intrinsics.mjs +18 -0
- package/dist/transform/props.mjs +19 -14
- package/dist/transform/server-fns.mjs +19 -14
- 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/styles.cjs +588 -0
- package/dist/transform/styles.d.cts +211 -0
- package/dist/transform/styles.d.ts +212 -0
- package/dist/transform/styles.d.ts.map +1 -0
- package/dist/transform/styles.js +714 -0
- package/dist/transform/styles.mjs +653 -0
- package/dist/transform/templates.cjs +1122 -76
- package/dist/transform/templates.d.cts +13 -0
- package/dist/transform/templates.d.ts +13 -0
- package/dist/transform/templates.d.ts.map +1 -1
- package/dist/transform/templates.js +51 -14
- package/dist/transform/templates.mjs +1140 -90
- package/dist/{transform-UWZ7ZGJ2.mjs → transform-GBP6Y4UI.mjs} +603 -19
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/dist/vite-styles.cjs +180 -0
- package/dist/vite-styles.d.cts +59 -0
- package/dist/vite-styles.d.ts +60 -0
- package/dist/vite-styles.d.ts.map +1 -0
- package/dist/vite-styles.js +198 -0
- package/dist/vite-styles.mjs +159 -0
- package/package.json +10 -3
package/dist/integrations.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @fluixi/compiler v1.0.0-alpha.
|
|
1
|
+
/*! @fluixi/compiler v1.0.0-alpha.94 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
|
|
2
2
|
"use strict";
|
|
3
3
|
var __create = Object.create;
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
@@ -136,6 +136,11 @@ var init_builtins = __esm({
|
|
|
136
136
|
});
|
|
137
137
|
|
|
138
138
|
// src/analyze/intrinsics.ts
|
|
139
|
+
function tagIntrinsics(bound) {
|
|
140
|
+
const tags = /* @__PURE__ */ new Map();
|
|
141
|
+
for (const [name, tag] of Object.entries(TAG_INTRINSICS)) if (!bound.has(name)) tags.set(name, tag.export);
|
|
142
|
+
return tags;
|
|
143
|
+
}
|
|
139
144
|
function mayHaveIntrinsic(code) {
|
|
140
145
|
return INTRINSIC_CALL.test(code);
|
|
141
146
|
}
|
|
@@ -145,7 +150,7 @@ function isIntrinsicName(name) {
|
|
|
145
150
|
function isPrimitiveModule(source) {
|
|
146
151
|
return PRIMITIVE_MODULES.includes(source);
|
|
147
152
|
}
|
|
148
|
-
var REACTIVE_MODULE, INTRINSICS, RUNTIME_PRIMITIVES, PRIMITIVE_MODULES, INTRINSIC_CALL;
|
|
153
|
+
var REACTIVE_MODULE, INTRINSICS, RUNTIME_PRIMITIVES, PRIMITIVE_MODULES, TAG_INTRINSICS, INTRINSIC_CALL;
|
|
149
154
|
var init_intrinsics = __esm({
|
|
150
155
|
"src/analyze/intrinsics.ts"() {
|
|
151
156
|
"use strict";
|
|
@@ -156,6 +161,7 @@ var init_intrinsics = __esm({
|
|
|
156
161
|
$effect: { export: "effect", module: REACTIVE_MODULE, returns: "effect" },
|
|
157
162
|
$store: { export: "store", module: "@fluixi/reactive/store", returns: "store-handle" },
|
|
158
163
|
$resource: { export: "resource", module: REACTIVE_MODULE, returns: "resource-handle" },
|
|
164
|
+
$cachedResource: { export: "cachedResource", module: "@fluixi/reactive/cached-resource", returns: "resource-handle" },
|
|
159
165
|
// No short runtime form for these yet, so the intrinsic stands for the `create*`
|
|
160
166
|
// name. Still worth having: no import to write, and when a shorter form is
|
|
161
167
|
// designed, the change is this line rather than a compiler pass.
|
|
@@ -166,6 +172,19 @@ var init_intrinsics = __esm({
|
|
|
166
172
|
// dependency analysis must not guess at.
|
|
167
173
|
$untrack: { export: "untrack", module: REACTIVE_MODULE, returns: "plain" },
|
|
168
174
|
$untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" },
|
|
175
|
+
// Scopes, scheduling and lifecycle: no value to classify, but the same authoring promise,
|
|
176
|
+
// no import to write. `$cleanup` registers a callback on the current owner (`onCleanup`).
|
|
177
|
+
$batch: { export: "batch", module: REACTIVE_MODULE, returns: "plain" },
|
|
178
|
+
$cleanup: { export: "onCleanup", module: REACTIVE_MODULE, returns: "plain" },
|
|
179
|
+
$root: { export: "root", module: REACTIVE_MODULE, returns: "plain" },
|
|
180
|
+
$context: { export: "context", module: REACTIVE_MODULE, returns: "plain" },
|
|
181
|
+
$renderEffect: { export: "renderEffect", module: REACTIVE_MODULE, returns: "effect" },
|
|
182
|
+
$computed: { export: "computed", module: REACTIVE_MODULE, returns: "effect" },
|
|
183
|
+
// Storage for where the code runs, and a signal kept in it. `$persisted` is a signal
|
|
184
|
+
// handle as far as reads go: the same accessor with `set` on it.
|
|
185
|
+
$storage: { export: "useStorage", module: "@fluixi/core/storage", returns: "plain" },
|
|
186
|
+
$asyncStorage: { export: "useAsyncStorage", module: "@fluixi/core/storage", returns: "plain" },
|
|
187
|
+
$persisted: { export: "persisted", module: "@fluixi/core/storage", returns: "signal-handle" },
|
|
169
188
|
// An environment variable, public or server-only; the browser build refuses a secret.
|
|
170
189
|
$env: { export: "env", module: "@fluixi/start/env", returns: "plain" }
|
|
171
190
|
};
|
|
@@ -178,8 +197,11 @@ var init_intrinsics = __esm({
|
|
|
178
197
|
createMemo: "memo-accessor",
|
|
179
198
|
createEffect: "effect",
|
|
180
199
|
createRenderEffect: "effect",
|
|
200
|
+
renderEffect: "effect",
|
|
201
|
+
computed: "effect",
|
|
181
202
|
createStore: "reactive-object",
|
|
182
203
|
resource: "resource-handle",
|
|
204
|
+
cachedResource: "resource-handle",
|
|
183
205
|
createResource: "reactive-object",
|
|
184
206
|
createSelector: "memo-accessor",
|
|
185
207
|
createDeferred: "memo-accessor"
|
|
@@ -188,8 +210,14 @@ var init_intrinsics = __esm({
|
|
|
188
210
|
"@fluixi/reactive",
|
|
189
211
|
"@fluixi/reactive/signal",
|
|
190
212
|
"@fluixi/reactive/store",
|
|
213
|
+
"@fluixi/reactive/cached-resource",
|
|
191
214
|
"@fluixi/core"
|
|
192
215
|
];
|
|
216
|
+
TAG_INTRINSICS = {
|
|
217
|
+
$html: { export: "html", module: "@fluixi/core" },
|
|
218
|
+
$svg: { export: "svg", module: "@fluixi/core" },
|
|
219
|
+
$css: { export: "css", module: "@fluixi/core" }
|
|
220
|
+
};
|
|
193
221
|
INTRINSIC_CALL = new RegExp(`\\$(?:${Object.keys(INTRINSICS).map((n) => n.slice(1)).join("|")})\\s*\\(`);
|
|
194
222
|
}
|
|
195
223
|
});
|
|
@@ -686,11 +714,12 @@ var init_reactive_bindings = __esm({
|
|
|
686
714
|
});
|
|
687
715
|
|
|
688
716
|
// src/transform/source-locations.ts
|
|
689
|
-
function
|
|
717
|
+
function mayHaveSourceMarks(code) {
|
|
690
718
|
for (const name of RUNTIME_PRIMITIVES2) {
|
|
691
719
|
if (code.includes(name)) return true;
|
|
692
720
|
}
|
|
693
|
-
|
|
721
|
+
if (code.includes("$signal") || code.includes("$memo") || code.includes("$effect") || code.includes("$store")) return true;
|
|
722
|
+
return /\bclass\b[^{;]*\bextends\b/.test(code);
|
|
694
723
|
}
|
|
695
724
|
function isLoneBranch(statement, parent) {
|
|
696
725
|
if (!parent || statement.type === "BlockStatement") return false;
|
|
@@ -719,6 +748,14 @@ function walk3(node, visit, stack = []) {
|
|
|
719
748
|
}
|
|
720
749
|
function nameFor(stack) {
|
|
721
750
|
const declarator = stack[stack.length - 1];
|
|
751
|
+
if (declarator && CLASS_FIELDS.has(declarator.type)) {
|
|
752
|
+
const key = declarator.key;
|
|
753
|
+
if (key?.type === "Identifier" || key?.type === "PrivateIdentifier" || key?.type === "PrivateName") {
|
|
754
|
+
const name = key.name ?? key.id?.name;
|
|
755
|
+
return name;
|
|
756
|
+
}
|
|
757
|
+
return void 0;
|
|
758
|
+
}
|
|
722
759
|
if (declarator?.type !== "VariableDeclarator") return void 0;
|
|
723
760
|
const id = declarator.id;
|
|
724
761
|
if (id?.type === "Identifier") return id.name;
|
|
@@ -767,6 +804,17 @@ function collectSourceEdits(program, filename) {
|
|
|
767
804
|
});
|
|
768
805
|
}
|
|
769
806
|
}
|
|
807
|
+
if ((node.type === "ClassDeclaration" || node.type === "ClassExpression") && node.superClass && !node.declare) {
|
|
808
|
+
const at = node.loc?.start;
|
|
809
|
+
const body = node.body;
|
|
810
|
+
if (at && body) {
|
|
811
|
+
edits.push({
|
|
812
|
+
start: body.start + 1,
|
|
813
|
+
end: body.start + 1,
|
|
814
|
+
code: `static{globalThis.${CLASS_MARKER}?.(this,${JSON.stringify(filename)},${at.line},${at.column});}`
|
|
815
|
+
});
|
|
816
|
+
}
|
|
817
|
+
}
|
|
770
818
|
if (node.type !== "CallExpression") return;
|
|
771
819
|
const callee = node.callee;
|
|
772
820
|
if (callee?.type !== "Identifier") return;
|
|
@@ -776,6 +824,26 @@ function collectSourceEdits(program, filename) {
|
|
|
776
824
|
if (!intrinsic && !imported) return;
|
|
777
825
|
const position = node.loc?.start;
|
|
778
826
|
if (!position) return;
|
|
827
|
+
for (let i = stack.length - 1; i >= 0; i--) {
|
|
828
|
+
const up = stack[i];
|
|
829
|
+
if (isStatement(up)) break;
|
|
830
|
+
if (CLASS_FIELDS.has(up.type)) {
|
|
831
|
+
if (claimed.has(node.start)) return;
|
|
832
|
+
claimed.add(node.start);
|
|
833
|
+
const label2 = nameFor(stack);
|
|
834
|
+
const own = !up.static;
|
|
835
|
+
const args2 = [
|
|
836
|
+
JSON.stringify(filename),
|
|
837
|
+
String(position.line),
|
|
838
|
+
String(position.column),
|
|
839
|
+
label2 ? JSON.stringify(label2) : own ? "undefined" : void 0,
|
|
840
|
+
own ? "this" : void 0
|
|
841
|
+
].filter((a) => a !== void 0).join(",");
|
|
842
|
+
edits.push({ start: node.start, end: node.start, code: `(globalThis.${SOURCE_MARKER}?.(${args2}),` });
|
|
843
|
+
edits.push({ start: node.end, end: node.end, code: ")" });
|
|
844
|
+
return;
|
|
845
|
+
}
|
|
846
|
+
}
|
|
779
847
|
let statement;
|
|
780
848
|
let parent;
|
|
781
849
|
let index = -1;
|
|
@@ -815,7 +883,7 @@ function collectSourceEdits(program, filename) {
|
|
|
815
883
|
});
|
|
816
884
|
return { edits, marked: edits.length };
|
|
817
885
|
}
|
|
818
|
-
var SOURCE_MARKER, COMPONENT_MARKER, HOLE_MARKER, markHole, PROPS_MARKER, markProps, RUNTIME_PRIMITIVES2, SINGLE_STATEMENT_PARENTS;
|
|
886
|
+
var SOURCE_MARKER, COMPONENT_MARKER, CLASS_MARKER, HOLE_MARKER, markHole, PROPS_MARKER, markProps, RUNTIME_PRIMITIVES2, SINGLE_STATEMENT_PARENTS, CLASS_FIELDS;
|
|
819
887
|
var init_source_locations = __esm({
|
|
820
888
|
"src/transform/source-locations.ts"() {
|
|
821
889
|
"use strict";
|
|
@@ -823,6 +891,7 @@ var init_source_locations = __esm({
|
|
|
823
891
|
init_reactive_bindings();
|
|
824
892
|
SOURCE_MARKER = "__fx_source";
|
|
825
893
|
COMPONENT_MARKER = "__fx_component";
|
|
894
|
+
CLASS_MARKER = "__fx_class";
|
|
826
895
|
HOLE_MARKER = "__fx_hole";
|
|
827
896
|
markHole = (accessor, line, column, name) => `(globalThis.${HOLE_MARKER} ?? ((f) => f))(${accessor},${line},${column}${name === void 0 ? "" : `,${JSON.stringify(name)}`})`;
|
|
828
897
|
PROPS_MARKER = "__fx_props";
|
|
@@ -850,6 +919,7 @@ var init_source_locations = __esm({
|
|
|
850
919
|
"LabeledStatement",
|
|
851
920
|
"WithStatement"
|
|
852
921
|
]);
|
|
922
|
+
CLASS_FIELDS = /* @__PURE__ */ new Set(["PropertyDefinition", "ClassProperty", "ClassPrivateProperty", "AccessorProperty"]);
|
|
853
923
|
}
|
|
854
924
|
});
|
|
855
925
|
|
|
@@ -1013,13 +1083,16 @@ function emitComponent(name, props, children, used, templates, at) {
|
|
|
1013
1083
|
used.add("createComponent");
|
|
1014
1084
|
const spreads = props.filter((p) => p.kind === "spread");
|
|
1015
1085
|
const normal = props.filter((p) => p.kind !== "spread");
|
|
1016
|
-
const
|
|
1017
|
-
(p) => `get ${propKey(p.name)}() { return ${componentPropValue(p)}; }`
|
|
1018
|
-
);
|
|
1086
|
+
const bodies = normal.map((p) => [p.name, componentPropValue(p)]);
|
|
1019
1087
|
if (children.length > 0) {
|
|
1020
|
-
|
|
1088
|
+
bodies.push(["children", emitChildren(children, used, templates)]);
|
|
1089
|
+
}
|
|
1090
|
+
let obj = `{ ${bodies.map(([name2, body]) => `get ${propKey(name2)}() { return ${body}; }`).join(", ")} }`;
|
|
1091
|
+
if (bodies.some(([, body]) => /\bthis\b/.test(body))) {
|
|
1092
|
+
const thunks = bodies.map(([name2, body]) => `${JSON.stringify(name2)}: () => (${body})`);
|
|
1093
|
+
const getters = bodies.map(([name2]) => `get ${propKey(name2)}() { return _$t[${JSON.stringify(name2)}](); }`);
|
|
1094
|
+
obj = `((_$t) => ({ ${getters.join(", ")} }))({ ${thunks.join(", ")} })`;
|
|
1021
1095
|
}
|
|
1022
|
-
let obj = `{ ${entries.join(", ")} }`;
|
|
1023
1096
|
if (spreads.length > 0) {
|
|
1024
1097
|
used.add("mergeProps");
|
|
1025
1098
|
obj = `mergeProps(${spreads.map((s) => s.expr).join(", ")}, ${obj})`;
|
|
@@ -1100,7 +1173,8 @@ function emitNode(node, used, templates) {
|
|
|
1100
1173
|
} else {
|
|
1101
1174
|
used.add("spread");
|
|
1102
1175
|
const svgFlag = node.svg ? ", isSVG: true" : "";
|
|
1103
|
-
const
|
|
1176
|
+
const accessors = node.props.filter((p) => p.kind !== "spread" && p.expr !== void 0 && p.reactive && p.name !== "ref").map((p) => p.name);
|
|
1177
|
+
const customFlag = node.tag.includes("-") ? `, isCustomElement: true, accessors: ${JSON.stringify(accessors)}` : "";
|
|
1104
1178
|
parts.push(
|
|
1105
1179
|
`spread({ element: ${el}, props: ${emitProps(node.props, null, used)}${svgFlag}${customFlag} });`
|
|
1106
1180
|
);
|
|
@@ -1180,6 +1254,277 @@ var init_text = __esm({
|
|
|
1180
1254
|
}
|
|
1181
1255
|
});
|
|
1182
1256
|
|
|
1257
|
+
// src/lower/entities.ts
|
|
1258
|
+
function decodeEntities(value) {
|
|
1259
|
+
if (!value.includes("&")) return value;
|
|
1260
|
+
return value.replace(REFERENCE, (match, hex, dec, name) => {
|
|
1261
|
+
const code = hex ? parseInt(hex, 16) : dec ? parseInt(dec, 10) : Object.prototype.hasOwnProperty.call(NAMED, name) ? NAMED[name] : void 0;
|
|
1262
|
+
return code !== void 0 && code <= 1114111 ? String.fromCodePoint(code) : match;
|
|
1263
|
+
});
|
|
1264
|
+
}
|
|
1265
|
+
var NAMED, REFERENCE;
|
|
1266
|
+
var init_entities = __esm({
|
|
1267
|
+
"src/lower/entities.ts"() {
|
|
1268
|
+
"use strict";
|
|
1269
|
+
NAMED = {
|
|
1270
|
+
quot: 34,
|
|
1271
|
+
amp: 38,
|
|
1272
|
+
apos: 39,
|
|
1273
|
+
lt: 60,
|
|
1274
|
+
gt: 62,
|
|
1275
|
+
nbsp: 160,
|
|
1276
|
+
iexcl: 161,
|
|
1277
|
+
cent: 162,
|
|
1278
|
+
pound: 163,
|
|
1279
|
+
curren: 164,
|
|
1280
|
+
yen: 165,
|
|
1281
|
+
brvbar: 166,
|
|
1282
|
+
sect: 167,
|
|
1283
|
+
uml: 168,
|
|
1284
|
+
copy: 169,
|
|
1285
|
+
ordf: 170,
|
|
1286
|
+
laquo: 171,
|
|
1287
|
+
not: 172,
|
|
1288
|
+
shy: 173,
|
|
1289
|
+
reg: 174,
|
|
1290
|
+
macr: 175,
|
|
1291
|
+
deg: 176,
|
|
1292
|
+
plusmn: 177,
|
|
1293
|
+
sup2: 178,
|
|
1294
|
+
sup3: 179,
|
|
1295
|
+
acute: 180,
|
|
1296
|
+
micro: 181,
|
|
1297
|
+
para: 182,
|
|
1298
|
+
middot: 183,
|
|
1299
|
+
cedil: 184,
|
|
1300
|
+
sup1: 185,
|
|
1301
|
+
ordm: 186,
|
|
1302
|
+
raquo: 187,
|
|
1303
|
+
frac14: 188,
|
|
1304
|
+
frac12: 189,
|
|
1305
|
+
frac34: 190,
|
|
1306
|
+
iquest: 191,
|
|
1307
|
+
Agrave: 192,
|
|
1308
|
+
Aacute: 193,
|
|
1309
|
+
Acirc: 194,
|
|
1310
|
+
Atilde: 195,
|
|
1311
|
+
Auml: 196,
|
|
1312
|
+
Aring: 197,
|
|
1313
|
+
AElig: 198,
|
|
1314
|
+
Ccedil: 199,
|
|
1315
|
+
Egrave: 200,
|
|
1316
|
+
Eacute: 201,
|
|
1317
|
+
Ecirc: 202,
|
|
1318
|
+
Euml: 203,
|
|
1319
|
+
Igrave: 204,
|
|
1320
|
+
Iacute: 205,
|
|
1321
|
+
Icirc: 206,
|
|
1322
|
+
Iuml: 207,
|
|
1323
|
+
ETH: 208,
|
|
1324
|
+
Ntilde: 209,
|
|
1325
|
+
Ograve: 210,
|
|
1326
|
+
Oacute: 211,
|
|
1327
|
+
Ocirc: 212,
|
|
1328
|
+
Otilde: 213,
|
|
1329
|
+
Ouml: 214,
|
|
1330
|
+
times: 215,
|
|
1331
|
+
Oslash: 216,
|
|
1332
|
+
Ugrave: 217,
|
|
1333
|
+
Uacute: 218,
|
|
1334
|
+
Ucirc: 219,
|
|
1335
|
+
Uuml: 220,
|
|
1336
|
+
Yacute: 221,
|
|
1337
|
+
THORN: 222,
|
|
1338
|
+
szlig: 223,
|
|
1339
|
+
agrave: 224,
|
|
1340
|
+
aacute: 225,
|
|
1341
|
+
acirc: 226,
|
|
1342
|
+
atilde: 227,
|
|
1343
|
+
auml: 228,
|
|
1344
|
+
aring: 229,
|
|
1345
|
+
aelig: 230,
|
|
1346
|
+
ccedil: 231,
|
|
1347
|
+
egrave: 232,
|
|
1348
|
+
eacute: 233,
|
|
1349
|
+
ecirc: 234,
|
|
1350
|
+
euml: 235,
|
|
1351
|
+
igrave: 236,
|
|
1352
|
+
iacute: 237,
|
|
1353
|
+
icirc: 238,
|
|
1354
|
+
iuml: 239,
|
|
1355
|
+
eth: 240,
|
|
1356
|
+
ntilde: 241,
|
|
1357
|
+
ograve: 242,
|
|
1358
|
+
oacute: 243,
|
|
1359
|
+
ocirc: 244,
|
|
1360
|
+
otilde: 245,
|
|
1361
|
+
ouml: 246,
|
|
1362
|
+
divide: 247,
|
|
1363
|
+
oslash: 248,
|
|
1364
|
+
ugrave: 249,
|
|
1365
|
+
uacute: 250,
|
|
1366
|
+
ucirc: 251,
|
|
1367
|
+
uuml: 252,
|
|
1368
|
+
yacute: 253,
|
|
1369
|
+
thorn: 254,
|
|
1370
|
+
yuml: 255,
|
|
1371
|
+
OElig: 338,
|
|
1372
|
+
oelig: 339,
|
|
1373
|
+
Scaron: 352,
|
|
1374
|
+
scaron: 353,
|
|
1375
|
+
Yuml: 376,
|
|
1376
|
+
fnof: 402,
|
|
1377
|
+
circ: 710,
|
|
1378
|
+
tilde: 732,
|
|
1379
|
+
Alpha: 913,
|
|
1380
|
+
Beta: 914,
|
|
1381
|
+
Gamma: 915,
|
|
1382
|
+
Delta: 916,
|
|
1383
|
+
Epsilon: 917,
|
|
1384
|
+
Zeta: 918,
|
|
1385
|
+
Eta: 919,
|
|
1386
|
+
Theta: 920,
|
|
1387
|
+
Iota: 921,
|
|
1388
|
+
Kappa: 922,
|
|
1389
|
+
Lambda: 923,
|
|
1390
|
+
Mu: 924,
|
|
1391
|
+
Nu: 925,
|
|
1392
|
+
Xi: 926,
|
|
1393
|
+
Omicron: 927,
|
|
1394
|
+
Pi: 928,
|
|
1395
|
+
Rho: 929,
|
|
1396
|
+
Sigma: 931,
|
|
1397
|
+
Tau: 932,
|
|
1398
|
+
Upsilon: 933,
|
|
1399
|
+
Phi: 934,
|
|
1400
|
+
Chi: 935,
|
|
1401
|
+
Psi: 936,
|
|
1402
|
+
Omega: 937,
|
|
1403
|
+
alpha: 945,
|
|
1404
|
+
beta: 946,
|
|
1405
|
+
gamma: 947,
|
|
1406
|
+
delta: 948,
|
|
1407
|
+
epsilon: 949,
|
|
1408
|
+
zeta: 950,
|
|
1409
|
+
eta: 951,
|
|
1410
|
+
theta: 952,
|
|
1411
|
+
iota: 953,
|
|
1412
|
+
kappa: 954,
|
|
1413
|
+
lambda: 955,
|
|
1414
|
+
mu: 956,
|
|
1415
|
+
nu: 957,
|
|
1416
|
+
xi: 958,
|
|
1417
|
+
omicron: 959,
|
|
1418
|
+
pi: 960,
|
|
1419
|
+
rho: 961,
|
|
1420
|
+
sigmaf: 962,
|
|
1421
|
+
sigma: 963,
|
|
1422
|
+
tau: 964,
|
|
1423
|
+
upsilon: 965,
|
|
1424
|
+
phi: 966,
|
|
1425
|
+
chi: 967,
|
|
1426
|
+
psi: 968,
|
|
1427
|
+
omega: 969,
|
|
1428
|
+
thetasym: 977,
|
|
1429
|
+
upsih: 978,
|
|
1430
|
+
piv: 982,
|
|
1431
|
+
ensp: 8194,
|
|
1432
|
+
emsp: 8195,
|
|
1433
|
+
thinsp: 8201,
|
|
1434
|
+
zwnj: 8204,
|
|
1435
|
+
zwj: 8205,
|
|
1436
|
+
lrm: 8206,
|
|
1437
|
+
rlm: 8207,
|
|
1438
|
+
ndash: 8211,
|
|
1439
|
+
mdash: 8212,
|
|
1440
|
+
lsquo: 8216,
|
|
1441
|
+
rsquo: 8217,
|
|
1442
|
+
sbquo: 8218,
|
|
1443
|
+
ldquo: 8220,
|
|
1444
|
+
rdquo: 8221,
|
|
1445
|
+
bdquo: 8222,
|
|
1446
|
+
dagger: 8224,
|
|
1447
|
+
Dagger: 8225,
|
|
1448
|
+
bull: 8226,
|
|
1449
|
+
hellip: 8230,
|
|
1450
|
+
permil: 8240,
|
|
1451
|
+
prime: 8242,
|
|
1452
|
+
Prime: 8243,
|
|
1453
|
+
lsaquo: 8249,
|
|
1454
|
+
rsaquo: 8250,
|
|
1455
|
+
oline: 8254,
|
|
1456
|
+
frasl: 8260,
|
|
1457
|
+
euro: 8364,
|
|
1458
|
+
image: 8465,
|
|
1459
|
+
weierp: 8472,
|
|
1460
|
+
real: 8476,
|
|
1461
|
+
trade: 8482,
|
|
1462
|
+
alefsym: 8501,
|
|
1463
|
+
larr: 8592,
|
|
1464
|
+
uarr: 8593,
|
|
1465
|
+
rarr: 8594,
|
|
1466
|
+
darr: 8595,
|
|
1467
|
+
harr: 8596,
|
|
1468
|
+
crarr: 8629,
|
|
1469
|
+
lArr: 8656,
|
|
1470
|
+
uArr: 8657,
|
|
1471
|
+
rArr: 8658,
|
|
1472
|
+
dArr: 8659,
|
|
1473
|
+
hArr: 8660,
|
|
1474
|
+
forall: 8704,
|
|
1475
|
+
part: 8706,
|
|
1476
|
+
exist: 8707,
|
|
1477
|
+
empty: 8709,
|
|
1478
|
+
nabla: 8711,
|
|
1479
|
+
isin: 8712,
|
|
1480
|
+
notin: 8713,
|
|
1481
|
+
ni: 8715,
|
|
1482
|
+
prod: 8719,
|
|
1483
|
+
sum: 8721,
|
|
1484
|
+
minus: 8722,
|
|
1485
|
+
lowast: 8727,
|
|
1486
|
+
radic: 8730,
|
|
1487
|
+
prop: 8733,
|
|
1488
|
+
infin: 8734,
|
|
1489
|
+
ang: 8736,
|
|
1490
|
+
and: 8743,
|
|
1491
|
+
or: 8744,
|
|
1492
|
+
cap: 8745,
|
|
1493
|
+
cup: 8746,
|
|
1494
|
+
int: 8747,
|
|
1495
|
+
there4: 8756,
|
|
1496
|
+
sim: 8764,
|
|
1497
|
+
cong: 8773,
|
|
1498
|
+
asymp: 8776,
|
|
1499
|
+
ne: 8800,
|
|
1500
|
+
equiv: 8801,
|
|
1501
|
+
le: 8804,
|
|
1502
|
+
ge: 8805,
|
|
1503
|
+
sub: 8834,
|
|
1504
|
+
sup: 8835,
|
|
1505
|
+
nsub: 8836,
|
|
1506
|
+
sube: 8838,
|
|
1507
|
+
supe: 8839,
|
|
1508
|
+
oplus: 8853,
|
|
1509
|
+
otimes: 8855,
|
|
1510
|
+
perp: 8869,
|
|
1511
|
+
sdot: 8901,
|
|
1512
|
+
lceil: 8968,
|
|
1513
|
+
rceil: 8969,
|
|
1514
|
+
lfloor: 8970,
|
|
1515
|
+
rfloor: 8971,
|
|
1516
|
+
lang: 9001,
|
|
1517
|
+
rang: 9002,
|
|
1518
|
+
loz: 9674,
|
|
1519
|
+
spades: 9824,
|
|
1520
|
+
clubs: 9827,
|
|
1521
|
+
hearts: 9829,
|
|
1522
|
+
diams: 9830
|
|
1523
|
+
};
|
|
1524
|
+
REFERENCE = /&(?:#[xX]([0-9a-fA-F]{1,6})|#([0-9]{1,7})|([a-zA-Z][a-zA-Z0-9]{1,31}));/g;
|
|
1525
|
+
}
|
|
1526
|
+
});
|
|
1527
|
+
|
|
1183
1528
|
// src/lower/template.ts
|
|
1184
1529
|
function escapeTemplate(s) {
|
|
1185
1530
|
return s.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${");
|
|
@@ -1191,7 +1536,7 @@ function lowerTemplate(pieces, holes, used, opts = {}) {
|
|
|
1191
1536
|
const { root } = (0, import_template_parser.parseTemplate)(pieces, { svg: opts.svg });
|
|
1192
1537
|
return new Lowerer(holes, used, opts.sourceFile, opts.positionAt).lowerRoot(root.children);
|
|
1193
1538
|
}
|
|
1194
|
-
var import_template_parser, DELEGATED, Lowerer;
|
|
1539
|
+
var import_template_parser, DELEGATED, CONTAINER, Lowerer;
|
|
1195
1540
|
var init_template = __esm({
|
|
1196
1541
|
"src/lower/template.ts"() {
|
|
1197
1542
|
"use strict";
|
|
@@ -1199,7 +1544,9 @@ var init_template = __esm({
|
|
|
1199
1544
|
init_load_directive();
|
|
1200
1545
|
init_imperative();
|
|
1201
1546
|
init_text();
|
|
1547
|
+
init_entities();
|
|
1202
1548
|
init_paren();
|
|
1549
|
+
init_source_locations();
|
|
1203
1550
|
DELEGATED = /* @__PURE__ */ new Set([
|
|
1204
1551
|
"click",
|
|
1205
1552
|
"dblclick",
|
|
@@ -1214,6 +1561,7 @@ var init_template = __esm({
|
|
|
1214
1561
|
"mousedown",
|
|
1215
1562
|
"mouseup"
|
|
1216
1563
|
]);
|
|
1564
|
+
CONTAINER = "container";
|
|
1217
1565
|
Lowerer = class {
|
|
1218
1566
|
constructor(holes, used, sourceFile, positionAt) {
|
|
1219
1567
|
this.holes = holes;
|
|
@@ -1265,10 +1613,6 @@ var init_template = __esm({
|
|
|
1265
1613
|
if (hasElse) i = elseIdx;
|
|
1266
1614
|
continue;
|
|
1267
1615
|
}
|
|
1268
|
-
if (child.attributes.some((a) => a.kind === "EachDirective")) {
|
|
1269
|
-
out.push(this.lowerEach(child));
|
|
1270
|
-
continue;
|
|
1271
|
-
}
|
|
1272
1616
|
}
|
|
1273
1617
|
const node = this.lowerNode(child);
|
|
1274
1618
|
if (node) out.push(node);
|
|
@@ -1282,7 +1626,7 @@ var init_template = __esm({
|
|
|
1282
1626
|
switch (node.kind) {
|
|
1283
1627
|
case "Text": {
|
|
1284
1628
|
if (node.raw) return { kind: "text", value: node.value };
|
|
1285
|
-
const cleaned = cleanTemplateText(node.value);
|
|
1629
|
+
const cleaned = decodeEntities(cleanTemplateText(node.value));
|
|
1286
1630
|
return cleaned ? { kind: "text", value: cleaned } : null;
|
|
1287
1631
|
}
|
|
1288
1632
|
case "Comment":
|
|
@@ -1310,13 +1654,16 @@ var init_template = __esm({
|
|
|
1310
1654
|
node.props.unshift({ name: "component", kind: "attr", expr: `() => ${paren(this.hole(isAttr.value.hole).code, "arrowBody")}` });
|
|
1311
1655
|
return node;
|
|
1312
1656
|
}
|
|
1657
|
+
const each = this.lowerEach(el);
|
|
1658
|
+
const children = each ? [each] : this.lowerChildren(el.children);
|
|
1659
|
+
if (el.tag === CONTAINER) return children.length === 1 ? children[0] : { kind: "fragment", children };
|
|
1313
1660
|
const at = this.tagAt(el);
|
|
1314
1661
|
return {
|
|
1315
1662
|
kind: "element",
|
|
1316
1663
|
tag: el.tag,
|
|
1317
1664
|
svg: el.namespace === "svg",
|
|
1318
|
-
props: this.lowerAttributes(el.attributes),
|
|
1319
|
-
children
|
|
1665
|
+
props: this.lowerAttributes(el.attributes, true),
|
|
1666
|
+
children,
|
|
1320
1667
|
static: false,
|
|
1321
1668
|
...at ? { at } : {}
|
|
1322
1669
|
};
|
|
@@ -1388,10 +1735,14 @@ var init_template = __esm({
|
|
|
1388
1735
|
const at = this.tagAt(el);
|
|
1389
1736
|
return { kind: "component", name: "Show", props, children: [child], ...at ? { at } : {}, ...cond.at ? { bindAt: cond.at } : {} };
|
|
1390
1737
|
}
|
|
1391
|
-
/**
|
|
1738
|
+
/**
|
|
1739
|
+
* `<el each=${items} key?>${item => …}</el>` → `<el><For each>{item => …}</For></el>`: the
|
|
1740
|
+
* content is repeated per item. Content that is not a `${item => …}` arrow is repeated as
|
|
1741
|
+
* it is. Null when the element has no `each`.
|
|
1742
|
+
*/
|
|
1392
1743
|
lowerEach(el) {
|
|
1393
1744
|
const eachDir = el.attributes.find((a) => a.kind === "EachDirective");
|
|
1394
|
-
if (!eachDir || eachDir.kind !== "EachDirective") return
|
|
1745
|
+
if (!eachDir || eachDir.kind !== "EachDirective") return null;
|
|
1395
1746
|
const each = this.hole(eachDir.hole);
|
|
1396
1747
|
const props = [{ name: "each", kind: "attr", expr: each.code, reactive: each.reactive, ...each.at ? { at: each.at } : {} }];
|
|
1397
1748
|
if (eachDir.key) {
|
|
@@ -1401,12 +1752,12 @@ var init_template = __esm({
|
|
|
1401
1752
|
const arrow = this.itemArrow(el);
|
|
1402
1753
|
let childrenCode;
|
|
1403
1754
|
if (arrow) {
|
|
1404
|
-
const
|
|
1405
|
-
|
|
1406
|
-
childrenCode = `(${arrow.params.join(", ")}) => ${paren(this.emit(repeated), "arrowBody")}`;
|
|
1755
|
+
const body = arrow.bodyReactive ? `() => ${paren(arrow.body, "arrowBody")}` : paren(arrow.body, "arrowBody");
|
|
1756
|
+
childrenCode = `(${arrow.params.join(", ")}) => ${body}`;
|
|
1407
1757
|
} else {
|
|
1408
|
-
const
|
|
1409
|
-
|
|
1758
|
+
const content = this.lowerChildren(el.children);
|
|
1759
|
+
const ir = content.length === 1 ? content[0] : { kind: "fragment", children: content };
|
|
1760
|
+
childrenCode = `() => ${paren(this.emit(ir), "arrowBody")}`;
|
|
1410
1761
|
}
|
|
1411
1762
|
const children = [{ kind: "expr", code: childrenCode, reactive: false }];
|
|
1412
1763
|
const at = this.tagAt(el);
|
|
@@ -1423,33 +1774,23 @@ var init_template = __esm({
|
|
|
1423
1774
|
const clone = { ...el, attributes: el.attributes.filter((a) => !drop(a)) };
|
|
1424
1775
|
return clone.kind === "Element" ? this.lowerElement(clone) : this.lowerComponent(clone);
|
|
1425
1776
|
}
|
|
1426
|
-
/** Same element (minus each/key) but with explicit IR children. */
|
|
1427
|
-
rebuildWithChildren(el, children) {
|
|
1428
|
-
const props = this.lowerAttributes(
|
|
1429
|
-
el.attributes.filter((a) => a.kind !== "EachDirective")
|
|
1430
|
-
);
|
|
1431
|
-
if (el.kind === "Element") {
|
|
1432
|
-
const at = this.tagAt(el);
|
|
1433
|
-
return {
|
|
1434
|
-
kind: "element",
|
|
1435
|
-
tag: el.tag,
|
|
1436
|
-
svg: el.namespace === "svg",
|
|
1437
|
-
props,
|
|
1438
|
-
children,
|
|
1439
|
-
static: false,
|
|
1440
|
-
...at ? { at } : {}
|
|
1441
|
-
};
|
|
1442
|
-
}
|
|
1443
|
-
return { kind: "component", name: el.tag, props, children };
|
|
1444
|
-
}
|
|
1445
1777
|
// --- attributes ---------------------------------------------------------
|
|
1446
|
-
|
|
1778
|
+
/**
|
|
1779
|
+
* `element`: a DOM element, where each class:/style: value that moves is its own accessor.
|
|
1780
|
+
* A component gets the object as before, rebuilt whole when any value moves.
|
|
1781
|
+
*/
|
|
1782
|
+
lowerAttributes(attrs, element = false) {
|
|
1783
|
+
let anyReactive = false;
|
|
1784
|
+
const entry = (name, h) => {
|
|
1785
|
+
anyReactive ||= h.reactive;
|
|
1786
|
+
if (!element || !h.reactive) return `${JSON.stringify(name)}: ${h.code}`;
|
|
1787
|
+
const accessor = `() => ${paren(h.code, "arrowBody")}`;
|
|
1788
|
+
return `${JSON.stringify(name)}: ${h.at ? markHole(accessor, h.at.line, h.at.column) : accessor}`;
|
|
1789
|
+
};
|
|
1447
1790
|
const props = [];
|
|
1448
1791
|
const classEntries = [];
|
|
1449
|
-
let classReactive = false;
|
|
1450
1792
|
let classAt;
|
|
1451
1793
|
const styleEntries = [];
|
|
1452
|
-
let styleReactive = false;
|
|
1453
1794
|
let styleAt;
|
|
1454
1795
|
const usePairs = [];
|
|
1455
1796
|
for (const a of attrs) {
|
|
@@ -1489,15 +1830,13 @@ var init_template = __esm({
|
|
|
1489
1830
|
break;
|
|
1490
1831
|
case "ClassDirective": {
|
|
1491
1832
|
const h = this.hole(a.hole);
|
|
1492
|
-
classEntries.push(
|
|
1493
|
-
classReactive = classReactive || h.reactive;
|
|
1833
|
+
classEntries.push(entry(a.name, h));
|
|
1494
1834
|
classAt ??= h.at;
|
|
1495
1835
|
break;
|
|
1496
1836
|
}
|
|
1497
1837
|
case "StyleDirective": {
|
|
1498
1838
|
const h = this.hole(a.hole);
|
|
1499
|
-
styleEntries.push(
|
|
1500
|
-
styleReactive = styleReactive || h.reactive;
|
|
1839
|
+
styleEntries.push(entry(a.name, h));
|
|
1501
1840
|
styleAt ??= h.at;
|
|
1502
1841
|
break;
|
|
1503
1842
|
}
|
|
@@ -1517,18 +1856,19 @@ var init_template = __esm({
|
|
|
1517
1856
|
name: "classList",
|
|
1518
1857
|
kind: "attr",
|
|
1519
1858
|
expr: `{ ${classEntries.join(", ")} }`,
|
|
1520
|
-
reactive:
|
|
1859
|
+
reactive: !element && anyReactive,
|
|
1521
1860
|
...classAt ? { at: classAt } : {}
|
|
1522
1861
|
});
|
|
1523
1862
|
}
|
|
1524
1863
|
if (styleEntries.length > 0) {
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1864
|
+
const entries = `{ ${styleEntries.join(", ")} }`;
|
|
1865
|
+
const base = props.findIndex((p) => p.name === "style");
|
|
1866
|
+
if (base === -1) props.push({ name: "style", kind: "attr", expr: entries, reactive: !element && anyReactive, ...styleAt ? { at: styleAt } : {} });
|
|
1867
|
+
else {
|
|
1868
|
+
const prop = props[base];
|
|
1869
|
+
const value = prop.expr === void 0 ? JSON.stringify(prop.literal) : prop.reactive ? `() => ${paren(prop.expr, "arrowBody")}` : prop.expr;
|
|
1870
|
+
props[base] = { name: "style", kind: "attr", expr: `[${value}, ${entries}]`, reactive: false, ...prop.at ? { at: prop.at } : {} };
|
|
1871
|
+
}
|
|
1532
1872
|
}
|
|
1533
1873
|
if (usePairs.length > 0) {
|
|
1534
1874
|
props.push({ name: "use", kind: "attr", expr: `[${usePairs.join(", ")}]` });
|
|
@@ -1617,7 +1957,7 @@ var init_template = __esm({
|
|
|
1617
1957
|
return base;
|
|
1618
1958
|
}
|
|
1619
1959
|
if (v.kind === "static") {
|
|
1620
|
-
base.literal = v.value;
|
|
1960
|
+
base.literal = decodeEntities(v.value);
|
|
1621
1961
|
return base;
|
|
1622
1962
|
}
|
|
1623
1963
|
if (v.kind === "hole") {
|
|
@@ -1630,7 +1970,7 @@ var init_template = __esm({
|
|
|
1630
1970
|
let reactive = false;
|
|
1631
1971
|
let at;
|
|
1632
1972
|
const body = v.parts.map((p) => {
|
|
1633
|
-
if ("text" in p) return escapeTemplate(p.text);
|
|
1973
|
+
if ("text" in p) return escapeTemplate(decodeEntities(p.text));
|
|
1634
1974
|
const h = this.hole(p.hole);
|
|
1635
1975
|
reactive = reactive || h.reactive;
|
|
1636
1976
|
at ??= h.at;
|
|
@@ -1855,6 +2195,21 @@ var init_expr_shape = __esm({
|
|
|
1855
2195
|
});
|
|
1856
2196
|
|
|
1857
2197
|
// src/lower/jsx.ts
|
|
2198
|
+
function directive(node, name) {
|
|
2199
|
+
if (node.type !== "JSXElement") return void 0;
|
|
2200
|
+
const opening = node.openingElement;
|
|
2201
|
+
if (opening.name.type !== "JSXIdentifier" || opening.name.name[0] !== opening.name.name[0].toLowerCase()) return void 0;
|
|
2202
|
+
return opening.attributes.find((a) => a.type === "JSXAttribute" && a.name.type === "JSXIdentifier" && a.name.name === name);
|
|
2203
|
+
}
|
|
2204
|
+
function directiveExpr(attr) {
|
|
2205
|
+
const v = attr.value;
|
|
2206
|
+
return v?.type === "JSXExpressionContainer" && v.expression?.type !== "JSXEmptyExpression" ? v.expression : void 0;
|
|
2207
|
+
}
|
|
2208
|
+
function emitIR(ir, ctx) {
|
|
2209
|
+
const { code, imports, templates } = imperativeBackend.emit(ir, {});
|
|
2210
|
+
for (const s of imports) ctx.used.add(s);
|
|
2211
|
+
return inlineTemplates(code, templates);
|
|
2212
|
+
}
|
|
1858
2213
|
function literalOf(node) {
|
|
1859
2214
|
if (node.type === "StringLiteral" || node.type === "NumericLiteral" || node.type === "BooleanLiteral") {
|
|
1860
2215
|
return node.value;
|
|
@@ -1926,9 +2281,12 @@ function attrExprCode(attr, ctx) {
|
|
|
1926
2281
|
}
|
|
1927
2282
|
return null;
|
|
1928
2283
|
}
|
|
1929
|
-
function buildProps(attrs, ctx) {
|
|
2284
|
+
function buildProps(attrs, ctx, element = false) {
|
|
1930
2285
|
const props = [];
|
|
1931
2286
|
const usePairs = [];
|
|
2287
|
+
const classEntries = [];
|
|
2288
|
+
const styleEntries = [];
|
|
2289
|
+
let styleAt;
|
|
1932
2290
|
for (const a of attrs) {
|
|
1933
2291
|
if (a.type === "JSXSpreadAttribute") {
|
|
1934
2292
|
props.push({ name: "", kind: "spread", expr: ctx.code(a.argument) });
|
|
@@ -1944,6 +2302,27 @@ function buildProps(attrs, ctx) {
|
|
|
1944
2302
|
usePairs.push(opts != null ? `[${dir}, () => ${paren(opts, "arrowBody")}]` : `[${dir}]`);
|
|
1945
2303
|
continue;
|
|
1946
2304
|
}
|
|
2305
|
+
if (element && (ns === "class" || ns === "style")) {
|
|
2306
|
+
const key = JSON.stringify(a.name.name.name);
|
|
2307
|
+
const v = a.value;
|
|
2308
|
+
let value;
|
|
2309
|
+
if (v == null) value = "true";
|
|
2310
|
+
else if (isString(v)) value = JSON.stringify(literalOf(v));
|
|
2311
|
+
else if (v.type === "JSXExpressionContainer" && v.expression?.type !== "JSXEmptyExpression") {
|
|
2312
|
+
value = keyValue(v.expression, ctx);
|
|
2313
|
+
if (ns === "style") styleAt ??= posOf(v.expression, ctx);
|
|
2314
|
+
} else continue;
|
|
2315
|
+
(ns === "class" ? classEntries : styleEntries).push(`${key}: ${value}`);
|
|
2316
|
+
continue;
|
|
2317
|
+
}
|
|
2318
|
+
if (element && a.name.type === "JSXIdentifier" && a.name.name === "style" && a.value?.type === "JSXExpressionContainer") {
|
|
2319
|
+
const entries = objectEntries(a.value.expression, ctx);
|
|
2320
|
+
if (entries) {
|
|
2321
|
+
styleEntries.unshift(...entries);
|
|
2322
|
+
styleAt = posOf(a.value.expression, ctx);
|
|
2323
|
+
continue;
|
|
2324
|
+
}
|
|
2325
|
+
}
|
|
1947
2326
|
if (ns === "oncapture") {
|
|
1948
2327
|
const evt = a.name.name.name.toLowerCase();
|
|
1949
2328
|
const h = attrExprCode(a, ctx) ?? "undefined";
|
|
@@ -1952,12 +2331,49 @@ function buildProps(attrs, ctx) {
|
|
|
1952
2331
|
}
|
|
1953
2332
|
props.push(buildAttr(a, ctx));
|
|
1954
2333
|
}
|
|
2334
|
+
if (classEntries.length > 0) props.push({ name: "classList", kind: "attr", expr: `{ ${classEntries.join(", ")} }`, reactive: false });
|
|
2335
|
+
if (styleEntries.length > 0) {
|
|
2336
|
+
const entries = `{ ${styleEntries.join(", ")} }`;
|
|
2337
|
+
const base = props.findIndex((p) => p.name === "style" && p.kind === "attr");
|
|
2338
|
+
if (base === -1) props.push({ name: "style", kind: "attr", expr: entries, reactive: false, ...styleAt ? { at: styleAt } : {} });
|
|
2339
|
+
else {
|
|
2340
|
+
const prop = props[base];
|
|
2341
|
+
const value = prop.literal !== void 0 ? JSON.stringify(prop.literal) : prop.reactive ? `() => ${paren(prop.expr, "arrowBody")}` : prop.expr;
|
|
2342
|
+
props[base] = { name: "style", kind: "attr", expr: `[${value}, ${entries}]`, reactive: false, ...prop.at ? { at: prop.at } : {} };
|
|
2343
|
+
}
|
|
2344
|
+
}
|
|
1955
2345
|
if (usePairs.length > 0) props.push({ name: "use", kind: "attr", expr: `[${usePairs.join(", ")}]` });
|
|
1956
2346
|
return props;
|
|
1957
2347
|
}
|
|
2348
|
+
function keyValue(expr, ctx) {
|
|
2349
|
+
const code = ctx.code(expr);
|
|
2350
|
+
if (!isReactive(expr)) return code;
|
|
2351
|
+
const accessor = `() => ${paren(code, "arrowBody")}`;
|
|
2352
|
+
const at = posOf(expr, ctx);
|
|
2353
|
+
return at ? markHole(accessor, at.line, at.column) : accessor;
|
|
2354
|
+
}
|
|
2355
|
+
function objectEntries(expr, ctx) {
|
|
2356
|
+
if (expr?.type !== "ObjectExpression") return null;
|
|
2357
|
+
const entries = [];
|
|
2358
|
+
for (const p of expr.properties) {
|
|
2359
|
+
if (p.type !== "ObjectProperty") return null;
|
|
2360
|
+
const key = p.computed ? `[${ctx.code(p.key)}]` : p.key.type === "Identifier" ? JSON.stringify(p.key.name) : JSON.stringify(String(p.key.value));
|
|
2361
|
+
entries.push(`${key}: ${keyValue(p.value, ctx)}`);
|
|
2362
|
+
}
|
|
2363
|
+
return entries;
|
|
2364
|
+
}
|
|
1958
2365
|
function buildChildren(children, ctx) {
|
|
1959
2366
|
const out = [];
|
|
1960
|
-
for (
|
|
2367
|
+
for (let i = 0; i < children.length; i++) {
|
|
2368
|
+
const child = children[i];
|
|
2369
|
+
if (directive(child, "if")) {
|
|
2370
|
+
let next = i + 1;
|
|
2371
|
+
while (next < children.length && children[next].type === "JSXText" && !cleanTemplateText(children[next].value)) next++;
|
|
2372
|
+
const fallback = directive(children[next], "else") ? children[next] : null;
|
|
2373
|
+
out.push(buildIf(child, fallback, ctx));
|
|
2374
|
+
if (fallback) i = next;
|
|
2375
|
+
continue;
|
|
2376
|
+
}
|
|
1961
2377
|
if (child.type === "JSXText") {
|
|
1962
2378
|
const text = cleanTemplateText(child.value);
|
|
1963
2379
|
if (text) out.push({ kind: "text", value: text });
|
|
@@ -1973,6 +2389,7 @@ function buildChildren(children, ctx) {
|
|
|
1973
2389
|
});
|
|
1974
2390
|
}
|
|
1975
2391
|
} else if (child.type === "JSXElement" || child.type === "JSXFragment") {
|
|
2392
|
+
if (ctx.dropStyles?.has(child.start)) continue;
|
|
1976
2393
|
out.push(buildNode(child, ctx));
|
|
1977
2394
|
} else if (child.type === "JSXSpreadChild") {
|
|
1978
2395
|
out.push({ kind: "expr", code: ctx.code(child.expression), reactive: false });
|
|
@@ -1994,26 +2411,79 @@ function readLoad(attrs) {
|
|
|
1994
2411
|
}
|
|
1995
2412
|
return void 0;
|
|
1996
2413
|
}
|
|
2414
|
+
function buildIf(node, fallback, ctx) {
|
|
2415
|
+
const cond = directiveExpr(directive(node, "if"));
|
|
2416
|
+
const props = [
|
|
2417
|
+
cond ? { name: "when", kind: "attr", expr: ctx.code(cond), reactive: isReactive(cond), at: posOf(cond, ctx) } : { name: "when", kind: "attr", literal: true }
|
|
2418
|
+
];
|
|
2419
|
+
if (fallback) {
|
|
2420
|
+
props.push({ name: "fallback", kind: "attr", expr: emitIR(buildElement(fallback, ctx, ["else"]), ctx), jsxElement: true });
|
|
2421
|
+
}
|
|
2422
|
+
return { kind: "component", name: "Show", props, children: [buildElement(node, ctx, ["if"])] };
|
|
2423
|
+
}
|
|
2424
|
+
function buildEach(node, ctx) {
|
|
2425
|
+
const attr = directive(node, "each");
|
|
2426
|
+
if (!attr) return null;
|
|
2427
|
+
const list = directiveExpr(attr);
|
|
2428
|
+
const props = [
|
|
2429
|
+
list ? { name: "each", kind: "attr", expr: ctx.code(list), reactive: isReactive(list), at: posOf(list, ctx) } : { name: "each", kind: "attr", expr: "[]" }
|
|
2430
|
+
];
|
|
2431
|
+
const key = directive(node, "key");
|
|
2432
|
+
if (key) {
|
|
2433
|
+
const keyExpr = directiveExpr(key);
|
|
2434
|
+
const by = isString(key.value) ? `(item) => item[${JSON.stringify(literalOf(key.value))}]` : keyExpr ? ctx.code(keyExpr) : void 0;
|
|
2435
|
+
if (by) props.push({ name: "by", kind: "attr", expr: by });
|
|
2436
|
+
}
|
|
2437
|
+
const content = node.children.filter((c) => !(c.type === "JSXText" && !cleanTemplateText(c.value)));
|
|
2438
|
+
const only = content.length === 1 && content[0].type === "JSXExpressionContainer" ? content[0].expression : null;
|
|
2439
|
+
let render;
|
|
2440
|
+
if (only && (only.type === "ArrowFunctionExpression" || only.type === "FunctionExpression")) {
|
|
2441
|
+
const fn = ctx.code(only);
|
|
2442
|
+
const live = only.type === "ArrowFunctionExpression" && only.body.type !== "BlockStatement" && isReactive(only.body);
|
|
2443
|
+
render = live ? `(...args) => () => (${fn})(...args)` : fn;
|
|
2444
|
+
} else {
|
|
2445
|
+
const built = buildChildren(node.children, ctx);
|
|
2446
|
+
const ir = built.length === 1 ? built[0] : { kind: "fragment", children: built };
|
|
2447
|
+
render = `() => ${paren(emitIR(ir, ctx), "arrowBody")}`;
|
|
2448
|
+
}
|
|
2449
|
+
return { kind: "component", name: "For", props, children: [{ kind: "expr", code: render, reactive: false }] };
|
|
2450
|
+
}
|
|
2451
|
+
function buildElement(node, ctx, handled) {
|
|
2452
|
+
const skip = new Set(handled);
|
|
2453
|
+
const directives = /* @__PURE__ */ new Set(["if", "else", "each", ...directive(node, "each") ? ["key"] : []]);
|
|
2454
|
+
const attributes = node.openingElement.attributes.filter(
|
|
2455
|
+
(a) => !(a.type === "JSXAttribute" && a.name.type === "JSXIdentifier" && (skip.has(a.name.name) || directives.has(a.name.name)))
|
|
2456
|
+
);
|
|
2457
|
+
const { tag } = tagInfo(node.openingElement.name, ctx);
|
|
2458
|
+
const each = buildEach(node, ctx);
|
|
2459
|
+
const children = each ? [each] : buildChildren(node.children, ctx);
|
|
2460
|
+
if (tag === CONTAINER2) return children.length === 1 ? children[0] : { kind: "fragment", children };
|
|
2461
|
+
const at = ctx.sourceFile && node.loc?.start ? { file: ctx.sourceFile, line: node.loc.start.line, column: node.loc.start.column } : void 0;
|
|
2462
|
+
const props = buildProps(attributes, ctx, true);
|
|
2463
|
+
const scope = ctx.scopes?.find((s) => node.start >= s.start && node.end <= s.end);
|
|
2464
|
+
if (scope) props.unshift({ name: "data-fx-s", kind: "attr", literal: scope.value });
|
|
2465
|
+
return { kind: "element", tag, svg: SVG_TAGS.has(tag), props, children, static: false, ...at ? { at } : {} };
|
|
2466
|
+
}
|
|
1997
2467
|
function buildNode(node, ctx) {
|
|
1998
2468
|
if (node.type === "JSXFragment") {
|
|
1999
2469
|
return { kind: "fragment", children: buildChildren(node.children, ctx) };
|
|
2000
2470
|
}
|
|
2471
|
+
if (directive(node, "if")) return buildIf(node, null, ctx);
|
|
2472
|
+
if (ctx.dropStyles?.has(node.start)) return { kind: "fragment", children: [] };
|
|
2001
2473
|
const { tag, component } = tagInfo(node.openingElement.name, ctx);
|
|
2474
|
+
if (!component) return buildElement(node, ctx, []);
|
|
2002
2475
|
const props = buildProps(node.openingElement.attributes, ctx);
|
|
2003
2476
|
const children = buildChildren(node.children, ctx);
|
|
2004
2477
|
const at = ctx.sourceFile && node.loc?.start ? { file: ctx.sourceFile, line: node.loc.start.line, column: node.loc.start.column } : void 0;
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
return { kind: "component", name: tag, props, children, ...load ? { load } : {}, ...at ? { at } : {} };
|
|
2008
|
-
}
|
|
2009
|
-
return { kind: "element", tag, svg: SVG_TAGS.has(tag), props, children, static: false, ...at ? { at } : {} };
|
|
2478
|
+
const load = readLoad(node.openingElement.attributes);
|
|
2479
|
+
return { kind: "component", name: tag, props, children, ...load ? { load } : {}, ...at ? { at } : {} };
|
|
2010
2480
|
}
|
|
2011
2481
|
function buildJsxIR(node, ctx) {
|
|
2012
2482
|
const ir = buildNode(node, ctx);
|
|
2013
2483
|
analyzeStatic(ir);
|
|
2014
2484
|
return ir;
|
|
2015
2485
|
}
|
|
2016
|
-
var SVG_TAGS, EVENT_RE, DELEGATED2, isReactive, posOf, isString;
|
|
2486
|
+
var SVG_TAGS, EVENT_RE, DELEGATED2, isReactive, CONTAINER2, posOf, isString;
|
|
2017
2487
|
var init_jsx = __esm({
|
|
2018
2488
|
"src/lower/jsx.ts"() {
|
|
2019
2489
|
"use strict";
|
|
@@ -2023,6 +2493,8 @@ var init_jsx = __esm({
|
|
|
2023
2493
|
init_analyze_static();
|
|
2024
2494
|
init_text();
|
|
2025
2495
|
init_paren();
|
|
2496
|
+
init_source_locations();
|
|
2497
|
+
init_imperative();
|
|
2026
2498
|
SVG_TAGS = /* @__PURE__ */ new Set([
|
|
2027
2499
|
"svg",
|
|
2028
2500
|
"path",
|
|
@@ -2053,6 +2525,7 @@ var init_jsx = __esm({
|
|
|
2053
2525
|
"mouseup"
|
|
2054
2526
|
]);
|
|
2055
2527
|
isReactive = (node) => isReactiveShape(shapeOf(node));
|
|
2528
|
+
CONTAINER2 = "container";
|
|
2056
2529
|
posOf = (node, ctx) => {
|
|
2057
2530
|
if (!ctx.sourceFile) return void 0;
|
|
2058
2531
|
const at = node.loc?.start;
|
|
@@ -2669,6 +3142,569 @@ var init_babel = __esm({
|
|
|
2669
3142
|
}
|
|
2670
3143
|
});
|
|
2671
3144
|
|
|
3145
|
+
// src/transform/styles.ts
|
|
3146
|
+
function collectStyles(program, sourceName, options, tags = { html: /* @__PURE__ */ new Map([["html", "html"]]) }, module2) {
|
|
3147
|
+
const plan = {
|
|
3148
|
+
scopes: [],
|
|
3149
|
+
templateOwners: /* @__PURE__ */ new Map(),
|
|
3150
|
+
drop: /* @__PURE__ */ new Set(),
|
|
3151
|
+
styles: [],
|
|
3152
|
+
diagnostics: [],
|
|
3153
|
+
edits: [],
|
|
3154
|
+
literals: [],
|
|
3155
|
+
references: [],
|
|
3156
|
+
shadowClasses: /* @__PURE__ */ new Map()
|
|
3157
|
+
};
|
|
3158
|
+
if (!options) return plan;
|
|
3159
|
+
const literalsOf = findLiterals(program, options.cssModules ?? ["@fluixi/core", "@fluixi/dom"], plan, tags.css ?? []);
|
|
3160
|
+
plan.names = literalsOf;
|
|
3161
|
+
const classOf = /* @__PURE__ */ new Map();
|
|
3162
|
+
const shadowOf = (owner) => {
|
|
3163
|
+
const cls = classOf.get(owner);
|
|
3164
|
+
return cls ? plan.shadowClasses.get(cls) : void 0;
|
|
3165
|
+
};
|
|
3166
|
+
const resolved = /* @__PURE__ */ new Map();
|
|
3167
|
+
const piecesToNodes = (quasis, expressions, at, stack) => {
|
|
3168
|
+
const out = [];
|
|
3169
|
+
for (let i = 0; i < quasis.length; i++) {
|
|
3170
|
+
const text = quasis[i].value.cooked ?? quasis[i].value.raw;
|
|
3171
|
+
if (text.trim()) {
|
|
3172
|
+
try {
|
|
3173
|
+
const start = quasis[i].loc?.start;
|
|
3174
|
+
out.push(...options.process(text, sourceName).map((n) => start ? shiftLoc(n, sourceName, start) : n));
|
|
3175
|
+
} catch (error) {
|
|
3176
|
+
plan.diagnostics.push({ ...at, message: `CSS could not be processed: ${error.message}` });
|
|
3177
|
+
return null;
|
|
3178
|
+
}
|
|
3179
|
+
}
|
|
3180
|
+
const expr = expressions[i];
|
|
3181
|
+
if (!expr) continue;
|
|
3182
|
+
const value = expr.type === "Identifier" ? resolveLiteral(expr.name, at, stack) : void 0;
|
|
3183
|
+
if (value === void 0) {
|
|
3184
|
+
plan.diagnostics.push({
|
|
3185
|
+
...at,
|
|
3186
|
+
message: "Only css`` values can be interpolated into styles, and only by name: ${base}. Dynamic values go through custom properties (style:--x={...} and var(--x))."
|
|
3187
|
+
});
|
|
3188
|
+
return null;
|
|
3189
|
+
}
|
|
3190
|
+
if (value === null) return null;
|
|
3191
|
+
out.push(...value);
|
|
3192
|
+
}
|
|
3193
|
+
return out;
|
|
3194
|
+
};
|
|
3195
|
+
function resolveLiteral(name, at, stack) {
|
|
3196
|
+
const imported = literalsOf.imports.get(name);
|
|
3197
|
+
if (imported) {
|
|
3198
|
+
const nodes = options?.imported?.get(`${imported.source}#${imported.name}`);
|
|
3199
|
+
if (nodes) return nodes.map(dropLoc);
|
|
3200
|
+
plan.references.push({ name: imported.name, source: imported.source, ...at });
|
|
3201
|
+
plan.diagnostics.push({
|
|
3202
|
+
...at,
|
|
3203
|
+
message: options?.imported ? `${name} from ${imported.source} is not a css\`\` value the build could find.` : `${name} comes from ${imported.source}: style values from another module are resolved by the build.`
|
|
3204
|
+
});
|
|
3205
|
+
return null;
|
|
3206
|
+
}
|
|
3207
|
+
const literal = literalsOf.literals.get(name);
|
|
3208
|
+
if (!literal) return void 0;
|
|
3209
|
+
if (stack.includes(name)) {
|
|
3210
|
+
plan.diagnostics.push({ ...at, message: `css\`\` values include each other: ${[...stack, name].join(" → ")}.` });
|
|
3211
|
+
return null;
|
|
3212
|
+
}
|
|
3213
|
+
if (!resolved.has(name)) {
|
|
3214
|
+
resolved.set(name, piecesToNodes(literal.quasi.quasis, literal.quasi.expressions, at, [...stack, name]));
|
|
3215
|
+
}
|
|
3216
|
+
return resolved.get(name);
|
|
3217
|
+
}
|
|
3218
|
+
for (const [name, literal] of literalsOf.literals) {
|
|
3219
|
+
const at = { line: literal.loc?.start.line ?? 0, column: literal.loc?.start.column ?? 0 };
|
|
3220
|
+
const nodes = resolveLiteral(name, at, []);
|
|
3221
|
+
const id = hash(`${sourceName}:css:${name}`);
|
|
3222
|
+
plan.edits.push({ start: literal.start, end: literal.end, code: `({ $fxStyle: ${JSON.stringify(id)} })` });
|
|
3223
|
+
if (nodes) plan.literals.push({ id, name, css: printStyle(nodes, options.minify) });
|
|
3224
|
+
}
|
|
3225
|
+
const scopeOf = /* @__PURE__ */ new Map();
|
|
3226
|
+
const names = /* @__PURE__ */ new Map();
|
|
3227
|
+
const named = /* @__PURE__ */ new Map();
|
|
3228
|
+
const visit = (node, owners) => {
|
|
3229
|
+
if (!node || typeof node !== "object") return;
|
|
3230
|
+
if (node.type === "VariableDeclarator" && node.id.type === "Identifier" && node.init && FUNCTIONS.has(node.init.type)) {
|
|
3231
|
+
named.set(node.init, node.id.name);
|
|
3232
|
+
}
|
|
3233
|
+
if ((node.type === "ClassDeclaration" || node.type === "ClassExpression") && node.id) {
|
|
3234
|
+
for (const member of node.body.body) if (member.type === "ClassMethod") named.set(member, node.id.name);
|
|
3235
|
+
}
|
|
3236
|
+
if (node.type === "ClassDeclaration" || node.type === "ClassExpression") {
|
|
3237
|
+
for (const member of node.body.body) if (member.type === "ClassMethod") classOf.set(member, node);
|
|
3238
|
+
const shadow = staticMember(node, "shadow");
|
|
3239
|
+
if (shadow?.value && !(shadow.value.type === "BooleanLiteral" && shadow.value.value === false)) {
|
|
3240
|
+
plan.shadowClasses.set(node, { node, styles: staticMember(node, "styles"), indexes: [] });
|
|
3241
|
+
}
|
|
3242
|
+
}
|
|
3243
|
+
if (node.type === "TaggedTemplateExpression" && node.tag.type === "Identifier" && tags.html.get(node.tag.name) === "html") {
|
|
3244
|
+
const text = node.quasi.quasis.map((q) => q.value.raw).join("");
|
|
3245
|
+
if (/<style[\s>]/.test(text)) {
|
|
3246
|
+
const at = { line: node.loc?.start.line ?? 0, column: node.loc?.start.column ?? 0 };
|
|
3247
|
+
const owner = owners[0];
|
|
3248
|
+
if (!owner) plan.diagnostics.push({ ...at, message: "<style> has to be written inside a component." });
|
|
3249
|
+
else {
|
|
3250
|
+
const id = idFor(owner);
|
|
3251
|
+
const shadow = shadowOf(owner);
|
|
3252
|
+
plan.templateOwners.set(node.start, { id, component: functionName(owner, named) });
|
|
3253
|
+
for (const block of templateBlocks(node.quasi)) compileBlock(block, block.scoped, owner, at);
|
|
3254
|
+
}
|
|
3255
|
+
}
|
|
3256
|
+
}
|
|
3257
|
+
const inner = FUNCTIONS.has(node.type) ? [...owners, node] : owners;
|
|
3258
|
+
if (node.type === "JSXElement" && isStyle(node)) {
|
|
3259
|
+
handle(node, owners);
|
|
3260
|
+
return;
|
|
3261
|
+
}
|
|
3262
|
+
for (const key of Object.keys(node)) {
|
|
3263
|
+
if (key === "loc" || key === "leadingComments" || key === "trailingComments" || key === "innerComments") continue;
|
|
3264
|
+
const value = node[key];
|
|
3265
|
+
if (Array.isArray(value)) for (const v of value) visit(v, inner);
|
|
3266
|
+
else if (value && typeof value === "object" && "type" in value) visit(value, inner);
|
|
3267
|
+
}
|
|
3268
|
+
};
|
|
3269
|
+
const handle = (node, owners) => {
|
|
3270
|
+
const at = { line: node.loc?.start.line ?? 0, column: node.loc?.start.column ?? 0 };
|
|
3271
|
+
const pieces = blockPieces(node);
|
|
3272
|
+
if (pieces === null) {
|
|
3273
|
+
plan.diagnostics.push({
|
|
3274
|
+
...at,
|
|
3275
|
+
message: "<style> needs its CSS as one template literal, <style>{`...`}</style>: JSX reads a bare `{` as an expression."
|
|
3276
|
+
});
|
|
3277
|
+
return;
|
|
3278
|
+
}
|
|
3279
|
+
const owner = owners[0];
|
|
3280
|
+
if (!owner) {
|
|
3281
|
+
plan.diagnostics.push({ ...at, message: "<style> has to be written inside a component." });
|
|
3282
|
+
return;
|
|
3283
|
+
}
|
|
3284
|
+
compileBlock(pieces, isScoped(node), owner, at);
|
|
3285
|
+
plan.drop.add(node.start);
|
|
3286
|
+
};
|
|
3287
|
+
const compileBlock = (pieces, scoped, owner, at) => {
|
|
3288
|
+
const component = functionName(owner, named);
|
|
3289
|
+
const id = idFor(owner);
|
|
3290
|
+
const processed = piecesToNodes(pieces.quasis, pieces.expressions, at, []);
|
|
3291
|
+
if (!processed) return;
|
|
3292
|
+
let nodes = processed;
|
|
3293
|
+
const shadow = shadowOf(owner);
|
|
3294
|
+
if (scoped && !shadow) {
|
|
3295
|
+
if (!plan.scopes.some((s) => s.value === id)) plan.scopes.push({ start: owner.start, end: owner.end, value: id });
|
|
3296
|
+
nodes = scopeNodes(nodes, id, (message) => plan.diagnostics.push({ ...at, message }));
|
|
3297
|
+
}
|
|
3298
|
+
const printed = module2 ? printStyleWithMap(nodes, options.minify, sourceName, module2) : { css: printStyle(nodes, options.minify) };
|
|
3299
|
+
plan.styles.push({ id, scoped: scoped && !shadow, component, ...printed, ...shadow ? { shadow: true } : {}, ...at });
|
|
3300
|
+
if (shadow) shadow.indexes.push(plan.styles.length - 1);
|
|
3301
|
+
};
|
|
3302
|
+
function idFor(owner) {
|
|
3303
|
+
let id = scopeOf.get(owner);
|
|
3304
|
+
if (!id) {
|
|
3305
|
+
const component = functionName(owner, named);
|
|
3306
|
+
const seen = names.get(component) ?? 0;
|
|
3307
|
+
names.set(component, seen + 1);
|
|
3308
|
+
id = hash(`${sourceName}:${component}${seen ? ":" + seen : ""}`);
|
|
3309
|
+
scopeOf.set(owner, id);
|
|
3310
|
+
}
|
|
3311
|
+
return id;
|
|
3312
|
+
}
|
|
3313
|
+
visit(program, []);
|
|
3314
|
+
return plan;
|
|
3315
|
+
}
|
|
3316
|
+
function applyTemplateStyles(ir, t4) {
|
|
3317
|
+
const walk8 = (node) => {
|
|
3318
|
+
const children = node.children;
|
|
3319
|
+
if (children) {
|
|
3320
|
+
for (let i = children.length - 1; i >= 0; i--) {
|
|
3321
|
+
const child = children[i];
|
|
3322
|
+
if (child.kind === "element" && child.tag === "style" && t4.owner) children.splice(i, 1);
|
|
3323
|
+
else walk8(child);
|
|
3324
|
+
}
|
|
3325
|
+
}
|
|
3326
|
+
if (t4.scope && node.kind === "element" && node.tag !== "style" && node.props && !node.props.some((p) => p.name === SCOPE_ATTR)) {
|
|
3327
|
+
node.props.unshift({ name: SCOPE_ATTR, kind: "attr", literal: t4.scope });
|
|
3328
|
+
}
|
|
3329
|
+
};
|
|
3330
|
+
walk8(ir);
|
|
3331
|
+
}
|
|
3332
|
+
function staticMember(cls, name) {
|
|
3333
|
+
return cls.body.body.find(
|
|
3334
|
+
(m) => m.type === "ClassProperty" && m.static && (m.key.type === "Identifier" && m.key.name === name || m.key.type === "StringLiteral" && m.key.value === name)
|
|
3335
|
+
);
|
|
3336
|
+
}
|
|
3337
|
+
function finishShadowStyles(plan, code, moduleId) {
|
|
3338
|
+
const edits = [];
|
|
3339
|
+
const imports = [];
|
|
3340
|
+
let next = 0;
|
|
3341
|
+
const importOf = (specifier) => {
|
|
3342
|
+
const local = `__fxShadow${next++}`;
|
|
3343
|
+
imports.push(`import ${local} from ${JSON.stringify(specifier)};
|
|
3344
|
+
`);
|
|
3345
|
+
return local;
|
|
3346
|
+
};
|
|
3347
|
+
for (const shadow of plan.shadowClasses.values()) {
|
|
3348
|
+
const blocks = shadow.indexes.map((i) => importOf(`${moduleId}?fx-style&index=${i}&inline&lang.css`));
|
|
3349
|
+
let value;
|
|
3350
|
+
const prop = shadow.styles;
|
|
3351
|
+
if (prop?.value) {
|
|
3352
|
+
const start = prop.value.start;
|
|
3353
|
+
let text = code.slice(start, prop.value.end);
|
|
3354
|
+
const replacements = [];
|
|
3355
|
+
walkIdentifiers(prop.value, (id) => {
|
|
3356
|
+
const local = plan.names?.literals.has(id.name) ? importOf(`${moduleId}?fx-literal=${id.name}&inline&lang.css`) : plan.names?.imports.has(id.name) && !/\.css(\?|$)/.test(plan.names.imports.get(id.name).source) ? importOf(`${plan.names.imports.get(id.name).source}?fx-literal=${plan.names.imports.get(id.name).name}&inline&lang.css`) : void 0;
|
|
3357
|
+
if (local) replacements.push({ at: id.start - start, length: id.name.length, with: local });
|
|
3358
|
+
});
|
|
3359
|
+
for (const r of replacements.sort((a, b) => b.at - a.at)) text = text.slice(0, r.at) + r.with + text.slice(r.at + r.length);
|
|
3360
|
+
value = text;
|
|
3361
|
+
}
|
|
3362
|
+
if (!blocks.length && value === void 0) continue;
|
|
3363
|
+
if (prop?.value) {
|
|
3364
|
+
const merged = blocks.length ? `[${value}, ${blocks.join(", ")}]` : value;
|
|
3365
|
+
edits.push({ start: prop.value.start, end: prop.value.end, code: merged });
|
|
3366
|
+
} else if (blocks.length) {
|
|
3367
|
+
const open = shadow.node.body.start + 1;
|
|
3368
|
+
edits.push({ start: open, end: open, code: ` static styles = [${blocks.join(", ")}];` });
|
|
3369
|
+
}
|
|
3370
|
+
}
|
|
3371
|
+
if (imports.length) edits.push({ start: 0, end: 0, code: imports.join("") });
|
|
3372
|
+
return edits;
|
|
3373
|
+
}
|
|
3374
|
+
function walkIdentifiers(node, visit) {
|
|
3375
|
+
if (!node || typeof node !== "object") return;
|
|
3376
|
+
if (node.type === "Identifier") return visit(node);
|
|
3377
|
+
if (node.type === "MemberExpression") return walkIdentifiers(node.object, visit);
|
|
3378
|
+
if (node.type === "ObjectProperty") return walkIdentifiers(node.value, visit);
|
|
3379
|
+
for (const key of Object.keys(node)) {
|
|
3380
|
+
if (key === "loc") continue;
|
|
3381
|
+
const value = node[key];
|
|
3382
|
+
if (Array.isArray(value)) for (const v of value) walkIdentifiers(v, visit);
|
|
3383
|
+
else if (value && typeof value === "object" && "type" in value) walkIdentifiers(value, visit);
|
|
3384
|
+
}
|
|
3385
|
+
}
|
|
3386
|
+
function isStyle(node) {
|
|
3387
|
+
const name = node.openingElement.name;
|
|
3388
|
+
return name.type === "JSXIdentifier" && name.name === "style";
|
|
3389
|
+
}
|
|
3390
|
+
function isScoped(node) {
|
|
3391
|
+
return node.openingElement.attributes.some((a) => a.type === "JSXAttribute" && a.name.type === "JSXIdentifier" && a.name.name === "scoped");
|
|
3392
|
+
}
|
|
3393
|
+
function templateBlocks(quasi) {
|
|
3394
|
+
const blocks = [];
|
|
3395
|
+
let open = null;
|
|
3396
|
+
quasi.quasis.forEach((q, i) => {
|
|
3397
|
+
const raw = q.value.raw;
|
|
3398
|
+
let from = 0;
|
|
3399
|
+
while (from <= raw.length) {
|
|
3400
|
+
if (!open) {
|
|
3401
|
+
const tag = /<style\b([^>]*)>/g;
|
|
3402
|
+
tag.lastIndex = from;
|
|
3403
|
+
const m = tag.exec(raw);
|
|
3404
|
+
if (!m) break;
|
|
3405
|
+
open = { quasis: [], expressions: [], scoped: /\bscoped\b/.test(m[1]) };
|
|
3406
|
+
from = m.index + m[0].length;
|
|
3407
|
+
}
|
|
3408
|
+
const close = raw.indexOf("</style", from);
|
|
3409
|
+
open.quasis.push(slicePiece(q, raw, from, close === -1 ? raw.length : close));
|
|
3410
|
+
if (close === -1) break;
|
|
3411
|
+
blocks.push(open);
|
|
3412
|
+
open = null;
|
|
3413
|
+
from = close;
|
|
3414
|
+
}
|
|
3415
|
+
const expr = quasi.expressions[i];
|
|
3416
|
+
if (open && expr) open.expressions.push(expr);
|
|
3417
|
+
});
|
|
3418
|
+
return blocks;
|
|
3419
|
+
}
|
|
3420
|
+
function slicePiece(q, raw, from, to) {
|
|
3421
|
+
const text = raw.slice(from, to);
|
|
3422
|
+
const start = q.loc?.start;
|
|
3423
|
+
if (!start) return { type: "TemplateElement", value: { raw: text, cooked: text } };
|
|
3424
|
+
const before = raw.slice(0, from).split("\n");
|
|
3425
|
+
const line = start.line + before.length - 1;
|
|
3426
|
+
const column = before.length > 1 ? before[before.length - 1].length : start.column + from;
|
|
3427
|
+
return { type: "TemplateElement", value: { raw: text, cooked: text }, loc: { start: { line, column } } };
|
|
3428
|
+
}
|
|
3429
|
+
function blockPieces(node) {
|
|
3430
|
+
const meaningful = node.children.filter((c) => !(c.type === "JSXText" && !c.value.trim()));
|
|
3431
|
+
if (meaningful.length === 0) return { quasis: [], expressions: [] };
|
|
3432
|
+
if (meaningful.length !== 1) return null;
|
|
3433
|
+
const only = meaningful[0];
|
|
3434
|
+
if (only.type !== "JSXExpressionContainer") return null;
|
|
3435
|
+
const expr = only.expression;
|
|
3436
|
+
if (expr.type === "StringLiteral") return { quasis: [{ type: "TemplateElement", value: { raw: expr.value, cooked: expr.value } }], expressions: [] };
|
|
3437
|
+
if (expr.type === "TemplateLiteral") return { quasis: expr.quasis, expressions: expr.expressions };
|
|
3438
|
+
return null;
|
|
3439
|
+
}
|
|
3440
|
+
function findLiterals(program, modules, plan, intrinsic) {
|
|
3441
|
+
const literals = /* @__PURE__ */ new Map();
|
|
3442
|
+
const imports = /* @__PURE__ */ new Map();
|
|
3443
|
+
const tags = new Set(intrinsic);
|
|
3444
|
+
for (const statement of program.body ?? []) {
|
|
3445
|
+
if (statement.type !== "ImportDeclaration") continue;
|
|
3446
|
+
const source = statement.source.value;
|
|
3447
|
+
const specifiers = statement.specifiers;
|
|
3448
|
+
for (const sp of specifiers) {
|
|
3449
|
+
if (sp.type === "ImportSpecifier") imports.set(sp.local.name, { source, name: sp.imported.name ?? sp.imported.value });
|
|
3450
|
+
}
|
|
3451
|
+
if (!modules.includes(source)) continue;
|
|
3452
|
+
const css = specifiers.find((sp) => sp.type === "ImportSpecifier" && (sp.imported.name ?? sp.imported.value) === "css");
|
|
3453
|
+
if (!css) continue;
|
|
3454
|
+
const local = css.local.name;
|
|
3455
|
+
tags.add(local);
|
|
3456
|
+
imports.delete(local);
|
|
3457
|
+
plan.edits.push({ start: statement.start, end: statement.end, code: importWithout(statement, css) });
|
|
3458
|
+
}
|
|
3459
|
+
if (tags.size === 0) return { literals, imports };
|
|
3460
|
+
const visit = (node) => {
|
|
3461
|
+
if (!node || typeof node !== "object") return;
|
|
3462
|
+
if (node.type === "VariableDeclarator" && node.id.type === "Identifier" && node.init?.type === "TaggedTemplateExpression" && node.init.tag.type === "Identifier" && tags.has(node.init.tag.name)) {
|
|
3463
|
+
literals.set(node.id.name, node.init);
|
|
3464
|
+
}
|
|
3465
|
+
for (const key of Object.keys(node)) {
|
|
3466
|
+
if (key === "loc") continue;
|
|
3467
|
+
const value = node[key];
|
|
3468
|
+
if (Array.isArray(value)) for (const v of value) visit(v);
|
|
3469
|
+
else if (value && typeof value === "object" && "type" in value) visit(value);
|
|
3470
|
+
}
|
|
3471
|
+
};
|
|
3472
|
+
visit(program);
|
|
3473
|
+
return { literals, imports };
|
|
3474
|
+
}
|
|
3475
|
+
function importWithout(statement, removed) {
|
|
3476
|
+
const rest = statement.specifiers.filter((sp) => sp !== removed);
|
|
3477
|
+
const source = JSON.stringify(statement.source.value);
|
|
3478
|
+
if (rest.length === 0) return "";
|
|
3479
|
+
const def = rest.find((sp) => sp.type === "ImportDefaultSpecifier");
|
|
3480
|
+
const ns = rest.find((sp) => sp.type === "ImportNamespaceSpecifier");
|
|
3481
|
+
const named = rest.filter((sp) => sp.type === "ImportSpecifier").map((sp) => {
|
|
3482
|
+
const imported = sp.imported.name ?? JSON.stringify(sp.imported.value);
|
|
3483
|
+
return imported === sp.local.name ? imported : `${imported} as ${sp.local.name}`;
|
|
3484
|
+
});
|
|
3485
|
+
const parts = [def?.local.name, ns ? `* as ${ns.local.name}` : void 0, named.length ? `{ ${named.join(", ")} }` : void 0].filter(Boolean);
|
|
3486
|
+
return `import ${parts.join(", ")} from ${source};`;
|
|
3487
|
+
}
|
|
3488
|
+
function functionName(fn, named) {
|
|
3489
|
+
if ((fn.type === "FunctionDeclaration" || fn.type === "FunctionExpression") && fn.id) return fn.id.name;
|
|
3490
|
+
return named.get(fn) ?? "anonymous";
|
|
3491
|
+
}
|
|
3492
|
+
function hash(text) {
|
|
3493
|
+
let h = 2166136261;
|
|
3494
|
+
for (let i = 0; i < text.length; i++) {
|
|
3495
|
+
h ^= text.charCodeAt(i);
|
|
3496
|
+
h = Math.imul(h, 16777619);
|
|
3497
|
+
}
|
|
3498
|
+
return (h >>> 0).toString(36);
|
|
3499
|
+
}
|
|
3500
|
+
function scopeNodes(nodes, id, warn = () => {
|
|
3501
|
+
}) {
|
|
3502
|
+
return nodes.map((node) => {
|
|
3503
|
+
if (node.kind === "rule") return { ...node, selector: scopeSelector(node.selector, id, warn) };
|
|
3504
|
+
if (node.kind === "at-rule" && !OPAQUE.test(node.name)) return { ...node, nodes: scopeNodes(node.nodes, id, warn) };
|
|
3505
|
+
return node;
|
|
3506
|
+
});
|
|
3507
|
+
}
|
|
3508
|
+
function scopeSelector(selector, id, warn = () => {
|
|
3509
|
+
}) {
|
|
3510
|
+
return splitTop(selector, ",").map((complex) => scopeComplex(complex.trim(), `[${SCOPE_ATTR}="${id}"]`, warn)).join(", ");
|
|
3511
|
+
}
|
|
3512
|
+
function scopeComplex(selector, attr, warn) {
|
|
3513
|
+
if (/:host\b|::slotted\(/.test(selector)) {
|
|
3514
|
+
warn(`\`${selector}\` only means something in a shadow root; in a light-DOM component it is left as written.`);
|
|
3515
|
+
return selector;
|
|
3516
|
+
}
|
|
3517
|
+
const parts = compounds(selector);
|
|
3518
|
+
const deep = parts.findIndex((p) => p.text.startsWith(":deep("));
|
|
3519
|
+
if (deep !== -1) {
|
|
3520
|
+
const inner = unwrap(parts[deep].text, ":deep(");
|
|
3521
|
+
const before = parts.slice(0, deep);
|
|
3522
|
+
if (before.length === 0) return `${attr} ${inner}`;
|
|
3523
|
+
const scopedBefore = scopeAt(before, before.length - 1, attr);
|
|
3524
|
+
return `${join2(scopedBefore)} ${inner}`;
|
|
3525
|
+
}
|
|
3526
|
+
let target = -1;
|
|
3527
|
+
for (let i = parts.length - 1; i >= 0; i--) {
|
|
3528
|
+
if (!parts[i].text.startsWith(":global(")) {
|
|
3529
|
+
target = i;
|
|
3530
|
+
break;
|
|
3531
|
+
}
|
|
3532
|
+
}
|
|
3533
|
+
const out = target === -1 ? parts : scopeAt(parts, target, attr);
|
|
3534
|
+
return join2(out.map((p) => p.text.startsWith(":global(") ? { ...p, text: unwrap(p.text, ":global(") } : p));
|
|
3535
|
+
}
|
|
3536
|
+
function scopeAt(parts, index, attr) {
|
|
3537
|
+
return parts.map((p, i) => i === index ? { ...p, text: insertAttr(p.text, attr) } : p);
|
|
3538
|
+
}
|
|
3539
|
+
function insertAttr(compound, attr) {
|
|
3540
|
+
let depth = 0;
|
|
3541
|
+
let quote = "";
|
|
3542
|
+
for (let i = 0; i < compound.length; i++) {
|
|
3543
|
+
const c = compound[i];
|
|
3544
|
+
if (quote) {
|
|
3545
|
+
if (c === "\\") i++;
|
|
3546
|
+
else if (c === quote) quote = "";
|
|
3547
|
+
continue;
|
|
3548
|
+
}
|
|
3549
|
+
if (c === "\\") {
|
|
3550
|
+
i++;
|
|
3551
|
+
continue;
|
|
3552
|
+
}
|
|
3553
|
+
if (c === '"' || c === "'") quote = c;
|
|
3554
|
+
else if (c === "(" || c === "[") depth++;
|
|
3555
|
+
else if (c === ")" || c === "]") depth--;
|
|
3556
|
+
else if (c === ":" && depth === 0 && i > 0) return compound.slice(0, i) + attr + compound.slice(i);
|
|
3557
|
+
}
|
|
3558
|
+
return compound + attr;
|
|
3559
|
+
}
|
|
3560
|
+
function compounds(selector) {
|
|
3561
|
+
const out = [];
|
|
3562
|
+
let depth = 0;
|
|
3563
|
+
let quote = "";
|
|
3564
|
+
let current = "";
|
|
3565
|
+
let combinator = "";
|
|
3566
|
+
const push = () => {
|
|
3567
|
+
if (current.trim()) out.push({ combinator: out.length ? combinator || " " : "", text: current.trim() });
|
|
3568
|
+
current = "";
|
|
3569
|
+
combinator = "";
|
|
3570
|
+
};
|
|
3571
|
+
for (let i = 0; i < selector.length; i++) {
|
|
3572
|
+
const c = selector[i];
|
|
3573
|
+
if (quote) {
|
|
3574
|
+
current += c;
|
|
3575
|
+
if (c === "\\") current += selector[++i] ?? "";
|
|
3576
|
+
else if (c === quote) quote = "";
|
|
3577
|
+
continue;
|
|
3578
|
+
}
|
|
3579
|
+
if (c === "\\") {
|
|
3580
|
+
current += c + (selector[++i] ?? "");
|
|
3581
|
+
continue;
|
|
3582
|
+
}
|
|
3583
|
+
if (c === '"' || c === "'") quote = c;
|
|
3584
|
+
if (c === "(" || c === "[") depth++;
|
|
3585
|
+
if (c === ")" || c === "]") depth--;
|
|
3586
|
+
if (depth === 0 && (c === ">" || c === "+" || c === "~")) {
|
|
3587
|
+
push();
|
|
3588
|
+
combinator = c;
|
|
3589
|
+
continue;
|
|
3590
|
+
}
|
|
3591
|
+
if (depth === 0 && /\s/.test(c)) {
|
|
3592
|
+
if (current.trim()) {
|
|
3593
|
+
const keep = combinator;
|
|
3594
|
+
push();
|
|
3595
|
+
combinator = keep;
|
|
3596
|
+
}
|
|
3597
|
+
continue;
|
|
3598
|
+
}
|
|
3599
|
+
current += c;
|
|
3600
|
+
}
|
|
3601
|
+
push();
|
|
3602
|
+
return out;
|
|
3603
|
+
}
|
|
3604
|
+
function join2(parts) {
|
|
3605
|
+
return parts.map((p, i) => i === 0 ? p.text : p.combinator === " " ? ` ${p.text}` : ` ${p.combinator} ${p.text}`).join("");
|
|
3606
|
+
}
|
|
3607
|
+
function unwrap(text, prefix) {
|
|
3608
|
+
return text.slice(prefix.length, text.lastIndexOf(")")).trim() + text.slice(text.lastIndexOf(")") + 1);
|
|
3609
|
+
}
|
|
3610
|
+
function splitTop(selector, separator) {
|
|
3611
|
+
const parts = [];
|
|
3612
|
+
let depth = 0;
|
|
3613
|
+
let quote = "";
|
|
3614
|
+
let start = 0;
|
|
3615
|
+
for (let i = 0; i < selector.length; i++) {
|
|
3616
|
+
const c = selector[i];
|
|
3617
|
+
if (quote) {
|
|
3618
|
+
if (c === "\\") i++;
|
|
3619
|
+
else if (c === quote) quote = "";
|
|
3620
|
+
} else if (c === '"' || c === "'") quote = c;
|
|
3621
|
+
else if (c === "\\") i++;
|
|
3622
|
+
else if (c === "(" || c === "[") depth++;
|
|
3623
|
+
else if (c === ")" || c === "]") depth--;
|
|
3624
|
+
else if (c === separator && depth === 0) {
|
|
3625
|
+
parts.push(selector.slice(start, i));
|
|
3626
|
+
start = i + 1;
|
|
3627
|
+
}
|
|
3628
|
+
}
|
|
3629
|
+
parts.push(selector.slice(start));
|
|
3630
|
+
return parts.filter((p) => p.trim());
|
|
3631
|
+
}
|
|
3632
|
+
function shiftLoc(node, source, start) {
|
|
3633
|
+
const loc = node.loc && node.loc.source === source ? { source, line: start.line + node.loc.line - 1, column: node.loc.line === 1 ? start.column + node.loc.column : node.loc.column } : node.loc;
|
|
3634
|
+
if (node.kind === "rule" || node.kind === "at-rule") return { ...node, loc, nodes: node.nodes.map((n) => shiftLoc(n, source, start)) };
|
|
3635
|
+
return { ...node, loc };
|
|
3636
|
+
}
|
|
3637
|
+
function dropLoc(node) {
|
|
3638
|
+
const { loc: _loc, ...rest } = node;
|
|
3639
|
+
if (rest.kind === "rule" || rest.kind === "at-rule") return { ...rest, nodes: rest.nodes.map(dropLoc) };
|
|
3640
|
+
return rest;
|
|
3641
|
+
}
|
|
3642
|
+
function printStyleWithMap(nodes, minify, sourceName, module2) {
|
|
3643
|
+
const lines = [[]];
|
|
3644
|
+
let css = "";
|
|
3645
|
+
let column = 0;
|
|
3646
|
+
const emit = (text) => {
|
|
3647
|
+
for (const ch of text) {
|
|
3648
|
+
css += ch;
|
|
3649
|
+
if (ch === "\n") {
|
|
3650
|
+
lines.push([]);
|
|
3651
|
+
column = 0;
|
|
3652
|
+
} else column++;
|
|
3653
|
+
}
|
|
3654
|
+
};
|
|
3655
|
+
const mark = (loc) => {
|
|
3656
|
+
if (loc && loc.source === sourceName) lines[lines.length - 1].push([column, 0, loc.line - 1, loc.column]);
|
|
3657
|
+
};
|
|
3658
|
+
const write = (node, depth) => {
|
|
3659
|
+
const pad = minify ? "" : " ".repeat(depth);
|
|
3660
|
+
const nl = minify ? "" : "\n";
|
|
3661
|
+
const sp = minify ? "" : " ";
|
|
3662
|
+
emit(pad);
|
|
3663
|
+
mark(node.loc);
|
|
3664
|
+
if (node.kind === "declaration") {
|
|
3665
|
+
emit(`${node.property}:${sp}${node.value}${node.important ? `${sp}!important` : ""};${nl}`);
|
|
3666
|
+
} else if (node.kind === "raw") {
|
|
3667
|
+
emit(`${node.text}${nl}`);
|
|
3668
|
+
} else {
|
|
3669
|
+
emit(`${node.kind === "rule" ? node.selector : `@${node.name}${node.params ? " " + node.params : ""}`}${sp}{${nl}`);
|
|
3670
|
+
for (const child of node.nodes) write(child, depth + 1);
|
|
3671
|
+
emit(`${pad}}${nl}`);
|
|
3672
|
+
}
|
|
3673
|
+
};
|
|
3674
|
+
for (const node of nodes) write(node, 0);
|
|
3675
|
+
return { css, map: { version: 3, sources: [module2.id], sourcesContent: [module2.code], names: [], mappings: (0, import_sourcemap_codec.encode)(lines) } };
|
|
3676
|
+
}
|
|
3677
|
+
function printStyle(nodes, minify = false) {
|
|
3678
|
+
const out = [];
|
|
3679
|
+
const write = (node, depth) => {
|
|
3680
|
+
const pad = minify ? "" : " ".repeat(depth);
|
|
3681
|
+
const nl = minify ? "" : "\n";
|
|
3682
|
+
const sp = minify ? "" : " ";
|
|
3683
|
+
if (node.kind === "declaration") {
|
|
3684
|
+
out.push(`${pad}${node.property}:${sp}${node.value}${node.important ? `${sp}!important` : ""};${nl}`);
|
|
3685
|
+
} else if (node.kind === "raw") {
|
|
3686
|
+
out.push(`${pad}${node.text}${nl}`);
|
|
3687
|
+
} else {
|
|
3688
|
+
const header = node.kind === "rule" ? node.selector : `@${node.name}${node.params ? " " + node.params : ""}`;
|
|
3689
|
+
out.push(`${pad}${header}${sp}{${nl}`);
|
|
3690
|
+
for (const child of node.nodes) write(child, depth + 1);
|
|
3691
|
+
out.push(`${pad}}${nl}`);
|
|
3692
|
+
}
|
|
3693
|
+
};
|
|
3694
|
+
for (const node of nodes) write(node, 0);
|
|
3695
|
+
return out.join("");
|
|
3696
|
+
}
|
|
3697
|
+
var import_sourcemap_codec, SCOPE_ATTR, FUNCTIONS, OPAQUE;
|
|
3698
|
+
var init_styles = __esm({
|
|
3699
|
+
"src/transform/styles.ts"() {
|
|
3700
|
+
"use strict";
|
|
3701
|
+
import_sourcemap_codec = require("@jridgewell/sourcemap-codec");
|
|
3702
|
+
SCOPE_ATTR = "data-fx-s";
|
|
3703
|
+
FUNCTIONS = /* @__PURE__ */ new Set(["FunctionDeclaration", "FunctionExpression", "ArrowFunctionExpression", "ObjectMethod", "ClassMethod"]);
|
|
3704
|
+
OPAQUE = /(^|-)keyframes$|^font-face$|^property$|^counter-style$|^page$|^font-feature-values$/;
|
|
3705
|
+
}
|
|
3706
|
+
});
|
|
3707
|
+
|
|
2672
3708
|
// src/lower/compile-template.ts
|
|
2673
3709
|
function compilePieces(pieces, holes, options = {}) {
|
|
2674
3710
|
const used = /* @__PURE__ */ new Set();
|
|
@@ -2677,6 +3713,7 @@ function compilePieces(pieces, holes, options = {}) {
|
|
|
2677
3713
|
...options.sourceFile ? { sourceFile: options.sourceFile } : {},
|
|
2678
3714
|
...options.positionAt ? { positionAt: options.positionAt } : {}
|
|
2679
3715
|
});
|
|
3716
|
+
if (options.templateStyles) applyTemplateStyles(ir, options.templateStyles);
|
|
2680
3717
|
analyzeStatic(ir);
|
|
2681
3718
|
resolveComponentSources(ir, {
|
|
2682
3719
|
resolver: createComponentResolver(options.resolve ?? []),
|
|
@@ -2699,6 +3736,7 @@ function compilePieces(pieces, holes, options = {}) {
|
|
|
2699
3736
|
var init_compile_template = __esm({
|
|
2700
3737
|
"src/lower/compile-template.ts"() {
|
|
2701
3738
|
"use strict";
|
|
3739
|
+
init_styles();
|
|
2702
3740
|
init_analyze_static();
|
|
2703
3741
|
init_collapse_strategies();
|
|
2704
3742
|
init_imperative();
|
|
@@ -3231,8 +4269,8 @@ function isJsxRoot(node, parent, key) {
|
|
|
3231
4269
|
if (!isJsx(node)) return false;
|
|
3232
4270
|
return !(parent && isJsx(parent) && key === "children");
|
|
3233
4271
|
}
|
|
3234
|
-
function isTemplateTag(node,
|
|
3235
|
-
return node.type === "TaggedTemplateExpression" && node.tag?.type === "Identifier" && (node.tag.name
|
|
4272
|
+
function isTemplateTag(node, tags) {
|
|
4273
|
+
return node.type === "TaggedTemplateExpression" && node.tag?.type === "Identifier" && tags.has(node.tag.name);
|
|
3236
4274
|
}
|
|
3237
4275
|
function outermost(list) {
|
|
3238
4276
|
return list.filter(
|
|
@@ -3378,24 +4416,30 @@ function transformTemplates(code, id, options = {}) {
|
|
|
3378
4416
|
const wantsJsx = format !== "lit";
|
|
3379
4417
|
const mayHaveTemplate = wantsLit && (code.includes(`${litTag}\``) || code.includes("svg`"));
|
|
3380
4418
|
const wantsIntrinsics = options.intrinsics !== false && mayHaveIntrinsic(code);
|
|
3381
|
-
const wantsSources = options.sourceLocations === true &&
|
|
4419
|
+
const wantsSources = options.sourceLocations === true && mayHaveSourceMarks(code);
|
|
3382
4420
|
const sourceName = relativeToRoot(id, options.sourceRoot);
|
|
3383
|
-
|
|
4421
|
+
const wantsStyles = options.styles !== void 0 && (code.includes("<style") || code.includes("css`"));
|
|
4422
|
+
if (!mayHaveTemplate && !(wantsJsx && code.includes("<")) && !wantsIntrinsics && !wantsSources && !wantsStyles) return null;
|
|
3384
4423
|
const ast = (0, import_parser2.parse)(code, {
|
|
3385
4424
|
sourceType: "module",
|
|
3386
4425
|
plugins: ["jsx", "typescript"],
|
|
3387
4426
|
errorRecovery: true
|
|
3388
4427
|
});
|
|
4428
|
+
const intrinsicTags = options.intrinsics === false ? /* @__PURE__ */ new Map() : tagIntrinsics(moduleBindings(ast.program));
|
|
4429
|
+
const templateTags = /* @__PURE__ */ new Map([[litTag, "html"], ["svg", "svg"]]);
|
|
4430
|
+
for (const [name, tag] of intrinsicTags) if (tag !== "css") templateTags.set(name, tag);
|
|
4431
|
+
const cssTags = [...intrinsicTags].filter(([, tag]) => tag === "css").map(([name]) => name);
|
|
3389
4432
|
const found = [];
|
|
3390
4433
|
walk7(ast.program, (n, parent, key) => {
|
|
3391
|
-
if (wantsLit && isTemplateTag(n,
|
|
4434
|
+
if (wantsLit && isTemplateTag(n, templateTags)) found.push(n);
|
|
3392
4435
|
else if (wantsJsx && isJsxRoot(n, parent, key)) found.push(n);
|
|
3393
4436
|
});
|
|
3394
4437
|
const props = options.propsDestructure === false ? { edits: [], diagnostics: [], used: /* @__PURE__ */ new Set() } : collectPropsEdits(ast.program, code, { runtimeModule: options.runtimeModule });
|
|
3395
4438
|
const intrinsics = options.intrinsics === false ? { edits: [], diagnostics: [], imports: /* @__PURE__ */ new Map() } : collectIntrinsicEdits(ast.program);
|
|
3396
4439
|
if (intrinsics.edits.length) avoidBindingClashes(ast.program, intrinsics, moduleBindings(ast.program));
|
|
3397
4440
|
const sources = options.sourceLocations === true ? collectSourceEdits(ast.program, sourceName) : { edits: [], marked: 0 };
|
|
3398
|
-
const
|
|
4441
|
+
const styles = wantsStyles ? collectStyles(ast.program, sourceName, options.styles, { html: templateTags, css: cssTags }, { id, code }) : void 0;
|
|
4442
|
+
const silent = found.length === 0 && props.edits.length === 0 && sources.edits.length === 0 && intrinsics.edits.length === 0 && intrinsics.diagnostics.length === 0 && props.diagnostics.length === 0 && !styles?.edits.length && !styles?.diagnostics.length;
|
|
3399
4443
|
if (silent) return null;
|
|
3400
4444
|
found.sort((a, b) => b.start - a.start || a.end - b.end);
|
|
3401
4445
|
const used = new Set(props.used);
|
|
@@ -3409,20 +4453,32 @@ function transformTemplates(code, id, options = {}) {
|
|
|
3409
4453
|
declared: declaredNames(ast.program)
|
|
3410
4454
|
};
|
|
3411
4455
|
const hoisted = /* @__PURE__ */ new Map();
|
|
3412
|
-
const edits = [...props.edits, ...intrinsics.edits, ...sources.edits];
|
|
4456
|
+
const edits = [...props.edits, ...intrinsics.edits, ...sources.edits, ...styles?.edits ?? []];
|
|
3413
4457
|
for (const node of found) {
|
|
3414
4458
|
const nested = found.some(
|
|
3415
4459
|
(o) => o !== node && o.start <= node.start && o.end >= node.end && o.end - o.start > node.end - node.start
|
|
3416
4460
|
);
|
|
3417
4461
|
if (isJsx(node)) {
|
|
3418
|
-
edits.push({ start: node.start, end: node.end, code: compileJsx(code, node, edits, nested, used, needs, hoisted, options, sourceName) });
|
|
4462
|
+
edits.push({ start: node.start, end: node.end, code: compileJsx(code, node, edits, nested, used, needs, hoisted, options, sourceName, styles) });
|
|
3419
4463
|
continue;
|
|
3420
4464
|
}
|
|
3421
4465
|
const holes = node.quasi.expressions.map(
|
|
3422
4466
|
(e) => bindHole2(code, e, edits, options.sourceLocations === true)
|
|
3423
4467
|
);
|
|
4468
|
+
const scope = styles?.scopes.find((s) => node.start >= s.start && node.end <= s.end)?.value;
|
|
4469
|
+
const owner = styles?.templateOwners.get(node.start);
|
|
4470
|
+
const templateStyles = options.styles && styles && (scope || owner) ? {
|
|
4471
|
+
options: options.styles,
|
|
4472
|
+
...scope ? { scope } : {},
|
|
4473
|
+
...owner ? { owner } : {},
|
|
4474
|
+
line: node.loc?.start.line ?? 0,
|
|
4475
|
+
column: node.loc?.start.column ?? 0,
|
|
4476
|
+
styles: styles.styles,
|
|
4477
|
+
diagnostics: styles.diagnostics
|
|
4478
|
+
} : void 0;
|
|
3424
4479
|
const result = compilePieces(toPieces(node), holes, {
|
|
3425
4480
|
...options,
|
|
4481
|
+
...templateStyles ? { templateStyles } : {},
|
|
3426
4482
|
hoistTemplates: true,
|
|
3427
4483
|
// A tag inside a template gets the same mark a JSX tag does. Without one, the nodes it
|
|
3428
4484
|
// makes are the only ones in the module carrying no mark, and they take whichever was
|
|
@@ -3431,12 +4487,13 @@ function transformTemplates(code, id, options = {}) {
|
|
|
3431
4487
|
// Same defaults as the plugin, so moving a build over is not a rendering change.
|
|
3432
4488
|
templateClone: options.templateClone ?? true,
|
|
3433
4489
|
partialTemplates: nested ? false : options.partialTemplates ?? true,
|
|
3434
|
-
svg: node.tag.name === "svg"
|
|
4490
|
+
svg: templateTags.get(node.tag.name) === "svg"
|
|
3435
4491
|
});
|
|
3436
4492
|
for (const symbol of result.imports) used.add(symbol);
|
|
3437
4493
|
collectNeeds(result.ir, needs);
|
|
3438
4494
|
edits.push({ start: node.start, end: node.end, code: adoptTemplates2(result.code, result.templates, hoisted) });
|
|
3439
4495
|
}
|
|
4496
|
+
if (styles && options.styles) edits.push(...finishShadowStyles(styles, code, id));
|
|
3440
4497
|
const out = new import_magic_string2.default(code);
|
|
3441
4498
|
for (const e of outermost(edits)) {
|
|
3442
4499
|
if (e.start === e.end) out.appendLeft(e.start, e.code);
|
|
@@ -3494,13 +4551,19 @@ function transformTemplates(code, id, options = {}) {
|
|
|
3494
4551
|
...loadDiagnostics.length ? { loadDiagnostics } : {},
|
|
3495
4552
|
...unresolvedDiagnostics.length ? { unresolvedDiagnostics } : {},
|
|
3496
4553
|
...props.diagnostics.length ? { propsDiagnostics: props.diagnostics } : {},
|
|
3497
|
-
...intrinsics.diagnostics.length ? { intrinsicDiagnostics: intrinsics.diagnostics } : {}
|
|
4554
|
+
...intrinsics.diagnostics.length ? { intrinsicDiagnostics: intrinsics.diagnostics } : {},
|
|
4555
|
+
...styles?.styles.length ? { styles: styles.styles } : {},
|
|
4556
|
+
...styles?.diagnostics.length ? { styleDiagnostics: styles.diagnostics } : {},
|
|
4557
|
+
...styles?.literals.length ? { styleLiterals: styles.literals } : {},
|
|
4558
|
+
...styles?.references.length ? { styleReferences: styles.references } : {}
|
|
3498
4559
|
};
|
|
3499
4560
|
}
|
|
3500
|
-
function compileJsx(code, node, edits, nested, used, needs, hoisted, options, sourceFile) {
|
|
4561
|
+
function compileJsx(code, node, edits, nested, used, needs, hoisted, options, sourceFile, styles) {
|
|
3501
4562
|
const ir = buildJsxIR(node, {
|
|
3502
4563
|
code: (n) => slice(code, n.start, n.end, edits),
|
|
3503
4564
|
used,
|
|
4565
|
+
...styles?.scopes.length ? { scopes: styles.scopes } : {},
|
|
4566
|
+
...styles?.drop.size ? { dropStyles: styles.drop } : {},
|
|
3504
4567
|
...options.sourceLocations === true && sourceFile ? { sourceFile } : {}
|
|
3505
4568
|
});
|
|
3506
4569
|
analyzeStatic(ir);
|
|
@@ -3586,6 +4649,7 @@ var init_templates = __esm({
|
|
|
3586
4649
|
init_props();
|
|
3587
4650
|
init_intrinsics2();
|
|
3588
4651
|
init_source_locations();
|
|
4652
|
+
init_styles();
|
|
3589
4653
|
init_intrinsics();
|
|
3590
4654
|
init_reactive_bindings();
|
|
3591
4655
|
init_builtins();
|
|
@@ -3628,14 +4692,14 @@ var init_transform = __esm({
|
|
|
3628
4692
|
});
|
|
3629
4693
|
|
|
3630
4694
|
// src/transform/server-fn-id.ts
|
|
3631
|
-
function
|
|
4695
|
+
function hash2(s) {
|
|
3632
4696
|
let h = 5381;
|
|
3633
4697
|
for (let i = 0; i < s.length; i++) h = h * 33 ^ s.charCodeAt(i);
|
|
3634
4698
|
return (h >>> 0).toString(16);
|
|
3635
4699
|
}
|
|
3636
4700
|
function serverFnId(filename, root, index) {
|
|
3637
4701
|
const rel = (filename || "unknown").replace(root ? root + "/" : "", "");
|
|
3638
|
-
return `${
|
|
4702
|
+
return `${hash2(rel)}:${index}`;
|
|
3639
4703
|
}
|
|
3640
4704
|
var init_server_fn_id = __esm({
|
|
3641
4705
|
"src/transform/server-fn-id.ts"() {
|
|
@@ -3733,7 +4797,7 @@ var server_fns_exports = {};
|
|
|
3733
4797
|
__export(server_fns_exports, {
|
|
3734
4798
|
transformServerFns: () => transformServerFns
|
|
3735
4799
|
});
|
|
3736
|
-
function
|
|
4800
|
+
function directive2(node) {
|
|
3737
4801
|
if (!FUNCTION_TYPES.has(node.type)) return null;
|
|
3738
4802
|
const body = node.body;
|
|
3739
4803
|
if (!body || body.type !== "BlockStatement") return null;
|
|
@@ -3749,7 +4813,7 @@ function findServerFns(node, out) {
|
|
|
3749
4813
|
return;
|
|
3750
4814
|
}
|
|
3751
4815
|
if (typeof node.type === "string") {
|
|
3752
|
-
const found =
|
|
4816
|
+
const found = directive2(node);
|
|
3753
4817
|
if (found) {
|
|
3754
4818
|
out.push({ fn: node, directive: found });
|
|
3755
4819
|
return;
|
|
@@ -3891,7 +4955,7 @@ function componentGlobals(rules, options = {}) {
|
|
|
3891
4955
|
resolved.set(name, target);
|
|
3892
4956
|
}
|
|
3893
4957
|
}
|
|
3894
|
-
const usableIntrinsics = intrinsics ? Object.entries(INTRINSICS).filter(([, i]) => {
|
|
4958
|
+
const usableIntrinsics = intrinsics ? Object.entries({ ...INTRINSICS, ...TAG_INTRINSICS }).filter(([, i]) => {
|
|
3895
4959
|
const pkg = packageOf(i.module);
|
|
3896
4960
|
return !available || !pkg || available.has(pkg);
|
|
3897
4961
|
}) : [];
|
|
@@ -3954,11 +5018,11 @@ function coveredByInclude(root, target) {
|
|
|
3954
5018
|
}
|
|
3955
5019
|
if (config.extends !== void 0) return void 0;
|
|
3956
5020
|
if (!Array.isArray(config.include)) return true;
|
|
3957
|
-
const
|
|
5021
|
+
const relative3 = relativePosix(root, target);
|
|
3958
5022
|
return config.include.some((entry) => {
|
|
3959
5023
|
if (typeof entry !== "string") return false;
|
|
3960
5024
|
const pattern = entry.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*\*\//g, "(?:.*/)?").replace(/\*/g, "[^/]*");
|
|
3961
|
-
return new RegExp(`^${pattern}(?:/.*)?$`).test(
|
|
5025
|
+
return new RegExp(`^${pattern}(?:/.*)?$`).test(relative3);
|
|
3962
5026
|
});
|
|
3963
5027
|
}
|
|
3964
5028
|
function relativePosix(from, to) {
|
|
@@ -4044,13 +5108,169 @@ function writeComponentGlobals(options, root) {
|
|
|
4044
5108
|
}
|
|
4045
5109
|
function warnIfUnreachable(root, target) {
|
|
4046
5110
|
if (coveredByInclude(root, target) !== false) return void 0;
|
|
4047
|
-
const
|
|
4048
|
-
return `[fluixi] ${
|
|
5111
|
+
const relative3 = relativePosix(root, target);
|
|
5112
|
+
return `[fluixi] ${relative3} is not covered by "include" in tsconfig.json, so TypeScript will ignore it and every resolved component stays "Cannot find name". Add "${relative3}" to "include".`;
|
|
4049
5113
|
}
|
|
4050
5114
|
|
|
4051
|
-
// src/
|
|
5115
|
+
// src/vite-styles.ts
|
|
4052
5116
|
var import_node_fs2 = require("node:fs");
|
|
4053
5117
|
var import_node_path2 = require("node:path");
|
|
5118
|
+
var STYLE_ID = /\?fx-style&index=(\d+)(?:&inline)?&lang\.css$/;
|
|
5119
|
+
var LITERAL_ID = /\?fx-literal=([\w$]+)&inline&lang\.css$/;
|
|
5120
|
+
var styleId = (file, index) => `${file}?fx-style&index=${index}&lang.css`;
|
|
5121
|
+
var loader = (name) => `const href = new URL(${JSON.stringify(`./${name}`)}, import.meta.url).href;
|
|
5122
|
+
if (typeof document !== 'undefined' && !document.querySelector(\`link[data-fx-css="\${href}"]\`)) {
|
|
5123
|
+
const link = document.createElement('link');
|
|
5124
|
+
link.rel = 'stylesheet';
|
|
5125
|
+
link.href = href;
|
|
5126
|
+
link.dataset.fxCss = href;
|
|
5127
|
+
document.head.appendChild(link);
|
|
5128
|
+
}
|
|
5129
|
+
`;
|
|
5130
|
+
function createComponentStyles(compile) {
|
|
5131
|
+
let api;
|
|
5132
|
+
let server;
|
|
5133
|
+
let root = process.cwd();
|
|
5134
|
+
let library;
|
|
5135
|
+
const emitted = /* @__PURE__ */ new Map();
|
|
5136
|
+
const fileOf = (id) => (0, import_node_fs2.existsSync)(id) ? id : (0, import_node_path2.join)(root, id);
|
|
5137
|
+
const cache = /* @__PURE__ */ new Map();
|
|
5138
|
+
const resolveReference = async (ref, importer, ctx, seen) => {
|
|
5139
|
+
const resolved = await ctx.resolve?.(ref.source, importer);
|
|
5140
|
+
if (!resolved) return null;
|
|
5141
|
+
const file = resolved.id.split("?")[0];
|
|
5142
|
+
if (seen.has(file)) return null;
|
|
5143
|
+
let code;
|
|
5144
|
+
try {
|
|
5145
|
+
code = (0, import_node_fs2.readFileSync)(fileOf(file), "utf8");
|
|
5146
|
+
} catch {
|
|
5147
|
+
return null;
|
|
5148
|
+
}
|
|
5149
|
+
const styles = api.styles(file);
|
|
5150
|
+
let result = compile(code, file, styles);
|
|
5151
|
+
if (result?.styleReferences?.length) {
|
|
5152
|
+
const imported = await resolveAll(result.styleReferences, file, ctx, /* @__PURE__ */ new Set([...seen, file]));
|
|
5153
|
+
result = compile(code, file, { ...styles, imported });
|
|
5154
|
+
}
|
|
5155
|
+
const literal = result?.styleLiterals?.find((l) => l.name === ref.name);
|
|
5156
|
+
return literal ? styles.process(literal.css, file) : null;
|
|
5157
|
+
};
|
|
5158
|
+
const resolveAll = async (refs, importer, ctx, seen) => {
|
|
5159
|
+
const imported = /* @__PURE__ */ new Map();
|
|
5160
|
+
for (const ref of refs) {
|
|
5161
|
+
const nodes = await resolveReference(ref, importer, ctx, seen);
|
|
5162
|
+
if (nodes) imported.set(`${ref.source}#${ref.name}`, nodes);
|
|
5163
|
+
}
|
|
5164
|
+
return imported;
|
|
5165
|
+
};
|
|
5166
|
+
const run = async (code, id, ctx) => {
|
|
5167
|
+
const file = fileOf(id);
|
|
5168
|
+
const styles = api.styles(file);
|
|
5169
|
+
let result = compile(code, file, styles);
|
|
5170
|
+
if (result?.styleReferences?.length) {
|
|
5171
|
+
const imported = await resolveAll(result.styleReferences, id, ctx, /* @__PURE__ */ new Set([file]));
|
|
5172
|
+
result = compile(code, file, { ...styles, imported });
|
|
5173
|
+
}
|
|
5174
|
+
const css = (result?.styles ?? []).map((s) => s.css);
|
|
5175
|
+
const maps = (result?.styles ?? []).map((s) => s.map ?? null);
|
|
5176
|
+
const literals = new Map((result?.styleLiterals ?? []).map((l) => [l.name, l.css]));
|
|
5177
|
+
const before = cache.get(file);
|
|
5178
|
+
cache.set(file, { source: code, css, maps, literals });
|
|
5179
|
+
if (server && before) {
|
|
5180
|
+
for (let i = 0; i < css.length; i++) {
|
|
5181
|
+
if (before.css[i] === css[i]) continue;
|
|
5182
|
+
const mod = server.moduleGraph.getModuleById(styleId(id, i));
|
|
5183
|
+
if (mod) void server.reloadModule(mod);
|
|
5184
|
+
}
|
|
5185
|
+
}
|
|
5186
|
+
const page = (result?.styles ?? []).flatMap((s, i) => s.shadow ? [] : [i]);
|
|
5187
|
+
if (!result || page.length === 0) return result;
|
|
5188
|
+
if (library) {
|
|
5189
|
+
const name = `${(0, import_node_path2.basename)(file, (0, import_node_path2.extname)(file))}.css`;
|
|
5190
|
+
if ((0, import_node_fs2.existsSync)((0, import_node_path2.join)((0, import_node_path2.dirname)(file), name))) {
|
|
5191
|
+
throw new Error(`[fluixi] ${file} has <style> blocks, and ${name} next to it would be overwritten by their CSS. Rename one of them.`);
|
|
5192
|
+
}
|
|
5193
|
+
const out = (0, import_node_path2.join)((0, import_node_path2.relative)(library, (0, import_node_path2.dirname)(file)), name);
|
|
5194
|
+
emitted.set(out, page.map((i) => css[i]).join("\n"));
|
|
5195
|
+
emitted.set(`${out}.js`, loader(name));
|
|
5196
|
+
return { ...result, code: `${result.code}
|
|
5197
|
+
import ${JSON.stringify(`./${name}`)};` };
|
|
5198
|
+
}
|
|
5199
|
+
const imports = page.map((i) => `
|
|
5200
|
+
import ${JSON.stringify(styleId(id, i))};`).join("");
|
|
5201
|
+
return { ...result, code: result.code + imports };
|
|
5202
|
+
};
|
|
5203
|
+
return {
|
|
5204
|
+
/** Looks for @fluixi-css/vite among the plugins; without it component styles stay off. */
|
|
5205
|
+
connect(plugins, projectRoot) {
|
|
5206
|
+
if (projectRoot) root = projectRoot;
|
|
5207
|
+
api = (plugins ?? []).map((p) => p?.api?.fluixiCss).find((a) => Boolean(a));
|
|
5208
|
+
api?.useComponentStyles();
|
|
5209
|
+
},
|
|
5210
|
+
/** Turns on library output, from the directory of a `build.lib` entry. */
|
|
5211
|
+
setLibrary(entryDir) {
|
|
5212
|
+
library = entryDir;
|
|
5213
|
+
},
|
|
5214
|
+
/** A library build's style import: left for the package's consumer to bundle. */
|
|
5215
|
+
isLibraryImport(id, importer) {
|
|
5216
|
+
if (library === void 0 || !importer || !id.startsWith("./") || !id.endsWith(".css")) return false;
|
|
5217
|
+
return emitted.has((0, import_node_path2.join)((0, import_node_path2.relative)(library, (0, import_node_path2.dirname)(fileOf(importer))), id));
|
|
5218
|
+
},
|
|
5219
|
+
/** The style files a library build writes, by path under the output directory. */
|
|
5220
|
+
libraryFiles() {
|
|
5221
|
+
return emitted;
|
|
5222
|
+
},
|
|
5223
|
+
get active() {
|
|
5224
|
+
return api !== void 0;
|
|
5225
|
+
},
|
|
5226
|
+
setServer(dev) {
|
|
5227
|
+
server = dev;
|
|
5228
|
+
},
|
|
5229
|
+
isStyle(id) {
|
|
5230
|
+
return STYLE_ID.test(id) || LITERAL_ID.test(id);
|
|
5231
|
+
},
|
|
5232
|
+
/**
|
|
5233
|
+
* A style request as the module id Vite should keep: the file's absolute path and the
|
|
5234
|
+
* query. Vite invalidates a module when the file its id names changes, so a root-relative id
|
|
5235
|
+
* (`/src/card.tsx?fx-style…`, which is how a request arrives before the component's imports
|
|
5236
|
+
* were analysed) was never invalidated, and an edited block kept its old CSS until restart.
|
|
5237
|
+
*/
|
|
5238
|
+
resolveId(id) {
|
|
5239
|
+
const at = id.indexOf("?");
|
|
5240
|
+
return fileOf(id.slice(0, at)) + id.slice(at);
|
|
5241
|
+
},
|
|
5242
|
+
compile: run,
|
|
5243
|
+
/**
|
|
5244
|
+
* A block's CSS and its map back to the module, compiling the module again when the cache
|
|
5245
|
+
* does not match the file.
|
|
5246
|
+
*/
|
|
5247
|
+
async load(id, ctx) {
|
|
5248
|
+
const match = STYLE_ID.exec(id);
|
|
5249
|
+
const literal = LITERAL_ID.exec(id);
|
|
5250
|
+
if (!match && !literal || !api) return null;
|
|
5251
|
+
const file = id.slice(0, id.indexOf("?"));
|
|
5252
|
+
let source;
|
|
5253
|
+
try {
|
|
5254
|
+
source = (0, import_node_fs2.readFileSync)(fileOf(file), "utf8");
|
|
5255
|
+
} catch {
|
|
5256
|
+
return null;
|
|
5257
|
+
}
|
|
5258
|
+
if (cache.get(fileOf(file))?.source !== source) await run(source, file, ctx);
|
|
5259
|
+
const entry = cache.get(fileOf(file));
|
|
5260
|
+
if (literal) {
|
|
5261
|
+
const css = entry?.literals.get(literal[1]);
|
|
5262
|
+
if (css === void 0) throw new Error(`[fluixi] ${literal[1]} in ${file} is not a css\`\` value, so it cannot be a shadow root's styles.`);
|
|
5263
|
+
return { code: css, map: null };
|
|
5264
|
+
}
|
|
5265
|
+
const index = Number(match[1]);
|
|
5266
|
+
return { code: entry?.css[index] ?? "", map: entry?.maps[index] ?? null };
|
|
5267
|
+
}
|
|
5268
|
+
};
|
|
5269
|
+
}
|
|
5270
|
+
|
|
5271
|
+
// src/integrations.ts
|
|
5272
|
+
var import_node_fs3 = require("node:fs");
|
|
5273
|
+
var import_node_path3 = require("node:path");
|
|
4054
5274
|
async function createBabelPlugin(options = {}) {
|
|
4055
5275
|
let pluginModule = null;
|
|
4056
5276
|
try {
|
|
@@ -4115,6 +5335,11 @@ var RETIRED_SUBPATHS = {
|
|
|
4115
5335
|
"@fluixi/core/rx": "is gone — import signals and effects from @fluixi/reactive, or the server primitives it resolved to under node from @fluixi/core/server"
|
|
4116
5336
|
};
|
|
4117
5337
|
function createVitePlugin(options = {}) {
|
|
5338
|
+
let transformTemplates2;
|
|
5339
|
+
let projectRoot = process.cwd();
|
|
5340
|
+
const componentStyles = createComponentStyles((code, id, styles) => {
|
|
5341
|
+
return transformTemplates2(code, id, { ...transformOptions(options, id), sourceRoot: projectRoot, styles });
|
|
5342
|
+
});
|
|
4118
5343
|
return {
|
|
4119
5344
|
name: "vite-fluixi-jsx",
|
|
4120
5345
|
enforce: "pre",
|
|
@@ -4128,14 +5353,32 @@ function createVitePlugin(options = {}) {
|
|
|
4128
5353
|
},
|
|
4129
5354
|
// Written once per build, and on dev-server start, rather than per transform: the
|
|
4130
5355
|
// set of resolvable names comes from config, so nothing a file does can change it.
|
|
4131
|
-
configResolved(config) {
|
|
5356
|
+
async configResolved(config) {
|
|
4132
5357
|
const outcome = writeComponentGlobals(options, config?.root ?? process.cwd());
|
|
4133
5358
|
if (outcome.warning) console.warn(outcome.warning);
|
|
5359
|
+
if (options.babel) return;
|
|
5360
|
+
projectRoot = config?.root ?? projectRoot;
|
|
5361
|
+
componentStyles.connect(config?.plugins, config?.root);
|
|
5362
|
+
const entry = config?.command === "build" && config.build?.lib ? config.build.lib.entry : void 0;
|
|
5363
|
+
const first = typeof entry === "string" ? entry : Array.isArray(entry) ? entry[0] : entry && typeof entry === "object" ? Object.values(entry)[0] : void 0;
|
|
5364
|
+
if (typeof first === "string") componentStyles.setLibrary((0, import_node_path3.dirname)((0, import_node_path3.resolve)(config.root ?? process.cwd(), first)));
|
|
5365
|
+
if (componentStyles.active) ({ transformTemplates: transformTemplates2 } = await Promise.resolve().then(() => (init_transform(), transform_exports)));
|
|
5366
|
+
},
|
|
5367
|
+
generateBundle() {
|
|
5368
|
+
for (const [fileName, source] of componentStyles.libraryFiles()) this.emitFile({ type: "asset", fileName, source });
|
|
5369
|
+
},
|
|
5370
|
+
configureServer(server) {
|
|
5371
|
+
componentStyles.setServer(server);
|
|
5372
|
+
},
|
|
5373
|
+
load(id) {
|
|
5374
|
+
return componentStyles.isStyle(id) ? componentStyles.load(id, this) : null;
|
|
4134
5375
|
},
|
|
4135
5376
|
// A subpath we retired resolves to nothing, and the bundler reports that as
|
|
4136
5377
|
// `Missing "./x" specifier`, which names neither the replacement nor the file
|
|
4137
5378
|
// that asked. Answer it here, where the rename is known.
|
|
4138
5379
|
resolveId(id, importer) {
|
|
5380
|
+
if (componentStyles.isStyle(id)) return componentStyles.resolveId(id);
|
|
5381
|
+
if (componentStyles.isLibraryImport(id, importer)) return { id, external: true };
|
|
4139
5382
|
const moved = RETIRED_SUBPATHS[id];
|
|
4140
5383
|
if (!moved) return null;
|
|
4141
5384
|
throw new Error(
|
|
@@ -4147,6 +5390,11 @@ function createVitePlugin(options = {}) {
|
|
|
4147
5390
|
if (!/\.(jsx|tsx|ts)$/i.test(id)) {
|
|
4148
5391
|
return null;
|
|
4149
5392
|
}
|
|
5393
|
+
if (!options.babel && componentStyles.active) {
|
|
5394
|
+
const result = await componentStyles.compile(code, id, this);
|
|
5395
|
+
reportDiagnostics(result, id);
|
|
5396
|
+
return result;
|
|
5397
|
+
}
|
|
4150
5398
|
if (!options.babel) return compileModule(code, id, options);
|
|
4151
5399
|
const babelPlugin = await createBabelPlugin(options);
|
|
4152
5400
|
try {
|
|
@@ -4242,6 +5490,7 @@ function reportDiagnostics(result, id) {
|
|
|
4242
5490
|
for (const d of r?.unresolvedDiagnostics ?? []) say(d.message);
|
|
4243
5491
|
for (const d of r?.loadDiagnostics ?? []) say(d.message);
|
|
4244
5492
|
for (const d of r?.intrinsicDiagnostics ?? []) say(d.message);
|
|
5493
|
+
for (const d of r?.styleDiagnostics ?? []) say(`${d.line}:${d.column + 1} ${d.message}`);
|
|
4245
5494
|
for (const d of r?.propsDiagnostics ?? []) {
|
|
4246
5495
|
say(`\`${d.name}\` was left destructured: ${d.message}. It reads once instead of tracking.`);
|
|
4247
5496
|
}
|
|
@@ -4294,8 +5543,8 @@ function createESBuildPlugin(options = {}) {
|
|
|
4294
5543
|
name: "esbuild-fluixi-jsx",
|
|
4295
5544
|
setup(build) {
|
|
4296
5545
|
build.onLoad({ filter: /\.[jt]sx?$/ }, async (args) => {
|
|
4297
|
-
const { readFileSync:
|
|
4298
|
-
const source =
|
|
5546
|
+
const { readFileSync: readFileSync4 } = await import("node:fs");
|
|
5547
|
+
const source = readFileSync4(args.path, "utf8");
|
|
4299
5548
|
try {
|
|
4300
5549
|
const result = await compileModule(source, args.path, options);
|
|
4301
5550
|
return {
|
|
@@ -4323,17 +5572,17 @@ function hasServerDirective(source) {
|
|
|
4323
5572
|
function findServerFnModules(dir, out = []) {
|
|
4324
5573
|
let entries;
|
|
4325
5574
|
try {
|
|
4326
|
-
entries = (0,
|
|
5575
|
+
entries = (0, import_node_fs3.readdirSync)(dir, { withFileTypes: true });
|
|
4327
5576
|
} catch {
|
|
4328
5577
|
return out;
|
|
4329
5578
|
}
|
|
4330
5579
|
for (const e of entries) {
|
|
4331
5580
|
if (e.name === "node_modules" || e.name === "dist" || e.name.startsWith(".")) continue;
|
|
4332
|
-
const full = (0,
|
|
5581
|
+
const full = (0, import_node_path3.join)(dir, e.name);
|
|
4333
5582
|
if (e.isDirectory()) findServerFnModules(full, out);
|
|
4334
5583
|
else if (/\.[jt]sx?$/.test(e.name)) {
|
|
4335
5584
|
try {
|
|
4336
|
-
if (hasServerDirective((0,
|
|
5585
|
+
if (hasServerDirective((0, import_node_fs3.readFileSync)(full, "utf8"))) out.push(full);
|
|
4337
5586
|
} catch {
|
|
4338
5587
|
}
|
|
4339
5588
|
}
|
|
@@ -4353,7 +5602,7 @@ function serverFunctionsVitePlugin(options = {}) {
|
|
|
4353
5602
|
},
|
|
4354
5603
|
load(id) {
|
|
4355
5604
|
if (id !== "\0" + SERVER_FNS_VMOD) return null;
|
|
4356
|
-
const mods = findServerFnModules((0,
|
|
5605
|
+
const mods = findServerFnModules((0, import_node_path3.join)(root, "src"));
|
|
4357
5606
|
const setup = `import '@fluixi/start/server-fn-setup';
|
|
4358
5607
|
`;
|
|
4359
5608
|
const imports = mods.map((m) => `import ${JSON.stringify(m)};`).join("\n");
|