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