@fluixi/compiler 1.0.0-alpha.93 → 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.
Files changed (90) hide show
  1. package/dist/analyze/intrinsics.cjs +13 -1
  2. package/dist/analyze/intrinsics.d.cts +14 -0
  3. package/dist/analyze/intrinsics.d.ts +14 -0
  4. package/dist/analyze/intrinsics.d.ts.map +1 -1
  5. package/dist/analyze/intrinsics.js +17 -0
  6. package/dist/analyze/intrinsics.mjs +13 -1
  7. package/dist/analyze/static-graph.cjs +1 -1
  8. package/dist/analyze/static-graph.mjs +1 -1
  9. package/dist/{babel-RJHJQVEM.mjs → babel-RJFQVFJW.mjs} +4 -4
  10. package/dist/{chunk-56QSOVVL.mjs → chunk-DP2QDWWH.mjs} +1 -1
  11. package/dist/{chunk-R7PPFBCL.mjs → chunk-E2RWTIYE.mjs} +21 -15
  12. package/dist/{chunk-OD53TMER.mjs → chunk-HCCBEJEZ.mjs} +13 -1
  13. package/dist/{chunk-TJIH7TLX.mjs → chunk-HIZU7WI2.mjs} +1 -1
  14. package/dist/{chunk-U7HCFLZ2.mjs → chunk-ZR2QHTEX.mjs} +356 -24
  15. package/dist/codegen/backends/imperative.cjs +1 -1
  16. package/dist/codegen/backends/imperative.d.ts.map +1 -1
  17. package/dist/codegen/backends/imperative.js +2 -1
  18. package/dist/codegen/backends/imperative.mjs +1 -1
  19. package/dist/frontend/babel/build-ir-lit.cjs +352 -22
  20. package/dist/frontend/babel/build-ir-lit.mjs +352 -22
  21. package/dist/frontend/babel/build-ir.cjs +352 -22
  22. package/dist/frontend/babel/build-ir.mjs +352 -22
  23. package/dist/frontend/babel/index.cjs +353 -23
  24. package/dist/frontend/babel/index.mjs +353 -23
  25. package/dist/frontend/babel/lower-template.cjs +352 -22
  26. package/dist/frontend/babel/lower-template.mjs +352 -22
  27. package/dist/frontend/babel/plugin.cjs +352 -22
  28. package/dist/frontend/babel/plugin.mjs +352 -22
  29. package/dist/index.cjs +321 -22
  30. package/dist/index.mjs +333 -22
  31. package/dist/integrations.cjs +1174 -49
  32. package/dist/integrations.d.ts.map +1 -1
  33. package/dist/integrations.js +44 -2
  34. package/dist/integrations.mjs +205 -19
  35. package/dist/lower/compile-template.cjs +315 -21
  36. package/dist/lower/compile-template.d.cts +13 -0
  37. package/dist/lower/compile-template.d.ts +13 -0
  38. package/dist/lower/compile-template.d.ts.map +1 -1
  39. package/dist/lower/compile-template.js +3 -0
  40. package/dist/lower/compile-template.mjs +327 -21
  41. package/dist/lower/entities.cjs +288 -0
  42. package/dist/lower/entities.d.cts +1 -0
  43. package/dist/lower/entities.d.ts +2 -0
  44. package/dist/lower/entities.d.ts.map +1 -0
  45. package/dist/lower/entities.js +54 -0
  46. package/dist/lower/entities.mjs +267 -0
  47. package/dist/lower/jsx.cjs +104 -47
  48. package/dist/lower/jsx.d.cts +8 -0
  49. package/dist/lower/jsx.d.ts +8 -0
  50. package/dist/lower/jsx.d.ts.map +1 -1
  51. package/dist/lower/jsx.js +92 -2
  52. package/dist/lower/jsx.mjs +104 -47
  53. package/dist/lower/template.cjs +293 -20
  54. package/dist/lower/template.d.ts.map +1 -1
  55. package/dist/lower/template.js +35 -19
  56. package/dist/lower/template.mjs +293 -20
  57. package/dist/resolve/builtins.cjs +1 -1
  58. package/dist/resolve/builtins.mjs +1 -1
  59. package/dist/resolve/component-globals.cjs +6 -1
  60. package/dist/resolve/component-globals.js +2 -2
  61. package/dist/resolve/component-globals.mjs +6 -1
  62. package/dist/resolve/write-globals.cjs +6 -1
  63. package/dist/resolve/write-globals.mjs +6 -1
  64. package/dist/{server-fns-ZFRDIQ2X.mjs → server-fns-JLSTKWPS.mjs} +4 -4
  65. package/dist/{server-functions-CTDXX67X.mjs → server-functions-BGY3RD4R.mjs} +3 -3
  66. package/dist/transform/index.cjs +956 -33
  67. package/dist/transform/index.mjs +974 -47
  68. package/dist/transform/props.mjs +19 -14
  69. package/dist/transform/server-fns.mjs +19 -14
  70. package/dist/transform/styles.cjs +588 -0
  71. package/dist/transform/styles.d.cts +211 -0
  72. package/dist/transform/styles.d.ts +212 -0
  73. package/dist/transform/styles.d.ts.map +1 -0
  74. package/dist/transform/styles.js +714 -0
  75. package/dist/transform/styles.mjs +653 -0
  76. package/dist/transform/templates.cjs +955 -32
  77. package/dist/transform/templates.d.cts +13 -0
  78. package/dist/transform/templates.d.ts +13 -0
  79. package/dist/transform/templates.d.ts.map +1 -1
  80. package/dist/transform/templates.js +49 -12
  81. package/dist/transform/templates.mjs +973 -46
  82. package/dist/{transform-QWWQDCXE.mjs → transform-GBP6Y4UI.mjs} +601 -17
  83. package/dist/tsconfig.lib.tsbuildinfo +1 -1
  84. package/dist/vite-styles.cjs +180 -0
  85. package/dist/vite-styles.d.cts +59 -0
  86. package/dist/vite-styles.d.ts +60 -0
  87. package/dist/vite-styles.d.ts.map +1 -0
  88. package/dist/vite-styles.js +198 -0
  89. package/dist/vite-styles.mjs +159 -0
  90. package/package.json +4 -3
@@ -1,9 +1,9 @@
1
- /*! @fluixi/compiler v1.0.0-alpha.93 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
1
+ /*! @fluixi/compiler v1.0.0-alpha.94 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
2
2
 
3
3
  // src/transform/templates.ts
4
4
  import { parse as parse2 } from "@babel/parser";
5
5
 
6
- // ../../node_modules/.pnpm/@jridgewell+sourcemap-codec@1.5.5/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.mjs
6
+ // ../../node_modules/.pnpm/@jridgewell+sourcemap-codec@1.6.0/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.mjs
7
7
  var comma = ",".charCodeAt(0);
8
8
  var semicolon = ";".charCodeAt(0);
9
9
  var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
@@ -14,16 +14,16 @@ for (let i = 0; i < chars.length; i++) {
14
14
  intToChar[i] = c;
15
15
  charToInt[c] = i;
16
16
  }
17
- function encodeInteger(builder, num, relative) {
18
- let delta = num - relative;
19
- delta = delta < 0 ? -delta << 1 | 1 : delta << 1;
17
+ function encodeInteger(builder, num) {
20
18
  do {
21
- let clamped = delta & 31;
22
- delta >>>= 5;
23
- if (delta > 0) clamped |= 32;
19
+ let clamped = num & 31;
20
+ num >>>= 5;
21
+ if (num > 0) clamped |= 32;
24
22
  builder.write(intToChar[clamped]);
25
- } while (delta > 0);
26
- return num;
23
+ } while (num > 0);
24
+ }
25
+ function encodeSign(num) {
26
+ return num < 0 ? -num << 1 | 1 : num << 1;
27
27
  }
28
28
  var bufLength = 1024 * 16;
29
29
  var td = typeof TextDecoder !== "undefined" ? /* @__PURE__ */ new TextDecoder() : typeof Buffer !== "undefined" ? {
@@ -73,13 +73,18 @@ function encode(decoded) {
73
73
  for (let j = 0; j < line.length; j++) {
74
74
  const segment = line[j];
75
75
  if (j > 0) writer.write(comma);
76
- genColumn = encodeInteger(writer, segment[0], genColumn);
76
+ encodeInteger(writer, encodeSign(segment[0] - genColumn));
77
+ genColumn = segment[0];
77
78
  if (segment.length === 1) continue;
78
- sourcesIndex = encodeInteger(writer, segment[1], sourcesIndex);
79
- sourceLine = encodeInteger(writer, segment[2], sourceLine);
80
- sourceColumn = encodeInteger(writer, segment[3], sourceColumn);
79
+ encodeInteger(writer, encodeSign(segment[1] - sourcesIndex));
80
+ encodeInteger(writer, encodeSign(segment[2] - sourceLine));
81
+ encodeInteger(writer, encodeSign(segment[3] - sourceColumn));
82
+ sourcesIndex = segment[1];
83
+ sourceLine = segment[2];
84
+ sourceColumn = segment[3];
81
85
  if (segment.length === 4) continue;
82
- namesIndex = encodeInteger(writer, segment[4], namesIndex);
86
+ encodeInteger(writer, encodeSign(segment[4] - namesIndex));
87
+ namesIndex = segment[4];
83
88
  }
84
89
  }
85
90
  return writer.flush();
@@ -1076,6 +1081,562 @@ var MagicString = class _MagicString {
1076
1081
  }
1077
1082
  };
