@barefootjs/jinja 0.31.4 → 0.31.6

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.
@@ -187314,8 +187314,8 @@ import {
187314
187314
  dangerousInnerHtmlMetacharViolation,
187315
187315
  dangerousInnerHtmlDiagnostic,
187316
187316
  resolveStaticLoopSource,
187317
- collectLoopBoundNames,
187318
- derivesScopeFromSlot
187317
+ derivesScopeFromSlot,
187318
+ BindingScope
187319
187319
  } from "@barefootjs/jsx";
187320
187320
 
187321
187321
  // src/adapter/boolean-result.ts
@@ -188320,8 +188320,7 @@ class JinjaAdapter extends BaseAdapter {
188320
188320
  _searchParamsLocals = new Set;
188321
188321
  _loweringMatchers = [];
188322
188322
  localConstants = [];
188323
- staticLoopSourceBoundNames = new Set;
188324
- loopBoundNames = new Map;
188323
+ scope = BindingScope.EMPTY;
188325
188324
  nullableOptionalProps = new Set;
188326
188325
  constructor(options = {}) {
188327
188326
  super();
@@ -188337,8 +188336,7 @@ class JinjaAdapter extends BaseAdapter {
188337
188336
  this.propsParams = ir.metadata.propsParams.map((p) => ({ name: p.name }));
188338
188337
  this.booleanTypedProps = collectBooleanTypedProps(ir);
188339
188338
  this.localConstants = ir.metadata.localConstants ?? [];
188340
- this.staticLoopSourceBoundNames = collectLoopBoundNames(ir);
188341
- this.loopBoundNames.clear();
188339
+ this.scope = BindingScope.EMPTY;
188342
188340
  this.nullableOptionalProps = collectNullableOptionalProps(ir);
188343
188341
  this.stringValueNames = collectStringValueNames(ir);
188344
188342
  this.moduleStringConsts = collectModuleStringConsts(ir.metadata.localConstants);
@@ -188633,7 +188631,7 @@ ${whenTrue}
188633
188631
  });
188634
188632
  }
188635
188633
  const staticItems = resolveStaticLoopSource(loop.arrayParsed, this.localConstants, {
188636
- isNameShadowed: (name) => this.staticLoopSourceBoundNames.has(name)
188634
+ isNameShadowed: this.scope.asShadowPredicate()
188637
188635
  });
188638
188636
  const staticArray = staticItems !== null ? staticValueToJinja(staticItems) : null;
188639
188637
  const arrayName = loop.array.trim();
@@ -188646,7 +188644,8 @@ ${whenTrue}
188646
188644
  message: `Loop array \`${arrayName}\` is a local computed value (\`${arrayConst.value}\`) that the Jinja adapter cannot bind as a template variable — only numeric/string-literal locals inline at their use site.`,
188647
188645
  loc: loop.loc ?? { file: this.componentName + ".tsx", start: { line: 1, column: 0 }, end: { line: 1, column: 0 } },
188648
188646
  suggestion: {
188649
- message: "Pre-compute the array server-side and pass it as a prop, or mark the loop position as @client-only so it runs in JS on the client."
188647
+ message: "Pre-compute the array server-side and pass it as a prop, or mark the loop position as @client-only so it runs in JS on the client.",
188648
+ escape: [{ kind: "prop-precompute" }, { kind: "client-directive" }]
188650
188649
  }
188651
188650
  });
188652
188651
  }
@@ -188687,40 +188686,15 @@ ${whenTrue}
188687
188686
  this.inLoop = true;
188688
188687
  const prevLoopKeyDepth = this.currentLoopKeyDepth;
188689
188688
  this.currentLoopKeyDepth = loop.depth;
188689
+ const prevScope = this.scope;
188690
+ this.scope = prevScope.enterLoopRow(loop);
188690
188691
  const preambleLines = (loop.preamble?.declarations ?? []).map((d) => `{% set ${jinjaIdent(d.name)} = ${this.convertExpressionToJinja(d.raw, d.valueParsed)} %}`);
