@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
|
@@ -36,6 +36,563 @@ module.exports = __toCommonJS(templates_exports);
|
|
|
36
36
|
var import_parser2 = require("@babel/parser");
|
|
37
37
|
var import_magic_string2 = __toESM(require("magic-string"), 1);
|
|
38
38
|
|
|
39
|
+
// src/transform/styles.ts
|
|
40
|
+
var import_sourcemap_codec = require("@jridgewell/sourcemap-codec");
|
|
41
|
+
var SCOPE_ATTR = "data-fx-s";
|
|
42
|
+
var FUNCTIONS = /* @__PURE__ */ new Set(["FunctionDeclaration", "FunctionExpression", "ArrowFunctionExpression", "ObjectMethod", "ClassMethod"]);
|
|
43
|
+
function collectStyles(program, sourceName, options, tags = { html: /* @__PURE__ */ new Map([["html", "html"]]) }, module2) {
|
|
44
|
+
const plan = {
|
|
45
|
+
scopes: [],
|
|
46
|
+
templateOwners: /* @__PURE__ */ new Map(),
|
|
47
|
+
drop: /* @__PURE__ */ new Set(),
|
|
48
|
+
styles: [],
|
|
49
|
+
diagnostics: [],
|
|
50
|
+
edits: [],
|
|
51
|
+
literals: [],
|
|
52
|
+
references: [],
|
|
53
|
+
shadowClasses: /* @__PURE__ */ new Map()
|
|
54
|
+
};
|
|
55
|
+
if (!options) return plan;
|
|
56
|
+
const literalsOf = findLiterals(program, options.cssModules ?? ["@fluixi/core", "@fluixi/dom"], plan, tags.css ?? []);
|
|
57
|
+
plan.names = literalsOf;
|
|
58
|
+
const classOf = /* @__PURE__ */ new Map();
|
|
59
|
+
const shadowOf = (owner) => {
|
|
60
|
+
const cls = classOf.get(owner);
|
|
61
|
+
return cls ? plan.shadowClasses.get(cls) : void 0;
|
|
62
|
+
};
|
|
63
|
+
const resolved = /* @__PURE__ */ new Map();
|
|
64
|
+
const piecesToNodes = (quasis, expressions, at, stack) => {
|
|
65
|
+
const out = [];
|
|
66
|
+
for (let i = 0; i < quasis.length; i++) {
|
|
67
|
+
const text = quasis[i].value.cooked ?? quasis[i].value.raw;
|
|
68
|
+
if (text.trim()) {
|
|
69
|
+
try {
|
|
70
|
+
const start = quasis[i].loc?.start;
|
|
71
|
+
out.push(...options.process(text, sourceName).map((n) => start ? shiftLoc(n, sourceName, start) : n));
|
|
72
|
+
} catch (error) {
|
|
73
|
+
plan.diagnostics.push({ ...at, message: `CSS could not be processed: ${error.message}` });
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
const expr = expressions[i];
|
|
78
|
+
if (!expr) continue;
|
|
79
|
+
const value = expr.type === "Identifier" ? resolveLiteral(expr.name, at, stack) : void 0;
|
|
80
|
+
if (value === void 0) {
|
|
81
|
+
plan.diagnostics.push({
|
|
82
|
+
...at,
|
|
83
|
+
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))."
|
|
84
|
+
});
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
if (value === null) return null;
|
|
88
|
+
out.push(...value);
|
|
89
|
+
}
|
|
90
|
+
return out;
|
|
91
|
+
};
|
|
92
|
+
function resolveLiteral(name, at, stack) {
|
|
93
|
+
const imported = literalsOf.imports.get(name);
|
|
94
|
+
if (imported) {
|
|
95
|
+
const nodes = options?.imported?.get(`${imported.source}#${imported.name}`);
|
|
96
|
+
if (nodes) return nodes.map(dropLoc);
|
|
97
|
+
plan.references.push({ name: imported.name, source: imported.source, ...at });
|
|
98
|
+
plan.diagnostics.push({
|
|
99
|
+
...at,
|
|
100
|
+
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.`
|
|
101
|
+
});
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
const literal = literalsOf.literals.get(name);
|
|
105
|
+
if (!literal) return void 0;
|
|
106
|
+
if (stack.includes(name)) {
|
|
107
|
+
plan.diagnostics.push({ ...at, message: `css\`\` values include each other: ${[...stack, name].join(" → ")}.` });
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
if (!resolved.has(name)) {
|
|
111
|
+
resolved.set(name, piecesToNodes(literal.quasi.quasis, literal.quasi.expressions, at, [...stack, name]));
|
|
112
|
+
}
|
|
113
|
+
return resolved.get(name);
|
|
114
|
+
}
|
|
115
|
+
for (const [name, literal] of literalsOf.literals) {
|
|
116
|
+
const at = { line: literal.loc?.start.line ?? 0, column: literal.loc?.start.column ?? 0 };
|
|
117
|
+
const nodes = resolveLiteral(name, at, []);
|
|
118
|
+
const id = hash(`${sourceName}:css:${name}`);
|
|
119
|
+
plan.edits.push({ start: literal.start, end: literal.end, code: `({ $fxStyle: ${JSON.stringify(id)} })` });
|
|
120
|
+
if (nodes) plan.literals.push({ id, name, css: printStyle(nodes, options.minify) });
|
|
121
|
+
}
|
|
122
|
+
const scopeOf = /* @__PURE__ */ new Map();
|
|
123
|
+
const names = /* @__PURE__ */ new Map();
|
|
124
|
+
const named = /* @__PURE__ */ new Map();
|
|
125
|
+
const visit = (node, owners) => {
|
|
126
|
+
if (!node || typeof node !== "object") return;
|
|
127
|
+
if (node.type === "VariableDeclarator" && node.id.type === "Identifier" && node.init && FUNCTIONS.has(node.init.type)) {
|
|
128
|
+
named.set(node.init, node.id.name);
|
|
129
|
+
}
|
|
130
|
+
if ((node.type === "ClassDeclaration" || node.type === "ClassExpression") && node.id) {
|
|
131
|
+
for (const member of node.body.body) if (member.type === "ClassMethod") named.set(member, node.id.name);
|
|
132
|
+
}
|
|
133
|
+
if (node.type === "ClassDeclaration" || node.type === "ClassExpression") {
|
|
134
|
+
for (const member of node.body.body) if (member.type === "ClassMethod") classOf.set(member, node);
|
|
135
|
+
const shadow = staticMember(node, "shadow");
|
|
136
|
+
if (shadow?.value && !(shadow.value.type === "BooleanLiteral" && shadow.value.value === false)) {
|
|
137
|
+
plan.shadowClasses.set(node, { node, styles: staticMember(node, "styles"), indexes: [] });
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
if (node.type === "TaggedTemplateExpression" && node.tag.type === "Identifier" && tags.html.get(node.tag.name) === "html") {
|
|
141
|
+
const text = node.quasi.quasis.map((q) => q.value.raw).join("");
|
|
142
|
+
if (/<style[\s>]/.test(text)) {
|
|
143
|
+
const at = { line: node.loc?.start.line ?? 0, column: node.loc?.start.column ?? 0 };
|
|
144
|
+
const owner = owners[0];
|
|
145
|
+
if (!owner) plan.diagnostics.push({ ...at, message: "<style> has to be written inside a component." });
|
|
146
|
+
else {
|
|
147
|
+
const id = idFor(owner);
|
|
148
|
+
const shadow = shadowOf(owner);
|
|
149
|
+
plan.templateOwners.set(node.start, { id, component: functionName(owner, named) });
|
|
150
|
+
for (const block of templateBlocks(node.quasi)) compileBlock(block, block.scoped, owner, at);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
const inner = FUNCTIONS.has(node.type) ? [...owners, node] : owners;
|
|
155
|
+
if (node.type === "JSXElement" && isStyle(node)) {
|
|
156
|
+
handle(node, owners);
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
for (const key of Object.keys(node)) {
|
|
160
|
+
if (key === "loc" || key === "leadingComments" || key === "trailingComments" || key === "innerComments") continue;
|
|
161
|
+
const value = node[key];
|
|
162
|
+
if (Array.isArray(value)) for (const v of value) visit(v, inner);
|
|
163
|
+
else if (value && typeof value === "object" && "type" in value) visit(value, inner);
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
const handle = (node, owners) => {
|
|
167
|
+
const at = { line: node.loc?.start.line ?? 0, column: node.loc?.start.column ?? 0 };
|
|
168
|
+
const pieces = blockPieces(node);
|
|
169
|
+
if (pieces === null) {
|
|
170
|
+
plan.diagnostics.push({
|
|
171
|
+
...at,
|
|
172
|
+
message: "<style> needs its CSS as one template literal, <style>{`...`}</style>: JSX reads a bare `{` as an expression."
|
|
173
|
+
});
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
const owner = owners[0];
|
|
177
|
+
if (!owner) {
|
|
178
|
+
plan.diagnostics.push({ ...at, message: "<style> has to be written inside a component." });
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
compileBlock(pieces, isScoped(node), owner, at);
|
|
182
|
+
plan.drop.add(node.start);
|
|
183
|
+
};
|
|
184
|
+
const compileBlock = (pieces, scoped, owner, at) => {
|
|
185
|
+
const component = functionName(owner, named);
|
|
186
|
+
const id = idFor(owner);
|
|
187
|
+
const processed = piecesToNodes(pieces.quasis, pieces.expressions, at, []);
|
|
188
|
+
if (!processed) return;
|
|
189
|
+
let nodes = processed;
|
|
190
|
+
const shadow = shadowOf(owner);
|
|
191
|
+
if (scoped && !shadow) {
|
|
192
|
+
if (!plan.scopes.some((s) => s.value === id)) plan.scopes.push({ start: owner.start, end: owner.end, value: id });
|
|
193
|
+
nodes = scopeNodes(nodes, id, (message) => plan.diagnostics.push({ ...at, message }));
|
|
194
|
+
}
|
|
195
|
+
const printed = module2 ? printStyleWithMap(nodes, options.minify, sourceName, module2) : { css: printStyle(nodes, options.minify) };
|
|
196
|
+
plan.styles.push({ id, scoped: scoped && !shadow, component, ...printed, ...shadow ? { shadow: true } : {}, ...at });
|
|
197
|
+
if (shadow) shadow.indexes.push(plan.styles.length - 1);
|
|
198
|
+
};
|
|
199
|
+
function idFor(owner) {
|
|
200
|
+
let id = scopeOf.get(owner);
|
|
201
|
+
if (!id) {
|
|
202
|
+
const component = functionName(owner, named);
|
|
203
|
+
const seen = names.get(component) ?? 0;
|
|
204
|
+
names.set(component, seen + 1);
|
|
205
|
+
id = hash(`${sourceName}:${component}${seen ? ":" + seen : ""}`);
|
|
206
|
+
scopeOf.set(owner, id);
|
|
207
|
+
}
|
|
208
|
+
return id;
|
|
209
|
+
}
|
|
210
|
+
visit(program, []);
|
|
211
|
+
return plan;
|
|
212
|
+
}
|
|
213
|
+
function applyTemplateStyles(ir, t) {
|
|
214
|
+
const walk8 = (node) => {
|
|
215
|
+
const children = node.children;
|
|
216
|
+
if (children) {
|
|
217
|
+
for (let i = children.length - 1; i >= 0; i--) {
|
|
218
|
+
const child = children[i];
|
|
219
|
+
if (child.kind === "element" && child.tag === "style" && t.owner) children.splice(i, 1);
|
|
220
|
+
else walk8(child);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
if (t.scope && node.kind === "element" && node.tag !== "style" && node.props && !node.props.some((p) => p.name === SCOPE_ATTR)) {
|
|
224
|
+
node.props.unshift({ name: SCOPE_ATTR, kind: "attr", literal: t.scope });
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
walk8(ir);
|
|
228
|
+
}
|
|
229
|
+
function staticMember(cls, name) {
|
|
230
|
+
return cls.body.body.find(
|
|
231
|
+
(m) => m.type === "ClassProperty" && m.static && (m.key.type === "Identifier" && m.key.name === name || m.key.type === "StringLiteral" && m.key.value === name)
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
function finishShadowStyles(plan, code, moduleId) {
|
|
235
|
+
const edits = [];
|
|
236
|
+
const imports = [];
|
|
237
|
+
let next = 0;
|
|
238
|
+
const importOf = (specifier) => {
|
|
239
|
+
const local = `__fxShadow${next++}`;
|
|
240
|
+
imports.push(`import ${local} from ${JSON.stringify(specifier)};
|
|
241
|
+
`);
|
|
242
|
+
return local;
|
|
243
|
+
};
|
|
244
|
+
for (const shadow of plan.shadowClasses.values()) {
|
|
245
|
+
const blocks = shadow.indexes.map((i) => importOf(`${moduleId}?fx-style&index=${i}&inline&lang.css`));
|
|
246
|
+
let value;
|
|
247
|
+
const prop = shadow.styles;
|
|
248
|
+
if (prop?.value) {
|
|
249
|
+
const start = prop.value.start;
|
|
250
|
+
let text = code.slice(start, prop.value.end);
|
|
251
|
+
const replacements = [];
|
|
252
|
+
walkIdentifiers(prop.value, (id) => {
|
|
253
|
+
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;
|
|
254
|
+
if (local) replacements.push({ at: id.start - start, length: id.name.length, with: local });
|
|
255
|
+
});
|
|
256
|
+
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);
|
|
257
|
+
value = text;
|
|
258
|
+
}
|
|
259
|
+
if (!blocks.length && value === void 0) continue;
|
|
260
|
+
if (prop?.value) {
|
|
261
|
+
const merged = blocks.length ? `[${value}, ${blocks.join(", ")}]` : value;
|
|
262
|
+
edits.push({ start: prop.value.start, end: prop.value.end, code: merged });
|
|
263
|
+
} else if (blocks.length) {
|
|
264
|
+
const open = shadow.node.body.start + 1;
|
|
265
|
+
edits.push({ start: open, end: open, code: ` static styles = [${blocks.join(", ")}];` });
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
if (imports.length) edits.push({ start: 0, end: 0, code: imports.join("") });
|
|
269
|
+
return edits;
|
|
270
|
+
}
|
|
271
|
+
function walkIdentifiers(node, visit) {
|
|
272
|
+
if (!node || typeof node !== "object") return;
|
|
273
|
+
if (node.type === "Identifier") return visit(node);
|
|
274
|
+
if (node.type === "MemberExpression") return walkIdentifiers(node.object, visit);
|
|
275
|
+
if (node.type === "ObjectProperty") return walkIdentifiers(node.value, visit);
|
|
276
|
+
for (const key of Object.keys(node)) {
|
|
277
|
+
if (key === "loc") continue;
|
|
278
|
+
const value = node[key];
|
|
279
|
+
if (Array.isArray(value)) for (const v of value) walkIdentifiers(v, visit);
|
|
280
|
+
else if (value && typeof value === "object" && "type" in value) walkIdentifiers(value, visit);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
function isStyle(node) {
|
|
284
|
+
const name = node.openingElement.name;
|
|
285
|
+
return name.type === "JSXIdentifier" && name.name === "style";
|
|
286
|
+
}
|
|
287
|
+
function isScoped(node) {
|
|
288
|
+
return node.openingElement.attributes.some((a) => a.type === "JSXAttribute" && a.name.type === "JSXIdentifier" && a.name.name === "scoped");
|
|
289
|
+
}
|
|
290
|
+
function templateBlocks(quasi) {
|
|
291
|
+
const blocks = [];
|
|
292
|
+
let open = null;
|
|
293
|
+
quasi.quasis.forEach((q, i) => {
|
|
294
|
+
const raw = q.value.raw;
|
|
295
|
+
let from = 0;
|
|
296
|
+
while (from <= raw.length) {
|
|
297
|
+
if (!open) {
|
|
298
|
+
const tag = /<style\b([^>]*)>/g;
|
|
299
|
+
tag.lastIndex = from;
|
|
300
|
+
const m = tag.exec(raw);
|
|
301
|
+
if (!m) break;
|
|
302
|
+
open = { quasis: [], expressions: [], scoped: /\bscoped\b/.test(m[1]) };
|
|
303
|
+
from = m.index + m[0].length;
|
|
304
|
+
}
|
|
305
|
+
const close = raw.indexOf("</style", from);
|
|
306
|
+
open.quasis.push(slicePiece(q, raw, from, close === -1 ? raw.length : close));
|
|
307
|
+
if (close === -1) break;
|
|
308
|
+
blocks.push(open);
|
|
309
|
+
open = null;
|
|
310
|
+
from = close;
|
|
311
|
+
}
|
|
312
|
+
const expr = quasi.expressions[i];
|
|
313
|
+
if (open && expr) open.expressions.push(expr);
|
|
314
|
+
});
|
|
315
|
+
return blocks;
|
|
316
|
+
}
|
|
317
|
+
function slicePiece(q, raw, from, to) {
|
|
318
|
+
const text = raw.slice(from, to);
|
|
319
|
+
const start = q.loc?.start;
|
|
320
|
+
if (!start) return { type: "TemplateElement", value: { raw: text, cooked: text } };
|
|
321
|
+
const before = raw.slice(0, from).split("\n");
|
|
322
|
+
const line = start.line + before.length - 1;
|
|
323
|
+
const column = before.length > 1 ? before[before.length - 1].length : start.column + from;
|
|
324
|
+
return { type: "TemplateElement", value: { raw: text, cooked: text }, loc: { start: { line, column } } };
|
|
325
|
+
}
|
|
326
|
+
function blockPieces(node) {
|
|
327
|
+
const meaningful = node.children.filter((c) => !(c.type === "JSXText" && !c.value.trim()));
|
|
328
|
+
if (meaningful.length === 0) return { quasis: [], expressions: [] };
|
|
329
|
+
if (meaningful.length !== 1) return null;
|
|
330
|
+
const only = meaningful[0];
|
|
331
|
+
if (only.type !== "JSXExpressionContainer") return null;
|
|
332
|
+
const expr = only.expression;
|
|
333
|
+
if (expr.type === "StringLiteral") return { quasis: [{ type: "TemplateElement", value: { raw: expr.value, cooked: expr.value } }], expressions: [] };
|
|
334
|
+
if (expr.type === "TemplateLiteral") return { quasis: expr.quasis, expressions: expr.expressions };
|
|
335
|
+
return null;
|
|
336
|
+
}
|
|
337
|
+
function findLiterals(program, modules, plan, intrinsic) {
|
|
338
|
+
const literals = /* @__PURE__ */ new Map();
|
|
339
|
+
const imports = /* @__PURE__ */ new Map();
|
|
340
|
+
const tags = new Set(intrinsic);
|
|
341
|
+
for (const statement of program.body ?? []) {
|
|
342
|
+
if (statement.type !== "ImportDeclaration") continue;
|
|
343
|
+
const source = statement.source.value;
|
|
344
|
+
const specifiers = statement.specifiers;
|
|
345
|
+
for (const sp of specifiers) {
|
|
346
|
+
if (sp.type === "ImportSpecifier") imports.set(sp.local.name, { source, name: sp.imported.name ?? sp.imported.value });
|
|
347
|
+
}
|
|
348
|
+
if (!modules.includes(source)) continue;
|
|
349
|
+
const css = specifiers.find((sp) => sp.type === "ImportSpecifier" && (sp.imported.name ?? sp.imported.value) === "css");
|
|
350
|
+
if (!css) continue;
|
|
351
|
+
const local = css.local.name;
|
|
352
|
+
tags.add(local);
|
|
353
|
+
imports.delete(local);
|
|
354
|
+
plan.edits.push({ start: statement.start, end: statement.end, code: importWithout(statement, css) });
|
|
355
|
+
}
|
|
356
|
+
if (tags.size === 0) return { literals, imports };
|
|
357
|
+
const visit = (node) => {
|
|
358
|
+
if (!node || typeof node !== "object") return;
|
|
359
|
+
if (node.type === "VariableDeclarator" && node.id.type === "Identifier" && node.init?.type === "TaggedTemplateExpression" && node.init.tag.type === "Identifier" && tags.has(node.init.tag.name)) {
|
|
360
|
+
literals.set(node.id.name, node.init);
|
|
361
|
+
}
|
|
362
|
+
for (const key of Object.keys(node)) {
|
|
363
|
+
if (key === "loc") continue;
|
|
364
|
+
const value = node[key];
|
|
365
|
+
if (Array.isArray(value)) for (const v of value) visit(v);
|
|
366
|
+
else if (value && typeof value === "object" && "type" in value) visit(value);
|
|
367
|
+
}
|
|
368
|
+
};
|
|
369
|
+
visit(program);
|
|
370
|
+
return { literals, imports };
|
|
371
|
+
}
|
|
372
|
+
function importWithout(statement, removed) {
|
|
373
|
+
const rest = statement.specifiers.filter((sp) => sp !== removed);
|
|
374
|
+
const source = JSON.stringify(statement.source.value);
|
|
375
|
+
if (rest.length === 0) return "";
|
|
376
|
+
const def = rest.find((sp) => sp.type === "ImportDefaultSpecifier");
|
|
377
|
+
const ns = rest.find((sp) => sp.type === "ImportNamespaceSpecifier");
|
|
378
|
+
const named = rest.filter((sp) => sp.type === "ImportSpecifier").map((sp) => {
|
|
379
|
+
const imported = sp.imported.name ?? JSON.stringify(sp.imported.value);
|
|
380
|
+
return imported === sp.local.name ? imported : `${imported} as ${sp.local.name}`;
|
|
381
|
+
});
|
|
382
|
+
const parts = [def?.local.name, ns ? `* as ${ns.local.name}` : void 0, named.length ? `{ ${named.join(", ")} }` : void 0].filter(Boolean);
|
|
383
|
+
return `import ${parts.join(", ")} from ${source};`;
|
|
384
|
+
}
|
|
385
|
+
function functionName(fn, named) {
|
|
386
|
+
if ((fn.type === "FunctionDeclaration" || fn.type === "FunctionExpression") && fn.id) return fn.id.name;
|
|
387
|
+
return named.get(fn) ?? "anonymous";
|
|
388
|
+
}
|
|
389
|
+
function hash(text) {
|
|
390
|
+
let h = 2166136261;
|
|
391
|
+
for (let i = 0; i < text.length; i++) {
|
|
392
|
+
h ^= text.charCodeAt(i);
|
|
393
|
+
h = Math.imul(h, 16777619);
|
|
394
|
+
}
|
|
395
|
+
return (h >>> 0).toString(36);
|
|
396
|
+
}
|
|
397
|
+
var OPAQUE = /(^|-)keyframes$|^font-face$|^property$|^counter-style$|^page$|^font-feature-values$/;
|
|
398
|
+
function scopeNodes(nodes, id, warn = () => {
|
|
399
|
+
}) {
|
|
400
|
+
return nodes.map((node) => {
|
|
401
|
+
if (node.kind === "rule") return { ...node, selector: scopeSelector(node.selector, id, warn) };
|
|
402
|
+
if (node.kind === "at-rule" && !OPAQUE.test(node.name)) return { ...node, nodes: scopeNodes(node.nodes, id, warn) };
|
|
403
|
+
return node;
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
function scopeSelector(selector, id, warn = () => {
|
|
407
|
+
}) {
|
|
408
|
+
return splitTop(selector, ",").map((complex) => scopeComplex(complex.trim(), `[${SCOPE_ATTR}="${id}"]`, warn)).join(", ");
|
|
409
|
+
}
|
|
410
|
+
function scopeComplex(selector, attr, warn) {
|
|
411
|
+
if (/:host\b|::slotted\(/.test(selector)) {
|
|
412
|
+
warn(`\`${selector}\` only means something in a shadow root; in a light-DOM component it is left as written.`);
|
|
413
|
+
return selector;
|
|
414
|
+
}
|
|
415
|
+
const parts = compounds(selector);
|
|
416
|
+
const deep = parts.findIndex((p) => p.text.startsWith(":deep("));
|
|
417
|
+
if (deep !== -1) {
|
|
418
|
+
const inner = unwrap(parts[deep].text, ":deep(");
|
|
419
|
+
const before = parts.slice(0, deep);
|
|
420
|
+
if (before.length === 0) return `${attr} ${inner}`;
|
|
421
|
+
const scopedBefore = scopeAt(before, before.length - 1, attr);
|
|
422
|
+
return `${join(scopedBefore)} ${inner}`;
|
|
423
|
+
}
|
|
424
|
+
let target = -1;
|
|
425
|
+
for (let i = parts.length - 1; i >= 0; i--) {
|
|
426
|
+
if (!parts[i].text.startsWith(":global(")) {
|
|
427
|
+
target = i;
|
|
428
|
+
break;
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
const out = target === -1 ? parts : scopeAt(parts, target, attr);
|
|
432
|
+
return join(out.map((p) => p.text.startsWith(":global(") ? { ...p, text: unwrap(p.text, ":global(") } : p));
|
|
433
|
+
}
|
|
434
|
+
function scopeAt(parts, index, attr) {
|
|
435
|
+
return parts.map((p, i) => i === index ? { ...p, text: insertAttr(p.text, attr) } : p);
|
|
436
|
+
}
|
|
437
|
+
function insertAttr(compound, attr) {
|
|
438
|
+
let depth = 0;
|
|
439
|
+
let quote = "";
|
|
440
|
+
for (let i = 0; i < compound.length; i++) {
|
|
441
|
+
const c = compound[i];
|
|
442
|
+
if (quote) {
|
|
443
|
+
if (c === "\\") i++;
|
|
444
|
+
else if (c === quote) quote = "";
|
|
445
|
+
continue;
|
|
446
|
+
}
|
|
447
|
+
if (c === "\\") {
|
|
448
|
+
i++;
|
|
449
|
+
continue;
|
|
450
|
+
}
|
|
451
|
+
if (c === '"' || c === "'") quote = c;
|
|
452
|
+
else if (c === "(" || c === "[") depth++;
|
|
453
|
+
else if (c === ")" || c === "]") depth--;
|
|
454
|
+
else if (c === ":" && depth === 0 && i > 0) return compound.slice(0, i) + attr + compound.slice(i);
|
|
455
|
+
}
|
|
456
|
+
return compound + attr;
|
|
457
|
+
}
|
|
458
|
+
function compounds(selector) {
|
|
459
|
+
const out = [];
|
|
460
|
+
let depth = 0;
|
|
461
|
+
let quote = "";
|
|
462
|
+
let current = "";
|
|
463
|
+
let combinator = "";
|
|
464
|
+
const push = () => {
|
|
465
|
+
if (current.trim()) out.push({ combinator: out.length ? combinator || " " : "", text: current.trim() });
|
|
466
|
+
current = "";
|
|
467
|
+
combinator = "";
|
|
468
|
+
};
|
|
469
|
+
for (let i = 0; i < selector.length; i++) {
|
|
470
|
+
const c = selector[i];
|
|
471
|
+
if (quote) {
|
|
472
|
+
current += c;
|
|
473
|
+
if (c === "\\") current += selector[++i] ?? "";
|
|
474
|
+
else if (c === quote) quote = "";
|
|
475
|
+
continue;
|
|
476
|
+
}
|
|
477
|
+
if (c === "\\") {
|
|
478
|
+
current += c + (selector[++i] ?? "");
|
|
479
|
+
continue;
|
|
480
|
+
}
|
|
481
|
+
if (c === '"' || c === "'") quote = c;
|
|
482
|
+
if (c === "(" || c === "[") depth++;
|
|
483
|
+
if (c === ")" || c === "]") depth--;
|
|
484
|
+
if (depth === 0 && (c === ">" || c === "+" || c === "~")) {
|
|
485
|
+
push();
|
|
486
|
+
combinator = c;
|
|
487
|
+
continue;
|
|
488
|
+
}
|
|
489
|
+
if (depth === 0 && /\s/.test(c)) {
|
|
490
|
+
if (current.trim()) {
|
|
491
|
+
const keep = combinator;
|
|
492
|
+
push();
|
|
493
|
+
combinator = keep;
|
|
494
|
+
}
|
|
495
|
+
continue;
|
|
496
|
+
}
|
|
497
|
+
current += c;
|
|
498
|
+
}
|
|
499
|
+
push();
|
|
500
|
+
return out;
|
|
501
|
+
}
|
|
502
|
+
function join(parts) {
|
|
503
|
+
return parts.map((p, i) => i === 0 ? p.text : p.combinator === " " ? ` ${p.text}` : ` ${p.combinator} ${p.text}`).join("");
|
|
504
|
+
}
|
|
505
|
+
function unwrap(text, prefix) {
|
|
506
|
+
return text.slice(prefix.length, text.lastIndexOf(")")).trim() + text.slice(text.lastIndexOf(")") + 1);
|
|
507
|
+
}
|
|
508
|
+
function splitTop(selector, separator) {
|
|
509
|
+
const parts = [];
|
|
510
|
+
let depth = 0;
|
|
511
|
+
let quote = "";
|
|
512
|
+
let start = 0;
|
|
513
|
+
for (let i = 0; i < selector.length; i++) {
|
|
514
|
+
const c = selector[i];
|
|
515
|
+
if (quote) {
|
|
516
|
+
if (c === "\\") i++;
|
|
517
|
+
else if (c === quote) quote = "";
|
|
518
|
+
} else if (c === '"' || c === "'") quote = c;
|
|
519
|
+
else if (c === "\\") i++;
|
|
520
|
+
else if (c === "(" || c === "[") depth++;
|
|
521
|
+
else if (c === ")" || c === "]") depth--;
|
|
522
|
+
else if (c === separator && depth === 0) {
|
|
523
|
+
parts.push(selector.slice(start, i));
|
|
524
|
+
start = i + 1;
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
parts.push(selector.slice(start));
|
|
528
|
+
return parts.filter((p) => p.trim());
|
|
529
|
+
}
|
|
530
|
+
function shiftLoc(node, source, start) {
|
|
531
|
+
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;
|
|
532
|
+
if (node.kind === "rule" || node.kind === "at-rule") return { ...node, loc, nodes: node.nodes.map((n) => shiftLoc(n, source, start)) };
|
|
533
|
+
return { ...node, loc };
|
|
534
|
+
}
|
|
535
|
+
function dropLoc(node) {
|
|
536
|
+
const { loc: _loc, ...rest } = node;
|
|
537
|
+
if (rest.kind === "rule" || rest.kind === "at-rule") return { ...rest, nodes: rest.nodes.map(dropLoc) };
|
|
538
|
+
return rest;
|
|
539
|
+
}
|
|
540
|
+
function printStyleWithMap(nodes, minify, sourceName, module2) {
|
|
541
|
+
const lines = [[]];
|
|
542
|
+
let css = "";
|
|
543
|
+
let column = 0;
|
|
544
|
+
const emit = (text) => {
|
|
545
|
+
for (const ch of text) {
|
|
546
|
+
css += ch;
|
|
547
|
+
if (ch === "\n") {
|
|
548
|
+
lines.push([]);
|
|
549
|
+
column = 0;
|
|
550
|
+
} else column++;
|
|
551
|
+
}
|
|
552
|
+
};
|
|
553
|
+
const mark = (loc) => {
|
|
554
|
+
if (loc && loc.source === sourceName) lines[lines.length - 1].push([column, 0, loc.line - 1, loc.column]);
|
|
555
|
+
};
|
|
556
|
+
const write = (node, depth) => {
|
|
557
|
+
const pad = minify ? "" : " ".repeat(depth);
|
|
558
|
+
const nl = minify ? "" : "\n";
|
|
559
|
+
const sp = minify ? "" : " ";
|
|
560
|
+
emit(pad);
|
|
561
|
+
mark(node.loc);
|
|
562
|
+
if (node.kind === "declaration") {
|
|
563
|
+
emit(`${node.property}:${sp}${node.value}${node.important ? `${sp}!important` : ""};${nl}`);
|
|
564
|
+
} else if (node.kind === "raw") {
|
|
565
|
+
emit(`${node.text}${nl}`);
|
|
566
|
+
} else {
|
|
567
|
+
emit(`${node.kind === "rule" ? node.selector : `@${node.name}${node.params ? " " + node.params : ""}`}${sp}{${nl}`);
|
|
568
|
+
for (const child of node.nodes) write(child, depth + 1);
|
|
569
|
+
emit(`${pad}}${nl}`);
|
|
570
|
+
}
|
|
571
|
+
};
|
|
572
|
+
for (const node of nodes) write(node, 0);
|
|
573
|
+
return { css, map: { version: 3, sources: [module2.id], sourcesContent: [module2.code], names: [], mappings: (0, import_sourcemap_codec.encode)(lines) } };
|
|
574
|
+
}
|
|
575
|
+
function printStyle(nodes, minify = false) {
|
|
576
|
+
const out = [];
|
|
577
|
+
const write = (node, depth) => {
|
|
578
|
+
const pad = minify ? "" : " ".repeat(depth);
|
|
579
|
+
const nl = minify ? "" : "\n";
|
|
580
|
+
const sp = minify ? "" : " ";
|
|
581
|
+
if (node.kind === "declaration") {
|
|
582
|
+
out.push(`${pad}${node.property}:${sp}${node.value}${node.important ? `${sp}!important` : ""};${nl}`);
|
|
583
|
+
} else if (node.kind === "raw") {
|
|
584
|
+
out.push(`${pad}${node.text}${nl}`);
|
|
585
|
+
} else {
|
|
586
|
+
const header = node.kind === "rule" ? node.selector : `@${node.name}${node.params ? " " + node.params : ""}`;
|
|
587
|
+
out.push(`${pad}${header}${sp}{${nl}`);
|
|
588
|
+
for (const child of node.nodes) write(child, depth + 1);
|
|
589
|
+
out.push(`${pad}}${nl}`);
|
|
590
|
+
}
|
|
591
|
+
};
|
|
592
|
+
for (const node of nodes) write(node, 0);
|
|
593
|
+
return out.join("");
|
|
594
|
+
}
|
|
595
|
+
|
|
39
596
|
// src/optimize/analyze-static.ts
|
|
40
597
|
function propReason(prop) {
|
|
41
598
|
switch (prop.kind) {
|
|
@@ -481,6 +1038,7 @@ var INTRINSICS = {
|
|
|
481
1038
|
$effect: { export: "effect", module: REACTIVE_MODULE, returns: "effect" },
|
|
482
1039
|
$store: { export: "store", module: "@fluixi/reactive/store", returns: "store-handle" },
|
|
483
1040
|
$resource: { export: "resource", module: REACTIVE_MODULE, returns: "resource-handle" },
|
|
1041
|
+
$cachedResource: { export: "cachedResource", module: "@fluixi/reactive/cached-resource", returns: "resource-handle" },
|
|
484
1042
|
// No short runtime form for these yet, so the intrinsic stands for the `create*`
|
|
485
1043
|
// name. Still worth having: no import to write, and when a shorter form is
|
|
486
1044
|
// designed, the change is this line rather than a compiler pass.
|
|
@@ -491,6 +1049,19 @@ var INTRINSICS = {
|
|
|
491
1049
|
// dependency analysis must not guess at.
|
|
492
1050
|
$untrack: { export: "untrack", module: REACTIVE_MODULE, returns: "plain" },
|
|
493
1051
|
$untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" },
|
|
1052
|
+
// Scopes, scheduling and lifecycle: no value to classify, but the same authoring promise,
|
|
1053
|
+
// no import to write. `$cleanup` registers a callback on the current owner (`onCleanup`).
|
|
1054
|
+
$batch: { export: "batch", module: REACTIVE_MODULE, returns: "plain" },
|
|
1055
|
+
$cleanup: { export: "onCleanup", module: REACTIVE_MODULE, returns: "plain" },
|
|
1056
|
+
$root: { export: "root", module: REACTIVE_MODULE, returns: "plain" },
|
|
1057
|
+
$context: { export: "context", module: REACTIVE_MODULE, returns: "plain" },
|
|
1058
|
+
$renderEffect: { export: "renderEffect", module: REACTIVE_MODULE, returns: "effect" },
|
|
1059
|
+
$computed: { export: "computed", module: REACTIVE_MODULE, returns: "effect" },
|
|
1060
|
+
// Storage for where the code runs, and a signal kept in it. `$persisted` is a signal
|
|
1061
|
+
// handle as far as reads go: the same accessor with `set` on it.
|
|
1062
|
+
$storage: { export: "useStorage", module: "@fluixi/core/storage", returns: "plain" },
|
|
1063
|
+
$asyncStorage: { export: "useAsyncStorage", module: "@fluixi/core/storage", returns: "plain" },
|
|
1064
|
+
$persisted: { export: "persisted", module: "@fluixi/core/storage", returns: "signal-handle" },
|
|
494
1065
|
// An environment variable, public or server-only; the browser build refuses a secret.
|
|
495
1066
|
$env: { export: "env", module: "@fluixi/start/env", returns: "plain" }
|
|
496
1067
|
};
|
|
@@ -503,8 +1074,11 @@ var RUNTIME_PRIMITIVES = {
|
|
|
503
1074
|
createMemo: "memo-accessor",
|
|
504
1075
|
createEffect: "effect",
|
|
505
1076
|
createRenderEffect: "effect",
|
|
1077
|
+
renderEffect: "effect",
|
|
1078
|
+
computed: "effect",
|
|
506
1079
|
createStore: "reactive-object",
|
|
507
1080
|
resource: "resource-handle",
|
|
1081
|
+
cachedResource: "resource-handle",
|
|
508
1082
|
createResource: "reactive-object",
|
|
509
1083
|
createSelector: "memo-accessor",
|
|
510
1084
|
createDeferred: "memo-accessor"
|
|
@@ -513,8 +1087,19 @@ var PRIMITIVE_MODULES = [
|
|
|
513
1087
|
"@fluixi/reactive",
|
|
514
1088
|
"@fluixi/reactive/signal",
|
|
515
1089
|
"@fluixi/reactive/store",
|
|
1090
|
+
"@fluixi/reactive/cached-resource",
|
|
516
1091
|
"@fluixi/core"
|
|
517
1092
|
];
|
|
1093
|
+
var TAG_INTRINSICS = {
|
|
1094
|
+
$html: { export: "html", module: "@fluixi/core" },
|
|
1095
|
+
$svg: { export: "svg", module: "@fluixi/core" },
|
|
1096
|
+
$css: { export: "css", module: "@fluixi/core" }
|
|
1097
|
+
};
|
|
1098
|
+
function tagIntrinsics(bound) {
|
|
1099
|
+
const tags = /* @__PURE__ */ new Map();
|
|
1100
|
+
for (const [name, tag] of Object.entries(TAG_INTRINSICS)) if (!bound.has(name)) tags.set(name, tag.export);
|
|
1101
|
+
return tags;
|
|
1102
|
+
}
|
|
518
1103
|
var INTRINSIC_CALL = new RegExp(`\\$(?:${Object.keys(INTRINSICS).map((n) => n.slice(1)).join("|")})\\s*\\(`);
|
|
519
1104
|
function mayHaveIntrinsic(code) {
|
|
520
1105
|
return INTRINSIC_CALL.test(code);
|
|
@@ -648,6 +1233,7 @@ function resolveReactiveBindings(program) {
|
|
|
648
1233
|
// src/transform/source-locations.ts
|
|
649
1234
|
var SOURCE_MARKER = "__fx_source";
|
|
650
1235
|
var COMPONENT_MARKER = "__fx_component";
|
|
1236
|
+
var CLASS_MARKER = "__fx_class";
|
|
651
1237
|
var HOLE_MARKER = "__fx_hole";
|
|
652
1238
|
var markHole = (accessor, line, column, name) => `(globalThis.${HOLE_MARKER} ?? ((f) => f))(${accessor},${line},${column}${name === void 0 ? "" : `,${JSON.stringify(name)}`})`;
|
|
653
1239
|
var PROPS_MARKER = "__fx_props";
|
|
@@ -665,11 +1251,12 @@ var RUNTIME_PRIMITIVES2 = /* @__PURE__ */ new Set([
|
|
|
665
1251
|
"createStore",
|
|
666
1252
|
"createResource"
|
|
667
1253
|
]);
|
|
668
|
-
function
|
|
1254
|
+
function mayHaveSourceMarks(code) {
|
|
669
1255
|
for (const name of RUNTIME_PRIMITIVES2) {
|
|
670
1256
|
if (code.includes(name)) return true;
|
|
671
1257
|
}
|
|
672
|
-
|
|
1258
|
+
if (code.includes("$signal") || code.includes("$memo") || code.includes("$effect") || code.includes("$store")) return true;
|
|
1259
|
+
return /\bclass\b[^{;]*\bextends\b/.test(code);
|
|
673
1260
|
}
|
|
674
1261
|
var SINGLE_STATEMENT_PARENTS = /* @__PURE__ */ new Set([
|
|
675
1262
|
"IfStatement",
|
|
@@ -688,6 +1275,7 @@ function isLoneBranch(statement, parent) {
|
|
|
688
1275
|
function isExport(node) {
|
|
689
1276
|
return node.type === "ExportNamedDeclaration" || node.type === "ExportDefaultDeclaration";
|
|
690
1277
|
}
|
|
1278
|
+
var CLASS_FIELDS = /* @__PURE__ */ new Set(["PropertyDefinition", "ClassProperty", "ClassPrivateProperty", "AccessorProperty"]);
|
|
691
1279
|
function isStatement(node) {
|
|
692
1280
|
return node.type.endsWith("Statement") || node.type === "VariableDeclaration";
|
|
693
1281
|
}
|
|
@@ -708,6 +1296,14 @@ function walk3(node, visit, stack = []) {
|
|
|
708
1296
|
}
|
|
709
1297
|
function nameFor(stack) {
|
|
710
1298
|
const declarator = stack[stack.length - 1];
|
|
1299
|
+
if (declarator && CLASS_FIELDS.has(declarator.type)) {
|
|
1300
|
+
const key = declarator.key;
|
|
1301
|
+
if (key?.type === "Identifier" || key?.type === "PrivateIdentifier" || key?.type === "PrivateName") {
|
|
1302
|
+
const name = key.name ?? key.id?.name;
|
|
1303
|
+
return name;
|
|
1304
|
+
}
|
|
1305
|
+
return void 0;
|
|
1306
|
+
}
|
|
711
1307
|
if (declarator?.type !== "VariableDeclarator") return void 0;
|
|
712
1308
|
const id = declarator.id;
|
|
713
1309
|
if (id?.type === "Identifier") return id.name;
|
|
@@ -756,6 +1352,17 @@ function collectSourceEdits(program, filename) {
|
|
|
756
1352
|
});
|
|
757
1353
|
}
|
|
758
1354
|
}
|
|
1355
|
+
if ((node.type === "ClassDeclaration" || node.type === "ClassExpression") && node.superClass && !node.declare) {
|
|
1356
|
+
const at = node.loc?.start;
|
|
1357
|
+
const body = node.body;
|
|
1358
|
+
if (at && body) {
|
|
1359
|
+
edits.push({
|
|
1360
|
+
start: body.start + 1,
|
|
1361
|
+
end: body.start + 1,
|
|
1362
|
+
code: `static{globalThis.${CLASS_MARKER}?.(this,${JSON.stringify(filename)},${at.line},${at.column});}`
|
|
1363
|
+
});
|
|
1364
|
+
}
|
|
1365
|
+
}
|
|
759
1366
|
if (node.type !== "CallExpression") return;
|
|
760
1367
|
const callee = node.callee;
|
|
761
1368
|
if (callee?.type !== "Identifier") return;
|
|
@@ -765,6 +1372,26 @@ function collectSourceEdits(program, filename) {
|
|
|
765
1372
|
if (!intrinsic && !imported) return;
|
|
766
1373
|
const position = node.loc?.start;
|
|
767
1374
|
if (!position) return;
|
|
1375
|
+
for (let i = stack.length - 1; i >= 0; i--) {
|
|
1376
|
+
const up = stack[i];
|
|
1377
|
+
if (isStatement(up)) break;
|
|
1378
|
+
if (CLASS_FIELDS.has(up.type)) {
|
|
1379
|
+
if (claimed.has(node.start)) return;
|
|
1380
|
+
claimed.add(node.start);
|
|
1381
|
+
const label2 = nameFor(stack);
|
|
1382
|
+
const own = !up.static;
|
|
1383
|
+
const args2 = [
|
|
1384
|
+
JSON.stringify(filename),
|
|
1385
|
+
String(position.line),
|
|
1386
|
+
String(position.column),
|
|
1387
|
+
label2 ? JSON.stringify(label2) : own ? "undefined" : void 0,
|
|
1388
|
+
own ? "this" : void 0
|
|
1389
|
+
].filter((a) => a !== void 0).join(",");
|
|
1390
|
+
edits.push({ start: node.start, end: node.start, code: `(globalThis.${SOURCE_MARKER}?.(${args2}),` });
|
|
1391
|
+
edits.push({ start: node.end, end: node.end, code: ")" });
|
|
1392
|
+
return;
|
|
1393
|
+
}
|
|
1394
|
+
}
|
|
768
1395
|
let statement;
|
|
769
1396
|
let parent;
|
|
770
1397
|
let index = -1;
|
|
@@ -970,13 +1597,16 @@ function emitComponent(name, props, children, used, templates, at) {
|
|
|
970
1597
|
used.add("createComponent");
|
|
971
1598
|
const spreads = props.filter((p) => p.kind === "spread");
|
|
972
1599
|
const normal = props.filter((p) => p.kind !== "spread");
|
|
973
|
-
const
|
|
974
|
-
(p) => `get ${propKey(p.name)}() { return ${componentPropValue(p)}; }`
|
|
975
|
-
);
|
|
1600
|
+
const bodies = normal.map((p) => [p.name, componentPropValue(p)]);
|
|
976
1601
|
if (children.length > 0) {
|
|
977
|
-
|
|
1602
|
+
bodies.push(["children", emitChildren(children, used, templates)]);
|
|
1603
|
+
}
|
|
1604
|
+
let obj = `{ ${bodies.map(([name2, body]) => `get ${propKey(name2)}() { return ${body}; }`).join(", ")} }`;
|
|
1605
|
+
if (bodies.some(([, body]) => /\bthis\b/.test(body))) {
|
|
1606
|
+
const thunks = bodies.map(([name2, body]) => `${JSON.stringify(name2)}: () => (${body})`);
|
|
1607
|
+
const getters = bodies.map(([name2]) => `get ${propKey(name2)}() { return _$t[${JSON.stringify(name2)}](); }`);
|
|
1608
|
+
obj = `((_$t) => ({ ${getters.join(", ")} }))({ ${thunks.join(", ")} })`;
|
|
978
1609
|
}
|
|
979
|
-
let obj = `{ ${entries.join(", ")} }`;
|
|
980
1610
|
if (spreads.length > 0) {
|
|
981
1611
|
used.add("mergeProps");
|
|
982
1612
|
obj = `mergeProps(${spreads.map((s) => s.expr).join(", ")}, ${obj})`;
|
|
@@ -1058,7 +1688,8 @@ function emitNode(node, used, templates) {
|
|
|
1058
1688
|
} else {
|
|
1059
1689
|
used.add("spread");
|
|
1060
1690
|
const svgFlag = node.svg ? ", isSVG: true" : "";
|
|
1061
|
-
const
|
|
1691
|
+
const accessors = node.props.filter((p) => p.kind !== "spread" && p.expr !== void 0 && p.reactive && p.name !== "ref").map((p) => p.name);
|
|
1692
|
+
const customFlag = node.tag.includes("-") ? `, isCustomElement: true, accessors: ${JSON.stringify(accessors)}` : "";
|
|
1062
1693
|
parts.push(
|
|
1063
1694
|
`spread({ element: ${el}, props: ${emitProps(node.props, null, used)}${svgFlag}${customFlag} });`
|
|
1064
1695
|
);
|
|
@@ -1171,6 +1802,271 @@ function cleanTemplateText(value) {
|
|
|
1171
1802
|
return out;
|
|
1172
1803
|
}
|
|
1173
1804
|
|
|
1805
|
+
// src/lower/entities.ts
|
|
1806
|
+
var NAMED = {
|
|
1807
|
+
quot: 34,
|
|
1808
|
+
amp: 38,
|
|
1809
|
+
apos: 39,
|
|
1810
|
+
lt: 60,
|
|
1811
|
+
gt: 62,
|
|
1812
|
+
nbsp: 160,
|
|
1813
|
+
iexcl: 161,
|
|
1814
|
+
cent: 162,
|
|
1815
|
+
pound: 163,
|
|
1816
|
+
curren: 164,
|
|
1817
|
+
yen: 165,
|
|
1818
|
+
brvbar: 166,
|
|
1819
|
+
sect: 167,
|
|
1820
|
+
uml: 168,
|
|
1821
|
+
copy: 169,
|
|
1822
|
+
ordf: 170,
|
|
1823
|
+
laquo: 171,
|
|
1824
|
+
not: 172,
|
|
1825
|
+
shy: 173,
|
|
1826
|
+
reg: 174,
|
|
1827
|
+
macr: 175,
|
|
1828
|
+
deg: 176,
|
|
1829
|
+
plusmn: 177,
|
|
1830
|
+
sup2: 178,
|
|
1831
|
+
sup3: 179,
|
|
1832
|
+
acute: 180,
|
|
1833
|
+
micro: 181,
|
|
1834
|
+
para: 182,
|
|
1835
|
+
middot: 183,
|
|
1836
|
+
cedil: 184,
|
|
1837
|
+
sup1: 185,
|
|
1838
|
+
ordm: 186,
|
|
1839
|
+
raquo: 187,
|
|
1840
|
+
frac14: 188,
|
|
1841
|
+
frac12: 189,
|
|
1842
|
+
frac34: 190,
|
|
1843
|
+
iquest: 191,
|
|
1844
|
+
Agrave: 192,
|
|
1845
|
+
Aacute: 193,
|
|
1846
|
+
Acirc: 194,
|
|
1847
|
+
Atilde: 195,
|
|
1848
|
+
Auml: 196,
|
|
1849
|
+
Aring: 197,
|
|
1850
|
+
AElig: 198,
|
|
1851
|
+
Ccedil: 199,
|
|
1852
|
+
Egrave: 200,
|
|
1853
|
+
Eacute: 201,
|
|
1854
|
+
Ecirc: 202,
|
|
1855
|
+
Euml: 203,
|
|
1856
|
+
Igrave: 204,
|
|
1857
|
+
Iacute: 205,
|
|
1858
|
+
Icirc: 206,
|
|
1859
|
+
Iuml: 207,
|
|
1860
|
+
ETH: 208,
|
|
1861
|
+
Ntilde: 209,
|
|
1862
|
+
Ograve: 210,
|
|
1863
|
+
Oacute: 211,
|
|
1864
|
+
Ocirc: 212,
|
|
1865
|
+
Otilde: 213,
|
|
1866
|
+
Ouml: 214,
|
|
1867
|
+
times: 215,
|
|
1868
|
+
Oslash: 216,
|
|
1869
|
+
Ugrave: 217,
|
|
1870
|
+
Uacute: 218,
|
|
1871
|
+
Ucirc: 219,
|
|
1872
|
+
Uuml: 220,
|
|
1873
|
+
Yacute: 221,
|
|
1874
|
+
THORN: 222,
|
|
1875
|
+
szlig: 223,
|
|
1876
|
+
agrave: 224,
|
|
1877
|
+
aacute: 225,
|
|
1878
|
+
acirc: 226,
|
|
1879
|
+
atilde: 227,
|
|
1880
|
+
auml: 228,
|
|
1881
|
+
aring: 229,
|
|
1882
|
+
aelig: 230,
|
|
1883
|
+
ccedil: 231,
|
|
1884
|
+
egrave: 232,
|
|
1885
|
+
eacute: 233,
|
|
1886
|
+
ecirc: 234,
|
|
1887
|
+
euml: 235,
|
|
1888
|
+
igrave: 236,
|
|
1889
|
+
iacute: 237,
|
|
1890
|
+
icirc: 238,
|
|
1891
|
+
iuml: 239,
|
|
1892
|
+
eth: 240,
|
|
1893
|
+
ntilde: 241,
|
|
1894
|
+
ograve: 242,
|
|
1895
|
+
oacute: 243,
|
|
1896
|
+
ocirc: 244,
|
|
1897
|
+
otilde: 245,
|
|
1898
|
+
ouml: 246,
|
|
1899
|
+
divide: 247,
|
|
1900
|
+
oslash: 248,
|
|
1901
|
+
ugrave: 249,
|
|
1902
|
+
uacute: 250,
|
|
1903
|
+
ucirc: 251,
|
|
1904
|
+
uuml: 252,
|
|
1905
|
+
yacute: 253,
|
|
1906
|
+
thorn: 254,
|
|
1907
|
+
yuml: 255,
|
|
1908
|
+
OElig: 338,
|
|
1909
|
+
oelig: 339,
|
|
1910
|
+
Scaron: 352,
|
|
1911
|
+
scaron: 353,
|
|
1912
|
+
Yuml: 376,
|
|
1913
|
+
fnof: 402,
|
|
1914
|
+
circ: 710,
|
|
1915
|
+
tilde: 732,
|
|
1916
|
+
Alpha: 913,
|
|
1917
|
+
Beta: 914,
|
|
1918
|
+
Gamma: 915,
|
|
1919
|
+
Delta: 916,
|
|
1920
|
+
Epsilon: 917,
|
|
1921
|
+
Zeta: 918,
|
|
1922
|
+
Eta: 919,
|
|
1923
|
+
Theta: 920,
|
|
1924
|
+
Iota: 921,
|
|
1925
|
+
Kappa: 922,
|
|
1926
|
+
Lambda: 923,
|
|
1927
|
+
Mu: 924,
|
|
1928
|
+
Nu: 925,
|
|
1929
|
+
Xi: 926,
|
|
1930
|
+
Omicron: 927,
|
|
1931
|
+
Pi: 928,
|
|
1932
|
+
Rho: 929,
|
|
1933
|
+
Sigma: 931,
|
|
1934
|
+
Tau: 932,
|
|
1935
|
+
Upsilon: 933,
|
|
1936
|
+
Phi: 934,
|
|
1937
|
+
Chi: 935,
|
|
1938
|
+
Psi: 936,
|
|
1939
|
+
Omega: 937,
|
|
1940
|
+
alpha: 945,
|
|
1941
|
+
beta: 946,
|
|
1942
|
+
gamma: 947,
|
|
1943
|
+
delta: 948,
|
|
1944
|
+
epsilon: 949,
|
|
1945
|
+
zeta: 950,
|
|
1946
|
+
eta: 951,
|
|
1947
|
+
theta: 952,
|
|
1948
|
+
iota: 953,
|
|
1949
|
+
kappa: 954,
|
|
1950
|
+
lambda: 955,
|
|
1951
|
+
mu: 956,
|
|
1952
|
+
nu: 957,
|
|
1953
|
+
xi: 958,
|
|
1954
|
+
omicron: 959,
|
|
1955
|
+
pi: 960,
|
|
1956
|
+
rho: 961,
|
|
1957
|
+
sigmaf: 962,
|
|
1958
|
+
sigma: 963,
|
|
1959
|
+
tau: 964,
|
|
1960
|
+
upsilon: 965,
|
|
1961
|
+
phi: 966,
|
|
1962
|
+
chi: 967,
|
|
1963
|
+
psi: 968,
|
|
1964
|
+
omega: 969,
|
|
1965
|
+
thetasym: 977,
|
|
1966
|
+
upsih: 978,
|
|
1967
|
+
piv: 982,
|
|
1968
|
+
ensp: 8194,
|
|
1969
|
+
emsp: 8195,
|
|
1970
|
+
thinsp: 8201,
|
|
1971
|
+
zwnj: 8204,
|
|
1972
|
+
zwj: 8205,
|
|
1973
|
+
lrm: 8206,
|
|
1974
|
+
rlm: 8207,
|
|
1975
|
+
ndash: 8211,
|
|
1976
|
+
mdash: 8212,
|
|
1977
|
+
lsquo: 8216,
|
|
1978
|
+
rsquo: 8217,
|
|
1979
|
+
sbquo: 8218,
|
|
1980
|
+
ldquo: 8220,
|
|
1981
|
+
rdquo: 8221,
|
|
1982
|
+
bdquo: 8222,
|
|
1983
|
+
dagger: 8224,
|
|
1984
|
+
Dagger: 8225,
|
|
1985
|
+
bull: 8226,
|
|
1986
|
+
hellip: 8230,
|
|
1987
|
+
permil: 8240,
|
|
1988
|
+
prime: 8242,
|
|
1989
|
+
Prime: 8243,
|
|
1990
|
+
lsaquo: 8249,
|
|
1991
|
+
rsaquo: 8250,
|
|
1992
|
+
oline: 8254,
|
|
1993
|
+
frasl: 8260,
|
|
1994
|
+
euro: 8364,
|
|
1995
|
+
image: 8465,
|
|
1996
|
+
weierp: 8472,
|
|
1997
|
+
real: 8476,
|
|
1998
|
+
trade: 8482,
|
|
1999
|
+
alefsym: 8501,
|
|
2000
|
+
larr: 8592,
|
|
2001
|
+
uarr: 8593,
|
|
2002
|
+
rarr: 8594,
|
|
2003
|
+
darr: 8595,
|
|
2004
|
+
harr: 8596,
|
|
2005
|
+
crarr: 8629,
|
|
2006
|
+
lArr: 8656,
|
|
2007
|
+
uArr: 8657,
|
|
2008
|
+
rArr: 8658,
|
|
2009
|
+
dArr: 8659,
|
|
2010
|
+
hArr: 8660,
|
|
2011
|
+
forall: 8704,
|
|
2012
|
+
part: 8706,
|
|
2013
|
+
exist: 8707,
|
|
2014
|
+
empty: 8709,
|
|
2015
|
+
nabla: 8711,
|
|
2016
|
+
isin: 8712,
|
|
2017
|
+
notin: 8713,
|
|
2018
|
+
ni: 8715,
|
|
2019
|
+
prod: 8719,
|
|
2020
|
+
sum: 8721,
|
|
2021
|
+
minus: 8722,
|
|
2022
|
+
lowast: 8727,
|
|
2023
|
+
radic: 8730,
|
|
2024
|
+
prop: 8733,
|
|
2025
|
+
infin: 8734,
|
|
2026
|
+
ang: 8736,
|
|
2027
|
+
and: 8743,
|
|
2028
|
+
or: 8744,
|
|
2029
|
+
cap: 8745,
|
|
2030
|
+
cup: 8746,
|
|
2031
|
+
int: 8747,
|
|
2032
|
+
there4: 8756,
|
|
2033
|
+
sim: 8764,
|
|
2034
|
+
cong: 8773,
|
|
2035
|
+
asymp: 8776,
|
|
2036
|
+
ne: 8800,
|
|
2037
|
+
equiv: 8801,
|
|
2038
|
+
le: 8804,
|
|
2039
|
+
ge: 8805,
|
|
2040
|
+
sub: 8834,
|
|
2041
|
+
sup: 8835,
|
|
2042
|
+
nsub: 8836,
|
|
2043
|
+
sube: 8838,
|
|
2044
|
+
supe: 8839,
|
|
2045
|
+
oplus: 8853,
|
|
2046
|
+
otimes: 8855,
|
|
2047
|
+
perp: 8869,
|
|
2048
|
+
sdot: 8901,
|
|
2049
|
+
lceil: 8968,
|
|
2050
|
+
rceil: 8969,
|
|
2051
|
+
lfloor: 8970,
|
|
2052
|
+
rfloor: 8971,
|
|
2053
|
+
lang: 9001,
|
|
2054
|
+
rang: 9002,
|
|
2055
|
+
loz: 9674,
|
|
2056
|
+
spades: 9824,
|
|
2057
|
+
clubs: 9827,
|
|
2058
|
+
hearts: 9829,
|
|
2059
|
+
diams: 9830
|
|
2060
|
+
};
|
|
2061
|
+
var REFERENCE = /&(?:#[xX]([0-9a-fA-F]{1,6})|#([0-9]{1,7})|([a-zA-Z][a-zA-Z0-9]{1,31}));/g;
|
|
2062
|
+
function decodeEntities(value) {
|
|
2063
|
+
if (!value.includes("&")) return value;
|
|
2064
|
+
return value.replace(REFERENCE, (match, hex, dec, name) => {
|
|
2065
|
+
const code = hex ? parseInt(hex, 16) : dec ? parseInt(dec, 10) : Object.prototype.hasOwnProperty.call(NAMED, name) ? NAMED[name] : void 0;
|
|
2066
|
+
return code !== void 0 && code <= 1114111 ? String.fromCodePoint(code) : match;
|
|
2067
|
+
});
|
|
2068
|
+
}
|
|
2069
|
+
|
|
1174
2070
|
// src/lower/template.ts
|
|
1175
2071
|
var DELEGATED = /* @__PURE__ */ new Set([
|
|
1176
2072
|
"click",
|
|
@@ -1189,6 +2085,7 @@ var DELEGATED = /* @__PURE__ */ new Set([
|
|
|
1189
2085
|
function escapeTemplate(s) {
|
|
1190
2086
|
return s.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${");
|
|
1191
2087
|
}
|
|
2088
|
+
var CONTAINER = "container";
|
|
1192
2089
|
function capitalize(s) {
|
|
1193
2090
|
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
1194
2091
|
}
|
|
@@ -1243,10 +2140,6 @@ var Lowerer = class {
|
|
|
1243
2140
|
if (hasElse) i = elseIdx;
|
|
1244
2141
|
continue;
|
|
1245
2142
|
}
|
|
1246
|
-
if (child.attributes.some((a) => a.kind === "EachDirective")) {
|
|
1247
|
-
out.push(this.lowerEach(child));
|
|
1248
|
-
continue;
|
|
1249
|
-
}
|
|
1250
2143
|
}
|
|
1251
2144
|
const node = this.lowerNode(child);
|
|
1252
2145
|
if (node) out.push(node);
|
|
@@ -1260,7 +2153,7 @@ var Lowerer = class {
|
|
|
1260
2153
|
switch (node.kind) {
|
|
1261
2154
|
case "Text": {
|
|
1262
2155
|
if (node.raw) return { kind: "text", value: node.value };
|
|
1263
|
-
const cleaned = cleanTemplateText(node.value);
|
|
2156
|
+
const cleaned = decodeEntities(cleanTemplateText(node.value));
|
|
1264
2157
|
return cleaned ? { kind: "text", value: cleaned } : null;
|
|
1265
2158
|
}
|
|
1266
2159
|
case "Comment":
|
|
@@ -1288,13 +2181,16 @@ var Lowerer = class {
|
|
|
1288
2181
|
node.props.unshift({ name: "component", kind: "attr", expr: `() => ${paren(this.hole(isAttr.value.hole).code, "arrowBody")}` });
|
|
1289
2182
|
return node;
|
|
1290
2183
|
}
|
|
2184
|
+
const each = this.lowerEach(el);
|
|
2185
|
+
const children = each ? [each] : this.lowerChildren(el.children);
|
|
2186
|
+
if (el.tag === CONTAINER) return children.length === 1 ? children[0] : { kind: "fragment", children };
|
|
1291
2187
|
const at = this.tagAt(el);
|
|
1292
2188
|
return {
|
|
1293
2189
|
kind: "element",
|
|
1294
2190
|
tag: el.tag,
|
|
1295
2191
|
svg: el.namespace === "svg",
|
|
1296
|
-
props: this.lowerAttributes(el.attributes),
|
|
1297
|
-
children
|
|
2192
|
+
props: this.lowerAttributes(el.attributes, true),
|
|
2193
|
+
children,
|
|
1298
2194
|
static: false,
|
|
1299
2195
|
...at ? { at } : {}
|
|
1300
2196
|
};
|
|
@@ -1366,10 +2262,14 @@ var Lowerer = class {
|
|
|
1366
2262
|
const at = this.tagAt(el);
|
|
1367
2263
|
return { kind: "component", name: "Show", props, children: [child], ...at ? { at } : {}, ...cond.at ? { bindAt: cond.at } : {} };
|
|
1368
2264
|
}
|
|
1369
|
-
/**
|
|
2265
|
+
/**
|
|
2266
|
+
* `<el each=${items} key?>${item => …}</el>` → `<el><For each>{item => …}</For></el>`: the
|
|
2267
|
+
* content is repeated per item. Content that is not a `${item => …}` arrow is repeated as
|
|
2268
|
+
* it is. Null when the element has no `each`.
|
|
2269
|
+
*/
|
|
1370
2270
|
lowerEach(el) {
|
|
1371
2271
|
const eachDir = el.attributes.find((a) => a.kind === "EachDirective");
|
|
1372
|
-
if (!eachDir || eachDir.kind !== "EachDirective") return
|
|
2272
|
+
if (!eachDir || eachDir.kind !== "EachDirective") return null;
|
|
1373
2273
|
const each = this.hole(eachDir.hole);
|
|
1374
2274
|
const props = [{ name: "each", kind: "attr", expr: each.code, reactive: each.reactive, ...each.at ? { at: each.at } : {} }];
|
|
1375
2275
|
if (eachDir.key) {
|
|
@@ -1379,12 +2279,12 @@ var Lowerer = class {
|
|
|
1379
2279
|
const arrow = this.itemArrow(el);
|
|
1380
2280
|
let childrenCode;
|
|
1381
2281
|
if (arrow) {
|
|
1382
|
-
const
|
|
1383
|
-
|
|
1384
|
-
childrenCode = `(${arrow.params.join(", ")}) => ${paren(this.emit(repeated), "arrowBody")}`;
|
|
2282
|
+
const body = arrow.bodyReactive ? `() => ${paren(arrow.body, "arrowBody")}` : paren(arrow.body, "arrowBody");
|
|
2283
|
+
childrenCode = `(${arrow.params.join(", ")}) => ${body}`;
|
|
1385
2284
|
} else {
|
|
1386
|
-
const
|
|
1387
|
-
|
|
2285
|
+
const content = this.lowerChildren(el.children);
|
|
2286
|
+
const ir = content.length === 1 ? content[0] : { kind: "fragment", children: content };
|
|
2287
|
+
childrenCode = `() => ${paren(this.emit(ir), "arrowBody")}`;
|
|
1388
2288
|
}
|
|
1389
2289
|
const children = [{ kind: "expr", code: childrenCode, reactive: false }];
|
|
1390
2290
|
const at = this.tagAt(el);
|
|
@@ -1401,33 +2301,23 @@ var Lowerer = class {
|
|
|
1401
2301
|
const clone = { ...el, attributes: el.attributes.filter((a) => !drop(a)) };
|
|
1402
2302
|
return clone.kind === "Element" ? this.lowerElement(clone) : this.lowerComponent(clone);
|
|
1403
2303
|
}
|
|
1404
|
-
/** Same element (minus each/key) but with explicit IR children. */
|
|
1405
|
-
rebuildWithChildren(el, children) {
|
|
1406
|
-
const props = this.lowerAttributes(
|
|
1407
|
-
el.attributes.filter((a) => a.kind !== "EachDirective")
|
|
1408
|
-
);
|
|
1409
|
-
if (el.kind === "Element") {
|
|
1410
|
-
const at = this.tagAt(el);
|
|
1411
|
-
return {
|
|
1412
|
-
kind: "element",
|
|
1413
|
-
tag: el.tag,
|
|
1414
|
-
svg: el.namespace === "svg",
|
|
1415
|
-
props,
|
|
1416
|
-
children,
|
|
1417
|
-
static: false,
|
|
1418
|
-
...at ? { at } : {}
|
|
1419
|
-
};
|
|
1420
|
-
}
|
|
1421
|
-
return { kind: "component", name: el.tag, props, children };
|
|
1422
|
-
}
|
|
1423
2304
|
// --- attributes ---------------------------------------------------------
|
|
1424
|
-
|
|
2305
|
+
/**
|
|
2306
|
+
* `element`: a DOM element, where each class:/style: value that moves is its own accessor.
|
|
2307
|
+
* A component gets the object as before, rebuilt whole when any value moves.
|
|
2308
|
+
*/
|
|
2309
|
+
lowerAttributes(attrs, element = false) {
|
|
2310
|
+
let anyReactive = false;
|
|
2311
|
+
const entry = (name, h) => {
|
|
2312
|
+
anyReactive ||= h.reactive;
|
|
2313
|
+
if (!element || !h.reactive) return `${JSON.stringify(name)}: ${h.code}`;
|
|
2314
|
+
const accessor = `() => ${paren(h.code, "arrowBody")}`;
|
|
2315
|
+
return `${JSON.stringify(name)}: ${h.at ? markHole(accessor, h.at.line, h.at.column) : accessor}`;
|
|
2316
|
+
};
|
|
1425
2317
|
const props = [];
|
|
1426
2318
|
const classEntries = [];
|
|
1427
|
-
let classReactive = false;
|
|
1428
2319
|
let classAt;
|
|
1429
2320
|
const styleEntries = [];
|
|
1430
|
-
let styleReactive = false;
|
|
1431
2321
|
let styleAt;
|
|
1432
2322
|
const usePairs = [];
|
|
1433
2323
|
for (const a of attrs) {
|
|
@@ -1467,15 +2357,13 @@ var Lowerer = class {
|
|
|
1467
2357
|
break;
|
|
1468
2358
|
case "ClassDirective": {
|
|
1469
2359
|
const h = this.hole(a.hole);
|
|
1470
|
-
classEntries.push(
|
|
1471
|
-
classReactive = classReactive || h.reactive;
|
|
2360
|
+
classEntries.push(entry(a.name, h));
|
|
1472
2361
|
classAt ??= h.at;
|
|
1473
2362
|
break;
|
|
1474
2363
|
}
|
|
1475
2364
|
case "StyleDirective": {
|
|
1476
2365
|
const h = this.hole(a.hole);
|
|
1477
|
-
styleEntries.push(
|
|
1478
|
-
styleReactive = styleReactive || h.reactive;
|
|
2366
|
+
styleEntries.push(entry(a.name, h));
|
|
1479
2367
|
styleAt ??= h.at;
|
|
1480
2368
|
break;
|
|
1481
2369
|
}
|
|
@@ -1495,18 +2383,19 @@ var Lowerer = class {
|
|
|
1495
2383
|
name: "classList",
|
|
1496
2384
|
kind: "attr",
|
|
1497
2385
|
expr: `{ ${classEntries.join(", ")} }`,
|
|
1498
|
-
reactive:
|
|
2386
|
+
reactive: !element && anyReactive,
|
|
1499
2387
|
...classAt ? { at: classAt } : {}
|
|
1500
2388
|
});
|
|
1501
2389
|
}
|
|
1502
2390
|
if (styleEntries.length > 0) {
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
2391
|
+
const entries = `{ ${styleEntries.join(", ")} }`;
|
|
2392
|
+
const base = props.findIndex((p) => p.name === "style");
|
|
2393
|
+
if (base === -1) props.push({ name: "style", kind: "attr", expr: entries, reactive: !element && anyReactive, ...styleAt ? { at: styleAt } : {} });
|
|
2394
|
+
else {
|
|
2395
|
+
const prop = props[base];
|
|
2396
|
+
const value = prop.expr === void 0 ? JSON.stringify(prop.literal) : prop.reactive ? `() => ${paren(prop.expr, "arrowBody")}` : prop.expr;
|
|
2397
|
+
props[base] = { name: "style", kind: "attr", expr: `[${value}, ${entries}]`, reactive: false, ...prop.at ? { at: prop.at } : {} };
|
|
2398
|
+
}
|
|
1510
2399
|
}
|
|
1511
2400
|
if (usePairs.length > 0) {
|
|
1512
2401
|
props.push({ name: "use", kind: "attr", expr: `[${usePairs.join(", ")}]` });
|
|
@@ -1595,7 +2484,7 @@ var Lowerer = class {
|
|
|
1595
2484
|
return base;
|
|
1596
2485
|
}
|
|
1597
2486
|
if (v.kind === "static") {
|
|
1598
|
-
base.literal = v.value;
|
|
2487
|
+
base.literal = decodeEntities(v.value);
|
|
1599
2488
|
return base;
|
|
1600
2489
|
}
|
|
1601
2490
|
if (v.kind === "hole") {
|
|
@@ -1608,7 +2497,7 @@ var Lowerer = class {
|
|
|
1608
2497
|
let reactive = false;
|
|
1609
2498
|
let at;
|
|
1610
2499
|
const body = v.parts.map((p) => {
|
|
1611
|
-
if ("text" in p) return escapeTemplate(p.text);
|
|
2500
|
+
if ("text" in p) return escapeTemplate(decodeEntities(p.text));
|
|
1612
2501
|
const h = this.hole(p.hole);
|
|
1613
2502
|
reactive = reactive || h.reactive;
|
|
1614
2503
|
at ??= h.at;
|
|
@@ -1633,6 +2522,7 @@ function compilePieces(pieces, holes, options = {}) {
|
|
|
1633
2522
|
...options.sourceFile ? { sourceFile: options.sourceFile } : {},
|
|
1634
2523
|
...options.positionAt ? { positionAt: options.positionAt } : {}
|
|
1635
2524
|
});
|
|
2525
|
+
if (options.templateStyles) applyTemplateStyles(ir, options.templateStyles);
|
|
1636
2526
|
analyzeStatic(ir);
|
|
1637
2527
|
resolveComponentSources(ir, {
|
|
1638
2528
|
resolver: createComponentResolver(options.resolve ?? []),
|
|
@@ -1738,6 +2628,22 @@ var DELEGATED2 = /* @__PURE__ */ new Set([
|
|
|
1738
2628
|
"mouseup"
|
|
1739
2629
|
]);
|
|
1740
2630
|
var isReactive = (node) => isReactiveShape(shapeOf(node));
|
|
2631
|
+
var CONTAINER2 = "container";
|
|
2632
|
+
function directive(node, name) {
|
|
2633
|
+
if (node.type !== "JSXElement") return void 0;
|
|
2634
|
+
const opening = node.openingElement;
|
|
2635
|
+
if (opening.name.type !== "JSXIdentifier" || opening.name.name[0] !== opening.name.name[0].toLowerCase()) return void 0;
|
|
2636
|
+
return opening.attributes.find((a) => a.type === "JSXAttribute" && a.name.type === "JSXIdentifier" && a.name.name === name);
|
|
2637
|
+
}
|
|
2638
|
+
function directiveExpr(attr) {
|
|
2639
|
+
const v = attr.value;
|
|
2640
|
+
return v?.type === "JSXExpressionContainer" && v.expression?.type !== "JSXEmptyExpression" ? v.expression : void 0;
|
|
2641
|
+
}
|
|
2642
|
+
function emitIR(ir, ctx) {
|
|
2643
|
+
const { code, imports, templates } = imperativeBackend.emit(ir, {});
|
|
2644
|
+
for (const s of imports) ctx.used.add(s);
|
|
2645
|
+
return inlineTemplates(code, templates);
|
|
2646
|
+
}
|
|
1741
2647
|
var posOf = (node, ctx) => {
|
|
1742
2648
|
if (!ctx.sourceFile) return void 0;
|
|
1743
2649
|
const at = node.loc?.start;
|
|
@@ -1815,9 +2721,12 @@ function attrExprCode(attr, ctx) {
|
|
|
1815
2721
|
}
|
|
1816
2722
|
return null;
|
|
1817
2723
|
}
|
|
1818
|
-
function buildProps(attrs, ctx) {
|
|
2724
|
+
function buildProps(attrs, ctx, element = false) {
|
|
1819
2725
|
const props = [];
|
|
1820
2726
|
const usePairs = [];
|
|
2727
|
+
const classEntries = [];
|
|
2728
|
+
const styleEntries = [];
|
|
2729
|
+
let styleAt;
|
|
1821
2730
|
for (const a of attrs) {
|
|
1822
2731
|
if (a.type === "JSXSpreadAttribute") {
|
|
1823
2732
|
props.push({ name: "", kind: "spread", expr: ctx.code(a.argument) });
|
|
@@ -1833,6 +2742,27 @@ function buildProps(attrs, ctx) {
|
|
|
1833
2742
|
usePairs.push(opts != null ? `[${dir}, () => ${paren(opts, "arrowBody")}]` : `[${dir}]`);
|
|
1834
2743
|
continue;
|
|
1835
2744
|
}
|
|
2745
|
+
if (element && (ns === "class" || ns === "style")) {
|
|
2746
|
+
const key = JSON.stringify(a.name.name.name);
|
|
2747
|
+
const v = a.value;
|
|
2748
|
+
let value;
|
|
2749
|
+
if (v == null) value = "true";
|
|
2750
|
+
else if (isString(v)) value = JSON.stringify(literalOf(v));
|
|
2751
|
+
else if (v.type === "JSXExpressionContainer" && v.expression?.type !== "JSXEmptyExpression") {
|
|
2752
|
+
value = keyValue(v.expression, ctx);
|
|
2753
|
+
if (ns === "style") styleAt ??= posOf(v.expression, ctx);
|
|
2754
|
+
} else continue;
|
|
2755
|
+
(ns === "class" ? classEntries : styleEntries).push(`${key}: ${value}`);
|
|
2756
|
+
continue;
|
|
2757
|
+
}
|
|
2758
|
+
if (element && a.name.type === "JSXIdentifier" && a.name.name === "style" && a.value?.type === "JSXExpressionContainer") {
|
|
2759
|
+
const entries = objectEntries(a.value.expression, ctx);
|
|
2760
|
+
if (entries) {
|
|
2761
|
+
styleEntries.unshift(...entries);
|
|
2762
|
+
styleAt = posOf(a.value.expression, ctx);
|
|
2763
|
+
continue;
|
|
2764
|
+
}
|
|
2765
|
+
}
|
|
1836
2766
|
if (ns === "oncapture") {
|
|
1837
2767
|
const evt = a.name.name.name.toLowerCase();
|
|
1838
2768
|
const h = attrExprCode(a, ctx) ?? "undefined";
|
|
@@ -1841,12 +2771,49 @@ function buildProps(attrs, ctx) {
|
|
|
1841
2771
|
}
|
|
1842
2772
|
props.push(buildAttr(a, ctx));
|
|
1843
2773
|
}
|
|
2774
|
+
if (classEntries.length > 0) props.push({ name: "classList", kind: "attr", expr: `{ ${classEntries.join(", ")} }`, reactive: false });
|
|
2775
|
+
if (styleEntries.length > 0) {
|
|
2776
|
+
const entries = `{ ${styleEntries.join(", ")} }`;
|
|
2777
|
+
const base = props.findIndex((p) => p.name === "style" && p.kind === "attr");
|
|
2778
|
+
if (base === -1) props.push({ name: "style", kind: "attr", expr: entries, reactive: false, ...styleAt ? { at: styleAt } : {} });
|
|
2779
|
+
else {
|
|
2780
|
+
const prop = props[base];
|
|
2781
|
+
const value = prop.literal !== void 0 ? JSON.stringify(prop.literal) : prop.reactive ? `() => ${paren(prop.expr, "arrowBody")}` : prop.expr;
|
|
2782
|
+
props[base] = { name: "style", kind: "attr", expr: `[${value}, ${entries}]`, reactive: false, ...prop.at ? { at: prop.at } : {} };
|
|
2783
|
+
}
|
|
2784
|
+
}
|
|
1844
2785
|
if (usePairs.length > 0) props.push({ name: "use", kind: "attr", expr: `[${usePairs.join(", ")}]` });
|
|
1845
2786
|
return props;
|
|
1846
2787
|
}
|
|
2788
|
+
function keyValue(expr, ctx) {
|
|
2789
|
+
const code = ctx.code(expr);
|
|
2790
|
+
if (!isReactive(expr)) return code;
|
|
2791
|
+
const accessor = `() => ${paren(code, "arrowBody")}`;
|
|
2792
|
+
const at = posOf(expr, ctx);
|
|
2793
|
+
return at ? markHole(accessor, at.line, at.column) : accessor;
|
|
2794
|
+
}
|
|
2795
|
+
function objectEntries(expr, ctx) {
|
|
2796
|
+
if (expr?.type !== "ObjectExpression") return null;
|
|
2797
|
+
const entries = [];
|
|
2798
|
+
for (const p of expr.properties) {
|
|
2799
|
+
if (p.type !== "ObjectProperty") return null;
|
|
2800
|
+
const key = p.computed ? `[${ctx.code(p.key)}]` : p.key.type === "Identifier" ? JSON.stringify(p.key.name) : JSON.stringify(String(p.key.value));
|
|
2801
|
+
entries.push(`${key}: ${keyValue(p.value, ctx)}`);
|
|
2802
|
+
}
|
|
2803
|
+
return entries;
|
|
2804
|
+
}
|
|
1847
2805
|
function buildChildren(children, ctx) {
|
|
1848
2806
|
const out = [];
|
|
1849
|
-
for (
|
|
2807
|
+
for (let i = 0; i < children.length; i++) {
|
|
2808
|
+
const child = children[i];
|
|
2809
|
+
if (directive(child, "if")) {
|
|
2810
|
+
let next = i + 1;
|
|
2811
|
+
while (next < children.length && children[next].type === "JSXText" && !cleanTemplateText(children[next].value)) next++;
|
|
2812
|
+
const fallback = directive(children[next], "else") ? children[next] : null;
|
|
2813
|
+
out.push(buildIf(child, fallback, ctx));
|
|
2814
|
+
if (fallback) i = next;
|
|
2815
|
+
continue;
|
|
2816
|
+
}
|
|
1850
2817
|
if (child.type === "JSXText") {
|
|
1851
2818
|
const text = cleanTemplateText(child.value);
|
|
1852
2819
|
if (text) out.push({ kind: "text", value: text });
|
|
@@ -1862,6 +2829,7 @@ function buildChildren(children, ctx) {
|
|
|
1862
2829
|
});
|
|
1863
2830
|
}
|
|
1864
2831
|
} else if (child.type === "JSXElement" || child.type === "JSXFragment") {
|
|
2832
|
+
if (ctx.dropStyles?.has(child.start)) continue;
|
|
1865
2833
|
out.push(buildNode(child, ctx));
|
|
1866
2834
|
} else if (child.type === "JSXSpreadChild") {
|
|
1867
2835
|
out.push({ kind: "expr", code: ctx.code(child.expression), reactive: false });
|
|
@@ -1883,19 +2851,72 @@ function readLoad(attrs) {
|
|
|
1883
2851
|
}
|
|
1884
2852
|
return void 0;
|
|
1885
2853
|
}
|
|
2854
|
+
function buildIf(node, fallback, ctx) {
|
|
2855
|
+
const cond = directiveExpr(directive(node, "if"));
|
|
2856
|
+
const props = [
|
|
2857
|
+
cond ? { name: "when", kind: "attr", expr: ctx.code(cond), reactive: isReactive(cond), at: posOf(cond, ctx) } : { name: "when", kind: "attr", literal: true }
|
|
2858
|
+
];
|
|
2859
|
+
if (fallback) {
|
|
2860
|
+
props.push({ name: "fallback", kind: "attr", expr: emitIR(buildElement(fallback, ctx, ["else"]), ctx), jsxElement: true });
|
|
2861
|
+
}
|
|
2862
|
+
return { kind: "component", name: "Show", props, children: [buildElement(node, ctx, ["if"])] };
|
|
2863
|
+
}
|
|
2864
|
+
function buildEach(node, ctx) {
|
|
2865
|
+
const attr = directive(node, "each");
|
|
2866
|
+
if (!attr) return null;
|
|
2867
|
+
const list = directiveExpr(attr);
|
|
2868
|
+
const props = [
|
|
2869
|
+
list ? { name: "each", kind: "attr", expr: ctx.code(list), reactive: isReactive(list), at: posOf(list, ctx) } : { name: "each", kind: "attr", expr: "[]" }
|
|
2870
|
+
];
|
|
2871
|
+
const key = directive(node, "key");
|
|
2872
|
+
if (key) {
|
|
2873
|
+
const keyExpr = directiveExpr(key);
|
|
2874
|
+
const by = isString(key.value) ? `(item) => item[${JSON.stringify(literalOf(key.value))}]` : keyExpr ? ctx.code(keyExpr) : void 0;
|
|
2875
|
+
if (by) props.push({ name: "by", kind: "attr", expr: by });
|
|
2876
|
+
}
|
|
2877
|
+
const content = node.children.filter((c) => !(c.type === "JSXText" && !cleanTemplateText(c.value)));
|
|
2878
|
+
const only = content.length === 1 && content[0].type === "JSXExpressionContainer" ? content[0].expression : null;
|
|
2879
|
+
let render;
|
|
2880
|
+
if (only && (only.type === "ArrowFunctionExpression" || only.type === "FunctionExpression")) {
|
|
2881
|
+
const fn = ctx.code(only);
|
|
2882
|
+
const live = only.type === "ArrowFunctionExpression" && only.body.type !== "BlockStatement" && isReactive(only.body);
|
|
2883
|
+
render = live ? `(...args) => () => (${fn})(...args)` : fn;
|
|
2884
|
+
} else {
|
|
2885
|
+
const built = buildChildren(node.children, ctx);
|
|
2886
|
+
const ir = built.length === 1 ? built[0] : { kind: "fragment", children: built };
|
|
2887
|
+
render = `() => ${paren(emitIR(ir, ctx), "arrowBody")}`;
|
|
2888
|
+
}
|
|
2889
|
+
return { kind: "component", name: "For", props, children: [{ kind: "expr", code: render, reactive: false }] };
|
|
2890
|
+
}
|
|
2891
|
+
function buildElement(node, ctx, handled) {
|
|
2892
|
+
const skip = new Set(handled);
|
|
2893
|
+
const directives = /* @__PURE__ */ new Set(["if", "else", "each", ...directive(node, "each") ? ["key"] : []]);
|
|
2894
|
+
const attributes = node.openingElement.attributes.filter(
|
|
2895
|
+
(a) => !(a.type === "JSXAttribute" && a.name.type === "JSXIdentifier" && (skip.has(a.name.name) || directives.has(a.name.name)))
|
|
2896
|
+
);
|
|
2897
|
+
const { tag } = tagInfo(node.openingElement.name, ctx);
|
|
2898
|
+
const each = buildEach(node, ctx);
|
|
2899
|
+
const children = each ? [each] : buildChildren(node.children, ctx);
|
|
2900
|
+
if (tag === CONTAINER2) return children.length === 1 ? children[0] : { kind: "fragment", children };
|
|
2901
|
+
const at = ctx.sourceFile && node.loc?.start ? { file: ctx.sourceFile, line: node.loc.start.line, column: node.loc.start.column } : void 0;
|
|
2902
|
+
const props = buildProps(attributes, ctx, true);
|
|
2903
|
+
const scope = ctx.scopes?.find((s) => node.start >= s.start && node.end <= s.end);
|
|
2904
|
+
if (scope) props.unshift({ name: "data-fx-s", kind: "attr", literal: scope.value });
|
|
2905
|
+
return { kind: "element", tag, svg: SVG_TAGS.has(tag), props, children, static: false, ...at ? { at } : {} };
|
|
2906
|
+
}
|
|
1886
2907
|
function buildNode(node, ctx) {
|
|
1887
2908
|
if (node.type === "JSXFragment") {
|
|
1888
2909
|
return { kind: "fragment", children: buildChildren(node.children, ctx) };
|
|
1889
2910
|
}
|
|
2911
|
+
if (directive(node, "if")) return buildIf(node, null, ctx);
|
|
2912
|
+
if (ctx.dropStyles?.has(node.start)) return { kind: "fragment", children: [] };
|
|
1890
2913
|
const { tag, component } = tagInfo(node.openingElement.name, ctx);
|
|
2914
|
+
if (!component) return buildElement(node, ctx, []);
|
|
1891
2915
|
const props = buildProps(node.openingElement.attributes, ctx);
|
|
1892
2916
|
const children = buildChildren(node.children, ctx);
|
|
1893
2917
|
const at = ctx.sourceFile && node.loc?.start ? { file: ctx.sourceFile, line: node.loc.start.line, column: node.loc.start.column } : void 0;
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
return { kind: "component", name: tag, props, children, ...load ? { load } : {}, ...at ? { at } : {} };
|
|
1897
|
-
}
|
|
1898
|
-
return { kind: "element", tag, svg: SVG_TAGS.has(tag), props, children, static: false, ...at ? { at } : {} };
|
|
2918
|
+
const load = readLoad(node.openingElement.attributes);
|
|
2919
|
+
return { kind: "component", name: tag, props, children, ...load ? { load } : {}, ...at ? { at } : {} };
|
|
1899
2920
|
}
|
|
1900
2921
|
function buildJsxIR(node, ctx) {
|
|
1901
2922
|
const ir = buildNode(node, ctx);
|
|
@@ -2394,8 +3415,8 @@ function isJsxRoot(node, parent, key) {
|
|
|
2394
3415
|
if (!isJsx(node)) return false;
|
|
2395
3416
|
return !(parent && isJsx(parent) && key === "children");
|
|
2396
3417
|
}
|
|
2397
|
-
function isTemplateTag(node,
|
|
2398
|
-
return node.type === "TaggedTemplateExpression" && node.tag?.type === "Identifier" && (node.tag.name
|
|
3418
|
+
function isTemplateTag(node, tags) {
|
|
3419
|
+
return node.type === "TaggedTemplateExpression" && node.tag?.type === "Identifier" && tags.has(node.tag.name);
|
|
2399
3420
|
}
|
|
2400
3421
|
function outermost(list) {
|
|
2401
3422
|
return list.filter(
|
|
@@ -2541,24 +3562,30 @@ function transformTemplates(code, id, options = {}) {
|
|
|
2541
3562
|
const wantsJsx = format !== "lit";
|
|
2542
3563
|
const mayHaveTemplate = wantsLit && (code.includes(`${litTag}\``) || code.includes("svg`"));
|
|
2543
3564
|
const wantsIntrinsics = options.intrinsics !== false && mayHaveIntrinsic(code);
|
|
2544
|
-
const wantsSources = options.sourceLocations === true &&
|
|
3565
|
+
const wantsSources = options.sourceLocations === true && mayHaveSourceMarks(code);
|
|
2545
3566
|
const sourceName = relativeToRoot(id, options.sourceRoot);
|
|
2546
|
-
|
|
3567
|
+
const wantsStyles = options.styles !== void 0 && (code.includes("<style") || code.includes("css`"));
|
|
3568
|
+
if (!mayHaveTemplate && !(wantsJsx && code.includes("<")) && !wantsIntrinsics && !wantsSources && !wantsStyles) return null;
|
|
2547
3569
|
const ast = (0, import_parser2.parse)(code, {
|
|
2548
3570
|
sourceType: "module",
|
|
2549
3571
|
plugins: ["jsx", "typescript"],
|
|
2550
3572
|
errorRecovery: true
|
|
2551
3573
|
});
|
|
3574
|
+
const intrinsicTags = options.intrinsics === false ? /* @__PURE__ */ new Map() : tagIntrinsics(moduleBindings(ast.program));
|
|
3575
|
+
const templateTags = /* @__PURE__ */ new Map([[litTag, "html"], ["svg", "svg"]]);
|
|
3576
|
+
for (const [name, tag] of intrinsicTags) if (tag !== "css") templateTags.set(name, tag);
|
|
3577
|
+
const cssTags = [...intrinsicTags].filter(([, tag]) => tag === "css").map(([name]) => name);
|
|
2552
3578
|
const found = [];
|
|
2553
3579
|
walk7(ast.program, (n, parent, key) => {
|
|
2554
|
-
if (wantsLit && isTemplateTag(n,
|
|
3580
|
+
if (wantsLit && isTemplateTag(n, templateTags)) found.push(n);
|
|
2555
3581
|
else if (wantsJsx && isJsxRoot(n, parent, key)) found.push(n);
|
|
2556
3582
|
});
|
|
2557
3583
|
const props = options.propsDestructure === false ? { edits: [], diagnostics: [], used: /* @__PURE__ */ new Set() } : collectPropsEdits(ast.program, code, { runtimeModule: options.runtimeModule });
|
|
2558
3584
|
const intrinsics = options.intrinsics === false ? { edits: [], diagnostics: [], imports: /* @__PURE__ */ new Map() } : collectIntrinsicEdits(ast.program);
|
|
2559
3585
|
if (intrinsics.edits.length) avoidBindingClashes(ast.program, intrinsics, moduleBindings(ast.program));
|
|
2560
3586
|
const sources = options.sourceLocations === true ? collectSourceEdits(ast.program, sourceName) : { edits: [], marked: 0 };
|
|
2561
|
-
const
|
|
3587
|
+
const styles = wantsStyles ? collectStyles(ast.program, sourceName, options.styles, { html: templateTags, css: cssTags }, { id, code }) : void 0;
|
|
3588
|
+
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;
|
|
2562
3589
|
if (silent) return null;
|
|
2563
3590
|
found.sort((a, b) => b.start - a.start || a.end - b.end);
|
|
2564
3591
|
const used = new Set(props.used);
|
|
@@ -2572,20 +3599,32 @@ function transformTemplates(code, id, options = {}) {
|
|
|
2572
3599
|
declared: declaredNames(ast.program)
|
|
2573
3600
|
};
|
|
2574
3601
|
const hoisted = /* @__PURE__ */ new Map();
|
|
2575
|
-
const edits = [...props.edits, ...intrinsics.edits, ...sources.edits];
|
|
3602
|
+
const edits = [...props.edits, ...intrinsics.edits, ...sources.edits, ...styles?.edits ?? []];
|
|
2576
3603
|
for (const node of found) {
|
|
2577
3604
|
const nested = found.some(
|
|
2578
3605
|
(o) => o !== node && o.start <= node.start && o.end >= node.end && o.end - o.start > node.end - node.start
|
|
2579
3606
|
);
|
|
2580
3607
|
if (isJsx(node)) {
|
|
2581
|
-
edits.push({ start: node.start, end: node.end, code: compileJsx(code, node, edits, nested, used, needs, hoisted, options, sourceName) });
|
|
3608
|
+
edits.push({ start: node.start, end: node.end, code: compileJsx(code, node, edits, nested, used, needs, hoisted, options, sourceName, styles) });
|
|
2582
3609
|
continue;
|
|
2583
3610
|
}
|
|
2584
3611
|
const holes = node.quasi.expressions.map(
|
|
2585
3612
|
(e) => bindHole(code, e, edits, options.sourceLocations === true)
|
|
2586
3613
|
);
|
|
3614
|
+
const scope = styles?.scopes.find((s) => node.start >= s.start && node.end <= s.end)?.value;
|
|
3615
|
+
const owner = styles?.templateOwners.get(node.start);
|
|
3616
|
+
const templateStyles = options.styles && styles && (scope || owner) ? {
|
|
3617
|
+
options: options.styles,
|
|
3618
|
+
...scope ? { scope } : {},
|
|
3619
|
+
...owner ? { owner } : {},
|
|
3620
|
+
line: node.loc?.start.line ?? 0,
|
|
3621
|
+
column: node.loc?.start.column ?? 0,
|
|
3622
|
+
styles: styles.styles,
|
|
3623
|
+
diagnostics: styles.diagnostics
|
|
3624
|
+
} : void 0;
|
|
2587
3625
|
const result = compilePieces(toPieces(node), holes, {
|
|
2588
3626
|
...options,
|
|
3627
|
+
...templateStyles ? { templateStyles } : {},
|
|
2589
3628
|
hoistTemplates: true,
|
|
2590
3629
|
// A tag inside a template gets the same mark a JSX tag does. Without one, the nodes it
|
|
2591
3630
|
// makes are the only ones in the module carrying no mark, and they take whichever was
|
|
@@ -2594,12 +3633,13 @@ function transformTemplates(code, id, options = {}) {
|
|
|
2594
3633
|
// Same defaults as the plugin, so moving a build over is not a rendering change.
|
|
2595
3634
|
templateClone: options.templateClone ?? true,
|
|
2596
3635
|
partialTemplates: nested ? false : options.partialTemplates ?? true,
|
|
2597
|
-
svg: node.tag.name === "svg"
|
|
3636
|
+
svg: templateTags.get(node.tag.name) === "svg"
|
|
2598
3637
|
});
|
|
2599
3638
|
for (const symbol of result.imports) used.add(symbol);
|
|
2600
3639
|
collectNeeds(result.ir, needs);
|
|
2601
3640
|
edits.push({ start: node.start, end: node.end, code: adoptTemplates(result.code, result.templates, hoisted) });
|
|
2602
3641
|
}
|
|
3642
|
+
if (styles && options.styles) edits.push(...finishShadowStyles(styles, code, id));
|
|
2603
3643
|
const out = new import_magic_string2.default(code);
|
|
2604
3644
|
for (const e of outermost(edits)) {
|
|
2605
3645
|
if (e.start === e.end) out.appendLeft(e.start, e.code);
|
|
@@ -2657,13 +3697,19 @@ function transformTemplates(code, id, options = {}) {
|
|
|
2657
3697
|
...loadDiagnostics.length ? { loadDiagnostics } : {},
|
|
2658
3698
|
...unresolvedDiagnostics.length ? { unresolvedDiagnostics } : {},
|
|
2659
3699
|
...props.diagnostics.length ? { propsDiagnostics: props.diagnostics } : {},
|
|
2660
|
-
...intrinsics.diagnostics.length ? { intrinsicDiagnostics: intrinsics.diagnostics } : {}
|
|
3700
|
+
...intrinsics.diagnostics.length ? { intrinsicDiagnostics: intrinsics.diagnostics } : {},
|
|
3701
|
+
...styles?.styles.length ? { styles: styles.styles } : {},
|
|
3702
|
+
...styles?.diagnostics.length ? { styleDiagnostics: styles.diagnostics } : {},
|
|
3703
|
+
...styles?.literals.length ? { styleLiterals: styles.literals } : {},
|
|
3704
|
+
...styles?.references.length ? { styleReferences: styles.references } : {}
|
|
2661
3705
|
};
|
|
2662
3706
|
}
|
|
2663
|
-
function compileJsx(code, node, edits, nested, used, needs, hoisted, options, sourceFile) {
|
|
3707
|
+
function compileJsx(code, node, edits, nested, used, needs, hoisted, options, sourceFile, styles) {
|
|
2664
3708
|
const ir = buildJsxIR(node, {
|
|
2665
3709
|
code: (n) => slice(code, n.start, n.end, edits),
|
|
2666
3710
|
used,
|
|
3711
|
+
...styles?.scopes.length ? { scopes: styles.scopes } : {},
|
|
3712
|
+
...styles?.drop.size ? { dropStyles: styles.drop } : {},
|
|
2667
3713
|
...options.sourceLocations === true && sourceFile ? { sourceFile } : {}
|
|
2668
3714
|
});
|
|
2669
3715
|
analyzeStatic(ir);
|