1078
1083
 
1084
+ // src/transform/styles.ts
1085
+ var SCOPE_ATTR = "data-fx-s";
1086
+ var FUNCTIONS = /* @__PURE__ */ new Set(["FunctionDeclaration", "FunctionExpression", "ArrowFunctionExpression", "ObjectMethod", "ClassMethod"]);
1087
+ function collectStyles(program, sourceName, options, tags = { html: /* @__PURE__ */ new Map([["html", "html"]]) }, module) {
1088
+ const plan = {
1089
+ scopes: [],
1090
+ templateOwners: /* @__PURE__ */ new Map(),
1091
+ drop: /* @__PURE__ */ new Set(),
1092
+ styles: [],
1093
+ diagnostics: [],
1094
+ edits: [],
1095
+ literals: [],
1096
+ references: [],
1097
+ shadowClasses: /* @__PURE__ */ new Map()
1098
+ };
1099
+ if (!options) return plan;
1100
+ const literalsOf = findLiterals(program, options.cssModules ?? ["@fluixi/core", "@fluixi/dom"], plan, tags.css ?? []);
1101
+ plan.names = literalsOf;
1102
+ const classOf = /* @__PURE__ */ new Map();
1103
+ const shadowOf = (owner) => {
1104
+ const cls = classOf.get(owner);
1105
+ return cls ? plan.shadowClasses.get(cls) : void 0;
1106
+ };
1107
+ const resolved = /* @__PURE__ */ new Map();
1108
+ const piecesToNodes = (quasis, expressions, at, stack) => {
1109
+ const out = [];
1110
+ for (let i = 0; i < quasis.length; i++) {
1111
+ const text = quasis[i].value.cooked ?? quasis[i].value.raw;
1112
+ if (text.trim()) {
1113
+ try {
1114
+ const start = quasis[i].loc?.start;
1115
+ out.push(...options.process(text, sourceName).map((n2) => start ? shiftLoc(n2, sourceName, start) : n2));
1116
+ } catch (error) {
1117
+ plan.diagnostics.push({ ...at, message: `CSS could not be processed: ${error.message}` });
1118
+ return null;
1119
+ }
1120
+ }
1121
+ const expr = expressions[i];
1122
+ if (!expr) continue;
1123
+ const value = expr.type === "Identifier" ? resolveLiteral(expr.name, at, stack) : void 0;
1124
+ if (value === void 0) {
1125
+ plan.diagnostics.push({
1126
+ ...at,
1127
+ 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))."
1128
+ });
1129
+ return null;
1130
+ }
1131
+ if (value === null) return null;
1132
+ out.push(...value);
1133
+ }
1134
+ return out;
1135
+ };
1136
+ function resolveLiteral(name, at, stack) {
1137
+ const imported = literalsOf.imports.get(name);
1138
+ if (imported) {
1139
+ const nodes = options?.imported?.get(`${imported.source}#${imported.name}`);
1140
+ if (nodes) return nodes.map(dropLoc);
1141
+ plan.references.push({ name: imported.name, source: imported.source, ...at });
1142
+ plan.diagnostics.push({
1143
+ ...at,
1144
+ 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.`
1145
+ });
1146
+ return null;
1147
+ }
1148
+ const literal = literalsOf.literals.get(name);
1149
+ if (!literal) return void 0;
1150
+ if (stack.includes(name)) {
1151
+ plan.diagnostics.push({ ...at, message: `css\`\` values include each other: ${[...stack, name].join(" → ")}.` });
1152
+ return null;
1153
+ }
1154
+ if (!resolved.has(name)) {
1155
+ resolved.set(name, piecesToNodes(literal.quasi.quasis, literal.quasi.expressions, at, [...stack, name]));
1156
+ }
1157
+ return resolved.get(name);
1158
+ }
1159
+ for (const [name, literal] of literalsOf.literals) {
1160
+ const at = { line: literal.loc?.start.line ?? 0, column: literal.loc?.start.column ?? 0 };
1161
+ const nodes = resolveLiteral(name, at, []);
1162
+ const id = hash(`${sourceName}:css:${name}`);
1163
+ plan.edits.push({ start: literal.start, end: literal.end, code: `({ $fxStyle: ${JSON.stringify(id)} })` });
1164
+ if (nodes) plan.literals.push({ id, name, css: printStyle(nodes, options.minify) });
1165
+ }
1166
+ const scopeOf = /* @__PURE__ */ new Map();
1167
+ const names = /* @__PURE__ */ new Map();
1168
+ const named = /* @__PURE__ */ new Map();
1169
+ const visit = (node, owners) => {
1170
+ if (!node || typeof node !== "object") return;
1171
+ if (node.type === "VariableDeclarator" && node.id.type === "Identifier" && node.init && FUNCTIONS.has(node.init.type)) {
1172
+ named.set(node.init, node.id.name);
1173
+ }
1174
+ if ((node.type === "ClassDeclaration" || node.type === "ClassExpression") && node.id) {
1175
+ for (const member of node.body.body) if (member.type === "ClassMethod") named.set(member, node.id.name);
1176
+ }
1177
+ if (node.type === "ClassDeclaration" || node.type === "ClassExpression") {
1178
+ for (const member of node.body.body) if (member.type === "ClassMethod") classOf.set(member, node);
1179
+ const shadow = staticMember(node, "shadow");
1180
+ if (shadow?.value && !(shadow.value.type === "BooleanLiteral" && shadow.value.value === false)) {
1181
+ plan.shadowClasses.set(node, { node, styles: staticMember(node, "styles"), indexes: [] });
1182
+ }
1183
+ }
1184
+ if (node.type === "TaggedTemplateExpression" && node.tag.type === "Identifier" && tags.html.get(node.tag.name) === "html") {
1185
+ const text = node.quasi.quasis.map((q) => q.value.raw).join("");
1186
+ if (/<style[\s>]/.test(text)) {
1187
+ const at = { line: node.loc?.start.line ?? 0, column: node.loc?.start.column ?? 0 };
1188
+ const owner = owners[0];
1189
+ if (!owner) plan.diagnostics.push({ ...at, message: "<style> has to be written inside a component." });
1190
+ else {
1191
+ const id = idFor(owner);
1192
+ const shadow = shadowOf(owner);
1193
+ plan.templateOwners.set(node.start, { id, component: functionName(owner, named) });
1194
+ for (const block of templateBlocks(node.quasi)) compileBlock(block, block.scoped, owner, at);
1195
+ }
1196
+ }
1197
+ }
1198
+ const inner = FUNCTIONS.has(node.type) ? [...owners, node] : owners;
1199
+ if (node.type === "JSXElement" && isStyle(node)) {
1200
+ handle(node, owners);
1201
+ return;
1202
+ }
1203
+ for (const key of Object.keys(node)) {
1204
+ if (key === "loc" || key === "leadingComments" || key === "trailingComments" || key === "innerComments") continue;
1205
+ const value = node[key];
1206
+ if (Array.isArray(value)) for (const v of value) visit(v, inner);
1207
+ else if (value && typeof value === "object" && "type" in value) visit(value, inner);
1208
+ }
1209
+ };
1210
+ const handle = (node, owners) => {
1211
+ const at = { line: node.loc?.start.line ?? 0, column: node.loc?.start.column ?? 0 };
1212
+ const pieces = blockPieces(node);
1213
+ if (pieces === null) {
1214
+ plan.diagnostics.push({
1215
+ ...at,
1216
+ message: "<style> needs its CSS as one template literal, <style>{`...`}</style>: JSX reads a bare `{` as an expression."
1217
+ });
1218
+ return;
1219
+ }
1220
+ const owner = owners[0];
1221
+ if (!owner) {
1222
+ plan.diagnostics.push({ ...at, message: "<style> has to be written inside a component." });
1223
+ return;
1224
+ }
1225
+ compileBlock(pieces, isScoped(node), owner, at);
1226
+ plan.drop.add(node.start);
1227
+ };
1228
+ const compileBlock = (pieces, scoped, owner, at) => {
1229
+ const component = functionName(owner, named);
1230
+ const id = idFor(owner);
1231
+ const processed = piecesToNodes(pieces.quasis, pieces.expressions, at, []);
1232
+ if (!processed) return;
1233
+ let nodes = processed;
1234
+ const shadow = shadowOf(owner);
1235
+ if (scoped && !shadow) {
1236
+ if (!plan.scopes.some((s) => s.value === id)) plan.scopes.push({ start: owner.start, end: owner.end, value: id });
1237
+ nodes = scopeNodes(nodes, id, (message) => plan.diagnostics.push({ ...at, message }));
1238
+ }
1239
+ const printed = module ? printStyleWithMap(nodes, options.minify, sourceName, module) : { css: printStyle(nodes, options.minify) };
1240
+ plan.styles.push({ id, scoped: scoped && !shadow, component, ...printed, ...shadow ? { shadow: true } : {}, ...at });
1241
+ if (shadow) shadow.indexes.push(plan.styles.length - 1);
1242
+ };
1243
+ function idFor(owner) {
1244
+ let id = scopeOf.get(owner);
1245
+ if (!id) {
1246
+ const component = functionName(owner, named);
1247
+ const seen = names.get(component) ?? 0;
1248
+ names.set(component, seen + 1);
1249
+ id = hash(`${sourceName}:${component}${seen ? ":" + seen : ""}`);
1250
+ scopeOf.set(owner, id);
1251
+ }
1252
+ return id;
1253
+ }
1254
+ visit(program, []);
1255
+ return plan;
1256
+ }
1257
+ function applyTemplateStyles(ir, t) {
1258
+ const walk8 = (node) => {
1259
+ const children = node.children;
1260
+ if (children) {
1261
+ for (let i = children.length - 1; i >= 0; i--) {
1262
+ const child = children[i];
1263
+ if (child.kind === "element" && child.tag === "style" && t.owner) children.splice(i, 1);
1264
+ else walk8(child);
1265
+ }
1266
+ }
1267
+ if (t.scope && node.kind === "element" && node.tag !== "style" && node.props && !node.props.some((p) => p.name === SCOPE_ATTR)) {
1268
+ node.props.unshift({ name: SCOPE_ATTR, kind: "attr", literal: t.scope });
1269
+ }
1270
+ };
1271
+ walk8(ir);
1272
+ }
1273
+ function staticMember(cls, name) {
1274
+ return cls.body.body.find(
1275
+ (m) => m.type === "ClassProperty" && m.static && (m.key.type === "Identifier" && m.key.name === name || m.key.type === "StringLiteral" && m.key.value === name)
1276
+ );
1277
+ }
1278
+ function finishShadowStyles(plan, code, moduleId) {
1279
+ const edits = [];
1280
+ const imports = [];
1281
+ let next = 0;
1282
+ const importOf = (specifier) => {
1283
+ const local = `__fxShadow${next++}`;
1284
+ imports.push(`import ${local} from ${JSON.stringify(specifier)};
1285
+ `);
1286
+ return local;
1287
+ };
1288
+ for (const shadow of plan.shadowClasses.values()) {
1289
+ const blocks = shadow.indexes.map((i) => importOf(`${moduleId}?fx-style&index=${i}&inline&lang.css`));
1290
+ let value;
1291
+ const prop = shadow.styles;
1292
+ if (prop?.value) {
1293
+ const start = prop.value.start;
1294
+ let text = code.slice(start, prop.value.end);
1295
+ const replacements = [];
1296
+ walkIdentifiers(prop.value, (id) => {
1297
+ 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;
1298
+ if (local) replacements.push({ at: id.start - start, length: id.name.length, with: local });
1299
+ });
1300
+ 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);
1301
+ value = text;
1302
+ }
1303
+ if (!blocks.length && value === void 0) continue;
1304
+ if (prop?.value) {
1305
+ const merged = blocks.length ? `[${value}, ${blocks.join(", ")}]` : value;
1306
+ edits.push({ start: prop.value.start, end: prop.value.end, code: merged });
1307
+ } else if (blocks.length) {
1308
+ const open = shadow.node.body.start + 1;
1309
+ edits.push({ start: open, end: open, code: ` static styles = [${blocks.join(", ")}];` });
1310
+ }
1311
+ }
1312
+ if (imports.length) edits.push({ start: 0, end: 0, code: imports.join("") });
1313
+ return edits;
1314
+ }
1315
+ function walkIdentifiers(node, visit) {
1316
+ if (!node || typeof node !== "object") return;
1317
+ if (node.type === "Identifier") return visit(node);
1318
+ if (node.type === "MemberExpression") return walkIdentifiers(node.object, visit);
1319
+ if (node.type === "ObjectProperty") return walkIdentifiers(node.value, visit);
1320
+ for (const key of Object.keys(node)) {
1321
+ if (key === "loc") continue;
1322
+ const value = node[key];
1323
+ if (Array.isArray(value)) for (const v of value) walkIdentifiers(v, visit);
1324
+ else if (value && typeof value === "object" && "type" in value) walkIdentifiers(value, visit);
1325
+ }
1326
+ }
1327
+ function isStyle(node) {
1328
+ const name = node.openingElement.name;
1329
+ return name.type === "JSXIdentifier" && name.name === "style";
1330
+ }
1331
+ function isScoped(node) {
1332
+ return node.openingElement.attributes.some((a) => a.type === "JSXAttribute" && a.name.type === "JSXIdentifier" && a.name.name === "scoped");
1333
+ }
1334
+ function templateBlocks(quasi) {
1335
+ const blocks = [];
1336
+ let open = null;
1337
+ quasi.quasis.forEach((q, i) => {
1338
+ const raw = q.value.raw;
1339
+ let from = 0;
1340
+ while (from <= raw.length) {
1341
+ if (!open) {
1342
+ const tag = /<style\b([^>]*)>/g;
1343
+ tag.lastIndex = from;
1344
+ const m = tag.exec(raw);
1345
+ if (!m) break;
1346
+ open = { quasis: [], expressions: [], scoped: /\bscoped\b/.test(m[1]) };
1347
+ from = m.index + m[0].length;
1348
+ }
1349
+ const close = raw.indexOf("</style", from);
1350
+ open.quasis.push(slicePiece(q, raw, from, close === -1 ? raw.length : close));
1351
+ if (close === -1) break;
1352
+ blocks.push(open);
1353
+ open = null;
1354
+ from = close;
1355
+ }
1356
+ const expr = quasi.expressions[i];
1357
+ if (open && expr) open.expressions.push(expr);
1358
+ });
1359
+ return blocks;
1360
+ }
1361
+ function slicePiece(q, raw, from, to) {
1362
+ const text = raw.slice(from, to);
1363
+ const start = q.loc?.start;
1364
+ if (!start) return { type: "TemplateElement", value: { raw: text, cooked: text } };
1365
+ const before = raw.slice(0, from).split("\n");
1366
+ const line = start.line + before.length - 1;
1367
+ const column = before.length > 1 ? before[before.length - 1].length : start.column + from;
1368
+ return { type: "TemplateElement", value: { raw: text, cooked: text }, loc: { start: { line, column } } };
1369
+ }
1370
+ function blockPieces(node) {
1371
+ const meaningful = node.children.filter((c) => !(c.type === "JSXText" && !c.value.trim()));
1372
+ if (meaningful.length === 0) return { quasis: [], expressions: [] };
1373
+ if (meaningful.length !== 1) return null;
1374
+ const only = meaningful[0];
1375
+ if (only.type !== "JSXExpressionContainer") return null;
1376
+ const expr = only.expression;
1377
+ if (expr.type === "StringLiteral") return { quasis: [{ type: "TemplateElement", value: { raw: expr.value, cooked: expr.value } }], expressions: [] };
1378
+ if (expr.type === "TemplateLiteral") return { quasis: expr.quasis, expressions: expr.expressions };
1379
+ return null;
1380
+ }
1381
+ function findLiterals(program, modules, plan, intrinsic) {
1382
+ const literals = /* @__PURE__ */ new Map();
1383
+ const imports = /* @__PURE__ */ new Map();
1384
+ const tags = new Set(intrinsic);
1385
+ for (const statement of program.body ?? []) {
1386
+ if (statement.type !== "ImportDeclaration") continue;
1387
+ const source = statement.source.value;
1388
+ const specifiers = statement.specifiers;
1389
+ for (const sp of specifiers) {
1390
+ if (sp.type === "ImportSpecifier") imports.set(sp.local.name, { source, name: sp.imported.name ?? sp.imported.value });
1391
+ }
1392
+ if (!modules.includes(source)) continue;
1393
+ const css = specifiers.find((sp) => sp.type === "ImportSpecifier" && (sp.imported.name ?? sp.imported.value) === "css");
1394
+ if (!css) continue;
1395
+ const local = css.local.name;
1396
+ tags.add(local);
1397
+ imports.delete(local);
1398
+ plan.edits.push({ start: statement.start, end: statement.end, code: importWithout(statement, css) });
1399
+ }
1400
+ if (tags.size === 0) return { literals, imports };
1401
+ const visit = (node) => {
1402
+ if (!node || typeof node !== "object") return;
1403
+ if (node.type === "VariableDeclarator" && node.id.type === "Identifier" && node.init?.type === "TaggedTemplateExpression" && node.init.tag.type === "Identifier" && tags.has(node.init.tag.name)) {
1404
+ literals.set(node.id.name, node.init);
1405
+ }
1406
+ for (const key of Object.keys(node)) {
1407
+ if (key === "loc") continue;
1408
+ const value = node[key];
1409
+ if (Array.isArray(value)) for (const v of value) visit(v);
1410
+ else if (value && typeof value === "object" && "type" in value) visit(value);
1411
+ }
1412
+ };
1413
+ visit(program);
1414
+ return { literals, imports };
1415
+ }
1416
+ function importWithout(statement, removed) {
1417
+ const rest = statement.specifiers.filter((sp) => sp !== removed);
1418
+ const source = JSON.stringify(statement.source.value);
1419
+ if (rest.length === 0) return "";
1420
+ const def = rest.find((sp) => sp.type === "ImportDefaultSpecifier");
1421
+ const ns = rest.find((sp) => sp.type === "ImportNamespaceSpecifier");
1422
+ const named = rest.filter((sp) => sp.type === "ImportSpecifier").map((sp) => {
1423
+ const imported = sp.imported.name ?? JSON.stringify(sp.imported.value);
1424
+ return imported === sp.local.name ? imported : `${imported} as ${sp.local.name}`;
1425
+ });
1426
+ const parts = [def?.local.name, ns ? `* as ${ns.local.name}` : void 0, named.length ? `{ ${named.join(", ")} }` : void 0].filter(Boolean);
1427
+ return `import ${parts.join(", ")} from ${source};`;
1428
+ }
1429
+ function functionName(fn, named) {
1430
+ if ((fn.type === "FunctionDeclaration" || fn.type === "FunctionExpression") && fn.id) return fn.id.name;
1431
+ return named.get(fn) ?? "anonymous";
1432
+ }
1433
+ function hash(text) {
1434
+ let h = 2166136261;
1435
+ for (let i = 0; i < text.length; i++) {
1436
+ h ^= text.charCodeAt(i);
1437
+ h = Math.imul(h, 16777619);
1438
+ }
1439
+ return (h >>> 0).toString(36);
1440
+ }
1441
+ var OPAQUE = /(^|-)keyframes$|^font-face$|^property$|^counter-style$|^page$|^font-feature-values$/;
1442
+ function scopeNodes(nodes, id, warn = () => {
1443
+ }) {
1444
+ return nodes.map((node) => {
1445
+ if (node.kind === "rule") return { ...node, selector: scopeSelector(node.selector, id, warn) };
1446
+ if (node.kind === "at-rule" && !OPAQUE.test(node.name)) return { ...node, nodes: scopeNodes(node.nodes, id, warn) };
1447
+ return node;
1448
+ });
1449
+ }
1450
+ function scopeSelector(selector, id, warn = () => {
1451
+ }) {
1452
+ return splitTop(selector, ",").map((complex) => scopeComplex(complex.trim(), `[${SCOPE_ATTR}="${id}"]`, warn)).join(", ");
1453
+ }
1454
+ function scopeComplex(selector, attr, warn) {
1455
+ if (/:host\b|::slotted\(/.test(selector)) {
1456
+ warn(`\`${selector}\` only means something in a shadow root; in a light-DOM component it is left as written.`);
1457
+ return selector;
1458
+ }
1459
+ const parts = compounds(selector);
1460
+ const deep = parts.findIndex((p) => p.text.startsWith(":deep("));
1461
+ if (deep !== -1) {
1462
+ const inner = unwrap(parts[deep].text, ":deep(");
1463
+ const before = parts.slice(0, deep);
1464
+ if (before.length === 0) return `${attr} ${inner}`;
1465
+ const scopedBefore = scopeAt(before, before.length - 1, attr);
1466
+ return `${join(scopedBefore)} ${inner}`;
1467
+ }
1468
+ let target = -1;
1469
+ for (let i = parts.length - 1; i >= 0; i--) {
1470
+ if (!parts[i].text.startsWith(":global(")) {
1471
+ target = i;
1472
+ break;
1473
+ }
1474
+ }
1475
+ const out = target === -1 ? parts : scopeAt(parts, target, attr);
1476
+ return join(out.map((p) => p.text.startsWith(":global(") ? { ...p, text: unwrap(p.text, ":global(") } : p));
1477
+ }
1478
+ function scopeAt(parts, index, attr) {
1479
+ return parts.map((p, i) => i === index ? { ...p, text: insertAttr(p.text, attr) } : p);
1480
+ }
1481
+ function insertAttr(compound, attr) {
1482
+ let depth = 0;
1483
+ let quote = "";
1484
+ for (let i = 0; i < compound.length; i++) {
1485
+ const c = compound[i];
1486
+ if (quote) {
1487
+ if (c === "\\") i++;
1488
+ else if (c === quote) quote = "";
1489
+ continue;
1490
+ }
1491
+ if (c === "\\") {
1492
+ i++;
1493
+ continue;
1494
+ }
1495
+ if (c === '"' || c === "'") quote = c;
1496
+ else if (c === "(" || c === "[") depth++;
1497
+ else if (c === ")" || c === "]") depth--;
1498
+ else if (c === ":" && depth === 0 && i > 0) return compound.slice(0, i) + attr + compound.slice(i);
1499
+ }
1500
+ return compound + attr;
1501
+ }
1502
+ function compounds(selector) {
1503
+ const out = [];
1504
+ let depth = 0;
1505
+ let quote = "";
1506
+ let current = "";
1507
+ let combinator = "";
1508
+ const push = () => {
1509
+ if (current.trim()) out.push({ combinator: out.length ? combinator || " " : "", text: current.trim() });
1510
+ current = "";
1511
+ combinator = "";
1512
+ };
1513
+ for (let i = 0; i < selector.length; i++) {
1514
+ const c = selector[i];
1515
+ if (quote) {
1516
+ current += c;
1517
+ if (c === "\\") current += selector[++i] ?? "";
1518
+ else if (c === quote) quote = "";
1519
+ continue;
1520
+ }
1521
+ if (c === "\\") {
1522
+ current += c + (selector[++i] ?? "");
1523
+ continue;
1524
+ }
1525
+ if (c === '"' || c === "'") quote = c;
1526
+ if (c === "(" || c === "[") depth++;
1527
+ if (c === ")" || c === "]") depth--;
1528
+ if (depth === 0 && (c === ">" || c === "+" || c === "~")) {
1529
+ push();
1530
+ combinator = c;
1531
+ continue;
1532
+ }
1533
+ if (depth === 0 && /\s/.test(c)) {
1534
+ if (current.trim()) {
1535
+ const keep = combinator;
1536
+ push();
1537
+ combinator = keep;
1538
+ }
1539
+ continue;
1540
+ }
1541
+ current += c;
1542
+ }
1543
+ push();
1544
+ return out;
1545
+ }
1546
+ function join(parts) {
1547
+ return parts.map((p, i) => i === 0 ? p.text : p.combinator === " " ? ` ${p.text}` : ` ${p.combinator} ${p.text}`).join("");
1548
+ }
1549
+ function unwrap(text, prefix) {
1550
+ return text.slice(prefix.length, text.lastIndexOf(")")).trim() + text.slice(text.lastIndexOf(")") + 1);
1551
+ }
1552
+ function splitTop(selector, separator) {
1553
+ const parts = [];
1554
+ let depth = 0;
1555
+ let quote = "";
1556
+ let start = 0;
1557
+ for (let i = 0; i < selector.length; i++) {
1558
+ const c = selector[i];
1559
+ if (quote) {
1560
+ if (c === "\\") i++;
1561
+ else if (c === quote) quote = "";
1562
+ } else if (c === '"' || c === "'") quote = c;
1563
+ else if (c === "\\") i++;
1564
+ else if (c === "(" || c === "[") depth++;
1565
+ else if (c === ")" || c === "]") depth--;
1566
+ else if (c === separator && depth === 0) {
1567
+ parts.push(selector.slice(start, i));
1568
+ start = i + 1;
1569
+ }
1570
+ }
1571
+ parts.push(selector.slice(start));
1572
+ return parts.filter((p) => p.trim());
1573
+ }
1574
+ function shiftLoc(node, source, start) {
1575
+ 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;
1576
+ if (node.kind === "rule" || node.kind === "at-rule") return { ...node, loc, nodes: node.nodes.map((n2) => shiftLoc(n2, source, start)) };
1577
+ return { ...node, loc };
1578
+ }
1579
+ function dropLoc(node) {
1580
+ const { loc: _loc, ...rest } = node;
1581
+ if (rest.kind === "rule" || rest.kind === "at-rule") return { ...rest, nodes: rest.nodes.map(dropLoc) };
1582
+ return rest;
1583
+ }
1584
+ function printStyleWithMap(nodes, minify, sourceName, module) {
1585
+ const lines = [[]];
1586
+ let css = "";
1587
+ let column = 0;
1588
+ const emit = (text) => {
1589
+ for (const ch of text) {
1590
+ css += ch;
1591
+ if (ch === "\n") {
1592
+ lines.push([]);
1593
+ column = 0;
1594
+ } else column++;
1595
+ }
1596
+ };
1597
+ const mark = (loc) => {
1598
+ if (loc && loc.source === sourceName) lines[lines.length - 1].push([column, 0, loc.line - 1, loc.column]);
1599
+ };
1600
+ const write = (node, depth) => {
1601
+ const pad = minify ? "" : " ".repeat(depth);
1602
+ const nl = minify ? "" : "\n";
1603
+ const sp = minify ? "" : " ";
1604
+ emit(pad);
1605
+ mark(node.loc);
1606
+ if (node.kind === "declaration") {
1607
+ emit(`${node.property}:${sp}${node.value}${node.important ? `${sp}!important` : ""};${nl}`);
1608
+ } else if (node.kind === "raw") {
1609
+ emit(`${node.text}${nl}`);
1610
+ } else {
1611
+ emit(`${node.kind === "rule" ? node.selector : `@${node.name}${node.params ? " " + node.params : ""}`}${sp}{${nl}`);
1612
+ for (const child of node.nodes) write(child, depth + 1);
1613
+ emit(`${pad}}${nl}`);
1614
+ }
1615
+ };
1616
+ for (const node of nodes) write(node, 0);
1617
+ return { css, map: { version: 3, sources: [module.id], sourcesContent: [module.code], names: [], mappings: encode(lines) } };
1618
+ }
1619
+ function printStyle(nodes, minify = false) {
1620
+ const out = [];
1621
+ const write = (node, depth) => {
1622
+ const pad = minify ? "" : " ".repeat(depth);
1623
+ const nl = minify ? "" : "\n";
1624
+ const sp = minify ? "" : " ";
1625
+ if (node.kind === "declaration") {
1626
+ out.push(`${pad}${node.property}:${sp}${node.value}${node.important ? `${sp}!important` : ""};${nl}`);
1627
+ } else if (node.kind === "raw") {
1628
+ out.push(`${pad}${node.text}${nl}`);
1629
+ } else {
1630
+ const header = node.kind === "rule" ? node.selector : `@${node.name}${node.params ? " " + node.params : ""}`;
1631
+ out.push(`${pad}${header}${sp}{${nl}`);
1632
+ for (const child of node.nodes) write(child, depth + 1);
1633
+ out.push(`${pad}}${nl}`);
1634
+ }
1635
+ };
1636
+ for (const node of nodes) write(node, 0);
1637
+ return out.join("");
1638
+ }
1639
+
1079
1640
  // src/optimize/analyze-static.ts
1080
1641
  function propReason(prop) {
1081
1642
  switch (prop.kind) {
@@ -1573,6 +2134,16 @@ var PRIMITIVE_MODULES = [
1573
2134
  "@fluixi/reactive/cached-resource",
1574
2135
  "@fluixi/core"
1575
2136
  ];
2137
+ var TAG_INTRINSICS = {
2138
+ $html: { export: "html", module: "@fluixi/core" },
2139
+ $svg: { export: "svg", module: "@fluixi/core" },
2140
+ $css: { export: "css", module: "@fluixi/core" }
2141
+ };
2142
+ function tagIntrinsics(bound) {
2143
+ const tags = /* @__PURE__ */ new Map();
2144
+ for (const [name, tag] of Object.entries(TAG_INTRINSICS)) if (!bound.has(name)) tags.set(name, tag.export);
2145
+ return tags;
2146
+ }
1576
2147
  var INTRINSIC_CALL = new RegExp(`\\$(?:${Object.keys(INTRINSICS).map((n2) => n2.slice(1)).join("|")})\\s*\\(`);
1577
2148
  function mayHaveIntrinsic(code) {
1578
2149
  return INTRINSIC_CALL.test(code);
@@ -2076,7 +2647,7 @@ function emitComponent(name, props, children, used, templates, at) {
2076
2647
  }
2077
2648
  let obj = `{ ${bodies.map(([name2, body]) => `get ${propKey(name2)}() { return ${body}; }`).join(", ")} }`;
2078
2649
  if (bodies.some(([, body]) => /\bthis\b/.test(body))) {
2079
- const thunks = bodies.map(([name2, body]) => `${JSON.stringify(name2)}: () => ${body}`);
2650
+ const thunks = bodies.map(([name2, body]) => `${JSON.stringify(name2)}: () => (${body})`);
2080
2651
  const getters = bodies.map(([name2]) => `get ${propKey(name2)}() { return _$t[${JSON.stringify(name2)}](); }`);
2081
2652
  obj = `((_$t) => ({ ${getters.join(", ")} }))({ ${thunks.join(", ")} })`;
2082
2653
  }
@@ -2277,6 +2848,271 @@ function cleanTemplateText(value) {
2277
2848
  return out;
2278
2849
  }
2279
2850
 
2851
+ // src/lower/entities.ts
2852
+ var NAMED = {
2853
+ quot: 34,
2854
+ amp: 38,
2855
+ apos: 39,
2856
+ lt: 60,
2857
+ gt: 62,
2858
+ nbsp: 160,
2859
+ iexcl: 161,
2860
+ cent: 162,
2861
+ pound: 163,
2862
+ curren: 164,
2863
+ yen: 165,
2864
+ brvbar: 166,
2865
+ sect: 167,
2866
+ uml: 168,
2867
+ copy: 169,
2868
+ ordf: 170,
2869
+ laquo: 171,
2870
+ not: 172,
2871
+ shy: 173,
2872
+ reg: 174,
2873
+ macr: 175,
2874
+ deg: 176,
2875
+ plusmn: 177,
2876
+ sup2: 178,
2877
+ sup3: 179,
2878
+ acute: 180,
2879
+ micro: 181,
2880
+ para: 182,
2881
+ middot: 183,
2882
+ cedil: 184,
2883
+ sup1: 185,
2884
+ ordm: 186,
2885
+ raquo: 187,
2886
+ frac14: 188,
2887
+ frac12: 189,
2888
+ frac34: 190,
2889
+ iquest: 191,
2890
+ Agrave: 192,
2891
+ Aacute: 193,
2892
+ Acirc: 194,
2893
+ Atilde: 195,
2894
+ Auml: 196,
2895
+ Aring: 197,
2896
+ AElig: 198,
2897
+ Ccedil: 199,
2898
+ Egrave: 200,
2899
+ Eacute: 201,
2900
+ Ecirc: 202,
2901
+ Euml: 203,
2902
+ Igrave: 204,
2903
+ Iacute: 205,
2904
+ Icirc: 206,
2905
+ Iuml: 207,
2906
+ ETH: 208,
2907
+ Ntilde: 209,
2908
+ Ograve: 210,
2909
+ Oacute: 211,
2910
+ Ocirc: 212,
2911
+ Otilde: 213,
2912
+ Ouml: 214,
2913
+ times: 215,
2914
+ Oslash: 216,
2915
+ Ugrave: 217,
2916
+ Uacute: 218,
2917
+ Ucirc: 219,
2918
+ Uuml: 220,
2919
+ Yacute: 221,
2920
+ THORN: 222,
2921
+ szlig: 223,
2922
+ agrave: 224,
2923
+ aacute: 225,
2924
+ acirc: 226,
2925
+ atilde: 227,
2926
+ auml: 228,
2927
+ aring: 229,
2928
+ aelig: 230,
2929
+ ccedil: 231,
2930
+ egrave: 232,
2931
+ eacute: 233,
2932
+ ecirc: 234,
2933
+ euml: 235,
2934
+ igrave: 236,
2935
+ iacute: 237,
2936
+ icirc: 238,
2937
+ iuml: 239,
2938
+ eth: 240,
2939
+ ntilde: 241,
2940
+ ograve: 242,
2941
+ oacute: 243,
2942
+ ocirc: 244,
2943
+ otilde: 245,
2944
+ ouml: 246,
2945
+ divide: 247,
2946
+ oslash: 248,
2947
+ ugrave: 249,
2948
+ uacute: 250,
2949
+ ucirc: 251,
2950
+ uuml: 252,
2951
+ yacute: 253,
2952
+ thorn: 254,
2953
+ yuml: 255,
2954
+ OElig: 338,
2955
+ oelig: 339,
2956
+ Scaron: 352,
2957
+ scaron: 353,
2958
+ Yuml: 376,
2959
+ fnof: 402,
2960
+ circ: 710,
2961
+ tilde: 732,
2962
+ Alpha: 913,
2963
+ Beta: 914,
2964
+ Gamma: 915,
2965
+ Delta: 916,
2966
+ Epsilon: 917,
2967
+ Zeta: 918,
2968
+ Eta: 919,
2969
+ Theta: 920,
2970
+ Iota: 921,
2971
+ Kappa: 922,
2972
+ Lambda: 923,
2973
+ Mu: 924,
2974
+ Nu: 925,
2975
+ Xi: 926,
2976
+ Omicron: 927,
2977
+ Pi: 928,
2978
+ Rho: 929,
2979
+ Sigma: 931,
2980
+ Tau: 932,
2981
+ Upsilon: 933,
2982
+ Phi: 934,
2983
+ Chi: 935,
2984
+ Psi: 936,
2985
+ Omega: 937,
2986
+ alpha: 945,
2987
+ beta: 946,
2988
+ gamma: 947,
2989
+ delta: 948,
2990
+ epsilon: 949,
2991
+ zeta: 950,
2992
+ eta: 951,
2993
+ theta: 952,
2994
+ iota: 953,
2995
+ kappa: 954,
2996
+ lambda: 955,
2997
+ mu: 956,
2998
+ nu: 957,
2999
+ xi: 958,
3000
+ omicron: 959,
3001
+ pi: 960,
3002
+ rho: 961,
3003
+ sigmaf: 962,
3004
+ sigma: 963,
3005
+ tau: 964,
3006
+ upsilon: 965,
3007
+ phi: 966,
3008
+ chi: 967,
3009
+ psi: 968,
3010
+ omega: 969,
3011
+ thetasym: 977,
3012
+ upsih: 978,
3013
+ piv: 982,
3014
+ ensp: 8194,
3015
+ emsp: 8195,
3016
+ thinsp: 8201,
3017
+ zwnj: 8204,
3018
+ zwj: 8205,
3019
+ lrm: 8206,
3020
+ rlm: 8207,
3021
+ ndash: 8211,
3022
+ mdash: 8212,
3023
+ lsquo: 8216,
3024
+ rsquo: 8217,
3025
+ sbquo: 8218,
3026
+ ldquo: 8220,
3027
+ rdquo: 8221,
3028
+ bdquo: 8222,
3029
+ dagger: 8224,
3030
+ Dagger: 8225,
3031
+ bull: 8226,
3032
+ hellip: 8230,
3033
+ permil: 8240,
3034
+ prime: 8242,
3035
+ Prime: 8243,
3036
+ lsaquo: 8249,
3037
+ rsaquo: 8250,
3038
+ oline: 8254,
3039
+ frasl: 8260,
3040
+ euro: 8364,
3041
+ image: 8465,
3042
+ weierp: 8472,
3043
+ real: 8476,
3044
+ trade: 8482,
3045
+ alefsym: 8501,
3046
+ larr: 8592,
3047
+ uarr: 8593,
3048
+ rarr: 8594,
3049
+ darr: 8595,
3050
+ harr: 8596,
3051
+ crarr: 8629,
3052
+ lArr: 8656,
3053
+ uArr: 8657,
3054
+ rArr: 8658,
3055
+ dArr: 8659,
3056
+ hArr: 8660,
3057
+ forall: 8704,
3058
+ part: 8706,
3059
+ exist: 8707,
3060
+ empty: 8709,
3061
+ nabla: 8711,
3062
+ isin: 8712,
3063
+ notin: 8713,
3064
+ ni: 8715,
3065
+ prod: 8719,
3066
+ sum: 8721,
3067
+ minus: 8722,
3068
+ lowast: 8727,
3069
+ radic: 8730,
3070
+ prop: 8733,
3071
+ infin: 8734,
3072
+ ang: 8736,
3073
+ and: 8743,
3074
+ or: 8744,
3075
+ cap: 8745,
3076
+ cup: 8746,
3077
+ int: 8747,
3078
+ there4: 8756,
3079
+ sim: 8764,
3080
+ cong: 8773,
3081
+ asymp: 8776,
3082
+ ne: 8800,
3083
+ equiv: 8801,
3084
+ le: 8804,
3085
+ ge: 8805,
3086
+ sub: 8834,
3087
+ sup: 8835,
3088
+ nsub: 8836,
3089
+ sube: 8838,
3090
+ supe: 8839,
3091
+ oplus: 8853,
3092
+ otimes: 8855,
3093
+ perp: 8869,
3094
+ sdot: 8901,
3095
+ lceil: 8968,
3096
+ rceil: 8969,
3097
+ lfloor: 8970,
3098
+ rfloor: 8971,
3099
+ lang: 9001,
3100
+ rang: 9002,
3101
+ loz: 9674,
3102
+ spades: 9824,
3103
+ clubs: 9827,
3104
+ hearts: 9829,
3105
+ diams: 9830
3106
+ };
3107
+ var REFERENCE = /&(?:#[xX]([0-9a-fA-F]{1,6})|#([0-9]{1,7})|([a-zA-Z][a-zA-Z0-9]{1,31}));/g;
3108
+ function decodeEntities(value) {
3109
+ if (!value.includes("&")) return value;
3110
+ return value.replace(REFERENCE, (match, hex, dec, name) => {
3111
+ const code = hex ? parseInt(hex, 16) : dec ? parseInt(dec, 10) : Object.prototype.hasOwnProperty.call(NAMED, name) ? NAMED[name] : void 0;
3112
+ return code !== void 0 && code <= 1114111 ? String.fromCodePoint(code) : match;
3113
+ });
3114
+ }
3115
+
2280
3116
  // src/lower/template.ts
2281
3117
  var DELEGATED = /* @__PURE__ */ new Set([
2282
3118
  "click",
@@ -2363,7 +3199,7 @@ var Lowerer = class {
2363
3199
  switch (node.kind) {
2364
3200
  case "Text": {
2365
3201
  if (node.raw) return { kind: "text", value: node.value };
2366
- const cleaned = cleanTemplateText(node.value);
3202
+ const cleaned = decodeEntities(cleanTemplateText(node.value));
2367
3203
  return cleaned ? { kind: "text", value: cleaned } : null;
2368
3204
  }
2369
3205
  case "Comment":
@@ -2399,7 +3235,7 @@ var Lowerer = class {
2399
3235
  kind: "element",
2400
3236
  tag: el.tag,
2401
3237
  svg: el.namespace === "svg",
2402
- props: this.lowerAttributes(el.attributes),
3238
+ props: this.lowerAttributes(el.attributes, true),
2403
3239
  children,
2404
3240
  static: false,
2405
3241
  ...at ? { at } : {}
@@ -2512,13 +3348,22 @@ var Lowerer = class {
2512
3348
  return clone.kind === "Element" ? this.lowerElement(clone) : this.lowerComponent(clone);
2513
3349
  }
2514
3350
  // --- attributes ---------------------------------------------------------
2515
- lowerAttributes(attrs) {
3351
+ /**
3352
+ * `element`: a DOM element, where each class:/style: value that moves is its own accessor.
3353
+ * A component gets the object as before, rebuilt whole when any value moves.
3354
+ */
3355
+ lowerAttributes(attrs, element = false) {
3356
+ let anyReactive = false;
3357
+ const entry = (name, h) => {
3358
+ anyReactive ||= h.reactive;
3359
+ if (!element || !h.reactive) return `${JSON.stringify(name)}: ${h.code}`;
3360
+ const accessor = `() => ${paren(h.code, "arrowBody")}`;
3361
+ return `${JSON.stringify(name)}: ${h.at ? markHole(accessor, h.at.line, h.at.column) : accessor}`;
3362
+ };
2516
3363
  const props = [];
2517
3364
  const classEntries = [];
2518
- let classReactive = false;
2519
3365
  let classAt;
2520
3366
  const styleEntries = [];
2521
- let styleReactive = false;
2522
3367
  let styleAt;
2523
3368
  const usePairs = [];
2524
3369
  for (const a of attrs) {
@@ -2558,15 +3403,13 @@ var Lowerer = class {
2558
3403
  break;
2559
3404
  case "ClassDirective": {
2560
3405
  const h = this.hole(a.hole);
2561
- classEntries.push(`${JSON.stringify(a.name)}: ${h.code}`);
2562
- classReactive = classReactive || h.reactive;
3406
+ classEntries.push(entry(a.name, h));
2563
3407
  classAt ??= h.at;
2564
3408
  break;
2565
3409
  }
2566
3410
  case "StyleDirective": {
2567
3411
  const h = this.hole(a.hole);
2568
- styleEntries.push(`${JSON.stringify(a.name)}: ${h.code}`);
2569
- styleReactive = styleReactive || h.reactive;
3412
+ styleEntries.push(entry(a.name, h));
2570
3413
  styleAt ??= h.at;
2571
3414
  break;
2572
3415
  }
@@ -2586,18 +3429,19 @@ var Lowerer = class {
2586
3429
  name: "classList",
2587
3430
  kind: "attr",
2588
3431
  expr: `{ ${classEntries.join(", ")} }`,
2589
- reactive: classReactive,
3432
+ reactive: !element && anyReactive,
2590
3433
  ...classAt ? { at: classAt } : {}
2591
3434
  });
2592
3435
  }
2593
3436
  if (styleEntries.length > 0) {
2594
- props.push({
2595
- name: "style",
2596
- kind: "attr",
2597
- expr: `{ ${styleEntries.join(", ")} }`,
2598
- reactive: styleReactive,
2599
- ...styleAt ? { at: styleAt } : {}
2600
- });
3437
+ const entries = `{ ${styleEntries.join(", ")} }`;
3438
+ const base = props.findIndex((p) => p.name === "style");
3439
+ if (base === -1) props.push({ name: "style", kind: "attr", expr: entries, reactive: !element && anyReactive, ...styleAt ? { at: styleAt } : {} });
3440
+ else {
3441
+ const prop = props[base];
3442
+ const value = prop.expr === void 0 ? JSON.stringify(prop.literal) : prop.reactive ? `() => ${paren(prop.expr, "arrowBody")}` : prop.expr;
3443
+ props[base] = { name: "style", kind: "attr", expr: `[${value}, ${entries}]`, reactive: false, ...prop.at ? { at: prop.at } : {} };
3444
+ }
2601
3445
  }
2602
3446
  if (usePairs.length > 0) {
2603
3447
  props.push({ name: "use", kind: "attr", expr: `[${usePairs.join(", ")}]` });
@@ -2686,7 +3530,7 @@ var Lowerer = class {
2686
3530
  return base;
2687
3531
  }
2688
3532
  if (v.kind === "static") {
2689
- base.literal = v.value;
3533
+ base.literal = decodeEntities(v.value);
2690
3534
  return base;
2691
3535
  }
2692
3536
  if (v.kind === "hole") {
@@ -2699,7 +3543,7 @@ var Lowerer = class {
2699
3543
  let reactive = false;
2700
3544
  let at;
2701
3545
  const body = v.parts.map((p) => {
2702
- if ("text" in p) return escapeTemplate(p.text);
3546
+ if ("text" in p) return escapeTemplate(decodeEntities(p.text));
2703
3547
  const h = this.hole(p.hole);
2704
3548
  reactive = reactive || h.reactive;
2705
3549
  at ??= h.at;
@@ -2724,6 +3568,7 @@ function compilePieces(pieces, holes, options = {}) {
2724
3568
  ...options.sourceFile ? { sourceFile: options.sourceFile } : {},
2725
3569
  ...options.positionAt ? { positionAt: options.positionAt } : {}
2726
3570
  });
3571
+ if (options.templateStyles) applyTemplateStyles(ir, options.templateStyles);
2727
3572
  analyzeStatic(ir);
2728
3573
  resolveComponentSources(ir, {
2729
3574
  resolver: createComponentResolver(options.resolve ?? []),
@@ -2922,9 +3767,12 @@ function attrExprCode(attr, ctx) {
2922
3767
  }
2923
3768
  return null;
2924
3769
  }
2925
- function buildProps(attrs, ctx) {
3770
+ function buildProps(attrs, ctx, element = false) {
2926
3771
  const props = [];
2927
3772
  const usePairs = [];
3773
+ const classEntries = [];
3774
+ const styleEntries = [];
3775
+ let styleAt;
2928
3776
  for (const a of attrs) {
2929
3777
  if (a.type === "JSXSpreadAttribute") {
2930
3778
  props.push({ name: "", kind: "spread", expr: ctx.code(a.argument) });
@@ -2940,6 +3788,27 @@ function buildProps(attrs, ctx) {
2940
3788
  usePairs.push(opts != null ? `[${dir}, () => ${paren(opts, "arrowBody")}]` : `[${dir}]`);
2941
3789
  continue;
2942
3790
  }
3791
+ if (element && (ns === "class" || ns === "style")) {
3792
+ const key = JSON.stringify(a.name.name.name);
3793
+ const v = a.value;
3794
+ let value;
3795
+ if (v == null) value = "true";
3796
+ else if (isString(v)) value = JSON.stringify(literalOf(v));
3797
+ else if (v.type === "JSXExpressionContainer" && v.expression?.type !== "JSXEmptyExpression") {
3798
+ value = keyValue(v.expression, ctx);
3799
+ if (ns === "style") styleAt ??= posOf(v.expression, ctx);
3800
+ } else continue;
3801
+ (ns === "class" ? classEntries : styleEntries).push(`${key}: ${value}`);
3802
+ continue;
3803
+ }
3804
+ if (element && a.name.type === "JSXIdentifier" && a.name.name === "style" && a.value?.type === "JSXExpressionContainer") {
3805
+ const entries = objectEntries(a.value.expression, ctx);
3806
+ if (entries) {
3807
+ styleEntries.unshift(...entries);
3808
+ styleAt = posOf(a.value.expression, ctx);
3809
+ continue;
3810
+ }
3811
+ }
2943
3812
  if (ns === "oncapture") {
2944
3813
  const evt = a.name.name.name.toLowerCase();
2945
3814
  const h = attrExprCode(a, ctx) ?? "undefined";
@@ -2948,9 +3817,37 @@ function buildProps(attrs, ctx) {
2948
3817
  }
2949
3818
  props.push(buildAttr(a, ctx));
2950
3819
  }
3820
+ if (classEntries.length > 0) props.push({ name: "classList", kind: "attr", expr: `{ ${classEntries.join(", ")} }`, reactive: false });
3821
+ if (styleEntries.length > 0) {
3822
+ const entries = `{ ${styleEntries.join(", ")} }`;
3823
+ const base = props.findIndex((p) => p.name === "style" && p.kind === "attr");
3824
+ if (base === -1) props.push({ name: "style", kind: "attr", expr: entries, reactive: false, ...styleAt ? { at: styleAt } : {} });
3825
+ else {
3826
+ const prop = props[base];
3827
+ const value = prop.literal !== void 0 ? JSON.stringify(prop.literal) : prop.reactive ? `() => ${paren(prop.expr, "arrowBody")}` : prop.expr;
3828
+ props[base] = { name: "style", kind: "attr", expr: `[${value}, ${entries}]`, reactive: false, ...prop.at ? { at: prop.at } : {} };
3829
+ }
3830
+ }
2951
3831
  if (usePairs.length > 0) props.push({ name: "use", kind: "attr", expr: `[${usePairs.join(", ")}]` });
2952
3832
  return props;
2953
3833
  }
3834
+ function keyValue(expr, ctx) {
3835
+ const code = ctx.code(expr);
3836
+ if (!isReactive(expr)) return code;
3837
+ const accessor = `() => ${paren(code, "arrowBody")}`;
3838
+ const at = posOf(expr, ctx);
3839
+ return at ? markHole(accessor, at.line, at.column) : accessor;
3840
+ }
3841
+ function objectEntries(expr, ctx) {
3842
+ if (expr?.type !== "ObjectExpression") return null;
3843
+ const entries = [];
3844
+ for (const p of expr.properties) {
3845
+ if (p.type !== "ObjectProperty") return null;
3846
+ const key = p.computed ? `[${ctx.code(p.key)}]` : p.key.type === "Identifier" ? JSON.stringify(p.key.name) : JSON.stringify(String(p.key.value));
3847
+ entries.push(`${key}: ${keyValue(p.value, ctx)}`);
3848
+ }
3849
+ return entries;
3850
+ }
2954
3851
  function buildChildren(children, ctx) {
2955
3852
  const out = [];
2956
3853
  for (let i = 0; i < children.length; i++) {
@@ -2978,6 +3875,7 @@ function buildChildren(children, ctx) {
2978
3875
  });
2979
3876
  }
2980
3877
  } else if (child.type === "JSXElement" || child.type === "JSXFragment") {
3878
+ if (ctx.dropStyles?.has(child.start)) continue;
2981
3879
  out.push(buildNode(child, ctx));
2982
3880
  } else if (child.type === "JSXSpreadChild") {
2983
3881
  out.push({ kind: "expr", code: ctx.code(child.expression), reactive: false });
@@ -3047,13 +3945,17 @@ function buildElement(node, ctx, handled) {
3047
3945
  const children = each ? [each] : buildChildren(node.children, ctx);
3048
3946
  if (tag === CONTAINER2) return children.length === 1 ? children[0] : { kind: "fragment", children };
3049
3947
  const at = ctx.sourceFile && node.loc?.start ? { file: ctx.sourceFile, line: node.loc.start.line, column: node.loc.start.column } : void 0;
3050
- return { kind: "element", tag, svg: SVG_TAGS.has(tag), props: buildProps(attributes, ctx), children, static: false, ...at ? { at } : {} };
3948
+ const props = buildProps(attributes, ctx, true);
3949
+ const scope = ctx.scopes?.find((s) => node.start >= s.start && node.end <= s.end);
3950
+ if (scope) props.unshift({ name: "data-fx-s", kind: "attr", literal: scope.value });
3951
+ return { kind: "element", tag, svg: SVG_TAGS.has(tag), props, children, static: false, ...at ? { at } : {} };
3051
3952
  }
3052
3953
  function buildNode(node, ctx) {
3053
3954
  if (node.type === "JSXFragment") {
3054
3955
  return { kind: "fragment", children: buildChildren(node.children, ctx) };
3055
3956
  }
3056
3957
  if (directive(node, "if")) return buildIf(node, null, ctx);
3958
+ if (ctx.dropStyles?.has(node.start)) return { kind: "fragment", children: [] };
3057
3959
  const { tag, component } = tagInfo(node.openingElement.name, ctx);
3058
3960
  if (!component) return buildElement(node, ctx, []);
3059
3961
  const props = buildProps(node.openingElement.attributes, ctx);
@@ -3581,8 +4483,8 @@ function isJsxRoot(node, parent, key) {
3581
4483
  if (!isJsx(node)) return false;
3582
4484
  return !(parent && isJsx(parent) && key === "children");
3583
4485
  }
3584
- function isTemplateTag(node, litTag) {
3585
- return node.type === "TaggedTemplateExpression" && node.tag?.type === "Identifier" && (node.tag.name === litTag || node.tag.name === "svg");
4486
+ function isTemplateTag(node, tags) {
4487
+ return node.type === "TaggedTemplateExpression" && node.tag?.type === "Identifier" && tags.has(node.tag.name);
3586
4488
  }
3587
4489
  function outermost(list) {
3588
4490
  return list.filter(
@@ -3730,22 +4632,28 @@ function transformTemplates(code, id, options = {}) {
3730
4632
  const wantsIntrinsics = options.intrinsics !== false && mayHaveIntrinsic(code);
3731
4633
  const wantsSources = options.sourceLocations === true && mayHaveSourceMarks(code);
3732
4634
  const sourceName = relativeToRoot(id, options.sourceRoot);
3733
- if (!mayHaveTemplate && !(wantsJsx && code.includes("<")) && !wantsIntrinsics && !wantsSources) return null;
4635
+ const wantsStyles = options.styles !== void 0 && (code.includes("<style") || code.includes("css`"));
4636
+ if (!mayHaveTemplate && !(wantsJsx && code.includes("<")) && !wantsIntrinsics && !wantsSources && !wantsStyles) return null;
3734
4637
  const ast = parse2(code, {
3735
4638
  sourceType: "module",
3736
4639
  plugins: ["jsx", "typescript"],
3737
4640
  errorRecovery: true
3738
4641
  });
4642
+ const intrinsicTags = options.intrinsics === false ? /* @__PURE__ */ new Map() : tagIntrinsics(moduleBindings(ast.program));
4643
+ const templateTags = /* @__PURE__ */ new Map([[litTag, "html"], ["svg", "svg"]]);
4644
+ for (const [name, tag] of intrinsicTags) if (tag !== "css") templateTags.set(name, tag);
4645
+ const cssTags = [...intrinsicTags].filter(([, tag]) => tag === "css").map(([name]) => name);
3739
4646
  const found = [];
3740
4647
  walk7(ast.program, (n2, parent, key) => {
3741
- if (wantsLit && isTemplateTag(n2, litTag)) found.push(n2);
4648
+ if (wantsLit && isTemplateTag(n2, templateTags)) found.push(n2);
3742
4649
  else if (wantsJsx && isJsxRoot(n2, parent, key)) found.push(n2);
3743
4650
  });
3744
4651
  const props = options.propsDestructure === false ? { edits: [], diagnostics: [], used: /* @__PURE__ */ new Set() } : collectPropsEdits(ast.program, code, { runtimeModule: options.runtimeModule });
3745
4652
  const intrinsics = options.intrinsics === false ? { edits: [], diagnostics: [], imports: /* @__PURE__ */ new Map() } : collectIntrinsicEdits(ast.program);
3746
4653
  if (intrinsics.edits.length) avoidBindingClashes(ast.program, intrinsics, moduleBindings(ast.program));
3747
4654
  const sources = options.sourceLocations === true ? collectSourceEdits(ast.program, sourceName) : { edits: [], marked: 0 };
3748
- 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;
4655
+ const styles = wantsStyles ? collectStyles(ast.program, sourceName, options.styles, { html: templateTags, css: cssTags }, { id, code }) : void 0;
4656
+ 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;
3749
4657
  if (silent) return null;
3750
4658
  found.sort((a, b) => b.start - a.start || a.end - b.end);
3751
4659
  const used = new Set(props.used);
@@ -3759,20 +4667,32 @@ function transformTemplates(code, id, options = {}) {
3759
4667
  declared: declaredNames(ast.program)
3760
4668
  };
3761
4669
  const hoisted = /* @__PURE__ */ new Map();
3762
- const edits = [...props.edits, ...intrinsics.edits, ...sources.edits];
4670
+ const edits = [...props.edits, ...intrinsics.edits, ...sources.edits, ...styles?.edits ?? []];
3763
4671
  for (const node of found) {
3764
4672
  const nested = found.some(
3765
4673
  (o) => o !== node && o.start <= node.start && o.end >= node.end && o.end - o.start > node.end - node.start
3766
4674
  );
3767
4675
  if (isJsx(node)) {
3768
- edits.push({ start: node.start, end: node.end, code: compileJsx(code, node, edits, nested, used, needs, hoisted, options, sourceName) });
4676
+ edits.push({ start: node.start, end: node.end, code: compileJsx(code, node, edits, nested, used, needs, hoisted, options, sourceName, styles) });
3769
4677
  continue;
3770
4678
  }
3771
4679
  const holes = node.quasi.expressions.map(
3772
4680
  (e) => bindHole(code, e, edits, options.sourceLocations === true)
3773
4681
  );
4682
+ const scope = styles?.scopes.find((s) => node.start >= s.start && node.end <= s.end)?.value;
4683
+ const owner = styles?.templateOwners.get(node.start);
4684
+ const templateStyles = options.styles && styles && (scope || owner) ? {
4685
+ options: options.styles,
4686
+ ...scope ? { scope } : {},
4687
+ ...owner ? { owner } : {},
4688
+ line: node.loc?.start.line ?? 0,
4689
+ column: node.loc?.start.column ?? 0,
4690
+ styles: styles.styles,
4691
+ diagnostics: styles.diagnostics
4692
+ } : void 0;
3774
4693
  const result = compilePieces(toPieces(node), holes, {
3775
4694
  ...options,
4695
+ ...templateStyles ? { templateStyles } : {},
3776
4696
  hoistTemplates: true,
3777
4697
  // A tag inside a template gets the same mark a JSX tag does. Without one, the nodes it
3778
4698
  // makes are the only ones in the module carrying no mark, and they take whichever was
@@ -3781,12 +4701,13 @@ function transformTemplates(code, id, options = {}) {
3781
4701
  // Same defaults as the plugin, so moving a build over is not a rendering change.
3782
4702
  templateClone: options.templateClone ?? true,
3783
4703
  partialTemplates: nested ? false : options.partialTemplates ?? true,
3784
- svg: node.tag.name === "svg"
4704
+ svg: templateTags.get(node.tag.name) === "svg"
3785
4705
  });
3786
4706
  for (const symbol of result.imports) used.add(symbol);
3787
4707
  collectNeeds(result.ir, needs);
3788
4708
  edits.push({ start: node.start, end: node.end, code: adoptTemplates(result.code, result.templates, hoisted) });
3789
4709
  }
4710
+ if (styles && options.styles) edits.push(...finishShadowStyles(styles, code, id));
3790
4711
  const out = new MagicString(code);
3791
4712
  for (const e of outermost(edits)) {
3792
4713
  if (e.start === e.end) out.appendLeft(e.start, e.code);
@@ -3844,13 +4765,19 @@ function transformTemplates(code, id, options = {}) {
3844
4765
  ...loadDiagnostics.length ? { loadDiagnostics } : {},
3845
4766
  ...unresolvedDiagnostics.length ? { unresolvedDiagnostics } : {},
3846
4767
  ...props.diagnostics.length ? { propsDiagnostics: props.diagnostics } : {},
3847
- ...intrinsics.diagnostics.length ? { intrinsicDiagnostics: intrinsics.diagnostics } : {}
4768
+ ...intrinsics.diagnostics.length ? { intrinsicDiagnostics: intrinsics.diagnostics } : {},
4769
+ ...styles?.styles.length ? { styles: styles.styles } : {},
4770
+ ...styles?.diagnostics.length ? { styleDiagnostics: styles.diagnostics } : {},
4771
+ ...styles?.literals.length ? { styleLiterals: styles.literals } : {},
4772
+ ...styles?.references.length ? { styleReferences: styles.references } : {}
3848
4773
  };
3849
4774
  }
3850
- function compileJsx(code, node, edits, nested, used, needs, hoisted, options, sourceFile) {
4775
+ function compileJsx(code, node, edits, nested, used, needs, hoisted, options, sourceFile, styles) {
3851
4776
  const ir = buildJsxIR(node, {
3852
4777
  code: (n2) => slice(code, n2.start, n2.end, edits),
3853
4778
  used,
4779
+ ...styles?.scopes.length ? { scopes: styles.scopes } : {},
4780
+ ...styles?.drop.size ? { dropStyles: styles.drop } : {},
3854
4781
  ...options.sourceLocations === true && sourceFile ? { sourceFile } : {}
3855
4782
  });
3856
4783
  analyzeStatic(ir);