@barefootjs/go-template 0.15.2 → 0.17.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/dist/adapter/analysis/component-tree.d.ts +23 -0
- package/dist/adapter/analysis/component-tree.d.ts.map +1 -0
- package/dist/adapter/emit-context.d.ts +53 -0
- package/dist/adapter/emit-context.d.ts.map +1 -0
- package/dist/adapter/expr/helper-inline.d.ts +31 -0
- package/dist/adapter/expr/helper-inline.d.ts.map +1 -0
- package/dist/adapter/expr/url-builder.d.ts +23 -0
- package/dist/adapter/expr/url-builder.d.ts.map +1 -0
- package/dist/adapter/go-template-adapter.d.ts +291 -1070
- package/dist/adapter/go-template-adapter.d.ts.map +1 -1
- package/dist/adapter/index.js +2859 -2618
- package/dist/adapter/lib/compile-state.d.ts +116 -0
- package/dist/adapter/lib/compile-state.d.ts.map +1 -0
- package/dist/adapter/lib/constants.d.ts +11 -0
- package/dist/adapter/lib/constants.d.ts.map +1 -0
- package/dist/adapter/lib/go-emit.d.ts +117 -0
- package/dist/adapter/lib/go-emit.d.ts.map +1 -0
- package/dist/adapter/lib/go-naming.d.ts +39 -0
- package/dist/adapter/lib/go-naming.d.ts.map +1 -0
- package/dist/adapter/lib/ir-scope.d.ts +13 -0
- package/dist/adapter/lib/ir-scope.d.ts.map +1 -0
- package/dist/adapter/lib/types.d.ts +165 -0
- package/dist/adapter/lib/types.d.ts.map +1 -0
- package/dist/adapter/memo/ctor-lowering.d.ts +39 -0
- package/dist/adapter/memo/ctor-lowering.d.ts.map +1 -0
- package/dist/adapter/memo/memo-compute.d.ts +124 -0
- package/dist/adapter/memo/memo-compute.d.ts.map +1 -0
- package/dist/adapter/memo/memo-type.d.ts +38 -0
- package/dist/adapter/memo/memo-type.d.ts.map +1 -0
- package/dist/adapter/memo/memo-value.d.ts +64 -0
- package/dist/adapter/memo/memo-value.d.ts.map +1 -0
- package/dist/adapter/memo/template-interp.d.ts +43 -0
- package/dist/adapter/memo/template-interp.d.ts.map +1 -0
- package/dist/adapter/props/prop-types.d.ts +31 -0
- package/dist/adapter/props/prop-types.d.ts.map +1 -0
- package/dist/adapter/spread/spread-codegen.d.ts +40 -0
- package/dist/adapter/spread/spread-codegen.d.ts.map +1 -0
- package/dist/adapter/type/type-codegen.d.ts +25 -0
- package/dist/adapter/type/type-codegen.d.ts.map +1 -0
- package/dist/adapter/value/parsed-literal-to-go.d.ts +17 -0
- package/dist/adapter/value/parsed-literal-to-go.d.ts.map +1 -0
- package/dist/adapter/value/value-lowering.d.ts +46 -0
- package/dist/adapter/value/value-lowering.d.ts.map +1 -0
- package/dist/build.js +2857 -2616
- package/dist/index.js +2859 -2618
- package/dist/test-render.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/__tests__/derived-state-memo.test.ts +155 -84
- package/src/__tests__/go-template-adapter.test.ts +211 -60
- package/src/__tests__/lowering-plugin.test.ts +109 -0
- package/src/__tests__/query-href.test.ts +179 -0
- package/src/adapter/analysis/component-tree.ts +174 -0
- package/src/adapter/emit-context.ts +59 -0
- package/src/adapter/expr/helper-inline.ts +274 -0
- package/src/adapter/expr/url-builder.ts +123 -0
- package/src/adapter/go-template-adapter.ts +2100 -5316
- package/src/adapter/lib/compile-state.ts +150 -0
- package/src/adapter/lib/constants.ts +24 -0
- package/src/adapter/lib/go-emit.ts +289 -0
- package/src/adapter/lib/go-naming.ts +84 -0
- package/src/adapter/lib/ir-scope.ts +31 -0
- package/src/adapter/lib/types.ts +182 -0
- package/src/adapter/memo/ctor-lowering.ts +267 -0
- package/src/adapter/memo/memo-compute.ts +451 -0
- package/src/adapter/memo/memo-type.ts +74 -0
- package/src/adapter/memo/memo-value.ts +197 -0
- package/src/adapter/memo/template-interp.ts +246 -0
- package/src/adapter/props/prop-types.ts +84 -0
- package/src/adapter/spread/spread-codegen.ts +458 -0
- package/src/adapter/type/type-codegen.ts +95 -0
- package/src/adapter/value/parsed-literal-to-go.ts +94 -0
- package/src/adapter/value/value-lowering.ts +162 -0
- package/src/test-render.ts +2 -14
|
@@ -1,32 +1,8 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
import type { ComponentIR, IRNode, IRElement, IRText, IRExpression, IRConditional, IRLoop, IRComponent, IRFragment, IRSlot, ParsedExpr, SortComparator, ReduceOp, FlatDepth, FlatMapOp, TemplatePart, IRIfStatement, IRProvider, IRAsync, TemplatePrimitiveRegistry } from '@barefootjs/jsx';
|
|
7
|
-
import { BaseAdapter, type AdapterOutput, type AdapterGenerateOptions, type ParsedExprEmitter, type HigherOrderMethod, type ArrayMethod, type LiteralType, type IRNodeEmitter, type EmitIRNode } from '@barefootjs/jsx';
|
|
8
|
-
/**
|
|
9
|
-
* Go-template adapter's IRNode render context. Only `isRootOfClientComponent`
|
|
10
|
-
* is consumed today (forwarded into `renderComponent` / `renderIfStatement`);
|
|
11
|
-
* the type stays open so future render-position flags can be added without
|
|
12
|
-
* widening the `IRNodeEmitter` contract.
|
|
13
|
-
*/
|
|
14
|
-
type GoRenderCtx = {
|
|
15
|
-
isRootOfClientComponent?: boolean;
|
|
16
|
-
};
|
|
17
|
-
export interface GoTemplateAdapterOptions {
|
|
18
|
-
/** Go package name for generated types (default: 'components') */
|
|
19
|
-
packageName?: string;
|
|
20
|
-
/**
|
|
21
|
-
* Base path for client JS files (e.g., '/static/client/').
|
|
22
|
-
* Used to generate script registration paths.
|
|
23
|
-
*/
|
|
24
|
-
clientJsBasePath?: string;
|
|
25
|
-
/**
|
|
26
|
-
* Path to barefoot.js runtime (e.g., '/static/client/barefoot.js').
|
|
27
|
-
*/
|
|
28
|
-
barefootJsPath?: string;
|
|
29
|
-
}
|
|
1
|
+
/** BarefootJS adapter: BarefootJS IR → Go `html/template` files. */
|
|
2
|
+
import type { ComponentIR, IRNode, IRElement, IRText, IRExpression, IRConditional, IRLoop, IRComponent, IRFragment, IRSlot, CompilerError, ParsedExpr, ObjectLiteralProperty, FlatDepth, TemplatePart, IRIfStatement, IRProvider, IRAsync, TemplatePrimitiveRegistry } from '@barefootjs/jsx';
|
|
3
|
+
import { BaseAdapter, type AdapterOutput, type AdapterGenerateOptions, type ParsedExprEmitter, type ArrayMethod, type LiteralType, type IRNodeEmitter, type EmitIRNode } from '@barefootjs/jsx';
|
|
4
|
+
import type { GoRenderCtx, GoTemplateAdapterOptions } from "./lib/types.ts";
|
|
5
|
+
export type { GoTemplateAdapterOptions } from "./lib/types.ts";
|
|
30
6
|
export declare class GoTemplateAdapter extends BaseAdapter implements ParsedExprEmitter, IRNodeEmitter<GoRenderCtx> {
|
|
31
7
|
name: string;
|
|
32
8
|
extension: string;
|
|
@@ -35,247 +11,87 @@ export declare class GoTemplateAdapter extends BaseAdapter implements ParsedExpr
|
|
|
35
11
|
private filterExprDepth;
|
|
36
12
|
private filterExprUnsupported;
|
|
37
13
|
/**
|
|
38
|
-
* Identifier-path callees the Go runtime can render in template
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
* `call` branch) uses the same map to substitute the JS call with
|
|
43
|
-
* the registered Go template form.
|
|
44
|
-
*
|
|
45
|
-
* Keys are the textual callee path as written in the JSX
|
|
46
|
-
* expression. Values are emit functions that receive the already-
|
|
47
|
-
* Go-rendered argument expressions (e.g. `.Config`, `_p.Score`)
|
|
48
|
-
* and return the substituted Go template body — without the
|
|
49
|
-
* surrounding `{{ }}` action delimiters, so callers can wrap the
|
|
50
|
-
* result in `{{...}}` or compose into larger expressions like
|
|
51
|
-
* `{{if eq (bf_json .X) "..."}}`.
|
|
52
|
-
*
|
|
53
|
-
* V1 scope (#1187 R1): identifier-path callees only. Method calls
|
|
54
|
-
* on values (`(arr).join(",")`) require analyzer-resolved receiver
|
|
55
|
-
* type and are explicitly out of scope — users fall back to
|
|
56
|
-
* `/* @client *\/` for those.
|
|
14
|
+
* Identifier-path callees the Go runtime can render in template scope, keyed
|
|
15
|
+
* by the textual callee path as written in JSX. Each value emits the
|
|
16
|
+
* substituted Go body from already-Go-rendered args, WITHOUT the `{{ }}`
|
|
17
|
+
* delimiters so callers compose it (`{{if eq (bf_json .X) "..."}}`).
|
|
57
18
|
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
* deliberate.
|
|
19
|
+
* Identifier-path callees only; method calls on values (`(arr).join(",")`)
|
|
20
|
+
* need an analyzer-resolved receiver type and are out of scope. Public
|
|
21
|
+
* because the relocate pass reads it for boolean acceptance.
|
|
62
22
|
*/
|
|
63
23
|
templatePrimitives: TemplatePrimitiveRegistry;
|
|
64
24
|
/**
|
|
65
|
-
* Expected arg count per primitive
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
* Derived from `GO_TEMPLATE_PRIMITIVES` so it can't drift from
|
|
71
|
-
* `templatePrimitives` — a wrong-arity call falls back to the
|
|
72
|
-
* standard BF101 unsupported-call diagnostic.
|
|
25
|
+
* Expected arg count per primitive, so a wrong-arity call (`JSON.stringify()`,
|
|
26
|
+
* `JSON.stringify(x, replacer)`) falls back to BF101 instead of emitting
|
|
27
|
+
* invalid Go from the emit fn's blind `args[0]` read. Derived from
|
|
28
|
+
* `GO_TEMPLATE_PRIMITIVES` so it can't drift from `templatePrimitives`.
|
|
73
29
|
*/
|
|
74
30
|
private readonly templatePrimitiveArities;
|
|
75
|
-
private componentName;
|
|
76
31
|
private options;
|
|
77
|
-
|
|
32
|
+
/** Per-compile mutable state, reset at `generate()` / `generateTypes()` entry. See `CompileState` for the field-by-field docs. */
|
|
33
|
+
private readonly state;
|
|
78
34
|
/**
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
* string — they render through a per-call-site define executed via
|
|
84
|
-
* `bf_tmpl` with the PARENT's data, and the result is injected into
|
|
85
|
-
* the child props with `bf_with_children`. Flushed after the main
|
|
86
|
-
* define in `generate()`.
|
|
35
|
+
* The `GoEmitContext` handed to extracted emit modules — the seam that keeps
|
|
36
|
+
* `state` / `convert*` off the public adapter type. `state` is captured by
|
|
37
|
+
* reference (reset in place, never reassigned), so this single `emitCtx` stays
|
|
38
|
+
* valid across `generate()` calls.
|
|
87
39
|
*/
|
|
88
|
-
private
|
|
40
|
+
private readonly emitCtx;
|
|
41
|
+
/** Diagnostics from the current compile (backed by `CompileState`); `generate()` also merges these into `ir.errors`. */
|
|
42
|
+
get errors(): CompilerError[];
|
|
43
|
+
private inLoop;
|
|
89
44
|
private loopParamStack;
|
|
45
|
+
/**
|
|
46
|
+
* Per-loop: true when the body renders the bare range value (scalar-item
|
|
47
|
+
* inline-literal loop), so the `bf_tmpl` companion is fed `.BfLoopItem` (the
|
|
48
|
+
* wrapper's synthetic scalar field) instead of `.`. Innermost last.
|
|
49
|
+
*/
|
|
50
|
+
private loopScalarItemStack;
|
|
90
51
|
private loopVarRefCount;
|
|
91
52
|
/** Stack of destructure-param binding maps (binding name → Go accessor on the
|
|
92
|
-
* range var, e.g. `id` → `$__bf_item0.Id`, `rest` → `$__bf_item0`). Innermost
|
|
93
|
-
* Lets `.map(({ id, ...rest }) => …)` resolve
|
|
94
|
-
* refusing with BF104. (#1310) */
|
|
53
|
+
* range var, e.g. `id` → `$__bf_item0.Id`, `rest` → `$__bf_item0`). Innermost
|
|
54
|
+
* last. Lets `.map(({ id, ...rest }) => …)` resolve instead of BF104. */
|
|
95
55
|
private loopBindingStack;
|
|
96
|
-
private errors;
|
|
97
|
-
/** The current IR's memos, stashed like `localConstants` so nested memo
|
|
98
|
-
* resolution (a ternary memo whose condition is another memo, #1896)
|
|
99
|
-
* can recurse without threading the list through every signature. */
|
|
100
|
-
private currentMemos;
|
|
101
|
-
private propsObjectName;
|
|
102
|
-
/**
|
|
103
|
-
* Component-scoped rest binding identifier (`function({ a, ...rest }: P)`
|
|
104
|
-
* → `'rest'`). Stashed at `generate()` entry so per-attribute
|
|
105
|
-
* emitter callbacks can classify a spread expression against it
|
|
106
|
-
* without threading the IR through each recursion (#1407
|
|
107
|
-
* follow-up).
|
|
108
|
-
*/
|
|
109
|
-
private restPropsName;
|
|
110
|
-
private templateVarCounter;
|
|
111
|
-
/** Local type names resolved from typeDefinitions (populated during generateTypes) */
|
|
112
|
-
private localTypeNames;
|
|
113
|
-
/** Local type aliases mapping type name to base type (e.g., Filter → 'string') */
|
|
114
|
-
private localTypeAliases;
|
|
115
56
|
/**
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
* Synthesised array types for untyped object-array signals (signal getter →
|
|
123
|
-
* `[]SynthStruct` TypeInfo), populated during generateTypes (#1680). An
|
|
124
|
-
* untyped `createSignal([{ id: "a" }])` has no element type to bake against;
|
|
125
|
-
* we infer a struct from the literal's shape so the field can be typed and
|
|
126
|
-
* the items baked. Consulted by both the signal field-type emitter and the
|
|
127
|
-
* initial-value baker.
|
|
128
|
-
*/
|
|
129
|
-
private synthStructTypes;
|
|
130
|
-
/** Full type definitions from the current IR, stashed for loop-datum field resolution (#1897). */
|
|
131
|
-
private currentTypeDefinitions;
|
|
132
|
-
/** Set during type generation when any emit references
|
|
133
|
-
* `template.HTML(...)`; toggles the `"html/template"` import. */
|
|
134
|
-
private usesHtmlTemplate;
|
|
135
|
-
/** Component root scope element(s) — each carries `data-key` for a keyed loop
|
|
136
|
-
* item. A plain element root is one node; an `if-statement` (early-return)
|
|
137
|
-
* root contributes the top element of every branch. (#1297) */
|
|
138
|
-
private rootScopeNodes;
|
|
139
|
-
/** Set during type generation when any emit references
|
|
140
|
-
* `fmt.Sprint(...)` — e.g. a `Record<staticKeys, scalar>[propKey]`
|
|
141
|
-
* indexed-map spread value (#checkbox); toggles the `"fmt"` import. */
|
|
142
|
-
private usesFmt;
|
|
143
|
-
/**
|
|
144
|
-
* Cross-component child shapes (#checkbox), keyed by child component name.
|
|
145
|
-
* Populated out-of-band via `registerChildComponentShape` before the parent
|
|
146
|
-
* component's `generateTypes` runs, so the static-child-init codegen can
|
|
147
|
-
* route an attribute that is NOT a declared param of the child
|
|
148
|
-
* (`<CheckIcon data-slot=.../>`) into the child's rest bag
|
|
149
|
-
* (`Capitalize(restPropsName)` map field) instead of emitting an invalid
|
|
150
|
-
* hyphenated top-level field (`Data-slot:`). A child with no rest bag and
|
|
151
|
-
* an unknown attr is left as-is so the existing field path / Go compile
|
|
152
|
-
* error still surfaces.
|
|
57
|
+
* Cross-component child shapes, keyed by child component name. Populated via
|
|
58
|
+
* `registerChildComponentShape` before the parent's `generateTypes`, so the
|
|
59
|
+
* static-child-init codegen can route an attribute that is NOT a declared
|
|
60
|
+
* child param (`<CheckIcon data-slot=.../>`) into the child's rest bag instead
|
|
61
|
+
* of an invalid hyphenated field (`Data-slot:`). An unknown attr on a child
|
|
62
|
+
* with no rest bag is left as-is (existing field path / Go error surfaces).
|
|
153
63
|
*/
|
|
154
64
|
private childComponentShapes;
|
|
155
|
-
/**
|
|
156
|
-
* Module-scope pure string-literal constants (`const X = 'literal'` at
|
|
157
|
-
* file top-level), keyed by name → resolved literal value. Populated at
|
|
158
|
-
* `generate()` entry from `ir.metadata.localConstants`. When an identifier
|
|
159
|
-
* in an expression resolves to one of these, the adapter inlines the
|
|
160
|
-
* literal value instead of emitting a struct-field reference
|
|
161
|
-
* (`{{.X}}`) — the field never exists on the Props struct, so without
|
|
162
|
-
* inlining Go's template engine fails with `can't evaluate field X`.
|
|
163
|
-
* Hono inlines it for free (it evaluates real JS); this restores parity.
|
|
164
|
-
* Only module-scope, pure string literals qualify — function-scope
|
|
165
|
-
* locals legitimately become template vars/props, and `Record<T,string>`
|
|
166
|
-
* indexed lookups / memos / signals are deliberately excluded.
|
|
167
|
-
*/
|
|
168
|
-
private moduleStringConsts;
|
|
169
|
-
/**
|
|
170
|
-
* All local constants (module + function-scope) from the IR, retained for
|
|
171
|
-
* the lifetime of `generate()` so the memo-computation path can resolve
|
|
172
|
-
* `Record`-index lookups (`variantClasses[variant]`) without re-threading the
|
|
173
|
-
* full `ir` through every helper. Reset at `generate()` entry.
|
|
174
|
-
*/
|
|
175
|
-
private localConstants;
|
|
176
|
-
/**
|
|
177
|
-
* `useContext(...)` consumers in the component being generated. Each becomes
|
|
178
|
-
* a struct field defaulted to the `createContext` default, which an enclosing
|
|
179
|
-
* `<Ctx.Provider value>` overwrites for descendant child slots. Reset at
|
|
180
|
-
* `generate()` / `generateTypes()` entry. (#1297)
|
|
181
|
-
*/
|
|
182
|
-
private contextConsumers;
|
|
183
|
-
/**
|
|
184
|
-
* (#1922) Local binding names the request-scoped `searchParams()` env signal
|
|
185
|
-
* is imported under (handles `import { searchParams as sp }`). A zero-arg call
|
|
186
|
-
* on one of these names lowers to the canonical `.SearchParams` field
|
|
187
|
-
* regardless of the JS alias. Set at `generate()` / `generateTypes()` entry.
|
|
188
|
-
*/
|
|
189
|
-
private searchParamsLocals;
|
|
190
|
-
/**
|
|
191
|
-
* Names of component-scope arrow-const helpers (`const sortClass = …`),
|
|
192
|
-
* eligible for call-site inlining (#1897). Precomputed per component so the
|
|
193
|
-
* inliner can skip the AST parse for the common non-helper expression.
|
|
194
|
-
*/
|
|
195
|
-
private localHelperNames;
|
|
196
|
-
/** Set when a constructor-context lowering emits a `strings.` call (#1897), so
|
|
197
|
-
* `strings` is added to the generated types file's import block. */
|
|
198
|
-
private needsStringsImport;
|
|
199
|
-
/** Component-scope derived consts referenced by the template during rendering
|
|
200
|
-
* (e.g. `root` → `.Root`). `generateTypes` emits a computed field for each
|
|
201
|
-
* that's resolvable and non-colliding (#1897). */
|
|
202
|
-
private referencedDerivedConsts;
|
|
203
|
-
/** Array-memo name → the handler-filled loop slice field its `.map()` feeds
|
|
204
|
-
* (e.g. `visible` → `PostListItems`). Lets `<memo>().length` lower to
|
|
205
|
-
* `len .<Slice>` instead of `len .<Memo>` (a nil/unset memo field) — the
|
|
206
|
-
* slice IS the rendered (filtered) items, so its length is the count (#1897). */
|
|
207
|
-
private memoBackedLoopSlice;
|
|
208
65
|
/** Child component name → the contexts it consumes (cross-component, for provider wiring). */
|
|
209
66
|
private childContextConsumers;
|
|
210
|
-
/**
|
|
211
|
-
* Set of prop NAMES whose resolved Go struct-field type is exactly
|
|
212
|
-
* `interface{}` — i.e. nillable. Populated at `generate()` entry from
|
|
213
|
-
* the SAME per-prop Go-type computation `generatePropsStruct` /
|
|
214
|
-
* `generateInputStruct` use (`propTypeOverrides` + `typeInfoToGo`), so
|
|
215
|
-
* it can't drift from the actual field types. Used by
|
|
216
|
-
* `elementAttrEmitter.emitExpression` to omit a dynamic attribute whose
|
|
217
|
-
* value is a bare reference to a nillable prop when that prop is nil
|
|
218
|
-
* (Hono-style nullish-attribute omission: an `undefined`-valued
|
|
219
|
-
* attribute is dropped rather than rendered as `attr=""`). Concrete
|
|
220
|
-
* (`string`/`int`/`bool`) fields are never in this set and always emit
|
|
221
|
-
* unconditionally, matching Hono's `value=""` / `data-count="0"`.
|
|
222
|
-
*/
|
|
223
|
-
private nillablePropNames;
|
|
224
67
|
constructor(options?: GoTemplateAdapterOptions);
|
|
225
68
|
/**
|
|
226
|
-
*
|
|
227
|
-
*
|
|
228
|
-
*
|
|
69
|
+
* Prime the per-compile state both `generate()` and `generateTypes()` derive
|
|
70
|
+
* from the IR. Both must prime identically or the emitted Input/Props structs
|
|
71
|
+
* drift (`generateTypes` runs on a separately round-tripped IR).
|
|
72
|
+
* `propsObjectName` is set first because the inherited-attr scan keys off it.
|
|
229
73
|
*/
|
|
74
|
+
private primeCompileState;
|
|
75
|
+
/** Generate template output for a component. */
|
|
230
76
|
generate(ir: ComponentIR, options?: AdapterGenerateOptions): AdapterOutput;
|
|
231
77
|
/**
|
|
232
|
-
*
|
|
233
|
-
*
|
|
234
|
-
*
|
|
235
|
-
*
|
|
236
|
-
* -
|
|
237
|
-
|
|
238
|
-
private hasClientInteractivity;
|
|
239
|
-
/**
|
|
240
|
-
* Recursively check if any element in the tree has events.
|
|
241
|
-
*/
|
|
242
|
-
private hasEventsInTree;
|
|
243
|
-
/**
|
|
244
|
-
* Find all child component names used in the IR tree.
|
|
245
|
-
*/
|
|
246
|
-
private findChildComponentNames;
|
|
247
|
-
private collectChildComponentNames;
|
|
248
|
-
/**
|
|
249
|
-
* Push a `BF103` diagnostic for every component reference inside a
|
|
250
|
-
* loop body whose name is imported from a relative-path module
|
|
251
|
-
* (i.e. a sibling .tsx file). The Go adapter renders these as
|
|
252
|
-
* `{{template "X" .}}` calls, which Go's template engine resolves
|
|
253
|
-
* only against templates registered on the same `*template.Template`
|
|
254
|
-
* — so a user who factored a list item into `./list-item.tsx` and
|
|
255
|
-
* mapped over it gets a working build and a `template: "X" is
|
|
256
|
-
* undefined` at request time. Surfacing this at build time matches
|
|
257
|
-
* the louder-over-silent contract (#1266).
|
|
258
|
-
*
|
|
259
|
-
* Scoped to loop bodies because that's the natural Hono-style
|
|
260
|
-
* pattern the issue calls out; static (non-loop) usage of imported
|
|
261
|
-
* components is left alone so existing static-layout patterns
|
|
262
|
-
* keep working without noise.
|
|
78
|
+
* Push BF103 for every loop-body component reference whose name is imported
|
|
79
|
+
* from a relative-path (sibling) module. The Go adapter renders these as
|
|
80
|
+
* `{{template "X" .}}`, which resolves only against templates registered on
|
|
81
|
+
* the same `*template.Template` — otherwise a clean build fails at request
|
|
82
|
+
* time with `template: "X" is undefined`. Static (non-loop) usage is left
|
|
83
|
+
* alone so existing layouts keep working.
|
|
263
84
|
*/
|
|
264
85
|
private checkImportedLoopChildComponents;
|
|
265
86
|
/**
|
|
266
|
-
*
|
|
267
|
-
*
|
|
268
|
-
*
|
|
269
|
-
* The same ScriptCollector should be shared across parent and child props.
|
|
270
|
-
* Wrapped in {{if .Scripts}} to safely handle nil Scripts.
|
|
87
|
+
* Script registration code for the template start. Reads `.Scripts` (on every
|
|
88
|
+
* Props struct) and guards the registrations with `{{if .Scripts}}` for a nil
|
|
89
|
+
* collector.
|
|
271
90
|
*/
|
|
272
91
|
private generateScriptRegistrations;
|
|
273
92
|
/**
|
|
274
|
-
* Register a child component's shape (
|
|
275
|
-
*
|
|
276
|
-
* rest bag rather than emitting an invalid hyphenated top-level field. Call
|
|
277
|
-
* once per known child IR (siblings in the same source, auto-inferred
|
|
278
|
-
* `../<name>` imports) before generating the parent's types. Idempotent.
|
|
93
|
+
* Register a child component's shape (see `childComponentShapes`). Call once
|
|
94
|
+
* per known child IR before the parent's `generateTypes`. Idempotent.
|
|
279
95
|
*/
|
|
280
96
|
registerChildComponentShape(ir: ComponentIR): void;
|
|
281
97
|
/** Go field name for a `useContext` consumer (the capitalized local binding). */
|
|
@@ -284,119 +100,55 @@ export declare class GoTemplateAdapter extends BaseAdapter implements ParsedExpr
|
|
|
284
100
|
private contextConsumerGoType;
|
|
285
101
|
/** Go literal for a context-consumer's default value (the `createContext` arg). */
|
|
286
102
|
private contextConsumerGoDefault;
|
|
287
|
-
/**
|
|
288
|
-
* Context-consumer fields that don't collide with an already-emitted prop /
|
|
289
|
-
* signal / memo field. The template reads them as `{{.Field}}` (the local
|
|
290
|
-
* `useContext` binding lowered to a root field); the struct must carry them.
|
|
291
|
-
*/
|
|
103
|
+
/** Context-consumer fields not colliding with an already-emitted prop/signal/memo field (the struct must carry them; template reads `{{.Field}}`). */
|
|
292
104
|
private nonCollidingContextConsumers;
|
|
293
105
|
generateTypes(ir: ComponentIR): string | null;
|
|
294
|
-
/**
|
|
295
|
-
* Convert a TypeScript type definition to a Go type.
|
|
296
|
-
* Handles object types → Go structs, and union string literals → string alias.
|
|
297
|
-
*/
|
|
106
|
+
/** Convert a TS type definition to Go: object types → structs, string-literal unions → a `string` alias. */
|
|
298
107
|
private typeDefinitionToGo;
|
|
299
108
|
/**
|
|
300
|
-
*
|
|
301
|
-
* properties
|
|
302
|
-
*
|
|
303
|
-
* name
|
|
304
|
-
*
|
|
305
|
-
*
|
|
306
|
-
*
|
|
307
|
-
* A property whose source key isn't a valid Go identifier (`"data-id"`, a
|
|
308
|
-
* numeric key, …) can't become a struct field, so it's dropped here — and is
|
|
309
|
-
* therefore absent from the baker's field map too, which bails to nil for any
|
|
310
|
-
* literal that uses such a key.
|
|
109
|
+
* Single source of truth for a generated struct's Go fields, derived from the
|
|
110
|
+
* analyzer's structured properties (no definition-string parsing). Both the
|
|
111
|
+
* struct emitter and the object-literal baker consume it, so a baked literal
|
|
112
|
+
* can't name a field the struct lacks. A non-Go-identifier source key
|
|
113
|
+
* (`"data-id"`, a numeric key) is dropped here, so the baker bails to nil for
|
|
114
|
+
* any literal using such a key.
|
|
311
115
|
*/
|
|
312
116
|
private structFieldsFor;
|
|
313
117
|
/**
|
|
314
118
|
* Synthesise a Go struct from an untyped object-array signal's inline initial
|
|
315
|
-
* value
|
|
316
|
-
*
|
|
317
|
-
*
|
|
318
|
-
*
|
|
319
|
-
*
|
|
320
|
-
* - the initial value is a non-empty array literal of object literals,
|
|
321
|
-
* - every element shares the same set of Go-identifier keys, and
|
|
322
|
-
* - every value is a scalar literal whose Go type is consistent per key
|
|
323
|
-
* (numeric keys widen int→float64 when mixed).
|
|
324
|
-
*
|
|
325
|
-
* Any deviation (heterogeneous shape, a nested object/array value, a
|
|
326
|
-
* non-literal value, a non-identifier key, or a name collision with an
|
|
327
|
-
* existing type) returns `null`.
|
|
119
|
+
* value, or `null` (caller keeps `[]interface{}`/`nil`). Requires: untyped
|
|
120
|
+
* array type; a non-empty array literal of object literals; every element
|
|
121
|
+
* sharing the same Go-identifier key set; every value a scalar literal with a
|
|
122
|
+
* per-key-consistent Go type (mixed int/float64 widens to float64). Any
|
|
123
|
+
* deviation, or a name collision with an existing type, returns `null`.
|
|
328
124
|
*/
|
|
329
125
|
private synthesizeStructFromSignal;
|
|
330
126
|
/**
|
|
331
|
-
*
|
|
332
|
-
*
|
|
333
|
-
*
|
|
127
|
+
* Go type for a scalar-literal `ParsedExpr` field value, else `null` (caller
|
|
128
|
+
* bails out of synthesis). string/no-substitution template → `string`;
|
|
129
|
+
* numeric (optionally negated) → int/float64; boolean → `bool`.
|
|
334
130
|
*/
|
|
335
|
-
private
|
|
336
|
-
/** `
|
|
337
|
-
* or exponent. */
|
|
131
|
+
private scalarParsedGoType;
|
|
132
|
+
/** `float64` when the literal has a fraction or exponent, else `int`. */
|
|
338
133
|
private numericLiteralGoType;
|
|
339
|
-
/** Reconcile two
|
|
340
|
-
* types stay; mixed numeric (int/float64) widens to float64; otherwise null
|
|
341
|
-
* (incompatible → bail). */
|
|
134
|
+
/** Reconcile two per-key Go types: equal stays; mixed numeric widens to float64; else null. */
|
|
342
135
|
private mergeScalarGoType;
|
|
343
136
|
/**
|
|
344
|
-
*
|
|
345
|
-
*
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
*
|
|
350
|
-
* When a signal is initialized from a prop (e.g., createSignal(props.initial ?? 0)),
|
|
351
|
-
* the signal's type annotation may be more specific than the prop's TypeInfo.
|
|
352
|
-
*/
|
|
353
|
-
private buildPropTypeOverrides;
|
|
354
|
-
/**
|
|
355
|
-
* Resolve a prop param's Go struct-field type using the SAME logic
|
|
356
|
-
* `generatePropsStruct` / `generateInputStruct` use for the field
|
|
357
|
-
* declaration: a `propTypeOverrides` entry (signal-inferred override)
|
|
358
|
-
* wins, otherwise `typeInfoToGo(param.type, param.defaultValue)`.
|
|
359
|
-
* Factored out so the nillable-field set (`collectNillablePropNames`)
|
|
360
|
-
* can't drift from the actual emitted field types.
|
|
361
|
-
*/
|
|
362
|
-
private resolvePropGoType;
|
|
363
|
-
/**
|
|
364
|
-
* Build the set of prop NAMES whose resolved Go field type is exactly
|
|
365
|
-
* `interface{}` (nillable). Uses the same `propTypeOverrides` +
|
|
366
|
-
* `resolvePropGoType` pipeline as the struct generators, so a prop
|
|
367
|
-
* that ends up `interface{}` on the Props struct — and only such a
|
|
368
|
-
* prop — is treated as nillable for Hono-style attribute omission.
|
|
369
|
-
* Concrete (`string`/`int`/`bool`/`[]T`/struct) types are excluded.
|
|
370
|
-
*/
|
|
371
|
-
private collectNillablePropNames;
|
|
372
|
-
/**
|
|
373
|
-
* Whether the component reads the request-scoped `searchParams()`
|
|
374
|
-
* environment signal (router v0.5, #1922). Detected from `searchParamsLocals`
|
|
375
|
-
* — the binding names the shared `searchParamsLocalNames` helper found at
|
|
376
|
-
* `generate()` / `generateTypes()` entry, covering any local name (including
|
|
377
|
-
* an aliased `import { searchParams as sp }`). When non-empty the generated
|
|
378
|
-
* structs carry a `SearchParams bf.SearchParams` binding the route handler
|
|
379
|
-
* fills per request and the template reads via `.SearchParams.Get "key"`.
|
|
380
|
-
*
|
|
381
|
-
* Guarded against a name collision with a user prop / signal / memo also
|
|
382
|
-
* called `searchParams`: that author owns the `SearchParams` field, so the
|
|
383
|
-
* env-signal field is dropped (the reference would resolve to their value).
|
|
137
|
+
* Whether the component reads the request-scoped `searchParams()` env signal
|
|
138
|
+
* (from `searchParamsLocals`, covering any local incl. aliased imports). When
|
|
139
|
+
* true the structs carry a `SearchParams bf.SearchParams` binding the handler
|
|
140
|
+
* fills per request, read as `.SearchParams.Get "key"`. Returns false when a
|
|
141
|
+
* user prop/signal/memo named `searchParams` already owns the field (the
|
|
142
|
+
* binding would resolve to their value).
|
|
384
143
|
*/
|
|
385
144
|
private usesSearchParams;
|
|
386
|
-
/**
|
|
387
|
-
* Generate Input struct for a component
|
|
388
|
-
*/
|
|
145
|
+
/** Generate the Input struct for a component. */
|
|
389
146
|
private generateInputStruct;
|
|
390
|
-
/**
|
|
391
|
-
* Generate Props struct for a component
|
|
392
|
-
*/
|
|
393
147
|
private generatePropsStruct;
|
|
394
148
|
/**
|
|
395
|
-
*
|
|
396
|
-
*
|
|
397
|
-
*
|
|
398
|
-
* within the loop body children (e.g. the `TableCell` instances inside
|
|
399
|
-
* `<TableRow>…</TableRow>`).
|
|
149
|
+
* Wrapper struct for a loop-body component with JSX children: embeds the
|
|
150
|
+
* child's Props, datum fields from the loop's item type, and slot fields for
|
|
151
|
+
* sub-components in the body (`TableCell` inside `<TableRow>…</TableRow>`).
|
|
400
152
|
*/
|
|
401
153
|
private generateLoopBodyWrapperStruct;
|
|
402
154
|
/** Extract a memo name from a loop array expression like `sortedData()` → `sortedData`. */
|
|
@@ -405,31 +157,37 @@ export declare class GoTemplateAdapter extends BaseAdapter implements ParsedExpr
|
|
|
405
157
|
private loopBodyWrapperName;
|
|
406
158
|
/** Resolve a loop item's TypeInfo to Go struct fields for the wrapper. */
|
|
407
159
|
private resolveLoopDatumFields;
|
|
408
|
-
/** Collect static child instances from loop body children for the wrapper struct. */
|
|
409
|
-
private collectBodyChildInstances;
|
|
410
160
|
/**
|
|
411
|
-
*
|
|
161
|
+
* `'interface{}'` for a loop over an inline primitive-literal array whose body
|
|
162
|
+
* renders the bare item (`[1,2,3,4,5].map(n => …{n}…)`), else null. Such
|
|
163
|
+
* scalar-item loops have no datum fields, so the value is carried on the
|
|
164
|
+
* wrapper's synthetic `BfLoopItem`; object/field loops and non-literal sources
|
|
165
|
+
* keep the datum-field path.
|
|
412
166
|
*/
|
|
167
|
+
private scalarLiteralLoopGoType;
|
|
168
|
+
/** Collect static child instances from loop body children for the wrapper struct. */
|
|
169
|
+
private collectBodyChildInstances;
|
|
170
|
+
/** Generate the NewXxxProps function. */
|
|
413
171
|
private generateNewPropsFunction;
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
172
|
+
private emitStaticChildInstances;
|
|
173
|
+
private emitNewPropsDocComment;
|
|
174
|
+
private emitSpreadBagInits;
|
|
175
|
+
private emitStaticBodyWrappers;
|
|
176
|
+
private emitDynamicBodyWrappers;
|
|
177
|
+
private buildLocalTypeTables;
|
|
178
|
+
private emitLocalTypeStructs;
|
|
179
|
+
private emitSynthStructs;
|
|
180
|
+
private resolveNestedLoopItemTypes;
|
|
181
|
+
private composeFileHeader;
|
|
182
|
+
private emitPropsStructHeader;
|
|
183
|
+
private emitPropsDataFields;
|
|
184
|
+
private emitPropsAuxFields;
|
|
185
|
+
/** Convert a field name to its JSON tag (camelCase). */
|
|
417
186
|
private toJsonTag;
|
|
418
187
|
/**
|
|
419
|
-
*
|
|
420
|
-
*
|
|
421
|
-
|
|
422
|
-
private findNestedComponents;
|
|
423
|
-
private collectNestedComponents;
|
|
424
|
-
/**
|
|
425
|
-
* Collect all static child component instances from the IR tree.
|
|
426
|
-
* Excludes components inside loops (which are handled by nestedComponents).
|
|
427
|
-
*
|
|
428
|
-
* Each instance is identified by:
|
|
429
|
-
* - name: Component name (e.g., "ReactiveChild")
|
|
430
|
-
* - slotId: Unique slot ID (e.g., "slot_6")
|
|
431
|
-
* - props: Component props
|
|
432
|
-
* - fieldName: Go field name (e.g., "ReactiveChildSlot6")
|
|
188
|
+
* Collect all static child component instances from the IR tree. Excludes
|
|
189
|
+
* components inside loops (handled by nestedComponents). Each instance carries
|
|
190
|
+
* its component `name`, `slotId`, `props`, and Go `fieldName`.
|
|
433
191
|
*/
|
|
434
192
|
private collectStaticChildInstances;
|
|
435
193
|
/**
|
|
@@ -437,33 +195,20 @@ export declare class GoTemplateAdapter extends BaseAdapter implements ParsedExpr
|
|
|
437
195
|
* every node is plain text; otherwise null.
|
|
438
196
|
*/
|
|
439
197
|
private extractTextChildren;
|
|
440
|
-
/**
|
|
441
|
-
* Render JSX children to a Go-template-ready HTML fragment when
|
|
442
|
-
* children are non-text but produce purely-static HTML (no Go
|
|
443
|
-
* template actions). Returns null when:
|
|
444
|
-
* - children are absent or text-only (handled by extractTextChildren), or
|
|
445
|
-
* - the rendered fragment contains any `{{...}}` action — passing
|
|
446
|
-
* such a fragment through `template.HTML` and the parent's
|
|
447
|
-
* `{{.Children}}` would output the actions verbatim instead of
|
|
448
|
-
* evaluating them, which is worse than the existing
|
|
449
|
-
* "drop children" fallback. Dynamic / component-bearing children
|
|
450
|
-
* stay on the drop path until a re-evaluation hook lands.
|
|
451
|
-
*/
|
|
452
198
|
/**
|
|
453
199
|
* Pull the IR nodes out of a `children={<…/>}` attribute (a `jsx-children`
|
|
454
|
-
* prop value). Empty when the component takes no such prop.
|
|
200
|
+
* prop value). Empty when the component takes no such prop.
|
|
455
201
|
*/
|
|
456
202
|
private jsxChildrenPropNodes;
|
|
457
203
|
private extractHtmlChildren;
|
|
458
204
|
/**
|
|
459
205
|
* Build a Go string-concat expression for hoisted-JSX children whose root
|
|
460
|
-
* carries `needsScope` (`children={<span/>}`
|
|
461
|
-
*
|
|
462
|
-
*
|
|
463
|
-
*
|
|
464
|
-
*
|
|
465
|
-
*
|
|
466
|
-
* those stay on the drop path).
|
|
206
|
+
* carries `needsScope` (`children={<span/>}`). Such roots render in the
|
|
207
|
+
* PARENT's scope, so their `bf-s` is the runtime parent `scopeID`, not a
|
|
208
|
+
* bake-time constant. Render the fragment, swap the parent-scope hydration
|
|
209
|
+
* marker for a sentinel, and splice `scopeID` back in. Returns null when the
|
|
210
|
+
* plain static `childrenHtml` path already applies, or when any other template
|
|
211
|
+
* action survives (genuinely dynamic — those stay on the drop path).
|
|
467
212
|
*/
|
|
468
213
|
private extractScopedHtmlChildren;
|
|
469
214
|
private collectStaticChildInstancesRecursive;
|
|
@@ -474,420 +219,42 @@ export declare class GoTemplateAdapter extends BaseAdapter implements ParsedExpr
|
|
|
474
219
|
*/
|
|
475
220
|
private extendProviderContext;
|
|
476
221
|
/**
|
|
477
|
-
*
|
|
478
|
-
*
|
|
479
|
-
*
|
|
480
|
-
*
|
|
481
|
-
*
|
|
482
|
-
*
|
|
483
|
-
* Walks the IR tree, descending into elements, fragments,
|
|
484
|
-
* conditionals, providers, async, and components, but stopping at
|
|
485
|
-
* loop bodies. Each `IRElement.attrs[i].value` of kind `'spread'`
|
|
486
|
-
* that has a `slotId` becomes one `SpreadSlotInfo` entry.
|
|
487
|
-
*/
|
|
488
|
-
private collectSpreadSlots;
|
|
489
|
-
/**
|
|
490
|
-
* Decide how a spread bag should be plumbed onto the Input/Props
|
|
491
|
-
* structs (#1407 follow-up). A bare-identifier spread that
|
|
492
|
-
* matches the component's `restPropsName` is open-ended (Go's
|
|
493
|
-
* static typing can't enumerate the keys), so the caller must
|
|
494
|
-
* supply the bag via an Input-side `map[string]any` field. Every
|
|
495
|
-
* other shape — signal getter, `propsObjectName`, plain
|
|
496
|
-
* propsParam, object literal — can be constructed inline in
|
|
497
|
-
* `NewXxxProps` from compile-time-known data.
|
|
498
|
-
*
|
|
499
|
-
* Reads `this.restPropsName` (stashed at `generate()` entry)
|
|
500
|
-
* rather than receiving the IR per-call — matches the existing
|
|
501
|
-
* `this.propsObjectName` / `this.componentName` storage pattern.
|
|
502
|
-
*/
|
|
503
|
-
private classifySpreadBagSource;
|
|
504
|
-
private collectSpreadSlotsRecursive;
|
|
505
|
-
/**
|
|
506
|
-
* Parse a JS object-literal source text (the raw string captured
|
|
507
|
-
* for a signal's `initialValue` or a spread expression's argument)
|
|
508
|
-
* into a Go `map[string]any{...}` literal source (#1407).
|
|
509
|
-
*
|
|
510
|
-
* Supports a deliberately conservative subset so the Go output is
|
|
511
|
-
* a 1:1 translation of the JS source: string/number/boolean/null
|
|
512
|
-
* values keyed by identifier or string-literal keys. Returns null
|
|
513
|
-
* for unsupported shapes (nested objects, computed values,
|
|
514
|
-
* function calls, spread elements) — callers fall back to BF101.
|
|
515
|
-
*/
|
|
516
|
-
private parseJsObjectLiteralToGoMap;
|
|
517
|
-
/**
|
|
518
|
-
* Build a Go expression for a JSX spread bag's initial value, to
|
|
519
|
-
* be placed inside `NewXxxProps`'s return literal (#1407).
|
|
520
|
-
*
|
|
521
|
-
* Supported shapes:
|
|
522
|
-
* - Signal-getter call (e.g. `attrs()`): look up the signal,
|
|
523
|
-
* parse its `initialValue` as a JS object literal, and emit a
|
|
524
|
-
* Go `map[string]any{...}` literal.
|
|
525
|
-
* - Bare identifier matching a destructured `propsParam` (e.g.
|
|
526
|
-
* `function({ extras }: P) { <el {...extras}/> }`): emit
|
|
527
|
-
* `in.<FieldName>` — works when the prop's Go type is a map
|
|
528
|
-
* type the bag is assignable to.
|
|
529
|
-
* - Bare identifier matching `propsObjectName` (SolidJS-style
|
|
530
|
-
* `function(props: P) { <el {...props}/> }`): enumerate the
|
|
531
|
-
* analyzer-extracted `propsParams` into an inline
|
|
532
|
-
* `map[string]any{...}` literal so each typed Input field
|
|
533
|
-
* surfaces as a bag key (#1407 follow-up).
|
|
534
|
-
* - Bare identifier matching `restPropsName` (the destructured-
|
|
535
|
-
* rest pattern `function({a, ...rest}: P) { <el {...rest}/> }`):
|
|
536
|
-
* emit `in.<slotId>` against the `map[string]any` Input field
|
|
537
|
-
* that `generateInputStruct` adds for `input-bag` slots. The
|
|
538
|
-
* caller (parent component or test harness) populates the
|
|
539
|
-
* bag with the open-ended rest values (#1407 follow-up).
|
|
540
|
-
*
|
|
541
|
-
* Returns null for unsupported shapes so the caller can raise a
|
|
542
|
-
* narrowed BF101 with the offending expression.
|
|
543
|
-
*/
|
|
544
|
-
private buildSpreadInitializer;
|
|
545
|
-
/**
|
|
546
|
-
* Lower a conditional inline-object spread bag value:
|
|
547
|
-
* `(COND ? { 'aria-describedby': describedBy } : {})`
|
|
548
|
-
* into an immediately-invoked Go func literal that conditionally
|
|
549
|
-
* builds the map (so the falsy branch OMITS the key rather than
|
|
550
|
-
* rendering it as an empty string, which `SpreadAttrs` does not
|
|
551
|
-
* filter):
|
|
552
|
-
*
|
|
553
|
-
* func() map[string]any {
|
|
554
|
-
* if in.DescribedBy != nil && in.DescribedBy != "" {
|
|
555
|
-
* return map[string]any{"aria-describedby": in.DescribedBy}
|
|
556
|
-
* }
|
|
557
|
-
* return map[string]any{}
|
|
558
|
-
* }()
|
|
559
|
-
*
|
|
560
|
-
* Returns:
|
|
561
|
-
* - `undefined` when the expression is NOT a parenthesized ternary
|
|
562
|
-
* of object literals — the caller falls through to other shapes.
|
|
563
|
-
* - `null` when it IS that shape but a part can't be faithfully
|
|
564
|
-
* converted (non-static key, unsupported condition, …) — the
|
|
565
|
-
* caller raises BF101.
|
|
566
|
-
* - the Go IIFE string when fully convertible.
|
|
567
|
-
*/
|
|
568
|
-
private buildConditionalSpreadInitializer;
|
|
569
|
-
/** Strip redundant parenthesised wrappers off a TS expression. */
|
|
570
|
-
private unwrapParens;
|
|
571
|
-
/**
|
|
572
|
-
* Convert a conditional-spread condition expression to a Go bool in
|
|
573
|
-
* the `in.` context. Supports a bare prop identifier (`describedBy`)
|
|
574
|
-
* and its negation (`!describedBy`), type-aware on the prop:
|
|
575
|
-
* string → `in.X != ""`
|
|
576
|
-
* boolean → `in.X`
|
|
577
|
-
* number → `in.X != 0`
|
|
578
|
-
* unknown / interface{} → `in.X != nil && in.X != ""`
|
|
579
|
-
* (faithful JS string-truthiness for an interface holding a
|
|
580
|
-
* string — textarea's `describedBy` resolves to interface{}).
|
|
581
|
-
* Returns null for any other shape (caller → BF101).
|
|
582
|
-
*/
|
|
583
|
-
private conditionToGoBool;
|
|
584
|
-
/**
|
|
585
|
-
* Convert a static object literal (`{ 'aria-describedby': describedBy }`)
|
|
586
|
-
* into a Go `map[string]any{...}` literal for a conditional spread.
|
|
587
|
-
* Only static string/identifier keys are allowed; values resolve
|
|
588
|
-
* prop-identifier references to `in.FieldName` and string literals to
|
|
589
|
-
* Go string literals. Returns null for any computed/spread/dynamic
|
|
590
|
-
* key or unsupported value (caller → BF101). Empty object → `map[string]any{}`.
|
|
591
|
-
*/
|
|
592
|
-
private objectLiteralToGoSpreadMap;
|
|
593
|
-
/**
|
|
594
|
-
* Lower a spread-object VALUE of the form `IDENT[KEY]` where:
|
|
595
|
-
* - `IDENT` resolves via `localConstants` to a MODULE-scope object
|
|
596
|
-
* literal whose property values are all scalar (number/string)
|
|
597
|
-
* literals under static (string-literal or identifier) keys
|
|
598
|
-
* (a `Record<staticKeys, scalar>` map like `sizeMap`), AND
|
|
599
|
-
* - `KEY` is a bare identifier that is a prop.
|
|
600
|
-
* Emits an inline indexed Go map:
|
|
601
|
-
* `map[string]any{"sm": 16, ...}[fmt.Sprint(in.Size)]`
|
|
602
|
-
* (`fmt.Sprint` coerces the `interface{}`/typed prop to the map's
|
|
603
|
-
* string key space — sets `usesFmt` so the `"fmt"` import is added).
|
|
604
|
-
*
|
|
605
|
-
* Returns the Go string when convertible, else `null` (caller → BF101)
|
|
606
|
-
* for any non-scalar value, non-static key, or non-prop index so
|
|
607
|
-
* unrelated shapes don't regress. (#checkbox / icon `sizeMap[size]`.)
|
|
608
|
-
*/
|
|
609
|
-
private recordIndexAccessToGoMap;
|
|
610
|
-
/**
|
|
611
|
-
* Convert JavaScript initial value to Go value for NewXxxProps function.
|
|
612
|
-
* References to props params are converted to in.FieldName format.
|
|
613
|
-
*/
|
|
614
|
-
private convertInitialValue;
|
|
615
|
-
/**
|
|
616
|
-
* Convert a fully-literal JS expression string into an equivalent Go literal
|
|
617
|
-
* whose Go type matches `typeInfo` (#1672), used to bake a signal's inline
|
|
618
|
-
* initial value into the SSR data context:
|
|
619
|
-
*
|
|
620
|
-
* `["x", "y"]` (string[]) → `[]string{"x", "y"}`
|
|
621
|
-
* `["x", "y"]` (unknown[]) → `[]interface{}{"x", "y"}`
|
|
622
|
-
* `[{ id: "a" }]` (Item[]) → `[]Item{Item{ID: "a"}}`
|
|
623
|
-
*
|
|
624
|
-
* Returns `null` — so the caller keeps `nil` — when the expression (or any
|
|
625
|
-
* nested element) is not a pure literal (a call, identifier, template with
|
|
626
|
-
* interpolation, …) or cannot be expressed in the target Go type without a
|
|
627
|
-
* render/compile mismatch (e.g. an object element in a `[]interface{}` field,
|
|
628
|
-
* which the SSR template reaches via struct field access the map lacks).
|
|
629
|
-
*/
|
|
630
|
-
private jsLiteralToGo;
|
|
631
|
-
/**
|
|
632
|
-
* Parse a JS expression string into its TS AST node (parentheses unwrapped),
|
|
633
|
-
* or `null` when it isn't a single expression. Shared by the literal baker
|
|
634
|
-
* and the struct-shape synthesiser.
|
|
635
|
-
*/
|
|
636
|
-
private parseLiteralExpression;
|
|
637
|
-
/**
|
|
638
|
-
* Recursively convert a TS literal AST node to a Go literal typed as
|
|
639
|
-
* `typeInfo`, or null when the node is not a pure literal / cannot be
|
|
640
|
-
* represented in that Go type.
|
|
641
|
-
*/
|
|
642
|
-
private tsLiteralToGo;
|
|
643
|
-
/**
|
|
644
|
-
* Convert TypeInfo to Go type string.
|
|
645
|
-
* If type is unknown, tries to infer from defaultValue.
|
|
646
|
-
*/
|
|
647
|
-
private typeInfoToGo;
|
|
648
|
-
/**
|
|
649
|
-
* Get signal's initial value as Go code.
|
|
650
|
-
* Handles both literal values (0, true, "str") and props references (initial).
|
|
651
|
-
*
|
|
652
|
-
* (#1423) When the signal references a prop via `props.X ?? N` and
|
|
653
|
-
* the caller hoisted a fallback variable for `X`, return the hoisted
|
|
654
|
-
* variable's name so the memo inherits the signal-time fallback.
|
|
655
|
-
*/
|
|
656
|
-
private getSignalInitialValueAsGo;
|
|
657
|
-
/**
|
|
658
|
-
* Resolve dynamic prop value (e.g., signal/memo getter calls) to Go initial value.
|
|
659
|
-
* Handles expressions like `count()` → signal's initial value
|
|
660
|
-
*/
|
|
661
|
-
/**
|
|
662
|
-
* Convert a template literal's parsed parts into a Go expression of
|
|
663
|
-
* type `string`, evaluated in `NewXxxProps` scope (where destructured
|
|
664
|
-
* prop refs resolve via `in.FieldName`). Returns null when any part
|
|
665
|
-
* is not representable in static Go code so the caller can fall back
|
|
666
|
-
* to `resolveDynamicPropValue` (which handles the simpler shapes).
|
|
667
|
-
*
|
|
668
|
-
* Supported parts:
|
|
669
|
-
* - `string`: emit as a Go string literal.
|
|
670
|
-
* - `lookup`: `${MAP[KEY]}` against a `Record<T, string>` literal —
|
|
671
|
-
* emit an IIFE that switches on the key prop and returns the
|
|
672
|
-
* matching case (empty when no case matches). The key must be a
|
|
673
|
-
* bare prop identifier today; other key shapes opt out.
|
|
674
|
-
*
|
|
675
|
-
* `ternary` is intentionally left unsupported — the existing
|
|
676
|
-
* element-attribute path handles it via Go template `{{if}}` syntax,
|
|
677
|
-
* and component-prop-via-ternary cases are rarer and can be added
|
|
678
|
-
* incrementally.
|
|
222
|
+
* Convert a template literal's parsed parts into a `string`-typed Go
|
|
223
|
+
* expression in `NewXxxProps` scope (destructured prop refs → `in.FieldName`),
|
|
224
|
+
* or null so the caller falls back to `resolveDynamicPropValue`. A `string`
|
|
225
|
+
* part emits a Go literal; a `lookup` (`${MAP[KEY]}` over a `Record<T,string>`,
|
|
226
|
+
* key must be a bare prop ident) emits a switch-on-key IIFE. `ternary` opts out
|
|
227
|
+
* — the element-attribute path handles it via `{{if}}`.
|
|
679
228
|
*/
|
|
680
229
|
private templatePartsToGoCode;
|
|
681
230
|
private resolveDynamicPropValue;
|
|
682
|
-
/**
|
|
683
|
-
* Compute the initial value for a memo based on its computation and signal initial values.
|
|
684
|
-
* Handles simple cases like `() => count() * 2` → `in.Initial * 2`
|
|
685
|
-
* Also handles props.xxx patterns like `() => props.value * 10` → `in.Value * 10`
|
|
686
|
-
*
|
|
687
|
-
* (#1423) When `propFallbackVars` carries a hoisted variable for the
|
|
688
|
-
* referenced prop, substitute it for `in.FieldName` so the memo
|
|
689
|
-
* inherits the signal-time `??` fallback.
|
|
690
|
-
*/
|
|
691
|
-
/**
|
|
692
|
-
* (#checkbox) Compute the SSR initial value of a template-literal memo as a
|
|
693
|
-
* Go `string` expression. The memo computation looks like
|
|
694
|
-
* `() => `${a} ${b} ${props.className ?? ''} grid place-content-center``.
|
|
695
|
-
*
|
|
696
|
-
* Each quasi (literal text span) becomes a Go string literal; each
|
|
697
|
-
* interpolation is resolved:
|
|
698
|
-
* - an identifier naming a module string const → its inlined literal
|
|
699
|
-
* (covers both pure-string and `[...].join(' ')` consts);
|
|
700
|
-
* - `props.<name> ?? '<fallback>'` or bare `props.<name>` → `in.<Field>`
|
|
701
|
-
* when `<name>` is a known prop param (typed `string`); the `?? ''`
|
|
702
|
-
* fallback maps to Go's zero value for an unset string field, matching
|
|
703
|
-
* the Hono reference's empty-string result.
|
|
704
|
-
*
|
|
705
|
-
* Returns the `"a" + in.Field + " grid..."` concatenation, or null when the
|
|
706
|
-
* computation isn't a single template literal or any interpolation isn't
|
|
707
|
-
* representable (so the caller keeps its existing pattern matching).
|
|
708
|
-
*/
|
|
709
|
-
private computeTemplateLiteralMemoInitialValue;
|
|
710
|
-
/**
|
|
711
|
-
* (#checkbox) Resolve one `${expr}` interpolation of a template-literal memo
|
|
712
|
-
* to a Go string expression, or null when unsupported. See
|
|
713
|
-
* `computeTemplateLiteralMemoInitialValue` for the supported shapes.
|
|
714
|
-
*/
|
|
715
|
-
private resolveTemplateInterpolation;
|
|
716
|
-
/**
|
|
717
|
-
* Parse a memo-local `const X = …` initializer into a `Record`-index key
|
|
718
|
-
* binding: `props.Y ?? 'lit'` → `{ propName: 'Y', defaultLiteral: 'lit' }`,
|
|
719
|
-
* or bare `props.Y` → `{ propName: 'Y' }`. Returns null for any other shape
|
|
720
|
-
* (a literal const, a call, etc.) so it simply isn't registered as a key.
|
|
721
|
-
*/
|
|
722
|
-
private parseLocalKeyBinding;
|
|
723
|
-
/**
|
|
724
|
-
* Lower a `recordConst[key]` interpolation to an inline indexed Go map,
|
|
725
|
-
* emitting `map[string]string{…}[fmt.Sprint(in.Field)]` (or `map[string]any`
|
|
726
|
-
* for mixed values). `key` is a bare prop or a memo-local const bound to
|
|
727
|
-
* `props.X ?? 'default'` (resolved via `localKeyBindings`); a `'default'`
|
|
728
|
-
* fallback also maps `""` to that entry, so an unset prop (Go zero value `""`)
|
|
729
|
-
* renders the default — matching Hono's `props.X ?? 'default'`. Returns null
|
|
730
|
-
* for any non-record / non-resolvable key so the caller falls through.
|
|
731
|
-
*/
|
|
732
|
-
private recordIndexInterpolationToGo;
|
|
733
|
-
/**
|
|
734
|
-
* If `node` is a `<propsObjectName>.<name>` access, return `<name>`, else
|
|
735
|
-
* null. Used to recognize props-object reads inside memo interpolations.
|
|
736
|
-
*/
|
|
737
|
-
private propsAccessName;
|
|
738
|
-
private computeMemoInitialValue;
|
|
739
|
-
/**
|
|
740
|
-
* Pattern-matching core of `computeMemoInitialValue`: returns the
|
|
741
|
-
* memo's SSR initial value as a Go expression, or `null` when no
|
|
742
|
-
* pattern applies. Callers that have a typed field to fill use the
|
|
743
|
-
* zero-value-defaulting wrapper above; callers that can simply OMIT
|
|
744
|
-
* the field (a child-instance prop init — Go's zero values then apply
|
|
745
|
-
* with the right type for free) use this directly (#1896,
|
|
746
|
-
* data-table's `Checked: 0` into a bool field).
|
|
747
|
-
*/
|
|
748
|
-
private computeMemoInitialValueOrNull;
|
|
749
|
-
/**
|
|
750
|
-
* (#1897) Recognises a block-body memo whose SSR path returns a module-const
|
|
751
|
-
* array when the guard signal starts falsy:
|
|
752
|
-
* `() => { const k = getter(); if (!k) return MODULE_CONST; … }`
|
|
753
|
-
* Returns the constant's name and inferred type, or null.
|
|
754
|
-
*/
|
|
755
|
-
private resolveBlockBodyMemoModuleConst;
|
|
756
|
-
/**
|
|
757
|
-
* (#1897 PostList) Compute the SSR value of an object-returning block-body
|
|
758
|
-
* memo derived from `searchParams()`:
|
|
759
|
-
* () => { const sp = searchParams(); return { sort: asSortKey(sp.get('sort')),
|
|
760
|
-
* tag: sp.get('tag') ?? '' } }
|
|
761
|
-
* Emits a Go `map[string]interface{}{ "Sort": …, "Tag": … }` whose values are
|
|
762
|
-
* lowered from the request query (see `lowerCtorExpr`). Keys are capitalized to
|
|
763
|
-
* match the template's `.Params.<Field>` map access. Returns null for any shape
|
|
764
|
-
* the lowerer can't represent, so the caller falls back to a nil map.
|
|
765
|
-
*/
|
|
766
|
-
private computeObjectMemoInitialValue;
|
|
767
|
-
/**
|
|
768
|
-
* Lower a JS expression to a Go expression in the `NewXxxProps` constructor
|
|
769
|
-
* context. This is Go *code*, not template syntax — so a search-param read
|
|
770
|
-
* becomes `in.SearchParams.Get("k")` (method call), not the template's
|
|
771
|
-
* `.SearchParams.Get "k"`. Supports the narrow surface derived-state memos
|
|
772
|
-
* need: string/number literals, `<sp>.get('k')`, `<arr>.includes(<x>)`,
|
|
773
|
-
* module arrow-helper inlining, `<expr> ?? <fallback>`, and string ternaries.
|
|
774
|
-
* Returns null for anything else so the caller can fall back safely.
|
|
775
|
-
*/
|
|
776
|
-
private lowerCtorExpr;
|
|
777
|
-
/**
|
|
778
|
-
* Lower a JS expression used as a *boolean* condition to a Go bool expression,
|
|
779
|
-
* or null when it is not provably boolean. Distinct from `lowerCtorExpr`,
|
|
780
|
-
* which lowers value expressions: a string-valued condition (`sp.get('tag')`)
|
|
781
|
-
* is truthy in JS but `if "<string>"` does not compile in Go, so anything not
|
|
782
|
-
* known to yield a Go bool must fall back to null (#1941 review).
|
|
783
|
-
*/
|
|
784
|
-
private lowerCtorCond;
|
|
785
|
-
/**
|
|
786
|
-
* Resolve a string-array expression (a `['a','b']` literal, or a module const
|
|
787
|
-
* bound to one) to a Go `[]string{…}` literal, or null when it isn't a pure
|
|
788
|
-
* string-array. Used by `lowerCtorExpr` for `<arr>.includes(<x>)`.
|
|
789
|
-
*/
|
|
790
|
-
private lowerCtorStringArray;
|
|
791
|
-
/**
|
|
792
|
-
* Whether a memo is an arrow whose result is a template literal — either a
|
|
793
|
-
* concise body (`() => \`…\``) or a block body whose `return` is one.
|
|
794
|
-
*/
|
|
795
|
-
private isTemplateLiteralMemo;
|
|
796
|
-
/**
|
|
797
|
-
* Infer the Go type for a memo based on its computation and dependencies.
|
|
798
|
-
*/
|
|
231
|
+
/** Infer the Go type for a memo from its computation and dependencies. */
|
|
799
232
|
private inferMemoType;
|
|
800
233
|
/**
|
|
801
|
-
*
|
|
802
|
-
*
|
|
803
|
-
*
|
|
804
|
-
* (zero value `false`) over the int `0` default for the SSR initial value.
|
|
805
|
-
*/
|
|
806
|
-
private isBooleanMemo;
|
|
807
|
-
/**
|
|
808
|
-
* Infer Go type from a JavaScript value literal.
|
|
809
|
-
*/
|
|
810
|
-
private inferTypeFromValue;
|
|
811
|
-
/**
|
|
812
|
-
* (#1423) Hoisted-variable record for a prop with a signal-time
|
|
813
|
-
* `??` fallback. The same record is referenced from the prop field
|
|
814
|
-
* loop, the signal field loop, and the memo computation path.
|
|
815
|
-
*/
|
|
816
|
-
private static EMPTY_PROP_FALLBACK_VARS;
|
|
817
|
-
/**
|
|
818
|
-
* (#1423) Walk signals to collect prop fallbacks. Skips props that
|
|
819
|
-
* already have a destructure-side default (`{ X = N }`) or signals
|
|
820
|
-
* whose fallback resolves to the type's Go zero value (no-op).
|
|
234
|
+
* Walk signals to collect prop fallbacks. Skips props that already have a
|
|
235
|
+
* destructure-side default (`{ X = N }`) or signals whose fallback resolves to
|
|
236
|
+
* the type's Go zero value (no-op).
|
|
821
237
|
*/
|
|
822
238
|
private collectPropFallbackVars;
|
|
823
239
|
/**
|
|
824
|
-
*
|
|
825
|
-
*
|
|
826
|
-
*
|
|
827
|
-
*
|
|
828
|
-
* `propsObjectName`
|
|
829
|
-
* - the fallback isn't a simple literal `goPropDefault` can translate
|
|
240
|
+
* Parse a signal-time initial value of the form `props.X ?? <literal>` into
|
|
241
|
+
* the source prop name and the Go-formatted fallback. Returns null when the
|
|
242
|
+
* expression isn't a `??` against a property access on `propsObjectName`, or
|
|
243
|
+
* the fallback isn't a simple literal `goPropDefault` can translate.
|
|
830
244
|
*
|
|
831
|
-
*
|
|
832
|
-
*
|
|
833
|
-
* need the original prop reference (not just the resolved value)
|
|
834
|
-
* to honour caller-supplied non-zero inputs.
|
|
245
|
+
* Keeps the original prop reference (not just the resolved value) so
|
|
246
|
+
* caller-supplied non-zero inputs are honoured.
|
|
835
247
|
*/
|
|
836
248
|
private extractPropFallback;
|
|
837
249
|
/**
|
|
838
|
-
* Extract prop name from a signal's
|
|
839
|
-
* e.g
|
|
250
|
+
* Extract the prop name from a signal's `props.xxx`-pattern initialValue,
|
|
251
|
+
* e.g. `"props.initial ?? 0"` → `"initial"`, `"props.checked"` → `"checked"`.
|
|
840
252
|
*/
|
|
841
253
|
private extractPropNameFromInitialValue;
|
|
842
|
-
/**
|
|
843
|
-
* A source key that can become a Go struct field — i.e. a valid Go
|
|
844
|
-
* identifier. TS object keys that aren't (e.g. `"data-id"`, numeric keys)
|
|
845
|
-
* can't be exported struct fields, so they're excluded from struct generation
|
|
846
|
-
* and from the baker's field map.
|
|
847
|
-
*/
|
|
848
|
-
private static GO_IDENTIFIER;
|
|
849
|
-
/** Go common initialisms that should be fully uppercased (https://go.dev/wiki/CodeReviewComments#initialisms) */
|
|
850
|
-
static GO_INITIALISMS: Set<string>;
|
|
851
|
-
/**
|
|
852
|
-
* (#1423) Go reserved keywords. When we hoist a local var named after
|
|
853
|
-
* a JSX prop, the prop name could collide with one of these — append
|
|
854
|
-
* `_` until the name is free.
|
|
855
|
-
*/
|
|
856
|
-
private static GO_KEYWORDS;
|
|
857
|
-
private capitalizeFieldName;
|
|
858
|
-
/**
|
|
859
|
-
* Convert a JavaScript literal value to Go literal syntax.
|
|
860
|
-
*/
|
|
861
|
-
/**
|
|
862
|
-
* Translate a JSX param default (e.g. `'default'`, `0`, `false`) into
|
|
863
|
-
* the corresponding Go literal. Returns null when the default is
|
|
864
|
-
* absent or non-trivial (objects, arrow functions, etc.) — those
|
|
865
|
-
* fall back to letting Go's zero value win.
|
|
866
|
-
*/
|
|
867
|
-
private goPropDefault;
|
|
868
|
-
/**
|
|
869
|
-
* Wrap an `in.X` reference in a Go expression that substitutes
|
|
870
|
-
* `fallback` when the input is the zero value for its type. We pick
|
|
871
|
-
* the comparison based on the fallback literal's shape.
|
|
872
|
-
*
|
|
873
|
-
* Asymmetry on bool defaults is intentional and worth flagging:
|
|
874
|
-
* - For a `true` default, the generated expression is
|
|
875
|
-
* `(in.X || true)` — which is **always `true`**. Go has no
|
|
876
|
-
* unset-vs-explicit-false distinction at the struct-field level,
|
|
877
|
-
* so any caller wanting to thread `false` through has to set it
|
|
878
|
-
* after `NewXxxProps` rather than via the input struct.
|
|
879
|
-
* - For a `false` default, the Go zero value already matches, so
|
|
880
|
-
* the helper is a no-op (returns `ref` unchanged).
|
|
881
|
-
* Numeric `0` defaults are similarly indistinguishable from "unset"
|
|
882
|
-
* and pass through as the zero value; non-zero numeric defaults
|
|
883
|
-
* substitute, matching the JSX behavior of `(initial = 5) => ...`.
|
|
884
|
-
*/
|
|
885
|
-
private applyGoFallback;
|
|
886
|
-
private goLiteral;
|
|
887
254
|
/**
|
|
888
255
|
* Public entry point for node rendering. Delegates to the shared
|
|
889
|
-
* `IRNodeEmitter` dispatcher
|
|
890
|
-
*
|
|
256
|
+
* `IRNodeEmitter` dispatcher; per-kind logic lives in the `IRNodeEmitter`
|
|
257
|
+
* methods below.
|
|
891
258
|
*/
|
|
892
259
|
renderNode(node: IRNode, ctx?: GoRenderCtx): string;
|
|
893
260
|
emitElement(node: IRElement, _ctx: GoRenderCtx, _emit: EmitIRNode<GoRenderCtx>): string;
|
|
@@ -904,57 +271,38 @@ export declare class GoTemplateAdapter extends BaseAdapter implements ParsedExpr
|
|
|
904
271
|
renderElement(element: IRElement): string;
|
|
905
272
|
renderExpression(expr: IRExpression): string;
|
|
906
273
|
/**
|
|
907
|
-
*
|
|
908
|
-
*
|
|
909
|
-
*
|
|
910
|
-
*
|
|
911
|
-
* wrap-or-not decision across `renderExpression`, `templateLiteral`, and the
|
|
912
|
-
* static-string / attribute interpolation paths.
|
|
274
|
+
* Whether a lowered Go string already carries its own `{{...}}` actions and so
|
|
275
|
+
* must NOT be re-wrapped (`{{ {{...}} }}` is a parse error). Single source of
|
|
276
|
+
* the wrap-or-not decision across the expression / template-literal / attr
|
|
277
|
+
* paths.
|
|
913
278
|
*
|
|
914
|
-
*
|
|
915
|
-
*
|
|
916
|
-
*
|
|
917
|
-
*
|
|
918
|
-
*
|
|
919
|
-
*
|
|
920
|
-
* 1. A pure action block (`{{if}}` / `{{with}}` / `{{range}}` from a ternary,
|
|
921
|
-
* a `find().prop`, a `filter().length`, …). The emitter prepends NO
|
|
922
|
-
* literal text to these, so they ALWAYS start with `{{`; a leading `{{`
|
|
923
|
-
* is therefore an unambiguous structural marker for this whole class.
|
|
924
|
-
* 2. A template literal — the ONLY source form that interleaves author
|
|
925
|
-
* literal text with `{{...}}` actions (` · #${tag}` → ` · #{{.Tag}}`), so
|
|
926
|
-
* it may begin with literal text and is detected by its parsed `kind`.
|
|
927
|
-
*
|
|
928
|
-
* Everything else is a bare pipeline (`.Foo`, `len .X`, `bf_arr …`) — even one
|
|
929
|
-
* whose value contains `{{` inside a Go string literal — and MUST be wrapped.
|
|
930
|
-
*
|
|
931
|
-
* Invariant (enforced by the `template-fragment invariant` tests): no
|
|
932
|
-
* non-template-literal fragment ever begins with literal text, so case 1's
|
|
933
|
-
* `startsWith('{{')` is complete. If a future emitter prepends literal text to
|
|
934
|
-
* an action block those tests fail — fix it by giving that shape a parsed kind
|
|
935
|
-
* this helper can key off, exactly as template literals are handled here.
|
|
279
|
+
* Structural, deliberately NOT a `{{` substring scan (a Go string literal may
|
|
280
|
+
* contain `{{`). Exactly two shapes are fragments: an action block, which the
|
|
281
|
+
* emitter never prefixes with literal text so it always starts with `{{`; and
|
|
282
|
+
* a template literal, the only form interleaving author text with actions,
|
|
283
|
+
* keyed by its parsed `kind`. The "no non-template-literal fragment starts
|
|
284
|
+
* with literal text" invariant is enforced by the template-fragment tests.
|
|
936
285
|
*/
|
|
937
286
|
private isTemplateFragment;
|
|
938
287
|
/**
|
|
939
|
-
* Render a client-only conditional as comment markers
|
|
940
|
-
*
|
|
941
|
-
*
|
|
288
|
+
* Render a client-only conditional as comment markers (used when @client is
|
|
289
|
+
* applied to an unsupported conditional). The client evaluates the condition
|
|
290
|
+
* via insert().
|
|
942
291
|
*/
|
|
943
292
|
private renderClientOnlyConditional;
|
|
944
293
|
/**
|
|
945
|
-
* Render a ParsedExpr to Go template syntax via the shared
|
|
946
|
-
*
|
|
947
|
-
*
|
|
948
|
-
* so existing call sites keep working.
|
|
294
|
+
* Render a ParsedExpr to Go template syntax via the shared dispatcher. The
|
|
295
|
+
* per-kind logic lives in the `ParsedExprEmitter` methods below; this is a
|
|
296
|
+
* thin wrapper so existing call sites keep working.
|
|
949
297
|
*/
|
|
950
298
|
private renderParsedExpr;
|
|
951
299
|
identifier(name: string): string;
|
|
952
300
|
/**
|
|
953
|
-
*
|
|
954
|
-
*
|
|
955
|
-
*
|
|
956
|
-
*
|
|
957
|
-
*
|
|
301
|
+
* Compute the Go struct fields for component-scope derived string consts
|
|
302
|
+
* referenced by the template (e.g. `root = base || '/'`). Each is lowered to a
|
|
303
|
+
* constructor-context Go expression via `lowerCtorExpr`, with its dependency
|
|
304
|
+
* consts inlined. Skips names that collide with an existing field
|
|
305
|
+
* (`takenFieldNames`) or that the lowerer can't represent.
|
|
958
306
|
*/
|
|
959
307
|
private computeDerivedConstFields;
|
|
960
308
|
/**
|
|
@@ -978,15 +326,15 @@ export declare class GoTemplateAdapter extends BaseAdapter implements ParsedExpr
|
|
|
978
326
|
* that lives on the component's top-level data struct. Inside a `{{range}}`
|
|
979
327
|
* the dot is rebound to the iteration element, so root data must be reached
|
|
980
328
|
* through Go template's `$` (the top-level argument to Execute), which never
|
|
981
|
-
* rebinds. Outside any loop the root *is* the dot, so we emit `.Field
|
|
329
|
+
* rebinds. Outside any loop the root *is* the dot, so we emit `.Field`.
|
|
982
330
|
*/
|
|
983
331
|
private rootFieldRef;
|
|
984
332
|
/**
|
|
985
|
-
*
|
|
986
|
-
*
|
|
987
|
-
*
|
|
988
|
-
*
|
|
989
|
-
*
|
|
333
|
+
* When `name` is a local binding of the `searchParams()` env signal, resolve
|
|
334
|
+
* it to the canonical `.SearchParams` field — not `.<Capitalized name>` — so
|
|
335
|
+
* an aliased `import { searchParams as sp }` (`sp()`) reaches the same struct
|
|
336
|
+
* field the generator emits. Returns null for any other name so callers fall
|
|
337
|
+
* back to their normal field-ref lowering.
|
|
990
338
|
*/
|
|
991
339
|
private searchParamsFieldRef;
|
|
992
340
|
/**
|
|
@@ -999,21 +347,14 @@ export declare class GoTemplateAdapter extends BaseAdapter implements ParsedExpr
|
|
|
999
347
|
* pure compile-time string can be safely inlined byte-for-byte.
|
|
1000
348
|
*/
|
|
1001
349
|
private collectModuleStringConsts;
|
|
1002
|
-
/**
|
|
1003
|
-
* (#checkbox) Statically evaluate `[<string literals>].join(<sep?>)`.
|
|
1004
|
-
* Returns the joined string, or null when the shape doesn't match (non-call,
|
|
1005
|
-
* non-`.join`, non-array receiver, any non-string-literal element, or a
|
|
1006
|
-
* non-string-literal separator). Comments/whitespace between elements are
|
|
1007
|
-
* irrelevant — the TS parser already discarded them.
|
|
1008
|
-
*/
|
|
1009
350
|
/**
|
|
1010
351
|
* Resolve an identifier to its inlined Go string literal when it names a
|
|
1011
352
|
* module pure-string const. Returns the Go template literal form
|
|
1012
|
-
* (`"<escaped>"`) so callers can drop it straight into a `{{...}}` action,
|
|
1013
|
-
*
|
|
1014
|
-
*
|
|
1015
|
-
*
|
|
1016
|
-
*
|
|
353
|
+
* (`"<escaped>"`) so callers can drop it straight into a `{{...}}` action, or
|
|
354
|
+
* `null` when the name is not such a const (the caller then falls back to its
|
|
355
|
+
* normal field-ref lowering). The value is escaped for a Go double-quoted
|
|
356
|
+
* string literal; `html/template` then applies its usual contextual
|
|
357
|
+
* auto-escaping.
|
|
1017
358
|
*/
|
|
1018
359
|
private resolveModuleStringConst;
|
|
1019
360
|
/**
|
|
@@ -1033,37 +374,66 @@ export declare class GoTemplateAdapter extends BaseAdapter implements ParsedExpr
|
|
|
1033
374
|
logical(op: '&&' | '||' | '??', left: ParsedExpr, right: ParsedExpr, emit: (e: ParsedExpr) => string): string;
|
|
1034
375
|
conditional(test: ParsedExpr, consequent: ParsedExpr, alternate: ParsedExpr, emit: (e: ParsedExpr) => string): string;
|
|
1035
376
|
templateLiteral(parts: TemplatePart[], emit: (e: ParsedExpr) => string): string;
|
|
1036
|
-
|
|
377
|
+
arrow(params: string[], _body: ParsedExpr, _emit: (e: ParsedExpr) => string): string;
|
|
378
|
+
regex(raw: string): string;
|
|
1037
379
|
arrayLiteral(elements: ParsedExpr[], emit: (e: ParsedExpr) => string): string;
|
|
1038
|
-
|
|
380
|
+
objectLiteral(_properties: ObjectLiteralProperty[], raw: string, _emit: (e: ParsedExpr) => string): string;
|
|
381
|
+
/** Set of predicate (boolean-callback) higher-order methods. */
|
|
382
|
+
private static readonly PREDICATE_METHODS;
|
|
383
|
+
/**
|
|
384
|
+
* Recover the (removed) `higher-order` destructured shape from a generic
|
|
385
|
+
* `call` that is a recognised callback method whose method is a *predicate*
|
|
386
|
+
* one. Returns null for sort/reduce/flatMap or any non-callback call. Used by
|
|
387
|
+
* the `member`-arm short-circuits (`obj.filter(...).length`,
|
|
388
|
+
* `obj.find(...).prop`) that need the structured fallbacks.
|
|
389
|
+
*/
|
|
390
|
+
private higherOrderShapeOf;
|
|
391
|
+
/**
|
|
392
|
+
* Push BF101 for a callback method whose shape has no Go template form.
|
|
393
|
+
*
|
|
394
|
+
* `selfContained` callbacks (`reduce` / `flatMap` off the eval-lowerable
|
|
395
|
+
* catalogue — a `.reduce` with no init, a tuple `.flatMap` with a non-leaf
|
|
396
|
+
* element) carry the self-contained "no SSR" remedy and must NOT get the
|
|
397
|
+
* generic Options block appended (mirrors `isSupported`'s `selfContained`
|
|
398
|
+
* flag for `UNSUPPORTED_METHODS`). Predicate callbacks that exhaust their
|
|
399
|
+
* template-block fallbacks keep the generic Options remediation.
|
|
400
|
+
*/
|
|
401
|
+
private pushCallbackBF101;
|
|
402
|
+
callbackMethod(method: string, object: ParsedExpr, arrow: Extract<ParsedExpr, {
|
|
403
|
+
kind: 'arrow';
|
|
404
|
+
}>, restArgs: ParsedExpr[], emit: (e: ParsedExpr) => string): string;
|
|
1039
405
|
arrayMethod(method: ArrayMethod, object: ParsedExpr, args: ParsedExpr[], emit: (e: ParsedExpr) => string): string;
|
|
1040
|
-
sortMethod(method: 'sort' | 'toSorted', object: ParsedExpr, comparator: SortComparator, emit: (e: ParsedExpr) => string): string;
|
|
1041
|
-
reduceMethod(method: 'reduce' | 'reduceRight', object: ParsedExpr, reduceOp: ReduceOp, emit: (e: ParsedExpr) => string): string;
|
|
1042
406
|
flatMethod(object: ParsedExpr, depth: FlatDepth, emit: (e: ParsedExpr) => string): string;
|
|
1043
|
-
flatMapMethod(object: ParsedExpr, op: FlatMapOp, emit: (e: ParsedExpr) => string): string;
|
|
1044
407
|
unsupported(raw: string, _reason: string): string;
|
|
1045
408
|
/**
|
|
1046
409
|
* Extract field name and negation from a simple predicate.
|
|
1047
|
-
*
|
|
1048
|
-
*
|
|
410
|
+
* `t => t.done` → { field: "Done", negated: false }
|
|
411
|
+
* `t => !t.done` → { field: "Done", negated: true }
|
|
1049
412
|
*/
|
|
1050
413
|
private extractFieldPredicate;
|
|
1051
414
|
/**
|
|
1052
|
-
* Extract field name and value from an equality predicate
|
|
1053
|
-
*
|
|
1054
|
-
*
|
|
1055
|
-
*
|
|
1056
|
-
*
|
|
1057
|
-
* u.id
|
|
1058
|
-
* selectedId() === u.id → same (supports both operand orders)
|
|
415
|
+
* Extract field name and value from an equality predicate (extends
|
|
416
|
+
* extractFieldPredicate to also handle equality comparisons).
|
|
417
|
+
* `t.done` → { field: "Done", value: "true" }
|
|
418
|
+
* `!t.done` → { field: "Done", value: "false" }
|
|
419
|
+
* `u.id === selectedId()` → { field: "Id", value: <rendered expr> }
|
|
420
|
+
* `selectedId() === u.id` → same (both operand orders supported)
|
|
1059
421
|
*/
|
|
1060
422
|
private extractEqualityPredicate;
|
|
1061
423
|
/**
|
|
1062
|
-
*
|
|
1063
|
-
*
|
|
1064
|
-
*
|
|
1065
|
-
*
|
|
1066
|
-
*
|
|
424
|
+
* Emit a higher-order method through the runtime evaluator (#2018 P2):
|
|
425
|
+
* `bf_filter_eval` / `bf_every_eval` / `bf_some_eval` / `bf_find_eval` /
|
|
426
|
+
* `bf_find_index_eval`, carrying the serialized predicate body + captured
|
|
427
|
+
* env. Returns null when the predicate is outside the evaluator surface
|
|
428
|
+
* (caller falls back to the structured helper / template block). The find /
|
|
429
|
+
* findLast (and findIndex / findLastIndex) pair share a helper, differing
|
|
430
|
+
* only by the `forward` bool argument.
|
|
431
|
+
*/
|
|
432
|
+
private renderHigherOrderEval;
|
|
433
|
+
/**
|
|
434
|
+
* Render a higher-order expression (filter, every, some, find, findIndex) to
|
|
435
|
+
* Go template, or null when the shape isn't supported. `renderArray` is passed
|
|
436
|
+
* in so the array can recurse through different lowering methods.
|
|
1067
437
|
*/
|
|
1068
438
|
private renderHigherOrderExpr;
|
|
1069
439
|
/**
|
|
@@ -1077,39 +447,30 @@ export declare class GoTemplateAdapter extends BaseAdapter implements ParsedExpr
|
|
|
1077
447
|
*/
|
|
1078
448
|
private renderFindTemplateBlock;
|
|
1079
449
|
/**
|
|
1080
|
-
* Render every()/some() with complex predicates
|
|
1081
|
-
*
|
|
1082
|
-
*
|
|
450
|
+
* Render every()/some() with complex predicates as a `{{range}}{{if}}` with
|
|
451
|
+
* variable reassignment — the fallback from bf_every/bf_some when
|
|
452
|
+
* extractFieldPredicate returns null.
|
|
1083
453
|
*
|
|
1084
|
-
*
|
|
1085
|
-
*
|
|
1086
|
-
*
|
|
1087
|
-
* @param expr - The higher-order every/some expression
|
|
1088
|
-
* @param renderArray - Function to render the array expression
|
|
454
|
+
* every: start true, set false on first failure, break early
|
|
455
|
+
* some: start false, set true on first match, break early
|
|
1089
456
|
*/
|
|
1090
457
|
private renderEverySomeTemplateBlock;
|
|
1091
458
|
/**
|
|
1092
|
-
* Negate a Go template condition
|
|
1093
|
-
*
|
|
1094
|
-
* otherwise uses `not condition`.
|
|
459
|
+
* Negate a Go template condition: `not (...)` when it's a Go function call
|
|
460
|
+
* (eq, ne, gt, …), else `not condition`.
|
|
1095
461
|
*/
|
|
1096
462
|
private negateGoCondition;
|
|
1097
463
|
/**
|
|
1098
|
-
* Render
|
|
1099
|
-
*
|
|
1100
|
-
*
|
|
1101
|
-
* @param filterExpr - The filter higher-order expression
|
|
1102
|
-
* @param renderArray - Function to render the array expression
|
|
464
|
+
* Render `.length` on a filter higher-order expression, e.g.
|
|
465
|
+
* `todos().filter(t => !t.done).length` → `len (bf_filter .Todos "Done" false)`.
|
|
1103
466
|
*/
|
|
1104
467
|
private renderFilterLengthExpr;
|
|
1105
468
|
/**
|
|
1106
|
-
* Render a predicate
|
|
1107
|
-
*
|
|
469
|
+
* Render a predicate for use in Go template `{{if}}` conditions, substituting
|
|
470
|
+
* the loop parameter (e.g. `t` in `t.done`) with dot notation.
|
|
1108
471
|
*/
|
|
1109
472
|
private renderPredicateCondition;
|
|
1110
|
-
/**
|
|
1111
|
-
* Check if expression needs parentheses when used in and/or.
|
|
1112
|
-
*/
|
|
473
|
+
/** Whether an expression needs parentheses when used in and/or. */
|
|
1113
474
|
private needsParens;
|
|
1114
475
|
/**
|
|
1115
476
|
* Split a rendered template block into preamble + final expression.
|
|
@@ -1120,169 +481,50 @@ export declare class GoTemplateAdapter extends BaseAdapter implements ParsedExpr
|
|
|
1120
481
|
*/
|
|
1121
482
|
private splitPreamble;
|
|
1122
483
|
/**
|
|
1123
|
-
* Render
|
|
1124
|
-
*
|
|
1125
|
-
*
|
|
1126
|
-
*
|
|
1127
|
-
* filter(t => {
|
|
1128
|
-
* const f = filter()
|
|
1129
|
-
* if (f === 'active') return !t.done
|
|
1130
|
-
* if (f === 'completed') return t.done
|
|
1131
|
-
* return true
|
|
1132
|
-
* })
|
|
1133
|
-
* ```
|
|
1134
|
-
*
|
|
1135
|
-
* Becomes:
|
|
1136
|
-
* ```
|
|
1137
|
-
* or (and (eq $.Filter "active") (not .Done))
|
|
1138
|
-
* (and (eq $.Filter "completed") .Done)
|
|
1139
|
-
* (and (ne $.Filter "active") (ne $.Filter "completed"))
|
|
1140
|
-
* ```
|
|
1141
|
-
*/
|
|
1142
|
-
private renderBlockBodyCondition;
|
|
1143
|
-
/**
|
|
1144
|
-
* Recursively collect all return paths through the statements.
|
|
1145
|
-
* Returns an array of ReturnPath objects.
|
|
1146
|
-
*/
|
|
1147
|
-
private collectReturnPaths;
|
|
1148
|
-
/**
|
|
1149
|
-
* Build a condition for a single return path.
|
|
1150
|
-
*/
|
|
1151
|
-
private buildSinglePathCondition;
|
|
1152
|
-
/**
|
|
1153
|
-
* Build an OR condition from multiple return paths.
|
|
1154
|
-
*/
|
|
1155
|
-
private buildOrCondition;
|
|
1156
|
-
/**
|
|
1157
|
-
* Render multiple conditions combined with AND.
|
|
1158
|
-
*/
|
|
1159
|
-
private renderConditionsAnd;
|
|
1160
|
-
/**
|
|
1161
|
-
* Unified method for rendering filter predicate expressions.
|
|
1162
|
-
* Used for both expression body (t => !t.done) and block body filters.
|
|
1163
|
-
*
|
|
1164
|
-
* @param expr - The parsed expression to render
|
|
1165
|
-
* @param param - The loop parameter name (e.g., 't' in filter(t => ...))
|
|
1166
|
-
* @param localVarMap - Optional map of local variables to signal names (for block body)
|
|
484
|
+
* Render a filter predicate expression (`t => !t.done`, or a block body
|
|
485
|
+
* normalized to one — #2040). `localVarMap` is a vestigial empty default kept
|
|
486
|
+
* on the recursion; block-body locals are now inlined upstream, so no caller
|
|
487
|
+
* populates it.
|
|
1167
488
|
*/
|
|
1168
489
|
private renderFilterExpr;
|
|
1169
490
|
private renderFilterExprNode;
|
|
1170
491
|
/**
|
|
1171
|
-
*
|
|
1172
|
-
*
|
|
492
|
+
* Whether a ParsedExpr renders as a Go template function call (so it needs
|
|
493
|
+
* parentheses around it).
|
|
1173
494
|
*/
|
|
1174
495
|
private isGoFunctionCall;
|
|
1175
496
|
/**
|
|
1176
|
-
* Render a branch of a conditional expression.
|
|
1177
|
-
*
|
|
1178
|
-
*
|
|
497
|
+
* Render a branch of a conditional expression. String literals render as bare
|
|
498
|
+
* text (no quotes); nested conditionals render as complete `{{if}}…{{end}}`
|
|
499
|
+
* blocks; everything else is wrapped in `{{...}}`.
|
|
1179
500
|
*/
|
|
1180
501
|
private renderConditionalBranch;
|
|
1181
502
|
/**
|
|
1182
|
-
*
|
|
1183
|
-
*
|
|
1184
|
-
*
|
|
503
|
+
* Whether a ParsedExpr renders to a Go template function call (`len .X`,
|
|
504
|
+
* `bf_add .A .B`) that needs parentheses when used as an argument to a
|
|
505
|
+
* comparison operator (eq, gt, lt, …).
|
|
1185
506
|
*/
|
|
1186
507
|
private needsParensInGoTemplate;
|
|
1187
|
-
/**
|
|
1188
|
-
* Convert a JS expression to Go template syntax.
|
|
1189
|
-
*/
|
|
508
|
+
/** Convert a JS expression to Go template syntax. */
|
|
1190
509
|
private convertExpressionToGo;
|
|
1191
510
|
/**
|
|
1192
|
-
*
|
|
1193
|
-
*
|
|
1194
|
-
*
|
|
1195
|
-
*
|
|
1196
|
-
* or
|
|
1197
|
-
*
|
|
1198
|
-
*
|
|
1199
|
-
* shadowing- and member-name-safe.
|
|
1200
|
-
*/
|
|
1201
|
-
private inlineLocalHelperCall;
|
|
1202
|
-
/**
|
|
1203
|
-
* Guard for `substituteHelperParams`: the span splicer replaces identifiers by
|
|
1204
|
-
* name without scope tracking, so it is only safe on bodies free of
|
|
1205
|
-
* constructs where a param name could appear in a position the splice can't
|
|
1206
|
-
* handle — a nested function scope (shadowing or its own parameters), or an
|
|
1207
|
-
* object shorthand key (`{ k }`, which can't be rewritten to `{ (arg) }`).
|
|
1208
|
-
*/
|
|
1209
|
-
private isSpliceSafeHelperBody;
|
|
1210
|
-
/**
|
|
1211
|
-
* True when `body` contains a call to a *local* (component-scope) arrow helper
|
|
1212
|
-
* const — the signal that inlining `body` here would only push the problem to
|
|
1213
|
-
* another un-lowered helper (e.g. `sortHref`'s body calls `hrefFor`).
|
|
1214
|
-
*/
|
|
1215
|
-
private bodyCallsLocalHelper;
|
|
1216
|
-
/**
|
|
1217
|
-
* Re-emit `body` to source with each identifier named in `subs` replaced by
|
|
1218
|
-
* the substitution's source text. Implemented as span splicing over `body`'s
|
|
1219
|
-
* own source (single source file — args are passed as text, not cross-file
|
|
1220
|
-
* AST nodes, which would corrupt a printer keyed to `body`'s source). The walk
|
|
1221
|
-
* skips non-value identifier positions — the property NAME in `a.b` and a
|
|
1222
|
-
* plain object-literal key in `{ k: … }` — so a param sharing a name with a
|
|
1223
|
-
* member or key is left untouched. (`isSpliceSafeHelperBody` has already
|
|
1224
|
-
* rejected nested functions and `{ k }` shorthand keys.)
|
|
1225
|
-
*/
|
|
1226
|
-
private substituteHelperParams;
|
|
1227
|
-
/**
|
|
1228
|
-
* (#1897 PostList) Lower a call to a local URL-builder helper to a `bf_query`
|
|
1229
|
-
* template expression. Handles two shapes:
|
|
1230
|
-
* - the builder itself — `(sort, tag) => { const u = new URLSearchParams();
|
|
1231
|
-
* if (sort !== 'date') u.set('sort', sort); if (tag) u.set('tag', tag);
|
|
1232
|
-
* return u.toString() ? \`${root}?${u}\` : root }` — substitute the call
|
|
1233
|
-
* args for params and emit `bf_query <base> (<guard>) "key" <value> …`;
|
|
1234
|
-
* - a pass-through delegate — `(k) => hrefFor(k, params().tag)` — substitute
|
|
1235
|
-
* and recurse on the delegated call.
|
|
1236
|
-
* Returns null for anything else (→ existing lowering / method-call fallback).
|
|
1237
|
-
*/
|
|
1238
|
-
private lowerUrlBuilderHelperCall;
|
|
1239
|
-
/**
|
|
1240
|
-
* Extract the `bf_query` shape from a `(…) => { const u = new URLSearchParams();
|
|
1241
|
-
* [if (G)] u.set(K, V); …; return <s> ? … : <base> }` helper, or null when the
|
|
1242
|
-
* block doesn't match that exact builder idiom.
|
|
1243
|
-
*/
|
|
1244
|
-
private extractUrlBuilder;
|
|
1245
|
-
/**
|
|
1246
|
-
* Match `<builderVar>.set('literalKey', <value>)` — as a statement or an
|
|
1247
|
-
* if-then — returning the key text and value node, else null.
|
|
1248
|
-
*/
|
|
1249
|
-
private matchUrlSet;
|
|
1250
|
-
/**
|
|
1251
|
-
* Emit `bf_query <base> (<guard>) "key" <value> …` from an extracted builder
|
|
1252
|
-
* shape, lowering each part (with the call args substituted for params) via
|
|
1253
|
-
* the normal expression / condition lowering. Unguarded sets use `true`.
|
|
1254
|
-
*/
|
|
1255
|
-
private emitUrlBuilder;
|
|
1256
|
-
/**
|
|
1257
|
-
* Lower a `u.set()` guard to a Go *bool* for `bf_query`'s `include` argument.
|
|
1258
|
-
* A comparison / logical / negation / bool-literal already yields a bool
|
|
1259
|
-
* (`convertConditionToGo`); a bare value (`if (tag)`) is JS string-truthiness,
|
|
1260
|
-
* lowered to `ne <value> ""`. The arg must be a real bool — `bf_query` type-
|
|
1261
|
-
* asserts it, so Go-template truthiness (`{{if x}}`) is not enough.
|
|
1262
|
-
*/
|
|
1263
|
-
private lowerUrlGuard;
|
|
1264
|
-
/**
|
|
1265
|
-
* Resolve `IDENT['key']` / `IDENT["key"]` where `IDENT` is a
|
|
1266
|
-
* module-scope object-literal const and the key is a string literal —
|
|
1267
|
-
* a compile-time-static lookup (the icon registry's
|
|
1268
|
-
* `strokePaths['chevron-down']`, #1896). Returns the looked-up value
|
|
1269
|
-
* as a Go literal (quoted string / bare number) usable inside a
|
|
1270
|
-
* template action, or `null` for any other shape so the caller falls
|
|
1271
|
-
* through to the generic lowering. The prop-keyed variant of the same
|
|
1272
|
-
* pattern lives in `parseRecordIndexAccess` (shared with Mojo); this
|
|
1273
|
-
* helper covers the literal-key case that parse rejects.
|
|
511
|
+
* Resolve `IDENT['key']` / `IDENT["key"]` where `IDENT` is a module-scope
|
|
512
|
+
* object-literal const and the key is a string literal — a compile-time-static
|
|
513
|
+
* lookup (the icon registry's `strokePaths['chevron-down']`). Returns the
|
|
514
|
+
* looked-up value as a Go literal (quoted string / bare number) usable inside a
|
|
515
|
+
* template action, or `null` for any other shape so the caller falls through to
|
|
516
|
+
* the generic lowering. The prop-keyed variant lives in `parseRecordIndexAccess`
|
|
517
|
+
* (shared with Mojo); this helper covers the literal-key case parse rejects.
|
|
1274
518
|
*/
|
|
1275
519
|
private resolveStaticRecordLiteralIndex;
|
|
1276
|
-
/**
|
|
1277
|
-
* Create a source location for error reporting.
|
|
1278
|
-
*/
|
|
520
|
+
/** Create a source location for error reporting. */
|
|
1279
521
|
private makeLoc;
|
|
1280
522
|
private renderIfStatement;
|
|
1281
523
|
renderConditional(cond: IRConditional): string;
|
|
1282
524
|
/**
|
|
1283
|
-
* Convert a JS condition to Go template condition syntax.
|
|
1284
|
-
*
|
|
1285
|
-
*
|
|
525
|
+
* Convert a JS condition to Go template condition syntax. `preamble` holds
|
|
526
|
+
* template blocks that must be emitted before the `{{if}}` (e.g. every/some
|
|
527
|
+
* range blocks).
|
|
1286
528
|
*/
|
|
1287
529
|
private convertConditionToGo;
|
|
1288
530
|
private renderConditionExpr;
|
|
@@ -1290,36 +532,33 @@ export declare class GoTemplateAdapter extends BaseAdapter implements ParsedExpr
|
|
|
1290
532
|
* Map each destructure binding to its Go accessor on the range var: a named
|
|
1291
533
|
* binding → `$<rangeVar>.<Field>`, an object-rest binding → the bare
|
|
1292
534
|
* `$<rangeVar>` so the member emitter renders `rest.flag` → `$<rangeVar>.Flag`.
|
|
1293
|
-
* (#1310)
|
|
1294
535
|
*/
|
|
1295
536
|
private buildDestructureBindingMap;
|
|
1296
537
|
renderLoop(loop: IRLoop): string;
|
|
1297
538
|
/**
|
|
1298
539
|
* Per-item `<!--bf-loop-i-->` / `<!--bf-loop-i:KEY-->` start marker emitted
|
|
1299
|
-
* inside a `{{range}}` body. Multi-root Fragment items
|
|
1300
|
-
*
|
|
1301
|
-
*
|
|
540
|
+
* inside a `{{range}}` body. Multi-root Fragment items get the bare anchor;
|
|
541
|
+
* whole-item conditional items get the key-bearing anchor so the client's
|
|
542
|
+
* `mapArrayAnchored` can hydrate items that render no element.
|
|
1302
543
|
*/
|
|
1303
544
|
private loopItemMarker;
|
|
1304
|
-
/**
|
|
1305
|
-
* Find the first component child in a list of nodes
|
|
1306
|
-
*/
|
|
545
|
+
/** Find the first component child in a list of nodes. */
|
|
1307
546
|
private findChildComponent;
|
|
1308
547
|
/**
|
|
1309
|
-
* When `comp`'s JSX children contain template actions (nested
|
|
1310
|
-
*
|
|
1311
|
-
* `collectStaticChildInstances` apply — render them into a companion
|
|
1312
|
-
*
|
|
1313
|
-
*
|
|
1314
|
-
*
|
|
1315
|
-
*
|
|
548
|
+
* When `comp`'s JSX children contain template actions (nested components,
|
|
549
|
+
* dynamic text) — i.e. none of the static bake paths in
|
|
550
|
+
* `collectStaticChildInstances` apply — render them into a companion define
|
|
551
|
+
* and return its name; `renderComponent` then routes the child call through
|
|
552
|
+
* `bf_with_children` + `bf_tmpl`. Returns null for childless or
|
|
553
|
+
* statically-bakeable children, which keep the constructor-baked `Children`
|
|
554
|
+
* value.
|
|
1316
555
|
*/
|
|
1317
556
|
private queueDynamicChildrenDefine;
|
|
1318
557
|
/**
|
|
1319
|
-
*
|
|
1320
|
-
*
|
|
1321
|
-
*
|
|
1322
|
-
*
|
|
558
|
+
* Queue a companion define for a loop body component's JSX children. Like
|
|
559
|
+
* `queueDynamicChildrenDefine` but temporarily exits the `inLoop` context so
|
|
560
|
+
* nested component calls render with the normal `.NameSlotN` field-access
|
|
561
|
+
* pattern (the fields live on the wrapper struct that the
|
|
1323
562
|
* companion define receives as its data context). The loop param stack
|
|
1324
563
|
* stays intact so datum-field references (`payment.id` → `.Id`) still
|
|
1325
564
|
* resolve.
|
|
@@ -1329,28 +568,23 @@ export declare class GoTemplateAdapter extends BaseAdapter implements ParsedExpr
|
|
|
1329
568
|
isRootOfClientComponent?: boolean;
|
|
1330
569
|
}): string;
|
|
1331
570
|
/**
|
|
1332
|
-
* Render a Portal component by adding its children to PortalCollector.
|
|
1333
|
-
*
|
|
1334
|
-
*
|
|
1335
|
-
*
|
|
1336
|
-
* For dynamic content: uses bfPortalHTML() to parse and execute template string
|
|
571
|
+
* Render a Portal component by adding its children to PortalCollector. Portal
|
|
572
|
+
* content is rendered at </body> instead of inline: static content via a plain
|
|
573
|
+
* string literal, dynamic content via `bfPortalHTML()` (parses and executes
|
|
574
|
+
* the template string with the provided data).
|
|
1337
575
|
*/
|
|
1338
576
|
private renderPortalComponent;
|
|
1339
577
|
private renderFragment;
|
|
1340
578
|
private renderSlot;
|
|
1341
579
|
renderAsync(node: IRAsync): string;
|
|
1342
|
-
private escapeGoString;
|
|
1343
580
|
/**
|
|
1344
|
-
* AttrValue lowering for intrinsic-element attributes
|
|
1345
|
-
*
|
|
1346
|
-
* `renderAttributes`; routed through the shared dispatcher so a new
|
|
1347
|
-
* AttrValue kind becomes a TS compile error here (#1290 step 2).
|
|
581
|
+
* AttrValue lowering for intrinsic-element attributes. Routed through the
|
|
582
|
+
* shared dispatcher so a new AttrValue kind becomes a TS compile error here.
|
|
1348
583
|
*
|
|
1349
|
-
* Components have no equivalent AttrValueEmitter
|
|
1350
|
-
*
|
|
1351
|
-
*
|
|
1352
|
-
*
|
|
1353
|
-
* intrinsic-attribute one.
|
|
584
|
+
* Components have no equivalent AttrValueEmitter: Go templates pass
|
|
585
|
+
* component-instance props as Go struct fields (built by
|
|
586
|
+
* `collectStaticChildInstances`), not as string-emitted markup, so that path
|
|
587
|
+
* doesn't share a contract with the intrinsic-attribute one.
|
|
1354
588
|
*/
|
|
1355
589
|
private readonly elementAttrEmitter;
|
|
1356
590
|
/**
|
|
@@ -1359,36 +593,24 @@ export declare class GoTemplateAdapter extends BaseAdapter implements ParsedExpr
|
|
|
1359
593
|
* `{ backgroundColor: color, padding: '8px' }` →
|
|
1360
594
|
* `background-color:{{.Color}};padding:8px`. Returns null when the object
|
|
1361
595
|
* shape is unsupported or any value expression can't be lowered (the caller
|
|
1362
|
-
* then falls through to the generic BF101 path).
|
|
596
|
+
* then falls through to the generic BF101 path).
|
|
1363
597
|
*/
|
|
1364
598
|
private tryLowerStyleObject;
|
|
1365
599
|
private renderAttributes;
|
|
1366
600
|
/**
|
|
1367
|
-
* Replace `${EXPR}`
|
|
1368
|
-
*
|
|
1369
|
-
*
|
|
1370
|
-
*
|
|
1371
|
-
*
|
|
1372
|
-
* UnoCSS arbitrary-value classes like `[class*="size-"]:size-4`
|
|
1373
|
-
* legitimately contain `"`, which would otherwise terminate the
|
|
1374
|
-
* `class="..."` attribute early and produce invalid HTML / a
|
|
1375
|
-
* `html/template` error at execution time.
|
|
1376
|
-
*
|
|
1377
|
-
* The interpolation parser is brace-depth aware: nested `{...}`
|
|
1378
|
-
* inside an expression (object literals, nested template literals,
|
|
1379
|
-
* etc.) are skipped past correctly so the closing brace of the
|
|
1380
|
-
* outer `${...}` is found. An unterminated `${` falls back to
|
|
1381
|
-
* literal text — better to output something than swallow it.
|
|
601
|
+
* Replace `${EXPR}` interpolations with Go actions (`{{<expr-as-go>}}`) and
|
|
602
|
+
* HTML-escape the surrounding literal text — UnoCSS arbitrary values
|
|
603
|
+
* (`[class*="size-"]:size-4`) contain `"` that would otherwise close the
|
|
604
|
+
* `class="..."` attribute. Brace-depth aware (nested `{...}` skipped to find
|
|
605
|
+
* the outer `}`); an unterminated `${` falls back to literal text.
|
|
1382
606
|
*/
|
|
1383
607
|
private substituteJsInterpolations;
|
|
1384
608
|
/**
|
|
1385
|
-
* HTML-attribute-safe escaping for double-quoted attribute values.
|
|
1386
|
-
*
|
|
1387
|
-
* `class
|
|
1388
|
-
*
|
|
1389
|
-
*
|
|
1390
|
-
* lexer is contextual and we'd rather not bet on its edge cases
|
|
1391
|
-
* matching ours forever.
|
|
609
|
+
* HTML-attribute-safe escaping for double-quoted attribute values. `&`/`"`/`<`
|
|
610
|
+
* are non-negotiable — without them the surrounding `class="..."` quoting
|
|
611
|
+
* breaks (e.g. UnoCSS's `[class*="size-"]`). `>`/`'` are belt-and-suspenders:
|
|
612
|
+
* HTML5 permits both inside double-quoted attrs, but Go's `html/template`
|
|
613
|
+
* lexer is contextual, so escape them too.
|
|
1392
614
|
*/
|
|
1393
615
|
private escapeAttrText;
|
|
1394
616
|
private renderTemplateLiteralParts;
|
|
@@ -1398,5 +620,4 @@ export declare class GoTemplateAdapter extends BaseAdapter implements ParsedExpr
|
|
|
1398
620
|
private wrapWithCondMarker;
|
|
1399
621
|
}
|
|
1400
622
|
export declare const goTemplateAdapter: GoTemplateAdapter;
|
|
1401
|
-
export {};
|
|
1402
623
|
//# sourceMappingURL=go-template-adapter.d.ts.map
|