@fluixi/compiler 1.0.0-alpha.94 → 1.0.0-alpha.96

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.
Files changed (60) hide show
  1. package/LICENSE +1 -1
  2. package/dist/analyze/static-graph.cjs +1 -1
  3. package/dist/analyze/static-graph.mjs +1 -1
  4. package/dist/{babel-RJFQVFJW.mjs → babel-YG5PQAMX.mjs} +4 -4
  5. package/dist/{chunk-ZR2QHTEX.mjs → chunk-JHBI26FW.mjs} +6 -4
  6. package/dist/{chunk-DP2QDWWH.mjs → chunk-JJ4ZAZKY.mjs} +1 -1
  7. package/dist/{chunk-HCCBEJEZ.mjs → chunk-L6WBOEIO.mjs} +1 -1
  8. package/dist/{chunk-HIZU7WI2.mjs → chunk-UVH2BMMY.mjs} +1 -1
  9. package/dist/chunk-VX2OBUMB.mjs +92 -0
  10. package/dist/{chunk-E2RWTIYE.mjs → chunk-X735CULF.mjs} +4 -89
  11. package/dist/chunk-ZPEHDBCH.mjs +584 -0
  12. package/dist/codegen/backends/imperative.cjs +4 -2
  13. package/dist/codegen/backends/imperative.d.ts.map +1 -1
  14. package/dist/codegen/backends/imperative.js +9 -2
  15. package/dist/codegen/backends/imperative.mjs +4 -2
  16. package/dist/frontend/babel/build-ir-lit.cjs +4 -2
  17. package/dist/frontend/babel/build-ir-lit.mjs +4 -2
  18. package/dist/frontend/babel/build-ir.cjs +4 -2
  19. package/dist/frontend/babel/build-ir.mjs +4 -2
  20. package/dist/frontend/babel/index.cjs +5 -3
  21. package/dist/frontend/babel/index.mjs +5 -3
  22. package/dist/frontend/babel/lower-template.cjs +4 -2
  23. package/dist/frontend/babel/lower-template.mjs +4 -2
  24. package/dist/frontend/babel/plugin.cjs +4 -2
  25. package/dist/frontend/babel/plugin.mjs +4 -2
  26. package/dist/index.cjs +5 -3
  27. package/dist/index.mjs +5 -3
  28. package/dist/integrations.cjs +3330 -3269
  29. package/dist/integrations.d.ts.map +1 -1
  30. package/dist/integrations.js +19 -8
  31. package/dist/integrations.mjs +85 -40
  32. package/dist/lower/compile-template.cjs +5 -3
  33. package/dist/lower/compile-template.mjs +5 -3
  34. package/dist/lower/jsx.cjs +4 -2
  35. package/dist/lower/jsx.mjs +4 -2
  36. package/dist/lower/template.cjs +4 -2
  37. package/dist/lower/template.mjs +4 -2
  38. package/dist/resolve/builtins.cjs +1 -1
  39. package/dist/resolve/builtins.mjs +1 -1
  40. package/dist/{server-fns-JLSTKWPS.mjs → server-fns-PZEOON2D.mjs} +5 -4
  41. package/dist/{server-functions-BGY3RD4R.mjs → server-functions-JNSQMA63.mjs} +3 -3
  42. package/dist/transform/index.cjs +35 -16
  43. package/dist/transform/index.mjs +35 -16
  44. package/dist/transform/styles.cjs +31 -13
  45. package/dist/transform/styles.d.cts +27 -1
  46. package/dist/transform/styles.d.ts +27 -1
  47. package/dist/transform/styles.d.ts.map +1 -1
  48. package/dist/transform/styles.js +45 -16
  49. package/dist/transform/styles.mjs +31 -13
  50. package/dist/transform/templates.cjs +34 -15
  51. package/dist/transform/templates.mjs +34 -15
  52. package/dist/{transform-GBP6Y4UI.mjs → transform-UODP37VJ.mjs} +12 -563
  53. package/dist/tsconfig.lib.tsbuildinfo +1 -1
  54. package/dist/vite-styles.cjs +66 -23
  55. package/dist/vite-styles.d.cts +16 -7
  56. package/dist/vite-styles.d.ts +16 -7
  57. package/dist/vite-styles.d.ts.map +1 -1
  58. package/dist/vite-styles.js +68 -25
  59. package/dist/vite-styles.mjs +78 -23
  60. package/package.json +4 -4
