@barefootjs/blade 0.18.3 → 0.18.5

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.
@@ -262,6 +262,14 @@ export declare class BladeAdapter extends BaseAdapter implements IRNodeEmitter<B
262
262
  private options;
263
263
  private errors;
264
264
  private inLoop;
265
+ /**
266
+ * `IRLoop.depth` of the loop currently being rendered (save/restore
267
+ * around `renderChildren(loop.children)`, mirroring `inLoop` above).
268
+ * `renderAttributes` reads this to derive the `key` → `data-key`/
269
+ * `data-key-N` suffix — the depth is IR-computed (jsx-to-ir.ts), not
270
+ * re-derived here (#2168 nested-loop-outer-binding).
271
+ */
272
+ private currentLoopKeyDepth;
265
273
  /**
266
274
  * SolidJS-style props identifier (`function(props: P)`) and the
267
275
  * analyzer-extracted prop names. Stashed at `generate()` entry so the
@@ -1 +1 @@
1
- {"version":3,"file":"blade-adapter.d.ts","sourceRoot":"","sources":["../../src/adapter/blade-adapter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"blade-adapter.d.ts","sourceRoot":"","sources":["../../src/adapter/blade-adapter.ts"],"names":[],"mappings":"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"}
@@ -36,6 +36,8 @@ export interface BladeEmitContext {
36
36
  * (`variantClasses.ghost`) to its Blade value at compile time, or null.
37
37
  */
38
38
  _resolveStaticRecordLiteral(objectName: string, key: string): string | null;
39
+ /** Whether a getter/prop name resolves to a string-typed SSR value. */
40
+ _isStringValueName(name: string): boolean;
39
41
  /** Record a BF101 unsupported-expression diagnostic. */
40
42
  _recordExprBF101(message: string, reason?: string): void;
41
43
  /** Lower a filter/predicate body to its Blade form, bound to `param`. */
