@barefootjs/go-template 0.16.0 → 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 +2857 -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 +2856 -2617
- package/dist/index.js +2857 -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 +118 -54
- 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 +2099 -5325
- 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
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Value lowering: convert a JS signal/const initial value into a Go literal for
|
|
3
|
+
* the SSR data context — scalars, prop references, and fully-literal
|
|
4
|
+
* arrays/objects — falling back to `nil`/`0` for anything not reducible to a
|
|
5
|
+
* literal. Pure free functions over a {@link GoEmitContext}.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { ParsedExpr, TypeInfo } from '@barefootjs/jsx'
|
|
9
|
+
|
|
10
|
+
import type { GoEmitContext } from '../emit-context.ts'
|
|
11
|
+
import type { PropFallbackVar } from '../lib/types.ts'
|
|
12
|
+
import { capitalizeFieldName } from '../lib/go-naming.ts'
|
|
13
|
+
import { parsedLiteralToGo } from './parsed-literal-to-go.ts'
|
|
14
|
+
|
|
15
|
+
/** Default for `getSignalInitialValueAsGo`'s optional fallback-var map. */
|
|
16
|
+
const EMPTY_PROP_FALLBACK_VARS: ReadonlyMap<string, PropFallbackVar> = new Map()
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Lower a signal/const initial value to its Go SSR literal: a prop reference
|
|
20
|
+
* becomes `in.<Field>`, a non-literal falls back to the type's zero value.
|
|
21
|
+
*/
|
|
22
|
+
export function convertInitialValue(
|
|
23
|
+
ctx: GoEmitContext,
|
|
24
|
+
value: string,
|
|
25
|
+
typeInfo: TypeInfo,
|
|
26
|
+
propsParams?: { name: string }[],
|
|
27
|
+
preParsed?: ParsedExpr,
|
|
28
|
+
): string {
|
|
29
|
+
if (/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(value)) {
|
|
30
|
+
if (propsParams?.some(p => p.name === value)) {
|
|
31
|
+
return `in.${capitalizeFieldName(value)}`
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const propName = ctx.extractPropNameFromInitialValue(value)
|
|
36
|
+
if (propName && propsParams?.some(p => p.name === propName)) {
|
|
37
|
+
return `in.${capitalizeFieldName(propName)}`
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (typeInfo.kind === 'primitive') {
|
|
41
|
+
if (typeInfo.primitive === 'boolean') {
|
|
42
|
+
return value === 'true' ? 'true' : 'false'
|
|
43
|
+
}
|
|
44
|
+
if (typeInfo.primitive === 'number') {
|
|
45
|
+
if (/^\d+$/.test(value)) return value
|
|
46
|
+
if (/^\d+\.\d+$/.test(value)) return value
|
|
47
|
+
return '0'
|
|
48
|
+
}
|
|
49
|
+
if (typeInfo.primitive === 'string') {
|
|
50
|
+
if (value.startsWith("'") || value.endsWith("'")) {
|
|
51
|
+
return value.replace(/'/g, '"')
|
|
52
|
+
}
|
|
53
|
+
if (value.startsWith('"') && value.endsWith('"')) {
|
|
54
|
+
return value
|
|
55
|
+
}
|
|
56
|
+
return '""'
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (typeInfo.kind === 'array') {
|
|
61
|
+
return jsLiteralToGo(ctx, typeInfo, preParsed) ?? 'nil'
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// A string type-alias keeps its string value instead of falling to nil.
|
|
65
|
+
if (typeInfo.kind === 'interface' && typeInfo.raw) {
|
|
66
|
+
const aliasBase = ctx.state.localTypeAliases.get(typeInfo.raw)
|
|
67
|
+
if (aliasBase === 'string') {
|
|
68
|
+
if (value.startsWith("'") || value.startsWith('"')) {
|
|
69
|
+
return value.replace(/'/g, '"')
|
|
70
|
+
}
|
|
71
|
+
return '""'
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return 'nil'
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Lower a fully-literal value — from the analyzer's carried `ParsedExpr` tree —
|
|
80
|
+
* to a Go literal typed as `typeInfo`:
|
|
81
|
+
*
|
|
82
|
+
* `["x", "y"]` (string[]) → `[]string{"x", "y"}`
|
|
83
|
+
* `["x", "y"]` (unknown[]) → `[]interface{}{"x", "y"}`
|
|
84
|
+
* `[{ id: "a" }]` (Item[]) → `[]Item{Item{ID: "a"}}`
|
|
85
|
+
*
|
|
86
|
+
* Returns null (caller keeps `nil`) for a non-literal, or a shape that can't be
|
|
87
|
+
* expressed in the target type (e.g. an object in a `[]interface{}`, unreachable
|
|
88
|
+
* via the template's struct-field access).
|
|
89
|
+
*/
|
|
90
|
+
export function jsLiteralToGo(
|
|
91
|
+
ctx: GoEmitContext,
|
|
92
|
+
typeInfo: TypeInfo,
|
|
93
|
+
preParsed?: ParsedExpr,
|
|
94
|
+
): string | null {
|
|
95
|
+
if (preParsed) {
|
|
96
|
+
const structured = parsedLiteralToGo(ctx, preParsed, typeInfo)
|
|
97
|
+
if (structured !== null) return structured
|
|
98
|
+
}
|
|
99
|
+
return null
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Bake a flat object literal (`{ align: 'start' }`) into a Go
|
|
104
|
+
* `map[string]interface{}` keyed by SOURCE property names, so it round-trips
|
|
105
|
+
* through `bf_json` like `JSON.stringify` (only the supplied keys, no zero-filled
|
|
106
|
+
* struct fields). Used for an inline object passed to a child's optional object
|
|
107
|
+
* prop. Returns null for a non-object / shorthand / nested / empty object.
|
|
108
|
+
*/
|
|
109
|
+
export function objectLiteralToGoMap(ctx: GoEmitContext, expr: ParsedExpr): string | null {
|
|
110
|
+
if (expr.kind !== 'object-literal') return null
|
|
111
|
+
const entries: string[] = []
|
|
112
|
+
for (const prop of expr.properties) {
|
|
113
|
+
if (prop.shorthand) return null
|
|
114
|
+
const val = parsedLiteralToGo(ctx, prop.value)
|
|
115
|
+
if (val === null) return null
|
|
116
|
+
entries.push(`${JSON.stringify(prop.key)}: ${val}`)
|
|
117
|
+
}
|
|
118
|
+
if (entries.length === 0) return null
|
|
119
|
+
return `map[string]interface{}{${entries.join(', ')}}`
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Get a signal's initial value as Go code — a literal, or a props reference
|
|
124
|
+
* (`in.<Field>`, or the hoisted fallback var when `props.X ?? N` has one).
|
|
125
|
+
* Unrecognized values default to `0`.
|
|
126
|
+
*/
|
|
127
|
+
export function getSignalInitialValueAsGo(
|
|
128
|
+
ctx: GoEmitContext,
|
|
129
|
+
initialValue: string,
|
|
130
|
+
propsParams: { name: string }[],
|
|
131
|
+
propFallbackVars: ReadonlyMap<string, PropFallbackVar> = EMPTY_PROP_FALLBACK_VARS,
|
|
132
|
+
): string {
|
|
133
|
+
if (propsParams.some(p => p.name === initialValue)) {
|
|
134
|
+
const hoisted = propFallbackVars.get(initialValue)
|
|
135
|
+
if (hoisted) return hoisted.varName
|
|
136
|
+
return `in.${capitalizeFieldName(initialValue)}`
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const propName = ctx.extractPropNameFromInitialValue(initialValue)
|
|
140
|
+
if (propName && propsParams.some(p => p.name === propName)) {
|
|
141
|
+
const hoisted = propFallbackVars.get(propName)
|
|
142
|
+
if (hoisted) return hoisted.varName
|
|
143
|
+
return `in.${capitalizeFieldName(propName)}`
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// single quotes are normalized to Go double quotes
|
|
147
|
+
if (/^-?\d+$/.test(initialValue)) {
|
|
148
|
+
return initialValue
|
|
149
|
+
}
|
|
150
|
+
if (/^-?\d+\.\d+$/.test(initialValue)) {
|
|
151
|
+
return initialValue
|
|
152
|
+
}
|
|
153
|
+
if (initialValue === 'true' || initialValue === 'false') {
|
|
154
|
+
return initialValue
|
|
155
|
+
}
|
|
156
|
+
if ((initialValue.startsWith("'") && initialValue.endsWith("'")) ||
|
|
157
|
+
(initialValue.startsWith('"') && initialValue.endsWith('"'))) {
|
|
158
|
+
return initialValue.replace(/'/g, '"')
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return '0'
|
|
162
|
+
}
|
package/src/test-render.ts
CHANGED
|
@@ -9,19 +9,7 @@ import { compileJSX } from '@barefootjs/jsx'
|
|
|
9
9
|
import type { TemplateAdapter, ComponentIR } from '@barefootjs/jsx'
|
|
10
10
|
import { GoTemplateAdapter } from './adapter/go-template-adapter.ts'
|
|
11
11
|
import { deduplicateGoTypes } from './build.ts'
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Capitalize a JSON key to its Go struct field name using the same
|
|
15
|
-
* initialism rules as the adapter (`capitalizeFieldName`): a whole-word Go
|
|
16
|
-
* initialism uppercases entirely (`id` → `ID`), otherwise just the first
|
|
17
|
-
* letter. Keeps harness-emitted struct literals (`ItemInput{ID: …}`) matching
|
|
18
|
-
* the generated exported field names. (#1297)
|
|
19
|
-
*/
|
|
20
|
-
function capitalizeGoField(name: string): string {
|
|
21
|
-
if (!name) return name
|
|
22
|
-
if (GoTemplateAdapter.GO_INITIALISMS.has(name.toLowerCase())) return name.toUpperCase()
|
|
23
|
-
return name.charAt(0).toUpperCase() + name.slice(1)
|
|
24
|
-
}
|
|
12
|
+
import { capitalizeFieldName } from './adapter/lib/go-naming.ts'
|
|
25
13
|
import { mkdir, rm } from 'node:fs/promises'
|
|
26
14
|
import { resolve } from 'node:path'
|
|
27
15
|
|
|
@@ -703,7 +691,7 @@ function goTypedSliceLiteralFromArray(arr: unknown[], elemType: string): string
|
|
|
703
691
|
function goStructLiteral(obj: Record<string, unknown>, typeName: string): string {
|
|
704
692
|
const fields: string[] = []
|
|
705
693
|
for (const [k, v] of Object.entries(obj)) {
|
|
706
|
-
const goField =
|
|
694
|
+
const goField = capitalizeFieldName(k)
|
|
707
695
|
if (typeof v === 'string') fields.push(`${goField}: "${v.replace(/"/g, '\\"')}"`)
|
|
708
696
|
else if (typeof v === 'number' || typeof v === 'boolean') fields.push(`${goField}: ${v}`)
|
|
709
697
|
else if (v === null) fields.push(`${goField}: nil`)
|