@barefootjs/go-template 0.6.1 → 0.8.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/go-template-adapter.d.ts +122 -0
- package/dist/adapter/go-template-adapter.d.ts.map +1 -1
- package/dist/adapter/index.js +191 -3
- package/dist/build.js +191 -3
- package/dist/index.js +191 -3
- package/package.json +2 -2
- package/src/__tests__/go-template-adapter.test.ts +124 -10
- package/src/__tests__/slot-dynamic-tag.test.ts +79 -0
- package/src/adapter/go-template-adapter.ts +380 -3
- package/src/test-render.ts +33 -1
|
@@ -109,6 +109,34 @@ export declare class GoTemplateAdapter extends BaseAdapter implements ParsedExpr
|
|
|
109
109
|
/** Set during type generation when any emit references
|
|
110
110
|
* `template.HTML(...)`; toggles the `"html/template"` import. */
|
|
111
111
|
private usesHtmlTemplate;
|
|
112
|
+
/**
|
|
113
|
+
* Module-scope pure string-literal constants (`const X = 'literal'` at
|
|
114
|
+
* file top-level), keyed by name → resolved literal value. Populated at
|
|
115
|
+
* `generate()` entry from `ir.metadata.localConstants`. When an identifier
|
|
116
|
+
* in an expression resolves to one of these, the adapter inlines the
|
|
117
|
+
* literal value instead of emitting a struct-field reference
|
|
118
|
+
* (`{{.X}}`) — the field never exists on the Props struct, so without
|
|
119
|
+
* inlining Go's template engine fails with `can't evaluate field X`.
|
|
120
|
+
* Hono inlines it for free (it evaluates real JS); this restores parity.
|
|
121
|
+
* Only module-scope, pure string literals qualify — function-scope
|
|
122
|
+
* locals legitimately become template vars/props, and `Record<T,string>`
|
|
123
|
+
* indexed lookups / memos / signals are deliberately excluded.
|
|
124
|
+
*/
|
|
125
|
+
private moduleStringConsts;
|
|
126
|
+
/**
|
|
127
|
+
* Set of prop NAMES whose resolved Go struct-field type is exactly
|
|
128
|
+
* `interface{}` — i.e. nillable. Populated at `generate()` entry from
|
|
129
|
+
* the SAME per-prop Go-type computation `generatePropsStruct` /
|
|
130
|
+
* `generateInputStruct` use (`propTypeOverrides` + `typeInfoToGo`), so
|
|
131
|
+
* it can't drift from the actual field types. Used by
|
|
132
|
+
* `elementAttrEmitter.emitExpression` to omit a dynamic attribute whose
|
|
133
|
+
* value is a bare reference to a nillable prop when that prop is nil
|
|
134
|
+
* (Hono-style nullish-attribute omission: an `undefined`-valued
|
|
135
|
+
* attribute is dropped rather than rendered as `attr=""`). Concrete
|
|
136
|
+
* (`string`/`int`/`bool`) fields are never in this set and always emit
|
|
137
|
+
* unconditionally, matching Hono's `value=""` / `data-count="0"`.
|
|
138
|
+
*/
|
|
139
|
+
private nillablePropNames;
|
|
112
140
|
constructor(options?: GoTemplateAdapterOptions);
|
|
113
141
|
/**
|
|
114
142
|
* Generate template output for a component.
|
|
@@ -219,6 +247,24 @@ export declare class GoTemplateAdapter extends BaseAdapter implements ParsedExpr
|
|
|
219
247
|
* the signal's type annotation may be more specific than the prop's TypeInfo.
|
|
220
248
|
*/
|
|
221
249
|
private buildPropTypeOverrides;
|
|
250
|
+
/**
|
|
251
|
+
* Resolve a prop param's Go struct-field type using the SAME logic
|
|
252
|
+
* `generatePropsStruct` / `generateInputStruct` use for the field
|
|
253
|
+
* declaration: a `propTypeOverrides` entry (signal-inferred override)
|
|
254
|
+
* wins, otherwise `typeInfoToGo(param.type, param.defaultValue)`.
|
|
255
|
+
* Factored out so the nillable-field set (`collectNillablePropNames`)
|
|
256
|
+
* can't drift from the actual emitted field types.
|
|
257
|
+
*/
|
|
258
|
+
private resolvePropGoType;
|
|
259
|
+
/**
|
|
260
|
+
* Build the set of prop NAMES whose resolved Go field type is exactly
|
|
261
|
+
* `interface{}` (nillable). Uses the same `propTypeOverrides` +
|
|
262
|
+
* `resolvePropGoType` pipeline as the struct generators, so a prop
|
|
263
|
+
* that ends up `interface{}` on the Props struct — and only such a
|
|
264
|
+
* prop — is treated as nillable for Hono-style attribute omission.
|
|
265
|
+
* Concrete (`string`/`int`/`bool`/`[]T`/struct) types are excluded.
|
|
266
|
+
*/
|
|
267
|
+
private collectNillablePropNames;
|
|
222
268
|
/**
|
|
223
269
|
* Generate Input struct for a component
|
|
224
270
|
*/
|
|
@@ -340,6 +386,54 @@ export declare class GoTemplateAdapter extends BaseAdapter implements ParsedExpr
|
|
|
340
386
|
* narrowed BF101 with the offending expression.
|
|
341
387
|
*/
|
|
342
388
|
private buildSpreadInitializer;
|
|
389
|
+
/**
|
|
390
|
+
* Lower a conditional inline-object spread bag value:
|
|
391
|
+
* `(COND ? { 'aria-describedby': describedBy } : {})`
|
|
392
|
+
* into an immediately-invoked Go func literal that conditionally
|
|
393
|
+
* builds the map (so the falsy branch OMITS the key rather than
|
|
394
|
+
* rendering it as an empty string, which `SpreadAttrs` does not
|
|
395
|
+
* filter):
|
|
396
|
+
*
|
|
397
|
+
* func() map[string]any {
|
|
398
|
+
* if in.DescribedBy != nil && in.DescribedBy != "" {
|
|
399
|
+
* return map[string]any{"aria-describedby": in.DescribedBy}
|
|
400
|
+
* }
|
|
401
|
+
* return map[string]any{}
|
|
402
|
+
* }()
|
|
403
|
+
*
|
|
404
|
+
* Returns:
|
|
405
|
+
* - `undefined` when the expression is NOT a parenthesized ternary
|
|
406
|
+
* of object literals — the caller falls through to other shapes.
|
|
407
|
+
* - `null` when it IS that shape but a part can't be faithfully
|
|
408
|
+
* converted (non-static key, unsupported condition, …) — the
|
|
409
|
+
* caller raises BF101.
|
|
410
|
+
* - the Go IIFE string when fully convertible.
|
|
411
|
+
*/
|
|
412
|
+
private buildConditionalSpreadInitializer;
|
|
413
|
+
/** Strip redundant parenthesised wrappers off a TS expression. */
|
|
414
|
+
private unwrapParens;
|
|
415
|
+
/**
|
|
416
|
+
* Convert a conditional-spread condition expression to a Go bool in
|
|
417
|
+
* the `in.` context. Supports a bare prop identifier (`describedBy`)
|
|
418
|
+
* and its negation (`!describedBy`), type-aware on the prop:
|
|
419
|
+
* string → `in.X != ""`
|
|
420
|
+
* boolean → `in.X`
|
|
421
|
+
* number → `in.X != 0`
|
|
422
|
+
* unknown / interface{} → `in.X != nil && in.X != ""`
|
|
423
|
+
* (faithful JS string-truthiness for an interface holding a
|
|
424
|
+
* string — textarea's `describedBy` resolves to interface{}).
|
|
425
|
+
* Returns null for any other shape (caller → BF101).
|
|
426
|
+
*/
|
|
427
|
+
private conditionToGoBool;
|
|
428
|
+
/**
|
|
429
|
+
* Convert a static object literal (`{ 'aria-describedby': describedBy }`)
|
|
430
|
+
* into a Go `map[string]any{...}` literal for a conditional spread.
|
|
431
|
+
* Only static string/identifier keys are allowed; values resolve
|
|
432
|
+
* prop-identifier references to `in.FieldName` and string literals to
|
|
433
|
+
* Go string literals. Returns null for any computed/spread/dynamic
|
|
434
|
+
* key or unsupported value (caller → BF101). Empty object → `map[string]any{}`.
|
|
435
|
+
*/
|
|
436
|
+
private objectLiteralToGoSpreadMap;
|
|
343
437
|
/**
|
|
344
438
|
* Convert JavaScript initial value to Go value for NewXxxProps function.
|
|
345
439
|
* References to props params are converted to in.FieldName format.
|
|
@@ -554,6 +648,34 @@ export declare class GoTemplateAdapter extends BaseAdapter implements ParsedExpr
|
|
|
554
648
|
* rebinds. Outside any loop the root *is* the dot, so we emit `.Field` (#1677).
|
|
555
649
|
*/
|
|
556
650
|
private rootFieldRef;
|
|
651
|
+
/**
|
|
652
|
+
* Build the module pure-string-const map from the IR's localConstants.
|
|
653
|
+
* A const qualifies only when it is module-scope (`isModule`) and its
|
|
654
|
+
* initializer parses to a single string literal (`ts.StringLiteral` or
|
|
655
|
+
* `ts.NoSubstitutionTemplateLiteral` — a backtick string with no `${}`).
|
|
656
|
+
* Template literals *with* interpolations, numeric/object initializers,
|
|
657
|
+
* `Record<T,string>` maps, memos, and signals are all excluded: only a
|
|
658
|
+
* pure compile-time string can be safely inlined byte-for-byte.
|
|
659
|
+
*/
|
|
660
|
+
private collectModuleStringConsts;
|
|
661
|
+
/**
|
|
662
|
+
* Parse a const initializer's source text. Returns the unescaped string
|
|
663
|
+
* value when the whole initializer is a single string literal (or a
|
|
664
|
+
* no-substitution template literal), else `null`. Uses the TS parser so
|
|
665
|
+
* escapes/quotes are resolved exactly as JS would, matching the value
|
|
666
|
+
* the Hono reference inlines at runtime.
|
|
667
|
+
*/
|
|
668
|
+
private parsePureStringLiteral;
|
|
669
|
+
/**
|
|
670
|
+
* Resolve an identifier to its inlined Go string literal when it names a
|
|
671
|
+
* module pure-string const. Returns the Go template literal form
|
|
672
|
+
* (`"<escaped>"`) so callers can drop it straight into a `{{...}}` action,
|
|
673
|
+
* or `null` when the name is not such a const (the caller then falls back
|
|
674
|
+
* to its normal field-ref lowering). The value is escaped for a Go
|
|
675
|
+
* double-quoted string literal — Go's `html/template` then applies the
|
|
676
|
+
* same contextual auto-escaping it applies to any literal, matching Hono.
|
|
677
|
+
*/
|
|
678
|
+
private resolveModuleStringConst;
|
|
557
679
|
literal(value: string | number | boolean | null, literalType: LiteralType): string;
|
|
558
680
|
call(callee: ParsedExpr, args: ParsedExpr[], emit: (e: ParsedExpr) => string): string;
|
|
559
681
|
member(object: ParsedExpr, property: string, _computed: boolean, emit: (e: ParsedExpr) => string): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"go-template-adapter.d.ts","sourceRoot":"","sources":["../../src/adapter/go-template-adapter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EACV,WAAW,EACX,MAAM,EACN,SAAS,EACT,MAAM,EACN,YAAY,EACZ,aAAa,EACb,MAAM,EAEN,WAAW,EACX,UAAU,EACV,MAAM,EAON,UAAU,EAEV,cAAc,EACd,QAAQ,EACR,SAAS,EACT,SAAS,EACT,YAAY,EACZ,aAAa,EACb,UAAU,EACV,OAAO,
|
|
1
|
+
{"version":3,"file":"go-template-adapter.d.ts","sourceRoot":"","sources":["../../src/adapter/go-template-adapter.ts"],"names":[],"mappings":"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"}
|
package/dist/adapter/index.js
CHANGED
|
@@ -117,6 +117,8 @@ class GoTemplateAdapter extends BaseAdapter {
|
|
|
117
117
|
localStructFields = new Map;
|
|
118
118
|
synthStructTypes = new Map;
|
|
119
119
|
usesHtmlTemplate = false;
|
|
120
|
+
moduleStringConsts = new Map;
|
|
121
|
+
nillablePropNames = new Set;
|
|
120
122
|
constructor(options = {}) {
|
|
121
123
|
super();
|
|
122
124
|
this.options = {
|
|
@@ -131,6 +133,8 @@ class GoTemplateAdapter extends BaseAdapter {
|
|
|
131
133
|
this.templateVarCounter = 0;
|
|
132
134
|
this.propsObjectName = ir.metadata.propsObjectName;
|
|
133
135
|
this.restPropsName = ir.metadata.restPropsName ?? null;
|
|
136
|
+
this.moduleStringConsts = this.collectModuleStringConsts(ir.metadata.localConstants);
|
|
137
|
+
this.nillablePropNames = this.collectNillablePropNames(ir);
|
|
134
138
|
if (!options?.siblingTemplatesRegistered) {
|
|
135
139
|
this.checkImportedLoopChildComponents(ir);
|
|
136
140
|
}
|
|
@@ -566,6 +570,19 @@ ${goFields.join(`
|
|
|
566
570
|
}
|
|
567
571
|
return overrides;
|
|
568
572
|
}
|
|
573
|
+
resolvePropGoType(param, propTypeOverrides) {
|
|
574
|
+
return propTypeOverrides.get(param.name) ?? this.typeInfoToGo(param.type, param.defaultValue);
|
|
575
|
+
}
|
|
576
|
+
collectNillablePropNames(ir) {
|
|
577
|
+
const propTypeOverrides = this.buildPropTypeOverrides(ir);
|
|
578
|
+
const nillable = new Set;
|
|
579
|
+
for (const param of ir.metadata.propsParams) {
|
|
580
|
+
if (this.resolvePropGoType(param, propTypeOverrides) === "interface{}") {
|
|
581
|
+
nillable.add(param.name);
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
return nillable;
|
|
585
|
+
}
|
|
569
586
|
generateInputStruct(lines, ir, componentName, nestedComponents, propTypeOverrides, spreadSlots) {
|
|
570
587
|
const inputTypeName = `${componentName}Input`;
|
|
571
588
|
lines.push(`// ${inputTypeName} is the user-facing input type.`);
|
|
@@ -579,7 +596,7 @@ ${goFields.join(`
|
|
|
579
596
|
const fieldName = this.capitalizeFieldName(param.name);
|
|
580
597
|
if (nestedArrayFields.has(fieldName))
|
|
581
598
|
continue;
|
|
582
|
-
const goType =
|
|
599
|
+
const goType = this.resolvePropGoType(param, propTypeOverrides);
|
|
583
600
|
lines.push(` ${fieldName} ${goType}`);
|
|
584
601
|
}
|
|
585
602
|
for (const nested of inputNested) {
|
|
@@ -618,7 +635,7 @@ ${goFields.join(`
|
|
|
618
635
|
const fieldName = this.capitalizeFieldName(param.name);
|
|
619
636
|
if (nestedArrayFields.has(fieldName))
|
|
620
637
|
continue;
|
|
621
|
-
const goType =
|
|
638
|
+
const goType = this.resolvePropGoType(param, propTypeOverrides);
|
|
622
639
|
const jsonTag = this.toJsonTag(param.name);
|
|
623
640
|
lines.push(` ${fieldName} ${goType} \`json:"${jsonTag}"\``);
|
|
624
641
|
propFieldNames.add(fieldName);
|
|
@@ -912,6 +929,12 @@ ${goFields.join(`
|
|
|
912
929
|
collectStaticChildInstancesRecursive(node, result, inLoop) {
|
|
913
930
|
if (node.type === "component") {
|
|
914
931
|
const comp = node;
|
|
932
|
+
if (comp.dynamicTag) {
|
|
933
|
+
for (const child of comp.children) {
|
|
934
|
+
this.collectStaticChildInstancesRecursive(child, result, inLoop);
|
|
935
|
+
}
|
|
936
|
+
return;
|
|
937
|
+
}
|
|
915
938
|
if (comp.name !== "Portal" && !inLoop && comp.slotId) {
|
|
916
939
|
const suffix = slotIdToFieldSuffix(comp.slotId);
|
|
917
940
|
result.push({
|
|
@@ -1086,6 +1109,9 @@ ${goFields.join(`
|
|
|
1086
1109
|
}
|
|
1087
1110
|
buildSpreadInitializer(spreadExpr, ir) {
|
|
1088
1111
|
const trimmed = spreadExpr.trim();
|
|
1112
|
+
const conditional = this.buildConditionalSpreadInitializer(trimmed, ir);
|
|
1113
|
+
if (conditional !== undefined)
|
|
1114
|
+
return conditional;
|
|
1089
1115
|
const callMatch = /^([a-zA-Z_][a-zA-Z0-9_]*)\s*\(\s*\)$/.exec(trimmed);
|
|
1090
1116
|
if (callMatch) {
|
|
1091
1117
|
const getterName = callMatch[1];
|
|
@@ -1112,6 +1138,98 @@ ${goFields.join(`
|
|
|
1112
1138
|
}
|
|
1113
1139
|
return null;
|
|
1114
1140
|
}
|
|
1141
|
+
buildConditionalSpreadInitializer(spreadExpr, ir) {
|
|
1142
|
+
const expr = this.parseLiteralExpression(spreadExpr);
|
|
1143
|
+
if (!expr || !ts.isConditionalExpression(expr))
|
|
1144
|
+
return;
|
|
1145
|
+
const whenTrue = this.unwrapParens(expr.whenTrue);
|
|
1146
|
+
const whenFalse = this.unwrapParens(expr.whenFalse);
|
|
1147
|
+
if (!ts.isObjectLiteralExpression(whenTrue) || !ts.isObjectLiteralExpression(whenFalse)) {
|
|
1148
|
+
return;
|
|
1149
|
+
}
|
|
1150
|
+
const goCond = this.conditionToGoBool(expr.condition, ir);
|
|
1151
|
+
if (goCond === null)
|
|
1152
|
+
return null;
|
|
1153
|
+
const trueMap = this.objectLiteralToGoSpreadMap(whenTrue, ir);
|
|
1154
|
+
const falseMap = this.objectLiteralToGoSpreadMap(whenFalse, ir);
|
|
1155
|
+
if (trueMap === null || falseMap === null)
|
|
1156
|
+
return null;
|
|
1157
|
+
return `func() map[string]any {
|
|
1158
|
+
` + ` if ${goCond} {
|
|
1159
|
+
` + ` return ${trueMap}
|
|
1160
|
+
` + ` }
|
|
1161
|
+
` + ` return ${falseMap}
|
|
1162
|
+
` + ` }()`;
|
|
1163
|
+
}
|
|
1164
|
+
unwrapParens(node) {
|
|
1165
|
+
let e = node;
|
|
1166
|
+
while (ts.isParenthesizedExpression(e))
|
|
1167
|
+
e = e.expression;
|
|
1168
|
+
return e;
|
|
1169
|
+
}
|
|
1170
|
+
conditionToGoBool(condition, ir) {
|
|
1171
|
+
let node = this.unwrapParens(condition);
|
|
1172
|
+
let negate = false;
|
|
1173
|
+
if (ts.isPrefixUnaryExpression(node) && node.operator === ts.SyntaxKind.ExclamationToken) {
|
|
1174
|
+
negate = true;
|
|
1175
|
+
node = this.unwrapParens(node.operand);
|
|
1176
|
+
}
|
|
1177
|
+
if (!ts.isIdentifier(node))
|
|
1178
|
+
return null;
|
|
1179
|
+
const param = ir.metadata.propsParams.find((p) => p.name === node.text);
|
|
1180
|
+
if (!param)
|
|
1181
|
+
return null;
|
|
1182
|
+
const field = `in.${this.capitalizeFieldName(param.name)}`;
|
|
1183
|
+
const prim = param.type.kind === "primitive" ? param.type.primitive : undefined;
|
|
1184
|
+
let truthy;
|
|
1185
|
+
if (prim === "boolean") {
|
|
1186
|
+
truthy = field;
|
|
1187
|
+
} else if (prim === "number") {
|
|
1188
|
+
truthy = `${field} != 0`;
|
|
1189
|
+
} else if (prim === "string") {
|
|
1190
|
+
truthy = `${field} != ""`;
|
|
1191
|
+
} else {
|
|
1192
|
+
truthy = `bf.Truthy(${field})`;
|
|
1193
|
+
}
|
|
1194
|
+
if (!negate)
|
|
1195
|
+
return truthy;
|
|
1196
|
+
if (prim === "boolean")
|
|
1197
|
+
return `!${field}`;
|
|
1198
|
+
if (prim === "number")
|
|
1199
|
+
return `${field} == 0`;
|
|
1200
|
+
if (prim === "string")
|
|
1201
|
+
return `${field} == ""`;
|
|
1202
|
+
return `!bf.Truthy(${field})`;
|
|
1203
|
+
}
|
|
1204
|
+
objectLiteralToGoSpreadMap(obj, ir) {
|
|
1205
|
+
const entries = [];
|
|
1206
|
+
for (const prop of obj.properties) {
|
|
1207
|
+
if (!ts.isPropertyAssignment(prop))
|
|
1208
|
+
return null;
|
|
1209
|
+
let key;
|
|
1210
|
+
if (ts.isIdentifier(prop.name)) {
|
|
1211
|
+
key = prop.name.text;
|
|
1212
|
+
} else if (ts.isStringLiteral(prop.name) || ts.isNoSubstitutionTemplateLiteral(prop.name)) {
|
|
1213
|
+
key = prop.name.text;
|
|
1214
|
+
} else {
|
|
1215
|
+
return null;
|
|
1216
|
+
}
|
|
1217
|
+
const val = this.unwrapParens(prop.initializer);
|
|
1218
|
+
let goVal;
|
|
1219
|
+
if (ts.isStringLiteral(val) || ts.isNoSubstitutionTemplateLiteral(val)) {
|
|
1220
|
+
goVal = JSON.stringify(val.text);
|
|
1221
|
+
} else if (ts.isIdentifier(val)) {
|
|
1222
|
+
const param = ir.metadata.propsParams.find((p) => p.name === val.text);
|
|
1223
|
+
if (!param)
|
|
1224
|
+
return null;
|
|
1225
|
+
goVal = `in.${this.capitalizeFieldName(param.name)}`;
|
|
1226
|
+
} else {
|
|
1227
|
+
return null;
|
|
1228
|
+
}
|
|
1229
|
+
entries.push(`${JSON.stringify(key)}: ${goVal}`);
|
|
1230
|
+
}
|
|
1231
|
+
return `map[string]any{${entries.join(", ")}}`;
|
|
1232
|
+
}
|
|
1115
1233
|
convertInitialValue(value, typeInfo, propsParams) {
|
|
1116
1234
|
if (/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(value)) {
|
|
1117
1235
|
if (propsParams?.some((p) => p.name === value)) {
|
|
@@ -1748,6 +1866,9 @@ ${goFields.join(`
|
|
|
1748
1866
|
return emitParsedExpr(expr, this);
|
|
1749
1867
|
}
|
|
1750
1868
|
identifier(name) {
|
|
1869
|
+
const inlined = this.resolveModuleStringConst(name);
|
|
1870
|
+
if (inlined !== null)
|
|
1871
|
+
return inlined;
|
|
1751
1872
|
const currentLoopParam = this.loopParamStack[this.loopParamStack.length - 1];
|
|
1752
1873
|
if (currentLoopParam && name === currentLoopParam)
|
|
1753
1874
|
return ".";
|
|
@@ -1769,6 +1890,48 @@ ${goFields.join(`
|
|
|
1769
1890
|
const prefix = this.loopParamStack.length > 0 ? "$." : ".";
|
|
1770
1891
|
return `${prefix}${this.capitalizeFieldName(name)}`;
|
|
1771
1892
|
}
|
|
1893
|
+
collectModuleStringConsts(constants) {
|
|
1894
|
+
const map = new Map;
|
|
1895
|
+
for (const c of constants ?? []) {
|
|
1896
|
+
if (!c.isModule)
|
|
1897
|
+
continue;
|
|
1898
|
+
if (c.value === undefined)
|
|
1899
|
+
continue;
|
|
1900
|
+
const literal = this.parsePureStringLiteral(c.value);
|
|
1901
|
+
if (literal !== null)
|
|
1902
|
+
map.set(c.name, literal);
|
|
1903
|
+
}
|
|
1904
|
+
return map;
|
|
1905
|
+
}
|
|
1906
|
+
parsePureStringLiteral(source) {
|
|
1907
|
+
const sf = ts.createSourceFile("__const.ts", `const __x = (${source});`, ts.ScriptTarget.Latest, false);
|
|
1908
|
+
const stmt = sf.statements[0];
|
|
1909
|
+
if (!stmt || !ts.isVariableStatement(stmt))
|
|
1910
|
+
return null;
|
|
1911
|
+
const decl = stmt.declarationList.declarations[0];
|
|
1912
|
+
let init = decl?.initializer;
|
|
1913
|
+
while (init && ts.isParenthesizedExpression(init))
|
|
1914
|
+
init = init.expression;
|
|
1915
|
+
if (!init)
|
|
1916
|
+
return null;
|
|
1917
|
+
if (ts.isStringLiteral(init) || ts.isNoSubstitutionTemplateLiteral(init)) {
|
|
1918
|
+
return init.text;
|
|
1919
|
+
}
|
|
1920
|
+
return null;
|
|
1921
|
+
}
|
|
1922
|
+
resolveModuleStringConst(name) {
|
|
1923
|
+
if (this.loopParamStack.length > 0 && this.loopParamStack[this.loopParamStack.length - 1] === name) {
|
|
1924
|
+
return null;
|
|
1925
|
+
}
|
|
1926
|
+
if (this.loopVarRefCount.has(name))
|
|
1927
|
+
return null;
|
|
1928
|
+
if (this.isOuterLoopParam(name))
|
|
1929
|
+
return null;
|
|
1930
|
+
const value = this.moduleStringConsts.get(name);
|
|
1931
|
+
if (value === undefined)
|
|
1932
|
+
return null;
|
|
1933
|
+
return `"${this.escapeGoString(value)}"`;
|
|
1934
|
+
}
|
|
1772
1935
|
literal(value, literalType) {
|
|
1773
1936
|
if (literalType === "string")
|
|
1774
1937
|
return `"${value}"`;
|
|
@@ -2609,6 +2772,9 @@ ${goFields.join(`
|
|
|
2609
2772
|
switch (expr.kind) {
|
|
2610
2773
|
case "identifier":
|
|
2611
2774
|
{
|
|
2775
|
+
const inlined = this.resolveModuleStringConst(expr.name);
|
|
2776
|
+
if (inlined !== null)
|
|
2777
|
+
return plain(inlined);
|
|
2612
2778
|
const currentLoopParam = this.loopParamStack[this.loopParamStack.length - 1];
|
|
2613
2779
|
if (currentLoopParam && expr.name === currentLoopParam) {
|
|
2614
2780
|
return plain(".");
|
|
@@ -2631,6 +2797,20 @@ ${goFields.join(`
|
|
|
2631
2797
|
if (expr.callee.kind === "identifier" && expr.args.length === 0) {
|
|
2632
2798
|
return plain(this.rootFieldRef(expr.callee.name));
|
|
2633
2799
|
}
|
|
2800
|
+
if (expr.callee.kind === "identifier" && (identifierPath(expr.callee) ?? expr.callee.name) === "isValidElement" && expr.args.length === 1) {
|
|
2801
|
+
return this.renderConditionExpr(expr.args[0]);
|
|
2802
|
+
}
|
|
2803
|
+
if (expr.callee.kind === "identifier" && !this.templatePrimitives[identifierPath(expr.callee) ?? ""]) {
|
|
2804
|
+
const path = identifierPath(expr.callee) ?? expr.callee.name;
|
|
2805
|
+
this.errors.push({
|
|
2806
|
+
code: "BF102",
|
|
2807
|
+
severity: "error",
|
|
2808
|
+
message: `Predicate '${path}(...)' cannot be evaluated in a Go template. ` + `A server-side template cannot call user-defined JavaScript predicates.`,
|
|
2809
|
+
loc: this.makeLoc(),
|
|
2810
|
+
suggestion: { message: GO_REMEDIATION_OPTIONS }
|
|
2811
|
+
});
|
|
2812
|
+
return plain("false");
|
|
2813
|
+
}
|
|
2634
2814
|
return plain(this.renderParsedExpr(expr));
|
|
2635
2815
|
}
|
|
2636
2816
|
case "member": {
|
|
@@ -2842,6 +3022,9 @@ ${goFields.join(`
|
|
|
2842
3022
|
if (comp.name === "Portal") {
|
|
2843
3023
|
return this.renderPortalComponent(comp);
|
|
2844
3024
|
}
|
|
3025
|
+
if (comp.dynamicTag) {
|
|
3026
|
+
return this.renderChildren(comp.children);
|
|
3027
|
+
}
|
|
2845
3028
|
let templateCall;
|
|
2846
3029
|
if (this.inLoop) {
|
|
2847
3030
|
templateCall = `{{template "${comp.name}" .}}`;
|
|
@@ -2895,6 +3078,11 @@ ${children}`;
|
|
|
2895
3078
|
if (parsed.kind === "conditional" || parsed.kind === "template-literal") {
|
|
2896
3079
|
return `${name}="${this.renderParsedExpr(parsed)}"`;
|
|
2897
3080
|
}
|
|
3081
|
+
const bareId = value.expr.trim();
|
|
3082
|
+
if (this.nillablePropNames.has(bareId)) {
|
|
3083
|
+
const field = `.${this.capitalizeFieldName(bareId)}`;
|
|
3084
|
+
return `{{if ne ${field} nil}}${name}="{{${this.convertExpressionToGo(value.expr)}}}"{{end}}`;
|
|
3085
|
+
}
|
|
2898
3086
|
return `${name}="{{${this.convertExpressionToGo(value.expr)}}}"`;
|
|
2899
3087
|
},
|
|
2900
3088
|
emitBooleanAttr: (_value, name) => name,
|
|
@@ -2985,7 +3173,7 @@ ${children}`;
|
|
|
2985
3173
|
continue;
|
|
2986
3174
|
const branches = caseEntries.map(([k, v], i) => {
|
|
2987
3175
|
const head = i === 0 ? "{{if" : "{{else if";
|
|
2988
|
-
return `${head} eq ${keyExpr} ${JSON.stringify(k)}}}${v}`;
|
|
3176
|
+
return `${head} eq ${keyExpr} ${JSON.stringify(k)}}}${this.escapeAttrText(v)}`;
|
|
2989
3177
|
});
|
|
2990
3178
|
output += branches.join("") + "{{end}}";
|
|
2991
3179
|
}
|