@@ -1 +1 @@
1
- {"version":3,"file":"emit-context.d.ts","sourceRoot":"","sources":["../../src/adapter/emit-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAE5E,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,QAAQ,CAAC,mBAAmB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IAEzC;;;OAGG;IACH,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;IAEtD,oFAAoF;IACpF,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;IAEjD;;;OAGG;IACH,2BAA2B,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;IAE3E,wDAAwD;IACxD,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAExD,yEAAyE;IACzE,4BAA4B,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAAA;CACtE;AAED;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IACjC,uDAAuD;IACvD,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;IAE9B,kEAAkE;IAClE,QAAQ,CAAC,MAAM,EAAE,aAAa,EAAE,CAAA;IAEhC,0EAA0E;IAC1E,QAAQ,CAAC,cAAc,EAAE,UAAU,CAAC,gBAAgB,CAAC,CAAA;IAErD,sEAAsE;IACtE,QAAQ,CAAC,WAAW,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IAExC;;;;;;;;OAQG;IACH,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,UAAU,GAAG,MAAM,CAAA;IAEtE;;;;;;OAMG;IACH,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,UAAU,GAAG,MAAM,CAAA;CACtE;AAED;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,UAAU,GAAG,MAAM,CAAA;IAEtE;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,MAAM,EAAE,aAAa,EAAE,CAAA;CACjC"}
1
+ {"version":3,"file":"emit-context.d.ts","sourceRoot":"","sources":["../../src/adapter/emit-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAE5E,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,QAAQ,CAAC,mBAAmB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IAEzC;;;OAGG;IACH,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;IAEtD,oFAAoF;IACpF,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;IAEjD;;;OAGG;IACH,2BAA2B,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;IAE3E,uEAAuE;IACvE,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;IAEzC,wDAAwD;IACxD,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAExD,yEAAyE;IACzE,4BAA4B,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAAA;CACtE;AAED;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IACjC,uDAAuD;IACvD,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;IAE9B,kEAAkE;IAClE,QAAQ,CAAC,MAAM,EAAE,aAAa,EAAE,CAAA;IAEhC,0EAA0E;IAC1E,QAAQ,CAAC,cAAc,EAAE,UAAU,CAAC,gBAAgB,CAAC,CAAA;IAErD,sEAAsE;IACtE,QAAQ,CAAC,WAAW,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IAExC;;;;;;;;OAQG;IACH,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,UAAU,GAAG,MAAM,CAAA;IAEtE;;;;;;OAMG;IACH,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,UAAU,GAAG,MAAM,CAAA;CACtE;AAED;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,UAAU,GAAG,MAAM,CAAA;IAEtE;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,MAAM,EAAE,aAAa,EAAE,CAAA;CACjC"}
@@ -1 +1 @@
1
- {"version":3,"file":"array-method.d.ts","sourceRoot":"","sources":["../../../src/adapter/expr/array-method.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAMH,OAAO,KAAK,EACV,UAAU,EACV,WAAW,EACX,cAAc,EACd,SAAS,EACV,MAAM,iBAAiB,CAAA;AAGxB,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,UAAU,EAAE,EAClB,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAC9B,MAAM,CA6HR;AAqBD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,MAAM,EAAE,EAChB,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAC9B,MAAM,GAAG,IAAI,CAUf;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,MAAM,EAAE,EAChB,IAAI,EAAE,UAAU,EAChB,SAAS,EAAE,MAAM,GAAG,OAAO,EAC3B,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAC9B,MAAM,GAAG,IAAI,CAkBf;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,UAAU,EACrB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,EAC/B,OAAO,CAAC,EAAE,OAAO,GAChB,MAAM,GAAG,IAAI,CAMf;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAC9B,MAAM,GAAG,IAAI,CAKf;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAC9B,MAAM,GAAG,IAAI,CAKf;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,cAAc,GAAG,MAAM,CASxE;AAGD,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,SAAS,GAAG;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,EACvC,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAC9B,MAAM,CAmBR"}
1
+ {"version":3,"file":"array-method.d.ts","sourceRoot":"","sources":["../../../src/adapter/expr/array-method.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAMH,OAAO,KAAK,EACV,UAAU,EACV,WAAW,EACX,cAAc,EACd,SAAS,EACV,MAAM,iBAAiB,CAAA;AAGxB,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,UAAU,EAAE,EAClB,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAC9B,MAAM,CAgJR;AAqBD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,MAAM,EAAE,EAChB,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAC9B,MAAM,GAAG,IAAI,CAUf;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,MAAM,EAAE,EAChB,IAAI,EAAE,UAAU,EAChB,SAAS,EAAE,MAAM,GAAG,OAAO,EAC3B,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAC9B,MAAM,GAAG,IAAI,CAkBf;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,UAAU,EACrB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,EAC/B,OAAO,CAAC,EAAE,OAAO,GAChB,MAAM,GAAG,IAAI,CAMf;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAC9B,MAAM,GAAG,IAAI,CAKf;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAC9B,MAAM,GAAG,IAAI,CAKf;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,cAAc,GAAG,MAAM,CASxE;AAGD,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,SAAS,GAAG;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,EACvC,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAC9B,MAAM,CAmBR"}
@@ -111,7 +111,7 @@ export declare class BladeFilterEmitter implements ParsedExprEmitter {
111
111
  constructor(param: string, localVarMap: Map<string, string>, isStringName?: (n: string) => boolean, onUnsupported?: ((message: string, reason?: string) => void) | undefined);
112
112
  identifier(name: string): string;
113
113
  literal(value: string | number | boolean | null, literalType: LiteralType): string;
114
- member(object: ParsedExpr, property: string, _computed: boolean, emit: (e: ParsedExpr) => string): string;
114
+ member(object: ParsedExpr, property: string, _computed: boolean, _optional: boolean, emit: (e: ParsedExpr) => string): string;
115
115
  indexAccess(object: ParsedExpr, index: ParsedExpr, emit: (e: ParsedExpr) => string): string;
116
116
  call(callee: ParsedExpr, args: ParsedExpr[], emit: (e: ParsedExpr) => string): string;
117
117
  unary(op: string, argument: ParsedExpr, emit: (e: ParsedExpr) => string): string;
@@ -145,7 +145,7 @@ export declare class BladeTopLevelEmitter implements ParsedExprEmitter {
145
145
  constructor(ctx: BladeEmitContext);
146
146
  identifier(name: string): string;
147
147
  literal(value: string | number | boolean | null, literalType: LiteralType): string;
148
- member(object: ParsedExpr, property: string, _computed: boolean, emit: (e: ParsedExpr) => string): string;
148
+ member(object: ParsedExpr, property: string, _computed: boolean, _optional: boolean, emit: (e: ParsedExpr) => string): string;
149
149
  indexAccess(object: ParsedExpr, index: ParsedExpr, emit: (e: ParsedExpr) => string): string;
150
150
  call(callee: ParsedExpr, args: ParsedExpr[], emit: (e: ParsedExpr) => string): string;
151
151
  unary(op: string, argument: ParsedExpr, emit: (e: ParsedExpr) => string): string;
@@ -1 +1 @@
1
- {"version":3,"file":"emitters.d.ts","sourceRoot":"","sources":["../../../src/adapter/expr/emitters.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"emitters.d.ts","sourceRoot":"","sources":["../../../src/adapter/expr/emitters.ts"],"names":[],"mappings":"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"}
@@ -187369,7 +187369,7 @@ function isAriaBooleanAttr(name) {
187369
187369
  }
187370
187370
 
187371
187371
  // src/adapter/blade-adapter.ts
187372
- import { BF_SLOT, BF_COND, BF_REGION } from "@barefootjs/shared";
187372
+ import { BF_SLOT, BF_COND, BF_REGION, escapeHtml } from "@barefootjs/shared";
187373
187373
 
187374
187374
  // src/adapter/lib/constants.ts
187375
187375
  var BLADE_TEMPLATE_PRIMITIVES = {
@@ -187378,7 +187378,10 @@ var BLADE_TEMPLATE_PRIMITIVES = {
187378
187378
  Number: { arity: 1, emit: (args) => `$bf->number(${args[0]})` },
187379
187379
  "Math.floor": { arity: 1, emit: (args) => `$bf->floor(${args[0]})` },
187380
187380
  "Math.ceil": { arity: 1, emit: (args) => `$bf->ceil(${args[0]})` },
187381
- "Math.round": { arity: 1, emit: (args) => `$bf->round(${args[0]})` }
187381
+ "Math.round": { arity: 1, emit: (args) => `$bf->round(${args[0]})` },
187382
+ "Math.min": { arity: 2, emit: (args) => `$bf->min(${args[0]}, ${args[1]})` },
187383
+ "Math.max": { arity: 2, emit: (args) => `$bf->max(${args[0]}, ${args[1]})` },
187384
+ "Math.abs": { arity: 1, emit: (args) => `$bf->abs(${args[0]})` }
187382
187385
  };
187383
187386
  var BLADE_PRIMITIVE_EMIT_MAP = Object.fromEntries(Object.entries(BLADE_TEMPLATE_PRIMITIVES).map(([k, v]) => [k, v.emit]));
187384
187387
 
@@ -187512,6 +187515,12 @@ function renderArrayMethod(method, object, args, emit) {
187512
187515
  const recv = emit(object);
187513
187516
  return `$bf->trim(${recv})`;
187514
187517
  }
187518
+ case "trimStart":
187519
+ case "trimEnd": {
187520
+ const fn = method === "trimStart" ? "trim_start" : "trim_end";
187521
+ const recv = emit(object);
187522
+ return `$bf->${fn}(${recv})`;
187523
+ }
187515
187524
  case "toFixed": {
187516
187525
  const recv = emit(object);
187517
187526
  const digits = args.length >= 1 ? emit(args[0]) : "0";
@@ -187545,6 +187554,12 @@ function renderArrayMethod(method, object, args, emit) {
187545
187554
  const newS = emit(args[1]);
187546
187555
  return `$bf->replace(${recv}, ${oldS}, ${newS})`;
187547
187556
  }
187557
+ case "replaceAll": {
187558
+ const recv = emit(object);
187559
+ const oldS = emit(args[0]);
187560
+ const newS = emit(args[1]);
187561
+ return `$bf->replace_all(${recv}, ${oldS}, ${newS})`;
187562
+ }
187548
187563
  case "repeat": {
187549
187564
  const recv = emit(object);
187550
187565
  const count = args.length === 0 ? "0" : emit(args[0]);
@@ -187641,6 +187656,8 @@ function renderFlatMethod(recv, depth, emit) {
187641
187656
 
187642
187657
  // src/adapter/expr/emitters.ts
187643
187658
  import {
187659
+ groupBinaryOperand,
187660
+ isStringConcatBinary,
187644
187661
  identifierPath,
187645
187662
  matchSearchParamsMethodCall,
187646
187663
  sortComparatorFromArrow
@@ -187686,7 +187703,7 @@ class BladeFilterEmitter {
187686
187703
  return "null";
187687
187704
  return String(value);
187688
187705
  }
187689
- member(object, property, _computed, emit) {
187706
+ member(object, property, _computed, _optional, emit) {
187690
187707
  if (property === "length") {
187691
187708
  return `$bf->length(${emit(object)})`;
187692
187709
  }
@@ -187709,12 +187726,15 @@ class BladeFilterEmitter {
187709
187726
  return emit(argument);
187710
187727
  }
187711
187728
  binary(op, left, right, emit) {
187712
- const l = emit(left);
187713
- const r = emit(right);
187729
+ const l = groupBinaryOperand(left, emit(left));
187730
+ const r = groupBinaryOperand(right, emit(right));
187714
187731
  if (op === "===")
187715
187732
  return `$bf->eq(${l}, ${r})`;
187716
187733
  if (op === "!==")
187717
187734
  return `$bf->neq(${l}, ${r})`;
187735
+ if (isStringConcatBinary(op, left, right, this.isStringName)) {
187736
+ return `${l} . ${r}`;
187737
+ }
187718
187738
  const opMap = {
187719
187739
  ">": ">",
187720
187740
  "<": "<",
@@ -187794,7 +187814,7 @@ class BladeTopLevelEmitter {
187794
187814
  return "null";
187795
187815
  return String(value);
187796
187816
  }
187797
- member(object, property, _computed, emit) {
187817
+ member(object, property, _computed, _optional, emit) {
187798
187818
  if (object.kind === "identifier" && object.name === "props") {
187799
187819
  return bladeVar(property);
187800
187820
  }
@@ -187840,12 +187860,15 @@ class BladeTopLevelEmitter {
187840
187860
  return emit(argument);
187841
187861
  }
187842
187862
  binary(op, left, right, emit) {
187843
- const l = emit(left);
187844
- const r = emit(right);
187863
+ const l = groupBinaryOperand(left, emit(left));
187864
+ const r = groupBinaryOperand(right, emit(right));
187845
187865
  if (op === "===")
187846
187866
  return `$bf->eq(${l}, ${r})`;
187847
187867
  if (op === "!==")
187848
187868
  return `$bf->neq(${l}, ${r})`;
187869
+ if (isStringConcatBinary(op, left, right, (n) => this.ctx._isStringValueName(n))) {
187870
+ return `${l} . ${r}`;
187871
+ }
187849
187872
  const opMap = {
187850
187873
  ">": ">",
187851
187874
  "<": "<",
@@ -188215,6 +188238,7 @@ class BladeAdapter extends BaseAdapter {
188215
188238
  options;
188216
188239
  errors = [];
188217
188240
  inLoop = false;
188241
+ currentLoopKeyDepth = 0;
188218
188242
  propsObjectName = null;
188219
188243
  propsParams = [];
188220
188244
  booleanTypedProps = new Set;
@@ -188291,7 +188315,7 @@ class BladeAdapter extends BaseAdapter {
188291
188315
  return this.renderElement(node);
188292
188316
  }
188293
188317
  emitText(node) {
188294
- return node.value;
188318
+ return escapeHtml(node.value);
188295
188319
  }
188296
188320
  emitExpression(node) {
188297
188321
  return this.renderExpression(node);
@@ -188521,7 +188545,7 @@ ${whenTrue}
188521
188545
  const renderedChildren = this.renderChildren(loop.children);
188522
188546
  const loopVar = loop.iterationShape === "keys" ? "__bf_item" : supportableDestructure ? "__bf_item" : param;
188523
188547
  const indexLocalLines = [];
188524
- if (loop.iterationShape === "keys") {
188548
+ if (loop.objectIteration) {} else if (loop.iterationShape === "keys") {
188525
188549
  indexLocalLines.push(`@php(${bladeVar(param)} = $loop->index)`);
188526
188550
  } else if (loop.index) {
188527
188551
  indexLocalLines.push(`@php(${bladeVar(loop.index)} = $loop->index)`);
@@ -188542,13 +188566,17 @@ ${whenTrue}
188542
188566
  }
188543
188567
  const prevInLoop = this.inLoop;
188544
188568
  this.inLoop = true;
188569
+ const prevLoopKeyDepth = this.currentLoopKeyDepth;
188570
+ this.currentLoopKeyDepth = loop.depth;
188545
188571
  const childrenUnderLoop = this.renderChildren(loop.children);
188572
+ this.currentLoopKeyDepth = prevLoopKeyDepth;
188546
188573
  this.inLoop = prevInLoop;
188547
188574
  const bodyChildren = loop.bodyIsItemConditional && loop.key ? `{!! $bf->comment('loop-i:' . $bf->string(${this.convertExpressionToBlade(loop.key)})) !!}
188548
188575
  ${childrenUnderLoop}` : childrenUnderLoop;
188549
188576
  const lines = [];
188550
188577
  lines.push(`{!! $bf->comment("loop:${loop.markerId}") !!}`);
188551
- lines.push(`@foreach((${array} ?? []) as ${bladeVar(loopVar)})`);
188578
+ const forHeader = loop.objectIteration === "entries" ? `@foreach($bf->entries(${array} ?? []) as ${bladeVar(loop.index ?? param)} => ${bladeVar(param)})` : loop.objectIteration === "keys" ? `@foreach($bf->keys(${array} ?? []) as ${bladeVar(param)})` : loop.objectIteration === "values" ? `@foreach($bf->values(${array} ?? []) as ${bladeVar(param)})` : `@foreach((${array} ?? []) as ${bladeVar(loopVar)})`;
188579
+ lines.push(forHeader);
188552
188580
  for (const il of indexLocalLines)
188553
188581
  lines.push(il);
188554
188582
  if (loop.filterPredicate) {
@@ -188618,9 +188646,22 @@ ${childrenUnderLoop}` : childrenUnderLoop;
188618
188646
  renderComponent(comp) {
188619
188647
  const segments = [{ kind: "entries", parts: [] }];
188620
188648
  const currentEntries = () => this.componentPropSegmentEntries(segments);
188649
+ const namedSlotCaptures = [];
188621
188650
  for (const p of comp.props) {
188622
188651
  if ((p.name.match(/^on[A-Z]/) || p.name === "ref") && p.value.kind === "expression")
188623
188652
  continue;
188653
+ if (p.value.kind === "jsx-children" && p.name !== "children") {
188654
+ const prevInLoop = this.inLoop;
188655
+ this.inLoop = false;
188656
+ const slotBody = this.renderChildren(p.value.children);
188657
+ this.inLoop = prevInLoop;
188658
+ const captureVar = bladeVar(`bf_prop_${this.childrenCaptureCounter++}`);
188659
+ namedSlotCaptures.push(`@php(ob_start())
188660
+ ${slotBody}
188661
+ ` + `@php(${captureVar} = $bf->backend->mark_raw(preg_replace('/\\n\\z/', '', ob_get_clean(), 1)))`);
188662
+ currentEntries().push(`${bladeHashKey(p.name)} => ${captureVar}`);
188663
+ continue;
188664
+ }
188624
188665
  if (p.value.kind === "spread") {
188625
188666
  const trimmed = p.value.expr.trim();
188626
188667
  if (this.propsObjectName && this.propsObjectName === trimmed) {
@@ -188650,13 +188691,13 @@ ${childrenUnderLoop}` : childrenUnderLoop;
188650
188691
  const captureVar = bladeVar(`bf_children_${comp.slotId ?? "c" + this.childrenCaptureCounter++}`);
188651
188692
  currentEntries().push(`${bladeHashKey("children")} => ${captureVar}`);
188652
188693
  const dict = this.combineComponentPropSegments(segments);
188653
- return `@php(ob_start())
188694
+ return namedSlotCaptures.join("") + `@php(ob_start())
188654
188695
  ${childrenBody}
188655
188696
  ` + `@php(${captureVar} = $bf->backend->mark_raw(preg_replace('/\\n\\z/', '', ob_get_clean(), 1)))` + `{!! $bf->render_child('${tplName}', ${dict}) !!}`;
188656
188697
  }
188657
188698
  const isEmpty = segments.every((s) => s.kind === "entries" && s.parts.length === 0);
188658
188699
  const dictEntries = isEmpty ? "" : `, ${this.combineComponentPropSegments(segments)}`;
188659
- return `{!! $bf->render_child('${tplName}'${dictEntries}) !!}`;
188700
+ return `${namedSlotCaptures.join("")}{!! $bf->render_child('${tplName}'${dictEntries}) !!}`;
188660
188701
  }
188661
188702
  childrenCaptureCounter = 0;
188662
188703
  presenceVarCounter = 0;
@@ -188703,7 +188744,7 @@ ${fallback}
188703
188744
  ${children}`;
188704
188745
  }
188705
188746
  elementAttrEmitter = {
188706
- emitLiteral: (value, name) => `${name}="${value.value}"`,
188747
+ emitLiteral: (value, name) => `${name}="${escapeHtml(value.value)}"`,
188707
188748
  emitExpression: (value, name) => {
188708
188749
  if (name === "style") {
188709
188750
  const css = this.tryLowerStyleObject(value.expr);
@@ -188812,9 +188853,10 @@ ${name}="{!! e($bf->string(${val})) !!}"
188812
188853
  let attrName;
188813
188854
  if (attr.name === "className")
188814
188855
  attrName = "class";
188815
- else if (attr.name === "key")
188816
- attrName = "data-key";
188817
- else
188856
+ else if (attr.name === "key") {
188857
+ const depth = this.currentLoopKeyDepth;
188858
+ attrName = depth > 0 ? `data-key-${depth}` : "data-key";
188859
+ } else
188818
188860
  attrName = attr.name;
188819
188861
  const lowered = emitAttrValue(attr.value, this.elementAttrEmitter, attrName);
188820
188862
  if (lowered)
@@ -188901,6 +188943,7 @@ ${reason}` : "";
188901
188943
  _resolveModuleStringConst: (name) => this._resolveModuleStringConst(name),
188902
188944
  _resolveLiteralConst: (name) => this._resolveLiteralConst(name),
188903
188945
  _resolveStaticRecordLiteral: (o, k) => this._resolveStaticRecordLiteral(o, k),
188946
+ _isStringValueName: (name) => this._isStringValueName(name),
188904
188947
  _recordExprBF101: (message, reason) => this._recordExprBF101(message, reason),
188905
188948
  _renderBladeFilterExprPublic: (e, p) => this._renderBladeFilterExprPublic(e, p)
188906
188949
  };
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/adapter/lib/constants.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/C;;;;;;;;GAQG;AACH,eAAO,MAAM,yBAAyB,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAOnE,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,wBAAwB,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,MAAM,CAG7E,CAAA"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/adapter/lib/constants.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/C;;;;;;;;GAQG;AACH,eAAO,MAAM,yBAAyB,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAUnE,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,wBAAwB,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,MAAM,CAG7E,CAAA"}
package/dist/build.js CHANGED
@@ -187369,7 +187369,7 @@ function isAriaBooleanAttr(name) {
187369
187369
  }
187370
187370
 
187371
187371
  // src/adapter/blade-adapter.ts
187372
- import { BF_SLOT, BF_COND, BF_REGION } from "@barefootjs/shared";
187372
+ import { BF_SLOT, BF_COND, BF_REGION, escapeHtml } from "@barefootjs/shared";
187373
187373
 
187374
187374
  // src/adapter/lib/constants.ts
187375
187375
  var BLADE_TEMPLATE_PRIMITIVES = {
@@ -187378,7 +187378,10 @@ var BLADE_TEMPLATE_PRIMITIVES = {
187378
187378
  Number: { arity: 1, emit: (args) => `$bf->number(${args[0]})` },
187379
187379
  "Math.floor": { arity: 1, emit: (args) => `$bf->floor(${args[0]})` },
187380
187380
  "Math.ceil": { arity: 1, emit: (args) => `$bf->ceil(${args[0]})` },
187381
- "Math.round": { arity: 1, emit: (args) => `$bf->round(${args[0]})` }
187381
+ "Math.round": { arity: 1, emit: (args) => `$bf->round(${args[0]})` },
187382
+ "Math.min": { arity: 2, emit: (args) => `$bf->min(${args[0]}, ${args[1]})` },
187383
+ "Math.max": { arity: 2, emit: (args) => `$bf->max(${args[0]}, ${args[1]})` },
187384
+ "Math.abs": { arity: 1, emit: (args) => `$bf->abs(${args[0]})` }
187382
187385
  };
187383
187386
  var BLADE_PRIMITIVE_EMIT_MAP = Object.fromEntries(Object.entries(BLADE_TEMPLATE_PRIMITIVES).map(([k, v]) => [k, v.emit]));
187384
187387
 
@@ -187512,6 +187515,12 @@ function renderArrayMethod(method, object, args, emit) {
187512
187515
  const recv = emit(object);
187513
187516
  return `$bf->trim(${recv})`;
187514
187517
  }
187518
+ case "trimStart":
187519
+ case "trimEnd": {
187520
+ const fn = method === "trimStart" ? "trim_start" : "trim_end";
187521
+ const recv = emit(object);
187522
+ return `$bf->${fn}(${recv})`;
187523
+ }
187515
187524
  case "toFixed": {
187516
187525
  const recv = emit(object);
187517
187526
  const digits = args.length >= 1 ? emit(args[0]) : "0";
@@ -187545,6 +187554,12 @@ function renderArrayMethod(method, object, args, emit) {
187545
187554
  const newS = emit(args[1]);
187546
187555
  return `$bf->replace(${recv}, ${oldS}, ${newS})`;
187547
187556
  }
187557
+ case "replaceAll": {
187558
+ const recv = emit(object);
187559
+ const oldS = emit(args[0]);
187560
+ const newS = emit(args[1]);
187561
+ return `$bf->replace_all(${recv}, ${oldS}, ${newS})`;
187562
+ }
187548
187563
  case "repeat": {
187549
187564
  const recv = emit(object);
187550
187565
  const count = args.length === 0 ? "0" : emit(args[0]);
@@ -187641,6 +187656,8 @@ function renderFlatMethod(recv, depth, emit) {
187641
187656
 
187642
187657
  // src/adapter/expr/emitters.ts
187643
187658
  import {
187659
+ groupBinaryOperand,
187660
+ isStringConcatBinary,
187644
187661
  identifierPath,
187645
187662
  matchSearchParamsMethodCall,
187646
187663
  sortComparatorFromArrow
@@ -187686,7 +187703,7 @@ class BladeFilterEmitter {
187686
187703
  return "null";
187687
187704
  return String(value);
187688
187705
  }
187689
- member(object, property, _computed, emit) {
187706
+ member(object, property, _computed, _optional, emit) {
187690
187707
  if (property === "length") {
187691
187708
  return `$bf->length(${emit(object)})`;
187692
187709
  }
@@ -187709,12 +187726,15 @@ class BladeFilterEmitter {
187709
187726
  return emit(argument);
187710
187727
  }
187711
187728
  binary(op, left, right, emit) {
187712
- const l = emit(left);
187713
- const r = emit(right);
187729
+ const l = groupBinaryOperand(left, emit(left));
187730
+ const r = groupBinaryOperand(right, emit(right));
187714
187731
  if (op === "===")
187715
187732
  return `$bf->eq(${l}, ${r})`;
187716
187733
  if (op === "!==")
187717
187734
  return `$bf->neq(${l}, ${r})`;
187735
+ if (isStringConcatBinary(op, left, right, this.isStringName)) {
187736
+ return `${l} . ${r}`;
187737
+ }
187718
187738
  const opMap = {
187719
187739
  ">": ">",
187720
187740
  "<": "<",
@@ -187794,7 +187814,7 @@ class BladeTopLevelEmitter {
187794
187814
  return "null";
187795
187815
  return String(value);
187796
187816
  }
187797
- member(object, property, _computed, emit) {
187817
+ member(object, property, _computed, _optional, emit) {
187798
187818
  if (object.kind === "identifier" && object.name === "props") {
187799
187819
  return bladeVar(property);
187800
187820
  }
@@ -187840,12 +187860,15 @@ class BladeTopLevelEmitter {
187840
187860
  return emit(argument);
187841
187861
  }
187842
187862
  binary(op, left, right, emit) {
187843
- const l = emit(left);
187844
- const r = emit(right);
187863
+ const l = groupBinaryOperand(left, emit(left));
187864
+ const r = groupBinaryOperand(right, emit(right));
187845
187865
  if (op === "===")
187846
187866
  return `$bf->eq(${l}, ${r})`;
187847
187867
  if (op === "!==")
187848
187868
  return `$bf->neq(${l}, ${r})`;
187869
+ if (isStringConcatBinary(op, left, right, (n) => this.ctx._isStringValueName(n))) {
187870
+ return `${l} . ${r}`;
187871
+ }
187849
187872
  const opMap = {
187850
187873
  ">": ">",
187851
187874
  "<": "<",
@@ -188215,6 +188238,7 @@ class BladeAdapter extends BaseAdapter {
188215
188238
  options;
188216
188239
  errors = [];
188217
188240
  inLoop = false;
188241
+ currentLoopKeyDepth = 0;
188218
188242
  propsObjectName = null;
188219
188243
  propsParams = [];
188220
188244
  booleanTypedProps = new Set;
@@ -188291,7 +188315,7 @@ class BladeAdapter extends BaseAdapter {
188291
188315
  return this.renderElement(node);
188292
188316
  }
188293
188317
  emitText(node) {
188294
- return node.value;
188318
+ return escapeHtml(node.value);
188295
188319
  }
188296
188320
  emitExpression(node) {
188297
188321
  return this.renderExpression(node);
@@ -188521,7 +188545,7 @@ ${whenTrue}
188521
188545
  const renderedChildren = this.renderChildren(loop.children);
188522
188546
  const loopVar = loop.iterationShape === "keys" ? "__bf_item" : supportableDestructure ? "__bf_item" : param;
188523
188547
  const indexLocalLines = [];
188524
- if (loop.iterationShape === "keys") {
188548
+ if (loop.objectIteration) {} else if (loop.iterationShape === "keys") {
188525
188549
  indexLocalLines.push(`@php(${bladeVar(param)} = $loop->index)`);
188526
188550
  } else if (loop.index) {
188527
188551
  indexLocalLines.push(`@php(${bladeVar(loop.index)} = $loop->index)`);
@@ -188542,13 +188566,17 @@ ${whenTrue}
188542
188566
  }
188543
188567
  const prevInLoop = this.inLoop;
188544
188568
  this.inLoop = true;
188569
+ const prevLoopKeyDepth = this.currentLoopKeyDepth;
188570
+ this.currentLoopKeyDepth = loop.depth;
188545
188571
  const childrenUnderLoop = this.renderChildren(loop.children);
188572
+ this.currentLoopKeyDepth = prevLoopKeyDepth;
188546
188573
  this.inLoop = prevInLoop;
188547
188574
  const bodyChildren = loop.bodyIsItemConditional && loop.key ? `{!! $bf->comment('loop-i:' . $bf->string(${this.convertExpressionToBlade(loop.key)})) !!}
188548
188575
  ${childrenUnderLoop}` : childrenUnderLoop;
188549
188576
  const lines = [];
188550
188577
  lines.push(`{!! $bf->comment("loop:${loop.markerId}") !!}`);
188551
- lines.push(`@foreach((${array} ?? []) as ${bladeVar(loopVar)})`);
188578
+ const forHeader = loop.objectIteration === "entries" ? `@foreach($bf->entries(${array} ?? []) as ${bladeVar(loop.index ?? param)} => ${bladeVar(param)})` : loop.objectIteration === "keys" ? `@foreach($bf->keys(${array} ?? []) as ${bladeVar(param)})` : loop.objectIteration === "values" ? `@foreach($bf->values(${array} ?? []) as ${bladeVar(param)})` : `@foreach((${array} ?? []) as ${bladeVar(loopVar)})`;
188579
+ lines.push(forHeader);
188552
188580
  for (const il of indexLocalLines)
188553
188581
  lines.push(il);
188554
188582
  if (loop.filterPredicate) {
@@ -188618,9 +188646,22 @@ ${childrenUnderLoop}` : childrenUnderLoop;
188618
188646
  renderComponent(comp) {
188619
188647
  const segments = [{ kind: "entries", parts: [] }];
188620
188648
  const currentEntries = () => this.componentPropSegmentEntries(segments);
188649
+ const namedSlotCaptures = [];
188621
188650
  for (const p of comp.props) {
188622
188651
  if ((p.name.match(/^on[A-Z]/) || p.name === "ref") && p.value.kind === "expression")
188623
188652
  continue;
188653
+ if (p.value.kind === "jsx-children" && p.name !== "children") {
188654
+ const prevInLoop = this.inLoop;
188655
+ this.inLoop = false;
188656
+ const slotBody = this.renderChildren(p.value.children);
188657
+ this.inLoop = prevInLoop;
188658
+ const captureVar = bladeVar(`bf_prop_${this.childrenCaptureCounter++}`);
188659
+ namedSlotCaptures.push(`@php(ob_start())
188660
+ ${slotBody}
188661
+ ` + `@php(${captureVar} = $bf->backend->mark_raw(preg_replace('/\\n\\z/', '', ob_get_clean(), 1)))`);
188662
+ currentEntries().push(`${bladeHashKey(p.name)} => ${captureVar}`);
188663
+ continue;
188664
+ }
188624
188665
  if (p.value.kind === "spread") {
188625
188666
  const trimmed = p.value.expr.trim();
188626
188667
  if (this.propsObjectName && this.propsObjectName === trimmed) {
@@ -188650,13 +188691,13 @@ ${childrenUnderLoop}` : childrenUnderLoop;
188650
188691
  const captureVar = bladeVar(`bf_children_${comp.slotId ?? "c" + this.childrenCaptureCounter++}`);
188651
188692
  currentEntries().push(`${bladeHashKey("children")} => ${captureVar}`);
188652
188693
  const dict = this.combineComponentPropSegments(segments);
188653
- return `@php(ob_start())
188694
+ return namedSlotCaptures.join("") + `@php(ob_start())
188654
188695
  ${childrenBody}
188655
188696
  ` + `@php(${captureVar} = $bf->backend->mark_raw(preg_replace('/\\n\\z/', '', ob_get_clean(), 1)))` + `{!! $bf->render_child('${tplName}', ${dict}) !!}`;
188656
188697
  }
188657
188698
  const isEmpty = segments.every((s) => s.kind === "entries" && s.parts.length === 0);
188658
188699
  const dictEntries = isEmpty ? "" : `, ${this.combineComponentPropSegments(segments)}`;
188659
- return `{!! $bf->render_child('${tplName}'${dictEntries}) !!}`;
188700
+ return `${namedSlotCaptures.join("")}{!! $bf->render_child('${tplName}'${dictEntries}) !!}`;
188660
188701
  }
188661
188702
  childrenCaptureCounter = 0;
188662
188703
  presenceVarCounter = 0;
@@ -188703,7 +188744,7 @@ ${fallback}
188703
188744
  ${children}`;
188704
188745
  }
188705
188746
  elementAttrEmitter = {
188706
- emitLiteral: (value, name) => `${name}="${value.value}"`,
188747
+ emitLiteral: (value, name) => `${name}="${escapeHtml(value.value)}"`,
188707
188748
  emitExpression: (value, name) => {
188708
188749
  if (name === "style") {
188709
188750
  const css = this.tryLowerStyleObject(value.expr);
@@ -188812,9 +188853,10 @@ ${name}="{!! e($bf->string(${val})) !!}"
188812
188853
  let attrName;
188813
188854
  if (attr.name === "className")
188814
188855
  attrName = "class";
188815
- else if (attr.name === "key")
188816
- attrName = "data-key";
188817
- else
188856
+ else if (attr.name === "key") {
188857
+ const depth = this.currentLoopKeyDepth;
188858
+ attrName = depth > 0 ? `data-key-${depth}` : "data-key";
188859
+ } else
188818
188860
  attrName = attr.name;
188819
188861
  const lowered = emitAttrValue(attr.value, this.elementAttrEmitter, attrName);
188820
188862
  if (lowered)
@@ -188901,6 +188943,7 @@ ${reason}` : "";
188901
188943
  _resolveModuleStringConst: (name) => this._resolveModuleStringConst(name),
188902
188944
  _resolveLiteralConst: (name) => this._resolveLiteralConst(name),
188903
188945
  _resolveStaticRecordLiteral: (o, k) => this._resolveStaticRecordLiteral(o, k),
188946
+ _isStringValueName: (name) => this._isStringValueName(name),
188904
188947
  _recordExprBF101: (message, reason) => this._recordExprBF101(message, reason),
188905
188948
  _renderBladeFilterExprPublic: (e, p) => this._renderBladeFilterExprPublic(e, p)
188906
188949
  };
@@ -1 +1 @@
1
- {"version":3,"file":"conformance-pins.d.ts","sourceRoot":"","sources":["../src/conformance-pins.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEtD,eAAO,MAAM,eAAe,EAAE,eAoF7B,CAAA"}
1
+ {"version":3,"file":"conformance-pins.d.ts","sourceRoot":"","sources":["../src/conformance-pins.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEtD,eAAO,MAAM,eAAe,EAAE,eA+E7B,CAAA"}
package/dist/index.js CHANGED
@@ -187369,7 +187369,7 @@ function isAriaBooleanAttr(name) {
187369
187369
  }
187370
187370
 
187371
187371
  // src/adapter/blade-adapter.ts
187372
- import { BF_SLOT, BF_COND, BF_REGION } from "@barefootjs/shared";
187372
+ import { BF_SLOT, BF_COND, BF_REGION, escapeHtml } from "@barefootjs/shared";
187373
187373
 
187374
187374
  // src/adapter/lib/constants.ts
187375
187375
  var BLADE_TEMPLATE_PRIMITIVES = {
@@ -187378,7 +187378,10 @@ var BLADE_TEMPLATE_PRIMITIVES = {
187378
187378
  Number: { arity: 1, emit: (args) => `$bf->number(${args[0]})` },
187379
187379
  "Math.floor": { arity: 1, emit: (args) => `$bf->floor(${args[0]})` },
187380
187380
  "Math.ceil": { arity: 1, emit: (args) => `$bf->ceil(${args[0]})` },
187381
- "Math.round": { arity: 1, emit: (args) => `$bf->round(${args[0]})` }
187381
+ "Math.round": { arity: 1, emit: (args) => `$bf->round(${args[0]})` },
187382
+ "Math.min": { arity: 2, emit: (args) => `$bf->min(${args[0]}, ${args[1]})` },
187383
+ "Math.max": { arity: 2, emit: (args) => `$bf->max(${args[0]}, ${args[1]})` },
187384
+ "Math.abs": { arity: 1, emit: (args) => `$bf->abs(${args[0]})` }
187382
187385
  };
187383
187386
  var BLADE_PRIMITIVE_EMIT_MAP = Object.fromEntries(Object.entries(BLADE_TEMPLATE_PRIMITIVES).map(([k, v]) => [k, v.emit]));
187384
187387
 
@@ -187512,6 +187515,12 @@ function renderArrayMethod(method, object, args, emit) {
187512
187515
  const recv = emit(object);
187513
187516
  return `$bf->trim(${recv})`;
187514
187517
  }
187518
+ case "trimStart":
187519
+ case "trimEnd": {
187520
+ const fn = method === "trimStart" ? "trim_start" : "trim_end";
187521
+ const recv = emit(object);
187522
+ return `$bf->${fn}(${recv})`;
187523
+ }
187515
187524
  case "toFixed": {
187516
187525
  const recv = emit(object);
187517
187526
  const digits = args.length >= 1 ? emit(args[0]) : "0";
@@ -187545,6 +187554,12 @@ function renderArrayMethod(method, object, args, emit) {
187545
187554
  const newS = emit(args[1]);
187546
187555
  return `$bf->replace(${recv}, ${oldS}, ${newS})`;
187547
187556
  }
187557
+ case "replaceAll": {
187558
+ const recv = emit(object);
187559
+ const oldS = emit(args[0]);
187560
+ const newS = emit(args[1]);
187561
+ return `$bf->replace_all(${recv}, ${oldS}, ${newS})`;
187562
+ }
187548
187563
  case "repeat": {
187549
187564
  const recv = emit(object);
187550
187565
  const count = args.length === 0 ? "0" : emit(args[0]);
@@ -187641,6 +187656,8 @@ function renderFlatMethod(recv, depth, emit) {
187641
187656
 
187642
187657
  // src/adapter/expr/emitters.ts
187643
187658
  import {
187659
+ groupBinaryOperand,
187660
+ isStringConcatBinary,
187644
187661
  identifierPath,
187645
187662
  matchSearchParamsMethodCall,
187646
187663
  sortComparatorFromArrow
@@ -187686,7 +187703,7 @@ class BladeFilterEmitter {
187686
187703
  return "null";
187687
187704
  return String(value);
187688
187705
  }
187689
- member(object, property, _computed, emit) {
187706
+ member(object, property, _computed, _optional, emit) {
187690
187707
  if (property === "length") {
187691
187708
  return `$bf->length(${emit(object)})`;
187692
187709
  }
@@ -187709,12 +187726,15 @@ class BladeFilterEmitter {
187709
187726
  return emit(argument);
187710
187727
  }
187711
187728
  binary(op, left, right, emit) {
187712
- const l = emit(left);
187713
- const r = emit(right);
187729
+ const l = groupBinaryOperand(left, emit(left));
187730
+ const r = groupBinaryOperand(right, emit(right));
187714
187731
  if (op === "===")
187715
187732
  return `$bf->eq(${l}, ${r})`;
187716
187733
  if (op === "!==")
187717
187734
  return `$bf->neq(${l}, ${r})`;
187735
+ if (isStringConcatBinary(op, left, right, this.isStringName)) {
187736
+ return `${l} . ${r}`;
187737
+ }
187718
187738
  const opMap = {
187719
187739
  ">": ">",
187720
187740
  "<": "<",
@@ -187794,7 +187814,7 @@ class BladeTopLevelEmitter {
187794
187814
  return "null";
187795
187815
  return String(value);
187796
187816
  }
187797
- member(object, property, _computed, emit) {
187817
+ member(object, property, _computed, _optional, emit) {
187798
187818
  if (object.kind === "identifier" && object.name === "props") {
187799
187819
  return bladeVar(property);
187800
187820
  }
@@ -187840,12 +187860,15 @@ class BladeTopLevelEmitter {
187840
187860
  return emit(argument);
187841
187861
  }
187842
187862
  binary(op, left, right, emit) {
187843
- const l = emit(left);
187844
- const r = emit(right);
187863
+ const l = groupBinaryOperand(left, emit(left));
187864
+ const r = groupBinaryOperand(right, emit(right));
187845
187865
  if (op === "===")
187846
187866
  return `$bf->eq(${l}, ${r})`;
187847
187867
  if (op === "!==")
187848
187868
  return `$bf->neq(${l}, ${r})`;
187869
+ if (isStringConcatBinary(op, left, right, (n) => this.ctx._isStringValueName(n))) {
187870
+ return `${l} . ${r}`;
187871
+ }
187849
187872
  const opMap = {
187850
187873
  ">": ">",
187851
187874
  "<": "<",
@@ -188215,6 +188238,7 @@ class BladeAdapter extends BaseAdapter {
188215
188238
  options;
188216
188239
  errors = [];
188217
188240
  inLoop = false;
188241
+ currentLoopKeyDepth = 0;
188218
188242
  propsObjectName = null;
188219
188243
  propsParams = [];
188220
188244
  booleanTypedProps = new Set;
@@ -188291,7 +188315,7 @@ class BladeAdapter extends BaseAdapter {
188291
188315
  return this.renderElement(node);
188292
188316
  }
188293
188317
  emitText(node) {
188294
- return node.value;
188318
+ return escapeHtml(node.value);
188295
188319
  }
188296
188320
  emitExpression(node) {
188297
188321
  return this.renderExpression(node);
@@ -188521,7 +188545,7 @@ ${whenTrue}
188521
188545
  const renderedChildren = this.renderChildren(loop.children);
188522
188546
  const loopVar = loop.iterationShape === "keys" ? "__bf_item" : supportableDestructure ? "__bf_item" : param;
188523
188547
  const indexLocalLines = [];
188524
- if (loop.iterationShape === "keys") {
188548
+ if (loop.objectIteration) {} else if (loop.iterationShape === "keys") {
188525
188549
  indexLocalLines.push(`@php(${bladeVar(param)} = $loop->index)`);
188526
188550
  } else if (loop.index) {
188527
188551
  indexLocalLines.push(`@php(${bladeVar(loop.index)} = $loop->index)`);
@@ -188542,13 +188566,17 @@ ${whenTrue}
188542
188566
  }
188543
188567
  const prevInLoop = this.inLoop;
188544
188568
  this.inLoop = true;
188569
+ const prevLoopKeyDepth = this.currentLoopKeyDepth;
188570
+ this.currentLoopKeyDepth = loop.depth;
188545
188571
  const childrenUnderLoop = this.renderChildren(loop.children);
188572
+ this.currentLoopKeyDepth = prevLoopKeyDepth;
188546
188573
  this.inLoop = prevInLoop;
188547
188574
  const bodyChildren = loop.bodyIsItemConditional && loop.key ? `{!! $bf->comment('loop-i:' . $bf->string(${this.convertExpressionToBlade(loop.key)})) !!}
188548
188575
  ${childrenUnderLoop}` : childrenUnderLoop;
188549
188576
  const lines = [];
188550
188577
  lines.push(`{!! $bf->comment("loop:${loop.markerId}") !!}`);
188551
- lines.push(`@foreach((${array} ?? []) as ${bladeVar(loopVar)})`);
188578
+ const forHeader = loop.objectIteration === "entries" ? `@foreach($bf->entries(${array} ?? []) as ${bladeVar(loop.index ?? param)} => ${bladeVar(param)})` : loop.objectIteration === "keys" ? `@foreach($bf->keys(${array} ?? []) as ${bladeVar(param)})` : loop.objectIteration === "values" ? `@foreach($bf->values(${array} ?? []) as ${bladeVar(param)})` : `@foreach((${array} ?? []) as ${bladeVar(loopVar)})`;
188579
+ lines.push(forHeader);
188552
188580
  for (const il of indexLocalLines)
188553
188581
  lines.push(il);
188554
188582
  if (loop.filterPredicate) {
@@ -188618,9 +188646,22 @@ ${childrenUnderLoop}` : childrenUnderLoop;
188618
188646
  renderComponent(comp) {
188619
188647
  const segments = [{ kind: "entries", parts: [] }];
188620
188648
  const currentEntries = () => this.componentPropSegmentEntries(segments);
188649
+ const namedSlotCaptures = [];
188621
188650
  for (const p of comp.props) {
188622
188651
  if ((p.name.match(/^on[A-Z]/) || p.name === "ref") && p.value.kind === "expression")
188623
188652
  continue;
188653
+ if (p.value.kind === "jsx-children" && p.name !== "children") {
188654
+ const prevInLoop = this.inLoop;
188655
+ this.inLoop = false;
188656
+ const slotBody = this.renderChildren(p.value.children);
188657
+ this.inLoop = prevInLoop;
188658
+ const captureVar = bladeVar(`bf_prop_${this.childrenCaptureCounter++}`);
188659
+ namedSlotCaptures.push(`@php(ob_start())
188660
+ ${slotBody}
188661
+ ` + `@php(${captureVar} = $bf->backend->mark_raw(preg_replace('/\\n\\z/', '', ob_get_clean(), 1)))`);
188662
+ currentEntries().push(`${bladeHashKey(p.name)} => ${captureVar}`);
188663
+ continue;
188664
+ }
188624
188665
  if (p.value.kind === "spread") {
188625
188666
  const trimmed = p.value.expr.trim();
188626
188667
  if (this.propsObjectName && this.propsObjectName === trimmed) {
@@ -188650,13 +188691,13 @@ ${childrenUnderLoop}` : childrenUnderLoop;
188650
188691
  const captureVar = bladeVar(`bf_children_${comp.slotId ?? "c" + this.childrenCaptureCounter++}`);
188651
188692
  currentEntries().push(`${bladeHashKey("children")} => ${captureVar}`);
188652
188693
  const dict = this.combineComponentPropSegments(segments);
188653
- return `@php(ob_start())
188694
+ return namedSlotCaptures.join("") + `@php(ob_start())
188654
188695
  ${childrenBody}
188655
188696
  ` + `@php(${captureVar} = $bf->backend->mark_raw(preg_replace('/\\n\\z/', '', ob_get_clean(), 1)))` + `{!! $bf->render_child('${tplName}', ${dict}) !!}`;
188656
188697
  }
188657
188698
  const isEmpty = segments.every((s) => s.kind === "entries" && s.parts.length === 0);
188658
188699
  const dictEntries = isEmpty ? "" : `, ${this.combineComponentPropSegments(segments)}`;
188659
- return `{!! $bf->render_child('${tplName}'${dictEntries}) !!}`;
188700
+ return `${namedSlotCaptures.join("")}{!! $bf->render_child('${tplName}'${dictEntries}) !!}`;
188660
188701
  }
188661
188702
  childrenCaptureCounter = 0;
188662
188703
  presenceVarCounter = 0;
@@ -188703,7 +188744,7 @@ ${fallback}
188703
188744
  ${children}`;
188704
188745
  }
188705
188746
  elementAttrEmitter = {
188706
- emitLiteral: (value, name) => `${name}="${value.value}"`,
188747
+ emitLiteral: (value, name) => `${name}="${escapeHtml(value.value)}"`,
188707
188748
  emitExpression: (value, name) => {
188708
188749
  if (name === "style") {
188709
188750
  const css = this.tryLowerStyleObject(value.expr);
@@ -188812,9 +188853,10 @@ ${name}="{!! e($bf->string(${val})) !!}"
188812
188853
  let attrName;
188813
188854
  if (attr.name === "className")
188814
188855
  attrName = "class";
188815
- else if (attr.name === "key")
188816
- attrName = "data-key";
188817
- else
188856
+ else if (attr.name === "key") {
188857
+ const depth = this.currentLoopKeyDepth;
188858
+ attrName = depth > 0 ? `data-key-${depth}` : "data-key";
188859
+ } else
188818
188860
  attrName = attr.name;
188819
188861
  const lowered = emitAttrValue(attr.value, this.elementAttrEmitter, attrName);
188820
188862
  if (lowered)
@@ -188901,6 +188943,7 @@ ${reason}` : "";
188901
188943
  _resolveModuleStringConst: (name) => this._resolveModuleStringConst(name),
188902
188944
  _resolveLiteralConst: (name) => this._resolveLiteralConst(name),
188903
188945
  _resolveStaticRecordLiteral: (o, k) => this._resolveStaticRecordLiteral(o, k),
188946
+ _isStringValueName: (name) => this._isStringValueName(name),
188904
188947
  _recordExprBF101: (message, reason) => this._recordExprBF101(message, reason),
188905
188948
  _renderBladeFilterExprPublic: (e, p) => this._renderBladeFilterExprPublic(e, p)
188906
188949
  };
@@ -189071,25 +189114,10 @@ var conformancePins = {
189071
189114
  { code: "BF101", severity: "error", issue: "https://github.com/piconic-ai/barefootjs/issues/2038" }
189072
189115
  ],
189073
189116
  "array-map-function-reference": [{ code: "BF101", severity: "error" }],
189074
- "dangerous-inner-html": [{ code: "BF101", severity: "error" }],
189075
- "string-replaceall": [{ code: "BF101", severity: "error" }]
189117
+ "dangerous-inner-html": [{ code: "BF101", severity: "error" }]
189076
189118
  };
189077
189119
  // src/render-divergences.ts
189078
- var renderDivergences = {
189079
- "arithmetic-text": "`(count() + 2) * 3` renders 10 instead of 18 — the parenthesised sub-expression loses its grouping (silent wrong arithmetic)",
189080
- "string-concat-plus": "`'Hello, ' + name` is emitted as PHP `+`, which fatals with \"Unsupported operand types: string + string\" — needs PHP's `.` concat",
189081
- "html-entity-text": "`&copy;` in JSX literal text: Hono decodes to `©`, this adapter re-emits the raw entity — same DOM, different bytes",
189082
- "math-methods": "Math.min/max/abs over a signal render empty (only Math.floor is in the template-primitive registry)",
189083
- "boolean-attr-literals": 'camelCase boolean alias `readOnly`: Hono SSRs `readOnly="true"`, this adapter emits bare presence',
189084
- "camelcase-attributes": "`htmlFor` is not lowered to `for` (Hono maps it)",
189085
- "static-attr-escape": 'static attribute values are not HTML-escaped (`title="Fish & Chips"` emitted raw; Hono escapes)',
189086
- "svg-icon": "SVG camelCase presentation attrs (`strokeWidth`, `strokeLinecap`) pass through unmapped; Hono lowers to kebab-case",
189087
- "object-entries-map": "`Object.entries(prop).map(([k, v]) => …)` renders an EMPTY list — the object-shaped prop silently produces zero iterations",
189088
- "nested-loop-outer-binding": "nested-loop inner items carry `data-key` where the reference emits the depth-suffixed `data-key-1`",
189089
- "jsx-element-prop": "a JSX element passed as a NON-children prop renders an empty slot — the element value is silently dropped",
189090
- "string-slice": "`.slice()` on a STRING renders empty (array-slice helper misfires on strings)",
189091
- "string-trim-sided": "`.trimStart()` / `.trimEnd()` render empty (no lowering)"
189092
- };
189120
+ var renderDivergences = {};
189093
189121
  export {
189094
189122
  renderDivergences,
189095
189123
  conformancePins,
@@ -1 +1 @@
1
- {"version":3,"file":"render-divergences.d.ts","sourceRoot":"","sources":["../src/render-divergences.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AAExD,eAAO,MAAM,iBAAiB,EAAE,iBA2B/B,CAAA"}
1
+ {"version":3,"file":"render-divergences.d.ts","sourceRoot":"","sources":["../src/render-divergences.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AAExD,eAAO,MAAM,iBAAiB,EAAE,iBAAsB,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@barefootjs/blade",
3
- "version": "0.18.3",
3
+ "version": "0.18.5",
4
4
  "description": "Laravel Blade (PHP) adapter for BarefootJS — compiles IR to .blade.php templates and ships the PHP BarefootJS rendering runtime on illuminate/view standalone",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -54,14 +54,14 @@
54
54
  "directory": "packages/adapter-blade"
55
55
  },
56
56
  "dependencies": {
57
- "@barefootjs/shared": "0.18.3"
57
+ "@barefootjs/shared": "0.18.5"
58
58
  },
59
59
  "peerDependencies": {
60
60
  "@barefootjs/jsx": ">=0.2.0"
61
61
  },
62
62
  "devDependencies": {
63
63
  "@barefootjs/adapter-tests": "0.1.0",
64
- "@barefootjs/jsx": "0.18.3",
64
+ "@barefootjs/jsx": "0.18.5",
65
65
  "typescript": "^5.0.0"
66
66
  }
67
67
  }
@@ -385,6 +385,27 @@ export function C(props: { count: number }) {
385
385
  })
386
386
  })
387
387
 
388
+ describe('BladeAdapter - named-slot capture identifier safety (#2168 jsx-element-prop)', () => {
389
+ // A JSX-valued prop under a hyphenated name (`data-slot`, a valid JSX
390
+ // attribute name) must not leak into the capture variable — `bladeIdent`
391
+ // only guards reserved words, not non-identifier characters like `-`, so
392
+ // a name-derived variable would emit invalid PHP. The capture variable is
393
+ // purely counter-based (never derived from the prop name); the hash KEY
394
+ // passed to `render_child` still carries the real name, quoted via
395
+ // `bladeHashKey`.
396
+ test('a hyphenated prop name does not appear in the capture variable', () => {
397
+ const { template } = compileAndGenerate(`
398
+ function Card(props) { return null }
399
+ export function Parent() {
400
+ return <Card data-slot={<strong>Title</strong>}>text</Card>
401
+ }
402
+ `)
403
+ expect(template).toContain('@php($bf_prop_0 = $bf->backend->mark_raw(')
404
+ expect(template).toContain("'data-slot' => $bf_prop_0")
405
+ expect(template).not.toContain('$bf_prop_data')
406
+ })
407
+ })
408
+
388
409
  // #2038 nested-callback-predicate loudness is pinned at the shared
389
410
  // conformance layer (workstream C): `filter-nested-callback-predicate` /
390
411
  // `filter-nested-find-predicate` (BF101 via `expectedDiagnostics`) and
@@ -292,7 +292,7 @@ import {
292
292
  } from '@barefootjs/jsx'
293
293
  import { isAriaBooleanAttr, isBooleanResultExpr, isExplicitStringCall } from './boolean-result.ts'
294
294
  import type { ParsedExpr, LoweringMatcher } from '@barefootjs/jsx'
295
- import { BF_SLOT, BF_COND, BF_REGION } from '@barefootjs/shared'
295
+ import { BF_SLOT, BF_COND, BF_REGION, escapeHtml } from '@barefootjs/shared'
296
296
 
297
297
  import type { BladeRenderCtx } from './lib/types.ts'
298
298
  import { BLADE_PRIMITIVE_EMIT_MAP } from './lib/constants.ts'
@@ -356,6 +356,14 @@ export class BladeAdapter extends BaseAdapter implements IRNodeEmitter<BladeRend
356
356
  private options: Required<BladeAdapterOptions>
357
357
  private errors: CompilerError[] = []
358
358
  private inLoop: boolean = false
359
+ /**
360
+ * `IRLoop.depth` of the loop currently being rendered (save/restore
361
+ * around `renderChildren(loop.children)`, mirroring `inLoop` above).
362
+ * `renderAttributes` reads this to derive the `key` → `data-key`/
363
+ * `data-key-N` suffix — the depth is IR-computed (jsx-to-ir.ts), not
364
+ * re-derived here (#2168 nested-loop-outer-binding).
365
+ */
366
+ private currentLoopKeyDepth = 0
359
367
  /**
360
368
  * SolidJS-style props identifier (`function(props: P)`) and the
361
369
  * analyzer-extracted prop names. Stashed at `generate()` entry so the
@@ -550,7 +558,9 @@ export class BladeAdapter extends BaseAdapter implements IRNodeEmitter<BladeRend
550
558
  }
551
559
 
552
560
  emitText(node: IRText): string {
553
- return node.value
561
+ // IRText carries the entity-DECODED value (Phase 1 decodes JSX
562
+ // character references); re-escape for direct HTML emission.
563
+ return escapeHtml(node.value)
554
564
  }
555
565
 
556
566
  emitExpression(node: IRExpression): string {
@@ -922,7 +932,11 @@ export class BladeAdapter extends BaseAdapter implements IRNodeEmitter<BladeRend
922
932
  // other than member-access / spread (already refused by the gate)
923
933
  // can't observe a sibling field the pattern destructured explicitly.
924
934
  const indexLocalLines: string[] = []
925
- if (loop.iterationShape === 'keys') {
935
+ if (loop.objectIteration) {
936
+ // `key`/`value` bind directly in the `@foreach` header (see below)
937
+ // via `$bf->entries`/`$bf->keys`/`$bf->values` — no derived
938
+ // `$loop->index` local needed, unlike the array `iterationShape` cases.
939
+ } else if (loop.iterationShape === 'keys') {
926
940
  indexLocalLines.push(`@php(${bladeVar(param)} = $loop->index)`)
927
941
  } else if (loop.index) {
928
942
  indexLocalLines.push(`@php(${bladeVar(loop.index)} = $loop->index)`)
@@ -950,10 +964,13 @@ export class BladeAdapter extends BaseAdapter implements IRNodeEmitter<BladeRend
950
964
 
951
965
  const prevInLoop = this.inLoop
952
966
  this.inLoop = true
967
+ const prevLoopKeyDepth = this.currentLoopKeyDepth
968
+ this.currentLoopKeyDepth = loop.depth
953
969
  // Re-render children now that inLoop is set (so nested components use the
954
970
  // loop-child naming convention). renderedChildren above was computed with
955
971
  // the previous flag; recompute under the loop flag.
956
972
  const childrenUnderLoop = this.renderChildren(loop.children)
973
+ this.currentLoopKeyDepth = prevLoopKeyDepth
957
974
  this.inLoop = prevInLoop
958
975
  void renderedChildren
959
976
 
@@ -973,7 +990,23 @@ export class BladeAdapter extends BaseAdapter implements IRNodeEmitter<BladeRend
973
990
  // See this file's header, divergence 2: raw PHP `foreach` over a
974
991
  // null/undefined array raises, unlike Twig's `strict_variables: false`
975
992
  // tolerance — the `?? []` guard restores that same tolerance uniformly.
976
- lines.push(`@foreach((${array} ?? []) as ${bladeVar(loopVar)})`)
993
+ //
994
+ // `objectIteration` (#2168 object-entries-map): PHP's native `foreach`
995
+ // CAN iterate a `stdClass` object's public properties directly (unlike
996
+ // Twig's `for` tag, which needs `Traversable`) — but this still routes
997
+ // through `$bf->entries`/`$bf->keys`/`$bf->values` for the same
998
+ // defensive non-object guard Twig needs and for a single source of
999
+ // truth on "is this a JS object" (`isJsObject`, `BarefootJS.php`); the
1000
+ // `(array)` cast those methods do preserves the object's own insertion
1001
+ // order either way.
1002
+ const forHeader = loop.objectIteration === 'entries'
1003
+ ? `@foreach($bf->entries(${array} ?? []) as ${bladeVar(loop.index ?? param)} => ${bladeVar(param)})`
1004
+ : loop.objectIteration === 'keys'
1005
+ ? `@foreach($bf->keys(${array} ?? []) as ${bladeVar(param)})`
1006
+ : loop.objectIteration === 'values'
1007
+ ? `@foreach($bf->values(${array} ?? []) as ${bladeVar(param)})`
1008
+ : `@foreach((${array} ?? []) as ${bladeVar(loopVar)})`
1009
+ lines.push(forHeader)
977
1010
  for (const il of indexLocalLines) lines.push(il)
978
1011
 
979
1012
  // Handle filter().map() pattern by wrapping children in if-condition
@@ -1114,11 +1147,37 @@ export class BladeAdapter extends BaseAdapter implements IRNodeEmitter<BladeRend
1114
1147
  type Segment = { kind: 'entries'; parts: string[] } | { kind: 'spread'; expr: string }
1115
1148
  const segments: Segment[] = [{ kind: 'entries', parts: [] }]
1116
1149
  const currentEntries = () => this.componentPropSegmentEntries(segments)
1150
+ // Named JSX-valued props OTHER than the reserved `children`
1151
+ // (`header={<strong>Title</strong>}`, #2168 jsx-element-prop) each get
1152
+ // their own output-buffering capture, prepended to the final returned
1153
+ // string below — same mechanism as the reserved children capture,
1154
+ // just keyed by the prop's own name instead of `children`.
1155
+ const namedSlotCaptures: string[] = []
1117
1156
 
1118
1157
  for (const p of comp.props) {
1119
1158
  // Skip callback props (onXxx) and `ref` — both are client-only for
1120
1159
  // SSR (Hono renders neither; the client JS wires them at hydration).
1121
1160
  if ((p.name.match(/^on[A-Z]/) || p.name === 'ref') && p.value.kind === 'expression') continue
1161
+ if (p.value.kind === 'jsx-children' && p.name !== 'children') {
1162
+ const prevInLoop = this.inLoop
1163
+ this.inLoop = false
1164
+ const slotBody = this.renderChildren(p.value.children)
1165
+ this.inLoop = prevInLoop
1166
+ // Purely counter-based — NOT derived from `p.name` or `comp.slotId`.
1167
+ // A JSX prop name can contain characters (`data-slot`) `bladeIdent`
1168
+ // doesn't sanitize (it only guards reserved words), producing an
1169
+ // invalid PHP variable name; `comp.slotId` alone would also collide
1170
+ // across two named-slot props on the same component invocation
1171
+ // (unlike the reserved children slot, there's only ever one of
1172
+ // those per invocation).
1173
+ const captureVar = bladeVar(`bf_prop_${this.childrenCaptureCounter++}`)
1174
+ namedSlotCaptures.push(
1175
+ `@php(ob_start())\n${slotBody}\n` +
1176
+ `@php(${captureVar} = $bf->backend->mark_raw(preg_replace('/\\n\\z/', '', ob_get_clean(), 1)))`,
1177
+ )
1178
+ currentEntries().push(`${bladeHashKey(p.name)} => ${captureVar}`)
1179
+ continue
1180
+ }
1122
1181
  if (p.value.kind === 'spread') {
1123
1182
  const trimmed = p.value.expr.trim()
1124
1183
  // SolidJS-style props identifier (`function(props: P)`) has no
@@ -1193,6 +1252,7 @@ export class BladeAdapter extends BaseAdapter implements IRNodeEmitter<BladeRend
1193
1252
  currentEntries().push(`${bladeHashKey('children')} => ${captureVar}`)
1194
1253
  const dict = this.combineComponentPropSegments(segments)
1195
1254
  return (
1255
+ namedSlotCaptures.join('') +
1196
1256
  `@php(ob_start())\n${childrenBody}\n` +
1197
1257
  `@php(${captureVar} = $bf->backend->mark_raw(preg_replace('/\\n\\z/', '', ob_get_clean(), 1)))` +
1198
1258
  `{!! $bf->render_child('${tplName}', ${dict}) !!}`
@@ -1201,7 +1261,7 @@ export class BladeAdapter extends BaseAdapter implements IRNodeEmitter<BladeRend
1201
1261
 
1202
1262
  const isEmpty = segments.every(s => s.kind === 'entries' && s.parts.length === 0)
1203
1263
  const dictEntries = isEmpty ? '' : `, ${this.combineComponentPropSegments(segments)}`
1204
- return `{!! $bf->render_child('${tplName}'${dictEntries}) !!}`
1264
+ return `${namedSlotCaptures.join('')}{!! $bf->render_child('${tplName}'${dictEntries}) !!}`
1205
1265
  }
1206
1266
 
1207
1267
  private childrenCaptureCounter = 0
@@ -1291,7 +1351,7 @@ export class BladeAdapter extends BaseAdapter implements IRNodeEmitter<BladeRend
1291
1351
  * AttrValue lowering for intrinsic-element attributes (Blade).
1292
1352
  */
1293
1353
  private readonly elementAttrEmitter: AttrValueEmitter = {
1294
- emitLiteral: (value, name) => `${name}="${value.value}"`,
1354
+ emitLiteral: (value, name) => `${name}="${escapeHtml(value.value)}"`,
1295
1355
  emitExpression: (value, name) => {
1296
1356
  // `style={{ … }}` object literal → a CSS string with dynamic values
1297
1357
  // interpolated, instead of refusing the bare object with BF101 (#1322).
@@ -1497,7 +1557,10 @@ export class BladeAdapter extends BaseAdapter implements IRNodeEmitter<BladeRend
1497
1557
  // Rewrite JSX special-prop names to their HTML-attribute counterparts.
1498
1558
  let attrName: string
1499
1559
  if (attr.name === 'className') attrName = 'class'
1500
- else if (attr.name === 'key') attrName = 'data-key'
1560
+ else if (attr.name === 'key') {
1561
+ const depth = this.currentLoopKeyDepth
1562
+ attrName = depth > 0 ? `data-key-${depth}` : 'data-key'
1563
+ }
1501
1564
  else attrName = attr.name
1502
1565
  const lowered = emitAttrValue(attr.value, this.elementAttrEmitter, attrName)
1503
1566
  if (lowered) parts.push(lowered)
@@ -1659,6 +1722,7 @@ export class BladeAdapter extends BaseAdapter implements IRNodeEmitter<BladeRend
1659
1722
  _resolveModuleStringConst: (name) => this._resolveModuleStringConst(name),
1660
1723
  _resolveLiteralConst: (name) => this._resolveLiteralConst(name),
1661
1724
  _resolveStaticRecordLiteral: (o, k) => this._resolveStaticRecordLiteral(o, k),
1725
+ _isStringValueName: (name) => this._isStringValueName(name),
1662
1726
  _recordExprBF101: (message, reason) => this._recordExprBF101(message, reason),
1663
1727
  _renderBladeFilterExprPublic: (e, p) => this._renderBladeFilterExprPublic(e, p),
1664
1728
  }
@@ -42,6 +42,9 @@ export interface BladeEmitContext {
42
42
  */
43
43
  _resolveStaticRecordLiteral(objectName: string, key: string): string | null
44
44
 
45
+ /** Whether a getter/prop name resolves to a string-typed SSR value. */
46
+ _isStringValueName(name: string): boolean
47
+
45
48
  /** Record a BF101 unsupported-expression diagnostic. */
46
49
  _recordExprBF101(message: string, reason?: string): void
47
50
 
@@ -90,6 +90,15 @@ export function renderArrayMethod(
90
90
  const recv = emit(object)
91
91
  return `$bf->trim(${recv})`
92
92
  }
93
+ case 'trimStart':
94
+ case 'trimEnd': {
95
+ // `.trimStart()` / `.trimEnd()` — the one-sided siblings of
96
+ // `.trim()` (#2183 follow-up). Dedicated `$bf->trim_start` /
97
+ // `$bf->trim_end` helpers, not `$bf->trim` with a flag.
98
+ const fn = method === 'trimStart' ? 'trim_start' : 'trim_end'
99
+ const recv = emit(object)
100
+ return `$bf->${fn}(${recv})`
101
+ }
93
102
  case 'toFixed': {
94
103
  // `.toFixed(digits?)` — `$bf->to_fixed` mirrors JS rounding +
95
104
  // zero-padding (default 0 digits). #1897.
@@ -125,6 +134,16 @@ export function renderArrayMethod(
125
134
  const newS = emit(args[1])
126
135
  return `$bf->replace(${recv}, ${oldS}, ${newS})`
127
136
  }
137
+ case 'replaceAll': {
138
+ // `.replaceAll(old, new)` — string-pattern form, EVERY occurrence,
139
+ // via the dedicated `$bf->replace_all` helper (not `$bf->replace`
140
+ // with a flag) — the regex-pattern form is refused upstream at
141
+ // the parser, same as `.replace`. See #2182.
142
+ const recv = emit(object)
143
+ const oldS = emit(args[0])
144
+ const newS = emit(args[1])
145
+ return `$bf->replace_all(${recv}, ${oldS}, ${newS})`
146
+ }
128
147
  case 'repeat': {
129
148
  const recv = emit(object)
130
149
  const count = args.length === 0 ? '0' : emit(args[0])
@@ -82,7 +82,8 @@
82
82
  * entry point `_renderBladeFilterExprPublic`.
83
83
  */
84
84
 
85
- import {
85
+ import { groupBinaryOperand,
86
+ isStringConcatBinary,
86
87
  type ParsedExprEmitter,
87
88
  type HigherOrderMethod,
88
89
  type ArrayMethod,
@@ -175,7 +176,7 @@ export class BladeFilterEmitter implements ParsedExprEmitter {
175
176
  return String(value)
176
177
  }
177
178
 
178
- member(object: ParsedExpr, property: string, _computed: boolean, emit: (e: ParsedExpr) => string): string {
179
+ member(object: ParsedExpr, property: string, _computed: boolean, _optional: boolean, emit: (e: ParsedExpr) => string): string {
179
180
  // `.length` — route through `$bf->length` (handles both array element
180
181
  // count and string char count, JS-compatibly).
181
182
  if (property === 'length') {
@@ -208,13 +209,22 @@ export class BladeFilterEmitter implements ParsedExprEmitter {
208
209
  }
209
210
 
210
211
  binary(op: string, left: ParsedExpr, right: ParsedExpr, emit: (e: ParsedExpr) => string): string {
211
- const l = emit(left)
212
- const r = emit(right)
212
+ // Preserve source grouping: a compound operand re-emitted as infix
213
+ // text is otherwise re-parsed under THIS language's precedence —
214
+ // `(count() + 2) * 3` would silently become `count + 2 * 3` (#2173).
215
+ const l = groupBinaryOperand(left, emit(left))
216
+ const r = groupBinaryOperand(right, emit(right))
213
217
  // See the file header, divergence 8: PHP's `==`/`!=`/`===`/`!==` are
214
218
  // NEVER emitted for JS `===`/`!==`. `$bf->eq`/`$bf->neq` are the one
215
219
  // shared JS-strict-equality implementation.
216
220
  if (op === '===') return `$bf->eq(${l}, ${r})`
217
221
  if (op === '!==') return `$bf->neq(${l}, ${r})`
222
+ // JS `+` with a string-typed operand is CONCATENATION, not addition —
223
+ // PHP's `+` fatals on non-numeric strings ("Unsupported operand
224
+ // types", #2176). Lower to PHP's `.` concat operator.
225
+ if (isStringConcatBinary(op, left, right, this.isStringName)) {
226
+ return `${l} . ${r}`
227
+ }
218
228
  const opMap: Record<string, string> = {
219
229
  '>': '>', '<': '<', '>=': '>=', '<=': '<=',
220
230
  '+': '+', '-': '-', '*': '*', '/': '/',
@@ -336,7 +346,7 @@ export class BladeTopLevelEmitter implements ParsedExprEmitter {
336
346
  return String(value)
337
347
  }
338
348
 
339
- member(object: ParsedExpr, property: string, _computed: boolean, emit: (e: ParsedExpr) => string): string {
349
+ member(object: ParsedExpr, property: string, _computed: boolean, _optional: boolean, emit: (e: ParsedExpr) => string): string {
340
350
  // `props.x` flattens to the bare context var the SSR caller binds each
341
351
  // prop to (props arrive as individual top-level context entries, not a
342
352
  // nested `props` hash).
@@ -405,12 +415,23 @@ export class BladeTopLevelEmitter implements ParsedExprEmitter {
405
415
  }
406
416
 
407
417
  binary(op: string, left: ParsedExpr, right: ParsedExpr, emit: (e: ParsedExpr) => string): string {
408
- const l = emit(left)
409
- const r = emit(right)
418
+ // Preserve source grouping: a compound operand re-emitted as infix
419
+ // text is otherwise re-parsed under THIS language's precedence —
420
+ // `(count() + 2) * 3` would silently become `count + 2 * 3` (#2173).
421
+ const l = groupBinaryOperand(left, emit(left))
422
+ const r = groupBinaryOperand(right, emit(right))
410
423
  // See the file header, divergence 8: PHP's `==`/`!=`/`===`/`!==` are
411
424
  // NEVER emitted for JS `===`/`!==`.
412
425
  if (op === '===') return `$bf->eq(${l}, ${r})`
413
426
  if (op === '!==') return `$bf->neq(${l}, ${r})`
427
+ // JS `+` with a string-typed operand is CONCATENATION, not addition —
428
+ // PHP's `+` fatals on non-numeric strings ("Unsupported operand
429
+ // types", #2176). Lower to PHP's `.` concat operator. The adapter's
430
+ // string-value registry catches getter/prop operands with no literal
431
+ // present (`firstName() + lastName()`).
432
+ if (isStringConcatBinary(op, left, right, n => this.ctx._isStringValueName(n))) {
433
+ return `${l} . ${r}`
434
+ }
414
435
  const opMap: Record<string, string> = {
415
436
  '>': '>', '<': '<', '>=': '>=', '<=': '<=',
416
437
  '+': '+', '-': '-', '*': '*',
@@ -22,6 +22,9 @@ export const BLADE_TEMPLATE_PRIMITIVES: Record<string, PrimitiveSpec> = {
22
22
  'Math.floor': { arity: 1, emit: (args) => `$bf->floor(${args[0]})` },
23
23
  'Math.ceil': { arity: 1, emit: (args) => `$bf->ceil(${args[0]})` },
24
24
  'Math.round': { arity: 1, emit: (args) => `$bf->round(${args[0]})` },
25
+ 'Math.min': { arity: 2, emit: (args) => `$bf->min(${args[0]}, ${args[1]})` },
26
+ 'Math.max': { arity: 2, emit: (args) => `$bf->max(${args[0]}, ${args[1]})` },
27
+ 'Math.abs': { arity: 1, emit: (args) => `$bf->abs(${args[0]})` },
25
28
  }
26
29
 
27
30
  /**
@@ -89,9 +89,4 @@ export const conformancePins: ConformancePins = {
89
89
  // the shape loudly instead of emitting entity-escaped markup that
90
90
  // silently renders tags as text.
91
91
  'dangerous-inner-html': [{ code: 'BF101', severity: 'error' }],
92
- // Edge-case sweep (Priority 12): `.replaceAll` has no lowering yet —
93
- // only first-occurrence `.replace` is wired to the runtime helpers.
94
- // Refused with BF101 rather than reusing the first-only lowering,
95
- // which would silently change semantics.
96
- 'string-replaceall': [{ code: 'BF101', severity: 'error' }],
97
92
  }
@@ -14,31 +14,4 @@
14
14
 
15
15
  import type { RenderDivergences } from '@barefootjs/jsx'
16
16
 
17
- export const renderDivergences: RenderDivergences = {
18
- 'arithmetic-text':
19
- '`(count() + 2) * 3` renders 10 instead of 18 — the parenthesised sub-expression loses its grouping (silent wrong arithmetic)',
20
- 'string-concat-plus':
21
- '`\'Hello, \' + name` is emitted as PHP `+`, which fatals with "Unsupported operand types: string + string" — needs PHP\'s `.` concat',
22
- 'html-entity-text':
23
- '`&copy;` in JSX literal text: Hono decodes to `©`, this adapter re-emits the raw entity — same DOM, different bytes',
24
- 'math-methods':
25
- 'Math.min/max/abs over a signal render empty (only Math.floor is in the template-primitive registry)',
26
- 'boolean-attr-literals':
27
- 'camelCase boolean alias `readOnly`: Hono SSRs `readOnly="true"`, this adapter emits bare presence',
28
- 'camelcase-attributes':
29
- '`htmlFor` is not lowered to `for` (Hono maps it)',
30
- 'static-attr-escape':
31
- 'static attribute values are not HTML-escaped (`title="Fish & Chips"` emitted raw; Hono escapes)',
32
- 'svg-icon':
33
- 'SVG camelCase presentation attrs (`strokeWidth`, `strokeLinecap`) pass through unmapped; Hono lowers to kebab-case',
34
- 'object-entries-map':
35
- '`Object.entries(prop).map(([k, v]) => …)` renders an EMPTY list — the object-shaped prop silently produces zero iterations',
36
- 'nested-loop-outer-binding':
37
- 'nested-loop inner items carry `data-key` where the reference emits the depth-suffixed `data-key-1`',
38
- 'jsx-element-prop':
39
- 'a JSX element passed as a NON-children prop renders an empty slot — the element value is silently dropped',
40
- 'string-slice':
41
- '`.slice()` on a STRING renders empty (array-slice helper misfires on strings)',
42
- 'string-trim-sided':
43
- '`.trimStart()` / `.trimEnd()` render empty (no lowering)',
44
- }
17
+ export const renderDivergences: RenderDivergences = {}