@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.
- package/README.md +194 -0
- package/dist/adapter/analysis/component-tree.d.ts +26 -0
- package/dist/adapter/analysis/component-tree.d.ts.map +1 -0
- package/dist/adapter/boolean-result.d.ts +85 -0
- package/dist/adapter/boolean-result.d.ts.map +1 -0
- package/dist/adapter/emit-context.d.ts +107 -0
- package/dist/adapter/emit-context.d.ts.map +1 -0
- package/dist/adapter/expr/array-method.d.ts +75 -0
- package/dist/adapter/expr/array-method.d.ts.map +1 -0
- package/dist/adapter/expr/emitters.d.ts +143 -0
- package/dist/adapter/expr/emitters.d.ts.map +1 -0
- package/dist/adapter/index.d.ts +6 -0
- package/dist/adapter/index.d.ts.map +1 -0
- package/dist/adapter/index.js +189091 -0
- package/dist/adapter/lib/constants.d.ts +25 -0
- package/dist/adapter/lib/constants.d.ts.map +1 -0
- package/dist/adapter/lib/ir-scope.d.ts +50 -0
- package/dist/adapter/lib/ir-scope.d.ts.map +1 -0
- package/dist/adapter/lib/minijinja-naming.d.ts +64 -0
- package/dist/adapter/lib/minijinja-naming.d.ts.map +1 -0
- package/dist/adapter/lib/types.d.ts +32 -0
- package/dist/adapter/lib/types.d.ts.map +1 -0
- package/dist/adapter/memo/seed.d.ts +84 -0
- package/dist/adapter/memo/seed.d.ts.map +1 -0
- package/dist/adapter/minijinja-adapter.d.ts +421 -0
- package/dist/adapter/minijinja-adapter.d.ts.map +1 -0
- package/dist/adapter/props/prop-classes.d.ts +33 -0
- package/dist/adapter/props/prop-classes.d.ts.map +1 -0
- package/dist/adapter/spread/spread-codegen.d.ts +63 -0
- package/dist/adapter/spread/spread-codegen.d.ts.map +1 -0
- package/dist/adapter/value/parsed-literal.d.ts +28 -0
- package/dist/adapter/value/parsed-literal.d.ts.map +1 -0
- package/dist/build.d.ts +29 -0
- package/dist/build.d.ts.map +1 -0
- package/dist/build.js +189111 -0
- package/dist/conformance-pins.d.ts +13 -0
- package/dist/conformance-pins.d.ts.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +189112 -0
- package/package.json +67 -0
- package/runtime/Cargo.lock +124 -0
- package/runtime/Cargo.toml +21 -0
- package/runtime/src/backend_minijinja.rs +176 -0
- package/runtime/src/bin/bf-render.rs +147 -0
- package/runtime/src/evaluator.rs +770 -0
- package/runtime/src/lib.rs +19 -0
- package/runtime/src/manifest.rs +258 -0
- package/runtime/src/num.rs +558 -0
- package/runtime/src/runtime.rs +1548 -0
- package/runtime/src/search_params.rs +173 -0
- package/runtime/tests/eval_vectors.rs +94 -0
- package/runtime/tests/evaluator.rs +407 -0
- package/runtime/tests/helper_vectors.rs +348 -0
- package/runtime/tests/manifest.rs +169 -0
- package/runtime/tests/omit.rs +79 -0
- package/runtime/tests/props_attr.rs +75 -0
- package/runtime/tests/query.rs +50 -0
- package/runtime/tests/render_child.rs +210 -0
- package/runtime/tests/search_params.rs +68 -0
- package/runtime/tests/spread_attrs.rs +94 -0
- package/runtime/tests/template_primitives.rs +376 -0
- package/runtime/tests/vector-divergences.json +33 -0
- package/src/__tests__/minijinja-adapter-unit.test.ts +392 -0
- package/src/__tests__/minijinja-adapter.test.ts +58 -0
- package/src/__tests__/minijinja-counter.test.ts +61 -0
- package/src/__tests__/minijinja-query-href.test.ts +101 -0
- package/src/__tests__/minijinja-spread-attrs.test.ts +227 -0
- package/src/adapter/analysis/component-tree.ts +119 -0
- package/src/adapter/boolean-result.ts +177 -0
- package/src/adapter/emit-context.ts +119 -0
- package/src/adapter/expr/array-method.ts +346 -0
- package/src/adapter/expr/emitters.ts +608 -0
- package/src/adapter/index.ts +6 -0
- package/src/adapter/lib/constants.ts +37 -0
- package/src/adapter/lib/ir-scope.ts +95 -0
- package/src/adapter/lib/minijinja-naming.ts +85 -0
- package/src/adapter/lib/types.ts +35 -0
- package/src/adapter/memo/seed.ts +135 -0
- package/src/adapter/minijinja-adapter.ts +1796 -0
- package/src/adapter/props/prop-classes.ts +65 -0
- package/src/adapter/spread/spread-codegen.ts +168 -0
- package/src/adapter/value/parsed-literal.ts +76 -0
- package/src/build.ts +38 -0
- package/src/conformance-pins.ts +101 -0
- package/src/index.ts +12 -0
- 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 ' (not minijinja's default '), 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"}
|
package/dist/build.d.ts
ADDED
|
@@ -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"}
|