@barefootjs/jinja 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/README.md +66 -0
  2. package/dist/adapter/analysis/component-tree.d.ts +26 -0
  3. package/dist/adapter/analysis/component-tree.d.ts.map +1 -0
  4. package/dist/adapter/boolean-result.d.ts +84 -0
  5. package/dist/adapter/boolean-result.d.ts.map +1 -0
  6. package/dist/adapter/emit-context.d.ts +106 -0
  7. package/dist/adapter/emit-context.d.ts.map +1 -0
  8. package/dist/adapter/expr/array-method.d.ts +75 -0
  9. package/dist/adapter/expr/array-method.d.ts.map +1 -0
  10. package/dist/adapter/expr/emitters.d.ts +143 -0
  11. package/dist/adapter/expr/emitters.d.ts.map +1 -0
  12. package/dist/adapter/expr/operand.d.ts +25 -0
  13. package/dist/adapter/expr/operand.d.ts.map +1 -0
  14. package/dist/adapter/index.d.ts +6 -0
  15. package/dist/adapter/index.d.ts.map +1 -0
  16. package/dist/adapter/index.js +189097 -0
  17. package/dist/adapter/jinja-adapter.d.ts +394 -0
  18. package/dist/adapter/jinja-adapter.d.ts.map +1 -0
  19. package/dist/adapter/lib/constants.d.ts +21 -0
  20. package/dist/adapter/lib/constants.d.ts.map +1 -0
  21. package/dist/adapter/lib/ir-scope.d.ts +50 -0
  22. package/dist/adapter/lib/ir-scope.d.ts.map +1 -0
  23. package/dist/adapter/lib/jinja-naming.d.ts +77 -0
  24. package/dist/adapter/lib/jinja-naming.d.ts.map +1 -0
  25. package/dist/adapter/lib/types.d.ts +27 -0
  26. package/dist/adapter/lib/types.d.ts.map +1 -0
  27. package/dist/adapter/memo/seed.d.ts +81 -0
  28. package/dist/adapter/memo/seed.d.ts.map +1 -0
  29. package/dist/adapter/props/prop-classes.d.ts +33 -0
  30. package/dist/adapter/props/prop-classes.d.ts.map +1 -0
  31. package/dist/adapter/spread/spread-codegen.d.ts +61 -0
  32. package/dist/adapter/spread/spread-codegen.d.ts.map +1 -0
  33. package/dist/adapter/value/parsed-literal.d.ts +28 -0
  34. package/dist/adapter/value/parsed-literal.d.ts.map +1 -0
  35. package/dist/build.d.ts +28 -0
  36. package/dist/build.d.ts.map +1 -0
  37. package/dist/build.js +189117 -0
  38. package/dist/conformance-pins.d.ts +12 -0
  39. package/dist/conformance-pins.d.ts.map +1 -0
  40. package/dist/index.d.ts +9 -0
  41. package/dist/index.d.ts.map +1 -0
  42. package/dist/index.js +189118 -0
  43. package/package.json +66 -0
  44. package/python/VERSION +1 -0
  45. package/python/barefootjs/__init__.py +57 -0
  46. package/python/barefootjs/backend_jinja.py +125 -0
  47. package/python/barefootjs/evaluator.py +787 -0
  48. package/python/barefootjs/runtime.py +1334 -0
  49. package/python/barefootjs/search_params.py +89 -0
  50. package/python/pyproject.toml +32 -0
  51. package/python/tests/__init__.py +0 -0
  52. package/python/tests/test_eval_vectors.py +88 -0
  53. package/python/tests/test_evaluator.py +406 -0
  54. package/python/tests/test_helper_vectors.py +288 -0
  55. package/python/tests/test_omit.py +62 -0
  56. package/python/tests/test_props_attr.py +54 -0
  57. package/python/tests/test_query.py +41 -0
  58. package/python/tests/test_render.py +102 -0
  59. package/python/tests/test_render_child.py +96 -0
  60. package/python/tests/test_search_params.py +50 -0
  61. package/python/tests/test_spread_attrs.py +86 -0
  62. package/python/tests/test_template_primitives.py +347 -0
  63. package/python/tests/vector-divergences.json +42 -0
  64. package/src/__tests__/jinja-adapter-unit.test.ts +390 -0
  65. package/src/__tests__/jinja-adapter.test.ts +53 -0
  66. package/src/__tests__/jinja-counter.test.ts +62 -0
  67. package/src/__tests__/jinja-query-href.test.ts +99 -0
  68. package/src/__tests__/jinja-spread-attrs.test.ts +225 -0
  69. package/src/adapter/analysis/component-tree.ts +119 -0
  70. package/src/adapter/boolean-result.ts +176 -0
  71. package/src/adapter/emit-context.ts +118 -0
  72. package/src/adapter/expr/array-method.ts +346 -0
  73. package/src/adapter/expr/emitters.ts +608 -0
  74. package/src/adapter/expr/operand.ts +35 -0
  75. package/src/adapter/index.ts +6 -0
  76. package/src/adapter/jinja-adapter.ts +1747 -0
  77. package/src/adapter/lib/constants.ts +33 -0
  78. package/src/adapter/lib/ir-scope.ts +95 -0
  79. package/src/adapter/lib/jinja-naming.ts +114 -0
  80. package/src/adapter/lib/types.ts +30 -0
  81. package/src/adapter/memo/seed.ts +132 -0
  82. package/src/adapter/props/prop-classes.ts +65 -0
  83. package/src/adapter/spread/spread-codegen.ts +166 -0
  84. package/src/adapter/value/parsed-literal.ts +76 -0
  85. package/src/build.ts +37 -0
  86. package/src/conformance-pins.ts +101 -0
  87. package/src/index.ts +9 -0
  88. package/src/test-render.ts +714 -0
