@fluixi/compiler 1.0.0-alpha.93 → 1.0.0-alpha.95

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 (93) hide show
  1. package/LICENSE +1 -1
  2. package/dist/analyze/intrinsics.cjs +13 -1
  3. package/dist/analyze/intrinsics.d.cts +14 -0
  4. package/dist/analyze/intrinsics.d.ts +14 -0
  5. package/dist/analyze/intrinsics.d.ts.map +1 -1
  6. package/dist/analyze/intrinsics.js +17 -0
  7. package/dist/analyze/intrinsics.mjs +13 -1
  8. package/dist/analyze/static-graph.cjs +1 -1
  9. package/dist/analyze/static-graph.mjs +1 -1
  10. package/dist/{babel-RJHJQVEM.mjs → babel-V33QLJBF.mjs} +4 -4
  11. package/dist/{chunk-56QSOVVL.mjs → chunk-62F2LLBM.mjs} +1 -1
  12. package/dist/{chunk-R7PPFBCL.mjs → chunk-7GNSGUHK.mjs} +4 -83
  13. package/dist/{chunk-U7HCFLZ2.mjs → chunk-B64LVPTU.mjs} +356 -24
  14. package/dist/{chunk-OD53TMER.mjs → chunk-C3AK5PBV.mjs} +13 -1
  15. package/dist/{chunk-TJIH7TLX.mjs → chunk-GLFUPZ27.mjs} +1 -1
  16. package/dist/chunk-HUABRVWB.mjs +92 -0
  17. package/dist/chunk-XCWP7WJG.mjs +584 -0
  18. package/dist/codegen/backends/imperative.cjs +1 -1
  19. package/dist/codegen/backends/imperative.d.ts.map +1 -1
  20. package/dist/codegen/backends/imperative.js +2 -1
  21. package/dist/codegen/backends/imperative.mjs +1 -1
  22. package/dist/frontend/babel/build-ir-lit.cjs +352 -22
  23. package/dist/frontend/babel/build-ir-lit.mjs +352 -22
  24. package/dist/frontend/babel/build-ir.cjs +352 -22
  25. package/dist/frontend/babel/build-ir.mjs +352 -22
  26. package/dist/frontend/babel/index.cjs +353 -23
  27. package/dist/frontend/babel/index.mjs +353 -23
  28. package/dist/frontend/babel/lower-template.cjs +352 -22
  29. package/dist/frontend/babel/lower-template.mjs +352 -22
  30. package/dist/frontend/babel/plugin.cjs +352 -22
  31. package/dist/frontend/babel/plugin.mjs +352 -22
  32. package/dist/index.cjs +321 -22
  33. package/dist/index.mjs +333 -22
  34. package/dist/integrations.cjs +1240 -56
  35. package/dist/integrations.d.ts.map +1 -1
  36. package/dist/integrations.js +62 -9
  37. package/dist/integrations.mjs +257 -26
  38. package/dist/lower/compile-template.cjs +315 -21
  39. package/dist/lower/compile-template.d.cts +13 -0
  40. package/dist/lower/compile-template.d.ts +13 -0
  41. package/dist/lower/compile-template.d.ts.map +1 -1
  42. package/dist/lower/compile-template.js +3 -0
  43. package/dist/lower/compile-template.mjs +327 -21
  44. package/dist/lower/entities.cjs +288 -0
  45. package/dist/lower/entities.d.cts +1 -0
  46. package/dist/lower/entities.d.ts +2 -0
  47. package/dist/lower/entities.d.ts.map +1 -0
  48. package/dist/lower/entities.js +54 -0
  49. package/dist/lower/entities.mjs +267 -0
  50. package/dist/lower/jsx.cjs +104 -47
  51. package/dist/lower/jsx.d.cts +8 -0
  52. package/dist/lower/jsx.d.ts +8 -0
  53. package/dist/lower/jsx.d.ts.map +1 -1
  54. package/dist/lower/jsx.js +92 -2
  55. package/dist/lower/jsx.mjs +104 -47
  56. package/dist/lower/template.cjs +293 -20
  57. package/dist/lower/template.d.ts.map +1 -1
  58. package/dist/lower/template.js +35 -19
  59. package/dist/lower/template.mjs +293 -20
  60. package/dist/resolve/builtins.cjs +1 -1
  61. package/dist/resolve/builtins.mjs +1 -1
  62. package/dist/resolve/component-globals.cjs +6 -1
  63. package/dist/resolve/component-globals.js +2 -2
  64. package/dist/resolve/component-globals.mjs +6 -1
  65. package/dist/resolve/write-globals.cjs +6 -1
  66. package/dist/resolve/write-globals.mjs +6 -1
  67. package/dist/{server-fns-ZFRDIQ2X.mjs → server-fns-N3SDJXA7.mjs} +5 -4
  68. package/dist/{server-functions-CTDXX67X.mjs → server-functions-LVS66Q4R.mjs} +3 -3
  69. package/dist/transform/index.cjs +973 -33
  70. package/dist/transform/index.mjs +991 -47
  71. package/dist/transform/props.mjs +19 -14
  72. package/dist/transform/server-fns.mjs +19 -14
  73. package/dist/transform/styles.cjs +606 -0
  74. package/dist/transform/styles.d.cts +237 -0
  75. package/dist/transform/styles.d.ts +238 -0
  76. package/dist/transform/styles.d.ts.map +1 -0
  77. package/dist/transform/styles.js +743 -0
  78. package/dist/transform/styles.mjs +671 -0
  79. package/dist/transform/templates.cjs +972 -32
  80. package/dist/transform/templates.d.cts +13 -0
  81. package/dist/transform/templates.d.ts +13 -0
  82. package/dist/transform/templates.d.ts.map +1 -1
  83. package/dist/transform/templates.js +49 -12
  84. package/dist/transform/templates.mjs +990 -46
  85. package/dist/{transform-QWWQDCXE.mjs → transform-P4AETYV4.mjs} +49 -16
  86. package/dist/tsconfig.lib.tsbuildinfo +1 -1
  87. package/dist/vite-styles.cjs +223 -0
  88. package/dist/vite-styles.d.cts +68 -0
  89. package/dist/vite-styles.d.ts +69 -0
  90. package/dist/vite-styles.d.ts.map +1 -0
  91. package/dist/vite-styles.js +241 -0
  92. package/dist/vite-styles.mjs +214 -0
  93. package/package.json +5 -4
