@barefootjs/erb 0.33.4 → 0.34.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/vite.js CHANGED
@@ -8,10 +8,45 @@ import { devModuleUrl, loadManifest, resolveDevOrigin, resolveScriptAssets, toPo
8
8
  import ts25 from "typescript";
9
9
 
10
10
  // ../jsx/src/analyzer.ts
11
- import ts9 from "typescript";
11
+ import ts10 from "typescript";
12
12
 
13
13
  // ../jsx/src/expression-parser.ts
14
14
  import ts from "typescript";
15
+
16
+ // ../jsx/src/lowering-registry.ts
17
+ var plugins = [];
18
+ function registerLoweringPlugin(plugin) {
19
+ const existing = plugins.findIndex((p) => p.name === plugin.name);
20
+ if (existing >= 0)
21
+ plugins[existing] = plugin;
22
+ else
23
+ plugins.push(plugin);
24
+ }
25
+ function prepareLoweringMatchers(metadata) {
26
+ const matchers = [];
27
+ for (const plugin of plugins) {
28
+ const matcher = plugin.prepare(metadata);
29
+ if (matcher)
30
+ matchers.push(matcher);
31
+ }
32
+ return matchers;
33
+ }
34
+ function loweringNodeChildren(node) {
35
+ if (node.kind === "helper-call")
36
+ return [...node.args];
37
+ const children = [node.base];
38
+ for (const t of node.triples) {
39
+ if (t.guard)
40
+ children.push(t.guard);
41
+ children.push(t.value);
42
+ }
43
+ return children;
44
+ }
45
+ function isValidHelperId(helper) {
46
+ return /^[A-Za-z_][A-Za-z0-9_]*$/.test(helper);
47
+ }
48
+
49
+ // ../jsx/src/expression-parser.ts
15
50
  var UNSUPPORTED_METHODS = new Set([
16
51
  "filter",
17
52
  "map",
@@ -263,7 +298,7 @@ function convertNode(node, raw) {
263
298
  }
264
299
  if (n === undefined || Number.isNaN(n)) {
265
300
  const parsedDepth = convertNode(depthNode, raw);
266
- if (checkSupport(parsedDepth, "rendered").supported) {
301
+ if (checkSupport(parsedDepth, "rendered", []).supported) {
267
302
  depthExpr = parsedDepth;
268
303
  flatDepth = 1;
269
304
  } else {
@@ -1041,13 +1076,13 @@ function getUnaryOperatorString(op) {
1041
1076
  return "unknown";
1042
1077
  }
1043
1078
  }
1044
- function isSupported(expr) {
1045
- return checkSupport(expr, "rendered");
1079
+ function isSupported(expr, opts) {
1080
+ return checkSupport(expr, "rendered", opts?.loweringMatchers ?? []);
1046
1081
  }
1047
- function isSupportedValue(expr) {
1048
- return checkSupport(expr, "value");
1082
+ function isSupportedValue(expr, opts) {
1083
+ return checkSupport(expr, "value", opts?.loweringMatchers ?? []);
1049
1084
  }
1050
- function checkSupport(expr, pos) {
1085
+ function checkSupport(expr, pos, matchers) {
1051
1086
  switch (expr.kind) {
1052
1087
  case "unsupported":
1053
1088
  return { supported: false, reason: expr.reason };
@@ -1056,7 +1091,7 @@ function checkSupport(expr, pos) {
1056
1091
  return { supported: false, reason: "Unsupported syntax: ObjectLiteralExpression" };
1057
1092
  }
1058
1093
  for (const prop of expr.properties) {
1059
- const propSupport = checkSupport(prop.kind === "spread" ? prop.expr : prop.value, pos);
1094
+ const propSupport = checkSupport(prop.kind === "spread" ? prop.expr : prop.value, pos, matchers);
1060
1095
  if (!propSupport.supported)
1061
1096
  return propSupport;
1062
1097
  }
@@ -1071,7 +1106,7 @@ function checkSupport(expr, pos) {
1071
1106
  return { supported: false, reason: "Standalone arrow functions / regex literals are not supported" };
1072
1107
  case "array-literal": {
1073
1108
  for (const el of expr.elements) {
1074
- const elSupport = checkSupport(el, pos);
1109
+ const elSupport = checkSupport(el, pos, matchers);
1075
1110
  if (!elSupport.supported)
1076
1111
  return elSupport;
1077
1112
  }
@@ -1084,28 +1119,39 @@ function checkSupport(expr, pos) {
1084
1119
  reason: `String.prototype.${expr.method} supports only a string pattern + string replacement (the regex form is deferred); use a string pattern or wrap the expression in /* @client */`
1085
1120
  };
1086
1121
  }
1087
- const objSupport = checkSupport(expr.object, pos);
1122
+ const objSupport = checkSupport(expr.object, pos, matchers);
1088
1123
  if (!objSupport.supported)
1089
1124
  return objSupport;
1090
1125
  for (const arg of expr.args) {
1091
- const argSupport = checkSupport(arg, pos);
1126
+ const argSupport = checkSupport(arg, pos, matchers);
1092
1127
  if (!argSupport.supported)
1093
1128
  return argSupport;
1094
1129
  }
1095
1130
  if (expr.method === "flat" && expr.depthExpr) {
1096
- const depthSupport = checkSupport(expr.depthExpr, pos);
1131
+ const depthSupport = checkSupport(expr.depthExpr, pos, matchers);
1097
1132
  if (!depthSupport.supported)
1098
1133
  return depthSupport;
1099
1134
  }
1100
1135
  return { supported: true, level: "L2" };
1101
1136
  }
1102
1137
  case "call": {
1138
+ for (const matcher of matchers) {
1139
+ const node = matcher(expr.callee, expr.args);
1140
+ if (!node)
1141
+ continue;
1142
+ for (const child of loweringNodeChildren(node)) {
1143
+ const childSupport = checkSupport(child, pos, matchers);
1144
+ if (!childSupport.supported)
1145
+ return childSupport;
1146
+ }
1147
+ return { supported: true, level: "L2" };
1148
+ }
1103
1149
  const cb = asCallbackMethodCall(expr);
1104
1150
  if (cb) {
1105
- const objSupport = checkSupport(cb.object, pos);
1151
+ const objSupport = checkSupport(cb.object, pos, matchers);
1106
1152
  if (!objSupport.supported)
1107
1153
  return objSupport;
1108
- const bodySupport = checkSupport(cb.arrow.body, pos);
1154
+ const bodySupport = checkSupport(cb.arrow.body, pos, matchers);
1109
1155
  if (!bodySupport.supported) {
1110
1156
  return {
1111
1157
  supported: false,
@@ -1114,13 +1160,13 @@ function checkSupport(expr, pos) {
1114
1160
  };
1115
1161
  }
1116
1162
  for (const rest of cb.args) {
1117
- const restSupport = checkSupport(rest, pos);
1163
+ const restSupport = checkSupport(rest, pos, matchers);
1118
1164
  if (!restSupport.supported)
1119
1165
  return restSupport;
1120
1166
  }
1121
1167
  return { supported: true, level: "L5" };
1122
1168
  }
1123
- const calleeSupport = checkSupport(expr.callee, pos);
1169
+ const calleeSupport = checkSupport(expr.callee, pos, matchers);
1124
1170
  if (!calleeSupport.supported) {
1125
1171
  return calleeSupport;
1126
1172
  }
@@ -1139,7 +1185,7 @@ function checkSupport(expr, pos) {
1139
1185
  return { supported: true, level: "L1" };
1140
1186
  }
1141
1187
  for (const arg of expr.args) {
1142
- const argSupport = checkSupport(arg, pos);
1188
+ const argSupport = checkSupport(arg, pos, matchers);
1143
1189
  if (!argSupport.supported) {
1144
1190
  return argSupport;
1145
1191
  }
@@ -1147,7 +1193,7 @@ function checkSupport(expr, pos) {
1147
1193
  return { supported: true, level: "L2" };
1148
1194
  }
1149
1195
  case "member": {
1150
- const objSupport = checkSupport(expr.object, pos);
1196
+ const objSupport = checkSupport(expr.object, pos, matchers);
1151
1197
  if (!objSupport.supported) {
1152
1198
  return objSupport;
1153
1199
  }
@@ -1157,19 +1203,19 @@ function checkSupport(expr, pos) {
1157
1203
  return { supported: true, level: "L2" };
1158
1204
  }
1159
1205
  case "index-access": {
1160
- const objSupport = checkSupport(expr.object, pos);
1206
+ const objSupport = checkSupport(expr.object, pos, matchers);
1161
1207
  if (!objSupport.supported)
1162
1208
  return objSupport;
1163
- const indexSupport = checkSupport(expr.index, pos);
1209
+ const indexSupport = checkSupport(expr.index, pos, matchers);
1164
1210
  if (!indexSupport.supported)
1165
1211
  return indexSupport;
1166
1212
  return { supported: true, level: "L2" };
1167
1213
  }
1168
1214
  case "binary": {
1169
- const leftSupport = checkSupport(expr.left, pos);
1215
+ const leftSupport = checkSupport(expr.left, pos, matchers);
1170
1216
  if (!leftSupport.supported)
1171
1217
  return leftSupport;
1172
- const rightSupport = checkSupport(expr.right, pos);
1218
+ const rightSupport = checkSupport(expr.right, pos, matchers);
1173
1219
  if (!rightSupport.supported)
1174
1220
  return rightSupport;
1175
1221
  if (["===", "==", "!==", "!=", ">", "<", ">=", "<="].includes(expr.op)) {
@@ -1181,7 +1227,7 @@ function checkSupport(expr, pos) {
1181
1227
  return { supported: false, reason: `Unknown operator: ${expr.op}` };
1182
1228
  }
1183
1229
  case "unary": {
1184
- const argSupport = checkSupport(expr.argument, pos);
1230
+ const argSupport = checkSupport(expr.argument, pos, matchers);
1185
1231
  if (!argSupport.supported)
1186
1232
  return argSupport;
1187
1233
  if (expr.op === "!") {
@@ -1193,25 +1239,25 @@ function checkSupport(expr, pos) {
1193
1239
  return { supported: false, reason: `Unsupported unary operator: ${expr.op}` };
1194
1240
  }
1195
1241
  case "logical": {
1196
- const leftSupport = checkSupport(expr.left, pos);
1242
+ const leftSupport = checkSupport(expr.left, pos, matchers);
1197
1243
  if (!leftSupport.supported)
1198
1244
  return leftSupport;
1199
1245
  if (expr.op === "??" && expr.right.kind === "object-literal" && expr.right.properties.length === 0) {
1200
1246
  return { supported: true, level: "L4" };
1201
1247
  }
1202
- const rightSupport = checkSupport(expr.right, pos);
1248
+ const rightSupport = checkSupport(expr.right, pos, matchers);
1203
1249
  if (!rightSupport.supported)
1204
1250
  return rightSupport;
1205
1251
  return { supported: true, level: "L4" };
1206
1252
  }
1207
1253
  case "conditional": {
1208
- const testSupport = checkSupport(expr.test, pos);
1254
+ const testSupport = checkSupport(expr.test, pos, matchers);
1209
1255
  if (!testSupport.supported)
1210
1256
  return testSupport;
1211
- const consSupport = checkSupport(expr.consequent, pos);
1257
+ const consSupport = checkSupport(expr.consequent, pos, matchers);
1212
1258
  if (!consSupport.supported)
1213
1259
  return consSupport;
1214
- const altSupport = checkSupport(expr.alternate, pos);
1260
+ const altSupport = checkSupport(expr.alternate, pos, matchers);
1215
1261
  if (!altSupport.supported)
1216
1262
  return altSupport;
1217
1263
  return { supported: true, level: "L4" };
@@ -1219,7 +1265,7 @@ function checkSupport(expr, pos) {
1219
1265
  case "template-literal": {
1220
1266
  for (const part of expr.parts) {
1221
1267
  if (part.type === "expression") {
1222
- const partSupport = checkSupport(part.expr, pos);
1268
+ const partSupport = checkSupport(part.expr, pos, matchers);
1223
1269
  if (!partSupport.supported)
1224
1270
  return partSupport;
1225
1271
  }
@@ -1941,7 +1987,7 @@ function identifierPath(callee) {
1941
1987
  }
1942
1988
 
1943
1989
  // ../jsx/src/prop-rewrite.ts
1944
- import ts5 from "typescript";
1990
+ import ts7 from "typescript";
1945
1991
 
1946
1992
  // ../jsx/src/ir-to-client-js/utils.ts
1947
1993
  import ts3 from "typescript";
@@ -2091,19 +2137,61 @@ function resolveJsxChildrenProp(props) {
2091
2137
  return [];
2092
2138
  return prop.value.children ?? [];
2093
2139
  }
2140
+ // ../jsx/src/ir-to-client-js/component-scope.ts
2141
+ function buildImportAliasMap(imports) {
2142
+ const aliases = new Map;
2143
+ for (const imp of imports) {
2144
+ if (imp.isTypeOnly)
2145
+ continue;
2146
+ for (const spec of imp.specifiers) {
2147
+ if (spec.isTypeOnly || spec.isDefault || spec.isNamespace || spec.alias === null)
2148
+ continue;
2149
+ aliases.set(spec.alias, spec.name);
2150
+ }
2151
+ }
2152
+ return aliases;
2153
+ }
2154
+
2094
2155
  // ../jsx/src/ir-to-client-js/csr-substitute.ts
2156
+ import ts5 from "typescript";
2157
+
2158
+ // ../jsx/src/props-binding.ts
2095
2159
  import ts4 from "typescript";
2160
+ function isIdentifierName(key) {
2161
+ if (key.length === 0)
2162
+ return false;
2163
+ for (let i = 0;i < key.length; ) {
2164
+ const cp = key.codePointAt(i);
2165
+ const ok = i === 0 ? ts4.isIdentifierStart(cp, ts4.ScriptTarget.Latest) : ts4.isIdentifierPart(cp, ts4.ScriptTarget.Latest);
2166
+ if (!ok)
2167
+ return false;
2168
+ i += cp > 65535 ? 2 : 1;
2169
+ }
2170
+ return true;
2171
+ }
2172
+ function propsDestructureBinding(p) {
2173
+ const callerKey = p.sourceName ?? p.name;
2174
+ const localName = p.name;
2175
+ const binding = callerKey === localName ? localName : `${isIdentifierName(callerKey) ? callerKey : JSON.stringify(callerKey)}: ${localName}`;
2176
+ return p.defaultValue ? `${binding} = ${p.defaultValue}` : binding;
2177
+ }
2178
+ var EMPTY_SET = new Set;
2179
+
2180
+ // ../jsx/src/ir-to-client-js/csr-substitute.ts
2096
2181
  function extractFreeIdentifiersFromText(text) {
2097
2182
  if (!text || text.trim().length === 0)
2098
2183
  return new Set;
2099
- const sf = ts4.createSourceFile("__free_ids__.ts", `(${text});`, ts4.ScriptTarget.Latest, true, ts4.ScriptKind.TS);
2184
+ const sf = ts5.createSourceFile("__free_ids__.ts", `(${text});`, ts5.ScriptTarget.Latest, true, ts5.ScriptKind.TS);
2100
2185
  const stmt = sf.statements[0];
2101
- if (!stmt || !ts4.isExpressionStatement(stmt))
2186
+ if (!stmt || !ts5.isExpressionStatement(stmt))
2102
2187
  return new Set;
2103
- const expr = ts4.isParenthesizedExpression(stmt.expression) ? stmt.expression.expression : stmt.expression;
2188
+ const expr = ts5.isParenthesizedExpression(stmt.expression) ? stmt.expression.expression : stmt.expression;
2104
2189
  return extractFreeIdentifiersFromNode(expr);
2105
2190
  }
2106
2191
 
2192
+ // ../jsx/src/ir-to-client-js/rewrite-props-object.ts
2193
+ import ts6 from "typescript";
2194
+
2107
2195
  // ../jsx/src/adapters/child-scope.ts
2108
2196
  function derivesScopeFromSlot(comp) {
2109
2197
  return comp.slotId != null && comp.loopItemRoot !== true;
@@ -2230,27 +2318,6 @@ var SKELETON_PATH_FORCE_CLOSE_GROUPS = [
2230
2318
  new Set(["li"])
2231
2319
  ];
2232
2320
 
2233
- // ../jsx/src/props-binding.ts
2234
- import ts6 from "typescript";
2235
- function isIdentifierName(key) {
2236
- if (key.length === 0)
2237
- return false;
2238
- for (let i = 0;i < key.length; ) {
2239
- const cp = key.codePointAt(i);
2240
- const ok = i === 0 ? ts6.isIdentifierStart(cp, ts6.ScriptTarget.Latest) : ts6.isIdentifierPart(cp, ts6.ScriptTarget.Latest);
2241
- if (!ok)
2242
- return false;
2243
- i += cp > 65535 ? 2 : 1;
2244
- }
2245
- return true;
2246
- }
2247
- function propsDestructureBinding(p) {
2248
- const callerKey = p.sourceName ?? p.name;
2249
- const localName = p.name;
2250
- const binding = callerKey === localName ? localName : `${isIdentifierName(callerKey) ? callerKey : JSON.stringify(callerKey)}: ${localName}`;
2251
- return p.defaultValue ? `${binding} = ${p.defaultValue}` : binding;
2252
- }
2253
-
2254
2321
  // ../jsx/src/instrumentation.ts
2255
2322
  var _counters = freshCounters();
2256
2323
  function freshCounters() {
@@ -2264,20 +2331,21 @@ function freshCounters() {
2264
2331
  }
2265
2332
 
2266
2333
  // ../jsx/src/analyzer-context.ts
2267
- import ts8 from "typescript";
2334
+ import ts9 from "typescript";
2268
2335
 
2269
2336
  // ../jsx/src/strip-types.ts
2270
- import ts7 from "typescript";
2337
+ import ts8 from "typescript";
2271
2338
 
2272
2339
  // ../jsx/src/analyzer-context.ts
2273
- var _typePrinter = ts8.createPrinter({ removeComments: true, omitTrailingSemicolon: true });
2274
- var _blankTypeSourceFile = ts8.createSourceFile("__bf_types__.ts", "", ts8.ScriptTarget.Latest);
2340
+ var _typePrinter = ts9.createPrinter({ removeComments: true, omitTrailingSemicolon: true });
2341
+ var _blankTypeSourceFile = ts9.createSourceFile("__bf_types__.ts", "", ts9.ScriptTarget.Latest);
2275
2342
 
2276
2343
  // ../jsx/src/errors.ts
2277
2344
  var ErrorCodes = {
2278
2345
  MISSING_USE_CLIENT: "BF001",
2279
2346
  CLIENT_IMPORTING_SERVER: "BF003",
2280
2347
  SIGNAL_OUTSIDE_COMPONENT: "BF011",
2348
+ PRIMITIVE_VIA_NAMESPACE_IMPORT: "BF013",
2281
2349
  UNSUPPORTED_JSX_PATTERN: "BF021",
2282
2350
  MISSING_KEY_IN_LIST: "BF023",
2283
2351
  MISSING_KEY_IN_NESTED_LIST: "BF024",
@@ -2310,6 +2378,7 @@ var errorMessages = {
2310
2378
  [ErrorCodes.MISSING_USE_CLIENT]: "'use client' directive required for components with createSignal or event handlers",
2311
2379
  [ErrorCodes.CLIENT_IMPORTING_SERVER]: "Client component cannot import server component",
2312
2380
  [ErrorCodes.SIGNAL_OUTSIDE_COMPONENT]: "Module-level reactive declaration (createSignal / createMemo) is not allowed. " + "The downstream codegen drops the declaration silently and every reference becomes a ReferenceError at SSR and at hydrate. " + "Move the declaration inside a component function so each mount gets its own state.",
2381
+ [ErrorCodes.PRIMITIVE_VIA_NAMESPACE_IMPORT]: "Reactive primitive called through a namespace import of '@barefootjs/client' (import * as ns) is not recognized; " + "the declaration is dropped and its references throw ReferenceError at hydrate. Import the primitive by name instead.",
2313
2382
  [ErrorCodes.UNSUPPORTED_JSX_PATTERN]: "Unsupported JSX pattern",
2314
2383
  [ErrorCodes.MISSING_KEY_IN_LIST]: "Missing key attribute in list rendering. Add a key prop for efficient updates",
2315
2384
  [ErrorCodes.MISSING_KEY_IN_NESTED_LIST]: "Nested .map() loop requires key attribute for event delegation. Add a key prop to elements in the inner loop",
@@ -2501,46 +2570,46 @@ function extractFreeIdentifiersFromNode(node) {
2501
2570
  const ids = new Set;
2502
2571
  const boundNames = new Set;
2503
2572
  function addBindingNames(name, out) {
2504
- if (ts9.isIdentifier(name))
2573
+ if (ts10.isIdentifier(name))
2505
2574
  out.push(name.text);
2506
- else if (ts9.isObjectBindingPattern(name))
2575
+ else if (ts10.isObjectBindingPattern(name))
2507
2576
  name.elements.forEach((e) => addBindingNames(e.name, out));
2508
- else if (ts9.isArrayBindingPattern(name))
2577
+ else if (ts10.isArrayBindingPattern(name))
2509
2578
  name.elements.forEach((e) => {
2510
- if (!ts9.isOmittedExpression(e))
2579
+ if (!ts10.isOmittedExpression(e))
2511
2580
  addBindingNames(e.name, out);
2512
2581
  });
2513
2582
  }
2514
2583
  function visit(n) {
2515
- if (ts9.isTypeNode(n))
2584
+ if (ts10.isTypeNode(n))
2516
2585
  return;
2517
- if (ts9.isIdentifier(n)) {
2586
+ if (ts10.isIdentifier(n)) {
2518
2587
  const parent = n.parent;
2519
- if (parent && ts9.isPropertyAccessExpression(parent) && parent.name === n)
2588
+ if (parent && ts10.isPropertyAccessExpression(parent) && parent.name === n)
2520
2589
  return;
2521
- if (parent && ts9.isPropertyAssignment(parent) && parent.name === n)
2590
+ if (parent && ts10.isPropertyAssignment(parent) && parent.name === n)
2522
2591
  return;
2523
- if (parent && ts9.isParameter(parent) && parent.name === n)
2592
+ if (parent && ts10.isParameter(parent) && parent.name === n)
2524
2593
  return;
2525
- if (parent && ts9.isVariableDeclaration(parent) && parent.name === n)
2594
+ if (parent && ts10.isVariableDeclaration(parent) && parent.name === n)
2526
2595
  return;
2527
2596
  if (boundNames.has(n.text))
2528
2597
  return;
2529
2598
  ids.add(n.text);
2530
2599
  return;
2531
2600
  }
2532
- if (ts9.isArrowFunction(n)) {
2601
+ if (ts10.isArrowFunction(n)) {
2533
2602
  const params = [];
2534
2603
  for (const p of n.parameters)
2535
2604
  addBindingNames(p.name, params);
2536
2605
  for (const name of params)
2537
2606
  boundNames.add(name);
2538
- ts9.forEachChild(n, visit);
2607
+ ts10.forEachChild(n, visit);
2539
2608
  for (const name of params)
2540
2609
  boundNames.delete(name);
2541
2610
  return;
2542
2611
  }
2543
- ts9.forEachChild(n, visit);
2612
+ ts10.forEachChild(n, visit);
2544
2613
  }
2545
2614
  visit(node);
2546
2615
  return ids;
@@ -2563,7 +2632,7 @@ var REACTIVE_PRIMITIVES = new Set([
2563
2632
  ]);
2564
2633
 
2565
2634
  // ../jsx/src/jsx-to-ir.ts
2566
- import ts13 from "typescript";
2635
+ import ts14 from "typescript";
2567
2636
 
2568
2637
  // ../jsx/src/types.ts
2569
2638
  var SCOPE_FORBIDDEN = {
@@ -2613,7 +2682,7 @@ function preambleAnalysisTemplateText(p) {
2613
2682
  }
2614
2683
 
2615
2684
  // ../jsx/src/module-exports.ts
2616
- import ts10 from "typescript";
2685
+ import ts11 from "typescript";
2617
2686
  function formatParamWithType(p) {
2618
2687
  const rest = p.isRest ? "..." : "";
2619
2688
  const optional = p.optional ? "?" : "";
@@ -2648,21 +2717,21 @@ function findAssignedNames(bodyText, candidates) {
2648
2717
  const assigned = new Set;
2649
2718
  if (candidates.size === 0)
2650
2719
  return assigned;
2651
- const sf = ts10.createSourceFile("bf-assignment-scan.tsx", bodyText, ts10.ScriptTarget.Latest, false, ts10.ScriptKind.TSX);
2720
+ const sf = ts11.createSourceFile("bf-assignment-scan.tsx", bodyText, ts11.ScriptTarget.Latest, false, ts11.ScriptKind.TSX);
2652
2721
  const record = (target) => {
2653
- if (ts10.isIdentifier(target) && candidates.has(target.text)) {
2722
+ if (ts11.isIdentifier(target) && candidates.has(target.text)) {
2654
2723
  assigned.add(target.text);
2655
2724
  }
2656
2725
  };
2657
2726
  const visit = (node) => {
2658
- if (ts10.isBinaryExpression(node) && isAssignmentOperator(node.operatorToken.kind)) {
2727
+ if (ts11.isBinaryExpression(node) && isAssignmentOperator(node.operatorToken.kind)) {
2659
2728
  record(node.left);
2660
- } else if ((ts10.isPrefixUnaryExpression(node) || ts10.isPostfixUnaryExpression(node)) && (node.operator === ts10.SyntaxKind.PlusPlusToken || node.operator === ts10.SyntaxKind.MinusMinusToken)) {
2729
+ } else if ((ts11.isPrefixUnaryExpression(node) || ts11.isPostfixUnaryExpression(node)) && (node.operator === ts11.SyntaxKind.PlusPlusToken || node.operator === ts11.SyntaxKind.MinusMinusToken)) {
2661
2730
  record(node.operand);
2662
2731
  }
2663
- ts10.forEachChild(node, visit);
2732
+ ts11.forEachChild(node, visit);
2664
2733
  };
2665
- ts10.forEachChild(sf, visit);
2734
+ ts11.forEachChild(sf, visit);
2666
2735
  return assigned;
2667
2736
  }
2668
2737
  function closeOverWritersOfMutableBindings(primaryRefs, declarations, mutableNames) {
@@ -2685,14 +2754,14 @@ function closeOverWritersOfMutableBindings(primaryRefs, declarations, mutableNam
2685
2754
  return reachable;
2686
2755
  }
2687
2756
  function isAssignmentOperator(kind) {
2688
- return kind >= ts10.SyntaxKind.FirstAssignment && kind <= ts10.SyntaxKind.LastAssignment;
2757
+ return kind >= ts11.SyntaxKind.FirstAssignment && kind <= ts11.SyntaxKind.LastAssignment;
2689
2758
  }
2690
2759
 
2691
2760
  // ../jsx/src/reactivity-checker.ts
2692
- import ts11 from "typescript";
2761
+ import ts12 from "typescript";
2693
2762
 
2694
2763
  // ../jsx/src/free-refs.ts
2695
- import ts12 from "typescript";
2764
+ import ts13 from "typescript";
2696
2765
  var _bindingMapCache = new WeakMap;
2697
2766
 
2698
2767
  // ../jsx/src/to-locale-date-lowering.ts
@@ -3140,40 +3209,16 @@ var KEYWORDS_AND_GLOBALS = new Set([
3140
3209
  ]);
3141
3210
 
3142
3211
  // ../jsx/src/ir-to-client-js/walk-prop-accesses.ts
3143
- import ts14 from "typescript";
3144
-
3145
- // ../jsx/src/ir-to-client-js/imports.ts
3146
- import ts16 from "typescript";
3147
-
3148
- // ../jsx/src/value-references.ts
3149
3212
  import ts15 from "typescript";
3150
3213
 
3151
- // ../jsx/src/relocate.ts
3214
+ // ../jsx/src/ir-to-client-js/imports.ts
3152
3215
  import ts17 from "typescript";
3153
3216
 
3154
- // ../jsx/src/lowering-registry.ts
3155
- var plugins = [];
3156
- function registerLoweringPlugin(plugin) {
3157
- const existing = plugins.findIndex((p) => p.name === plugin.name);
3158
- if (existing >= 0)
3159
- plugins[existing] = plugin;
3160
- else
3161
- plugins.push(plugin);
3162
- }
3163
- function prepareLoweringMatchers(metadata) {
3164
- const matchers = [];
3165
- for (const plugin of plugins) {
3166
- const matcher = plugin.prepare(metadata);
3167
- if (matcher)
3168
- matchers.push(matcher);
3169
- }
3170
- return matchers;
3171
- }
3172
- function isValidHelperId(helper) {
3173
- return /^[A-Za-z_][A-Za-z0-9_]*$/.test(helper);
3174
- }
3217
+ // ../jsx/src/value-references.ts
3218
+ import ts16 from "typescript";
3175
3219
 
3176
3220
  // ../jsx/src/relocate.ts
3221
+ import ts18 from "typescript";
3177
3222
  var REGISTRY_SAFE_BINDING_KINDS = new Set([
3178
3223
  "global",
3179
3224
  "module-import",
@@ -3366,10 +3411,10 @@ function matchSearchParamsMethodCall(callee, args, localNames) {
3366
3411
  }
3367
3412
 
3368
3413
  // ../jsx/src/ir-to-client-js/prune-unused-prop-extractions.ts
3369
- import ts18 from "typescript";
3414
+ import ts19 from "typescript";
3370
3415
 
3371
3416
  // ../jsx/src/ir-to-client-js/control-flow/plan/lazy-preamble.ts
3372
- import ts19 from "typescript";
3417
+ import ts20 from "typescript";
3373
3418
  var NO_PREAMBLE = {
3374
3419
  lazySafe: true,
3375
3420
  facts: { declaredNames: new Set, freeNames: new Set }
@@ -3419,7 +3464,7 @@ var INERT_BINDING_GLOBALS = new Set([
3419
3464
  ]);
3420
3465
 
3421
3466
  // ../jsx/src/ir-to-client-js/emit-reactive.ts
3422
- import ts20 from "typescript";
3467
+ import ts21 from "typescript";
3423
3468
 
3424
3469
  // ../jsx/src/ir-to-client-js/control-flow/stringify/event-delegation.ts
3425
3470
  var NON_BUBBLING_EVENTS = new Set([
@@ -3433,9 +3478,6 @@ var NON_BUBBLING_EVENTS = new Set([
3433
3478
  "pointerleave"
3434
3479
  ]);
3435
3480
 
3436
- // ../jsx/src/ir-to-client-js/rewrite-props-object.ts
3437
- import ts21 from "typescript";
3438
-
3439
3481
  // ../jsx/src/ir-to-client-js/source-map.ts
3440
3482
  var BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
3441
3483
  function encodeVLQ(value) {
@@ -4640,6 +4682,17 @@ function emitParsedExpr(expr, emitter) {
4640
4682
  case "literal":
4641
4683
  return emitter.literal(expr.value, expr.literalType);
4642
4684
  case "call": {
4685
+ if (emitter.lowering) {
4686
+ for (const matcher of emitter.lowering.matchers) {
4687
+ const node = matcher(expr.callee, expr.args);
4688
+ if (!node)
4689
+ continue;
4690
+ const rendered = emitter.lowering.render(node, emit);
4691
+ if (rendered !== null)
4692
+ return rendered;
4693
+ break;
4694
+ }
4695
+ }
4643
4696
  const cb = asCallbackMethodCall(expr);
4644
4697
  if (cb)
4645
4698
  return emitter.callbackMethod(cb.method, cb.object, cb.arrow, cb.args, emit);
@@ -5697,6 +5750,21 @@ class ErbTopLevelEmitter {
5697
5750
  constructor(ctx) {
5698
5751
  this.ctx = ctx;
5699
5752
  }
5753
+ get lowering() {
5754
+ return {
5755
+ matchers: this.ctx._loweringMatchers,
5756
+ render: (node, emit) => {
5757
+ if (node.kind === "guard-list" && node.helper === "query") {
5758
+ const qArgs = queryHrefArgs(node, emit);
5759
+ return `bf.query(${qArgs.join(", ")})`;
5760
+ }
5761
+ if (node.kind === "helper-call" && isValidHelperId(node.helper)) {
5762
+ return `bf.${node.helper}(${node.args.map(emit).join(", ")})`;
5763
+ }
5764
+ return null;
5765
+ }
5766
+ };
5767
+ }
5700
5768
  identifier(name) {
5701
5769
  if (name === "undefined" || name === "null")
5702
5770
  return "nil";
@@ -6176,6 +6244,7 @@ class ErbAdapter extends BaseAdapter {
6176
6244
  localConstants = [];
6177
6245
  scope = BindingScope.EMPTY;
6178
6246
  nullableOptionalProps = new Set;
6247
+ importAliases = new Map;
6179
6248
  constructor(options = {}) {
6180
6249
  super();
6181
6250
  this.options = {
@@ -6196,6 +6265,7 @@ class ErbAdapter extends BaseAdapter {
6196
6265
  this._searchParamsLocals = searchParamsLocalNames(ir.metadata);
6197
6266
  this._loweringMatchers = prepareLoweringMatchers(ir.metadata);
6198
6267
  this.localConstants = ir.metadata.localConstants ?? [];
6268
+ this.importAliases = buildImportAliasMap(ir.metadata.imports ?? []);
6199
6269
  this.scope = BindingScope.EMPTY;
6200
6270
  this.errors = [];
6201
6271
  this.childrenCaptureCounter = 0;
@@ -6249,7 +6319,9 @@ class ErbAdapter extends BaseAdapter {
6249
6319
  return null;
6250
6320
  return {
6251
6321
  condition: exprToString(parsed.test),
6252
- consequent: exprToString(parsed.consequent)
6322
+ consequent: exprToString(parsed.consequent),
6323
+ testParsed: parsed.test,
6324
+ consequentParsed: parsed.consequent
6253
6325
  };
6254
6326
  }
6255
6327
  resolveLiteralConst(name) {
@@ -6723,7 +6795,8 @@ ${renderedChildren}` : renderedChildren;
6723
6795
  }
6724
6796
  childrenCaptureCounter = 0;
6725
6797
  toTemplateName(componentName) {
6726
- return componentName.replace(/([A-Z])/g, "_$1").toLowerCase().replace(/^_/, "");
6798
+ const declaredName = this.importAliases.get(componentName) ?? componentName;
6799
+ return declaredName.replace(/([A-Z])/g, "_$1").toLowerCase().replace(/^_/, "");
6727
6800
  }
6728
6801
  renderIfStatement(ifStmt) {
6729
6802
  const condition = this.convertExpressionToRuby(ifStmt.condition);
@@ -6793,8 +6866,8 @@ ${children}`;
6793
6866
  {
6794
6867
  const m = this.parseUndefinedAlternateTernary(value.expr);
6795
6868
  if (m) {
6796
- const cond = this.convertExpressionToRuby(m.condition);
6797
- const val = this.convertExpressionToRuby(m.consequent);
6869
+ const cond = this.convertExpressionToRuby("", m.testParsed);
6870
+ const val = this.convertExpressionToRuby("", m.consequentParsed);
6798
6871
  return `<% if bf.truthy?(${cond}) %>${name}="<%= bf.h(${val}) %>"<% end %>`;
6799
6872
  }
6800
6873
  }
@@ -6924,7 +6997,7 @@ ${children}`;
6924
6997
  if (!startsAsObjectLiteral && !hasTaggedTemplate)
6925
6998
  return false;
6926
6999
  const parsed = parseExpression(expr.trim());
6927
- const support = isSupported(parsed);
7000
+ const support = isSupported(parsed, { loweringMatchers: this._loweringMatchers });
6928
7001
  if (parsed.kind !== "unsupported" && support.supported)
6929
7002
  return false;
6930
7003
  const reason = support.reason ?? (parsed.kind === "unsupported" ? parsed.reason : undefined);
@@ -6944,6 +7017,7 @@ ${reason}` : "";
6944
7017
  get emitCtx() {
6945
7018
  return {
6946
7019
  _searchParamsLocals: this._searchParamsLocals,
7020
+ _loweringMatchers: this._loweringMatchers,
6947
7021
  resolveModuleStringConst: (name) => this.resolveModuleStringConst(name),
6948
7022
  resolveLiteralConst: (name) => this.resolveLiteralConst(name),
6949
7023
  resolveStaticRecordLiteral: (o, k) => this.resolveStaticRecordLiteral(o, k),
@@ -6975,20 +7049,8 @@ ${reason}` : "";
6975
7049
  return "''";
6976
7050
  parsed = parseExpression(trimmed);
6977
7051
  }
6978
- if (parsed.kind === "call") {
6979
- for (const matcher of this._loweringMatchers) {
6980
- const node = matcher(parsed.callee, parsed.args);
6981
- if (node?.kind === "guard-list" && node.helper === "query") {
6982
- const argsRuby = queryHrefArgs(node, (n) => this.renderParsedExprToRuby(n));
6983
- return `bf.query(${argsRuby.join(", ")})`;
6984
- }
6985
- if (node?.kind === "helper-call" && isValidHelperId(node.helper)) {
6986
- const argsX = node.args.map((a) => this.renderParsedExprToRuby(a));
6987
- return `bf.${node.helper}(${argsX.join(", ")})`;
6988
- }
6989
- }
6990
- }
6991
- const support = pos === "value" ? isSupportedValue(parsed) : isSupported(parsed);
7052
+ const supportOpts = { loweringMatchers: this._loweringMatchers };
7053
+ const support = pos === "value" ? isSupportedValue(parsed, supportOpts) : isSupported(parsed, supportOpts);
6992
7054
  if (!support.supported) {
6993
7055
  this.errors.push({
6994
7056
  code: "BF101",