@@ -0,0 +1,584 @@
1
+ /*! @fluixi/compiler v1.0.0-alpha.96 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
2
+ import {
3
+ encode
4
+ } from "./chunk-VX2OBUMB.mjs";
5
+
6
+ // src/transform/styles.ts
7
+ var SCOPE_ATTR = "data-fx-s";
8
+ var FUNCTIONS = /* @__PURE__ */ new Set(["FunctionDeclaration", "FunctionExpression", "ArrowFunctionExpression", "ObjectMethod", "ClassMethod"]);
9
+ function collectStyles(program, sourceName, options, tags = { html: /* @__PURE__ */ new Map([["html", "html"]]) }, module) {
10
+ const plan = {
11
+ scopes: [],
12
+ templateOwners: /* @__PURE__ */ new Map(),
13
+ drop: /* @__PURE__ */ new Set(),
14
+ styles: [],
15
+ diagnostics: [],
16
+ edits: [],
17
+ literals: [],
18
+ references: [],
19
+ shadowClasses: /* @__PURE__ */ new Map()
20
+ };
21
+ if (!options) return plan;
22
+ const literalsOf = findLiterals(program, options.cssModules ?? ["@fluixi/core", "@fluixi/dom"], plan, tags.css ?? []);
23
+ plan.names = literalsOf;
24
+ const classOf = /* @__PURE__ */ new Map();
25
+ const shadowOf = (owner) => {
26
+ const cls = classOf.get(owner);
27
+ return cls ? plan.shadowClasses.get(cls) : void 0;
28
+ };
29
+ const resolved = /* @__PURE__ */ new Map();
30
+ const piecesToNodes = (quasis, expressions, at, stack) => {
31
+ const out = [];
32
+ for (let i = 0; i < quasis.length; i++) {
33
+ const text = quasis[i].value.cooked ?? quasis[i].value.raw;
34
+ if (text.trim()) {
35
+ try {
36
+ const start = quasis[i].loc?.start;
37
+ out.push(...options.process(text, sourceName).map((n) => start ? shiftLoc(n, sourceName, start) : n));
38
+ } catch (error) {
39
+ plan.diagnostics.push({ ...at, message: `CSS could not be processed: ${error.message}` });
40
+ return null;
41
+ }
42
+ }
43
+ const expr = expressions[i];
44
+ if (!expr) continue;
45
+ const value = expr.type === "Identifier" ? resolveLiteral(expr.name, at, stack) : void 0;
46
+ if (value === void 0) {
47
+ plan.diagnostics.push({
48
+ ...at,
49
+ 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))."
50
+ });
51
+ return null;
52
+ }
53
+ if (value === null) return null;
54
+ out.push(...value);
55
+ }
56
+ return out;
57
+ };
58
+ function resolveLiteral(name, at, stack) {
59
+ const imported = literalsOf.imports.get(name);
60
+ if (imported) {
61
+ const nodes = options?.imported?.get(`${imported.source}#${imported.name}`);
62
+ if (nodes) return nodes.map((n) => keepLocIn(n, options?.importedModules));
63
+ plan.references.push({ name: imported.name, source: imported.source, ...at });
64
+ plan.diagnostics.push({
65
+ ...at,
66
+ 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.`
67
+ });
68
+ return null;
69
+ }
70
+ const literal = literalsOf.literals.get(name);
71
+ if (!literal) return void 0;
72
+ if (stack.includes(name)) {
73
+ plan.diagnostics.push({ ...at, message: `css\`\` values include each other: ${[...stack, name].join(" → ")}.` });
74
+ return null;
75
+ }
76
+ if (!resolved.has(name)) {
77
+ resolved.set(name, piecesToNodes(literal.quasi.quasis, literal.quasi.expressions, at, [...stack, name]));
78
+ }
79
+ return resolved.get(name);
80
+ }
81
+ for (const [name, literal] of literalsOf.literals) {
82
+ const at = { line: literal.loc?.start.line ?? 0, column: literal.loc?.start.column ?? 0 };
83
+ const nodes = resolveLiteral(name, at, []);
84
+ const id = hash(`${sourceName}:css:${name}`);
85
+ plan.edits.push({ start: literal.start, end: literal.end, code: `({ $fxStyle: ${JSON.stringify(id)} })` });
86
+ if (nodes) plan.literals.push({ id, name, css: printStyle(nodes, options.minify), nodes });
87
+ }
88
+ const scopeOf = /* @__PURE__ */ new Map();
89
+ const names = /* @__PURE__ */ new Map();
90
+ const named = /* @__PURE__ */ new Map();
91
+ const visit = (node, owners) => {
92
+ if (!node || typeof node !== "object") return;
93
+ if (node.type === "VariableDeclarator" && node.id.type === "Identifier" && node.init && FUNCTIONS.has(node.init.type)) {
94
+ named.set(node.init, node.id.name);
95
+ }
96
+ if ((node.type === "ClassDeclaration" || node.type === "ClassExpression") && node.id) {
97
+ for (const member of node.body.body) if (member.type === "ClassMethod") named.set(member, node.id.name);
98
+ }
99
+ if (node.type === "ClassDeclaration" || node.type === "ClassExpression") {
100
+ for (const member of node.body.body) if (member.type === "ClassMethod") classOf.set(member, node);
101
+ const shadow = staticMember(node, "shadow");
102
+ if (shadow?.value && !(shadow.value.type === "BooleanLiteral" && shadow.value.value === false)) {
103
+ plan.shadowClasses.set(node, { node, styles: staticMember(node, "styles"), indexes: [] });
104
+ }
105
+ }
106
+ if (node.type === "TaggedTemplateExpression" && node.tag.type === "Identifier" && tags.html.get(node.tag.name) === "html") {
107
+ const text = node.quasi.quasis.map((q) => q.value.raw).join("");
108
+ if (/<style[\s>]/.test(text)) {
109
+ const at = { line: node.loc?.start.line ?? 0, column: node.loc?.start.column ?? 0 };
110
+ const owner = owners[0];
111
+ if (!owner) plan.diagnostics.push({ ...at, message: "<style> has to be written inside a component." });
112
+ else {
113
+ const id = idFor(owner);
114
+ const shadow = shadowOf(owner);
115
+ plan.templateOwners.set(node.start, { id, component: functionName(owner, named) });
116
+ for (const block of templateBlocks(node.quasi)) compileBlock(block, block.scoped, owner, at);
117
+ }
118
+ }
119
+ }
120
+ const inner = FUNCTIONS.has(node.type) ? [...owners, node] : owners;
121
+ if (node.type === "JSXElement" && isStyle(node)) {
122
+ handle(node, owners);
123
+ return;
124
+ }
125
+ for (const key of Object.keys(node)) {
126
+ if (key === "loc" || key === "leadingComments" || key === "trailingComments" || key === "innerComments") continue;
127
+ const value = node[key];
128
+ if (Array.isArray(value)) for (const v of value) visit(v, inner);
129
+ else if (value && typeof value === "object" && "type" in value) visit(value, inner);
130
+ }
131
+ };
132
+ const handle = (node, owners) => {
133
+ const at = { line: node.loc?.start.line ?? 0, column: node.loc?.start.column ?? 0 };
134
+ const pieces = blockPieces(node);
135
+ if (pieces === null) {
136
+ plan.diagnostics.push({
137
+ ...at,
138
+ message: "<style> needs its CSS as one template literal, <style>{`...`}</style>: JSX reads a bare `{` as an expression."
139
+ });
140
+ return;
141
+ }
142
+ const owner = owners[0];
143
+ if (!owner) {
144
+ plan.diagnostics.push({ ...at, message: "<style> has to be written inside a component." });
145
+ return;
146
+ }
147
+ compileBlock(pieces, isScoped(node), owner, at);
148
+ plan.drop.add(node.start);
149
+ };
150
+ const compileBlock = (pieces, scoped, owner, at) => {
151
+ const component = functionName(owner, named);
152
+ const id = idFor(owner);
153
+ const processed = piecesToNodes(pieces.quasis, pieces.expressions, at, []);
154
+ if (!processed) return;
155
+ let nodes = processed;
156
+ const shadow = shadowOf(owner);
157
+ if (scoped && !shadow) {
158
+ if (!plan.scopes.some((s) => s.value === id)) plan.scopes.push({ start: owner.start, end: owner.end, value: id });
159
+ nodes = scopeNodes(nodes, id, (message) => plan.diagnostics.push({ ...at, message }));
160
+ }
161
+ const printed = module ? printStyleWithMap(nodes, options.minify, sourceName, module, options.importedModules) : { css: printStyle(nodes, options.minify) };
162
+ plan.styles.push({ id, scoped: scoped && !shadow, component, ...printed, ...shadow ? { shadow: true } : {}, ...at });
163
+ if (shadow) shadow.indexes.push(plan.styles.length - 1);
164
+ };
165
+ function idFor(owner) {
166
+ let id = scopeOf.get(owner);
167
+ if (!id) {
168
+ const component = functionName(owner, named);
169
+ const seen = names.get(component) ?? 0;
170
+ names.set(component, seen + 1);
171
+ id = hash(`${sourceName}:${component}${seen ? ":" + seen : ""}`);
172
+ scopeOf.set(owner, id);
173
+ }
174
+ return id;
175
+ }
176
+ visit(program, []);
177
+ return plan;
178
+ }
179
+ function applyTemplateStyles(ir, t) {
180
+ const walk = (node) => {
181
+ const children = node.children;
182
+ if (children) {
183
+ for (let i = children.length - 1; i >= 0; i--) {
184
+ const child = children[i];
185
+ if (child.kind === "element" && child.tag === "style" && t.owner) children.splice(i, 1);
186
+ else walk(child);
187
+ }
188
+ }
189
+ if (t.scope && node.kind === "element" && node.tag !== "style" && node.props && !node.props.some((p) => p.name === SCOPE_ATTR)) {
190
+ node.props.unshift({ name: SCOPE_ATTR, kind: "attr", literal: t.scope });
191
+ }
192
+ };
193
+ walk(ir);
194
+ }
195
+ function staticMember(cls, name) {
196
+ return cls.body.body.find(
197
+ (m) => m.type === "ClassProperty" && m.static && (m.key.type === "Identifier" && m.key.name === name || m.key.type === "StringLiteral" && m.key.value === name)
198
+ );
199
+ }
200
+ var styleIds = {
201
+ block: (owner, index) => `${owner}.fx-${index}.css`,
202
+ inline: (owner, index) => `${owner}.fx-${index}.css?inline`,
203
+ literal: (owner, name) => `${owner}.fx-literal-${name}.css?inline`
204
+ };
205
+ function finishShadowStyles(plan, code, moduleId) {
206
+ const edits = [];
207
+ const imports = [];
208
+ let next = 0;
209
+ const importOf = (specifier) => {
210
+ const local = `__fxShadow${next++}`;
211
+ imports.push(`import ${local} from ${JSON.stringify(specifier)};
212
+ `);
213
+ return local;
214
+ };
215
+ for (const shadow of plan.shadowClasses.values()) {
216
+ const blocks = shadow.indexes.map((i) => importOf(styleIds.inline(moduleId, i)));
217
+ let value;
218
+ const prop = shadow.styles;
219
+ if (prop?.value) {
220
+ const start = prop.value.start;
221
+ let text = code.slice(start, prop.value.end);
222
+ const replacements = [];
223
+ walkIdentifiers(prop.value, (id) => {
224
+ const local = plan.names?.literals.has(id.name) ? importOf(styleIds.literal(moduleId, id.name)) : plan.names?.imports.has(id.name) && !/\.css(\?|$)/.test(plan.names.imports.get(id.name).source) ? importOf(styleIds.literal(plan.names.imports.get(id.name).source, plan.names.imports.get(id.name).name)) : void 0;
225
+ if (local) replacements.push({ at: id.start - start, length: id.name.length, with: local });
226
+ });
227
+ 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);
228
+ value = text;
229
+ }
230
+ if (!blocks.length && value === void 0) continue;
231
+ if (prop?.value) {
232
+ const merged = blocks.length ? `[${value}, ${blocks.join(", ")}]` : value;
233
+ edits.push({ start: prop.value.start, end: prop.value.end, code: merged });
234
+ } else if (blocks.length) {
235
+ const open = shadow.node.body.start + 1;
236
+ edits.push({ start: open, end: open, code: ` static styles = [${blocks.join(", ")}];` });
237
+ }
238
+ }
239
+ if (imports.length) edits.push({ start: 0, end: 0, code: imports.join("") });
240
+ return edits;
241
+ }
242
+ function walkIdentifiers(node, visit) {
243
+ if (!node || typeof node !== "object") return;
244
+ if (node.type === "Identifier") return visit(node);
245
+ if (node.type === "MemberExpression") return walkIdentifiers(node.object, visit);
246
+ if (node.type === "ObjectProperty") return walkIdentifiers(node.value, visit);
247
+ for (const key of Object.keys(node)) {
248
+ if (key === "loc") continue;
249
+ const value = node[key];
250
+ if (Array.isArray(value)) for (const v of value) walkIdentifiers(v, visit);
251
+ else if (value && typeof value === "object" && "type" in value) walkIdentifiers(value, visit);
252
+ }
253
+ }
254
+ function isStyle(node) {
255
+ const name = node.openingElement.name;
256
+ return name.type === "JSXIdentifier" && name.name === "style";
257
+ }
258
+ function isScoped(node) {
259
+ return node.openingElement.attributes.some((a) => a.type === "JSXAttribute" && a.name.type === "JSXIdentifier" && a.name.name === "scoped");
260
+ }
261
+ function templateBlocks(quasi) {
262
+ const blocks = [];
263
+ let open = null;
264
+ quasi.quasis.forEach((q, i) => {
265
+ const raw = q.value.raw;
266
+ let from = 0;
267
+ while (from <= raw.length) {
268
+ if (!open) {
269
+ const tag = /<style\b([^>]*)>/g;
270
+ tag.lastIndex = from;
271
+ const m = tag.exec(raw);
272
+ if (!m) break;
273
+ open = { quasis: [], expressions: [], scoped: /\bscoped\b/.test(m[1]) };
274
+ from = m.index + m[0].length;
275
+ }
276
+ const close = raw.indexOf("</style", from);
277
+ open.quasis.push(slicePiece(q, raw, from, close === -1 ? raw.length : close));
278
+ if (close === -1) break;
279
+ blocks.push(open);
280
+ open = null;
281
+ from = close;
282
+ }
283
+ const expr = quasi.expressions[i];
284
+ if (open && expr) open.expressions.push(expr);
285
+ });
286
+ return blocks;
287
+ }
288
+ function slicePiece(q, raw, from, to) {
289
+ const text = raw.slice(from, to);
290
+ const start = q.loc?.start;
291
+ if (!start) return { type: "TemplateElement", value: { raw: text, cooked: text } };
292
+ const before = raw.slice(0, from).split("\n");
293
+ const line = start.line + before.length - 1;
294
+ const column = before.length > 1 ? before[before.length - 1].length : start.column + from;
295
+ return { type: "TemplateElement", value: { raw: text, cooked: text }, loc: { start: { line, column } } };
296
+ }
297
+ function blockPieces(node) {
298
+ const meaningful = node.children.filter((c) => !(c.type === "JSXText" && !c.value.trim()));
299
+ if (meaningful.length === 0) return { quasis: [], expressions: [] };
300
+ if (meaningful.length !== 1) return null;
301
+ const only = meaningful[0];
302
+ if (only.type !== "JSXExpressionContainer") return null;
303
+ const expr = only.expression;
304
+ if (expr.type === "StringLiteral") return { quasis: [{ type: "TemplateElement", value: { raw: expr.value, cooked: expr.value } }], expressions: [] };
305
+ if (expr.type === "TemplateLiteral") return { quasis: expr.quasis, expressions: expr.expressions };
306
+ return null;
307
+ }
308
+ function findLiterals(program, modules, plan, intrinsic) {
309
+ const literals = /* @__PURE__ */ new Map();
310
+ const imports = /* @__PURE__ */ new Map();
311
+ const tags = new Set(intrinsic);
312
+ for (const statement of program.body ?? []) {
313
+ if (statement.type !== "ImportDeclaration") continue;
314
+ const source = statement.source.value;
315
+ const specifiers = statement.specifiers;
316
+ for (const sp of specifiers) {
317
+ if (sp.type === "ImportSpecifier") imports.set(sp.local.name, { source, name: sp.imported.name ?? sp.imported.value });
318
+ }
319
+ if (!modules.includes(source)) continue;
320
+ const css = specifiers.find((sp) => sp.type === "ImportSpecifier" && (sp.imported.name ?? sp.imported.value) === "css");
321
+ if (!css) continue;
322
+ const local = css.local.name;
323
+ tags.add(local);
324
+ imports.delete(local);
325
+ plan.edits.push({ start: statement.start, end: statement.end, code: importWithout(statement, css) });
326
+ }
327
+ if (tags.size === 0) return { literals, imports };
328
+ const visit = (node) => {
329
+ if (!node || typeof node !== "object") return;
330
+ if (node.type === "VariableDeclarator" && node.id.type === "Identifier" && node.init?.type === "TaggedTemplateExpression" && node.init.tag.type === "Identifier" && tags.has(node.init.tag.name)) {
331
+ literals.set(node.id.name, node.init);
332
+ }
333
+ for (const key of Object.keys(node)) {
334
+ if (key === "loc") continue;
335
+ const value = node[key];
336
+ if (Array.isArray(value)) for (const v of value) visit(v);
337
+ else if (value && typeof value === "object" && "type" in value) visit(value);
338
+ }
339
+ };
340
+ visit(program);
341
+ return { literals, imports };
342
+ }
343
+ function importWithout(statement, removed) {
344
+ const rest = statement.specifiers.filter((sp) => sp !== removed);
345
+ const source = JSON.stringify(statement.source.value);
346
+ if (rest.length === 0) return "";
347
+ const def = rest.find((sp) => sp.type === "ImportDefaultSpecifier");
348
+ const ns = rest.find((sp) => sp.type === "ImportNamespaceSpecifier");
349
+ const named = rest.filter((sp) => sp.type === "ImportSpecifier").map((sp) => {
350
+ const imported = sp.imported.name ?? JSON.stringify(sp.imported.value);
351
+ return imported === sp.local.name ? imported : `${imported} as ${sp.local.name}`;
352
+ });
353
+ const parts = [def?.local.name, ns ? `* as ${ns.local.name}` : void 0, named.length ? `{ ${named.join(", ")} }` : void 0].filter(Boolean);
354
+ return `import ${parts.join(", ")} from ${source};`;
355
+ }
356
+ function functionName(fn, named) {
357
+ if ((fn.type === "FunctionDeclaration" || fn.type === "FunctionExpression") && fn.id) return fn.id.name;
358
+ return named.get(fn) ?? "anonymous";
359
+ }
360
+ function hash(text) {
361
+ let h = 2166136261;
362
+ for (let i = 0; i < text.length; i++) {
363
+ h ^= text.charCodeAt(i);
364
+ h = Math.imul(h, 16777619);
365
+ }
366
+ return (h >>> 0).toString(36);
367
+ }
368
+ var OPAQUE = /(^|-)keyframes$|^font-face$|^property$|^counter-style$|^page$|^font-feature-values$/;
369
+ function scopeNodes(nodes, id, warn = () => {
370
+ }) {
371
+ return nodes.map((node) => {
372
+ if (node.kind === "rule") return { ...node, selector: scopeSelector(node.selector, id, warn) };
373
+ if (node.kind === "at-rule" && !OPAQUE.test(node.name)) return { ...node, nodes: scopeNodes(node.nodes, id, warn) };
374
+ return node;
375
+ });
376
+ }
377
+ function scopeSelector(selector, id, warn = () => {
378
+ }) {
379
+ return splitTop(selector, ",").map((complex) => scopeComplex(complex.trim(), `[${SCOPE_ATTR}="${id}"]`, warn)).join(", ");
380
+ }
381
+ function scopeComplex(selector, attr, warn) {
382
+ if (/:host\b|::slotted\(/.test(selector)) {
383
+ warn(`\`${selector}\` only means something in a shadow root; in a light-DOM component it is left as written.`);
384
+ return selector;
385
+ }
386
+ const parts = compounds(selector);
387
+ const deep = parts.findIndex((p) => p.text.startsWith(":deep("));
388
+ if (deep !== -1) {
389
+ const inner = unwrap(parts[deep].text, ":deep(");
390
+ const before = parts.slice(0, deep);
391
+ if (before.length === 0) return `${attr} ${inner}`;
392
+ const scopedBefore = scopeAt(before, before.length - 1, attr);
393
+ return `${join(scopedBefore)} ${inner}`;
394
+ }
395
+ let target = -1;
396
+ for (let i = parts.length - 1; i >= 0; i--) {
397
+ if (!parts[i].text.startsWith(":global(")) {
398
+ target = i;
399
+ break;
400
+ }
401
+ }
402
+ const out = target === -1 ? parts : scopeAt(parts, target, attr);
403
+ return join(out.map((p) => p.text.startsWith(":global(") ? { ...p, text: unwrap(p.text, ":global(") } : p));
404
+ }
405
+ function scopeAt(parts, index, attr) {
406
+ return parts.map((p, i) => i === index ? { ...p, text: insertAttr(p.text, attr) } : p);
407
+ }
408
+ function insertAttr(compound, attr) {
409
+ let depth = 0;
410
+ let quote = "";
411
+ for (let i = 0; i < compound.length; i++) {
412
+ const c = compound[i];
413
+ if (quote) {
414
+ if (c === "\\") i++;
415
+ else if (c === quote) quote = "";
416
+ continue;
417
+ }
418
+ if (c === "\\") {
419
+ i++;
420
+ continue;
421
+ }
422
+ if (c === '"' || c === "'") quote = c;
423
+ else if (c === "(" || c === "[") depth++;
424
+ else if (c === ")" || c === "]") depth--;
425
+ else if (c === ":" && depth === 0 && i > 0) return compound.slice(0, i) + attr + compound.slice(i);
426
+ }
427
+ return compound + attr;
428
+ }
429
+ function compounds(selector) {
430
+ const out = [];
431
+ let depth = 0;
432
+ let quote = "";
433
+ let current = "";
434
+ let combinator = "";
435
+ const push = () => {
436
+ if (current.trim()) out.push({ combinator: out.length ? combinator || " " : "", text: current.trim() });
437
+ current = "";
438
+ combinator = "";
439
+ };
440
+ for (let i = 0; i < selector.length; i++) {
441
+ const c = selector[i];
442
+ if (quote) {
443
+ current += c;
444
+ if (c === "\\") current += selector[++i] ?? "";
445
+ else if (c === quote) quote = "";
446
+ continue;
447
+ }
448
+ if (c === "\\") {
449
+ current += c + (selector[++i] ?? "");
450
+ continue;
451
+ }
452
+ if (c === '"' || c === "'") quote = c;
453
+ if (c === "(" || c === "[") depth++;
454
+ if (c === ")" || c === "]") depth--;
455
+ if (depth === 0 && (c === ">" || c === "+" || c === "~")) {
456
+ push();
457
+ combinator = c;
458
+ continue;
459
+ }
460
+ if (depth === 0 && /\s/.test(c)) {
461
+ if (current.trim()) {
462
+ const keep = combinator;
463
+ push();
464
+ combinator = keep;
465
+ }
466
+ continue;
467
+ }
468
+ current += c;
469
+ }
470
+ push();
471
+ return out;
472
+ }
473
+ function join(parts) {
474
+ return parts.map((p, i) => i === 0 ? p.text : p.combinator === " " ? ` ${p.text}` : ` ${p.combinator} ${p.text}`).join("");
475
+ }
476
+ function unwrap(text, prefix) {
477
+ return text.slice(prefix.length, text.lastIndexOf(")")).trim() + text.slice(text.lastIndexOf(")") + 1);
478
+ }
479
+ function splitTop(selector, separator) {
480
+ const parts = [];
481
+ let depth = 0;
482
+ let quote = "";
483
+ let start = 0;
484
+ for (let i = 0; i < selector.length; i++) {
485
+ const c = selector[i];
486
+ if (quote) {
487
+ if (c === "\\") i++;
488
+ else if (c === quote) quote = "";
489
+ } else if (c === '"' || c === "'") quote = c;
490
+ else if (c === "\\") i++;
491
+ else if (c === "(" || c === "[") depth++;
492
+ else if (c === ")" || c === "]") depth--;
493
+ else if (c === separator && depth === 0) {
494
+ parts.push(selector.slice(start, i));
495
+ start = i + 1;
496
+ }
497
+ }
498
+ parts.push(selector.slice(start));
499
+ return parts.filter((p) => p.trim());
500
+ }
501
+ function shiftLoc(node, source, start) {
502
+ 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;
503
+ if (node.kind === "rule" || node.kind === "at-rule") return { ...node, loc, nodes: node.nodes.map((n) => shiftLoc(n, source, start)) };
504
+ return { ...node, loc };
505
+ }
506
+ function keepLocIn(node, modules) {
507
+ const keep = node.loc !== void 0 && modules?.has(node.loc.source) === true;
508
+ const { loc, ...rest } = node;
509
+ const kept = keep ? { ...rest, loc } : rest;
510
+ if (kept.kind === "rule" || kept.kind === "at-rule") return { ...kept, nodes: kept.nodes.map((n) => keepLocIn(n, modules)) };
511
+ return kept;
512
+ }
513
+ function printStyleWithMap(nodes, minify, sourceName, module, others) {
514
+ const sources = [module];
515
+ const index = /* @__PURE__ */ new Map([[sourceName, 0]]);
516
+ const sourceOf = (name) => {
517
+ if (index.has(name)) return index.get(name);
518
+ const other = others?.get(name);
519
+ if (!other) return void 0;
520
+ index.set(name, sources.push(other) - 1);
521
+ return index.get(name);
522
+ };
523
+ const lines = [[]];
524
+ let css = "";
525
+ let column = 0;
526
+ const emit = (text) => {
527
+ for (const ch of text) {
528
+ css += ch;
529
+ if (ch === "\n") {
530
+ lines.push([]);
531
+ column = 0;
532
+ } else column++;
533
+ }
534
+ };
535
+ const mark = (loc) => {
536
+ const at = loc ? sourceOf(loc.source) : void 0;
537
+ if (loc && at !== void 0) lines[lines.length - 1].push([column, at, loc.line - 1, loc.column]);
538
+ };
539
+ const write = (node, depth) => {
540
+ const pad = minify ? "" : " ".repeat(depth);
541
+ const nl = minify ? "" : "\n";
542
+ const sp = minify ? "" : " ";
543
+ emit(pad);
544
+ mark(node.loc);
545
+ if (node.kind === "declaration") {
546
+ emit(`${node.property}:${sp}${node.value}${node.important ? `${sp}!important` : ""};${nl}`);
547
+ } else if (node.kind === "raw") {
548
+ emit(`${node.text}${nl}`);
549
+ } else {
550
+ emit(`${node.kind === "rule" ? node.selector : `@${node.name}${node.params ? " " + node.params : ""}`}${sp}{${nl}`);
551
+ for (const child of node.nodes) write(child, depth + 1);
552
+ emit(`${pad}}${nl}`);
553
+ }
554
+ };
555
+ for (const node of nodes) write(node, 0);
556
+ return { css, map: { version: 3, sources: sources.map((s) => s.id), sourcesContent: sources.map((s) => s.code), names: [], mappings: encode(lines) } };
557
+ }
558
+ function printStyle(nodes, minify = false) {
559
+ const out = [];
560
+ const write = (node, depth) => {
561
+ const pad = minify ? "" : " ".repeat(depth);
562
+ const nl = minify ? "" : "\n";
563
+ const sp = minify ? "" : " ";
564
+ if (node.kind === "declaration") {
565
+ out.push(`${pad}${node.property}:${sp}${node.value}${node.important ? `${sp}!important` : ""};${nl}`);
566
+ } else if (node.kind === "raw") {
567
+ out.push(`${pad}${node.text}${nl}`);
568
+ } else {
569
+ const header = node.kind === "rule" ? node.selector : `@${node.name}${node.params ? " " + node.params : ""}`;
570
+ out.push(`${pad}${header}${sp}{${nl}`);
571
+ for (const child of node.nodes) write(child, depth + 1);
572
+ out.push(`${pad}}${nl}`);
573
+ }
574
+ };
575
+ for (const node of nodes) write(node, 0);
576
+ return out.join("");
577
+ }
578
+
579
+ export {
580
+ collectStyles,
581
+ applyTemplateStyles,
582
+ styleIds,
583
+ finishShadowStyles
584
+ };
@@ -539,14 +539,16 @@ function emitNode(node, used, templates) {
539
539
  for (const child of node.children) {
540
540
  used.add("insert");
541
541
  const childCode = emitNode(child, used, templates);
542
- const isFn = child.kind === "expr" && child.reactive || child.kind === "component" || child.kind === "control";
543
- parts.push(isFn ? `insert(${el}, ${childCode}, null);` : `insert(${el}, ${childCode});`);
542
+ const anchored = child.kind === "expr" && (child.reactive || !isLiteralCode(child.code)) || child.kind === "component" || child.kind === "control";
543
+ parts.push(anchored ? `insert(${el}, ${childCode}, null);` : `insert(${el}, ${childCode});`);
544
544
  }
545
545
  parts.push(`return ${el};`);
546
546
  return `(() => { ${parts.join(" ")} })()`;
547
547
  }
548
548
  }
