@barefootjs/rust 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 (87) hide show
  1. package/README.md +194 -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 +85 -0
  5. package/dist/adapter/boolean-result.d.ts.map +1 -0
  6. package/dist/adapter/emit-context.d.ts +107 -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/index.d.ts +6 -0
  13. package/dist/adapter/index.d.ts.map +1 -0
  14. package/dist/adapter/index.js +189091 -0
  15. package/dist/adapter/lib/constants.d.ts +25 -0
  16. package/dist/adapter/lib/constants.d.ts.map +1 -0
  17. package/dist/adapter/lib/ir-scope.d.ts +50 -0
  18. package/dist/adapter/lib/ir-scope.d.ts.map +1 -0
  19. package/dist/adapter/lib/minijinja-naming.d.ts +64 -0
  20. package/dist/adapter/lib/minijinja-naming.d.ts.map +1 -0
  21. package/dist/adapter/lib/types.d.ts +32 -0
  22. package/dist/adapter/lib/types.d.ts.map +1 -0
  23. package/dist/adapter/memo/seed.d.ts +84 -0
  24. package/dist/adapter/memo/seed.d.ts.map +1 -0
  25. package/dist/adapter/minijinja-adapter.d.ts +421 -0
  26. package/dist/adapter/minijinja-adapter.d.ts.map +1 -0
  27. package/dist/adapter/props/prop-classes.d.ts +33 -0
  28. package/dist/adapter/props/prop-classes.d.ts.map +1 -0
  29. package/dist/adapter/spread/spread-codegen.d.ts +63 -0
  30. package/dist/adapter/spread/spread-codegen.d.ts.map +1 -0
  31. package/dist/adapter/value/parsed-literal.d.ts +28 -0
  32. package/dist/adapter/value/parsed-literal.d.ts.map +1 -0
  33. package/dist/build.d.ts +29 -0
  34. package/dist/build.d.ts.map +1 -0
  35. package/dist/build.js +189111 -0
  36. package/dist/conformance-pins.d.ts +13 -0
  37. package/dist/conformance-pins.d.ts.map +1 -0
  38. package/dist/index.d.ts +12 -0
  39. package/dist/index.d.ts.map +1 -0
  40. package/dist/index.js +189112 -0
  41. package/package.json +67 -0
  42. package/runtime/Cargo.lock +124 -0
  43. package/runtime/Cargo.toml +21 -0
  44. package/runtime/src/backend_minijinja.rs +176 -0
  45. package/runtime/src/bin/bf-render.rs +147 -0
  46. package/runtime/src/evaluator.rs +770 -0
  47. package/runtime/src/lib.rs +19 -0
  48. package/runtime/src/manifest.rs +258 -0
  49. package/runtime/src/num.rs +558 -0
  50. package/runtime/src/runtime.rs +1548 -0
  51. package/runtime/src/search_params.rs +173 -0
  52. package/runtime/tests/eval_vectors.rs +94 -0
  53. package/runtime/tests/evaluator.rs +407 -0
  54. package/runtime/tests/helper_vectors.rs +348 -0
  55. package/runtime/tests/manifest.rs +169 -0
  56. package/runtime/tests/omit.rs +79 -0
  57. package/runtime/tests/props_attr.rs +75 -0
  58. package/runtime/tests/query.rs +50 -0
  59. package/runtime/tests/render_child.rs +210 -0
  60. package/runtime/tests/search_params.rs +68 -0
  61. package/runtime/tests/spread_attrs.rs +94 -0
  62. package/runtime/tests/template_primitives.rs +376 -0
  63. package/runtime/tests/vector-divergences.json +33 -0
  64. package/src/__tests__/minijinja-adapter-unit.test.ts +392 -0
  65. package/src/__tests__/minijinja-adapter.test.ts +58 -0
  66. package/src/__tests__/minijinja-counter.test.ts +61 -0
  67. package/src/__tests__/minijinja-query-href.test.ts +101 -0
  68. package/src/__tests__/minijinja-spread-attrs.test.ts +227 -0
  69. package/src/adapter/analysis/component-tree.ts +119 -0
  70. package/src/adapter/boolean-result.ts +177 -0
  71. package/src/adapter/emit-context.ts +119 -0
  72. package/src/adapter/expr/array-method.ts +346 -0
  73. package/src/adapter/expr/emitters.ts +608 -0
  74. package/src/adapter/index.ts +6 -0
  75. package/src/adapter/lib/constants.ts +37 -0
  76. package/src/adapter/lib/ir-scope.ts +95 -0
  77. package/src/adapter/lib/minijinja-naming.ts +85 -0
  78. package/src/adapter/lib/types.ts +35 -0
  79. package/src/adapter/memo/seed.ts +135 -0
  80. package/src/adapter/minijinja-adapter.ts +1796 -0
  81. package/src/adapter/props/prop-classes.ts +65 -0
  82. package/src/adapter/spread/spread-codegen.ts +168 -0
  83. package/src/adapter/value/parsed-literal.ts +76 -0
  84. package/src/build.ts +38 -0
  85. package/src/conformance-pins.ts +101 -0
  86. package/src/index.ts +12 -0
  87. package/src/test-render.ts +680 -0