package/README.md ADDED
@@ -0,0 +1,66 @@
1
+ # @barefootjs/jinja
2
+
3
+ Jinja2 adapter for BarefootJS: compiles the BarefootJS IR (JSX → IR, see
4
+ `spec/compiler.md`) into `.jinja` template files plus the client JS bundle
5
+ every other adapter produces, and ships a Python rendering runtime
6
+ (`python/barefootjs/`) that renders those templates through a plain
7
+ `jinja2.Environment` — no framework is required (Flask, Django, bare WSGI,
8
+ etc. all work the same way).
9
+
10
+ Near-mechanical port of `@barefootjs/xslate` (the Text::Xslate/Kolon
11
+ adapter) to Jinja2 syntax. See `src/adapter/jinja-adapter.ts`'s header
12
+ comment for the full Kolon↔Jinja syntax-mapping table and the JS/Python
13
+ semantics divergences this port handles uniformly (truthiness,
14
+ stringification, reserved-word identifier mangling, and the
15
+ evaluator-only higher-order-callback lowering since Jinja has no lambda
16
+ expression).
17
+
18
+ ## Template output shape
19
+
20
+ - `name: 'jinja'`, `extension: '.jinja'`, `templatesPerComponent: true` —
21
+ one `.jinja` file per component, named by snake-casing the PascalCase
22
+ component name (`UserCard` → `user_card.jinja`).
23
+ - Hydration markers (`bf-s`, `bf-h`/`bf-m`/`bf-r`, `bf-p`, slot/conditional
24
+ comment markers, loop boundary comments) use the SAME runtime method
25
+ names as every other adapter's `bf.*` calls (`bf.scope_attr()`,
26
+ `bf.hydration_attrs()`, `bf.text_start`/`text_end`, `bf.comment(...)`,
27
+ …) — see `spec/template-helpers.md` for the shared helper contract.
28
+ - Every text/attribute interpolation of a possibly-non-string value is
29
+ routed through `bf.string(...)` (or `bf.bool_str(...)` for
30
+ boolean-shaped values); every non-comparison condition position is
31
+ routed through `bf.truthy(...)`. Both are pure Python-runtime helpers —
32
+ see the Python runtime pointer below.
33
+
34
+ ## Python runtime
35
+
36
+ `python/barefootjs/` is a self-contained Python package (only dependency:
37
+ `jinja2`) implementing the engine-agnostic `bf` object every emitted
38
+ template calls into: hydration markers, context propagation
39
+ (`provide_context`/`use_context`), child-component rendering
40
+ (`render_child`), script registration, and the JS-compatible helper
41
+ library (`string`, `bool_str`, `truthy`, `number`, `floor`/`ceil`/`round`,
42
+ array/string helpers, the `*_eval` evaluator helpers, `spread_attrs`,
43
+ `query`, …). It mirrors the layering of `packages/adapter-perl/lib/` (an
44
+ engine-agnostic core plus a thin per-engine backend) — see
45
+ `spec/template-helpers.md` for the semantic contract each helper must
46
+ satisfy, and the package's own tests under `python/tests/`.
47
+
48
+ ## Usage
49
+
50
+ ```ts
51
+ // barefoot.config.ts
52
+ import { createConfig } from '@barefootjs/jinja/build'
53
+
54
+ export default createConfig({
55
+ components: ['./src/components'],
56
+ outDir: './dist',
57
+ })
58
+ ```
59
+
60
+ `bf build` then emits `.jinja` templates + client JS under `outDir`. A
61
+ Python host renders a component by constructing a `jinja2.Environment`
62
+ (with `autoescape=True`, `undefined=jinja2.ChainableUndefined`,
63
+ `trim_blocks=True`, `lstrip_blocks=True` — see the adapter header comment
64
+ for why the last two are required) over a `FileSystemLoader` pointed at
65
+ the emitted templates, wiring in `barefootjs.backend_jinja` as the render
66
+ backend.
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Component-tree analysis for the Jinja2 template adapter.
3
+ *
4
+ * Ported from `packages/adapter-xslate/src/adapter/analysis/component-tree.ts`.
5
+ * Pure functions over the IR — they read no adapter instance state.
6
+ * `collectImportedLoopChildComponentErrors` returns its diagnostics instead
7
+ * of pushing onto the adapter's error list, so the adapter stays the sole
8
+ * owner of `errors`.
9
+ */
10
+ import type { ComponentIR, CompilerError } from '@barefootjs/jsx';
11
+ /**
12
+ * Whether the component needs the client runtime — it owns reactive state
13
+ * (signals / effects / onMount) or the analyzer flagged it as needing init.
14
+ */
15
+ export declare function hasClientInteractivity(ir: ComponentIR): boolean;
16
+ /**
17
+ * Build a `BF103` diagnostic for every component reference inside a loop body
18
+ * whose name is imported from a relative-path module. Mirror of the Go /
19
+ * Xslate adapter's check — the Jinja adapter has the same
20
+ * cross-template-registration constraint at request time (each `.jinja`
21
+ * component file must be registered with the shared `jinja2.Environment`
22
+ * loader alongside the parent). Returns the diagnostics so the caller pushes
23
+ * them onto its own error list.
24
+ */
25
+ export declare function collectImportedLoopChildComponentErrors(ir: ComponentIR, componentName: string): CompilerError[];
26
+ //# sourceMappingURL=component-tree.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"component-tree.d.ts","sourceRoot":"","sources":["../../../src/adapter/analysis/component-tree.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EACV,WAAW,EAUX,aAAa,EACd,MAAM,iBAAiB,CAAA;AAExB;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,WAAW,GAAG,OAAO,CAO/D;AAED;;;;;;;;GAQG;AACH,wBAAgB,uCAAuC,CACrD,EAAE,EAAE,WAAW,EACf,aAAa,EAAE,MAAM,GACpB,aAAa,EAAE,CAqEjB"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Structural classifier for JS expressions whose result is a boolean value
3
+ * (or unambiguously stringifies to "true"/"false" in JS).
4
+ *
5
+ * Ported from `packages/adapter-xslate/src/adapter/boolean-result.ts`
6
+ * (itself ported from the Mojo adapter's `bf->bool_str` classifier). Used by
7
+ * the Jinja adapter for TWO purposes — one inherited from Xslate, one new:
8
+ *
9
+ * 1. **Attribute/text stringification** (inherited): route a boolean-shaped
10
+ * reactive binding through the runtime `bf.bool_str` helper so the
11
+ * serialised value matches JS `String(boolean)` ("true"/"false"). Python
12
+ * has a real `bool` type (unlike Perl's `1`/`''`), but Python's own
13
+ * `str(True)` == `"True"` (capitalised) — still wrong for HTML output —
14
+ * so the same explicit routing is required.
15
+ * 2. **Condition-position truthy wrapping** (new — `isBooleanResultParsed` is
16
+ * exported, not just the string-based `isBooleanResultExpr`): Python
17
+ * truthiness diverges from JS specifically on empty containers (`[]` /
18
+ * `{}` are JS-truthy, Python-falsy). Perl doesn't have this problem — a
19
+ * Perl array/hash REFERENCE is always true, matching JS objects/arrays
20
+ * being unconditionally truthy — which is why Xslate never needed a
21
+ * truthy-routing layer for `if`/ternary/`&&`/`||` conditions. The Jinja
22
+ * adapter's condition-emission call sites (see `jinja-adapter.ts`'s
23
+ * `convertConditionToJinja`) reuse this SAME structural classifier: a
24
+ * condition that is already unambiguously boolean-shaped emits directly;
25
+ * everything else is wrapped in `bf.truthy(...)` (a JS-faithful
26
+ * `ToBoolean`) before being used as an `{% if %}` / ternary test.
27
+ *
28
+ * The classifier walks a `ParsedExpr` produced by
29
+ * `@barefootjs/jsx::parseExpression` — same AST the filter / loop lowerings
30
+ * already use — so detection is structural rather than regex-text-matching.
31
+ * Wrapped expression text is left to the caller's existing
32
+ * `convertExpressionToJinja` pipeline; this module only decides whether to
33
+ * wrap.
34
+ *
35
+ * Detected shapes:
36
+ * - `binary` with a comparison operator (`<`, `>`, `<=`, `>=`, `==`, `===`,
37
+ * `!=`, `!==`)
38
+ * - `unary` with logical `!`
39
+ * - `literal` with `literalType: 'boolean'`
40
+ * - `logical` (`&&` / `||` / `??`) when both sides are themselves
41
+ * boolean-result (catches `x > 0 && y < 10`; intentionally does NOT
42
+ * catch `x() || 'fallback'` whose right side stringifies as a regular
43
+ * value)
44
+ * - `conditional` (`?:`) when both branches are themselves boolean-result
45
+ *
46
+ * Anything else returns `false` — including bare identifiers (`accepted`)
47
+ * and call expressions (`accepted()`) whose return type the adapter has no
48
+ * way to infer from source text alone.
49
+ */
50
+ import { type ParsedExpr } from '@barefootjs/jsx';
51
+ /**
52
+ * Structural boolean-result check over an already-parsed `ParsedExpr` tree.
53
+ * Exported (unlike Xslate's private equivalent) so the condition-position
54
+ * truthy-wrapping call sites can reuse it without a stringify → re-parse
55
+ * round-trip.
56
+ */
57
+ export declare function isBooleanResultParsed(node: ParsedExpr): boolean;
58
+ export declare function isBooleanResultExpr(expr: string): boolean;
59
+ /**
60
+ * True when `expr`'s top-level shape is an explicit JS `String(x)` call
61
+ * (the `EVAL_BUILTIN_IDENTS` builtin the compiler recognizes structurally —
62
+ * `packages/jsx/src/expression-parser.ts`'s `EVAL_BUILTIN_IDENTS`; lowered
63
+ * by this adapter's `String` template primitive to `bf.string(x)`, see
64
+ * `lib/constants.ts`).
65
+ *
66
+ * Guards the `isAriaBooleanAttr`-driven `bf.bool_str(...)` override in
67
+ * `jinja-adapter.ts`'s `elementAttrEmitter`: `bf.string` and `bf.bool_str`
68
+ * produce IDENTICAL text for a real Python `bool` (both are `"true"` /
69
+ * `"false"`), so applying `bf.bool_str` to `String(x)`'s ALREADY-STRINGIFIED
70
+ * result is not a no-op — it is a Python-truthiness test over that STRING
71
+ * ("false" is a non-empty Python string, hence truthy, so
72
+ * `bf.bool_str(bf.string(false))` would wrongly render `"true"`). The Kolon
73
+ * port has the identical double-wrap shape and "works" only by an
74
+ * unrelated accident (`JSON::PP::Boolean` stringifies to `"0"`/`"1"`, and
75
+ * Perl specifically treats the STRING `"0"` as falsy) that doesn't hold in
76
+ * Python. An author who explicitly writes `String(...)` has already opted
77
+ * into JS `String()` semantics — `bf.string(x)` alone (which DOES special-
78
+ * case booleans, see `runtime.js_string`) is the complete, correct
79
+ * lowering; no attribute-name-driven override should run again on top of
80
+ * it.
81
+ */
82
+ export declare function isExplicitStringCall(expr: string): boolean;
83
+ export declare function isAriaBooleanAttr(name: string): boolean;
84
+ //# sourceMappingURL=boolean-result.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"boolean-result.d.ts","sourceRoot":"","sources":["../../src/adapter/boolean-result.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AAEH,OAAO,EAAmB,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAalE;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAuB/D;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAIzD;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAS1D;AAyCD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEvD"}
@@ -0,0 +1,106 @@
1
+ /**
2
+ * The contract the extracted expression-emitter modules depend on instead of
3
+ * the concrete `JinjaAdapter`.
4
+ *
5
+ * Ported from `packages/adapter-xslate/src/adapter/emit-context.ts`. The
6
+ * Jinja adapter's top-level expression lowering is mutually recursive with
7
+ * the adapter's own const/record resolution and its filter-predicate
8
+ * emitter, so the extracted `JinjaTopLevelEmitter` still needs to call back
9
+ * into shared per-compile state and recursive entry points.
10
+ * `JinjaEmitContext` is that seam: the emitter takes a `JinjaEmitContext`
11
+ * built by the adapter's private `emitCtx` getter (the adapter does NOT
12
+ * `implements` this interface, so the wrapped members stay private and off
13
+ * its exported public type). The emitter depends on this narrow interface
14
+ * rather than the full class, so the coupling is explicit and it's
15
+ * unit-testable against a stub.
16
+ *
17
+ * Keep this surface minimal: add a member only when an extracted module
18
+ * genuinely needs it, so the seam documents the real cross-module coupling
19
+ * rather than re-exposing the whole adapter.
20
+ */
21
+ import type { ParsedExpr, CompilerError, IRMetadata } from '@barefootjs/jsx';
22
+ export interface JinjaEmitContext {
23
+ /**
24
+ * (#1922) Local binding names the request-scoped `searchParams()` env signal
25
+ * is imported under. Non-empty enables the env-signal method-call lowering.
26
+ */
27
+ readonly _searchParamsLocals: Set<string>;
28
+ /**
29
+ * Inline a module-scope pure string-literal const by name as the resolved
30
+ * literal value, or null when the name is not such a const.
31
+ */
32
+ _resolveModuleStringConst(name: string): string | null;
33
+ /** Resolve a literal const (`const totalPages = 5`) to its Jinja value, or null. */
34
+ _resolveLiteralConst(name: string): string | null;
35
+ /**
36
+ * Resolve a static property access on a module object-literal const
37
+ * (`variantClasses.ghost`) to its Jinja value at compile time, or null.
38
+ */
39
+ _resolveStaticRecordLiteral(objectName: string, key: string): string | null;
40
+ /** Record a BF101 unsupported-expression diagnostic. */
41
+ _recordExprBF101(message: string, reason?: string): void;
42
+ /** Lower a filter/predicate body to its Jinja form, bound to `param`. */
43
+ _renderJinjaFilterExprPublic(expr: ParsedExpr, param: string): string;
44
+ }
45
+ /**
46
+ * The contract the extracted object-literal / conditional-spread lowering
47
+ * (`spread/spread-codegen.ts`) depends on. Declared separately from
48
+ * `JinjaEmitContext` so each extracted module's real coupling is documented
49
+ * precisely. Mirror of the Xslate adapter's `XslateSpreadContext`.
50
+ */
51
+ export interface JinjaSpreadContext {
52
+ /** Component name, for diagnostic source locations. */
53
+ readonly componentName: string;
54
+ /** Per-compile diagnostic list the spread lowering appends to. */
55
+ readonly errors: CompilerError[];
56
+ /** Local-constant metadata, for resolving `Record[key]` spread values. */
57
+ readonly localConstants: IRMetadata['localConstants'];
58
+ /** Prop params, for classifying a bare-identifier index as a prop. */
59
+ readonly propsParams: {
60
+ name: string;
61
+ }[];
62
+ /**
63
+ * Lower a JS expression to its Jinja form (the core recursive entry).
64
+ *
65
+ * When the IR already carries a structured `ParsedExpr` tree, pass it as
66
+ * `preParsed` so the converter threads it straight through instead of
67
+ * re-parsing `expr`. With `preParsed` set, `expr` is unused for parsing
68
+ * (the converter derives any diagnostic text from the tree), so callers
69
+ * may pass `''`.
70
+ */
71
+ convertExpressionToJinja(expr: string, preParsed?: ParsedExpr): string;
72
+ /**
73
+ * Lower a JS expression to a Jinja CONDITION (routes through `bf.truthy`
74
+ * unless the expression is structurally already boolean-shaped — see
75
+ * `boolean-result.ts`). Used for the conditional-spread ternary's test,
76
+ * which is a condition position, not a value position. Same `preParsed`
77
+ * contract as `convertExpressionToJinja`.
78
+ */
79
+ convertConditionToJinja(expr: string, preParsed?: ParsedExpr): string;
80
+ }
81
+ /**
82
+ * The contract the extracted in-template memo / context seeding
83
+ * (`memo/seed.ts`) depends on. The seed lowering recurses into the core
84
+ * expression lowering to compute a derived signal/memo value or a context
85
+ * default; that recursive entry is its only adapter coupling.
86
+ */
87
+ export interface JinjaMemoContext {
88
+ /**
89
+ * Lower a JS expression to its Jinja form (the core recursive entry). See
90
+ * `JinjaSpreadContext.convertExpressionToJinja` for the `preParsed` contract.
91
+ */
92
+ convertExpressionToJinja(expr: string, preParsed?: ParsedExpr): string;
93
+ /**
94
+ * Per-compile diagnostic list `convertExpressionToJinja` appends to on an
95
+ * unsupported shape (`_recordExprBF101`). `memo/seed.ts`'s
96
+ * `generateDerivedMemoSeed` is a SPECULATIVE "try this in-template
97
+ * recomputation, else fall back to the static ssrDefault seed" attempt per
98
+ * plan step — unlike every other `convertExpressionToJinja` call site, a
99
+ * failure here must NOT become a hard compile error, so it snapshots this
100
+ * array's length before calling in and truncates back to it on failure
101
+ * (discarding whatever `_recordExprBF101` appended) rather than letting
102
+ * the error escape.
103
+ */
104
+ readonly errors: CompilerError[];
105
+ }
106
+ //# sourceMappingURL=emit-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emit-context.d.ts","sourceRoot":"","sources":["../../src/adapter/emit-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;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"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Array / string method lowering for the Jinja2 template adapter.
3
+ *
4
+ * Ported from `packages/adapter-xslate/src/adapter/expr/array-method.ts`.
5
+ * Pure free functions shared by both the filter-context emitter and the
6
+ * top-level emitter — they take an `emit` callback for receiver / argument
7
+ * recursion and read no adapter instance state.
8
+ *
9
+ * The receiver/array helpers are the same runtime methods the Xslate adapter
10
+ * calls, invoked as `bf.NAME(...)` (bare, no `$` sigil) instead of
11
+ * `$bf.NAME(...)`.
12
+ */
13
+ import type { ParsedExpr, ArrayMethod, SortComparator, FlatDepth } from '@barefootjs/jsx';
14
+ export declare function renderArrayMethod(method: ArrayMethod, object: ParsedExpr, args: ParsedExpr[], emit: (e: ParsedExpr) => string): string;
15
+ /**
16
+ * Emit a `.sort(cmp)` / `.toSorted(cmp)` via the runtime evaluator (#2018):
17
+ * the comparator body travels as serialized-ParsedExpr JSON, evaluated per
18
+ * comparison against `{paramA, paramB, …captured}`. Returns null when the
19
+ * body is outside the evaluator surface (e.g. a `localeCompare` comparator —
20
+ * `serializeParsedExpr` refuses it), so the caller falls back to the
21
+ * structured `bf.sort`. `params` are the comparator arrow's two params
22
+ * (`[paramA, paramB]`).
23
+ */
24
+ export declare function renderSortEval(recv: string, body: ParsedExpr, params: string[], emit: (e: ParsedExpr) => string): string | null;
25
+ /**
26
+ * Emit a `.reduce(fn, init)` / `.reduceRight(fn, init)` via the runtime
27
+ * evaluator (#2018): the reducer body travels as serialized-ParsedExpr JSON,
28
+ * folded over the receiver from `init` in `direction` order. `params` are the
29
+ * reducer arrow's params (`[paramAcc, paramItem]`); `init` is the initial-value
30
+ * `ParsedExpr` from the call's trailing argument. Returns null when the body is
31
+ * outside the evaluator surface, or when `init` is not a literal string/number
32
+ * (→ caller refuses with BF101). A numeric seed passes through as a bare
33
+ * Jinja number; a string seed as a single-quoted literal.
34
+ */
35
+ export declare function renderReduceEval(recv: string, body: ParsedExpr, params: string[], init: ParsedExpr, direction: 'left' | 'right', emit: (e: ParsedExpr) => string): string | null;
36
+ /**
37
+ * Emit a higher-order predicate call via the runtime evaluator (#2018, P2):
38
+ * `bf.filter_eval` / `bf.every_eval` / `bf.some_eval` / `bf.find_eval` /
39
+ * `bf.find_index_eval`, carrying the serialized predicate body + captured env
40
+ * dict. Generalizes the lambda lowering to the same JS-faithful evaluator
41
+ * the Go/Xslate adapters use. Returns null when the predicate is outside the
42
+ * evaluator surface (e.g. a method-call predicate — `serializeParsedExpr`
43
+ * refuses it), so the caller falls back to the lambda form. `forward`
44
+ * (find / findIndex family only) selects the search direction — `false` =
45
+ * findLast / findLastIndex.
46
+ */
47
+ export declare function renderPredicateEval(funcName: string, recv: string, predicate: ParsedExpr, param: string, emit: (e: ParsedExpr) => string, forward?: boolean): string | null;
48
+ /**
49
+ * Emit a `.flatMap(proj)` via the runtime evaluator (#2018, P3): the projection
50
+ * body serializes to JSON and `bf.flat_map_eval` projects + flattens one
51
+ * level. `param` is the projection arrow's single param. Returns null when the
52
+ * projection is outside the evaluator surface (→ caller refuses with BF101).
53
+ */
54
+ export declare function renderFlatMapEval(recv: string, body: ParsedExpr, param: string, emit: (e: ParsedExpr) => string): string | null;
55
+ /**
56
+ * Emit a value-producing `.map(cb)` via the runtime evaluator (#2073): the
57
+ * projection body serializes to JSON and `bf.map_eval` projects each element,
58
+ * one result per element (no flatten — the JS `.map` contract). Composes
59
+ * through the array-method chain (`.map(cb).join(' ')`). Returns null when
60
+ * the projection is outside the evaluator surface (→ caller refuses with
61
+ * BF101). The JSX-returning `.map` is an IRLoop upstream and never reaches
62
+ * this emit.
63
+ */
64
+ export declare function renderMapEval(recv: string, body: ParsedExpr, param: string, emit: (e: ParsedExpr) => string): string | null;
65
+ /**
66
+ * Shared Jinja emit for `.sort(cmp)` / `.toSorted(cmp)`. Used by both the
67
+ * filter-context emitter and the top-level emitter, plus the loop-array
68
+ * wrap in `renderLoop`. The runtime `bf.sort` accepts an opts dict and
69
+ * returns a fresh list.
70
+ */
71
+ export declare function renderSortMethod(recv: string, c: SortComparator): string;
72
+ export declare function renderFlatMethod(recv: string, depth: FlatDepth | {
73
+ expr: ParsedExpr;
74
+ }, emit: (e: ParsedExpr) => string): string;
75
+ //# sourceMappingURL=array-method.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"array-method.d.ts","sourceRoot":"","sources":["../../../src/adapter/expr/array-method.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;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"}
@@ -0,0 +1,143 @@
1
+ /**
2
+ * ParsedExpr → Jinja2 emitters for the Jinja template adapter.
3
+ *
4
+ * Ported from `packages/adapter-xslate/src/adapter/expr/emitters.ts`
5
+ * (`XslateFilterEmitter` / `XslateTopLevelEmitter`). Two `ParsedExprEmitter`
6
+ * implementations:
7
+ *
8
+ * - `JinjaFilterEmitter` — filter/predicate context (loop param + local
9
+ * aliases + bare identifier signal fallback); self-contained, reads no
10
+ * adapter state.
11
+ * - `JinjaTopLevelEmitter` — top-level / per-render-var context; depends on
12
+ * the adapter only through the narrow `JinjaEmitContext` seam.
13
+ *
14
+ * Two deliberate divergences from the Kolon port, both documented at their
15
+ * definition site below:
16
+ *
17
+ * 1. **JS-truthy condition wrapping** (`truthyTest`) — Python truthiness
18
+ * diverges from JS on empty containers; Perl doesn't have this problem
19
+ * (a Perl ref is always true), so Kolon never needed this. Every
20
+ * condition-TEST position (`!x`, the left operand of `&&`/`||`, a
21
+ * ternary's test) routes through the shared `bf.truthy(...)` runtime
22
+ * helper unless the operand is structurally already boolean-shaped
23
+ * (`isBooleanResultParsed`). `&&`/`||` still return the ORIGINAL
24
+ * operand VALUE (not a coerced bool) on the taken branch — matching JS
25
+ * `a || b` returning `a` itself, not `true` — only the BRANCH TEST uses
26
+ * `bf.truthy`. Because Jinja's `if/else` ternary has no way to reuse an
27
+ * already-computed test value for both the test and (conditionally) the
28
+ * result, the left operand's rendered text is emitted TWICE (once as
29
+ * the test, once as the value) — safe because every operand reaching
30
+ * this pipeline is a pure, side-effect-free read (a signal/prop lookup
31
+ * or a call into a pure runtime helper), never a stateful expression.
32
+ * 2. **No Jinja lambda for the predicate-callback fallback.** Kolon's
33
+ * `-> $x { … }` lambda is the Xslate top-level emitter's fallback when a
34
+ * `.filter`/`.every`/`.some`/`.find*` predicate can't be serialized to
35
+ * the runtime evaluator's JSON form (e.g. a nested method-call
36
+ * predicate). Jinja has no lambda-expression syntax at all, so there is
37
+ * no equivalent fallback to port. `JinjaTopLevelEmitter` therefore uses
38
+ * ONE mechanism for every higher-order callback: the evaluator-JSON
39
+ * `*_eval` payload (`bf.filter_eval`, `bf.sort_eval`, …). When
40
+ * `serializeParsedExpr` refuses the body, the call surfaces `BF101`
41
+ * instead of silently degrading — `.sort`/`.toSorted` is the one
42
+ * exception, whose non-lambda STRUCTURED fallback (`bf.sort` with a
43
+ * `{keys: […]}` descriptor, no callback body at all) survives the port
44
+ * unchanged since it was never lambda-shaped to begin with.
45
+ * `JinjaFilterEmitter` (the loop `.filter().map()` INLINE predicate,
46
+ * rendered as a plain boolean expression, never a lambda) is otherwise
47
+ * unaffected and still used for that path plus the filter-predicate
48
+ * entry point `_renderJinjaFilterExprPublic`.
49
+ */
50
+ import { type ParsedExprEmitter, type ArrayMethod, type LiteralType, type ParsedExpr, type ObjectLiteralProperty, type FlatDepth, type TemplatePart } from '@barefootjs/jsx';
51
+ import type { JinjaEmitContext } from '../emit-context.ts';
52
+ /**
53
+ * Route a condition-TEST position through `bf.truthy(...)` unless the node
54
+ * is structurally already boolean-shaped. See the file header (divergence
55
+ * 1). Shared by both emitters below and reused by the adapter's top-level
56
+ * `convertConditionToJinja` for IR-level `if` / loop-filter conditions.
57
+ */
58
+ export declare function truthyTest(node: ParsedExpr, rendered: string): string;
59
+ /**
60
+ * Lowering for the predicate body of a filter / every / some / find, plus the
61
+ * same shape used by the loop-hoist `.filter().map()` inline condition.
62
+ * Higher-order predicates are emitted using Jinja's own scalar comparison
63
+ * operators.
64
+ *
65
+ * NOTE: Jinja has no `[x for x in … if …]`-as-expression form usable inline
66
+ * here (a comprehension is a value producer, not a boolean test), so a
67
+ * nested higher-order call (`x.tags.filter(...)`, `other.some(...)`) inside
68
+ * a predicate has no faithful scalar lowering here either — same BF101
69
+ * surfacing as Kolon (#2038) instead of silently degrading to the
70
+ * callback's receiver.
71
+ */
72
+ export declare class JinjaFilterEmitter implements ParsedExprEmitter {
73
+ private readonly param;
74
+ private readonly localVarMap;
75
+ private readonly isStringName;
76
+ private readonly onUnsupported?;
77
+ constructor(param: string, localVarMap: Map<string, string>, isStringName?: (n: string) => boolean, onUnsupported?: ((message: string, reason?: string) => void) | undefined);
78
+ identifier(name: string): string;
79
+ literal(value: string | number | boolean | null, literalType: LiteralType): string;
80
+ member(object: ParsedExpr, property: string, _computed: boolean, emit: (e: ParsedExpr) => string): string;
81
+ indexAccess(object: ParsedExpr, index: ParsedExpr, emit: (e: ParsedExpr) => string): string;
82
+ call(callee: ParsedExpr, args: ParsedExpr[], emit: (e: ParsedExpr) => string): string;
83
+ unary(op: string, argument: ParsedExpr, emit: (e: ParsedExpr) => string): string;
84
+ binary(op: string, left: ParsedExpr, right: ParsedExpr, emit: (e: ParsedExpr) => string): string;
85
+ logical(op: '&&' | '||' | '??', left: ParsedExpr, right: ParsedExpr, emit: (e: ParsedExpr) => string): string;
86
+ callbackMethod(method: string, object: ParsedExpr, _arrow: Extract<ParsedExpr, {
87
+ kind: 'arrow';
88
+ }>, _restArgs: ParsedExpr[], emit: (e: ParsedExpr) => string): string;
89
+ arrayLiteral(elements: ParsedExpr[], emit: (e: ParsedExpr) => string): string;
90
+ arrayMethod(method: ArrayMethod, object: ParsedExpr, args: ParsedExpr[], emit: (e: ParsedExpr) => string): string;
91
+ flatMethod(object: ParsedExpr, depth: FlatDepth | {
92
+ expr: ParsedExpr;
93
+ }, emit: (e: ParsedExpr) => string): string;
94
+ conditional(_test: ParsedExpr, _consequent: ParsedExpr, _alternate: ParsedExpr): string;
95
+ templateLiteral(_parts: TemplatePart[]): string;
96
+ arrow(_params: string[], _body: ParsedExpr): string;
97
+ regex(_raw: string): string;
98
+ unsupported(_raw: string, _reason: string): string;
99
+ objectLiteral(_properties: ObjectLiteralProperty[], _raw: string, _emit: (e: ParsedExpr) => string): string;
100
+ }
101
+ /**
102
+ * Lowering for top-level expressions whose identifiers resolve against the
103
+ * Jinja template's per-render context vars (signals, props, locals
104
+ * introduced by `{% set x = … %}`). Differs from the filter emitter mainly
105
+ * in
106
+ * - `conditional` is supported (filter predicates can't return ternaries),
107
+ * - higher-order methods route through `bf.*` array/evaluator helpers,
108
+ * - no lambda fallback exists (see the file header, divergence 2).
109
+ */
110
+ export declare class JinjaTopLevelEmitter implements ParsedExprEmitter {
111
+ private readonly ctx;
112
+ constructor(ctx: JinjaEmitContext);
113
+ identifier(name: string): string;
114
+ literal(value: string | number | boolean | null, literalType: LiteralType): string;
115
+ member(object: ParsedExpr, property: string, _computed: boolean, emit: (e: ParsedExpr) => string): string;
116
+ indexAccess(object: ParsedExpr, index: ParsedExpr, emit: (e: ParsedExpr) => string): string;
117
+ call(callee: ParsedExpr, args: ParsedExpr[], emit: (e: ParsedExpr) => string): string;
118
+ unary(op: string, argument: ParsedExpr, emit: (e: ParsedExpr) => string): string;
119
+ binary(op: string, left: ParsedExpr, right: ParsedExpr, emit: (e: ParsedExpr) => string): string;
120
+ logical(op: '&&' | '||' | '??', left: ParsedExpr, right: ParsedExpr, emit: (e: ParsedExpr) => string): string;
121
+ callbackMethod(method: string, object: ParsedExpr, arrow: Extract<ParsedExpr, {
122
+ kind: 'arrow';
123
+ }>, restArgs: ParsedExpr[], emit: (e: ParsedExpr) => string): string;
124
+ /**
125
+ * Lower a boolean-predicate callback (`filter` / `find*` / `every` /
126
+ * `some`). See the file header, divergence 2: Jinja has no lambda
127
+ * expression, so — unlike Kolon — there is no non-evaluator fallback here.
128
+ * A predicate the evaluator can't model surfaces `BF101`.
129
+ */
130
+ private _emitPredicateCallback;
131
+ arrayLiteral(elements: ParsedExpr[], emit: (e: ParsedExpr) => string): string;
132
+ arrayMethod(method: ArrayMethod, object: ParsedExpr, args: ParsedExpr[], emit: (e: ParsedExpr) => string): string;
133
+ flatMethod(object: ParsedExpr, depth: FlatDepth | {
134
+ expr: ParsedExpr;
135
+ }, emit: (e: ParsedExpr) => string): string;
136
+ conditional(test: ParsedExpr, consequent: ParsedExpr, alternate: ParsedExpr, emit: (e: ParsedExpr) => string): string;
137
+ templateLiteral(parts: TemplatePart[], emit: (e: ParsedExpr) => string): string;
138
+ arrow(_params: string[], _body: ParsedExpr): string;
139
+ regex(_raw: string): string;
140
+ unsupported(_raw: string, _reason: string): string;
141
+ objectLiteral(properties: ObjectLiteralProperty[], _raw: string, _emit: (e: ParsedExpr) => string): string;
142
+ }
143
+ //# sourceMappingURL=emitters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emitters.d.ts","sourceRoot":"","sources":["../../../src/adapter/expr/emitters.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Operand-type classification for the Jinja2 template adapter.
3
+ *
4
+ * Ported from `packages/adapter-xslate/src/adapter/expr/operand.ts`. Pure
5
+ * function over `ParsedExpr` taking an `isStringName` predicate rather than
6
+ * reading adapter instance state.
7
+ *
8
+ * NOTE: like Kolon's `==`/`!=`, Jinja/Python's `==`/`!=` are value-equality
9
+ * operators that compare strings and numbers correctly, so the Jinja
10
+ * emitters never need to steer string comparisons onto a different operator
11
+ * family. This helper is therefore not consumed by the Jinja lowering
12
+ * today either — kept only as the parallel of the Xslate/Mojo adapters'
13
+ * `expr/operand.ts` (groundwork for a future shared codegen surface).
14
+ */
15
+ import type { ParsedExpr } from '@barefootjs/jsx';
16
+ /**
17
+ * Whether a comparison operand is string-typed. In the Mojo adapter this
18
+ * selects Perl `eq`/`ne` over numeric `==`/`!=` for a `===`/`!==` against a
19
+ * string operand. Neither the Kolon nor the Jinja emitters consume it —
20
+ * both languages' `==`/`!=` compare strings and numbers correctly, so
21
+ * `===`/`!==` always map to `==`/`!=`. Kept only as the parallel of the
22
+ * Xslate/Mojo helper.
23
+ */
24
+ export declare function isStringTypedOperand(expr: ParsedExpr, isStringName: (n: string) => boolean): boolean;
25
+ //# sourceMappingURL=operand.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operand.d.ts","sourceRoot":"","sources":["../../../src/adapter/expr/operand.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAEjD;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,UAAU,EAAE,YAAY,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,GAAG,OAAO,CASpG"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Jinja2 Template Adapter Exports
3
+ */
4
+ export { JinjaAdapter, jinjaAdapter } from './jinja-adapter.ts';
5
+ export type { JinjaAdapterOptions } from './jinja-adapter.ts';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/adapter/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAC/D,YAAY,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA"}