549
549
  }
550
+ var LITERAL = /^\s*(?:'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|`[^`$]*`|-?\d[\d_.eE+-]*|true|false|null|undefined)\s*$/;
551
+ var isLiteralCode = (code) => LITERAL.test(code);
550
552
  function inlineTemplates(code, templates) {
551
553
  if (!templates || templates.length === 0) return code;
552
554
  const byId = new Map(templates.map((t) => [t.id, JSON.stringify(t.html)]));
@@ -1 +1 @@
1
- {"version":3,"file":"imperative.d.ts","sourceRoot":"","sources":["../../../src/codegen/backends/imperative.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAiB,cAAc,EAAE,MAAM,eAAe,CAAC;AAmVnF;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,cAAc,EAAE,GAAG,SAAS,GAAG,MAAM,CAK7F;AAED,eAAO,MAAM,iBAAiB,EAAE,cAgB/B,CAAC"}
1
+ {"version":3,"file":"imperative.d.ts","sourceRoot":"","sources":["../../../src/codegen/backends/imperative.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAiB,cAAc,EAAE,MAAM,eAAe,CAAC;AA2VnF;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,cAAc,EAAE,GAAG,SAAS,GAAG,MAAM,CAK7F;AAED,eAAO,MAAM,iBAAiB,EAAE,cAgB/B,CAAC"}
@@ -295,16 +295,23 @@ function emitNode(node, used, templates) {
295
295
  for (const child of node.children) {
296
296
  used.add('insert');
297
297
  const childCode = emitNode(child, used, templates);
298
- const isFn = (child.kind === 'expr' && child.reactive) ||
298
+ // `null` asks insert for an anchor of its own, which holds the child's place among
299
+ // its siblings. Every child whose content can change needs one: an expression the
300
+ // classifier calls opaque (an arrow, a function passed by name) may still be one.
301
+ // Only a literal never changes, and it goes straight in.
302
+ const anchored = (child.kind === 'expr' && (child.reactive || !isLiteralCode(child.code))) ||
299
303
  child.kind === 'component' ||
300
304
  child.kind === 'control';
301
- parts.push(isFn ? `insert(${el}, ${childCode}, null);` : `insert(${el}, ${childCode});`);
305
+ parts.push(anchored ? `insert(${el}, ${childCode}, null);` : `insert(${el}, ${childCode});`);
302
306
  }
303
307
  parts.push(`return ${el};`);
304
308
  return `(() => { ${parts.join(' ')} })()`;
305
309
  }
306
310
  }
307
311
  }
312
+ /** A string, number, boolean or nullish literal: an expression that never renders anything else. */
313
+ const LITERAL = /^\s*(?:'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|`[^`$]*`|-?\d[\d_.eE+-]*|true|false|null|undefined)\s*$/;
314
+ const isLiteralCode = (code) => LITERAL.test(code);
308
315
  /**
309
316
  * Substitute template declarations into the code as inline `createTemplate` calls.
310
317
  *
@@ -512,14 +512,16 @@ function emitNode(node, used, templates) {
512
512
  for (const child of node.children) {
513
513
  used.add("insert");
514
514
  const childCode = emitNode(child, used, templates);
515
- const isFn = child.kind === "expr" && child.reactive || child.kind === "component" || child.kind === "control";
516
- parts.push(isFn ? `insert(${el}, ${childCode}, null);` : `insert(${el}, ${childCode});`);
515
+ const anchored = child.kind === "expr" && (child.reactive || !isLiteralCode(child.code)) || child.kind === "component" || child.kind === "control";
516
+ parts.push(anchored ? `insert(${el}, ${childCode}, null);` : `insert(${el}, ${childCode});`);
517
517
  }
518
518
  parts.push(`return ${el};`);
519
519
  return `(() => { ${parts.join(" ")} })()`;
520
520
  }
521
521
  }
522
522
  }
523
+ var LITERAL = /^\s*(?:'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|`[^`$]*`|-?\d[\d_.eE+-]*|true|false|null|undefined)\s*$/;
524
+ var isLiteralCode = (code) => LITERAL.test(code);
523
525
  function inlineTemplates(code, templates) {
524
526
  if (!templates || templates.length === 0) return code;
525
527
  const byId = new Map(templates.map((t) => [t.id, JSON.stringify(t.html)]));
@@ -604,14 +604,16 @@ function emitNode(node, used, templates) {
604
604
  for (const child of node.children) {
605
605
  used.add("insert");
606
606
  const childCode = emitNode(child, used, templates);
607
- const isFn = child.kind === "expr" && child.reactive || child.kind === "component" || child.kind === "control";
608
- parts.push(isFn ? `insert(${el}, ${childCode}, null);` : `insert(${el}, ${childCode});`);
607
+ const anchored = child.kind === "expr" && (child.reactive || !isLiteralCode(child.code)) || child.kind === "component" || child.kind === "control";
608
+ parts.push(anchored ? `insert(${el}, ${childCode}, null);` : `insert(${el}, ${childCode});`);
609
609
  }
610
610
  parts.push(`return ${el};`);
611
611
  return `(() => { ${parts.join(" ")} })()`;
612
612
  }
613
613
  }
614
614
  }
615
+ var LITERAL = /^\s*(?:'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|`[^`$]*`|-?\d[\d_.eE+-]*|true|false|null|undefined)\s*$/;
616
+ var isLiteralCode = (code) => LITERAL.test(code);
615
617
  function inlineTemplates(code, templates) {
616
618
  if (!templates || templates.length === 0) return code;
617
619
  const byId = new Map(templates.map((t3) => [t3.id, JSON.stringify(t3.html)]));