@@ -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.95 | (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,579 @@ 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((n2) => keepLocIn(n2, options?.importedModules));
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), nodes });
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, options.importedModules) : { 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
+ var styleIds = {
1279
+ block: (owner, index) => `${owner}.fx-${index}.css`,
1280
+ inline: (owner, index) => `${owner}.fx-${index}.css?inline`,
1281
+ literal: (owner, name) => `${owner}.fx-literal-${name}.css?inline`
1282
+ };
1283
+ function finishShadowStyles(plan, code, moduleId) {
1284
+ const edits = [];
1285
+ const imports = [];
1286
+ let next = 0;
1287
+ const importOf = (specifier) => {
1288
+ const local = `__fxShadow${next++}`;
1289
+ imports.push(`import ${local} from ${JSON.stringify(specifier)};
1290
+ `);
1291
+ return local;
1292
+ };
1293
+ for (const shadow of plan.shadowClasses.values()) {
1294
+ const blocks = shadow.indexes.map((i) => importOf(styleIds.inline(moduleId, i)));
1295
+ let value;
1296
+ const prop = shadow.styles;
1297
+ if (prop?.value) {
1298
+ const start = prop.value.start;
1299
+ let text = code.slice(start, prop.value.end);
1300
+ const replacements = [];
1301
+ walkIdentifiers(prop.value, (id) => {
1302
+ 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;
1303
+ if (local) replacements.push({ at: id.start - start, length: id.name.length, with: local });
1304
+ });
1305
+ 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);
1306
+ value = text;
1307
+ }
1308
+ if (!blocks.length && value === void 0) continue;
1309
+ if (prop?.value) {
1310
+ const merged = blocks.length ? `[${value}, ${blocks.join(", ")}]` : value;
1311
+ edits.push({ start: prop.value.start, end: prop.value.end, code: merged });
1312
+ } else if (blocks.length) {
1313
+ const open = shadow.node.body.start + 1;
1314
+ edits.push({ start: open, end: open, code: ` static styles = [${blocks.join(", ")}];` });
1315
+ }
1316
+ }
1317
+ if (imports.length) edits.push({ start: 0, end: 0, code: imports.join("") });
1318
+ return edits;
1319
+ }
1320
+ function walkIdentifiers(node, visit) {
1321
+ if (!node || typeof node !== "object") return;
1322
+ if (node.type === "Identifier") return visit(node);
1323
+ if (node.type === "MemberExpression") return walkIdentifiers(node.object, visit);
1324
+ if (node.type === "ObjectProperty") return walkIdentifiers(node.value, visit);
1325
+ for (const key of Object.keys(node)) {
1326
+ if (key === "loc") continue;
1327
+ const value = node[key];
1328
+ if (Array.isArray(value)) for (const v of value) walkIdentifiers(v, visit);
1329
+ else if (value && typeof value === "object" && "type" in value) walkIdentifiers(value, visit);
1330
+ }
1331
+ }
1332
+ function isStyle(node) {
1333
+ const name = node.openingElement.name;
1334
+ return name.type === "JSXIdentifier" && name.name === "style";
1335
+ }
1336
+ function isScoped(node) {
1337
+ return node.openingElement.attributes.some((a) => a.type === "JSXAttribute" && a.name.type === "JSXIdentifier" && a.name.name === "scoped");
1338
+ }
1339
+ function templateBlocks(quasi) {
1340
+ const blocks = [];
1341
+ let open = null;
1342
+ quasi.quasis.forEach((q, i) => {
1343
+ const raw = q.value.raw;
1344
+ let from = 0;
1345
+ while (from <= raw.length) {
1346
+ if (!open) {
1347
+ const tag = /<style\b([^>]*)>/g;
1348
+ tag.lastIndex = from;
1349
+ const m = tag.exec(raw);
1350
+ if (!m) break;
1351
+ open = { quasis: [], expressions: [], scoped: /\bscoped\b/.test(m[1]) };
1352
+ from = m.index + m[0].length;
1353
+ }
1354
+ const close = raw.indexOf("</style", from);
1355
+ open.quasis.push(slicePiece(q, raw, from, close === -1 ? raw.length : close));
1356
+ if (close === -1) break;
1357
+ blocks.push(open);
1358
+ open = null;
1359
+ from = close;
1360
+ }
1361
+ const expr = quasi.expressions[i];
1362
+ if (open && expr) open.expressions.push(expr);
1363
+ });
1364
+ return blocks;
1365
+ }
1366
+ function slicePiece(q, raw, from, to) {
1367
+ const text = raw.slice(from, to);
1368
+ const start = q.loc?.start;
1369
+ if (!start) return { type: "TemplateElement", value: { raw: text, cooked: text } };
1370
+ const before = raw.slice(0, from).split("\n");
1371
+ const line = start.line + before.length - 1;
1372
+ const column = before.length > 1 ? before[before.length - 1].length : start.column + from;
1373
+ return { type: "TemplateElement", value: { raw: text, cooked: text }, loc: { start: { line, column } } };
1374
+ }
1375
+ function blockPieces(node) {
1376
+ const meaningful = node.children.filter((c) => !(c.type === "JSXText" && !c.value.trim()));
1377
+ if (meaningful.length === 0) return { quasis: [], expressions: [] };
1378
+ if (meaningful.length !== 1) return null;
1379
+ const only = meaningful[0];
1380
+ if (only.type !== "JSXExpressionContainer") return null;
1381
+ const expr = only.expression;
1382
+ if (expr.type === "StringLiteral") return { quasis: [{ type: "TemplateElement", value: { raw: expr.value, cooked: expr.value } }], expressions: [] };
1383
+ if (expr.type === "TemplateLiteral") return { quasis: expr.quasis, expressions: expr.expressions };
1384
+ return null;
1385
+ }
1386
+ function findLiterals(program, modules, plan, intrinsic) {
1387
+ const literals = /* @__PURE__ */ new Map();
1388
+ const imports = /* @__PURE__ */ new Map();
1389
+ const tags = new Set(intrinsic);
1390
+ for (const statement of program.body ?? []) {
1391
+ if (statement.type !== "ImportDeclaration") continue;
1392
+ const source = statement.source.value;
1393
+ const specifiers = statement.specifiers;
1394
+ for (const sp of specifiers) {
1395
+ if (sp.type === "ImportSpecifier") imports.set(sp.local.name, { source, name: sp.imported.name ?? sp.imported.value });
1396
+ }
1397
+ if (!modules.includes(source)) continue;
1398
+ const css = specifiers.find((sp) => sp.type === "ImportSpecifier" && (sp.imported.name ?? sp.imported.value) === "css");
1399
+ if (!css) continue;
1400
+ const local = css.local.name;
1401
+ tags.add(local);
1402
+ imports.delete(local);
1403
+ plan.edits.push({ start: statement.start, end: statement.end, code: importWithout(statement, css) });
1404
+ }
1405
+ if (tags.size === 0) return { literals, imports };
1406
+ const visit = (node) => {
1407
+ if (!node || typeof node !== "object") return;
1408
+ if (node.type === "VariableDeclarator" && node.id.type === "Identifier" && node.init?.type === "TaggedTemplateExpression" && node.init.tag.type === "Identifier" && tags.has(node.init.tag.name)) {
1409
+ literals.set(node.id.name, node.init);
1410
+ }
1411
+ for (const key of Object.keys(node)) {
1412
+ if (key === "loc") continue;
1413
+ const value = node[key];
1414
+ if (Array.isArray(value)) for (const v of value) visit(v);
1415
+ else if (value && typeof value === "object" && "type" in value) visit(value);
1416
+ }
1417
+ };
1418
+ visit(program);
1419
+ return { literals, imports };
1420
+ }
1421
+ function importWithout(statement, removed) {
1422
+ const rest = statement.specifiers.filter((sp) => sp !== removed);
1423
+ const source = JSON.stringify(statement.source.value);
1424
+ if (rest.length === 0) return "";
1425
+ const def = rest.find((sp) => sp.type === "ImportDefaultSpecifier");
1426
+ const ns = rest.find((sp) => sp.type === "ImportNamespaceSpecifier");
1427
+ const named = rest.filter((sp) => sp.type === "ImportSpecifier").map((sp) => {
1428
+ const imported = sp.imported.name ?? JSON.stringify(sp.imported.value);
1429
+ return imported === sp.local.name ? imported : `${imported} as ${sp.local.name}`;
1430
+ });
1431
+ const parts = [def?.local.name, ns ? `* as ${ns.local.name}` : void 0, named.length ? `{ ${named.join(", ")} }` : void 0].filter(Boolean);
1432
+ return `import ${parts.join(", ")} from ${source};`;
1433
+ }
1434
+ function functionName(fn, named) {
1435
+ if ((fn.type === "FunctionDeclaration" || fn.type === "FunctionExpression") && fn.id) return fn.id.name;
1436
+ return named.get(fn) ?? "anonymous";
1437
+ }
1438
+ function hash(text) {
1439
+ let h = 2166136261;
1440
+ for (let i = 0; i < text.length; i++) {
1441
+ h ^= text.charCodeAt(i);
1442
+ h = Math.imul(h, 16777619);
1443
+ }
1444
+ return (h >>> 0).toString(36);
1445
+ }
1446
+ var OPAQUE = /(^|-)keyframes$|^font-face$|^property$|^counter-style$|^page$|^font-feature-values$/;
1447
+ function scopeNodes(nodes, id, warn = () => {
1448
+ }) {
1449
+ return nodes.map((node) => {
1450
+ if (node.kind === "rule") return { ...node, selector: scopeSelector(node.selector, id, warn) };
1451
+ if (node.kind === "at-rule" && !OPAQUE.test(node.name)) return { ...node, nodes: scopeNodes(node.nodes, id, warn) };
1452
+ return node;
1453
+ });
1454
+ }
1455
+ function scopeSelector(selector, id, warn = () => {
1456
+ }) {
1457
+ return splitTop(selector, ",").map((complex) => scopeComplex(complex.trim(), `[${SCOPE_ATTR}="${id}"]`, warn)).join(", ");
1458
+ }
1459
+ function scopeComplex(selector, attr, warn) {
1460
+ if (/:host\b|::slotted\(/.test(selector)) {
1461
+ warn(`\`${selector}\` only means something in a shadow root; in a light-DOM component it is left as written.`);
1462
+ return selector;
1463
+ }
1464
+ const parts = compounds(selector);
1465
+ const deep = parts.findIndex((p) => p.text.startsWith(":deep("));
1466
+ if (deep !== -1) {
1467
+ const inner = unwrap(parts[deep].text, ":deep(");
1468
+ const before = parts.slice(0, deep);
1469
+ if (before.length === 0) return `${attr} ${inner}`;
1470
+ const scopedBefore = scopeAt(before, before.length - 1, attr);
1471
+ return `${join(scopedBefore)} ${inner}`;
1472
+ }
1473
+ let target = -1;
1474
+ for (let i = parts.length - 1; i >= 0; i--) {
1475
+ if (!parts[i].text.startsWith(":global(")) {
1476
+ target = i;
1477
+ break;
1478
+ }
1479
+ }
1480
+ const out = target === -1 ? parts : scopeAt(parts, target, attr);
1481
+ return join(out.map((p) => p.text.startsWith(":global(") ? { ...p, text: unwrap(p.text, ":global(") } : p));
1482
+ }
1483
+ function scopeAt(parts, index, attr) {
1484
+ return parts.map((p, i) => i === index ? { ...p, text: insertAttr(p.text, attr) } : p);
1485
+ }
1486
+ function insertAttr(compound, attr) {
1487
+ let depth = 0;
1488
+ let quote = "";
1489
+ for (let i = 0; i < compound.length; i++) {
1490
+ const c = compound[i];
1491
+ if (quote) {
1492
+ if (c === "\\") i++;
1493
+ else if (c === quote) quote = "";
1494
+ continue;
1495
+ }
1496
+ if (c === "\\") {
1497
+ i++;
1498
+ continue;
1499
+ }
1500
+ if (c === '"' || c === "'") quote = c;
1501
+ else if (c === "(" || c === "[") depth++;
1502
+ else if (c === ")" || c === "]") depth--;
1503
+ else if (c === ":" && depth === 0 && i > 0) return compound.slice(0, i) + attr + compound.slice(i);
1504
+ }
1505
+ return compound + attr;
1506
+ }
1507
+ function compounds(selector) {
1508
+ const out = [];
1509
+ let depth = 0;
1510
+ let quote = "";
1511
+ let current = "";
1512
+ let combinator = "";
1513
+ const push = () => {
1514
+ if (current.trim()) out.push({ combinator: out.length ? combinator || " " : "", text: current.trim() });
1515
+ current = "";
1516
+ combinator = "";
1517
+ };
1518
+ for (let i = 0; i < selector.length; i++) {
1519
+ const c = selector[i];
1520
+ if (quote) {
1521
+ current += c;
1522
+ if (c === "\\") current += selector[++i] ?? "";
1523
+ else if (c === quote) quote = "";
1524
+ continue;
1525
+ }
1526
+ if (c === "\\") {
1527
+ current += c + (selector[++i] ?? "");
1528
+ continue;
1529
+ }
1530
+ if (c === '"' || c === "'") quote = c;
1531
+ if (c === "(" || c === "[") depth++;
1532
+ if (c === ")" || c === "]") depth--;
1533
+ if (depth === 0 && (c === ">" || c === "+" || c === "~")) {
1534
+ push();
1535
+ combinator = c;
1536
+ continue;
1537
+ }
1538
+ if (depth === 0 && /\s/.test(c)) {
1539
+ if (current.trim()) {
1540
+ const keep = combinator;
1541
+ push();
1542
+ combinator = keep;
1543
+ }
1544
+ continue;
1545
+ }
1546
+ current += c;
1547
+ }
1548
+ push();
1549
+ return out;
1550
+ }
1551
+ function join(parts) {
1552
+ return parts.map((p, i) => i === 0 ? p.text : p.combinator === " " ? ` ${p.text}` : ` ${p.combinator} ${p.text}`).join("");
1553
+ }
1554
+ function unwrap(text, prefix) {
1555
+ return text.slice(prefix.length, text.lastIndexOf(")")).trim() + text.slice(text.lastIndexOf(")") + 1);
1556
+ }
1557
+ function splitTop(selector, separator) {
1558
+ const parts = [];
1559
+ let depth = 0;
1560
+ let quote = "";
1561
+ let start = 0;
1562
+ for (let i = 0; i < selector.length; i++) {
1563
+ const c = selector[i];
1564
+ if (quote) {
1565
+ if (c === "\\") i++;
1566
+ else if (c === quote) quote = "";
1567
+ } else if (c === '"' || c === "'") quote = c;
1568
+ else if (c === "\\") i++;
1569
+ else if (c === "(" || c === "[") depth++;
1570
+ else if (c === ")" || c === "]") depth--;
1571
+ else if (c === separator && depth === 0) {
1572
+ parts.push(selector.slice(start, i));
1573
+ start = i + 1;
1574
+ }
1575
+ }
1576
+ parts.push(selector.slice(start));
1577
+ return parts.filter((p) => p.trim());
1578
+ }
1579
+ function shiftLoc(node, source, start) {
1580
+ 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;
1581
+ if (node.kind === "rule" || node.kind === "at-rule") return { ...node, loc, nodes: node.nodes.map((n2) => shiftLoc(n2, source, start)) };
1582
+ return { ...node, loc };
1583
+ }
1584
+ function keepLocIn(node, modules) {
1585
+ const keep = node.loc !== void 0 && modules?.has(node.loc.source) === true;
1586
+ const { loc, ...rest } = node;
1587
+ const kept = keep ? { ...rest, loc } : rest;
1588
+ if (kept.kind === "rule" || kept.kind === "at-rule") return { ...kept, nodes: kept.nodes.map((n2) => keepLocIn(n2, modules)) };
1589
+ return kept;
1590
+ }
1591
+ function printStyleWithMap(nodes, minify, sourceName, module, others) {
1592
+ const sources = [module];
1593
+ const index = /* @__PURE__ */ new Map([[sourceName, 0]]);
1594
+ const sourceOf = (name) => {
1595
+ if (index.has(name)) return index.get(name);
1596
+ const other = others?.get(name);
1597
+ if (!other) return void 0;
1598
+ index.set(name, sources.push(other) - 1);
1599
+ return index.get(name);
1600
+ };
1601
+ const lines = [[]];
1602
+ let css = "";
1603
+ let column = 0;
1604
+ const emit = (text) => {
1605
+ for (const ch of text) {
1606
+ css += ch;
1607
+ if (ch === "\n") {
1608
+ lines.push([]);
1609
+ column = 0;
1610
+ } else column++;
1611
+ }
1612
+ };
1613
+ const mark = (loc) => {
1614
+ const at = loc ? sourceOf(loc.source) : void 0;
1615
+ if (loc && at !== void 0) lines[lines.length - 1].push([column, at, loc.line - 1, loc.column]);
1616
+ };
1617
+ const write = (node, depth) => {
1618
+ const pad = minify ? "" : " ".repeat(depth);
1619
+ const nl = minify ? "" : "\n";
1620
+ const sp = minify ? "" : " ";
1621
+ emit(pad);
1622
+ mark(node.loc);
1623
+ if (node.kind === "declaration") {
1624
+ emit(`${node.property}:${sp}${node.value}${node.important ? `${sp}!important` : ""};${nl}`);
1625
+ } else if (node.kind === "raw") {
1626
+ emit(`${node.text}${nl}`);
1627
+ } else {
1628
+ emit(`${node.kind === "rule" ? node.selector : `@${node.name}${node.params ? " " + node.params : ""}`}${sp}{${nl}`);
1629
+ for (const child of node.nodes) write(child, depth + 1);
1630
+ emit(`${pad}}${nl}`);
1631
+ }
1632
+ };
1633
+ for (const node of nodes) write(node, 0);
1634
+ return { css, map: { version: 3, sources: sources.map((s) => s.id), sourcesContent: sources.map((s) => s.code), names: [], mappings: encode(lines) } };
1635
+ }
1636
+ function printStyle(nodes, minify = false) {
1637
+ const out = [];
1638
+ const write = (node, depth) => {
1639
+ const pad = minify ? "" : " ".repeat(depth);
1640
+ const nl = minify ? "" : "\n";
1641
+ const sp = minify ? "" : " ";
1642
+ if (node.kind === "declaration") {
1643
+ out.push(`${pad}${node.property}:${sp}${node.value}${node.important ? `${sp}!important` : ""};${nl}`);
1644
+ } else if (node.kind === "raw") {
1645
+ out.push(`${pad}${node.text}${nl}`);
1646
+ } else {
1647
+ const header = node.kind === "rule" ? node.selector : `@${node.name}${node.params ? " " + node.params : ""}`;
1648
+ out.push(`${pad}${header}${sp}{${nl}`);
1649
+ for (const child of node.nodes) write(child, depth + 1);
1650
+ out.push(`${pad}}${nl}`);
1651
+ }
1652
+ };
1653
+ for (const node of nodes) write(node, 0);
1654
+ return out.join("");
1655
+ }
1656
+
1079
1657
  // src/optimize/analyze-static.ts
1080
1658
  function propReason(prop) {
1081
1659
  switch (prop.kind) {
@@ -1573,6 +2151,16 @@ var PRIMITIVE_MODULES = [
1573
2151
  "@fluixi/reactive/cached-resource",
1574
2152
  "@fluixi/core"
1575
2153
  ];
2154
+ var TAG_INTRINSICS = {
2155
+ $html: { export: "html", module: "@fluixi/core" },
2156
+ $svg: { export: "svg", module: "@fluixi/core" },
2157
+ $css: { export: "css", module: "@fluixi/core" }
2158
+ };
2159
+ function tagIntrinsics(bound) {
2160
+ const tags = /* @__PURE__ */ new Map();
2161
+ for (const [name, tag] of Object.entries(TAG_INTRINSICS)) if (!bound.has(name)) tags.set(name, tag.export);
2162
+ return tags;
2163
+ }
1576
2164
  var INTRINSIC_CALL = new RegExp(`\\$(?:${Object.keys(INTRINSICS).map((n2) => n2.slice(1)).join("|")})\\s*\\(`);
1577
2165
  function mayHaveIntrinsic(code) {
1578
2166
  return INTRINSIC_CALL.test(code);
@@ -2076,7 +2664,7 @@ function emitComponent(name, props, children, used, templates, at) {
2076
2664
  }
2077
2665
  let obj = `{ ${bodies.map(([name2, body]) => `get ${propKey(name2)}() { return ${body}; }`).join(", ")} }`;
2078
2666
  if (bodies.some(([, body]) => /\bthis\b/.test(body))) {
2079
- const thunks = bodies.map(([name2, body]) => `${JSON.stringify(name2)}: () => ${body}`);
2667
+ const thunks = bodies.map(([name2, body]) => `${JSON.stringify(name2)}: () => (${body})`);
2080
2668
  const getters = bodies.map(([name2]) => `get ${propKey(name2)}() { return _$t[${JSON.stringify(name2)}](); }`);
2081
2669
  obj = `((_$t) => ({ ${getters.join(", ")} }))({ ${thunks.join(", ")} })`;
2082
2670
  }
@@ -2277,6 +2865,271 @@ function cleanTemplateText(value) {
2277
2865
  return out;
2278
2866
  }
2279
2867
 
2868
+ // src/lower/entities.ts
2869
+ var NAMED = {
2870
+ quot: 34,
2871
+ amp: 38,
2872
+ apos: 39,
2873
+ lt: 60,
2874
+ gt: 62,
2875
+ nbsp: 160,
2876
+ iexcl: 161,
2877
+ cent: 162,
2878
+ pound: 163,
2879
+ curren: 164,
2880
+ yen: 165,
2881
+ brvbar: 166,
2882
+ sect: 167,
2883
+ uml: 168,
2884
+ copy: 169,
2885
+ ordf: 170,
2886
+ laquo: 171,
2887
+ not: 172,
2888
+ shy: 173,
2889
+ reg: 174,
2890
+ macr: 175,
2891
+ deg: 176,
2892
+ plusmn: 177,
2893
+ sup2: 178,
2894
+ sup3: 179,
2895
+ acute: 180,
2896
+ micro: 181,
2897
+ para: 182,
2898
+ middot: 183,
2899
+ cedil: 184,
2900
+ sup1: 185,
2901
+ ordm: 186,
2902
+ raquo: 187,
2903
+ frac14: 188,
2904
+ frac12: 189,
2905
+ frac34: 190,
2906
+ iquest: 191,
2907
+ Agrave: 192,
2908
+ Aacute: 193,
2909
+ Acirc: 194,
2910
+ Atilde: 195,
2911
+ Auml: 196,
2912
+ Aring: 197,
2913
+ AElig: 198,
2914
+ Ccedil: 199,
2915
+ Egrave: 200,
2916
+ Eacute: 201,
2917
+ Ecirc: 202,
2918
+ Euml: 203,
2919
+ Igrave: 204,
2920
+ Iacute: 205,
2921
+ Icirc: 206,
2922
+ Iuml: 207,
2923
+ ETH: 208,
2924
+ Ntilde: 209,
2925
+ Ograve: 210,
2926
+ Oacute: 211,
2927
+ Ocirc: 212,
2928
+ Otilde: 213,
2929
+ Ouml: 214,
2930
+ times: 215,
2931
+ Oslash: 216,
2932
+ Ugrave: 217,
2933
+ Uacute: 218,
2934
+ Ucirc: 219,
2935
+ Uuml: 220,
2936
+ Yacute: 221,
2937
+ THORN: 222,
2938
+ szlig: 223,
2939
+ agrave: 224,
2940
+ aacute: 225,
2941
+ acirc: 226,
2942
+ atilde: 227,
2943
+ auml: 228,
2944
+ aring: 229,
2945
+ aelig: 230,
2946
+ ccedil: 231,
2947
+ egrave: 232,
2948
+ eacute: 233,
2949
+ ecirc: 234,
2950
+ euml: 235,
2951
+ igrave: 236,
2952
+ iacute: 237,
2953
+ icirc: 238,
2954
+ iuml: 239,
2955
+ eth: 240,
2956
+ ntilde: 241,
2957
+ ograve: 242,
2958
+ oacute: 243,
2959
+ ocirc: 244,
2960
+ otilde: 245,
2961
+ ouml: 246,
2962
+ divide: 247,
2963
+ oslash: 248,
2964
+ ugrave: 249,
2965
+ uacute: 250,
2966
+ ucirc: 251,
2967
+ uuml: 252,
2968
+ yacute: 253,
2969
+ thorn: 254,
2970
+ yuml: 255,
2971
+ OElig: 338,
2972
+ oelig: 339,
2973
+ Scaron: 352,
2974
+ scaron: 353,
2975
+ Yuml: 376,
2976
+ fnof: 402,
2977
+ circ: 710,
2978
+ tilde: 732,
2979
+ Alpha: 913,
2980
+ Beta: 914,
2981
+ Gamma: 915,
2982
+ Delta: 916,
2983
+ Epsilon: 917,
2984
+ Zeta: 918,
2985
+ Eta: 919,
2986
+ Theta: 920,
2987
+ Iota: 921,
2988
+ Kappa: 922,
2989
+ Lambda: 923,
2990
+ Mu: 924,
2991
+ Nu: 925,
2992
+ Xi: 926,
2993
+ Omicron: 927,
2994
+ Pi: 928,
2995
+ Rho: 929,
2996
+ Sigma: 931,
2997
+ Tau: 932,
2998
+ Upsilon: 933,
2999
+ Phi: 934,
3000
+ Chi: 935,
3001
+ Psi: 936,
3002
+ Omega: 937,
3003
+ alpha: 945,
3004
+ beta: 946,
3005
+ gamma: 947,
3006
+ delta: 948,
3007
+ epsilon: 949,
3008
+ zeta: 950,
3009
+ eta: 951,
3010
+ theta: 952,
3011
+ iota: 953,
3012
+ kappa: 954,
3013
+ lambda: 955,
3014
+ mu: 956,
3015
+ nu: 957,
3016
+ xi: 958,
3017
+ omicron: 959,
3018
+ pi: 960,
3019
+ rho: 961,
3020
+ sigmaf: 962,
3021
+ sigma: 963,
3022
+ tau: 964,
3023
+ upsilon: 965,
3024
+ phi: 966,
3025
+ chi: 967,
3026
+ psi: 968,
3027
+ omega: 969,
3028
+ thetasym: 977,
3029
+ upsih: 978,
3030
+ piv: 982,
3031
+ ensp: 8194,
3032
+ emsp: 8195,
3033
+ thinsp: 8201,
3034
+ zwnj: 8204,
3035
+ zwj: 8205,
3036
+ lrm: 8206,
3037
+ rlm: 8207,
3038
+ ndash: 8211,
3039
+ mdash: 8212,
3040
+ lsquo: 8216,
3041
+ rsquo: 8217,
3042
+ sbquo: 8218,
3043
+ ldquo: 8220,
3044
+ rdquo: 8221,
3045
+ bdquo: 8222,
3046
+ dagger: 8224,
3047
+ Dagger: 8225,
3048
+ bull: 8226,
3049
+ hellip: 8230,
3050
+ permil: 8240,
3051
+ prime: 8242,
3052
+ Prime: 8243,
3053
+ lsaquo: 8249,
3054
+ rsaquo: 8250,
3055
+ oline: 8254,
3056
+ frasl: 8260,
3057
+ euro: 8364,
3058
+ image: 8465,
3059
+ weierp: 8472,
3060
+ real: 8476,
3061
+ trade: 8482,
3062
+ alefsym: 8501,
3063
+ larr: 8592,
3064
+ uarr: 8593,
3065
+ rarr: 8594,
3066
+ darr: 8595,
3067
+ harr: 8596,
3068
+ crarr: 8629,
3069
+ lArr: 8656,
3070
+ uArr: 8657,
3071
+ rArr: 8658,
3072
+ dArr: 8659,
3073
+ hArr: 8660,
3074
+ forall: 8704,
3075
+ part: 8706,
3076
+ exist: 8707,
3077
+ empty: 8709,
3078
+ nabla: 8711,
3079
+ isin: 8712,
3080
+ notin: 8713,
3081
+ ni: 8715,
3082
+ prod: 8719,
3083
+ sum: 8721,
3084
+ minus: 8722,
3085
+ lowast: 8727,
3086
+ radic: 8730,
3087
+ prop: 8733,
3088
+ infin: 8734,
3089
+ ang: 8736,
3090
+ and: 8743,
3091
+ or: 8744,
3092
+ cap: 8745,
3093
+ cup: 8746,
3094
+ int: 8747,
3095
+ there4: 8756,
3096
+ sim: 8764,
3097
+ cong: 8773,
3098
+ asymp: 8776,
3099
+ ne: 8800,
3100
+ equiv: 8801,
3101
+ le: 8804,
3102
+ ge: 8805,
3103
+ sub: 8834,
3104
+ sup: 8835,
3105
+ nsub: 8836,
3106
+ sube: 8838,
3107
+ supe: 8839,
3108
+ oplus: 8853,
3109
+ otimes: 8855,
3110
+ perp: 8869,
3111
+ sdot: 8901,
3112
+ lceil: 8968,
3113
+ rceil: 8969,
3114
+ lfloor: 8970,
3115
+ rfloor: 8971,
3116
+ lang: 9001,
3117
+ rang: 9002,
3118
+ loz: 9674,
3119
+ spades: 9824,
3120
+ clubs: 9827,
3121
+ hearts: 9829,
3122
+ diams: 9830
3123
+ };
3124
+ var REFERENCE = /&(?:#[xX]([0-9a-fA-F]{1,6})|#([0-9]{1,7})|([a-zA-Z][a-zA-Z0-9]{1,31}));/g;
3125
+ function decodeEntities(value) {
3126
+ if (!value.includes("&")) return value;
3127
+ return value.replace(REFERENCE, (match, hex, dec, name) => {
3128
+ const code = hex ? parseInt(hex, 16) : dec ? parseInt(dec, 10) : Object.prototype.hasOwnProperty.call(NAMED, name) ? NAMED[name] : void 0;
3129
+ return code !== void 0 && code <= 1114111 ? String.fromCodePoint(code) : match;
3130
+ });
3131
+ }
3132
+
2280
3133
  // src/lower/template.ts
2281
3134
  var DELEGATED = /* @__PURE__ */ new Set([
2282
3135
  "click",
@@ -2363,7 +3216,7 @@ var Lowerer = class {
2363
3216
  switch (node.kind) {
2364
3217
  case "Text": {
2365
3218
  if (node.raw) return { kind: "text", value: node.value };
2366
- const cleaned = cleanTemplateText(node.value);
3219
+ const cleaned = decodeEntities(cleanTemplateText(node.value));
2367
3220
  return cleaned ? { kind: "text", value: cleaned } : null;
2368
3221
  }
2369
3222
  case "Comment":
@@ -2399,7 +3252,7 @@ var Lowerer = class {
2399
3252
  kind: "element",
2400
3253
  tag: el.tag,
2401
3254
  svg: el.namespace === "svg",
2402
- props: this.lowerAttributes(el.attributes),
3255
+ props: this.lowerAttributes(el.attributes, true),
2403
3256
  children,
2404
3257
  static: false,
2405
3258
  ...at ? { at } : {}
@@ -2512,13 +3365,22 @@ var Lowerer = class {
2512
3365
  return clone.kind === "Element" ? this.lowerElement(clone) : this.lowerComponent(clone);
2513
3366
  }
2514
3367
  // --- attributes ---------------------------------------------------------
2515
- lowerAttributes(attrs) {
3368
+ /**
3369
+ * `element`: a DOM element, where each class:/style: value that moves is its own accessor.
3370
+ * A component gets the object as before, rebuilt whole when any value moves.
3371
+ */
3372
+ lowerAttributes(attrs, element = false) {
3373
+ let anyReactive = false;
3374
+ const entry = (name, h) => {
3375
+ anyReactive ||= h.reactive;
3376
+ if (!element || !h.reactive) return `${JSON.stringify(name)}: ${h.code}`;
3377
+ const accessor = `() => ${paren(h.code, "arrowBody")}`;
3378
+ return `${JSON.stringify(name)}: ${h.at ? markHole(accessor, h.at.line, h.at.column) : accessor}`;
3379
+ };
2516
3380
  const props = [];
2517
3381
  const classEntries = [];
2518
- let classReactive = false;
2519
3382
  let classAt;
2520
3383
  const styleEntries = [];
2521
- let styleReactive = false;
2522
3384
  let styleAt;
2523
3385
  const usePairs = [];
2524
3386
  for (const a of attrs) {
@@ -2558,15 +3420,13 @@ var Lowerer = class {
2558
3420
  break;
2559
3421
  case "ClassDirective": {
2560
3422
  const h = this.hole(a.hole);
2561
- classEntries.push(`${JSON.stringify(a.name)}: ${h.code}`);
2562
- classReactive = classReactive || h.reactive;
3423
+ classEntries.push(entry(a.name, h));
2563
3424
  classAt ??= h.at;
2564
3425
  break;
2565
3426
  }
2566
3427
  case "StyleDirective": {
2567
3428
  const h = this.hole(a.hole);
2568
- styleEntries.push(`${JSON.stringify(a.name)}: ${h.code}`);
2569
- styleReactive = styleReactive || h.reactive;
3429
+ styleEntries.push(entry(a.name, h));
2570
3430
  styleAt ??= h.at;
2571
3431
  break;
2572
3432
  }
@@ -2586,18 +3446,19 @@ var Lowerer = class {
2586
3446
  name: "classList",
2587
3447
  kind: "attr",
2588
3448
  expr: `{ ${classEntries.join(", ")} }`,
2589
- reactive: classReactive,
3449
+ reactive: !element && anyReactive,
2590
3450
  ...classAt ? { at: classAt } : {}
2591
3451
  });
2592
3452
  }
2593
3453
  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
- });
3454
+ const entries = `{ ${styleEntries.join(", ")} }`;
3455
+ const base = props.findIndex((p) => p.name === "style");
3456
+ if (base === -1) props.push({ name: "style", kind: "attr", expr: entries, reactive: !element && anyReactive, ...styleAt ? { at: styleAt } : {} });
3457
+ else {
3458
+ const prop = props[base];
3459
+ const value = prop.expr === void 0 ? JSON.stringify(prop.literal) : prop.reactive ? `() => ${paren(prop.expr, "arrowBody")}` : prop.expr;
3460
+ props[base] = { name: "style", kind: "attr", expr: `[${value}, ${entries}]`, reactive: false, ...prop.at ? { at: prop.at } : {} };
3461
+ }
2601
3462
  }
2602
3463
  if (usePairs.length > 0) {
2603
3464
  props.push({ name: "use", kind: "attr", expr: `[${usePairs.join(", ")}]` });
@@ -2686,7 +3547,7 @@ var Lowerer = class {
2686
3547
  return base;
2687
3548
  }
2688
3549
  if (v.kind === "static") {
2689
- base.literal = v.value;
3550
+ base.literal = decodeEntities(v.value);
2690
3551
  return base;
2691
3552
  }
2692
3553
  if (v.kind === "hole") {
@@ -2699,7 +3560,7 @@ var Lowerer = class {
2699
3560
  let reactive = false;
2700
3561
  let at;
2701
3562
  const body = v.parts.map((p) => {
2702
- if ("text" in p) return escapeTemplate(p.text);
3563
+ if ("text" in p) return escapeTemplate(decodeEntities(p.text));
2703
3564
  const h = this.hole(p.hole);
2704
3565
  reactive = reactive || h.reactive;
2705
3566
  at ??= h.at;
@@ -2724,6 +3585,7 @@ function compilePieces(pieces, holes, options = {}) {
2724
3585
  ...options.sourceFile ? { sourceFile: options.sourceFile } : {},
2725
3586
  ...options.positionAt ? { positionAt: options.positionAt } : {}
2726
3587
  });
3588
+ if (options.templateStyles) applyTemplateStyles(ir, options.templateStyles);
2727
3589
  analyzeStatic(ir);
2728
3590
  resolveComponentSources(ir, {
2729
3591
  resolver: createComponentResolver(options.resolve ?? []),
@@ -2922,9 +3784,12 @@ function attrExprCode(attr, ctx) {
2922
3784
  }
2923
3785
  return null;
2924
3786
  }
2925
- function buildProps(attrs, ctx) {
3787
+ function buildProps(attrs, ctx, element = false) {
2926
3788
  const props = [];
2927
3789
  const usePairs = [];
3790
+ const classEntries = [];
3791
+ const styleEntries = [];
3792
+ let styleAt;
2928
3793
  for (const a of attrs) {
2929
3794
  if (a.type === "JSXSpreadAttribute") {
2930
3795
  props.push({ name: "", kind: "spread", expr: ctx.code(a.argument) });
@@ -2940,6 +3805,27 @@ function buildProps(attrs, ctx) {
2940
3805
  usePairs.push(opts != null ? `[${dir}, () => ${paren(opts, "arrowBody")}]` : `[${dir}]`);
2941
3806
  continue;
2942
3807
  }
3808
+ if (element && (ns === "class" || ns === "style")) {
3809
+ const key = JSON.stringify(a.name.name.name);
3810
+ const v = a.value;
3811
+ let value;
3812
+ if (v == null) value = "true";
3813
+ else if (isString(v)) value = JSON.stringify(literalOf(v));
3814
+ else if (v.type === "JSXExpressionContainer" && v.expression?.type !== "JSXEmptyExpression") {
3815
+ value = keyValue(v.expression, ctx);
3816
+ if (ns === "style") styleAt ??= posOf(v.expression, ctx);
3817
+ } else continue;
3818
+ (ns === "class" ? classEntries : styleEntries).push(`${key}: ${value}`);
3819
+ continue;
3820
+ }
3821
+ if (element && a.name.type === "JSXIdentifier" && a.name.name === "style" && a.value?.type === "JSXExpressionContainer") {
3822
+ const entries = objectEntries(a.value.expression, ctx);
3823
+ if (entries) {
3824
+ styleEntries.unshift(...entries);
3825
+ styleAt = posOf(a.value.expression, ctx);
3826
+ continue;
3827
+ }
3828
+ }
2943
3829
  if (ns === "oncapture") {
2944
3830
  const evt = a.name.name.name.toLowerCase();
2945
3831
  const h = attrExprCode(a, ctx) ?? "undefined";
@@ -2948,9 +3834,37 @@ function buildProps(attrs, ctx) {
2948
3834
  }
2949
3835
  props.push(buildAttr(a, ctx));
2950
3836
  }
3837
+ if (classEntries.length > 0) props.push({ name: "classList", kind: "attr", expr: `{ ${classEntries.join(", ")} }`, reactive: false });
3838
+ if (styleEntries.length > 0) {
3839
+ const entries = `{ ${styleEntries.join(", ")} }`;
3840
+ const base = props.findIndex((p) => p.name === "style" && p.kind === "attr");
3841
+ if (base === -1) props.push({ name: "style", kind: "attr", expr: entries, reactive: false, ...styleAt ? { at: styleAt } : {} });
3842
+ else {
3843
+ const prop = props[base];
3844
+ const value = prop.literal !== void 0 ? JSON.stringify(prop.literal) : prop.reactive ? `() => ${paren(prop.expr, "arrowBody")}` : prop.expr;
3845
+ props[base] = { name: "style", kind: "attr", expr: `[${value}, ${entries}]`, reactive: false, ...prop.at ? { at: prop.at } : {} };
3846
+ }
3847
+ }
2951
3848
  if (usePairs.length > 0) props.push({ name: "use", kind: "attr", expr: `[${usePairs.join(", ")}]` });
2952
3849
  return props;
2953
3850
  }
3851
+ function keyValue(expr, ctx) {
3852
+ const code = ctx.code(expr);
3853
+ if (!isReactive(expr)) return code;
3854
+ const accessor = `() => ${paren(code, "arrowBody")}`;
3855
+ const at = posOf(expr, ctx);
3856
+ return at ? markHole(accessor, at.line, at.column) : accessor;
3857
+ }
3858
+ function objectEntries(expr, ctx) {
3859
+ if (expr?.type !== "ObjectExpression") return null;
3860
+ const entries = [];
3861
+ for (const p of expr.properties) {
3862
+ if (p.type !== "ObjectProperty") return null;
3863
+ const key = p.computed ? `[${ctx.code(p.key)}]` : p.key.type === "Identifier" ? JSON.stringify(p.key.name) : JSON.stringify(String(p.key.value));
3864
+ entries.push(`${key}: ${keyValue(p.value, ctx)}`);
3865
+ }
3866
+ return entries;
3867
+ }
2954
3868
  function buildChildren(children, ctx) {
2955
3869
  const out = [];
2956
3870
  for (let i = 0; i < children.length; i++) {
@@ -2978,6 +3892,7 @@ function buildChildren(children, ctx) {
2978
3892
  });
2979
3893
  }
2980
3894
  } else if (child.type === "JSXElement" || child.type === "JSXFragment") {
3895
+ if (ctx.dropStyles?.has(child.start)) continue;
2981
3896
  out.push(buildNode(child, ctx));
2982
3897
  } else if (child.type === "JSXSpreadChild") {
2983
3898
  out.push({ kind: "expr", code: ctx.code(child.expression), reactive: false });
@@ -3047,13 +3962,17 @@ function buildElement(node, ctx, handled) {
3047
3962
  const children = each ? [each] : buildChildren(node.children, ctx);
3048
3963
  if (tag === CONTAINER2) return children.length === 1 ? children[0] : { kind: "fragment", children };
3049
3964
  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 } : {} };
3965
+ const props = buildProps(attributes, ctx, true);
3966
+ const scope = ctx.scopes?.find((s) => node.start >= s.start && node.end <= s.end);
3967
+ if (scope) props.unshift({ name: "data-fx-s", kind: "attr", literal: scope.value });
3968
+ return { kind: "element", tag, svg: SVG_TAGS.has(tag), props, children, static: false, ...at ? { at } : {} };
3051
3969
  }
3052
3970
  function buildNode(node, ctx) {
3053
3971
  if (node.type === "JSXFragment") {
3054
3972
  return { kind: "fragment", children: buildChildren(node.children, ctx) };
3055
3973
  }
3056
3974
  if (directive(node, "if")) return buildIf(node, null, ctx);
3975
+ if (ctx.dropStyles?.has(node.start)) return { kind: "fragment", children: [] };
3057
3976
  const { tag, component } = tagInfo(node.openingElement.name, ctx);
3058
3977
  if (!component) return buildElement(node, ctx, []);
3059
3978
  const props = buildProps(node.openingElement.attributes, ctx);
@@ -3581,8 +4500,8 @@ function isJsxRoot(node, parent, key) {
3581
4500
  if (!isJsx(node)) return false;
3582
4501
  return !(parent && isJsx(parent) && key === "children");
3583
4502
  }
3584
- function isTemplateTag(node, litTag) {
3585
- return node.type === "TaggedTemplateExpression" && node.tag?.type === "Identifier" && (node.tag.name === litTag || node.tag.name === "svg");
4503
+ function isTemplateTag(node, tags) {
4504
+ return node.type === "TaggedTemplateExpression" && node.tag?.type === "Identifier" && tags.has(node.tag.name);
3586
4505
  }
3587
4506
  function outermost(list) {
3588
4507
  return list.filter(
@@ -3730,22 +4649,28 @@ function transformTemplates(code, id, options = {}) {
3730
4649
  const wantsIntrinsics = options.intrinsics !== false && mayHaveIntrinsic(code);
3731
4650
  const wantsSources = options.sourceLocations === true && mayHaveSourceMarks(code);
3732
4651
  const sourceName = relativeToRoot(id, options.sourceRoot);
3733
- if (!mayHaveTemplate && !(wantsJsx && code.includes("<")) && !wantsIntrinsics && !wantsSources) return null;
4652
+ const wantsStyles = options.styles !== void 0 && (code.includes("<style") || code.includes("css`"));
4653
+ if (!mayHaveTemplate && !(wantsJsx && code.includes("<")) && !wantsIntrinsics && !wantsSources && !wantsStyles) return null;
3734
4654
  const ast = parse2(code, {
3735
4655
  sourceType: "module",
3736
4656
  plugins: ["jsx", "typescript"],
3737
4657
  errorRecovery: true
3738
4658
  });
4659
+ const intrinsicTags = options.intrinsics === false ? /* @__PURE__ */ new Map() : tagIntrinsics(moduleBindings(ast.program));
4660
+ const templateTags = /* @__PURE__ */ new Map([[litTag, "html"], ["svg", "svg"]]);
4661
+ for (const [name, tag] of intrinsicTags) if (tag !== "css") templateTags.set(name, tag);
4662
+ const cssTags = [...intrinsicTags].filter(([, tag]) => tag === "css").map(([name]) => name);
3739
4663
  const found = [];
3740
4664
  walk7(ast.program, (n2, parent, key) => {
3741
- if (wantsLit && isTemplateTag(n2, litTag)) found.push(n2);
4665
+ if (wantsLit && isTemplateTag(n2, templateTags)) found.push(n2);
3742
4666
  else if (wantsJsx && isJsxRoot(n2, parent, key)) found.push(n2);
3743
4667
  });
3744
4668
  const props = options.propsDestructure === false ? { edits: [], diagnostics: [], used: /* @__PURE__ */ new Set() } : collectPropsEdits(ast.program, code, { runtimeModule: options.runtimeModule });
3745
4669
  const intrinsics = options.intrinsics === false ? { edits: [], diagnostics: [], imports: /* @__PURE__ */ new Map() } : collectIntrinsicEdits(ast.program);
3746
4670
  if (intrinsics.edits.length) avoidBindingClashes(ast.program, intrinsics, moduleBindings(ast.program));
3747
4671
  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;
4672
+ const styles = wantsStyles ? collectStyles(ast.program, sourceName, options.styles, { html: templateTags, css: cssTags }, { id, code }) : void 0;
4673
+ 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
4674
  if (silent) return null;
3750
4675
  found.sort((a, b) => b.start - a.start || a.end - b.end);
3751
4676
  const used = new Set(props.used);
@@ -3759,20 +4684,32 @@ function transformTemplates(code, id, options = {}) {
3759
4684
  declared: declaredNames(ast.program)
3760
4685
  };
3761
4686
  const hoisted = /* @__PURE__ */ new Map();
3762
- const edits = [...props.edits, ...intrinsics.edits, ...sources.edits];
4687
+ const edits = [...props.edits, ...intrinsics.edits, ...sources.edits, ...styles?.edits ?? []];
3763
4688
  for (const node of found) {
3764
4689
  const nested = found.some(
3765
4690
  (o) => o !== node && o.start <= node.start && o.end >= node.end && o.end - o.start > node.end - node.start
3766
4691
  );
3767
4692
  if (isJsx(node)) {
3768
- edits.push({ start: node.start, end: node.end, code: compileJsx(code, node, edits, nested, used, needs, hoisted, options, sourceName) });
4693
+ edits.push({ start: node.start, end: node.end, code: compileJsx(code, node, edits, nested, used, needs, hoisted, options, sourceName, styles) });
3769
4694
  continue;
3770
4695
  }
3771
4696
  const holes = node.quasi.expressions.map(
3772
4697
  (e) => bindHole(code, e, edits, options.sourceLocations === true)
3773
4698
  );
4699
+ const scope = styles?.scopes.find((s) => node.start >= s.start && node.end <= s.end)?.value;
4700
+ const owner = styles?.templateOwners.get(node.start);
4701
+ const templateStyles = options.styles && styles && (scope || owner) ? {
4702
+ options: options.styles,
4703
+ ...scope ? { scope } : {},
4704
+ ...owner ? { owner } : {},
4705
+ line: node.loc?.start.line ?? 0,
4706
+ column: node.loc?.start.column ?? 0,
4707
+ styles: styles.styles,
4708
+ diagnostics: styles.diagnostics
4709
+ } : void 0;
3774
4710
  const result = compilePieces(toPieces(node), holes, {
3775
4711
  ...options,
4712
+ ...templateStyles ? { templateStyles } : {},
3776
4713
  hoistTemplates: true,
3777
4714
  // A tag inside a template gets the same mark a JSX tag does. Without one, the nodes it
3778
4715
  // makes are the only ones in the module carrying no mark, and they take whichever was
@@ -3781,12 +4718,13 @@ function transformTemplates(code, id, options = {}) {
3781
4718
  // Same defaults as the plugin, so moving a build over is not a rendering change.
3782
4719
  templateClone: options.templateClone ?? true,
3783
4720
  partialTemplates: nested ? false : options.partialTemplates ?? true,
3784
- svg: node.tag.name === "svg"
4721
+ svg: templateTags.get(node.tag.name) === "svg"
3785
4722
  });
3786
4723
  for (const symbol of result.imports) used.add(symbol);
3787
4724
  collectNeeds(result.ir, needs);
3788
4725
  edits.push({ start: node.start, end: node.end, code: adoptTemplates(result.code, result.templates, hoisted) });
3789
4726
  }
4727
+ if (styles && options.styles) edits.push(...finishShadowStyles(styles, code, id));
3790
4728
  const out = new MagicString(code);
3791
4729
  for (const e of outermost(edits)) {
3792
4730
  if (e.start === e.end) out.appendLeft(e.start, e.code);
@@ -3844,13 +4782,19 @@ function transformTemplates(code, id, options = {}) {
3844
4782
  ...loadDiagnostics.length ? { loadDiagnostics } : {},
3845
4783
  ...unresolvedDiagnostics.length ? { unresolvedDiagnostics } : {},
3846
4784
  ...props.diagnostics.length ? { propsDiagnostics: props.diagnostics } : {},
3847
- ...intrinsics.diagnostics.length ? { intrinsicDiagnostics: intrinsics.diagnostics } : {}
4785
+ ...intrinsics.diagnostics.length ? { intrinsicDiagnostics: intrinsics.diagnostics } : {},
4786
+ ...styles?.styles.length ? { styles: styles.styles } : {},
4787
+ ...styles?.diagnostics.length ? { styleDiagnostics: styles.diagnostics } : {},
4788
+ ...styles?.literals.length ? { styleLiterals: styles.literals } : {},
4789
+ ...styles?.references.length ? { styleReferences: styles.references } : {}
3848
4790
  };
3849
4791
  }
3850
- function compileJsx(code, node, edits, nested, used, needs, hoisted, options, sourceFile) {
4792
+ function compileJsx(code, node, edits, nested, used, needs, hoisted, options, sourceFile, styles) {
3851
4793
  const ir = buildJsxIR(node, {
3852
4794
  code: (n2) => slice(code, n2.start, n2.end, edits),
3853
4795
  used,
4796
+ ...styles?.scopes.length ? { scopes: styles.scopes } : {},
4797
+ ...styles?.drop.size ? { dropStyles: styles.drop } : {},
3854
4798
  ...options.sourceLocations === true && sourceFile ? { sourceFile } : {}
3855
4799
  });
3856
4800
  analyzeStatic(ir);