@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/transform/index.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;
|
|
@@ -44,6 +44,563 @@ module.exports = __toCommonJS(index_exports);
|
|
|
44
44
|
var import_parser2 = require("@babel/parser");
|
|
45
45
|
var import_magic_string2 = __toESM(require("magic-string"), 1);
|
|
46
46
|
|
|
47
|
+
// src/transform/styles.ts
|
|
48
|
+
var import_sourcemap_codec = require("@jridgewell/sourcemap-codec");
|
|
49
|
+
var SCOPE_ATTR = "data-fx-s";
|
|
50
|
+
var FUNCTIONS = /* @__PURE__ */ new Set(["FunctionDeclaration", "FunctionExpression", "ArrowFunctionExpression", "ObjectMethod", "ClassMethod"]);
|
|
51
|
+
function collectStyles(program, sourceName, options, tags = { html: /* @__PURE__ */ new Map([["html", "html"]]) }, module2) {
|
|
52
|
+
const plan = {
|
|
53
|
+
scopes: [],
|
|
54
|
+
templateOwners: /* @__PURE__ */ new Map(),
|
|
55
|
+
drop: /* @__PURE__ */ new Set(),
|
|
56
|
+
styles: [],
|
|
57
|
+
diagnostics: [],
|
|
58
|
+
edits: [],
|
|
59
|
+
literals: [],
|
|
60
|
+
references: [],
|
|
61
|
+
shadowClasses: /* @__PURE__ */ new Map()
|
|
62
|
+
};
|
|
63
|
+
if (!options) return plan;
|
|
64
|
+
const literalsOf = findLiterals(program, options.cssModules ?? ["@fluixi/core", "@fluixi/dom"], plan, tags.css ?? []);
|
|
65
|
+
plan.names = literalsOf;
|
|
66
|
+
const classOf = /* @__PURE__ */ new Map();
|
|
67
|
+
const shadowOf = (owner) => {
|
|
68
|
+
const cls = classOf.get(owner);
|
|
69
|
+
return cls ? plan.shadowClasses.get(cls) : void 0;
|
|
70
|
+
};
|
|
71
|
+
const resolved = /* @__PURE__ */ new Map();
|
|
72
|
+
const piecesToNodes = (quasis, expressions, at, stack) => {
|
|
73
|
+
const out = [];
|
|
74
|
+
for (let i = 0; i < quasis.length; i++) {
|
|
75
|
+
const text = quasis[i].value.cooked ?? quasis[i].value.raw;
|
|
76
|
+
if (text.trim()) {
|
|
77
|
+
try {
|
|
78
|
+
const start = quasis[i].loc?.start;
|
|
79
|
+
out.push(...options.process(text, sourceName).map((n) => start ? shiftLoc(n, sourceName, start) : n));
|
|
80
|
+
} catch (error) {
|
|
81
|
+
plan.diagnostics.push({ ...at, message: `CSS could not be processed: ${error.message}` });
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
const expr = expressions[i];
|
|
86
|
+
if (!expr) continue;
|
|
87
|
+
const value = expr.type === "Identifier" ? resolveLiteral(expr.name, at, stack) : void 0;
|
|
88
|
+
if (value === void 0) {
|
|
89
|
+
plan.diagnostics.push({
|
|
90
|
+
...at,
|
|
91
|
+
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))."
|
|
92
|
+
});
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
if (value === null) return null;
|
|
96
|
+
out.push(...value);
|
|
97
|
+
}
|
|
98
|
+
return out;
|
|
99
|
+
};
|
|
100
|
+
function resolveLiteral(name, at, stack) {
|
|
101
|
+
const imported = literalsOf.imports.get(name);
|
|
102
|
+
if (imported) {
|
|
103
|
+
const nodes = options?.imported?.get(`${imported.source}#${imported.name}`);
|
|
104
|
+
if (nodes) return nodes.map(dropLoc);
|
|
105
|
+
plan.references.push({ name: imported.name, source: imported.source, ...at });
|
|
106
|
+
plan.diagnostics.push({
|
|
107
|
+
...at,
|
|
108
|
+
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.`
|
|
109
|
+
});
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
const literal = literalsOf.literals.get(name);
|
|
113
|
+
if (!literal) return void 0;
|
|
114
|
+
if (stack.includes(name)) {
|
|
115
|
+
plan.diagnostics.push({ ...at, message: `css\`\` values include each other: ${[...stack, name].join(" → ")}.` });
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
if (!resolved.has(name)) {
|
|
119
|
+
resolved.set(name, piecesToNodes(literal.quasi.quasis, literal.quasi.expressions, at, [...stack, name]));
|
|
120
|
+
}
|
|
121
|
+
return resolved.get(name);
|
|
122
|
+
}
|
|
123
|
+
for (const [name, literal] of literalsOf.literals) {
|
|
124
|
+
const at = { line: literal.loc?.start.line ?? 0, column: literal.loc?.start.column ?? 0 };
|
|
125
|
+
const nodes = resolveLiteral(name, at, []);
|
|
126
|
+
const id = hash(`${sourceName}:css:${name}`);
|
|
127
|
+
plan.edits.push({ start: literal.start, end: literal.end, code: `({ $fxStyle: ${JSON.stringify(id)} })` });
|
|
128
|
+
if (nodes) plan.literals.push({ id, name, css: printStyle(nodes, options.minify) });
|
|
129
|
+
}
|
|
130
|
+
const scopeOf = /* @__PURE__ */ new Map();
|
|
131
|
+
const names = /* @__PURE__ */ new Map();
|
|
132
|
+
const named = /* @__PURE__ */ new Map();
|
|
133
|
+
const visit = (node, owners) => {
|
|
134
|
+
if (!node || typeof node !== "object") return;
|
|
135
|
+
if (node.type === "VariableDeclarator" && node.id.type === "Identifier" && node.init && FUNCTIONS.has(node.init.type)) {
|
|
136
|
+
named.set(node.init, node.id.name);
|
|
137
|
+
}
|
|
138
|
+
if ((node.type === "ClassDeclaration" || node.type === "ClassExpression") && node.id) {
|
|
139
|
+
for (const member of node.body.body) if (member.type === "ClassMethod") named.set(member, node.id.name);
|
|
140
|
+
}
|
|
141
|
+
if (node.type === "ClassDeclaration" || node.type === "ClassExpression") {
|
|
142
|
+
for (const member of node.body.body) if (member.type === "ClassMethod") classOf.set(member, node);
|
|
143
|
+
const shadow = staticMember(node, "shadow");
|
|
144
|
+
if (shadow?.value && !(shadow.value.type === "BooleanLiteral" && shadow.value.value === false)) {
|
|
145
|
+
plan.shadowClasses.set(node, { node, styles: staticMember(node, "styles"), indexes: [] });
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
if (node.type === "TaggedTemplateExpression" && node.tag.type === "Identifier" && tags.html.get(node.tag.name) === "html") {
|
|
149
|
+
const text = node.quasi.quasis.map((q) => q.value.raw).join("");
|
|
150
|
+
if (/<style[\s>]/.test(text)) {
|
|
151
|
+
const at = { line: node.loc?.start.line ?? 0, column: node.loc?.start.column ?? 0 };
|
|
152
|
+
const owner = owners[0];
|
|
153
|
+
if (!owner) plan.diagnostics.push({ ...at, message: "<style> has to be written inside a component." });
|
|
154
|
+
else {
|
|
155
|
+
const id = idFor(owner);
|
|
156
|
+
const shadow = shadowOf(owner);
|
|
157
|
+
plan.templateOwners.set(node.start, { id, component: functionName(owner, named) });
|
|
158
|
+
for (const block of templateBlocks(node.quasi)) compileBlock(block, block.scoped, owner, at);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
const inner = FUNCTIONS.has(node.type) ? [...owners, node] : owners;
|
|
163
|
+
if (node.type === "JSXElement" && isStyle(node)) {
|
|
164
|
+
handle(node, owners);
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
for (const key of Object.keys(node)) {
|
|
168
|
+
if (key === "loc" || key === "leadingComments" || key === "trailingComments" || key === "innerComments") continue;
|
|
169
|
+
const value = node[key];
|
|
170
|
+
if (Array.isArray(value)) for (const v of value) visit(v, inner);
|
|
171
|
+
else if (value && typeof value === "object" && "type" in value) visit(value, inner);
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
const handle = (node, owners) => {
|
|
175
|
+
const at = { line: node.loc?.start.line ?? 0, column: node.loc?.start.column ?? 0 };
|
|
176
|
+
const pieces = blockPieces(node);
|
|
177
|
+
if (pieces === null) {
|
|
178
|
+
plan.diagnostics.push({
|
|
179
|
+
...at,
|
|
180
|
+
message: "<style> needs its CSS as one template literal, <style>{`...`}</style>: JSX reads a bare `{` as an expression."
|
|
181
|
+
});
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
const owner = owners[0];
|
|
185
|
+
if (!owner) {
|
|
186
|
+
plan.diagnostics.push({ ...at, message: "<style> has to be written inside a component." });
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
compileBlock(pieces, isScoped(node), owner, at);
|
|
190
|
+
plan.drop.add(node.start);
|
|
191
|
+
};
|
|
192
|
+
const compileBlock = (pieces, scoped, owner, at) => {
|
|
193
|
+
const component = functionName(owner, named);
|
|
194
|
+
const id = idFor(owner);
|
|
195
|
+
const processed = piecesToNodes(pieces.quasis, pieces.expressions, at, []);
|
|
196
|
+
if (!processed) return;
|
|
197
|
+
let nodes = processed;
|
|
198
|
+
const shadow = shadowOf(owner);
|
|
199
|
+
if (scoped && !shadow) {
|
|
200
|
+
if (!plan.scopes.some((s) => s.value === id)) plan.scopes.push({ start: owner.start, end: owner.end, value: id });
|
|
201
|
+
nodes = scopeNodes(nodes, id, (message) => plan.diagnostics.push({ ...at, message }));
|
|
202
|
+
}
|
|
203
|
+
const printed = module2 ? printStyleWithMap(nodes, options.minify, sourceName, module2) : { css: printStyle(nodes, options.minify) };
|
|
204
|
+
plan.styles.push({ id, scoped: scoped && !shadow, component, ...printed, ...shadow ? { shadow: true } : {}, ...at });
|
|
205
|
+
if (shadow) shadow.indexes.push(plan.styles.length - 1);
|
|
206
|
+
};
|
|
207
|
+
function idFor(owner) {
|
|
208
|
+
let id = scopeOf.get(owner);
|
|
209
|
+
if (!id) {
|
|
210
|
+
const component = functionName(owner, named);
|
|
211
|
+
const seen = names.get(component) ?? 0;
|
|
212
|
+
names.set(component, seen + 1);
|
|
213
|
+
id = hash(`${sourceName}:${component}${seen ? ":" + seen : ""}`);
|
|
214
|
+
scopeOf.set(owner, id);
|
|
215
|
+
}
|
|
216
|
+
return id;
|
|
217
|
+
}
|
|
218
|
+
visit(program, []);
|
|
219
|
+
return plan;
|
|
220
|
+
}
|
|
221
|
+
function applyTemplateStyles(ir, t) {
|
|
222
|
+
const walk8 = (node) => {
|
|
223
|
+
const children = node.children;
|
|
224
|
+
if (children) {
|
|
225
|
+
for (let i = children.length - 1; i >= 0; i--) {
|
|
226
|
+
const child = children[i];
|
|
227
|
+
if (child.kind === "element" && child.tag === "style" && t.owner) children.splice(i, 1);
|
|
228
|
+
else walk8(child);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
if (t.scope && node.kind === "element" && node.tag !== "style" && node.props && !node.props.some((p) => p.name === SCOPE_ATTR)) {
|
|
232
|
+
node.props.unshift({ name: SCOPE_ATTR, kind: "attr", literal: t.scope });
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
walk8(ir);
|
|
236
|
+
}
|
|
237
|
+
function staticMember(cls, name) {
|
|
238
|
+
return cls.body.body.find(
|
|
239
|
+
(m) => m.type === "ClassProperty" && m.static && (m.key.type === "Identifier" && m.key.name === name || m.key.type === "StringLiteral" && m.key.value === name)
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
function finishShadowStyles(plan, code, moduleId) {
|
|
243
|
+
const edits = [];
|
|
244
|
+
const imports = [];
|
|
245
|
+
let next = 0;
|
|
246
|
+
const importOf = (specifier) => {
|
|
247
|
+
const local = `__fxShadow${next++}`;
|
|
248
|
+
imports.push(`import ${local} from ${JSON.stringify(specifier)};
|
|
249
|
+
`);
|
|
250
|
+
return local;
|
|
251
|
+
};
|
|
252
|
+
for (const shadow of plan.shadowClasses.values()) {
|
|
253
|
+
const blocks = shadow.indexes.map((i) => importOf(`${moduleId}?fx-style&index=${i}&inline&lang.css`));
|
|
254
|
+
let value;
|
|
255
|
+
const prop = shadow.styles;
|
|
256
|
+
if (prop?.value) {
|
|
257
|
+
const start = prop.value.start;
|
|
258
|
+
let text = code.slice(start, prop.value.end);
|
|
259
|
+
const replacements = [];
|
|
260
|
+
walkIdentifiers(prop.value, (id) => {
|
|
261
|
+
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;
|
|
262
|
+
if (local) replacements.push({ at: id.start - start, length: id.name.length, with: local });
|
|
263
|
+
});
|
|
264
|
+
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);
|
|
265
|
+
value = text;
|
|
266
|
+
}
|
|
267
|
+
if (!blocks.length && value === void 0) continue;
|
|
268
|
+
if (prop?.value) {
|
|
269
|
+
const merged = blocks.length ? `[${value}, ${blocks.join(", ")}]` : value;
|
|
270
|
+
edits.push({ start: prop.value.start, end: prop.value.end, code: merged });
|
|
271
|
+
} else if (blocks.length) {
|
|
272
|
+
const open = shadow.node.body.start + 1;
|
|
273
|
+
edits.push({ start: open, end: open, code: ` static styles = [${blocks.join(", ")}];` });
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
if (imports.length) edits.push({ start: 0, end: 0, code: imports.join("") });
|
|
277
|
+
return edits;
|
|
278
|
+
}
|
|
279
|
+
function walkIdentifiers(node, visit) {
|
|
280
|
+
if (!node || typeof node !== "object") return;
|
|
281
|
+
if (node.type === "Identifier") return visit(node);
|
|
282
|
+
if (node.type === "MemberExpression") return walkIdentifiers(node.object, visit);
|
|
283
|
+
if (node.type === "ObjectProperty") return walkIdentifiers(node.value, visit);
|
|
284
|
+
for (const key of Object.keys(node)) {
|
|
285
|
+
if (key === "loc") continue;
|
|
286
|
+
const value = node[key];
|
|
287
|
+
if (Array.isArray(value)) for (const v of value) walkIdentifiers(v, visit);
|
|
288
|
+
else if (value && typeof value === "object" && "type" in value) walkIdentifiers(value, visit);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
function isStyle(node) {
|
|
292
|
+
const name = node.openingElement.name;
|
|
293
|
+
return name.type === "JSXIdentifier" && name.name === "style";
|
|
294
|
+
}
|
|
295
|
+
function isScoped(node) {
|
|
296
|
+
return node.openingElement.attributes.some((a) => a.type === "JSXAttribute" && a.name.type === "JSXIdentifier" && a.name.name === "scoped");
|
|
297
|
+
}
|
|
298
|
+
function templateBlocks(quasi) {
|
|
299
|
+
const blocks = [];
|
|
300
|
+
let open = null;
|
|
301
|
+
quasi.quasis.forEach((q, i) => {
|
|
302
|
+
const raw = q.value.raw;
|
|
303
|
+
let from = 0;
|
|
304
|
+
while (from <= raw.length) {
|
|
305
|
+
if (!open) {
|
|
306
|
+
const tag = /<style\b([^>]*)>/g;
|
|
307
|
+
tag.lastIndex = from;
|
|
308
|
+
const m = tag.exec(raw);
|
|
309
|
+
if (!m) break;
|
|
310
|
+
open = { quasis: [], expressions: [], scoped: /\bscoped\b/.test(m[1]) };
|
|
311
|
+
from = m.index + m[0].length;
|
|
312
|
+
}
|
|
313
|
+
const close = raw.indexOf("</style", from);
|
|
314
|
+
open.quasis.push(slicePiece(q, raw, from, close === -1 ? raw.length : close));
|
|
315
|
+
if (close === -1) break;
|
|
316
|
+
blocks.push(open);
|
|
317
|
+
open = null;
|
|
318
|
+
from = close;
|
|
319
|
+
}
|
|
320
|
+
const expr = quasi.expressions[i];
|
|
321
|
+
if (open && expr) open.expressions.push(expr);
|
|
322
|
+
});
|
|
323
|
+
return blocks;
|
|
324
|
+
}
|
|
325
|
+
function slicePiece(q, raw, from, to) {
|
|
326
|
+
const text = raw.slice(from, to);
|
|
327
|
+
const start = q.loc?.start;
|
|
328
|
+
if (!start) return { type: "TemplateElement", value: { raw: text, cooked: text } };
|
|
329
|
+
const before = raw.slice(0, from).split("\n");
|
|
330
|
+
const line = start.line + before.length - 1;
|
|
331
|
+
const column = before.length > 1 ? before[before.length - 1].length : start.column + from;
|
|
332
|
+
return { type: "TemplateElement", value: { raw: text, cooked: text }, loc: { start: { line, column } } };
|
|
333
|
+
}
|
|
334
|
+
function blockPieces(node) {
|
|
335
|
+
const meaningful = node.children.filter((c) => !(c.type === "JSXText" && !c.value.trim()));
|
|
336
|
+
if (meaningful.length === 0) return { quasis: [], expressions: [] };
|
|
337
|
+
if (meaningful.length !== 1) return null;
|
|
338
|
+
const only = meaningful[0];
|
|
339
|
+
if (only.type !== "JSXExpressionContainer") return null;
|
|
340
|
+
const expr = only.expression;
|
|
341
|
+
if (expr.type === "StringLiteral") return { quasis: [{ type: "TemplateElement", value: { raw: expr.value, cooked: expr.value } }], expressions: [] };
|
|
342
|
+
if (expr.type === "TemplateLiteral") return { quasis: expr.quasis, expressions: expr.expressions };
|
|
343
|
+
return null;
|
|
344
|
+
}
|
|
345
|
+
function findLiterals(program, modules, plan, intrinsic) {
|
|
346
|
+
const literals = /* @__PURE__ */ new Map();
|
|
347
|
+
const imports = /* @__PURE__ */ new Map();
|
|
348
|
+
const tags = new Set(intrinsic);
|
|
349
|
+
for (const statement of program.body ?? []) {
|
|
350
|
+
if (statement.type !== "ImportDeclaration") continue;
|
|
351
|
+
const source = statement.source.value;
|
|
352
|
+
const specifiers = statement.specifiers;
|
|
353
|
+
for (const sp of specifiers) {
|
|
354
|
+
if (sp.type === "ImportSpecifier") imports.set(sp.local.name, { source, name: sp.imported.name ?? sp.imported.value });
|
|
355
|
+
}
|
|
356
|
+
if (!modules.includes(source)) continue;
|
|
357
|
+
const css = specifiers.find((sp) => sp.type === "ImportSpecifier" && (sp.imported.name ?? sp.imported.value) === "css");
|
|
358
|
+
if (!css) continue;
|
|
359
|
+
const local = css.local.name;
|
|
360
|
+
tags.add(local);
|
|
361
|
+
imports.delete(local);
|
|
362
|
+
plan.edits.push({ start: statement.start, end: statement.end, code: importWithout(statement, css) });
|
|
363
|
+
}
|
|
364
|
+
if (tags.size === 0) return { literals, imports };
|
|
365
|
+
const visit = (node) => {
|
|
366
|
+
if (!node || typeof node !== "object") return;
|
|
367
|
+
if (node.type === "VariableDeclarator" && node.id.type === "Identifier" && node.init?.type === "TaggedTemplateExpression" && node.init.tag.type === "Identifier" && tags.has(node.init.tag.name)) {
|
|
368
|
+
literals.set(node.id.name, node.init);
|
|
369
|
+
}
|
|
370
|
+
for (const key of Object.keys(node)) {
|
|
371
|
+
if (key === "loc") continue;
|
|
372
|
+
const value = node[key];
|
|
373
|
+
if (Array.isArray(value)) for (const v of value) visit(v);
|
|
374
|
+
else if (value && typeof value === "object" && "type" in value) visit(value);
|
|
375
|
+
}
|
|
376
|
+
};
|
|
377
|
+
visit(program);
|
|
378
|
+
return { literals, imports };
|
|
379
|
+
}
|
|
380
|
+
function importWithout(statement, removed) {
|
|
381
|
+
const rest = statement.specifiers.filter((sp) => sp !== removed);
|
|
382
|
+
const source = JSON.stringify(statement.source.value);
|
|
383
|
+
if (rest.length === 0) return "";
|
|
384
|
+
const def = rest.find((sp) => sp.type === "ImportDefaultSpecifier");
|
|
385
|
+
const ns = rest.find((sp) => sp.type === "ImportNamespaceSpecifier");
|
|
386
|
+
const named = rest.filter((sp) => sp.type === "ImportSpecifier").map((sp) => {
|
|
387
|
+
const imported = sp.imported.name ?? JSON.stringify(sp.imported.value);
|
|
388
|
+
return imported === sp.local.name ? imported : `${imported} as ${sp.local.name}`;
|
|
389
|
+
});
|
|
390
|
+
const parts = [def?.local.name, ns ? `* as ${ns.local.name}` : void 0, named.length ? `{ ${named.join(", ")} }` : void 0].filter(Boolean);
|
|
391
|
+
return `import ${parts.join(", ")} from ${source};`;
|
|
392
|
+
}
|
|
393
|
+
function functionName(fn, named) {
|
|
394
|
+
if ((fn.type === "FunctionDeclaration" || fn.type === "FunctionExpression") && fn.id) return fn.id.name;
|
|
395
|
+
return named.get(fn) ?? "anonymous";
|
|
396
|
+
}
|
|
397
|
+
function hash(text) {
|
|
398
|
+
let h = 2166136261;
|
|
399
|
+
for (let i = 0; i < text.length; i++) {
|
|
400
|
+
h ^= text.charCodeAt(i);
|
|
401
|
+
h = Math.imul(h, 16777619);
|
|
402
|
+
}
|
|
403
|
+
return (h >>> 0).toString(36);
|
|
404
|
+
}
|
|
405
|
+
var OPAQUE = /(^|-)keyframes$|^font-face$|^property$|^counter-style$|^page$|^font-feature-values$/;
|
|
406
|
+
function scopeNodes(nodes, id, warn = () => {
|
|
407
|
+
}) {
|
|
408
|
+
return nodes.map((node) => {
|
|
409
|
+
if (node.kind === "rule") return { ...node, selector: scopeSelector(node.selector, id, warn) };
|
|
410
|
+
if (node.kind === "at-rule" && !OPAQUE.test(node.name)) return { ...node, nodes: scopeNodes(node.nodes, id, warn) };
|
|
411
|
+
return node;
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
function scopeSelector(selector, id, warn = () => {
|
|
415
|
+
}) {
|
|
416
|
+
return splitTop(selector, ",").map((complex) => scopeComplex(complex.trim(), `[${SCOPE_ATTR}="${id}"]`, warn)).join(", ");
|
|
417
|
+
}
|
|
418
|
+
function scopeComplex(selector, attr, warn) {
|
|
419
|
+
if (/:host\b|::slotted\(/.test(selector)) {
|
|
420
|
+
warn(`\`${selector}\` only means something in a shadow root; in a light-DOM component it is left as written.`);
|
|
421
|
+
return selector;
|
|
422
|
+
}
|
|
423
|
+
const parts = compounds(selector);
|
|
424
|
+
const deep = parts.findIndex((p) => p.text.startsWith(":deep("));
|
|
425
|
+
if (deep !== -1) {
|
|
426
|
+
const inner = unwrap(parts[deep].text, ":deep(");
|
|
427
|
+
const before = parts.slice(0, deep);
|
|
428
|
+
if (before.length === 0) return `${attr} ${inner}`;
|
|
429
|
+
const scopedBefore = scopeAt(before, before.length - 1, attr);
|
|
430
|
+
return `${join(scopedBefore)} ${inner}`;
|
|
431
|
+
}
|
|
432
|
+
let target = -1;
|
|
433
|
+
for (let i = parts.length - 1; i >= 0; i--) {
|
|
434
|
+
if (!parts[i].text.startsWith(":global(")) {
|
|
435
|
+
target = i;
|
|
436
|
+
break;
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
const out = target === -1 ? parts : scopeAt(parts, target, attr);
|
|
440
|
+
return join(out.map((p) => p.text.startsWith(":global(") ? { ...p, text: unwrap(p.text, ":global(") } : p));
|
|
441
|
+
}
|
|
442
|
+
function scopeAt(parts, index, attr) {
|
|
443
|
+
return parts.map((p, i) => i === index ? { ...p, text: insertAttr(p.text, attr) } : p);
|
|
444
|
+
}
|
|
445
|
+
function insertAttr(compound, attr) {
|
|
446
|
+
let depth = 0;
|
|
447
|
+
let quote = "";
|
|
448
|
+
for (let i = 0; i < compound.length; i++) {
|
|
449
|
+
const c = compound[i];
|
|
450
|
+
if (quote) {
|
|
451
|
+
if (c === "\\") i++;
|
|
452
|
+
else if (c === quote) quote = "";
|
|
453
|
+
continue;
|
|
454
|
+
}
|
|
455
|
+
if (c === "\\") {
|
|
456
|
+
i++;
|
|
457
|
+
continue;
|
|
458
|
+
}
|
|
459
|
+
if (c === '"' || c === "'") quote = c;
|
|
460
|
+
else if (c === "(" || c === "[") depth++;
|
|
461
|
+
else if (c === ")" || c === "]") depth--;
|
|
462
|
+
else if (c === ":" && depth === 0 && i > 0) return compound.slice(0, i) + attr + compound.slice(i);
|
|
463
|
+
}
|
|
464
|
+
return compound + attr;
|
|
465
|
+
}
|
|
466
|
+
function compounds(selector) {
|
|
467
|
+
const out = [];
|
|
468
|
+
let depth = 0;
|
|
469
|
+
let quote = "";
|
|
470
|
+
let current = "";
|
|
471
|
+
let combinator = "";
|
|
472
|
+
const push = () => {
|
|
473
|
+
if (current.trim()) out.push({ combinator: out.length ? combinator || " " : "", text: current.trim() });
|
|
474
|
+
current = "";
|
|
475
|
+
combinator = "";
|
|
476
|
+
};
|
|
477
|
+
for (let i = 0; i < selector.length; i++) {
|
|
478
|
+
const c = selector[i];
|
|
479
|
+
if (quote) {
|
|
480
|
+
current += c;
|
|
481
|
+
if (c === "\\") current += selector[++i] ?? "";
|
|
482
|
+
else if (c === quote) quote = "";
|
|
483
|
+
continue;
|
|
484
|
+
}
|
|
485
|
+
if (c === "\\") {
|
|
486
|
+
current += c + (selector[++i] ?? "");
|
|
487
|
+
continue;
|
|
488
|
+
}
|
|
489
|
+
if (c === '"' || c === "'") quote = c;
|
|
490
|
+
if (c === "(" || c === "[") depth++;
|
|
491
|
+
if (c === ")" || c === "]") depth--;
|
|
492
|
+
if (depth === 0 && (c === ">" || c === "+" || c === "~")) {
|
|
493
|
+
push();
|
|
494
|
+
combinator = c;
|
|
495
|
+
continue;
|
|
496
|
+
}
|
|
497
|
+
if (depth === 0 && /\s/.test(c)) {
|
|
498
|
+
if (current.trim()) {
|
|
499
|
+
const keep = combinator;
|
|
500
|
+
push();
|
|
501
|
+
combinator = keep;
|
|
502
|
+
}
|
|
503
|
+
continue;
|
|
504
|
+
}
|
|
505
|
+
current += c;
|
|
506
|
+
}
|
|
507
|
+
push();
|
|
508
|
+
return out;
|
|
509
|
+
}
|
|
510
|
+
function join(parts) {
|
|
511
|
+
return parts.map((p, i) => i === 0 ? p.text : p.combinator === " " ? ` ${p.text}` : ` ${p.combinator} ${p.text}`).join("");
|
|
512
|
+
}
|
|
513
|
+
function unwrap(text, prefix) {
|
|
514
|
+
return text.slice(prefix.length, text.lastIndexOf(")")).trim() + text.slice(text.lastIndexOf(")") + 1);
|
|
515
|
+
}
|
|
516
|
+
function splitTop(selector, separator) {
|
|
517
|
+
const parts = [];
|
|
518
|
+
let depth = 0;
|
|
519
|
+
let quote = "";
|
|
520
|
+
let start = 0;
|
|
521
|
+
for (let i = 0; i < selector.length; i++) {
|
|
522
|
+
const c = selector[i];
|
|
523
|
+
if (quote) {
|
|
524
|
+
if (c === "\\") i++;
|
|
525
|
+
else if (c === quote) quote = "";
|
|
526
|
+
} else if (c === '"' || c === "'") quote = c;
|
|
527
|
+
else if (c === "\\") i++;
|
|
528
|
+
else if (c === "(" || c === "[") depth++;
|
|
529
|
+
else if (c === ")" || c === "]") depth--;
|
|
530
|
+
else if (c === separator && depth === 0) {
|
|
531
|
+
parts.push(selector.slice(start, i));
|
|
532
|
+
start = i + 1;
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
parts.push(selector.slice(start));
|
|
536
|
+
return parts.filter((p) => p.trim());
|
|
537
|
+
}
|
|
538
|
+
function shiftLoc(node, source, start) {
|
|
539
|
+
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;
|
|
540
|
+
if (node.kind === "rule" || node.kind === "at-rule") return { ...node, loc, nodes: node.nodes.map((n) => shiftLoc(n, source, start)) };
|
|
541
|
+
return { ...node, loc };
|
|
542
|
+
}
|
|
543
|
+
function dropLoc(node) {
|
|
544
|
+
const { loc: _loc, ...rest } = node;
|
|
545
|
+
if (rest.kind === "rule" || rest.kind === "at-rule") return { ...rest, nodes: rest.nodes.map(dropLoc) };
|
|
546
|
+
return rest;
|
|
547
|
+
}
|
|
548
|
+
function printStyleWithMap(nodes, minify, sourceName, module2) {
|
|
549
|
+
const lines = [[]];
|
|
550
|
+
let css = "";
|
|
551
|
+
let column = 0;
|
|
552
|
+
const emit = (text) => {
|
|
553
|
+
for (const ch of text) {
|
|
554
|
+
css += ch;
|
|
555
|
+
if (ch === "\n") {
|
|
556
|
+
lines.push([]);
|
|
557
|
+
column = 0;
|
|
558
|
+
} else column++;
|
|
559
|
+
}
|
|
560
|
+
};
|
|
561
|
+
const mark = (loc) => {
|
|
562
|
+
if (loc && loc.source === sourceName) lines[lines.length - 1].push([column, 0, loc.line - 1, loc.column]);
|
|
563
|
+
};
|
|
564
|
+
const write = (node, depth) => {
|
|
565
|
+
const pad = minify ? "" : " ".repeat(depth);
|
|
566
|
+
const nl = minify ? "" : "\n";
|
|
567
|
+
const sp = minify ? "" : " ";
|
|
568
|
+
emit(pad);
|
|
569
|
+
mark(node.loc);
|
|
570
|
+
if (node.kind === "declaration") {
|
|
571
|
+
emit(`${node.property}:${sp}${node.value}${node.important ? `${sp}!important` : ""};${nl}`);
|
|
572
|
+
} else if (node.kind === "raw") {
|
|
573
|
+
emit(`${node.text}${nl}`);
|
|
574
|
+
} else {
|
|
575
|
+
emit(`${node.kind === "rule" ? node.selector : `@${node.name}${node.params ? " " + node.params : ""}`}${sp}{${nl}`);
|
|
576
|
+
for (const child of node.nodes) write(child, depth + 1);
|
|
577
|
+
emit(`${pad}}${nl}`);
|
|
578
|
+
}
|
|
579
|
+
};
|
|
580
|
+
for (const node of nodes) write(node, 0);
|
|
581
|
+
return { css, map: { version: 3, sources: [module2.id], sourcesContent: [module2.code], names: [], mappings: (0, import_sourcemap_codec.encode)(lines) } };
|
|
582
|
+
}
|
|
583
|
+
function printStyle(nodes, minify = false) {
|
|
584
|
+
const out = [];
|
|
585
|
+
const write = (node, depth) => {
|
|
586
|
+
const pad = minify ? "" : " ".repeat(depth);
|
|
587
|
+
const nl = minify ? "" : "\n";
|
|
588
|
+
const sp = minify ? "" : " ";
|
|
589
|
+
if (node.kind === "declaration") {
|
|
590
|
+
out.push(`${pad}${node.property}:${sp}${node.value}${node.important ? `${sp}!important` : ""};${nl}`);
|
|
591
|
+
} else if (node.kind === "raw") {
|
|
592
|
+
out.push(`${pad}${node.text}${nl}`);
|
|
593
|
+
} else {
|
|
594
|
+
const header = node.kind === "rule" ? node.selector : `@${node.name}${node.params ? " " + node.params : ""}`;
|
|
595
|
+
out.push(`${pad}${header}${sp}{${nl}`);
|
|
596
|
+
for (const child of node.nodes) write(child, depth + 1);
|
|
597
|
+
out.push(`${pad}}${nl}`);
|
|
598
|
+
}
|
|
599
|
+
};
|
|
600
|
+
for (const node of nodes) write(node, 0);
|
|
601
|
+
return out.join("");
|
|
602
|
+
}
|
|
603
|
+
|
|
47
604
|
// src/optimize/analyze-static.ts
|
|
48
605
|
function propReason(prop) {
|
|
49
606
|
switch (prop.kind) {
|
|
@@ -489,6 +1046,7 @@ var INTRINSICS = {
|
|
|
489
1046
|
$effect: { export: "effect", module: REACTIVE_MODULE, returns: "effect" },
|
|
490
1047
|
$store: { export: "store", module: "@fluixi/reactive/store", returns: "store-handle" },
|
|
491
1048
|
$resource: { export: "resource", module: REACTIVE_MODULE, returns: "resource-handle" },
|
|
1049
|
+
$cachedResource: { export: "cachedResource", module: "@fluixi/reactive/cached-resource", returns: "resource-handle" },
|
|
492
1050
|
// No short runtime form for these yet, so the intrinsic stands for the `create*`
|
|
493
1051
|
// name. Still worth having: no import to write, and when a shorter form is
|
|
494
1052
|
// designed, the change is this line rather than a compiler pass.
|
|
@@ -499,6 +1057,19 @@ var INTRINSICS = {
|
|
|
499
1057
|
// dependency analysis must not guess at.
|
|
500
1058
|
$untrack: { export: "untrack", module: REACTIVE_MODULE, returns: "plain" },
|
|
501
1059
|
$untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" },
|
|
1060
|
+
// Scopes, scheduling and lifecycle: no value to classify, but the same authoring promise,
|
|
1061
|
+
// no import to write. `$cleanup` registers a callback on the current owner (`onCleanup`).
|
|
1062
|
+
$batch: { export: "batch", module: REACTIVE_MODULE, returns: "plain" },
|
|
1063
|
+
$cleanup: { export: "onCleanup", module: REACTIVE_MODULE, returns: "plain" },
|
|
1064
|
+
$root: { export: "root", module: REACTIVE_MODULE, returns: "plain" },
|
|
1065
|
+
$context: { export: "context", module: REACTIVE_MODULE, returns: "plain" },
|
|
1066
|
+
$renderEffect: { export: "renderEffect", module: REACTIVE_MODULE, returns: "effect" },
|
|
1067
|
+
$computed: { export: "computed", module: REACTIVE_MODULE, returns: "effect" },
|
|
1068
|
+
// Storage for where the code runs, and a signal kept in it. `$persisted` is a signal
|
|
1069
|
+
// handle as far as reads go: the same accessor with `set` on it.
|
|
1070
|
+
$storage: { export: "useStorage", module: "@fluixi/core/storage", returns: "plain" },
|
|
1071
|
+
$asyncStorage: { export: "useAsyncStorage", module: "@fluixi/core/storage", returns: "plain" },
|
|
1072
|
+
$persisted: { export: "persisted", module: "@fluixi/core/storage", returns: "signal-handle" },
|
|
502
1073
|
// An environment variable, public or server-only; the browser build refuses a secret.
|
|
503
1074
|
$env: { export: "env", module: "@fluixi/start/env", returns: "plain" }
|
|
504
1075
|
};
|
|
@@ -511,8 +1082,11 @@ var RUNTIME_PRIMITIVES = {
|
|
|
511
1082
|
createMemo: "memo-accessor",
|
|
512
1083
|
createEffect: "effect",
|
|
513
1084
|
createRenderEffect: "effect",
|
|
1085
|
+
renderEffect: "effect",
|
|
1086
|
+
computed: "effect",
|
|
514
1087
|
createStore: "reactive-object",
|
|
515
1088
|
resource: "resource-handle",
|
|
1089
|
+
cachedResource: "resource-handle",
|
|
516
1090
|
createResource: "reactive-object",
|
|
517
1091
|
createSelector: "memo-accessor",
|
|
518
1092
|
createDeferred: "memo-accessor"
|
|
@@ -521,8 +1095,19 @@ var PRIMITIVE_MODULES = [
|
|
|
521
1095
|
"@fluixi/reactive",
|
|
522
1096
|
"@fluixi/reactive/signal",
|
|
523
1097
|
"@fluixi/reactive/store",
|
|
1098
|
+
"@fluixi/reactive/cached-resource",
|
|
524
1099
|
"@fluixi/core"
|
|
525
1100
|
];
|
|
1101
|
+
var TAG_INTRINSICS = {
|
|
1102
|
+
$html: { export: "html", module: "@fluixi/core" },
|
|
1103
|
+
$svg: { export: "svg", module: "@fluixi/core" },
|
|
1104
|
+
$css: { export: "css", module: "@fluixi/core" }
|
|
1105
|
+
};
|
|
1106
|
+
function tagIntrinsics(bound) {
|
|
1107
|
+
const tags = /* @__PURE__ */ new Map();
|
|
1108
|
+
for (const [name, tag] of Object.entries(TAG_INTRINSICS)) if (!bound.has(name)) tags.set(name, tag.export);
|
|
1109
|
+
return tags;
|
|
1110
|
+
}
|
|
526
1111
|
var INTRINSIC_CALL = new RegExp(`\\$(?:${Object.keys(INTRINSICS).map((n) => n.slice(1)).join("|")})\\s*\\(`);
|
|
527
1112
|
function mayHaveIntrinsic(code) {
|
|
528
1113
|
return INTRINSIC_CALL.test(code);
|
|
@@ -656,6 +1241,7 @@ function resolveReactiveBindings(program) {
|
|
|
656
1241
|
// src/transform/source-locations.ts
|
|
657
1242
|
var SOURCE_MARKER = "__fx_source";
|
|
658
1243
|
var COMPONENT_MARKER = "__fx_component";
|
|
1244
|
+
var CLASS_MARKER = "__fx_class";
|
|
659
1245
|
var HOLE_MARKER = "__fx_hole";
|
|
660
1246
|
var markHole = (accessor, line, column, name) => `(globalThis.${HOLE_MARKER} ?? ((f) => f))(${accessor},${line},${column}${name === void 0 ? "" : `,${JSON.stringify(name)}`})`;
|
|
661
1247
|
var PROPS_MARKER = "__fx_props";
|
|
@@ -673,11 +1259,12 @@ var RUNTIME_PRIMITIVES2 = /* @__PURE__ */ new Set([
|
|
|
673
1259
|
"createStore",
|
|
674
1260
|
"createResource"
|
|
675
1261
|
]);
|
|
676
|
-
function
|
|
1262
|
+
function mayHaveSourceMarks(code) {
|
|
677
1263
|
for (const name of RUNTIME_PRIMITIVES2) {
|
|
678
1264
|
if (code.includes(name)) return true;
|
|
679
1265
|
}
|
|
680
|
-
|
|
1266
|
+
if (code.includes("$signal") || code.includes("$memo") || code.includes("$effect") || code.includes("$store")) return true;
|
|
1267
|
+
return /\bclass\b[^{;]*\bextends\b/.test(code);
|
|
681
1268
|
}
|
|
682
1269
|
var SINGLE_STATEMENT_PARENTS = /* @__PURE__ */ new Set([
|
|
683
1270
|
"IfStatement",
|
|
@@ -696,6 +1283,7 @@ function isLoneBranch(statement, parent) {
|
|
|
696
1283
|
function isExport(node) {
|
|
697
1284
|
return node.type === "ExportNamedDeclaration" || node.type === "ExportDefaultDeclaration";
|
|
698
1285
|
}
|
|
1286
|
+
var CLASS_FIELDS = /* @__PURE__ */ new Set(["PropertyDefinition", "ClassProperty", "ClassPrivateProperty", "AccessorProperty"]);
|
|
699
1287
|
function isStatement(node) {
|
|
700
1288
|
return node.type.endsWith("Statement") || node.type === "VariableDeclaration";
|
|
701
1289
|
}
|
|
@@ -716,6 +1304,14 @@ function walk3(node, visit, stack = []) {
|
|
|
716
1304
|
}
|
|
717
1305
|
function nameFor(stack) {
|
|
718
1306
|
const declarator = stack[stack.length - 1];
|
|
1307
|
+
if (declarator && CLASS_FIELDS.has(declarator.type)) {
|
|
1308
|
+
const key = declarator.key;
|
|
1309
|
+
if (key?.type === "Identifier" || key?.type === "PrivateIdentifier" || key?.type === "PrivateName") {
|
|
1310
|
+
const name = key.name ?? key.id?.name;
|
|
1311
|
+
return name;
|
|
1312
|
+
}
|
|
1313
|
+
return void 0;
|
|
1314
|
+
}
|
|
719
1315
|
if (declarator?.type !== "VariableDeclarator") return void 0;
|
|
720
1316
|
const id = declarator.id;
|
|
721
1317
|
if (id?.type === "Identifier") return id.name;
|
|
@@ -764,6 +1360,17 @@ function collectSourceEdits(program, filename) {
|
|
|
764
1360
|
});
|
|
765
1361
|
}
|
|
766
1362
|
}
|
|
1363
|
+
if ((node.type === "ClassDeclaration" || node.type === "ClassExpression") && node.superClass && !node.declare) {
|
|
1364
|
+
const at = node.loc?.start;
|
|
1365
|
+
const body = node.body;
|
|
1366
|
+
if (at && body) {
|
|
1367
|
+
edits.push({
|
|
1368
|
+
start: body.start + 1,
|
|
1369
|
+
end: body.start + 1,
|
|
1370
|
+
code: `static{globalThis.${CLASS_MARKER}?.(this,${JSON.stringify(filename)},${at.line},${at.column});}`
|
|
1371
|
+
});
|
|
1372
|
+
}
|
|
1373
|
+
}
|
|
767
1374
|
if (node.type !== "CallExpression") return;
|
|
768
1375
|
const callee = node.callee;
|
|
769
1376
|
if (callee?.type !== "Identifier") return;
|
|
@@ -773,6 +1380,26 @@ function collectSourceEdits(program, filename) {
|
|
|
773
1380
|
if (!intrinsic && !imported) return;
|
|
774
1381
|
const position = node.loc?.start;
|
|
775
1382
|
if (!position) return;
|
|
1383
|
+
for (let i = stack.length - 1; i >= 0; i--) {
|
|
1384
|
+
const up = stack[i];
|
|
1385
|
+
if (isStatement(up)) break;
|
|
1386
|
+
if (CLASS_FIELDS.has(up.type)) {
|
|
1387
|
+
if (claimed.has(node.start)) return;
|
|
1388
|
+
claimed.add(node.start);
|
|
1389
|
+
const label2 = nameFor(stack);
|
|
1390
|
+
const own = !up.static;
|
|
1391
|
+
const args2 = [
|
|
1392
|
+
JSON.stringify(filename),
|
|
1393
|
+
String(position.line),
|
|
1394
|
+
String(position.column),
|
|
1395
|
+
label2 ? JSON.stringify(label2) : own ? "undefined" : void 0,
|
|
1396
|
+
own ? "this" : void 0
|
|
1397
|
+
].filter((a) => a !== void 0).join(",");
|
|
1398
|
+
edits.push({ start: node.start, end: node.start, code: `(globalThis.${SOURCE_MARKER}?.(${args2}),` });
|
|
1399
|
+
edits.push({ start: node.end, end: node.end, code: ")" });
|
|
1400
|
+
return;
|
|
1401
|
+
}
|
|
1402
|
+
}
|
|
776
1403
|
let statement;
|
|
777
1404
|
let parent;
|
|
778
1405
|
let index = -1;
|
|
@@ -978,13 +1605,16 @@ function emitComponent(name, props, children, used, templates, at) {
|
|
|
978
1605
|
used.add("createComponent");
|
|
979
1606
|
const spreads = props.filter((p) => p.kind === "spread");
|
|
980
1607
|
const normal = props.filter((p) => p.kind !== "spread");
|
|
981
|
-
const
|
|
982
|
-
(p) => `get ${propKey(p.name)}() { return ${componentPropValue(p)}; }`
|
|
983
|
-
);
|
|
1608
|
+
const bodies = normal.map((p) => [p.name, componentPropValue(p)]);
|
|
984
1609
|
if (children.length > 0) {
|
|
985
|
-
|
|
1610
|
+
bodies.push(["children", emitChildren(children, used, templates)]);
|
|
1611
|
+
}
|
|
1612
|
+
let obj = `{ ${bodies.map(([name2, body]) => `get ${propKey(name2)}() { return ${body}; }`).join(", ")} }`;
|
|
1613
|
+
if (bodies.some(([, body]) => /\bthis\b/.test(body))) {
|
|
1614
|
+
const thunks = bodies.map(([name2, body]) => `${JSON.stringify(name2)}: () => (${body})`);
|
|
1615
|
+
const getters = bodies.map(([name2]) => `get ${propKey(name2)}() { return _$t[${JSON.stringify(name2)}](); }`);
|
|
1616
|
+
obj = `((_$t) => ({ ${getters.join(", ")} }))({ ${thunks.join(", ")} })`;
|
|
986
1617
|
}
|
|
987
|
-
let obj = `{ ${entries.join(", ")} }`;
|
|
988
1618
|
if (spreads.length > 0) {
|
|
989
1619
|
used.add("mergeProps");
|
|
990
1620
|
obj = `mergeProps(${spreads.map((s) => s.expr).join(", ")}, ${obj})`;
|
|
@@ -1066,7 +1696,8 @@ function emitNode(node, used, templates) {
|
|
|
1066
1696
|
} else {
|
|
1067
1697
|
used.add("spread");
|
|
1068
1698
|
const svgFlag = node.svg ? ", isSVG: true" : "";
|
|
1069
|
-
const
|
|
1699
|
+
const accessors = node.props.filter((p) => p.kind !== "spread" && p.expr !== void 0 && p.reactive && p.name !== "ref").map((p) => p.name);
|
|
1700
|
+
const customFlag = node.tag.includes("-") ? `, isCustomElement: true, accessors: ${JSON.stringify(accessors)}` : "";
|
|
1070
1701
|
parts.push(
|
|
1071
1702
|
`spread({ element: ${el}, props: ${emitProps(node.props, null, used)}${svgFlag}${customFlag} });`
|
|
1072
1703
|
);
|
|
@@ -1179,6 +1810,271 @@ function cleanTemplateText(value) {
|
|
|
1179
1810
|
return out;
|
|
1180
1811
|
}
|
|
1181
1812
|
|
|
1813
|
+
// src/lower/entities.ts
|
|
1814
|
+
var NAMED = {
|
|
1815
|
+
quot: 34,
|
|
1816
|
+
amp: 38,
|
|
1817
|
+
apos: 39,
|
|
1818
|
+
lt: 60,
|
|
1819
|
+
gt: 62,
|
|
1820
|
+
nbsp: 160,
|
|
1821
|
+
iexcl: 161,
|
|
1822
|
+
cent: 162,
|
|
1823
|
+
pound: 163,
|
|
1824
|
+
curren: 164,
|
|
1825
|
+
yen: 165,
|
|
1826
|
+
brvbar: 166,
|
|
1827
|
+
sect: 167,
|
|
1828
|
+
uml: 168,
|
|
1829
|
+
copy: 169,
|
|
1830
|
+
ordf: 170,
|
|
1831
|
+
laquo: 171,
|
|
1832
|
+
not: 172,
|
|
1833
|
+
shy: 173,
|
|
1834
|
+
reg: 174,
|
|
1835
|
+
macr: 175,
|
|
1836
|
+
deg: 176,
|
|
1837
|
+
plusmn: 177,
|
|
1838
|
+
sup2: 178,
|
|
1839
|
+
sup3: 179,
|
|
1840
|
+
acute: 180,
|
|
1841
|
+
micro: 181,
|
|
1842
|
+
para: 182,
|
|
1843
|
+
middot: 183,
|
|
1844
|
+
cedil: 184,
|
|
1845
|
+
sup1: 185,
|
|
1846
|
+
ordm: 186,
|
|
1847
|
+
raquo: 187,
|
|
1848
|
+
frac14: 188,
|
|
1849
|
+
frac12: 189,
|
|
1850
|
+
frac34: 190,
|
|
1851
|
+
iquest: 191,
|
|
1852
|
+
Agrave: 192,
|
|
1853
|
+
Aacute: 193,
|
|
1854
|
+
Acirc: 194,
|
|
1855
|
+
Atilde: 195,
|
|
1856
|
+
Auml: 196,
|
|
1857
|
+
Aring: 197,
|
|
1858
|
+
AElig: 198,
|
|
1859
|
+
Ccedil: 199,
|
|
1860
|
+
Egrave: 200,
|
|
1861
|
+
Eacute: 201,
|
|
1862
|
+
Ecirc: 202,
|
|
1863
|
+
Euml: 203,
|
|
1864
|
+
Igrave: 204,
|
|
1865
|
+
Iacute: 205,
|
|
1866
|
+
Icirc: 206,
|
|
1867
|
+
Iuml: 207,
|
|
1868
|
+
ETH: 208,
|
|
1869
|
+
Ntilde: 209,
|
|
1870
|
+
Ograve: 210,
|
|
1871
|
+
Oacute: 211,
|
|
1872
|
+
Ocirc: 212,
|
|
1873
|
+
Otilde: 213,
|
|
1874
|
+
Ouml: 214,
|
|
1875
|
+
times: 215,
|
|
1876
|
+
Oslash: 216,
|
|
1877
|
+
Ugrave: 217,
|
|
1878
|
+
Uacute: 218,
|
|
1879
|
+
Ucirc: 219,
|
|
1880
|
+
Uuml: 220,
|
|
1881
|
+
Yacute: 221,
|
|
1882
|
+
THORN: 222,
|
|
1883
|
+
szlig: 223,
|
|
1884
|
+
agrave: 224,
|
|
1885
|
+
aacute: 225,
|
|
1886
|
+
acirc: 226,
|
|
1887
|
+
atilde: 227,
|
|
1888
|
+
auml: 228,
|
|
1889
|
+
aring: 229,
|
|
1890
|
+
aelig: 230,
|
|
1891
|
+
ccedil: 231,
|
|
1892
|
+
egrave: 232,
|
|
1893
|
+
eacute: 233,
|
|
1894
|
+
ecirc: 234,
|
|
1895
|
+
euml: 235,
|
|
1896
|
+
igrave: 236,
|
|
1897
|
+
iacute: 237,
|
|
1898
|
+
icirc: 238,
|
|
1899
|
+
iuml: 239,
|
|
1900
|
+
eth: 240,
|
|
1901
|
+
ntilde: 241,
|
|
1902
|
+
ograve: 242,
|
|
1903
|
+
oacute: 243,
|
|
1904
|
+
ocirc: 244,
|
|
1905
|
+
otilde: 245,
|
|
1906
|
+
ouml: 246,
|
|
1907
|
+
divide: 247,
|
|
1908
|
+
oslash: 248,
|
|
1909
|
+
ugrave: 249,
|
|
1910
|
+
uacute: 250,
|
|
1911
|
+
ucirc: 251,
|
|
1912
|
+
uuml: 252,
|
|
1913
|
+
yacute: 253,
|
|
1914
|
+
thorn: 254,
|
|
1915
|
+
yuml: 255,
|
|
1916
|
+
OElig: 338,
|
|
1917
|
+
oelig: 339,
|
|
1918
|
+
Scaron: 352,
|
|
1919
|
+
scaron: 353,
|
|
1920
|
+
Yuml: 376,
|
|
1921
|
+
fnof: 402,
|
|
1922
|
+
circ: 710,
|
|
1923
|
+
tilde: 732,
|
|
1924
|
+
Alpha: 913,
|
|
1925
|
+
Beta: 914,
|
|
1926
|
+
Gamma: 915,
|
|
1927
|
+
Delta: 916,
|
|
1928
|
+
Epsilon: 917,
|
|
1929
|
+
Zeta: 918,
|
|
1930
|
+
Eta: 919,
|
|
1931
|
+
Theta: 920,
|
|
1932
|
+
Iota: 921,
|
|
1933
|
+
Kappa: 922,
|
|
1934
|
+
Lambda: 923,
|
|
1935
|
+
Mu: 924,
|
|
1936
|
+
Nu: 925,
|
|
1937
|
+
Xi: 926,
|
|
1938
|
+
Omicron: 927,
|
|
1939
|
+
Pi: 928,
|
|
1940
|
+
Rho: 929,
|
|
1941
|
+
Sigma: 931,
|
|
1942
|
+
Tau: 932,
|
|
1943
|
+
Upsilon: 933,
|
|
1944
|
+
Phi: 934,
|
|
1945
|
+
Chi: 935,
|
|
1946
|
+
Psi: 936,
|
|
1947
|
+
Omega: 937,
|
|
1948
|
+
alpha: 945,
|
|
1949
|
+
beta: 946,
|
|
1950
|
+
gamma: 947,
|
|
1951
|
+
delta: 948,
|
|
1952
|
+
epsilon: 949,
|
|
1953
|
+
zeta: 950,
|
|
1954
|
+
eta: 951,
|
|
1955
|
+
theta: 952,
|
|
1956
|
+
iota: 953,
|
|
1957
|
+
kappa: 954,
|
|
1958
|
+
lambda: 955,
|
|
1959
|
+
mu: 956,
|
|
1960
|
+
nu: 957,
|
|
1961
|
+
xi: 958,
|
|
1962
|
+
omicron: 959,
|
|
1963
|
+
pi: 960,
|
|
1964
|
+
rho: 961,
|
|
1965
|
+
sigmaf: 962,
|
|
1966
|
+
sigma: 963,
|
|
1967
|
+
tau: 964,
|
|
1968
|
+
upsilon: 965,
|
|
1969
|
+
phi: 966,
|
|
1970
|
+
chi: 967,
|
|
1971
|
+
psi: 968,
|
|
1972
|
+
omega: 969,
|
|
1973
|
+
thetasym: 977,
|
|
1974
|
+
upsih: 978,
|
|
1975
|
+
piv: 982,
|
|
1976
|
+
ensp: 8194,
|
|
1977
|
+
emsp: 8195,
|
|
1978
|
+
thinsp: 8201,
|
|
1979
|
+
zwnj: 8204,
|
|
1980
|
+
zwj: 8205,
|
|
1981
|
+
lrm: 8206,
|
|
1982
|
+
rlm: 8207,
|
|
1983
|
+
ndash: 8211,
|
|
1984
|
+
mdash: 8212,
|
|
1985
|
+
lsquo: 8216,
|
|
1986
|
+
rsquo: 8217,
|
|
1987
|
+
sbquo: 8218,
|
|
1988
|
+
ldquo: 8220,
|
|
1989
|
+
rdquo: 8221,
|
|
1990
|
+
bdquo: 8222,
|
|
1991
|
+
dagger: 8224,
|
|
1992
|
+
Dagger: 8225,
|
|
1993
|
+
bull: 8226,
|
|
1994
|
+
hellip: 8230,
|
|
1995
|
+
permil: 8240,
|
|
1996
|
+
prime: 8242,
|
|
1997
|
+
Prime: 8243,
|
|
1998
|
+
lsaquo: 8249,
|
|
1999
|
+
rsaquo: 8250,
|
|
2000
|
+
oline: 8254,
|
|
2001
|
+
frasl: 8260,
|
|
2002
|
+
euro: 8364,
|
|
2003
|
+
image: 8465,
|
|
2004
|
+
weierp: 8472,
|
|
2005
|
+
real: 8476,
|
|
2006
|
+
trade: 8482,
|
|
2007
|
+
alefsym: 8501,
|
|
2008
|
+
larr: 8592,
|
|
2009
|
+
uarr: 8593,
|
|
2010
|
+
rarr: 8594,
|
|
2011
|
+
darr: 8595,
|
|
2012
|
+
harr: 8596,
|
|
2013
|
+
crarr: 8629,
|
|
2014
|
+
lArr: 8656,
|
|
2015
|
+
uArr: 8657,
|
|
2016
|
+
rArr: 8658,
|
|
2017
|
+
dArr: 8659,
|
|
2018
|
+
hArr: 8660,
|
|
2019
|
+
forall: 8704,
|
|
2020
|
+
part: 8706,
|
|
2021
|
+
exist: 8707,
|
|
2022
|
+
empty: 8709,
|
|
2023
|
+
nabla: 8711,
|
|
2024
|
+
isin: 8712,
|
|
2025
|
+
notin: 8713,
|
|
2026
|
+
ni: 8715,
|
|
2027
|
+
prod: 8719,
|
|
2028
|
+
sum: 8721,
|
|
2029
|
+
minus: 8722,
|
|
2030
|
+
lowast: 8727,
|
|
2031
|
+
radic: 8730,
|
|
2032
|
+
prop: 8733,
|
|
2033
|
+
infin: 8734,
|
|
2034
|
+
ang: 8736,
|
|
2035
|
+
and: 8743,
|
|
2036
|
+
or: 8744,
|
|
2037
|
+
cap: 8745,
|
|
2038
|
+
cup: 8746,
|
|
2039
|
+
int: 8747,
|
|
2040
|
+
there4: 8756,
|
|
2041
|
+
sim: 8764,
|
|
2042
|
+
cong: 8773,
|
|
2043
|
+
asymp: 8776,
|
|
2044
|
+
ne: 8800,
|
|
2045
|
+
equiv: 8801,
|
|
2046
|
+
le: 8804,
|
|
2047
|
+
ge: 8805,
|
|
2048
|
+
sub: 8834,
|
|
2049
|
+
sup: 8835,
|
|
2050
|
+
nsub: 8836,
|
|
2051
|
+
sube: 8838,
|
|
2052
|
+
supe: 8839,
|
|
2053
|
+
oplus: 8853,
|
|
2054
|
+
otimes: 8855,
|
|
2055
|
+
perp: 8869,
|
|
2056
|
+
sdot: 8901,
|
|
2057
|
+
lceil: 8968,
|
|
2058
|
+
rceil: 8969,
|
|
2059
|
+
lfloor: 8970,
|
|
2060
|
+
rfloor: 8971,
|
|
2061
|
+
lang: 9001,
|
|
2062
|
+
rang: 9002,
|
|
2063
|
+
loz: 9674,
|
|
2064
|
+
spades: 9824,
|
|
2065
|
+
clubs: 9827,
|
|
2066
|
+
hearts: 9829,
|
|
2067
|
+
diams: 9830
|
|
2068
|
+
};
|
|
2069
|
+
var REFERENCE = /&(?:#[xX]([0-9a-fA-F]{1,6})|#([0-9]{1,7})|([a-zA-Z][a-zA-Z0-9]{1,31}));/g;
|
|
2070
|
+
function decodeEntities(value) {
|
|
2071
|
+
if (!value.includes("&")) return value;
|
|
2072
|
+
return value.replace(REFERENCE, (match, hex, dec, name) => {
|
|
2073
|
+
const code = hex ? parseInt(hex, 16) : dec ? parseInt(dec, 10) : Object.prototype.hasOwnProperty.call(NAMED, name) ? NAMED[name] : void 0;
|
|
2074
|
+
return code !== void 0 && code <= 1114111 ? String.fromCodePoint(code) : match;
|
|
2075
|
+
});
|
|
2076
|
+
}
|
|
2077
|
+
|
|
1182
2078
|
// src/lower/template.ts
|
|
1183
2079
|
var DELEGATED = /* @__PURE__ */ new Set([
|
|
1184
2080
|
"click",
|
|
@@ -1197,6 +2093,7 @@ var DELEGATED = /* @__PURE__ */ new Set([
|
|
|
1197
2093
|
function escapeTemplate(s) {
|
|
1198
2094
|
return s.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${");
|
|
1199
2095
|
}
|
|
2096
|
+
var CONTAINER = "container";
|
|
1200
2097
|
function capitalize(s) {
|
|
1201
2098
|
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
1202
2099
|
}
|
|
@@ -1251,10 +2148,6 @@ var Lowerer = class {
|
|
|
1251
2148
|
if (hasElse) i = elseIdx;
|
|
1252
2149
|
continue;
|
|
1253
2150
|
}
|
|
1254
|
-
if (child.attributes.some((a) => a.kind === "EachDirective")) {
|
|
1255
|
-
out.push(this.lowerEach(child));
|
|
1256
|
-
continue;
|
|
1257
|
-
}
|
|
1258
2151
|
}
|
|
1259
2152
|
const node = this.lowerNode(child);
|
|
1260
2153
|
if (node) out.push(node);
|
|
@@ -1268,7 +2161,7 @@ var Lowerer = class {
|
|
|
1268
2161
|
switch (node.kind) {
|
|
1269
2162
|
case "Text": {
|
|
1270
2163
|
if (node.raw) return { kind: "text", value: node.value };
|
|
1271
|
-
const cleaned = cleanTemplateText(node.value);
|
|
2164
|
+
const cleaned = decodeEntities(cleanTemplateText(node.value));
|
|
1272
2165
|
return cleaned ? { kind: "text", value: cleaned } : null;
|
|
1273
2166
|
}
|
|
1274
2167
|
case "Comment":
|
|
@@ -1296,13 +2189,16 @@ var Lowerer = class {
|
|
|
1296
2189
|
node.props.unshift({ name: "component", kind: "attr", expr: `() => ${paren(this.hole(isAttr.value.hole).code, "arrowBody")}` });
|
|
1297
2190
|
return node;
|
|
1298
2191
|
}
|
|
2192
|
+
const each = this.lowerEach(el);
|
|
2193
|
+
const children = each ? [each] : this.lowerChildren(el.children);
|
|
2194
|
+
if (el.tag === CONTAINER) return children.length === 1 ? children[0] : { kind: "fragment", children };
|
|
1299
2195
|
const at = this.tagAt(el);
|
|
1300
2196
|
return {
|
|
1301
2197
|
kind: "element",
|
|
1302
2198
|
tag: el.tag,
|
|
1303
2199
|
svg: el.namespace === "svg",
|
|
1304
|
-
props: this.lowerAttributes(el.attributes),
|
|
1305
|
-
children
|
|
2200
|
+
props: this.lowerAttributes(el.attributes, true),
|
|
2201
|
+
children,
|
|
1306
2202
|
static: false,
|
|
1307
2203
|
...at ? { at } : {}
|
|
1308
2204
|
};
|
|
@@ -1374,10 +2270,14 @@ var Lowerer = class {
|
|
|
1374
2270
|
const at = this.tagAt(el);
|
|
1375
2271
|
return { kind: "component", name: "Show", props, children: [child], ...at ? { at } : {}, ...cond.at ? { bindAt: cond.at } : {} };
|
|
1376
2272
|
}
|
|
1377
|
-
/**
|
|
2273
|
+
/**
|
|
2274
|
+
* `<el each=${items} key?>${item => …}</el>` → `<el><For each>{item => …}</For></el>`: the
|
|
2275
|
+
* content is repeated per item. Content that is not a `${item => …}` arrow is repeated as
|
|
2276
|
+
* it is. Null when the element has no `each`.
|
|
2277
|
+
*/
|
|
1378
2278
|
lowerEach(el) {
|
|
1379
2279
|
const eachDir = el.attributes.find((a) => a.kind === "EachDirective");
|
|
1380
|
-
if (!eachDir || eachDir.kind !== "EachDirective") return
|
|
2280
|
+
if (!eachDir || eachDir.kind !== "EachDirective") return null;
|
|
1381
2281
|
const each = this.hole(eachDir.hole);
|
|
1382
2282
|
const props = [{ name: "each", kind: "attr", expr: each.code, reactive: each.reactive, ...each.at ? { at: each.at } : {} }];
|
|
1383
2283
|
if (eachDir.key) {
|
|
@@ -1387,12 +2287,12 @@ var Lowerer = class {
|
|
|
1387
2287
|
const arrow = this.itemArrow(el);
|
|
1388
2288
|
let childrenCode;
|
|
1389
2289
|
if (arrow) {
|
|
1390
|
-
const
|
|
1391
|
-
|
|
1392
|
-
childrenCode = `(${arrow.params.join(", ")}) => ${paren(this.emit(repeated), "arrowBody")}`;
|
|
2290
|
+
const body = arrow.bodyReactive ? `() => ${paren(arrow.body, "arrowBody")}` : paren(arrow.body, "arrowBody");
|
|
2291
|
+
childrenCode = `(${arrow.params.join(", ")}) => ${body}`;
|
|
1393
2292
|
} else {
|
|
1394
|
-
const
|
|
1395
|
-
|
|
2293
|
+
const content = this.lowerChildren(el.children);
|
|
2294
|
+
const ir = content.length === 1 ? content[0] : { kind: "fragment", children: content };
|
|
2295
|
+
childrenCode = `() => ${paren(this.emit(ir), "arrowBody")}`;
|
|
1396
2296
|
}
|
|
1397
2297
|
const children = [{ kind: "expr", code: childrenCode, reactive: false }];
|
|
1398
2298
|
const at = this.tagAt(el);
|
|
@@ -1409,33 +2309,23 @@ var Lowerer = class {
|
|
|
1409
2309
|
const clone = { ...el, attributes: el.attributes.filter((a) => !drop(a)) };
|
|
1410
2310
|
return clone.kind === "Element" ? this.lowerElement(clone) : this.lowerComponent(clone);
|
|
1411
2311
|
}
|
|
1412
|
-
/** Same element (minus each/key) but with explicit IR children. */
|
|
1413
|
-
rebuildWithChildren(el, children) {
|
|
1414
|
-
const props = this.lowerAttributes(
|
|
1415
|
-
el.attributes.filter((a) => a.kind !== "EachDirective")
|
|
1416
|
-
);
|
|
1417
|
-
if (el.kind === "Element") {
|
|
1418
|
-
const at = this.tagAt(el);
|
|
1419
|
-
return {
|
|
1420
|
-
kind: "element",
|
|
1421
|
-
tag: el.tag,
|
|
1422
|
-
svg: el.namespace === "svg",
|
|
1423
|
-
props,
|
|
1424
|
-
children,
|
|
1425
|
-
static: false,
|
|
1426
|
-
...at ? { at } : {}
|
|
1427
|
-
};
|
|
1428
|
-
}
|
|
1429
|
-
return { kind: "component", name: el.tag, props, children };
|
|
1430
|
-
}
|
|
1431
2312
|
// --- attributes ---------------------------------------------------------
|
|
1432
|
-
|
|
2313
|
+
/**
|
|
2314
|
+
* `element`: a DOM element, where each class:/style: value that moves is its own accessor.
|
|
2315
|
+
* A component gets the object as before, rebuilt whole when any value moves.
|
|
2316
|
+
*/
|
|
2317
|
+
lowerAttributes(attrs, element = false) {
|
|
2318
|
+
let anyReactive = false;
|
|
2319
|
+
const entry = (name, h) => {
|
|
2320
|
+
anyReactive ||= h.reactive;
|
|
2321
|
+
if (!element || !h.reactive) return `${JSON.stringify(name)}: ${h.code}`;
|
|
2322
|
+
const accessor = `() => ${paren(h.code, "arrowBody")}`;
|
|
2323
|
+
return `${JSON.stringify(name)}: ${h.at ? markHole(accessor, h.at.line, h.at.column) : accessor}`;
|
|
2324
|
+
};
|
|
1433
2325
|
const props = [];
|
|
1434
2326
|
const classEntries = [];
|
|
1435
|
-
let classReactive = false;
|
|
1436
2327
|
let classAt;
|
|
1437
2328
|
const styleEntries = [];
|
|
1438
|
-
let styleReactive = false;
|
|
1439
2329
|
let styleAt;
|
|
1440
2330
|
const usePairs = [];
|
|
1441
2331
|
for (const a of attrs) {
|
|
@@ -1475,15 +2365,13 @@ var Lowerer = class {
|
|
|
1475
2365
|
break;
|
|
1476
2366
|
case "ClassDirective": {
|
|
1477
2367
|
const h = this.hole(a.hole);
|
|
1478
|
-
classEntries.push(
|
|
1479
|
-
classReactive = classReactive || h.reactive;
|
|
2368
|
+
classEntries.push(entry(a.name, h));
|
|
1480
2369
|
classAt ??= h.at;
|
|
1481
2370
|
break;
|
|
1482
2371
|
}
|
|
1483
2372
|
case "StyleDirective": {
|
|
1484
2373
|
const h = this.hole(a.hole);
|
|
1485
|
-
styleEntries.push(
|
|
1486
|
-
styleReactive = styleReactive || h.reactive;
|
|
2374
|
+
styleEntries.push(entry(a.name, h));
|
|
1487
2375
|
styleAt ??= h.at;
|
|
1488
2376
|
break;
|
|
1489
2377
|
}
|
|
@@ -1503,18 +2391,19 @@ var Lowerer = class {
|
|
|
1503
2391
|
name: "classList",
|
|
1504
2392
|
kind: "attr",
|
|
1505
2393
|
expr: `{ ${classEntries.join(", ")} }`,
|
|
1506
|
-
reactive:
|
|
2394
|
+
reactive: !element && anyReactive,
|
|
1507
2395
|
...classAt ? { at: classAt } : {}
|
|
1508
2396
|
});
|
|
1509
2397
|
}
|
|
1510
2398
|
if (styleEntries.length > 0) {
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
2399
|
+
const entries = `{ ${styleEntries.join(", ")} }`;
|
|
2400
|
+
const base = props.findIndex((p) => p.name === "style");
|
|
2401
|
+
if (base === -1) props.push({ name: "style", kind: "attr", expr: entries, reactive: !element && anyReactive, ...styleAt ? { at: styleAt } : {} });
|
|
2402
|
+
else {
|
|
2403
|
+
const prop = props[base];
|
|
2404
|
+
const value = prop.expr === void 0 ? JSON.stringify(prop.literal) : prop.reactive ? `() => ${paren(prop.expr, "arrowBody")}` : prop.expr;
|
|
2405
|
+
props[base] = { name: "style", kind: "attr", expr: `[${value}, ${entries}]`, reactive: false, ...prop.at ? { at: prop.at } : {} };
|
|
2406
|
+
}
|
|
1518
2407
|
}
|
|
1519
2408
|
if (usePairs.length > 0) {
|
|
1520
2409
|
props.push({ name: "use", kind: "attr", expr: `[${usePairs.join(", ")}]` });
|
|
@@ -1603,7 +2492,7 @@ var Lowerer = class {
|
|
|
1603
2492
|
return base;
|
|
1604
2493
|
}
|
|
1605
2494
|
if (v.kind === "static") {
|
|
1606
|
-
base.literal = v.value;
|
|
2495
|
+
base.literal = decodeEntities(v.value);
|
|
1607
2496
|
return base;
|
|
1608
2497
|
}
|
|
1609
2498
|
if (v.kind === "hole") {
|
|
@@ -1616,7 +2505,7 @@ var Lowerer = class {
|
|
|
1616
2505
|
let reactive = false;
|
|
1617
2506
|
let at;
|
|
1618
2507
|
const body = v.parts.map((p) => {
|
|
1619
|
-
if ("text" in p) return escapeTemplate(p.text);
|
|
2508
|
+
if ("text" in p) return escapeTemplate(decodeEntities(p.text));
|
|
1620
2509
|
const h = this.hole(p.hole);
|
|
1621
2510
|
reactive = reactive || h.reactive;
|
|
1622
2511
|
at ??= h.at;
|
|
@@ -1641,6 +2530,7 @@ function compilePieces(pieces, holes, options = {}) {
|
|
|
1641
2530
|
...options.sourceFile ? { sourceFile: options.sourceFile } : {},
|
|
1642
2531
|
...options.positionAt ? { positionAt: options.positionAt } : {}
|
|
1643
2532
|
});
|
|
2533
|
+
if (options.templateStyles) applyTemplateStyles(ir, options.templateStyles);
|
|
1644
2534
|
analyzeStatic(ir);
|
|
1645
2535
|
resolveComponentSources(ir, {
|
|
1646
2536
|
resolver: createComponentResolver(options.resolve ?? []),
|
|
@@ -1746,6 +2636,22 @@ var DELEGATED2 = /* @__PURE__ */ new Set([
|
|
|
1746
2636
|
"mouseup"
|
|
1747
2637
|
]);
|
|
1748
2638
|
var isReactive = (node) => isReactiveShape(shapeOf(node));
|
|
2639
|
+
var CONTAINER2 = "container";
|
|
2640
|
+
function directive(node, name) {
|
|
2641
|
+
if (node.type !== "JSXElement") return void 0;
|
|
2642
|
+
const opening = node.openingElement;
|
|
2643
|
+
if (opening.name.type !== "JSXIdentifier" || opening.name.name[0] !== opening.name.name[0].toLowerCase()) return void 0;
|
|
2644
|
+
return opening.attributes.find((a) => a.type === "JSXAttribute" && a.name.type === "JSXIdentifier" && a.name.name === name);
|
|
2645
|
+
}
|
|
2646
|
+
function directiveExpr(attr) {
|
|
2647
|
+
const v = attr.value;
|
|
2648
|
+
return v?.type === "JSXExpressionContainer" && v.expression?.type !== "JSXEmptyExpression" ? v.expression : void 0;
|
|
2649
|
+
}
|
|
2650
|
+
function emitIR(ir, ctx) {
|
|
2651
|
+
const { code, imports, templates } = imperativeBackend.emit(ir, {});
|
|
2652
|
+
for (const s of imports) ctx.used.add(s);
|
|
2653
|
+
return inlineTemplates(code, templates);
|
|
2654
|
+
}
|
|
1749
2655
|
var posOf = (node, ctx) => {
|
|
1750
2656
|
if (!ctx.sourceFile) return void 0;
|
|
1751
2657
|
const at = node.loc?.start;
|
|
@@ -1823,9 +2729,12 @@ function attrExprCode(attr, ctx) {
|
|
|
1823
2729
|
}
|
|
1824
2730
|
return null;
|
|
1825
2731
|
}
|
|
1826
|
-
function buildProps(attrs, ctx) {
|
|
2732
|
+
function buildProps(attrs, ctx, element = false) {
|
|
1827
2733
|
const props = [];
|
|
1828
2734
|
const usePairs = [];
|
|
2735
|
+
const classEntries = [];
|
|
2736
|
+
const styleEntries = [];
|
|
2737
|
+
let styleAt;
|
|
1829
2738
|
for (const a of attrs) {
|
|
1830
2739
|
if (a.type === "JSXSpreadAttribute") {
|
|
1831
2740
|
props.push({ name: "", kind: "spread", expr: ctx.code(a.argument) });
|
|
@@ -1841,6 +2750,27 @@ function buildProps(attrs, ctx) {
|
|
|
1841
2750
|
usePairs.push(opts != null ? `[${dir}, () => ${paren(opts, "arrowBody")}]` : `[${dir}]`);
|
|
1842
2751
|
continue;
|
|
1843
2752
|
}
|
|
2753
|
+
if (element && (ns === "class" || ns === "style")) {
|
|
2754
|
+
const key = JSON.stringify(a.name.name.name);
|
|
2755
|
+
const v = a.value;
|
|
2756
|
+
let value;
|
|
2757
|
+
if (v == null) value = "true";
|
|
2758
|
+
else if (isString(v)) value = JSON.stringify(literalOf(v));
|
|
2759
|
+
else if (v.type === "JSXExpressionContainer" && v.expression?.type !== "JSXEmptyExpression") {
|
|
2760
|
+
value = keyValue(v.expression, ctx);
|
|
2761
|
+
if (ns === "style") styleAt ??= posOf(v.expression, ctx);
|
|
2762
|
+
} else continue;
|
|
2763
|
+
(ns === "class" ? classEntries : styleEntries).push(`${key}: ${value}`);
|
|
2764
|
+
continue;
|
|
2765
|
+
}
|
|
2766
|
+
if (element && a.name.type === "JSXIdentifier" && a.name.name === "style" && a.value?.type === "JSXExpressionContainer") {
|
|
2767
|
+
const entries = objectEntries(a.value.expression, ctx);
|
|
2768
|
+
if (entries) {
|
|
2769
|
+
styleEntries.unshift(...entries);
|
|
2770
|
+
styleAt = posOf(a.value.expression, ctx);
|
|
2771
|
+
continue;
|
|
2772
|
+
}
|
|
2773
|
+
}
|
|
1844
2774
|
if (ns === "oncapture") {
|
|
1845
2775
|
const evt = a.name.name.name.toLowerCase();
|
|
1846
2776
|
const h = attrExprCode(a, ctx) ?? "undefined";
|
|
@@ -1849,12 +2779,49 @@ function buildProps(attrs, ctx) {
|
|
|
1849
2779
|
}
|
|
1850
2780
|
props.push(buildAttr(a, ctx));
|
|
1851
2781
|
}
|
|
2782
|
+
if (classEntries.length > 0) props.push({ name: "classList", kind: "attr", expr: `{ ${classEntries.join(", ")} }`, reactive: false });
|
|
2783
|
+
if (styleEntries.length > 0) {
|
|
2784
|
+
const entries = `{ ${styleEntries.join(", ")} }`;
|
|
2785
|
+
const base = props.findIndex((p) => p.name === "style" && p.kind === "attr");
|
|
2786
|
+
if (base === -1) props.push({ name: "style", kind: "attr", expr: entries, reactive: false, ...styleAt ? { at: styleAt } : {} });
|
|
2787
|
+
else {
|
|
2788
|
+
const prop = props[base];
|
|
2789
|
+
const value = prop.literal !== void 0 ? JSON.stringify(prop.literal) : prop.reactive ? `() => ${paren(prop.expr, "arrowBody")}` : prop.expr;
|
|
2790
|
+
props[base] = { name: "style", kind: "attr", expr: `[${value}, ${entries}]`, reactive: false, ...prop.at ? { at: prop.at } : {} };
|
|
2791
|
+
}
|
|
2792
|
+
}
|
|
1852
2793
|
if (usePairs.length > 0) props.push({ name: "use", kind: "attr", expr: `[${usePairs.join(", ")}]` });
|
|
1853
2794
|
return props;
|
|
1854
2795
|
}
|
|
2796
|
+
function keyValue(expr, ctx) {
|
|
2797
|
+
const code = ctx.code(expr);
|
|
2798
|
+
if (!isReactive(expr)) return code;
|
|
2799
|
+
const accessor = `() => ${paren(code, "arrowBody")}`;
|
|
2800
|
+
const at = posOf(expr, ctx);
|
|
2801
|
+
return at ? markHole(accessor, at.line, at.column) : accessor;
|
|
2802
|
+
}
|
|
2803
|
+
function objectEntries(expr, ctx) {
|
|
2804
|
+
if (expr?.type !== "ObjectExpression") return null;
|
|
2805
|
+
const entries = [];
|
|
2806
|
+
for (const p of expr.properties) {
|
|
2807
|
+
if (p.type !== "ObjectProperty") return null;
|
|
2808
|
+
const key = p.computed ? `[${ctx.code(p.key)}]` : p.key.type === "Identifier" ? JSON.stringify(p.key.name) : JSON.stringify(String(p.key.value));
|
|
2809
|
+
entries.push(`${key}: ${keyValue(p.value, ctx)}`);
|
|
2810
|
+
}
|
|
2811
|
+
return entries;
|
|
2812
|
+
}
|
|
1855
2813
|
function buildChildren(children, ctx) {
|
|
1856
2814
|
const out = [];
|
|
1857
|
-
for (
|
|
2815
|
+
for (let i = 0; i < children.length; i++) {
|
|
2816
|
+
const child = children[i];
|
|
2817
|
+
if (directive(child, "if")) {
|
|
2818
|
+
let next = i + 1;
|
|
2819
|
+
while (next < children.length && children[next].type === "JSXText" && !cleanTemplateText(children[next].value)) next++;
|
|
2820
|
+
const fallback = directive(children[next], "else") ? children[next] : null;
|
|
2821
|
+
out.push(buildIf(child, fallback, ctx));
|
|
2822
|
+
if (fallback) i = next;
|
|
2823
|
+
continue;
|
|
2824
|
+
}
|
|
1858
2825
|
if (child.type === "JSXText") {
|
|
1859
2826
|
const text = cleanTemplateText(child.value);
|
|
1860
2827
|
if (text) out.push({ kind: "text", value: text });
|
|
@@ -1870,6 +2837,7 @@ function buildChildren(children, ctx) {
|
|
|
1870
2837
|
});
|
|
1871
2838
|
}
|
|
1872
2839
|
} else if (child.type === "JSXElement" || child.type === "JSXFragment") {
|
|
2840
|
+
if (ctx.dropStyles?.has(child.start)) continue;
|
|
1873
2841
|
out.push(buildNode(child, ctx));
|
|
1874
2842
|
} else if (child.type === "JSXSpreadChild") {
|
|
1875
2843
|
out.push({ kind: "expr", code: ctx.code(child.expression), reactive: false });
|
|
@@ -1891,19 +2859,72 @@ function readLoad(attrs) {
|
|
|
1891
2859
|
}
|
|
1892
2860
|
return void 0;
|
|
1893
2861
|
}
|
|
2862
|
+
function buildIf(node, fallback, ctx) {
|
|
2863
|
+
const cond = directiveExpr(directive(node, "if"));
|
|
2864
|
+
const props = [
|
|
2865
|
+
cond ? { name: "when", kind: "attr", expr: ctx.code(cond), reactive: isReactive(cond), at: posOf(cond, ctx) } : { name: "when", kind: "attr", literal: true }
|
|
2866
|
+
];
|
|
2867
|
+
if (fallback) {
|
|
2868
|
+
props.push({ name: "fallback", kind: "attr", expr: emitIR(buildElement(fallback, ctx, ["else"]), ctx), jsxElement: true });
|
|
2869
|
+
}
|
|
2870
|
+
return { kind: "component", name: "Show", props, children: [buildElement(node, ctx, ["if"])] };
|
|
2871
|
+
}
|
|
2872
|
+
function buildEach(node, ctx) {
|
|
2873
|
+
const attr = directive(node, "each");
|
|
2874
|
+
if (!attr) return null;
|
|
2875
|
+
const list = directiveExpr(attr);
|
|
2876
|
+
const props = [
|
|
2877
|
+
list ? { name: "each", kind: "attr", expr: ctx.code(list), reactive: isReactive(list), at: posOf(list, ctx) } : { name: "each", kind: "attr", expr: "[]" }
|
|
2878
|
+
];
|
|
2879
|
+
const key = directive(node, "key");
|
|
2880
|
+
if (key) {
|
|
2881
|
+
const keyExpr = directiveExpr(key);
|
|
2882
|
+
const by = isString(key.value) ? `(item) => item[${JSON.stringify(literalOf(key.value))}]` : keyExpr ? ctx.code(keyExpr) : void 0;
|
|
2883
|
+
if (by) props.push({ name: "by", kind: "attr", expr: by });
|
|
2884
|
+
}
|
|
2885
|
+
const content = node.children.filter((c) => !(c.type === "JSXText" && !cleanTemplateText(c.value)));
|
|
2886
|
+
const only = content.length === 1 && content[0].type === "JSXExpressionContainer" ? content[0].expression : null;
|
|
2887
|
+
let render;
|
|
2888
|
+
if (only && (only.type === "ArrowFunctionExpression" || only.type === "FunctionExpression")) {
|
|
2889
|
+
const fn = ctx.code(only);
|
|
2890
|
+
const live = only.type === "ArrowFunctionExpression" && only.body.type !== "BlockStatement" && isReactive(only.body);
|
|
2891
|
+
render = live ? `(...args) => () => (${fn})(...args)` : fn;
|
|
2892
|
+
} else {
|
|
2893
|
+
const built = buildChildren(node.children, ctx);
|
|
2894
|
+
const ir = built.length === 1 ? built[0] : { kind: "fragment", children: built };
|
|
2895
|
+
render = `() => ${paren(emitIR(ir, ctx), "arrowBody")}`;
|
|
2896
|
+
}
|
|
2897
|
+
return { kind: "component", name: "For", props, children: [{ kind: "expr", code: render, reactive: false }] };
|
|
2898
|
+
}
|
|
2899
|
+
function buildElement(node, ctx, handled) {
|
|
2900
|
+
const skip = new Set(handled);
|
|
2901
|
+
const directives = /* @__PURE__ */ new Set(["if", "else", "each", ...directive(node, "each") ? ["key"] : []]);
|
|
2902
|
+
const attributes = node.openingElement.attributes.filter(
|
|
2903
|
+
(a) => !(a.type === "JSXAttribute" && a.name.type === "JSXIdentifier" && (skip.has(a.name.name) || directives.has(a.name.name)))
|
|
2904
|
+
);
|
|
2905
|
+
const { tag } = tagInfo(node.openingElement.name, ctx);
|
|
2906
|
+
const each = buildEach(node, ctx);
|
|
2907
|
+
const children = each ? [each] : buildChildren(node.children, ctx);
|
|
2908
|
+
if (tag === CONTAINER2) return children.length === 1 ? children[0] : { kind: "fragment", children };
|
|
2909
|
+
const at = ctx.sourceFile && node.loc?.start ? { file: ctx.sourceFile, line: node.loc.start.line, column: node.loc.start.column } : void 0;
|
|
2910
|
+
const props = buildProps(attributes, ctx, true);
|
|
2911
|
+
const scope = ctx.scopes?.find((s) => node.start >= s.start && node.end <= s.end);
|
|
2912
|
+
if (scope) props.unshift({ name: "data-fx-s", kind: "attr", literal: scope.value });
|
|
2913
|
+
return { kind: "element", tag, svg: SVG_TAGS.has(tag), props, children, static: false, ...at ? { at } : {} };
|
|
2914
|
+
}
|
|
1894
2915
|
function buildNode(node, ctx) {
|
|
1895
2916
|
if (node.type === "JSXFragment") {
|
|
1896
2917
|
return { kind: "fragment", children: buildChildren(node.children, ctx) };
|
|
1897
2918
|
}
|
|
2919
|
+
if (directive(node, "if")) return buildIf(node, null, ctx);
|
|
2920
|
+
if (ctx.dropStyles?.has(node.start)) return { kind: "fragment", children: [] };
|
|
1898
2921
|
const { tag, component } = tagInfo(node.openingElement.name, ctx);
|
|
2922
|
+
if (!component) return buildElement(node, ctx, []);
|
|
1899
2923
|
const props = buildProps(node.openingElement.attributes, ctx);
|
|
1900
2924
|
const children = buildChildren(node.children, ctx);
|
|
1901
2925
|
const at = ctx.sourceFile && node.loc?.start ? { file: ctx.sourceFile, line: node.loc.start.line, column: node.loc.start.column } : void 0;
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
return { kind: "component", name: tag, props, children, ...load ? { load } : {}, ...at ? { at } : {} };
|
|
1905
|
-
}
|
|
1906
|
-
return { kind: "element", tag, svg: SVG_TAGS.has(tag), props, children, static: false, ...at ? { at } : {} };
|
|
2926
|
+
const load = readLoad(node.openingElement.attributes);
|
|
2927
|
+
return { kind: "component", name: tag, props, children, ...load ? { load } : {}, ...at ? { at } : {} };
|
|
1907
2928
|
}
|
|
1908
2929
|
function buildJsxIR(node, ctx) {
|
|
1909
2930
|
const ir = buildNode(node, ctx);
|
|
@@ -2425,8 +3446,8 @@ function isJsxRoot(node, parent, key) {
|
|
|
2425
3446
|
if (!isJsx(node)) return false;
|
|
2426
3447
|
return !(parent && isJsx(parent) && key === "children");
|
|
2427
3448
|
}
|
|
2428
|
-
function isTemplateTag(node,
|
|
2429
|
-
return node.type === "TaggedTemplateExpression" && node.tag?.type === "Identifier" && (node.tag.name
|
|
3449
|
+
function isTemplateTag(node, tags) {
|
|
3450
|
+
return node.type === "TaggedTemplateExpression" && node.tag?.type === "Identifier" && tags.has(node.tag.name);
|
|
2430
3451
|
}
|
|
2431
3452
|
function outermost(list) {
|
|
2432
3453
|
return list.filter(
|
|
@@ -2572,24 +3593,30 @@ function transformTemplates(code, id, options = {}) {
|
|
|
2572
3593
|
const wantsJsx = format !== "lit";
|
|
2573
3594
|
const mayHaveTemplate = wantsLit && (code.includes(`${litTag}\``) || code.includes("svg`"));
|
|
2574
3595
|
const wantsIntrinsics = options.intrinsics !== false && mayHaveIntrinsic(code);
|
|
2575
|
-
const wantsSources = options.sourceLocations === true &&
|
|
3596
|
+
const wantsSources = options.sourceLocations === true && mayHaveSourceMarks(code);
|
|
2576
3597
|
const sourceName = relativeToRoot(id, options.sourceRoot);
|
|
2577
|
-
|
|
3598
|
+
const wantsStyles = options.styles !== void 0 && (code.includes("<style") || code.includes("css`"));
|
|
3599
|
+
if (!mayHaveTemplate && !(wantsJsx && code.includes("<")) && !wantsIntrinsics && !wantsSources && !wantsStyles) return null;
|
|
2578
3600
|
const ast = (0, import_parser2.parse)(code, {
|
|
2579
3601
|
sourceType: "module",
|
|
2580
3602
|
plugins: ["jsx", "typescript"],
|
|
2581
3603
|
errorRecovery: true
|
|
2582
3604
|
});
|
|
3605
|
+
const intrinsicTags = options.intrinsics === false ? /* @__PURE__ */ new Map() : tagIntrinsics(moduleBindings(ast.program));
|
|
3606
|
+
const templateTags = /* @__PURE__ */ new Map([[litTag, "html"], ["svg", "svg"]]);
|
|
3607
|
+
for (const [name, tag] of intrinsicTags) if (tag !== "css") templateTags.set(name, tag);
|
|
3608
|
+
const cssTags = [...intrinsicTags].filter(([, tag]) => tag === "css").map(([name]) => name);
|
|
2583
3609
|
const found = [];
|
|
2584
3610
|
walk7(ast.program, (n, parent, key) => {
|
|
2585
|
-
if (wantsLit && isTemplateTag(n,
|
|
3611
|
+
if (wantsLit && isTemplateTag(n, templateTags)) found.push(n);
|
|
2586
3612
|
else if (wantsJsx && isJsxRoot(n, parent, key)) found.push(n);
|
|
2587
3613
|
});
|
|
2588
3614
|
const props = options.propsDestructure === false ? { edits: [], diagnostics: [], used: /* @__PURE__ */ new Set() } : collectPropsEdits(ast.program, code, { runtimeModule: options.runtimeModule });
|
|
2589
3615
|
const intrinsics = options.intrinsics === false ? { edits: [], diagnostics: [], imports: /* @__PURE__ */ new Map() } : collectIntrinsicEdits(ast.program);
|
|
2590
3616
|
if (intrinsics.edits.length) avoidBindingClashes(ast.program, intrinsics, moduleBindings(ast.program));
|
|
2591
3617
|
const sources = options.sourceLocations === true ? collectSourceEdits(ast.program, sourceName) : { edits: [], marked: 0 };
|
|
2592
|
-
const
|
|
3618
|
+
const styles = wantsStyles ? collectStyles(ast.program, sourceName, options.styles, { html: templateTags, css: cssTags }, { id, code }) : void 0;
|
|
3619
|
+
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;
|
|
2593
3620
|
if (silent) return null;
|
|
2594
3621
|
found.sort((a, b) => b.start - a.start || a.end - b.end);
|
|
2595
3622
|
const used = new Set(props.used);
|
|
@@ -2603,20 +3630,32 @@ function transformTemplates(code, id, options = {}) {
|
|
|
2603
3630
|
declared: declaredNames(ast.program)
|
|
2604
3631
|
};
|
|
2605
3632
|
const hoisted = /* @__PURE__ */ new Map();
|
|
2606
|
-
const edits = [...props.edits, ...intrinsics.edits, ...sources.edits];
|
|
3633
|
+
const edits = [...props.edits, ...intrinsics.edits, ...sources.edits, ...styles?.edits ?? []];
|
|
2607
3634
|
for (const node of found) {
|
|
2608
3635
|
const nested = found.some(
|
|
2609
3636
|
(o) => o !== node && o.start <= node.start && o.end >= node.end && o.end - o.start > node.end - node.start
|
|
2610
3637
|
);
|
|
2611
3638
|
if (isJsx(node)) {
|
|
2612
|
-
edits.push({ start: node.start, end: node.end, code: compileJsx(code, node, edits, nested, used, needs, hoisted, options, sourceName) });
|
|
3639
|
+
edits.push({ start: node.start, end: node.end, code: compileJsx(code, node, edits, nested, used, needs, hoisted, options, sourceName, styles) });
|
|
2613
3640
|
continue;
|
|
2614
3641
|
}
|
|
2615
3642
|
const holes = node.quasi.expressions.map(
|
|
2616
3643
|
(e) => bindHole(code, e, edits, options.sourceLocations === true)
|
|
2617
3644
|
);
|
|
3645
|
+
const scope = styles?.scopes.find((s) => node.start >= s.start && node.end <= s.end)?.value;
|
|
3646
|
+
const owner = styles?.templateOwners.get(node.start);
|
|
3647
|
+
const templateStyles = options.styles && styles && (scope || owner) ? {
|
|
3648
|
+
options: options.styles,
|
|
3649
|
+
...scope ? { scope } : {},
|
|
3650
|
+
...owner ? { owner } : {},
|
|
3651
|
+
line: node.loc?.start.line ?? 0,
|
|
3652
|
+
column: node.loc?.start.column ?? 0,
|
|
3653
|
+
styles: styles.styles,
|
|
3654
|
+
diagnostics: styles.diagnostics
|
|
3655
|
+
} : void 0;
|
|
2618
3656
|
const result = compilePieces(toPieces(node), holes, {
|
|
2619
3657
|
...options,
|
|
3658
|
+
...templateStyles ? { templateStyles } : {},
|
|
2620
3659
|
hoistTemplates: true,
|
|
2621
3660
|
// A tag inside a template gets the same mark a JSX tag does. Without one, the nodes it
|
|
2622
3661
|
// makes are the only ones in the module carrying no mark, and they take whichever was
|
|
@@ -2625,12 +3664,13 @@ function transformTemplates(code, id, options = {}) {
|
|
|
2625
3664
|
// Same defaults as the plugin, so moving a build over is not a rendering change.
|
|
2626
3665
|
templateClone: options.templateClone ?? true,
|
|
2627
3666
|
partialTemplates: nested ? false : options.partialTemplates ?? true,
|
|
2628
|
-
svg: node.tag.name === "svg"
|
|
3667
|
+
svg: templateTags.get(node.tag.name) === "svg"
|
|
2629
3668
|
});
|
|
2630
3669
|
for (const symbol of result.imports) used.add(symbol);
|
|
2631
3670
|
collectNeeds(result.ir, needs);
|
|
2632
3671
|
edits.push({ start: node.start, end: node.end, code: adoptTemplates(result.code, result.templates, hoisted) });
|
|
2633
3672
|
}
|
|
3673
|
+
if (styles && options.styles) edits.push(...finishShadowStyles(styles, code, id));
|
|
2634
3674
|
const out = new import_magic_string2.default(code);
|
|
2635
3675
|
for (const e of outermost(edits)) {
|
|
2636
3676
|
if (e.start === e.end) out.appendLeft(e.start, e.code);
|
|
@@ -2688,13 +3728,19 @@ function transformTemplates(code, id, options = {}) {
|
|
|
2688
3728
|
...loadDiagnostics.length ? { loadDiagnostics } : {},
|
|
2689
3729
|
...unresolvedDiagnostics.length ? { unresolvedDiagnostics } : {},
|
|
2690
3730
|
...props.diagnostics.length ? { propsDiagnostics: props.diagnostics } : {},
|
|
2691
|
-
...intrinsics.diagnostics.length ? { intrinsicDiagnostics: intrinsics.diagnostics } : {}
|
|
3731
|
+
...intrinsics.diagnostics.length ? { intrinsicDiagnostics: intrinsics.diagnostics } : {},
|
|
3732
|
+
...styles?.styles.length ? { styles: styles.styles } : {},
|
|
3733
|
+
...styles?.diagnostics.length ? { styleDiagnostics: styles.diagnostics } : {},
|
|
3734
|
+
...styles?.literals.length ? { styleLiterals: styles.literals } : {},
|
|
3735
|
+
...styles?.references.length ? { styleReferences: styles.references } : {}
|
|
2692
3736
|
};
|
|
2693
3737
|
}
|
|
2694
|
-
function compileJsx(code, node, edits, nested, used, needs, hoisted, options, sourceFile) {
|
|
3738
|
+
function compileJsx(code, node, edits, nested, used, needs, hoisted, options, sourceFile, styles) {
|
|
2695
3739
|
const ir = buildJsxIR(node, {
|
|
2696
3740
|
code: (n) => slice(code, n.start, n.end, edits),
|
|
2697
3741
|
used,
|
|
3742
|
+
...styles?.scopes.length ? { scopes: styles.scopes } : {},
|
|
3743
|
+
...styles?.drop.size ? { dropStyles: styles.drop } : {},
|
|
2698
3744
|
...options.sourceLocations === true && sourceFile ? { sourceFile } : {}
|
|
2699
3745
|
});
|
|
2700
3746
|
analyzeStatic(ir);
|