@barefootjs/erb 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.
- package/dist/adapter/erb-adapter.d.ts +26 -11
- package/dist/adapter/erb-adapter.d.ts.map +1 -1
- package/dist/adapter/index.js +20 -38
- package/dist/conformance-pins.d.ts.map +1 -1
- package/dist/index.js +31 -43
- package/dist/vite.js +151 -122
- package/package.json +5 -5
- package/src/adapter/erb-adapter.ts +66 -62
- package/src/adapter/expr/emitters.ts +5 -5
- package/src/conformance-pins.ts +14 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@barefootjs/erb",
|
|
3
|
-
"version": "0.31.
|
|
3
|
+
"version": "0.31.6",
|
|
4
4
|
"description": "ERB (Embedded Ruby) adapter for BarefootJS — compiles IR to .erb templates and ships the Ruby rendering backend; runs under any Rack app (Sinatra, Rails)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"directory": "packages/adapter-erb"
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
|
-
"@barefootjs/shared": "0.31.
|
|
57
|
+
"@barefootjs/shared": "0.31.6"
|
|
58
58
|
},
|
|
59
59
|
"peerDependencies": {
|
|
60
60
|
"@barefootjs/jsx": ">=0.2.0",
|
|
@@ -71,9 +71,9 @@
|
|
|
71
71
|
},
|
|
72
72
|
"devDependencies": {
|
|
73
73
|
"@barefootjs/adapter-tests": "0.1.0",
|
|
74
|
-
"@barefootjs/jsx": "0.31.
|
|
75
|
-
"@barefootjs/vite": "0.31.
|
|
76
|
-
"@barefootjs/client": "0.31.
|
|
74
|
+
"@barefootjs/jsx": "0.31.6",
|
|
75
|
+
"@barefootjs/vite": "0.31.6",
|
|
76
|
+
"@barefootjs/client": "0.31.6",
|
|
77
77
|
"typescript": "^5.0.0",
|
|
78
78
|
"vite": "^6.0.0"
|
|
79
79
|
}
|
|
@@ -94,9 +94,10 @@ import {
|
|
|
94
94
|
dangerousInnerHtmlDiagnostic,
|
|
95
95
|
resolveStaticLoopSource,
|
|
96
96
|
derivesScopeFromSlot,
|
|
97
|
+
BindingScope,
|
|
97
98
|
} from '@barefootjs/jsx'
|
|
98
99
|
import { isAriaBooleanAttr, isBooleanResultExpr, isExplicitStringCall } from './boolean-result.ts'
|
|
99
|
-
import type { ParsedExpr, LoweringMatcher, LoopBindingPathSegment } from '@barefootjs/jsx'
|
|
100
|
+
import type { ParsedExpr, LoweringMatcher, LoopBindingPathSegment, EscapeKind } from '@barefootjs/jsx'
|
|
100
101
|
import { BF_SLOT, BF_COND, BF_REGION, escapeHtml } from '@barefootjs/shared'
|
|
101
102
|
|
|
102
103
|
import type { ErbRenderCtx } from './lib/types.ts'
|
|
@@ -248,17 +249,23 @@ export class ErbAdapter extends BaseAdapter implements IRNodeEmitter<ErbRenderCt
|
|
|
248
249
|
*/
|
|
249
250
|
private localConstants: IRMetadata['localConstants'] = []
|
|
250
251
|
/**
|
|
251
|
-
*
|
|
252
|
-
*
|
|
253
|
-
*
|
|
254
|
-
* for TWO things in the ERB adapter
|
|
255
|
-
* only used it to guard
|
|
256
|
-
* fundamental `v[:name]` vs
|
|
257
|
-
* `ErbTopLevelEmitter.identifier` —
|
|
258
|
-
* `isLoopBoundName` docstring for why ERB's
|
|
259
|
-
* where Perl's uniform `$name` sigil does
|
|
252
|
+
* The one canonical, position-accurate "names bound by an enclosing loop
|
|
253
|
+
* callback" service (#2482 Stage 2) — replaces the ref-counted
|
|
254
|
+
* `Map<string, number>` this adapter used to push/pop around
|
|
255
|
+
* `renderLoop`'s body. Load-bearing for TWO things in the ERB adapter
|
|
256
|
+
* (more than the Mojo original, which only used it to guard
|
|
257
|
+
* const-inlining): it also decides the fundamental `v[:name]` vs
|
|
258
|
+
* bare-Ruby-local rendering choice in `ErbTopLevelEmitter.identifier` —
|
|
259
|
+
* see `emit-context.ts`'s `isLoopBoundName` docstring for why ERB's
|
|
260
|
+
* two-locals model needs this where Perl's uniform `$name` sigil does
|
|
261
|
+
* not. Threaded via save/restore-by-reference around
|
|
262
|
+
* `renderChildren(loop.children)` in `renderLoop` (immutable — no
|
|
263
|
+
* ref-count bookkeeping), mirroring the Stage 1a/1b `ctx.scope`
|
|
264
|
+
* precedent in `jsx-to-ir.ts`. `IRLoop` already structurally satisfies
|
|
265
|
+
* `LoopBindingSource` (`param`/`index`/`paramBindings`/`preamble`), so
|
|
266
|
+
* `renderLoop` passes the loop node straight to `enterLoopRow`.
|
|
260
267
|
*/
|
|
261
|
-
private
|
|
268
|
+
private scope: BindingScope = BindingScope.EMPTY
|
|
262
269
|
/**
|
|
263
270
|
* Prop names whose value is `nil` in the template body when the caller
|
|
264
271
|
* omits them — so a bare-reference attribute should be dropped rather
|
|
@@ -298,7 +305,7 @@ export class ErbAdapter extends BaseAdapter implements IRNodeEmitter<ErbRenderCt
|
|
|
298
305
|
this._searchParamsLocals = searchParamsLocalNames(ir.metadata)
|
|
299
306
|
this._loweringMatchers = prepareLoweringMatchers(ir.metadata)
|
|
300
307
|
this.localConstants = ir.metadata.localConstants ?? []
|
|
301
|
-
this.
|
|
308
|
+
this.scope = BindingScope.EMPTY
|
|
302
309
|
this.errors = []
|
|
303
310
|
this.childrenCaptureCounter = 0
|
|
304
311
|
|
|
@@ -440,7 +447,7 @@ export class ErbAdapter extends BaseAdapter implements IRNodeEmitter<ErbRenderCt
|
|
|
440
447
|
* would read nil.
|
|
441
448
|
*/
|
|
442
449
|
private resolveLiteralConst(name: string): string | null {
|
|
443
|
-
if (this.
|
|
450
|
+
if (this.scope.isBound(name)) return null
|
|
444
451
|
const c = (this.localConstants ?? []).find(lc => lc.name === name)
|
|
445
452
|
if (c?.value === undefined) return null
|
|
446
453
|
const v = c.value.trim()
|
|
@@ -451,8 +458,7 @@ export class ErbAdapter extends BaseAdapter implements IRNodeEmitter<ErbRenderCt
|
|
|
451
458
|
}
|
|
452
459
|
|
|
453
460
|
private resolveStaticRecordLiteral(objectName: string, key: string): string | null {
|
|
454
|
-
|
|
455
|
-
const hit = lookupStaticRecordLiteral(objectName, key, this.localConstants)
|
|
461
|
+
const hit = lookupStaticRecordLiteral(objectName, key, this.localConstants, name => this.scope.isBound(name))
|
|
456
462
|
if (!hit) return null
|
|
457
463
|
return hit.kind === 'number' ? hit.text : rubyStringLiteral(hit.text)
|
|
458
464
|
}
|
|
@@ -460,7 +466,7 @@ export class ErbAdapter extends BaseAdapter implements IRNodeEmitter<ErbRenderCt
|
|
|
460
466
|
private resolveModuleStringConst(name: string): string | null {
|
|
461
467
|
// A loop body introduces block-param bindings that shadow a module
|
|
462
468
|
// const of the same name — never inline inside one.
|
|
463
|
-
if (this.
|
|
469
|
+
if (this.scope.isBound(name)) return null
|
|
464
470
|
const value = this.moduleStringConsts.get(name)
|
|
465
471
|
if (value === undefined) return null
|
|
466
472
|
return rubyStringLiteral(value)
|
|
@@ -469,7 +475,7 @@ export class ErbAdapter extends BaseAdapter implements IRNodeEmitter<ErbRenderCt
|
|
|
469
475
|
/** Whether `name` currently names a loop-bound Ruby local. See
|
|
470
476
|
* `ErbEmitContext.isLoopBoundName`'s docstring. */
|
|
471
477
|
private isLoopBoundName(name: string): boolean {
|
|
472
|
-
return this.
|
|
478
|
+
return this.scope.isBound(name)
|
|
473
479
|
}
|
|
474
480
|
|
|
475
481
|
// ===========================================================================
|
|
@@ -957,15 +963,17 @@ export class ErbAdapter extends BaseAdapter implements IRNodeEmitter<ErbRenderCt
|
|
|
957
963
|
// `unsupported` object-literal path (BF101, "Expression not
|
|
958
964
|
// supported"), which is what this loop-specific check now also does
|
|
959
965
|
// deliberately, up front, for both shapes.
|
|
966
|
+
// Canonical, position-accurate predicate (#2482 Stage 2) — the
|
|
967
|
+
// enclosing loop scope's own membership.
|
|
960
968
|
const staticItems = resolveStaticLoopSource(loop.arrayParsed, this.localConstants, {
|
|
961
|
-
isNameShadowed:
|
|
969
|
+
isNameShadowed: this.scope.asShadowPredicate(),
|
|
962
970
|
})
|
|
963
971
|
const staticArray = staticItems !== null ? staticValueToRuby(staticItems) : null
|
|
964
972
|
|
|
965
973
|
if (staticArray === null && loop.arrayParsed?.kind === 'identifier') {
|
|
966
974
|
const arrayName = loop.arrayParsed.name
|
|
967
975
|
const isUnresolvableLocalConst =
|
|
968
|
-
!this.
|
|
976
|
+
!this.scope.isBound(arrayName) &&
|
|
969
977
|
this.resolveModuleStringConst(arrayName) === null &&
|
|
970
978
|
this.resolveLiteralConst(arrayName) === null &&
|
|
971
979
|
this.localConstants.some(c => c.name === arrayName && !c.isModule)
|
|
@@ -973,6 +981,7 @@ export class ErbAdapter extends BaseAdapter implements IRNodeEmitter<ErbRenderCt
|
|
|
973
981
|
this._recordExprBF101(
|
|
974
982
|
`Loop array \`${arrayName}\` is a component-scope const computed from a runtime expression the ERB adapter cannot evaluate at SSR render time.`,
|
|
975
983
|
`Options:\n1. Inline the array expression directly in the .map() call instead of a preceding const.\n2. Mark the loop position as @client-only so the array materialises on the client.\n3. Precompute the value server-side and pass it in as a prop.`,
|
|
984
|
+
[{ kind: 'prop-precompute' }, { kind: 'client-directive' }],
|
|
976
985
|
)
|
|
977
986
|
}
|
|
978
987
|
}
|
|
@@ -994,29 +1003,22 @@ export class ErbAdapter extends BaseAdapter implements IRNodeEmitter<ErbRenderCt
|
|
|
994
1003
|
const indexVar = loop.iterationShape === 'keys'
|
|
995
1004
|
? rubyLocal(param)
|
|
996
1005
|
: rubyLocal(loop.index ?? '_i')
|
|
997
|
-
//
|
|
998
|
-
//
|
|
999
|
-
//
|
|
1000
|
-
//
|
|
1001
|
-
//
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
//
|
|
1010
|
-
// declaration (#2447). The names must be loop-bound for the whole body,
|
|
1011
|
-
// or `ErbTopLevelEmitter.identifier` renders each read as `v[:cls]` —
|
|
1012
|
-
// a vars-Hash key nothing ever seeds, i.e. the empty attribute this
|
|
1013
|
-
// fixes. Phase 1 guarantees `declarations` is present or the loop was
|
|
1014
|
-
// already refused, so there is no partial-lowering case here.
|
|
1006
|
+
// This loop's row scope. Guards module-const inlining (and, in ERB, the
|
|
1007
|
+
// fundamental v[:name]-vs-local rendering choice) for the whole body
|
|
1008
|
+
// (children + key + filter) so a same-named loop variable isn't
|
|
1009
|
+
// replaced by the const literal / a vars-Hash read. `IRLoop` already
|
|
1010
|
+
// structurally satisfies `LoopBindingSource`
|
|
1011
|
+
// (`param`/`index`/`paramBindings`/`preamble`) — `enterLoopRow(loop)`
|
|
1012
|
+
// binds exactly what this renderLoop's header + preamble locals
|
|
1013
|
+
// introduce (#2482 Stage 2 — replaces the ref-counted `Map` this
|
|
1014
|
+
// adapter used to carry). Restored by reference (immutable — no
|
|
1015
|
+
// ref-count bookkeeping) at the matching pop below, once the WHOLE
|
|
1016
|
+
// body (including the filter predicate) has been rendered — except for
|
|
1017
|
+
// one temporary drop-to-outer window around the hoisted sort-comparator
|
|
1018
|
+
// emission below, since that runs OUTSIDE this loop.
|
|
1015
1019
|
const preambleDecls = loop.preamble?.declarations ?? []
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
this.loopBoundNames.set(n, (this.loopBoundNames.get(n) ?? 0) + 1)
|
|
1019
|
-
}
|
|
1020
|
+
const prevScope = this.scope
|
|
1021
|
+
this.scope = prevScope.enterLoopRow(loop)
|
|
1020
1022
|
const prevLoopKeyDepth = this.currentLoopKeyDepth
|
|
1021
1023
|
this.currentLoopKeyDepth = loop.depth
|
|
1022
1024
|
const renderedChildren = this.renderChildren(loop.children)
|
|
@@ -1042,18 +1044,16 @@ export class ErbAdapter extends BaseAdapter implements IRNodeEmitter<ErbRenderCt
|
|
|
1042
1044
|
// fall back to the structured `bf.sort` for a comparator the
|
|
1043
1045
|
// evaluator can't model (e.g. `localeCompare`).
|
|
1044
1046
|
//
|
|
1045
|
-
// The hoisted sort runs OUTSIDE this loop, so this loop's
|
|
1047
|
+
// The hoisted sort runs OUTSIDE this loop, so this loop's row scope
|
|
1046
1048
|
// must not shadow the comparator's captured free vars while emitting
|
|
1047
1049
|
// the env — otherwise a captured var that happens to share a
|
|
1048
1050
|
// loop-param name is blocked from inlining its module const / from
|
|
1049
1051
|
// reading `v[:name]` and instead resolves to the (out-of-scope) loop
|
|
1050
|
-
// local. Drop
|
|
1051
|
-
// restore (a nested loop's outer
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
else this.loopBoundNames.set(n, c)
|
|
1056
|
-
}
|
|
1052
|
+
// local. Drop back to the outer (pre-row) scope for the sort emit,
|
|
1053
|
+
// then restore the row scope below (a nested loop's own outer
|
|
1054
|
+
// bindings stay in effect throughout, since `prevScope` already
|
|
1055
|
+
// carries them).
|
|
1056
|
+
this.scope = prevScope
|
|
1057
1057
|
const sortEmit = (e: ParsedExpr) => this.convertExpressionToRuby('', e)
|
|
1058
1058
|
const sortArrow = loop.sortComparator.arrow
|
|
1059
1059
|
let sorted: string | null = null
|
|
@@ -1074,9 +1074,7 @@ export class ErbAdapter extends BaseAdapter implements IRNodeEmitter<ErbRenderCt
|
|
|
1074
1074
|
)
|
|
1075
1075
|
sorted = rawArray
|
|
1076
1076
|
}
|
|
1077
|
-
|
|
1078
|
-
this.loopBoundNames.set(n, (this.loopBoundNames.get(n) ?? 0) + 1)
|
|
1079
|
-
}
|
|
1077
|
+
this.scope = prevScope.enterLoopRow(loop)
|
|
1080
1078
|
lines.push(`<%- ${sortedHoist} = ${sorted} -%>`)
|
|
1081
1079
|
}
|
|
1082
1080
|
if (loop.objectIteration) {
|
|
@@ -1184,12 +1182,8 @@ export class ErbAdapter extends BaseAdapter implements IRNodeEmitter<ErbRenderCt
|
|
|
1184
1182
|
lines.push(children)
|
|
1185
1183
|
}
|
|
1186
1184
|
|
|
1187
|
-
// Body fully rendered —
|
|
1188
|
-
|
|
1189
|
-
const c = (this.loopBoundNames.get(n) ?? 1) - 1
|
|
1190
|
-
if (c <= 0) this.loopBoundNames.delete(n)
|
|
1191
|
-
else this.loopBoundNames.set(n, c)
|
|
1192
|
-
}
|
|
1185
|
+
// Body fully rendered — restore the outer (pre-row) scope.
|
|
1186
|
+
this.scope = prevScope
|
|
1193
1187
|
|
|
1194
1188
|
lines.push(`<%- end -%>`)
|
|
1195
1189
|
lines.push(`<%= bf.comment("/loop:${loop.markerId}") %>`)
|
|
@@ -1558,11 +1552,11 @@ export class ErbAdapter extends BaseAdapter implements IRNodeEmitter<ErbRenderCt
|
|
|
1558
1552
|
// function-scope (`!isModule`) consts whose value is NOT itself a
|
|
1559
1553
|
// bare identifier (loop guard) are considered.
|
|
1560
1554
|
//
|
|
1561
|
-
// `
|
|
1562
|
-
// param can shadow this outer const's name (`.map((attrs) => <p
|
|
1555
|
+
// `this.scope` shadow guard (#2489): an enclosing `.map()` callback's
|
|
1556
|
+
// own param can shadow this outer const's name (`.map((attrs) => <p
|
|
1563
1557
|
// {...attrs} />)`) — without the guard this forwarded the OUTER
|
|
1564
1558
|
// const's value at every iteration instead of the per-item value.
|
|
1565
|
-
if (/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(trimmed) && !this.
|
|
1559
|
+
if (/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(trimmed) && !this.scope.isBound(trimmed)) {
|
|
1566
1560
|
const localConst = this.localConstants.find(
|
|
1567
1561
|
c => c.name === trimmed && !c.isModule,
|
|
1568
1562
|
)
|
|
@@ -1968,7 +1962,16 @@ export class ErbAdapter extends BaseAdapter implements IRNodeEmitter<ErbRenderCt
|
|
|
1968
1962
|
return this.stringValueNames.has(name)
|
|
1969
1963
|
}
|
|
1970
1964
|
|
|
1971
|
-
|
|
1965
|
+
/**
|
|
1966
|
+
* `escape` is the structured claim (#2613) — populate it only with kinds
|
|
1967
|
+
* a conformance twin actually demonstrates for this shape, since
|
|
1968
|
+
* `escape-coverage.test.ts` checks claims against the twins. The prose
|
|
1969
|
+
* in `reason` may legitimately offer more than the structured field
|
|
1970
|
+
* (ERB's numbered list opens with an inline-rewrite option that no twin
|
|
1971
|
+
* proves); prose stays authoritative for humans, this field for
|
|
1972
|
+
* machines.
|
|
1973
|
+
*/
|
|
1974
|
+
private _recordExprBF101(message: string, reason?: string, escape?: ReadonlyArray<{ kind: EscapeKind }>): void {
|
|
1972
1975
|
this.errors.push({
|
|
1973
1976
|
code: 'BF101',
|
|
1974
1977
|
severity: 'error',
|
|
@@ -1978,6 +1981,7 @@ export class ErbAdapter extends BaseAdapter implements IRNodeEmitter<ErbRenderCt
|
|
|
1978
1981
|
message: reason
|
|
1979
1982
|
? `${reason}\n\nOptions:\n1. Use /* @client */ for client-side evaluation\n2. Pre-compute the value in Ruby`
|
|
1980
1983
|
: 'Options:\n1. Use /* @client */ for client-side evaluation\n2. Pre-compute the value in Ruby',
|
|
1984
|
+
...(escape ? { escape } : {}),
|
|
1981
1985
|
},
|
|
1982
1986
|
})
|
|
1983
1987
|
}
|
|
@@ -352,11 +352,11 @@ export class ErbTopLevelEmitter implements ParsedExprEmitter {
|
|
|
352
352
|
if (name === 'undefined' || name === 'null') return 'nil'
|
|
353
353
|
// A loop-bound name (this identifier resolves to a bare Ruby local
|
|
354
354
|
// introduced by an enclosing loop, not a vars-Hash entry) takes
|
|
355
|
-
// priority over const inlining — mirrors the Mojo adapter's
|
|
356
|
-
//
|
|
357
|
-
//
|
|
358
|
-
//
|
|
359
|
-
//
|
|
355
|
+
// priority over const inlining — mirrors the Mojo adapter's threaded
|
|
356
|
+
// scope shadow guard, but here it ALSO decides the fundamental
|
|
357
|
+
// v[:name]-vs-bare-local rendering, not just the const fast path
|
|
358
|
+
// (ERB's two-locals variable model needs this distinction; Perl's
|
|
359
|
+
// uniform `$name` sigil does not — see `ErbEmitContext`).
|
|
360
360
|
if (this.ctx.isLoopBoundName(name)) return rubyLocal(name)
|
|
361
361
|
// Module pure-string const (e.g. `const baseClasses = '...'` used in a
|
|
362
362
|
// className template literal): inline the literal value rather than
|
package/src/conformance-pins.ts
CHANGED
|
@@ -16,6 +16,9 @@ export const conformancePins: ConformancePins = {
|
|
|
16
16
|
// JS-runtime target runs it, a DSL adapter surfaces BF021 + `/* @client */`.
|
|
17
17
|
// See spec/callback-fidelity.md.
|
|
18
18
|
'filter-typeof-predicate': [{ code: 'BF021', severity: 'error' }],
|
|
19
|
+
// Array-builder `.map()` body (imperative `push`-into-array preamble):
|
|
20
|
+
// BF021, with a verified `/* @client */` escape — `map-array-builder-
|
|
21
|
+
// body-client` (#2613). See that fixture's docstring.
|
|
19
22
|
'map-array-builder-body': [{ code: 'BF021', severity: 'error' }],
|
|
20
23
|
'map-array-builder-escaping': [{ code: 'BF021', severity: 'error' }],
|
|
21
24
|
// `.fill(value)` mutates the receiver in place — no template lowering
|
|
@@ -82,12 +85,20 @@ export const conformancePins: ConformancePins = {
|
|
|
82
85
|
// "Loop array is a bare identifier..." comment) rather than faked as
|
|
83
86
|
// BF104 or silently producing broken Ruby.
|
|
84
87
|
'static-array-from-props': [
|
|
85
|
-
{
|
|
88
|
+
{
|
|
89
|
+
code: 'BF101',
|
|
90
|
+
severity: 'error',
|
|
91
|
+
issue: 'https://github.com/piconic-ai/barefootjs/issues/2321',
|
|
92
|
+
},
|
|
86
93
|
],
|
|
87
94
|
// BF103 (imported child in the loop body) no longer fires now that the
|
|
88
95
|
// conformance harness passes `siblingTemplatesRegistered: true` (#2205).
|
|
89
96
|
'static-array-from-props-with-component': [
|
|
90
|
-
{
|
|
97
|
+
{
|
|
98
|
+
code: 'BF101',
|
|
99
|
+
severity: 'error',
|
|
100
|
+
issue: 'https://github.com/piconic-ai/barefootjs/issues/2321',
|
|
101
|
+
},
|
|
91
102
|
],
|
|
92
103
|
// #2087 Phase B: `isLowerableLoopDestructure` now admits every fixed-
|
|
93
104
|
// binding shape (any field/index depth — `destructure-array-index-in-map`,
|
|
@@ -108,9 +119,7 @@ export const conformancePins: ConformancePins = {
|
|
|
108
119
|
// lowers it to a real inline Ruby block predicate and must render to
|
|
109
120
|
// Hono parity instead.
|
|
110
121
|
// Faithful lowering tracked: https://github.com/piconic-ai/barefootjs/issues/2320 (successor to #2038)
|
|
111
|
-
'filter-nested-find-predicate': [
|
|
112
|
-
{ code: 'BF101', severity: 'error', issue: 'https://github.com/piconic-ai/barefootjs/issues/2320' },
|
|
113
|
-
],
|
|
122
|
+
'filter-nested-find-predicate': [{ code: 'BF101', severity: 'error', issue: 'https://github.com/piconic-ai/barefootjs/issues/2320' }],
|
|
114
123
|
// #1467 demo-corpus context providers (`radio-group`, `accordion`,
|
|
115
124
|
// `dialog`, `popover`, `select`, `dropdown-menu`, `combobox`,
|
|
116
125
|
// `command`) are NOT pinned — an object-literal provider value lowers
|