188691
- const loopBound = [];
188692
- if (loop.objectIteration === "entries") {
188693
- loopBound.push(loop.index ?? param, param);
188694
- } else if (loop.objectIteration === "keys" || loop.objectIteration === "values") {
188695
- loopBound.push(param);
188696
- } else if (loop.iterationShape === "keys") {
188697
- loopBound.push("__bf_item", param);
188698
- } else if (supportableDestructure) {
188699
- loopBound.push("__bf_item", ...(loop.paramBindings ?? []).map((b) => b.name));
188700
- if (loop.index)
188701
- loopBound.push(loop.index);
188702
- } else {
188703
- loopBound.push(param);
188704
- if (loop.index)
188705
- loopBound.push(loop.index);
188706
- }
188707
- for (const d of loop.preamble?.declarations ?? [])
188708
- loopBound.push(d.name);
188709
- for (const n of loopBound) {
188710
- this.loopBoundNames.set(n, (this.loopBoundNames.get(n) ?? 0) + 1);
188711
- }
188712
188692
  const childrenUnderLoop = this.renderChildren(loop.children);
188713
- for (const n of loopBound) {
188714
- const c = (this.loopBoundNames.get(n) ?? 1) - 1;
188715
- if (c <= 0)
188716
- this.loopBoundNames.delete(n);
188717
- else
188718
- this.loopBoundNames.set(n, c);
188719
- }
188720
188693
  this.currentLoopKeyDepth = prevLoopKeyDepth;
188721
188694
  this.inLoop = prevInLoop;
188722
188695
  const bodyChildren = loop.bodyIsItemConditional && loop.key ? `{{ bf.comment("loop-i:" ~ bf.string(${this.convertExpressionToJinja(loop.key)})) | safe }}
188723
188696
  ${childrenUnderLoop}` : childrenUnderLoop;
188697
+ this.scope = prevScope;
188724
188698
  const lines = [];
188725
188699
  lines.push(`{{ bf.comment("loop:${loop.markerId}") | safe }}`);
188726
188700
  const forHeader = loop.objectIteration === "entries" ? `{% for ${jinjaIdent(loop.index ?? param)}, ${jinjaIdent(param)} in ${array}.items() %}` : loop.objectIteration === "keys" ? `{% for ${jinjaIdent(param)} in ${array}.keys() %}` : loop.objectIteration === "values" ? `{% for ${jinjaIdent(param)} in ${array}.values() %}` : `{% for ${jinjaIdent(loopVar)} in ${array} %}`;
@@ -188952,7 +188926,7 @@ ${name}="{{ bf.string(${val}) }}"
188952
188926
  if (ternaryDict !== null) {
188953
188927
  return `{{ bf.spread_attrs(${ternaryDict}) | safe }}`;
188954
188928
  }