@@ -0,0 +1,421 @@
1
+ /**
2
+ * BarefootJS minijinja (Rust) Template Adapter
3
+ *
4
+ * Generates Jinja2-compatible template files (.j2) from BarefootJS IR,
5
+ * rendered at conformance-test / runtime by the `minijinja` Rust crate
6
+ * (`packages/adapter-rust/runtime/`) instead of Python's `jinja2` package.
7
+ *
8
+ * Near-verbatim port of the Jinja2 adapter
9
+ * (packages/adapter-jinja/src/adapter/jinja-adapter.ts), itself a
10
+ * near-mechanical port of the Text::Xslate (Kolon) adapter
11
+ * (packages/adapter-xslate/src/adapter/xslate-adapter.ts). The EMITTED
12
+ * TEMPLATE SYNTAX IS IDENTICAL to adapter-jinja's output — minijinja 2.21 is
13
+ * Jinja2-compatible for everything this adapter emits (verified by an
14
+ * orchestrator spike; see the Environment contract below). Only identity
15
+ * fields differ (`MinijinjaAdapter`, `name = 'minijinja'`, `extension =
16
+ * '.j2'`) plus the render engine that interprets the syntax at request time.
17
+ * The syntax table below is therefore inherited unchanged from the Jinja2
18
+ * adapter's own header, which in turn documents its lineage from Kolon:
19
+ *
20
+ * Kolon `<: EXPR :>` → Jinja `{{ EXPR }}` (HTML-escaped)
21
+ * Kolon `<: EXPR | mark_raw :>` → Jinja `{{ EXPR | safe }}` (raw)
22
+ * Kolon `$bf.method(args)` → Jinja `bf.method(args)`
23
+ * Kolon `$name` → Jinja `name`
24
+ * Kolon `: if (C) { A : } else { B : }` → Jinja `{% if C %}A{% else %}B{% endif %}` (`elsif` → `{% elif %}`)
25
+ * Kolon `: for $arr -> $item { … : }` → Jinja `{% for item in arr %}…{% endfor %}`
26
+ * Kolon `: my $x = e;` → Jinja `{% set x = e %}`
27
+ * Kolon `{ k => v }` hashref → Jinja `{'k': v}` dict literal (ALWAYS quoted key — see `lib/minijinja-naming.ts`)
28
+ * Kolon `~` concat → Jinja `~` concat
29
+ * Kolon `//` defined-or → `(l if (l is defined and l is not none) else r)` inline (Jinja has no `//`; the `is defined` guard also treats a context var that was never seeded — Jinja's `ChainableUndefined`/minijinja's `UndefinedBehavior::Chainable` — as nullish, matching JS `??`'s null-OR-undefined check — see `expr/emitters.ts`'s `logical` for the full rationale)
30
+ * Kolon macro children capture → Jinja `{% set NAME %}…{% endset %}` set-block (see "Children capture" below)
31
+ *
32
+ * The `minijinja::Environment` this adapter's output assumes (constructed in
33
+ * the Rust runtime's `backend_minijinja.rs`, verified by the orchestrator
34
+ * spike against minijinja 2.21.0 — see that crate's module docs for the
35
+ * full verification notes):
36
+ *
37
+ * env.set_loader(minijinja::path_loader(templates_dir)); // .j2 files
38
+ * env.set_undefined_behavior(UndefinedBehavior::Chainable); // == Jinja2's ChainableUndefined; `missing.deep` renders '' — verified
39
+ * env.set_trim_blocks(true);
40
+ * env.set_lstrip_blocks(true);
41
+ * env.set_auto_escape_callback(|_| AutoEscape::Html); // REQUIRED: .j2 is not auto-escaped by default in minijinja
42
+ * env.set_formatter(<custom formatter>); // MarkupSafe-compatible &#39; (not minijinja's default &#x27;), JS-shaped number formatting via format_js_number as a fallback, true/false for bools, undefined/none print nothing
43
+ *
44
+ * `trim_blocks`/`lstrip_blocks` are required because this adapter places
45
+ * `{% … %}` control tags on their own source line (mirroring Kolon's
46
+ * line-statement `:` mode, which consumes its own line for free); without
47
+ * them every such line would leak a stray newline/indentation into the
48
+ * rendered HTML. Templates are named `<snake_case_component>.j2` (same
49
+ * convention as adapter-jinja's `.jinja` files and Xslate's `.tx` files).
50
+ *
51
+ * Divergences beyond the syntax table above (all uniform, not per-fixture —
52
+ * see the individual definition sites for the full rationale):
53
+ *
54
+ * 1. **JS truthiness** (`boolean-result.ts`, `expr/emitters.ts`'s
55
+ * `truthyTest`, this file's `convertConditionToJinja`). Python's `[]` /
56
+ * `{}` are falsy; JS's are truthy. Perl doesn't have this problem (a
57
+ * Perl reference is always true), so Kolon needed no truthy-routing
58
+ * layer. Every condition-TEST position (an `{% if %}` / `{% elif %}`
59
+ * test, a ternary test, the left operand of `&&`/`||`) routes through
60
+ * `bf.truthy(...)` unless it is structurally already boolean-shaped.
61
+ * 2. **Stringification** (`bf.string`, applied at every text/attribute
62
+ * interpolation position). Perl's default scalar stringification is
63
+ * close enough to JS's `String(x)` that Kolon only special-cases
64
+ * explicit `String()` calls and boolean-typed values (routed to
65
+ * `bf.bool_str`). Python's default `str()` diverges further —
66
+ * `str(True)` == `"True"`, `str(1.0)` == `"1.0"`, `str(None)` ==
67
+ * `"None"`, and Jinja's `~` concatenation operator calls `str()` on
68
+ * each operand internally — so this port explicitly routes EVERY
69
+ * text/attribute-position value (not already boolean-routed) through
70
+ * `bf.string(...)` before it reaches Jinja's own escaping/concat
71
+ * machinery. Verified empirically (`'a' ~ true ~ none` → `"aTrueNone"`
72
+ * under plain Jinja) — the reason this wrapping is mandatory, not
73
+ * cosmetic. This routing is retained unchanged for the minijinja port —
74
+ * the Rust runtime's own default `Display` formatting for a `Value`
75
+ * differs from CPython jinja2's `str()` in its own ways (float
76
+ * trailing-zero formatting in particular), so `bf.string(...)` stays
77
+ * the primary, uniform mechanism; the custom formatter's
78
+ * `format_js_number` (see the Environment contract above) is only a
79
+ * fallback for values that reach the formatter unrouted.
80
+ * 3. **No Jinja lambda** (`expr/emitters.ts` header, divergence 2). Kolon's
81
+ * `-> $x { … }` lambda — the Xslate top-level emitter's fallback when a
82
+ * predicate callback can't be serialized to the runtime evaluator's
83
+ * JSON form — has no Jinja equivalent. This adapter uses ONE mechanism
84
+ * for every higher-order callback (the evaluator-JSON `*_eval`
85
+ * payload); an unserializable predicate surfaces `BF101` instead of a
86
+ * lambda fallback. `.sort`'s non-lambda STRUCTURED fallback
87
+ * (`bf.sort` with a `{keys: […]}` descriptor) is unaffected and ports
88
+ * unchanged.
89
+ * 4. **Children/fallback capture via `{% set %}...{% endset %}`, never a
90
+ * macro.** Every Kolon macro-capture site in the ported adapter
91
+ * (`renderComponent`'s children forward, `renderAsync`'s fallback) is
92
+ * invoked immediately, in place, with zero arguments — never reused
93
+ * elsewhere or invoked lazily with different arguments. Jinja's
94
+ * set-block (`{% set NAME %}…{% endset %}`) captures exactly that
95
+ * shape as a safe HTML value (Python jinja2's `Markup`; minijinja's
96
+ * `Value::from_safe_string`, under the Environment's HTML
97
+ * auto-escape callback) with no macro indirection needed; the captured
98
+ * name is then referenced bare (`NAME`, not `NAME()`) everywhere the
99
+ * Kolon port called `NAME()`.
100
+ * 5. **Reserved-word identifier mangling** (`lib/minijinja-naming.ts`). Every
101
+ * bare Jinja variable reference / `{% set %}` target is passed through
102
+ * `minijinjaIdent()`; the Rust runtime must apply the IDENTICAL mangling
103
+ * (`mangle_ident` in `render_named`) when it builds the per-render
104
+ * context (so a prop literally named e.g. `class` is threaded through
105
+ * as context key `'class_'` on both sides). Dict-LITERAL keys are a
106
+ * separate, unconditional concern — see `minijinjaHashKey`'s docstring
107
+ * for why they are always quoted (unlike Kolon's bareword-key sugar).
108
+ * 6. **In-template signal/memo self-reference seeding is NOT skipped**
109
+ * (`memo/seed.ts`'s file header) — Jinja's `{% set x = x + 1 %}` safely
110
+ * resolves the right-hand `x` from the enclosing scope (verified
111
+ * empirically), unlike Kolon's `my`-shadowing hazard, so a same-name
112
+ * prop-derived signal/memo IS seeded in-template here (Xslate skips
113
+ * it). Strictly more correct, not merely a port artifact.
114
+ */
115
+ import type { ComponentIR, IRNode, IRElement, IRText, IRExpression, IRConditional, IRLoop, IRComponent, IRFragment, IRSlot, IRIfStatement, IRProvider, IRAsync, TemplatePrimitiveRegistry } from '@barefootjs/jsx';
116
+ import { BaseAdapter, type AdapterOutput, type AdapterGenerateOptions, type IRNodeEmitter, type EmitIRNode } from '@barefootjs/jsx';
117
+ import type { JinjaRenderCtx } from './lib/types.ts';
118
+ export type { MinijinjaAdapterOptions } from './lib/types.ts';
119
+ import type { MinijinjaAdapterOptions } from './lib/types.ts';
120
+ export declare class MinijinjaAdapter extends BaseAdapter implements IRNodeEmitter<JinjaRenderCtx> {
121
+ name: string;
122
+ extension: string;
123
+ templatesPerComponent: boolean;
124
+ importMapInjection: 'html-snippet';
125
+ /**
126
+ * Identifier-path callees the Jinja runtime can render in template scope.
127
+ * The relocate pass consults this map to mark matching calls as
128
+ * template-safe; the SSR template emitter substitutes the JS call with the
129
+ * registered `bf.NAME(...)` helper invocation.
130
+ */
131
+ templatePrimitives: TemplatePrimitiveRegistry;
132
+ private componentName;
133
+ /** Component root scope element(s) — each carries `data-key` for a keyed loop
134
+ * item (set by the child renderer from the JSX `key` prop). A plain element
135
+ * root is one node; an `if-statement` (early-return) root contributes the
136
+ * top element of every branch. */
137
+ private rootScopeNodes;
138
+ private options;
139
+ private errors;
140
+ private inLoop;
141
+ /**
142
+ * SolidJS-style props identifier (`function(props: P)`) and the
143
+ * analyzer-extracted prop names. Stashed at `generate()` entry so the
144
+ * per-attribute `emitSpread` callback can build a propsObject spread bag as
145
+ * an inline Jinja dict literal without re-walking the IR.
146
+ */
147
+ private propsObjectName;
148
+ private propsParams;
149
+ private booleanTypedProps;
150
+ /**
151
+ * Names (signal getters + props) whose value is a string. Carried for
152
+ * parity with the Perl-family adapters (Mojo needs it for `eq`/`ne`
153
+ * selection); the Jinja emitters don't consume it — Jinja's `==`/`!=`
154
+ * compare strings and numbers correctly.
155
+ */
156
+ private stringValueNames;
157
+ /**
158
+ * Module-scope pure-string consts (`const x = 'literal'`), keyed by name →
159
+ * unescaped value. A className template literal that references such a const
160
+ * (`className={`${x} ${className}`}`) must inline the literal: the const is
161
+ * module-scope, so it never reaches the per-render context, and a bare
162
+ * reference to `x` would resolve to Undefined.
163
+ */
164
+ private moduleStringConsts;
165
+ /**
166
+ * (#1922) Local binding names the request-scoped `searchParams()` env signal
167
+ * is imported under (handles `import { searchParams as sp }`). When non-empty
168
+ * the emitter lowers a `<binding>().get(k)` call to a real method call on the
169
+ * per-request `searchParams` reader (`searchParams.get('sort')`) instead of
170
+ * the generic dot deref. Set at `generate()` entry from `ir.metadata.imports`;
171
+ * read by the top-level ParsedExpr emitter.
172
+ */
173
+ private _searchParamsLocals;
174
+ /**
175
+ * Call-lowering matchers active for this component (#2057). Bound at
176
+ * `generate()` entry via `prepareLoweringMatchers` and read by the top-level
177
+ * emitter. Covers both userland plugins and the compiler's built-in plugins
178
+ * (e.g. `queryHref` → `bf.query`, #2042) — one uniform path, no per-API branch.
179
+ */
180
+ private _loweringMatchers;
181
+ /**
182
+ * Local + module constants from the IR, used by the conditional-spread and
183
+ * `Record<staticKeys, scalar>[propKey]` lowering paths (#textarea / #checkbox).
184
+ * Stashed at `generate()` entry so `emitSpread` can resolve a bare local
185
+ * const (`const sizeAttrs = size ? {…} : {}`) to its initializer text.
186
+ */
187
+ private localConstants;
188
+ /**
189
+ * Optional, no-default props that are `None` when the caller omits them.
190
+ * Their bare-reference attribute emission is guarded with a Jinja
191
+ * `is defined and is not none` test so the attribute DROPS rather than
192
+ * rendering `attr=""` (Hono-style nullish omission, e.g. textarea's
193
+ * `rows`). The filter excludes destructure-defaulted, rest, and
194
+ * concrete-primitive props.
195
+ */
196
+ private nullableOptionalProps;
197
+ constructor(options?: MinijinjaAdapterOptions);
198
+ generate(ir: ComponentIR, options?: AdapterGenerateOptions): AdapterOutput;
199
+ private generateScriptRegistrations;
200
+ /**
201
+ * Public entry point for node rendering. Delegates to the shared
202
+ * `IRNodeEmitter` dispatcher; per-kind logic lives in the `IRNodeEmitter`
203
+ * methods below.
204
+ */
205
+ renderNode(node: IRNode): string;
206
+ emitElement(node: IRElement, _ctx: JinjaRenderCtx, _emit: EmitIRNode<JinjaRenderCtx>): string;
207
+ emitText(node: IRText): string;
208
+ emitExpression(node: IRExpression): string;
209
+ emitConditional(node: IRConditional, _ctx: JinjaRenderCtx, _emit: EmitIRNode<JinjaRenderCtx>): string;
210
+ emitLoop(node: IRLoop, _ctx: JinjaRenderCtx, _emit: EmitIRNode<JinjaRenderCtx>): string;
211
+ emitComponent(node: IRComponent, _ctx: JinjaRenderCtx, _emit: EmitIRNode<JinjaRenderCtx>): string;
212
+ emitFragment(node: IRFragment, _ctx: JinjaRenderCtx, _emit: EmitIRNode<JinjaRenderCtx>): string;
213
+ emitSlot(node: IRSlot): string;
214
+ emitIfStatement(node: IRIfStatement, _ctx: JinjaRenderCtx, _emit: EmitIRNode<JinjaRenderCtx>): string;
215
+ emitProvider(node: IRProvider, _ctx: JinjaRenderCtx, _emit: EmitIRNode<JinjaRenderCtx>): string;
216
+ /** Lower a `<Ctx.Provider value>` value prop to a Jinja expression. */
217
+ private providerValueJinja;
218
+ /**
219
+ * Lower an object-literal provider value (`value={{ open: () => props.open
220
+ * ?? false, onOpenChange: … }}`) to a Jinja dict literal (#1897). The
221
+ * SSR lowering is a per-member snapshot of what a consumer would READ
222
+ * during the same render:
223
+ *
224
+ * - zero-param expression-body arrows are getters — lower the body (the
225
+ * value is fixed for the render, so the call-time indirection drops out)
226
+ * - `on[A-Z]`-named members and function-shaped values are client-only
227
+ * behavior SSR never invokes — lower to `none`
228
+ * - anything else lowers through the normal expression pipeline (so an
229
+ * unsupported getter body still refuses loudly with BF101)
230
+ *
231
+ * Keys keep their JS names verbatim so a consumer-side `ctx.open` access
232
+ * maps onto the same dict key. Returns `null` when the expression is not a
233
+ * plain object literal (spread / computed key) — the caller falls back to
234
+ * the whole-expression path, which refuses those shapes with BF101.
235
+ */
236
+ private providerObjectLiteralJinja;
237
+ emitAsync(node: IRAsync, _ctx: JinjaRenderCtx, _emit: EmitIRNode<JinjaRenderCtx>): string;
238
+ renderElement(element: IRElement): string;
239
+ renderExpression(expr: IRExpression): string;
240
+ renderConditional(cond: IRConditional): string;
241
+ private renderNodeOrNull;
242
+ /**
243
+ * Add bf-c attribute to the first HTML element in a branch.
244
+ * If no element found, wrap with comment markers.
245
+ */
246
+ private addCondMarkerToFirstElement;
247
+ renderLoop(loop: IRLoop): string;
248
+ /**
249
+ * AttrValue lowering for component invocation props (Jinja dict-entry
250
+ * form). Jinja CANNOT splat a dict into positional args, so every prop is
251
+ * emitted as a `'key': value` entry that the caller collects into ONE dict
252
+ * literal passed to `bf.render_child(name, { ... })`.
253
+ *
254
+ * `jsx-children` returns empty — children are captured via a Jinja
255
+ * set-block below, not threaded through the dict entry list.
256
+ */
257
+ private readonly componentPropEmitter;
258
+ /**
259
+ * A `renderComponent` props dict, built as an ORDERED sequence of
260
+ * segments so `{...before, ...spread, after: 1}` JSX spread semantics
261
+ * (later entries win) survive the trip through Jinja, which has no
262
+ * dict-splat syntax for anything past a SINGLE `**` per `dict(...)`
263
+ * call. Each `'entries'` segment is a literal Jinja dict `{'k': v, ...}`;
264
+ * each `'spread'` segment is an arbitrary expression lowered from a
265
+ * `{...expr}` prop. `combineComponentPropSegments` folds the sequence
266
+ * into ONE expression via nested `dict(base, **top)` calls (later
267
+ * segment wins on key conflict, matching `Object.assign`/JSX order).
268
+ */
269
+ private componentPropSegmentEntries;
270
+ /**
271
+ * Fold ordered prop segments into a single Jinja expression via nested
272
+ * `dict(base, **top)` calls — matching the CPython Jinja2 adapter's
273
+ * emitted syntax exactly (though minijinja itself tolerates more than
274
+ * one `**` per call, this adapter emits the SAME single-`**`-per-call
275
+ * nested form so the two engines stay syntax-identical): each
276
+ * successive segment wraps the accumulator as the positional `base`
277
+ * with the new segment `**`-unpacked on top, later argument wins on key
278
+ * conflict — exactly like `{...a, ...b}`. A spread segment's expression
279
+ * is wrapped `(EXPR or {})` before unpacking: minijinja's
280
+ * `UndefinedBehavior::Chainable` lets a missing bag (e.g.
281
+ * `children.props` when `children` was never passed) chain through
282
+ * member access without raising, but `**`-unpacking an undefined/none
283
+ * value still needs a concrete dict, so the `or {}` guard normalises it
284
+ * first (verified against the real minijinja crate v2 `bf-render`
285
+ * binary). Empty `'entries'` segments are dropped so a leading/trailing
286
+ * spread doesn't drag in a needless `dict({}, **...)`. Returns `'{}'`
287
+ * when every segment is empty (no props at all).
288
+ */
289
+ private combineComponentPropSegments;
290
+ renderComponent(comp: IRComponent): string;
291
+ private childrenCaptureCounter;
292
+ /** Uniquifies the `presenceOrUndefined` temp binding (`bf_puN`) so two
293
+ * presence-folded attrs in one template don't collide. */
294
+ private presenceVarCounter;
295
+ private toTemplateName;
296
+ private renderIfStatement;
297
+ private renderFragment;
298
+ private renderSlot;
299
+ renderAsync(node: IRAsync): string;
300
+ /**
301
+ * AttrValue lowering for intrinsic-element attributes (Jinja).
302
+ */
303
+ private readonly elementAttrEmitter;
304
+ /**
305
+ * Lower a `style={{ … }}` object literal to a CSS string with dynamic values
306
+ * interpolated as Jinja expressions, e.g. `{ backgroundColor: color }` →
307
+ * `background-color:{{ bf.string(color) }}`. Returns null when the shape is
308
+ * unsupported or any value can't be lowered (caller falls through to
309
+ * BF101). (#1322)
310
+ */
311
+ private tryLowerStyleObject;
312
+ /** HTML-attribute escape for static text inlined into a `"..."` attribute. */
313
+ private escapeAttrText;
314
+ private renderAttributes;
315
+ renderScopeMarker(_instanceIdExpr: string): string;
316
+ renderSlotMarker(slotId: string): string;
317
+ renderCondMarker(condId: string): string;
318
+ /**
319
+ * Convert a ParsedExpr AST to a Jinja expression string for filter
320
+ * predicates. Wraps the shared ParsedExpr dispatcher with a
321
+ * `JinjaFilterEmitter` carrying the predicate's loop param and any
322
+ * block-body local var aliases.
323
+ */
324
+ private renderJinjaFilterExpr;
325
+ private convertTemplateLiteralPartsToJinja;
326
+ /**
327
+ * Translate `${EXPR}` interpolations in a static template-part string into
328
+ * Jinja variable references and concatenate them with the surrounding
329
+ * literal text. Each interpolated (non-literal) segment routes through
330
+ * `bf.string(...)` — see the file header, divergence 2.
331
+ */
332
+ private substituteJsInterpolationsToJinja;
333
+ /**
334
+ * Refuse JS expression shapes that have no idiomatic Jinja representation:
335
+ * object literals (`style={{...}}`) and tagged-template-literal call
336
+ * expressions (`cn\`base \${tone()}\``). Records `BF101`. Returns `true`
337
+ * when the shape was rejected (caller should drop the attribute).
338
+ */
339
+ private refuseUnsupportedAttrExpression;
340
+ /**
341
+ * Build the EmitContext seam the top-level `ParsedExpr` emitter depends on.
342
+ * Built as a private object (the adapter does NOT `implements JinjaEmitContext`)
343
+ * so the wrapped bookkeeping — `_searchParamsLocals`, the const/record
344
+ * resolvers, BF101 recording, the filter-predicate entry — stays private and
345
+ * off the exported adapter's public type, matching the Go adapter's
346
+ * `emitCtx` and the `spreadCtx` / `memoCtx` seams below.
347
+ */
348
+ private get emitCtx();
349
+ /**
350
+ * Build the narrow context the extracted spread lowering depends on. Passing
351
+ * a purpose-built object (rather than `this`) keeps the adapter's bookkeeping
352
+ * members private — they stay internal implementation detail, not part of the
353
+ * exported class's public surface.
354
+ */
355
+ private get spreadCtx();
356
+ /** Build the narrow context the extracted memo seeding depends on. */
357
+ private get memoCtx();
358
+ private convertExpressionToJinja;
359
+ /**
360
+ * Convert a JS condition (an `if` / ternary / loop-filter test) to a Jinja
361
+ * boolean expression, routing through `bf.truthy(...)` unless the
362
+ * expression is structurally already boolean-shaped. See the file header,
363
+ * divergence 1.
364
+ */
365
+ private convertConditionToJinja;
366
+ /**
367
+ * Shared helper: given the ORIGINAL JS expression (or its already-parsed
368
+ * tree) and its ALREADY-RENDERED Jinja text, wrap the rendered text with
369
+ * `bf.truthy(...)` unless the expression is structurally boolean-shaped.
370
+ * Split from `convertConditionToJinja` so a caller that already lowered the
371
+ * expression for another purpose (e.g. the `presenceOrUndefined` temp bind)
372
+ * doesn't lower it twice.
373
+ */
374
+ private wrapConditionExpr;
375
+ /**
376
+ * Render a full ParsedExpr tree to Jinja for top-level (non-filter)
377
+ * expressions where identifiers are signals / template vars.
378
+ */
379
+ private renderParsedExprToJinja;
380
+ /** Whether `name` (a signal getter or prop) holds a string value. Carried
381
+ * for parity with the Perl-family adapters; the Jinja emitters don't
382
+ * consume it (Jinja's `==`/`!=` compare strings and numbers correctly). */
383
+ private _isStringValueName;
384
+ /**
385
+ * Parse `cond ? value : undefined` (or `: null`), returning the
386
+ * condition/consequent source spans, else `null`. Used for the
387
+ * attribute-omission rule (#1897).
388
+ */
389
+ parseUndefinedAlternateTernary(expr: string): {
390
+ condition: string;
391
+ consequent: string;
392
+ } | null;
393
+ isBooleanTypedPropRef(expr: string): boolean;
394
+ /**
395
+ * Whether an attribute-value expression should route through
396
+ * `bf.bool_str` (vs. plain `bf.string`) at its interpolation site.
397
+ * `isExplicitStringCall` is checked FIRST and short-circuits the other
398
+ * three: an explicit `String(x)` call already lowers to `bf.string(x)`,
399
+ * which — unlike Kolon's Perl port — correctly stringifies a real
400
+ * boolean on its own (see `runtime.js_string`'s bool branch), so
401
+ * layering `bf.bool_str` on top would run Python truthiness over the
402
+ * ALREADY-STRINGIFIED text instead of the original boolean. See
403
+ * `isExplicitStringCall`'s docstring in `boolean-result.ts` for the full
404
+ * double-wrap failure mode this guards against.
405
+ */
406
+ private shouldBoolStr;
407
+ /**
408
+ * Inline a const (any scope) whose initializer is a pure numeric or
409
+ * single-quoted string literal (`const totalPages = 5`, #1897
410
+ * pagination) — function-scope consts never reach the per-render
411
+ * context, so a bare reference would resolve to Undefined.
412
+ */
413
+ private _resolveLiteralConst;
414
+ private _resolveStaticRecordLiteral;
415
+ private _resolveModuleStringConst;
416
+ private _recordExprBF101;
417
+ /** Internal hook for higher-order: predicate body re-uses the filter emitter. */
418
+ private _renderJinjaFilterExprPublic;
419
+ }
420
+ export declare const minijinjaAdapter: MinijinjaAdapter;
421
+ //# sourceMappingURL=minijinja-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"minijinja-adapter.d.ts","sourceRoot":"","sources":["../../src/adapter/minijinja-adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Prop classification for the minijinja template adapter.
3
+ *
4
+ * Ported from `packages/adapter-xslate/src/adapter/props/prop-classes.ts`.
5
+ * Pure functions over `ir.metadata` that derive the per-compile prop/name
6
+ * sets the adapter consults during lowering. No adapter instance state.
7
+ */
8
+ import type { ComponentIR } from '@barefootjs/jsx';
9
+ /**
10
+ * Props whose declared TS type is boolean — a bare binding of one
11
+ * (`data-active={props.isActive}`) must stringify as JS `String(boolean)`
12
+ * ("true"/"false"), not Python's `str(bool)` ("True"/"False") (#1897,
13
+ * pagination's data-active).
14
+ */
15
+ export declare function collectBooleanTypedProps(ir: ComponentIR): Set<string>;
16
+ /**
17
+ * Bare references to optional, no-default, non-primitive props (e.g.
18
+ * textarea's `rows`) are `None` when omitted → guarded with
19
+ * `is defined and is not none` in `emitExpression`. See the
20
+ * `nullableOptionalProps` field docstring in `minijinja-adapter.ts`.
21
+ */
22
+ export declare function collectNullableOptionalProps(ir: ComponentIR): Set<string>;
23
+ /**
24
+ * String-typed signals and props. A signal is string-typed when its inferred
25
+ * type is `string` (or, defensively, when its initial value is a bare string
26
+ * literal); a prop when its annotated type is `string`. In the Mojo adapter
27
+ * this drives `eq`/`ne` selection for string equality; neither the Kolon nor
28
+ * the Jinja emitters consume the distinction (both languages' `==`/`!=`
29
+ * compare strings and numbers correctly), so this set is carried for parity
30
+ * with the Perl-family adapters, not because Jinja needs it today.
31
+ */
32
+ export declare function collectStringValueNames(ir: ComponentIR): Set<string>;
33
+ //# sourceMappingURL=prop-classes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prop-classes.d.ts","sourceRoot":"","sources":["../../../src/adapter/props/prop-classes.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAGlD;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,EAAE,EAAE,WAAW,GAAG,GAAG,CAAC,MAAM,CAAC,CAMrE;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAAC,EAAE,EAAE,WAAW,GAAG,GAAG,CAAC,MAAM,CAAC,CAWzE;AAED;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,WAAW,GAAG,GAAG,CAAC,MAAM,CAAC,CAWpE"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Object-literal / conditional-spread → Jinja dict lowering for the
3
+ * minijinja template adapter.
4
+ *
5
+ * Near-verbatim port of
6
+ * `packages/adapter-jinja/src/adapter/spread/spread-codegen.ts` (itself
7
+ * ported from `packages/adapter-xslate/src/adapter/spread/spread-codegen.ts`).
8
+ * Free functions taking a `JinjaSpreadContext` (built by the adapter's
9
+ * `spreadCtx` getter) so the cluster depends on the narrow seam — the
10
+ * recursive expression entry plus per-compile bookkeeping — rather than the
11
+ * whole adapter class.
12
+ *
13
+ * The conditional-spread / object-literal entries read the IR-carried
14
+ * structured `ParsedExpr` tree (#2018) instead of re-parsing the source with
15
+ * `ts.createSourceFile`. The condition and scalar values are threaded
16
+ * straight into `ctx.convertExpressionToJinja` as its `preParsed` argument,
17
+ * so no stringify→re-parse round-trip occurs. The `ts.factory` rebuild in
18
+ * `recordIndexAccessToJinja` only reconstructs the `IDENT[KEY]` node the
19
+ * shared `parseRecordIndexAccess` parser accepts; no source-text re-parse.
20
+ */
21
+ import type { ParsedExpr } from '@barefootjs/jsx';
22
+ import type { JinjaSpreadContext } from '../emit-context.ts';
23
+ /**
24
+ * Lower a conditional inline-object spread
25
+ * `COND ? { 'aria-describedby': describedBy } : {}`
26
+ * to a Jinja inline ternary of dicts
27
+ * `({'aria-describedby': describedBy} if bf.truthy(describedBy) else {})`.
28
+ * Reads the IR-carried structured `ParsedExpr` tree; both branches must be
29
+ * object literals; the condition + values route through
30
+ * `convertExpressionToJinja`. Returns `null` for any other shape so the
31
+ * caller falls back to its normal lowering.
32
+ */
33
+ export declare function conditionalSpreadToJinja(ctx: JinjaSpreadContext, expr: ParsedExpr | undefined): string | null;
34
+ /**
35
+ * (#1971) Lower a bare object-literal expression (`{ align: 'start' }`),
36
+ * carried as the IR's structured `ParsedExpr` tree, to a Jinja dict via
37
+ * `objectLiteralToJinjaDict`, or null when it isn't a plain object literal.
38
+ * Used for inline object-literal child props (carousel `opts`).
39
+ */
40
+ export declare function objectLiteralExprToJinjaDict(ctx: JinjaSpreadContext, expr: ParsedExpr | undefined): string | null;
41
+ /**
42
+ * Convert a static object literal into a Jinja dict string for a
43
+ * conditional spread. Only static string/identifier keys are allowed; values
44
+ * resolve via `convertExpressionToJinja` (or the `Record[propKey]` index
45
+ * lowering). Returns `null` for any computed/spread/dynamic key. Empty
46
+ * object → `{}`.
47
+ */
48
+ export declare function objectLiteralToJinjaDict(ctx: JinjaSpreadContext, obj: Extract<ParsedExpr, {
49
+ kind: 'object-literal';
50
+ }>): string | null;
51
+ /**
52
+ * Lower a spread-object VALUE of the form `IDENT[KEY]` (CheckIcon's
53
+ * `sizeMap[size]`) to an inline indexed Jinja dict
54
+ * `{'sm': 16, 'md': 20, ...}[size]`.
55
+ * Reuses the shared structural parse (`parseRecordIndexAccess`) — rebuilding
56
+ * the `IDENT[KEY]` node from the carried tree via `ts.factory` rather than
57
+ * re-parsing source text; this wrapper only does the single-quote escaping +
58
+ * bracket-index emit. Jinja indexes a dict literal with the SAME bracket
59
+ * syntax `{…}[key]` a JS object index would use — no Kolon-style divergence
60
+ * to steer around here.
61
+ */
62
+ export declare function recordIndexAccessToJinja(ctx: JinjaSpreadContext, val: ParsedExpr): string | null;
63
+ //# sourceMappingURL=spread-codegen.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spread-codegen.d.ts","sourceRoot":"","sources":["../../../src/adapter/spread/spread-codegen.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAEjD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAG5D;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,kBAAkB,EACvB,IAAI,EAAE,UAAU,GAAG,SAAS,GAC3B,MAAM,GAAG,IAAI,CAcf;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAC1C,GAAG,EAAE,kBAAkB,EACvB,IAAI,EAAE,UAAU,GAAG,SAAS,GAC3B,MAAM,GAAG,IAAI,CAGf;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,kBAAkB,EACvB,GAAG,EAAE,OAAO,CAAC,UAAU,EAAE;IAAE,IAAI,EAAE,gBAAgB,CAAA;CAAE,CAAC,GACnD,MAAM,GAAG,IAAI,CA0Cf;AAUD;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,kBAAkB,EAAE,GAAG,EAAE,UAAU,GAAG,MAAM,GAAG,IAAI,CAuBhG"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * String-literal value lowering for the minijinja template adapter.
3
+ *
4
+ * Ported from `packages/adapter-xslate/src/adapter/value/parsed-literal.ts`.
5
+ * Pure functions over const-initializer source text and analyzer type info —
6
+ * no adapter instance state. Byte-identical logic to the Xslate copy (the
7
+ * source-text parsing here is language-agnostic; only the caller's escaping
8
+ * of the resolved value into a template literal differs, and that happens at
9
+ * the call site in `minijinja-adapter.ts`, not here).
10
+ */
11
+ import { type TypeInfo } from '@barefootjs/jsx';
12
+ /**
13
+ * Parse a const initializer's source text. Returns the unescaped string value
14
+ * when the whole initializer is a single pure string literal — single/double
15
+ * quoted, or a no-substitution backtick template (no `${}`) — else `null`.
16
+ * Only such a value can be inlined byte-for-byte; template literals with
17
+ * interpolation, numbers, objects, and `Record<T,string>` maps are excluded.
18
+ */
19
+ export declare function parsePureStringLiteral(source: string): string | null;
20
+ /** Whether `s` contains an unescaped occurrence of `ch`. */
21
+ export declare function containsUnescaped(s: string, ch: string): boolean;
22
+ /** Unescape a JS string-literal body's common escape sequences. */
23
+ export declare function unescapeStringLiteralBody(s: string): string;
24
+ /** True when `type` is the `string` primitive. */
25
+ export declare function isStringTypeInfo(type: TypeInfo | undefined): boolean;
26
+ /** True when `initialValue` is a bare string-literal expression. */
27
+ export declare function isBareStringLiteral(initialValue: string | undefined): boolean;
28
+ //# sourceMappingURL=parsed-literal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parsed-literal.d.ts","sourceRoot":"","sources":["../../../src/adapter/value/parsed-literal.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAuB,KAAK,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AAEpE;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAqBpE;AAED,4DAA4D;AAC5D,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAMhE;AAED,mEAAmE;AACnE,wBAAgB,yBAAyB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAU3D;AAED,kDAAkD;AAClD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,OAAO,CAEpE;AAED,oEAAoE;AACpE,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAI7E"}
@@ -0,0 +1,29 @@
1
+ import type { BuildOptions } from '@barefootjs/jsx';
2
+ import { MinijinjaAdapter } from './adapter/index.ts';
3
+ import type { MinijinjaAdapterOptions } from './adapter/index.ts';
4
+ export interface MinijinjaBuildOptions extends BuildOptions {
5
+ /** Adapter-specific options passed to MinijinjaAdapter */
6
+ adapterOptions?: MinijinjaAdapterOptions;
7
+ }
8
+ /**
9
+ * Create a BarefootBuildConfig for minijinja (Jinja2-compatible) template
10
+ * projects.
11
+ *
12
+ * Uses structural typing — does not import BarefootBuildConfig to avoid a
13
+ * circular dependency between @barefootjs/rust and @barefootjs/cli.
14
+ */
15
+ export declare function createConfig(options?: MinijinjaBuildOptions): {
16
+ adapter: MinijinjaAdapter;
17
+ paths: import("@barefootjs/jsx").BarefootPaths | undefined;
18
+ components: string[] | undefined;
19
+ outDir: string | undefined;
20
+ minify: boolean | undefined;
21
+ contentHash: boolean | undefined;
22
+ externals: Record<string, import("@barefootjs/jsx").ExternalSpec> | undefined;
23
+ externalsBasePath: string | undefined;
24
+ bundleEntries: import("@barefootjs/jsx").BundleEntry[] | undefined;
25
+ localImportPrefixes: string[] | undefined;
26
+ outputLayout: import("@barefootjs/jsx").OutputLayout;
27
+ postBuild: ((ctx: import("@barefootjs/jsx").PostBuildContext) => Promise<void> | void) | undefined;
28
+ };
29
+ //# sourceMappingURL=build.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AACrD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAA;AAEjE,MAAM,WAAW,qBAAsB,SAAQ,YAAY;IACzD,0DAA0D;IAC1D,cAAc,CAAC,EAAE,uBAAuB,CAAA;CACzC;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,OAAO,GAAE,qBAA0B;IAE5D,OAAO;IACP,KAAK;IACL,UAAU;IACV,MAAM;IACN,MAAM;IACN,WAAW;IACX,SAAS;IACT,iBAAiB;IACjB,aAAa;IACb,mBAAmB;IACnB,YAAY;IAKZ,SAAS;EAEZ"}