188955
- if (/^[A-Za-z_$][\w$]*$/.test(trimmed) && !this.loopBoundNames.has(trimmed)) {
188929
+ if (/^[A-Za-z_$][\w$]*$/.test(trimmed) && !this.scope.isBound(trimmed)) {
188956
188930
  const localConst = (this.localConstants ?? []).find((c) => c.name === trimmed && !c.isModule);
188957
188931
  if (localConst?.value !== undefined) {
188958
188932
  const initTrimmed = localConst.value.trim();
@@ -189187,7 +189161,7 @@ Options:
189187
189161
  return this.booleanTypedProps.has(bare);
189188
189162
  }
189189
189163
  isLoopBoundName(name) {
189190
- return this.loopBoundNames.has(name);
189164
+ return this.scope.isBound(name);
189191
189165
  }
189192
189166
  shouldBoolStr(expr, name) {
189193
189167
  if (isExplicitStringCall(expr))
@@ -189195,7 +189169,7 @@ Options:
189195
189169
  return isBooleanResultExpr(expr) || isAriaBooleanAttr(name) || this.isBooleanTypedPropRef(expr);
189196
189170
  }
189197
189171
  _resolveLiteralConst(name) {
189198
- if (this.staticLoopSourceBoundNames.has(name))
189172
+ if (this.scope.isBound(name))
189199
189173
  return null;
189200
189174
  const c = (this.localConstants ?? []).find((lc) => lc.name === name);
189201
189175
  if (c?.value === undefined)
@@ -189209,9 +189183,7 @@ Options:
189209
189183
  return null;
189210
189184
  }
189211
189185
  _resolveStaticRecordLiteral(objectName, key) {
189212
- if (this.staticLoopSourceBoundNames.has(objectName))
189213
- return null;
189214
- const hit = lookupStaticRecordLiteral(objectName, key, this.localConstants);
189186
+ const hit = lookupStaticRecordLiteral(objectName, key, this.localConstants, (name) => this.scope.isBound(name));
189215
189187
  if (!hit)
189216
189188
  return null;
189217
189189
  return hit.kind === "number" ? hit.text : `'${escapeJinjaSingleQuoted(hit.text)}'`;
@@ -168,29 +168,24 @@ export declare class JinjaAdapter extends BaseAdapter implements IRNodeEmitter<J
168
168
  */
169
169
  private localConstants;
170
170
  /**
171
- * Every name a `.map()`/`.filter()` loop callback binds as its item/index
172
- * parameter anywhere in the component (#2208 fable review). A static
173
- * loop-SOURCE name (e.g. a function-scope `const items = [...]`) must
174
- * never resolve through `resolveStaticLoopSource` at a use site where a
175
- * DIFFERENT, enclosing loop's own callback param shadows it — same
176
- * shadowing hazard, and same coarse-but-safe mitigation, as #2212's
177
- * `collectLoopBoundNames` use in `collectStringValueNames`.
178
- */
179
- private staticLoopSourceBoundNames;
180
- /**
181
- * Names currently bound by an enclosing loop body — the block-param
182
- * locals `renderLoop` introduces (item, index, per-binding destructure
183
- * fields, `.map()` preamble declarations) — ref-counted so nested loops
184
- * compose. This is the POSITION-ACCURATE twin of the coarse
185
- * `staticLoopSourceBoundNames` above: that set is a whole-component
186
- * union used only to guard static-const inlining (safe to over-suppress
187
- * there — the fallback is just "don't inline"), whereas the boolean-prop
188
- * and nullable-optional classification sites (#2488) and `emitSpread`'s
189
- * local-const fallback (#2489) need to know whether a name is loop-bound
190
- * AT THIS POSITION, because for those the coarse fallback would silently
191
- * mis-render a genuine occurrence of the same name outside the loop too.
192
- */
193
- private loopBoundNames;
171
+ * The one canonical, position-accurate "names bound by an enclosing loop
172
+ * callback" service (#2482 Stage 2) replaces the two ad-hoc devices
173
+ * this adapter used to carry side by side: a coarse whole-component
174
+ * shadow-name Set (built once at `generate()` entry, used only to guard
175
+ * static-const inlining) and a ref-counted, position-accurate live map
176
+ * (pushed/popped around `renderLoop`'s body, used for the boolean-prop/
177
+ * nullable-optional classification sites (#2488) and `emitSpread`'s
178
+ * local-const fallback (#2489)). Both consulted the "is this name
179
+ * loop-bound" question with DIFFERENT meanings — the coarse/live drift
180
+ * #2482 Stage 2 ends. Every shadow-guard site now reads this ONE
181
+ * threaded, immutable scope: `enterLoopRow`/pop-by-reference around
182
+ * `renderChildren(loop.children)` in `renderLoop`, mirroring the Stage
183
+ * 1a/1b `ctx.scope` precedent in `jsx-to-ir.ts`. `IRLoop` already
184
+ * structurally satisfies `LoopBindingSource`
185
+ * (`param`/`index`/`paramBindings`/`preamble`), so `renderLoop` passes
186
+ * the loop node straight to `enterLoopRow`.
187
+ */
188
+ private scope;
194
189
  /**
195
190
  * Optional, no-default props that are `None` when the caller omits them.
196
191
  * Their bare-reference attribute emission is guarded with a Jinja
@@ -403,7 +398,7 @@ export declare class JinjaAdapter extends BaseAdapter implements IRNodeEmitter<J
403
398
  consequent: string;
404
399
  } | null;
405
400
  isBooleanTypedPropRef(expr: string): boolean;
406
- /** Position-accurate loop-bound-name check — see `loopBoundNames`'s docstring. */
401
+ /** Position-accurate loop-bound-name check — see `this.scope`'s docstring. */
407
402
  private isLoopBoundName;
408
403
  /**
409
404
  * Whether an attribute-value expression should route through
@@ -425,14 +420,13 @@ export declare class JinjaAdapter extends BaseAdapter implements IRNodeEmitter<J
425
420
  * context, so a bare reference would resolve to Undefined.
426
421
  *
427
422
  * The lookup is a flat name match with no notion of AST scope, so a
428
- * name that any loop callback binds as its item/index param never
429
- * inlines (#2221) — the occurrence may be the loop's own (shadowing)
430
- * binding, and substituting the outer const's value there renders every
431
- * iteration with the same hard-coded literal. Coarse (a genuinely
432
- * non-shadowed same-named const elsewhere in the component also stops
433
- * inlining, falling back to the bare identifier) but safe — the same
434
- * trade-off as #2212's `collectLoopBoundNames` use in
435
- * `collectStringValueNames`.
423
+ * name bound by the CURRENTLY ENCLOSING loop's item/index/destructure/
424
+ * preamble param never inlines (#2221) — the occurrence may be the
425
+ * loop's own (shadowing) binding, and substituting the outer const's
426
+ * value there renders every iteration with the same hard-coded literal.
427
+ * Position-accurate via the threaded `this.scope` (#2482 Stage 2) — a
428
+ * same-named const elsewhere in the component, outside any loop that
429
+ * shadows it, still inlines.
436
430
  */
437
431
  private _resolveLiteralConst;
438
432
  /**
@@ -443,11 +437,13 @@ export declare class JinjaAdapter extends BaseAdapter implements IRNodeEmitter<J
443
437
  * scope, so an enclosing loop callback's own param of the same name
444
438
  * (`.map((cfg) => <li>{cfg.x}</li>)` shadowing a module `const cfg = {…}`)
445
439
  * still resolved to the OUTER const's member value at every iteration
446
- * (#2237) — the sibling hazard to #2221's `_resolveLiteralConst`. Same
447
- * coarse-but-safe `staticLoopSourceBoundNames` guard: any name a loop
448
- * binds anywhere in the component never inlines, falling back to the bare
440
+ * (#2237) — the sibling hazard to #2221's `_resolveLiteralConst`.
441
+ * Position-accurate via the threaded `this.scope` (#2482 Stage 2), passed
442
+ * as `lookupStaticRecordLiteral`'s required guard: a name the CURRENTLY
443
+ * ENCLOSING loop binds never inlines, falling back to the bare
449
444
  * `cfg['x']` member expression (which a Jinja for-loop binds correctly
450
- * at the shadowed occurrences).
445
+ * at the shadowed occurrence); a same-named const elsewhere, outside any
446
+ * loop that shadows it, still inlines.
451
447
  */
452
448
  private _resolveStaticRecordLiteral;
453
449
  private _resolveModuleStringConst;
@@ -1 +1 @@
1
- {"version":3,"file":"jinja-adapter.d.ts","sourceRoot":"","sources":["../../src/adapter/jinja-adapter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"jinja-adapter.d.ts","sourceRoot":"","sources":["../../src/adapter/jinja-adapter.ts"],"names":[],"mappings":"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"}
@@ -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,eAyI7B,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,eAkJ7B,CAAA"}
package/dist/index.js CHANGED
@@ -187314,8 +187314,8 @@ import {
187314
187314
  dangerousInnerHtmlMetacharViolation,
187315
187315
  dangerousInnerHtmlDiagnostic,
187316
187316
  resolveStaticLoopSource,
187317
- collectLoopBoundNames,
187318
- derivesScopeFromSlot
187317
+ derivesScopeFromSlot,
187318
+ BindingScope
187319
187319
  } from "@barefootjs/jsx";
187320
187320
 
187321
187321
  // src/adapter/boolean-result.ts
@@ -188320,8 +188320,7 @@ class JinjaAdapter extends BaseAdapter {
188320
188320
  _searchParamsLocals = new Set;
188321
188321
  _loweringMatchers = [];
188322
188322
  localConstants = [];
188323
- staticLoopSourceBoundNames = new Set;
188324
- loopBoundNames = new Map;
188323
+ scope = BindingScope.EMPTY;
188325
188324
  nullableOptionalProps = new Set;
188326
188325
  constructor(options = {}) {
188327
188326
  super();
@@ -188337,8 +188336,7 @@ class JinjaAdapter extends BaseAdapter {
188337
188336
  this.propsParams = ir.metadata.propsParams.map((p) => ({ name: p.name }));
188338
188337
  this.booleanTypedProps = collectBooleanTypedProps(ir);
188339
188338
  this.localConstants = ir.metadata.localConstants ?? [];
188340
- this.staticLoopSourceBoundNames = collectLoopBoundNames(ir);
188341
- this.loopBoundNames.clear();
188339
+ this.scope = BindingScope.EMPTY;
188342
188340
  this.nullableOptionalProps = collectNullableOptionalProps(ir);
188343
188341
  this.stringValueNames = collectStringValueNames(ir);
188344
188342
  this.moduleStringConsts = collectModuleStringConsts(ir.metadata.localConstants);
@@ -188633,7 +188631,7 @@ ${whenTrue}
188633
188631
  });
188634
188632
  }
188635
188633
  const staticItems = resolveStaticLoopSource(loop.arrayParsed, this.localConstants, {
188636
- isNameShadowed: (name) => this.staticLoopSourceBoundNames.has(name)
188634
+ isNameShadowed: this.scope.asShadowPredicate()
188637
188635
  });
188638
188636
  const staticArray = staticItems !== null ? staticValueToJinja(staticItems) : null;
188639
188637
  const arrayName = loop.array.trim();
@@ -188646,7 +188644,8 @@ ${whenTrue}
188646
188644
  message: `Loop array \`${arrayName}\` is a local computed value (\`${arrayConst.value}\`) that the Jinja adapter cannot bind as a template variable — only numeric/string-literal locals inline at their use site.`,
188647
188645
  loc: loop.loc ?? { file: this.componentName + ".tsx", start: { line: 1, column: 0 }, end: { line: 1, column: 0 } },
188648
188646
  suggestion: {
188649
- message: "Pre-compute the array server-side and pass it as a prop, or mark the loop position as @client-only so it runs in JS on the client."
188647
+ message: "Pre-compute the array server-side and pass it as a prop, or mark the loop position as @client-only so it runs in JS on the client.",
188648
+ escape: [{ kind: "prop-precompute" }, { kind: "client-directive" }]
188650
188649
  }
188651
188650
  });
188652
188651
  }
@@ -188687,40 +188686,15 @@ ${whenTrue}
188687
188686
  this.inLoop = true;
188688
188687
  const prevLoopKeyDepth = this.currentLoopKeyDepth;
188689
188688
  this.currentLoopKeyDepth = loop.depth;
188689
+ const prevScope = this.scope;
188690
+ this.scope = prevScope.enterLoopRow(loop);
188690
188691
  const preambleLines = (loop.preamble?.declarations ?? []).map((d) => `{% set ${jinjaIdent(d.name)} = ${this.convertExpressionToJinja(d.raw, d.valueParsed)} %}`);
188691
- const loopBound = [];
188692
- if (loop.objectIteration === "entries") {
188693
- loopBound.push(loop.index ?? param, param);
188694
- } else if (loop.objectIteration === "keys" || loop.objectIteration === "values") {
188695
- loopBound.push(param);
188696
- } else if (loop.iterationShape === "keys") {
188697
- loopBound.push("__bf_item", param);
188698
- } else if (supportableDestructure) {
188699
- loopBound.push("__bf_item", ...(loop.paramBindings ?? []).map((b) => b.name));
188700
- if (loop.index)
188701
- loopBound.push(loop.index);
188702
- } else {
188703
- loopBound.push(param);
188704
- if (loop.index)
188705
- loopBound.push(loop.index);
188706
- }
188707
- for (const d of loop.preamble?.declarations ?? [])
188708
- loopBound.push(d.name);
188709
- for (const n of loopBound) {
188710
- this.loopBoundNames.set(n, (this.loopBoundNames.get(n) ?? 0) + 1);
188711
- }
188712
188692
  const childrenUnderLoop = this.renderChildren(loop.children);
188713
- for (const n of loopBound) {
188714
- const c = (this.loopBoundNames.get(n) ?? 1) - 1;
188715
- if (c <= 0)
188716
- this.loopBoundNames.delete(n);
188717
- else
188718
- this.loopBoundNames.set(n, c);
188719
- }
188720
188693
  this.currentLoopKeyDepth = prevLoopKeyDepth;
188721
188694
  this.inLoop = prevInLoop;
188722
188695
  const bodyChildren = loop.bodyIsItemConditional && loop.key ? `{{ bf.comment("loop-i:" ~ bf.string(${this.convertExpressionToJinja(loop.key)})) | safe }}
188723
188696
  ${childrenUnderLoop}` : childrenUnderLoop;
188697
+ this.scope = prevScope;
188724
188698
  const lines = [];
188725
188699
  lines.push(`{{ bf.comment("loop:${loop.markerId}") | safe }}`);
188726
188700
  const forHeader = loop.objectIteration === "entries" ? `{% for ${jinjaIdent(loop.index ?? param)}, ${jinjaIdent(param)} in ${array}.items() %}` : loop.objectIteration === "keys" ? `{% for ${jinjaIdent(param)} in ${array}.keys() %}` : loop.objectIteration === "values" ? `{% for ${jinjaIdent(param)} in ${array}.values() %}` : `{% for ${jinjaIdent(loopVar)} in ${array} %}`;
@@ -188952,7 +188926,7 @@ ${name}="{{ bf.string(${val}) }}"
188952
188926
  if (ternaryDict !== null) {
188953
188927
  return `{{ bf.spread_attrs(${ternaryDict}) | safe }}`;
188954
188928
  }
188955
- if (/^[A-Za-z_$][\w$]*$/.test(trimmed) && !this.loopBoundNames.has(trimmed)) {
188929
+ if (/^[A-Za-z_$][\w$]*$/.test(trimmed) && !this.scope.isBound(trimmed)) {
188956
188930
  const localConst = (this.localConstants ?? []).find((c) => c.name === trimmed && !c.isModule);
188957
188931
  if (localConst?.value !== undefined) {
188958
188932
  const initTrimmed = localConst.value.trim();
@@ -189187,7 +189161,7 @@ Options:
189187
189161
  return this.booleanTypedProps.has(bare);
189188
189162
  }
189189
189163
  isLoopBoundName(name) {
189190
- return this.loopBoundNames.has(name);
189164
+ return this.scope.isBound(name);
189191
189165
  }
189192
189166
  shouldBoolStr(expr, name) {
189193
189167
  if (isExplicitStringCall(expr))
@@ -189195,7 +189169,7 @@ Options:
189195
189169
  return isBooleanResultExpr(expr) || isAriaBooleanAttr(name) || this.isBooleanTypedPropRef(expr);
189196
189170
  }
189197
189171
  _resolveLiteralConst(name) {
189198
- if (this.staticLoopSourceBoundNames.has(name))
189172
+ if (this.scope.isBound(name))
189199
189173
  return null;
189200
189174
  const c = (this.localConstants ?? []).find((lc) => lc.name === name);
189201
189175
  if (c?.value === undefined)
@@ -189209,9 +189183,7 @@ Options:
189209
189183
  return null;
189210
189184
  }
189211
189185
  _resolveStaticRecordLiteral(objectName, key) {
189212
- if (this.staticLoopSourceBoundNames.has(objectName))
189213
- return null;
189214
- const hit = lookupStaticRecordLiteral(objectName, key, this.localConstants);
189186
+ const hit = lookupStaticRecordLiteral(objectName, key, this.localConstants, (name) => this.scope.isBound(name));
189215
189187
  if (!hit)
189216
189188
  return null;
189217
189189
  return hit.kind === "number" ? hit.text : `'${escapeJinjaSingleQuoted(hit.text)}'`;
@@ -189261,17 +189233,23 @@ var conformancePins = {
189261
189233
  "tag-cloud": [{ code: "BF021", severity: "error" }],
189262
189234
  "preamble-cells": [{ code: "BF021", severity: "error" }],
189263
189235
  "static-array-from-props": [
189264
- { code: "BF101", severity: "error", issue: "https://github.com/piconic-ai/barefootjs/issues/2321" }
189236
+ {
189237
+ code: "BF101",
189238
+ severity: "error",
189239
+ issue: "https://github.com/piconic-ai/barefootjs/issues/2321"
189240
+ }
189265
189241
  ],
189266
189242
  "static-array-from-props-with-component": [
189267
- { code: "BF101", severity: "error", issue: "https://github.com/piconic-ai/barefootjs/issues/2321" }
189243
+ {
189244
+ code: "BF101",
189245
+ severity: "error",
189246
+ issue: "https://github.com/piconic-ai/barefootjs/issues/2321"
189247
+ }
189268
189248
  ],
189269
189249
  "filter-nested-callback-predicate": [
189270
189250
  { code: "BF101", severity: "error", issue: "https://github.com/piconic-ai/barefootjs/issues/2320" }
189271
189251
  ],
189272
- "filter-nested-find-predicate": [
189273
- { code: "BF101", severity: "error", issue: "https://github.com/piconic-ai/barefootjs/issues/2320" }
189274
- ],
189252
+ "filter-nested-find-predicate": [{ code: "BF101", severity: "error", issue: "https://github.com/piconic-ai/barefootjs/issues/2320" }],
189275
189253
  "date-method-uncatalogued": [{ code: "BF021", severity: "error", issue: "https://github.com/piconic-ai/barefootjs/issues/2356" }]
189276
189254
  };
189277
189255
  // src/render-divergences.ts