@barefootjs/go-template 0.6.0 → 0.6.1
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 +5 -2
- package/dist/adapter/go-template-adapter.d.ts.map +1 -1
- package/dist/adapter/index.js +49 -19
- package/dist/build.js +49 -19
- package/dist/index.js +49 -19
- package/package.json +2 -2
- package/src/__tests__/go-template-adapter.test.ts +117 -4
- package/src/adapter/go-template-adapter.ts +121 -10
- package/src/test-render.ts +8 -1
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Generates Go html/template files from BarefootJS IR.
|
|
5
5
|
*/
|
|
6
|
-
import type { ComponentIR, IRNode, IRElement, IRText, IRExpression, IRConditional, IRLoop, IRComponent, IRFragment, IRSlot, ParsedExpr, SortComparator, TemplatePart, IRIfStatement, IRProvider, IRAsync, TemplatePrimitiveRegistry } from '@barefootjs/jsx';
|
|
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
7
|
import { BaseAdapter, type AdapterOutput, type AdapterGenerateOptions, type ParsedExprEmitter, type HigherOrderMethod, type ArrayMethod, type LiteralType, type IRNodeEmitter, type EmitIRNode } from '@barefootjs/jsx';
|
|
8
8
|
/**
|
|
9
9
|
* Go-template adapter's IRNode render context. Only `isRootOfClientComponent`
|
|
@@ -469,7 +469,7 @@ export declare class GoTemplateAdapter extends BaseAdapter implements ParsedExpr
|
|
|
469
469
|
*/
|
|
470
470
|
private static GO_IDENTIFIER;
|
|
471
471
|
/** Go common initialisms that should be fully uppercased (https://go.dev/wiki/CodeReviewComments#initialisms) */
|
|
472
|
-
|
|
472
|
+
static GO_INITIALISMS: Set<string>;
|
|
473
473
|
/**
|
|
474
474
|
* (#1423) Go reserved keywords. When we hoist a local var named after
|
|
475
475
|
* a JSX prop, the prop name could collide with one of these — append
|
|
@@ -567,6 +567,9 @@ export declare class GoTemplateAdapter extends BaseAdapter implements ParsedExpr
|
|
|
567
567
|
higherOrder(method: HigherOrderMethod, object: ParsedExpr, param: string, predicate: ParsedExpr, emit: (e: ParsedExpr) => string): string;
|
|
568
568
|
arrayMethod(method: ArrayMethod, object: ParsedExpr, args: ParsedExpr[], emit: (e: ParsedExpr) => string): string;
|
|
569
569
|
sortMethod(method: 'sort' | 'toSorted', object: ParsedExpr, comparator: SortComparator, emit: (e: ParsedExpr) => string): string;
|
|
570
|
+
reduceMethod(method: 'reduce' | 'reduceRight', object: ParsedExpr, reduceOp: ReduceOp, emit: (e: ParsedExpr) => string): string;
|
|
571
|
+
flatMethod(object: ParsedExpr, depth: FlatDepth, emit: (e: ParsedExpr) => string): string;
|
|
572
|
+
flatMapMethod(object: ParsedExpr, op: FlatMapOp, emit: (e: ParsedExpr) => string): string;
|
|
570
573
|
unsupported(raw: string, _reason: string): string;
|
|
571
574
|
/**
|
|
572
575
|
* Extract field name and negation from a simple predicate.
|
|
@@ -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,YAAY,EACZ,aAAa,EACb,UAAU,EACV,OAAO,EACP,yBAAyB,EAC1B,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACL,WAAW,EACX,KAAK,aAAa,EAClB,KAAK,sBAAsB,EAE3B,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,UAAU,
|
|
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
|
@@ -51,8 +51,20 @@ function emitBfSort(recv, c) {
|
|
|
51
51
|
});
|
|
52
52
|
return `bf_sort ${wrapIfMultiToken(recv)} ${groups.join(" ")}`;
|
|
53
53
|
}
|
|
54
|
+
function emitBfReduce(recv, op, direction) {
|
|
55
|
+
const keyName = op.key.kind === "field" ? capitalize(op.key.field) : "";
|
|
56
|
+
return `bf_reduce ${wrapIfMultiToken(recv)} "${op.op}" "${op.key.kind}" "${keyName}" "${op.type}" "${escapeGoString(op.init)}" "${direction}"`;
|
|
57
|
+
}
|
|
58
|
+
function escapeGoString(s) {
|
|
59
|
+
return s.replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
|
|
60
|
+
}
|
|
54
61
|
function capitalize(s) {
|
|
55
|
-
|
|
62
|
+
if (s.length === 0)
|
|
63
|
+
return s;
|
|
64
|
+
if (GoTemplateAdapter.GO_INITIALISMS.has(s.toLowerCase())) {
|
|
65
|
+
return s.toUpperCase();
|
|
66
|
+
}
|
|
67
|
+
return s[0].toUpperCase() + s.slice(1);
|
|
56
68
|
}
|
|
57
69
|
function slotIdToFieldSuffix(slotId) {
|
|
58
70
|
const cleanId = slotId.startsWith("^") ? slotId.slice(1) : slotId;
|
|
@@ -62,6 +74,18 @@ function slotIdToFieldSuffix(slotId) {
|
|
|
62
74
|
}
|
|
63
75
|
return cleanId.replace("slot_", "Slot");
|
|
64
76
|
}
|
|
77
|
+
var GO_REMEDIATION_OPTIONS = `Options:
|
|
78
|
+
1. Use @client directive for client-side evaluation
|
|
79
|
+
2. Pre-compute the value in Go code`;
|
|
80
|
+
function buildUnsupportedSuggestion(support) {
|
|
81
|
+
if (!support.reason)
|
|
82
|
+
return GO_REMEDIATION_OPTIONS;
|
|
83
|
+
if (support.selfContained)
|
|
84
|
+
return support.reason;
|
|
85
|
+
return `${support.reason}
|
|
86
|
+
|
|
87
|
+
${GO_REMEDIATION_OPTIONS}`;
|
|
88
|
+
}
|
|
65
89
|
var GO_TEMPLATE_PRIMITIVES = {
|
|
66
90
|
"JSON.stringify": { arity: 1, emit: (args) => `bf_json ${args[0]}` },
|
|
67
91
|
String: { arity: 1, emit: (args) => `bf_string ${args[0]}` },
|
|
@@ -1905,9 +1929,7 @@ ${goFields.join(`
|
|
|
1905
1929
|
message: `Higher-order method '.${method}' shape cannot be lowered to a Go template action`,
|
|
1906
1930
|
loc: this.makeLoc(),
|
|
1907
1931
|
suggestion: {
|
|
1908
|
-
message:
|
|
1909
|
-
1. Use @client directive for client-side evaluation
|
|
1910
|
-
2. Pre-compute the value in Go code`
|
|
1932
|
+
message: GO_REMEDIATION_OPTIONS
|
|
1911
1933
|
}
|
|
1912
1934
|
});
|
|
1913
1935
|
return `""`;
|
|
@@ -2027,6 +2049,26 @@ ${goFields.join(`
|
|
|
2027
2049
|
sortMethod(method, object, comparator, emit) {
|
|
2028
2050
|
return emitBfSort(emit(object), comparator);
|
|
2029
2051
|
}
|
|
2052
|
+
reduceMethod(method, object, reduceOp, emit) {
|
|
2053
|
+
const direction = method === "reduceRight" ? "right" : "left";
|
|
2054
|
+
return emitBfReduce(emit(object), reduceOp, direction);
|
|
2055
|
+
}
|
|
2056
|
+
flatMethod(object, depth, emit) {
|
|
2057
|
+
const d = depth === "infinity" ? -1 : depth;
|
|
2058
|
+
return `bf_flat ${wrapIfMultiToken(emit(object))} ${d}`;
|
|
2059
|
+
}
|
|
2060
|
+
flatMapMethod(object, op, emit) {
|
|
2061
|
+
const recv = wrapIfMultiToken(emit(object));
|
|
2062
|
+
const proj = op.projection;
|
|
2063
|
+
if (proj.kind === "tuple") {
|
|
2064
|
+
const pairs = proj.elements.map((l) => l.kind === "self" ? `"self" ""` : `"field" "${capitalize(l.field)}"`).join(" ");
|
|
2065
|
+
return `bf_flat_map_tuple ${recv} ${pairs}`;
|
|
2066
|
+
}
|
|
2067
|
+
if (proj.kind === "self") {
|
|
2068
|
+
return `bf_flat_map ${recv} "self" ""`;
|
|
2069
|
+
}
|
|
2070
|
+
return `bf_flat_map ${recv} "field" "${capitalize(proj.field)}"`;
|
|
2071
|
+
}
|
|
2030
2072
|
unsupported(raw, _reason) {
|
|
2031
2073
|
return `[UNSUPPORTED: ${raw}]`;
|
|
2032
2074
|
}
|
|
@@ -2449,13 +2491,7 @@ ${goFields.join(`
|
|
|
2449
2491
|
message: `Expression not supported: ${trimmed}`,
|
|
2450
2492
|
loc: this.makeLoc(),
|
|
2451
2493
|
suggestion: {
|
|
2452
|
-
message: support
|
|
2453
|
-
|
|
2454
|
-
Options:
|
|
2455
|
-
1. Use @client directive for client-side evaluation
|
|
2456
|
-
2. Pre-compute the value in Go code` : `Options:
|
|
2457
|
-
1. Use @client directive for client-side evaluation
|
|
2458
|
-
2. Pre-compute the value in Go code`
|
|
2494
|
+
message: buildUnsupportedSuggestion(support)
|
|
2459
2495
|
}
|
|
2460
2496
|
});
|
|
2461
2497
|
return `""`;
|
|
@@ -2484,9 +2520,7 @@ Options:
|
|
|
2484
2520
|
message: `Complex predicate in else-if is not supported: ${altIfStmt.condition}`,
|
|
2485
2521
|
loc: this.makeLoc(),
|
|
2486
2522
|
suggestion: {
|
|
2487
|
-
message:
|
|
2488
|
-
1. Use @client directive for client-side evaluation
|
|
2489
|
-
2. Pre-compute the value in Go code`
|
|
2523
|
+
message: GO_REMEDIATION_OPTIONS
|
|
2490
2524
|
}
|
|
2491
2525
|
});
|
|
2492
2526
|
}
|
|
@@ -2562,11 +2596,7 @@ Options:
|
|
|
2562
2596
|
message: `Condition not supported: ${trimmed}`,
|
|
2563
2597
|
loc: this.makeLoc(),
|
|
2564
2598
|
suggestion: {
|
|
2565
|
-
message: support
|
|
2566
|
-
|
|
2567
|
-
Options:
|
|
2568
|
-
1. Use @client directive for client-side evaluation
|
|
2569
|
-
2. Pre-compute the value in Go code` : "Expression contains unsupported syntax"
|
|
2599
|
+
message: buildUnsupportedSuggestion(support)
|
|
2570
2600
|
}
|
|
2571
2601
|
});
|
|
2572
2602
|
return { condition: `false`, preamble: "" };
|
package/dist/build.js
CHANGED
|
@@ -391,8 +391,20 @@ function emitBfSort(recv, c) {
|
|
|
391
391
|
});
|
|
392
392
|
return `bf_sort ${wrapIfMultiToken(recv)} ${groups.join(" ")}`;
|
|
393
393
|
}
|
|
394
|
+
function emitBfReduce(recv, op, direction) {
|
|
395
|
+
const keyName = op.key.kind === "field" ? capitalize(op.key.field) : "";
|
|
396
|
+
return `bf_reduce ${wrapIfMultiToken(recv)} "${op.op}" "${op.key.kind}" "${keyName}" "${op.type}" "${escapeGoString(op.init)}" "${direction}"`;
|
|
397
|
+
}
|
|
398
|
+
function escapeGoString(s) {
|
|
399
|
+
return s.replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
|
|
400
|
+
}
|
|
394
401
|
function capitalize(s) {
|
|
395
|
-
|
|
402
|
+
if (s.length === 0)
|
|
403
|
+
return s;
|
|
404
|
+
if (GoTemplateAdapter.GO_INITIALISMS.has(s.toLowerCase())) {
|
|
405
|
+
return s.toUpperCase();
|
|
406
|
+
}
|
|
407
|
+
return s[0].toUpperCase() + s.slice(1);
|
|
396
408
|
}
|
|
397
409
|
function slotIdToFieldSuffix(slotId) {
|
|
398
410
|
const cleanId = slotId.startsWith("^") ? slotId.slice(1) : slotId;
|
|
@@ -402,6 +414,18 @@ function slotIdToFieldSuffix(slotId) {
|
|
|
402
414
|
}
|
|
403
415
|
return cleanId.replace("slot_", "Slot");
|
|
404
416
|
}
|
|
417
|
+
var GO_REMEDIATION_OPTIONS = `Options:
|
|
418
|
+
1. Use @client directive for client-side evaluation
|
|
419
|
+
2. Pre-compute the value in Go code`;
|
|
420
|
+
function buildUnsupportedSuggestion(support) {
|
|
421
|
+
if (!support.reason)
|
|
422
|
+
return GO_REMEDIATION_OPTIONS;
|
|
423
|
+
if (support.selfContained)
|
|
424
|
+
return support.reason;
|
|
425
|
+
return `${support.reason}
|
|
426
|
+
|
|
427
|
+
${GO_REMEDIATION_OPTIONS}`;
|
|
428
|
+
}
|
|
405
429
|
var GO_TEMPLATE_PRIMITIVES = {
|
|
406
430
|
"JSON.stringify": { arity: 1, emit: (args) => `bf_json ${args[0]}` },
|
|
407
431
|
String: { arity: 1, emit: (args) => `bf_string ${args[0]}` },
|
|
@@ -2245,9 +2269,7 @@ ${goFields.join(`
|
|
|
2245
2269
|
message: `Higher-order method '.${method}' shape cannot be lowered to a Go template action`,
|
|
2246
2270
|
loc: this.makeLoc(),
|
|
2247
2271
|
suggestion: {
|
|
2248
|
-
message:
|
|
2249
|
-
1. Use @client directive for client-side evaluation
|
|
2250
|
-
2. Pre-compute the value in Go code`
|
|
2272
|
+
message: GO_REMEDIATION_OPTIONS
|
|
2251
2273
|
}
|
|
2252
2274
|
});
|
|
2253
2275
|
return `""`;
|
|
@@ -2367,6 +2389,26 @@ ${goFields.join(`
|
|
|
2367
2389
|
sortMethod(method, object, comparator, emit) {
|
|
2368
2390
|
return emitBfSort(emit(object), comparator);
|
|
2369
2391
|
}
|
|
2392
|
+
reduceMethod(method, object, reduceOp, emit) {
|
|
2393
|
+
const direction = method === "reduceRight" ? "right" : "left";
|
|
2394
|
+
return emitBfReduce(emit(object), reduceOp, direction);
|
|
2395
|
+
}
|
|
2396
|
+
flatMethod(object, depth, emit) {
|
|
2397
|
+
const d = depth === "infinity" ? -1 : depth;
|
|
2398
|
+
return `bf_flat ${wrapIfMultiToken(emit(object))} ${d}`;
|
|
2399
|
+
}
|
|
2400
|
+
flatMapMethod(object, op, emit) {
|
|
2401
|
+
const recv = wrapIfMultiToken(emit(object));
|
|
2402
|
+
const proj = op.projection;
|
|
2403
|
+
if (proj.kind === "tuple") {
|
|
2404
|
+
const pairs = proj.elements.map((l) => l.kind === "self" ? `"self" ""` : `"field" "${capitalize(l.field)}"`).join(" ");
|
|
2405
|
+
return `bf_flat_map_tuple ${recv} ${pairs}`;
|
|
2406
|
+
}
|
|
2407
|
+
if (proj.kind === "self") {
|
|
2408
|
+
return `bf_flat_map ${recv} "self" ""`;
|
|
2409
|
+
}
|
|
2410
|
+
return `bf_flat_map ${recv} "field" "${capitalize(proj.field)}"`;
|
|
2411
|
+
}
|
|
2370
2412
|
unsupported(raw, _reason) {
|
|
2371
2413
|
return `[UNSUPPORTED: ${raw}]`;
|
|
2372
2414
|
}
|
|
@@ -2789,13 +2831,7 @@ ${goFields.join(`
|
|
|
2789
2831
|
message: `Expression not supported: ${trimmed}`,
|
|
2790
2832
|
loc: this.makeLoc(),
|
|
2791
2833
|
suggestion: {
|
|
2792
|
-
message: support
|
|
2793
|
-
|
|
2794
|
-
Options:
|
|
2795
|
-
1. Use @client directive for client-side evaluation
|
|
2796
|
-
2. Pre-compute the value in Go code` : `Options:
|
|
2797
|
-
1. Use @client directive for client-side evaluation
|
|
2798
|
-
2. Pre-compute the value in Go code`
|
|
2834
|
+
message: buildUnsupportedSuggestion(support)
|
|
2799
2835
|
}
|
|
2800
2836
|
});
|
|
2801
2837
|
return `""`;
|
|
@@ -2824,9 +2860,7 @@ Options:
|
|
|
2824
2860
|
message: `Complex predicate in else-if is not supported: ${altIfStmt.condition}`,
|
|
2825
2861
|
loc: this.makeLoc(),
|
|
2826
2862
|
suggestion: {
|
|
2827
|
-
message:
|
|
2828
|
-
1. Use @client directive for client-side evaluation
|
|
2829
|
-
2. Pre-compute the value in Go code`
|
|
2863
|
+
message: GO_REMEDIATION_OPTIONS
|
|
2830
2864
|
}
|
|
2831
2865
|
});
|
|
2832
2866
|
}
|
|
@@ -2902,11 +2936,7 @@ Options:
|
|
|
2902
2936
|
message: `Condition not supported: ${trimmed}`,
|
|
2903
2937
|
loc: this.makeLoc(),
|
|
2904
2938
|
suggestion: {
|
|
2905
|
-
message: support
|
|
2906
|
-
|
|
2907
|
-
Options:
|
|
2908
|
-
1. Use @client directive for client-side evaluation
|
|
2909
|
-
2. Pre-compute the value in Go code` : "Expression contains unsupported syntax"
|
|
2939
|
+
message: buildUnsupportedSuggestion(support)
|
|
2910
2940
|
}
|
|
2911
2941
|
});
|
|
2912
2942
|
return { condition: `false`, preamble: "" };
|
package/dist/index.js
CHANGED
|
@@ -51,8 +51,20 @@ function emitBfSort(recv, c) {
|
|
|
51
51
|
});
|
|
52
52
|
return `bf_sort ${wrapIfMultiToken(recv)} ${groups.join(" ")}`;
|
|
53
53
|
}
|
|
54
|
+
function emitBfReduce(recv, op, direction) {
|
|
55
|
+
const keyName = op.key.kind === "field" ? capitalize(op.key.field) : "";
|
|
56
|
+
return `bf_reduce ${wrapIfMultiToken(recv)} "${op.op}" "${op.key.kind}" "${keyName}" "${op.type}" "${escapeGoString(op.init)}" "${direction}"`;
|
|
57
|
+
}
|
|
58
|
+
function escapeGoString(s) {
|
|
59
|
+
return s.replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
|
|
60
|
+
}
|
|
54
61
|
function capitalize(s) {
|
|
55
|
-
|
|
62
|
+
if (s.length === 0)
|
|
63
|
+
return s;
|
|
64
|
+
if (GoTemplateAdapter.GO_INITIALISMS.has(s.toLowerCase())) {
|
|
65
|
+
return s.toUpperCase();
|
|
66
|
+
}
|
|
67
|
+
return s[0].toUpperCase() + s.slice(1);
|
|
56
68
|
}
|
|
57
69
|
function slotIdToFieldSuffix(slotId) {
|
|
58
70
|
const cleanId = slotId.startsWith("^") ? slotId.slice(1) : slotId;
|
|
@@ -62,6 +74,18 @@ function slotIdToFieldSuffix(slotId) {
|
|
|
62
74
|
}
|
|
63
75
|
return cleanId.replace("slot_", "Slot");
|
|
64
76
|
}
|
|
77
|
+
var GO_REMEDIATION_OPTIONS = `Options:
|
|
78
|
+
1. Use @client directive for client-side evaluation
|
|
79
|
+
2. Pre-compute the value in Go code`;
|
|
80
|
+
function buildUnsupportedSuggestion(support) {
|
|
81
|
+
if (!support.reason)
|
|
82
|
+
return GO_REMEDIATION_OPTIONS;
|
|
83
|
+
if (support.selfContained)
|
|
84
|
+
return support.reason;
|
|
85
|
+
return `${support.reason}
|
|
86
|
+
|
|
87
|
+
${GO_REMEDIATION_OPTIONS}`;
|
|
88
|
+
}
|
|
65
89
|
var GO_TEMPLATE_PRIMITIVES = {
|
|
66
90
|
"JSON.stringify": { arity: 1, emit: (args) => `bf_json ${args[0]}` },
|
|
67
91
|
String: { arity: 1, emit: (args) => `bf_string ${args[0]}` },
|
|
@@ -1905,9 +1929,7 @@ ${goFields.join(`
|
|
|
1905
1929
|
message: `Higher-order method '.${method}' shape cannot be lowered to a Go template action`,
|
|
1906
1930
|
loc: this.makeLoc(),
|
|
1907
1931
|
suggestion: {
|
|
1908
|
-
message:
|
|
1909
|
-
1. Use @client directive for client-side evaluation
|
|
1910
|
-
2. Pre-compute the value in Go code`
|
|
1932
|
+
message: GO_REMEDIATION_OPTIONS
|
|
1911
1933
|
}
|
|
1912
1934
|
});
|
|
1913
1935
|
return `""`;
|
|
@@ -2027,6 +2049,26 @@ ${goFields.join(`
|
|
|
2027
2049
|
sortMethod(method, object, comparator, emit) {
|
|
2028
2050
|
return emitBfSort(emit(object), comparator);
|
|
2029
2051
|
}
|
|
2052
|
+
reduceMethod(method, object, reduceOp, emit) {
|
|
2053
|
+
const direction = method === "reduceRight" ? "right" : "left";
|
|
2054
|
+
return emitBfReduce(emit(object), reduceOp, direction);
|
|
2055
|
+
}
|
|
2056
|
+
flatMethod(object, depth, emit) {
|
|
2057
|
+
const d = depth === "infinity" ? -1 : depth;
|
|
2058
|
+
return `bf_flat ${wrapIfMultiToken(emit(object))} ${d}`;
|
|
2059
|
+
}
|
|
2060
|
+
flatMapMethod(object, op, emit) {
|
|
2061
|
+
const recv = wrapIfMultiToken(emit(object));
|
|
2062
|
+
const proj = op.projection;
|
|
2063
|
+
if (proj.kind === "tuple") {
|
|
2064
|
+
const pairs = proj.elements.map((l) => l.kind === "self" ? `"self" ""` : `"field" "${capitalize(l.field)}"`).join(" ");
|
|
2065
|
+
return `bf_flat_map_tuple ${recv} ${pairs}`;
|
|
2066
|
+
}
|
|
2067
|
+
if (proj.kind === "self") {
|
|
2068
|
+
return `bf_flat_map ${recv} "self" ""`;
|
|
2069
|
+
}
|
|
2070
|
+
return `bf_flat_map ${recv} "field" "${capitalize(proj.field)}"`;
|
|
2071
|
+
}
|
|
2030
2072
|
unsupported(raw, _reason) {
|
|
2031
2073
|
return `[UNSUPPORTED: ${raw}]`;
|
|
2032
2074
|
}
|
|
@@ -2449,13 +2491,7 @@ ${goFields.join(`
|
|
|
2449
2491
|
message: `Expression not supported: ${trimmed}`,
|
|
2450
2492
|
loc: this.makeLoc(),
|
|
2451
2493
|
suggestion: {
|
|
2452
|
-
message: support
|
|
2453
|
-
|
|
2454
|
-
Options:
|
|
2455
|
-
1. Use @client directive for client-side evaluation
|
|
2456
|
-
2. Pre-compute the value in Go code` : `Options:
|
|
2457
|
-
1. Use @client directive for client-side evaluation
|
|
2458
|
-
2. Pre-compute the value in Go code`
|
|
2494
|
+
message: buildUnsupportedSuggestion(support)
|
|
2459
2495
|
}
|
|
2460
2496
|
});
|
|
2461
2497
|
return `""`;
|
|
@@ -2484,9 +2520,7 @@ Options:
|
|
|
2484
2520
|
message: `Complex predicate in else-if is not supported: ${altIfStmt.condition}`,
|
|
2485
2521
|
loc: this.makeLoc(),
|
|
2486
2522
|
suggestion: {
|
|
2487
|
-
message:
|
|
2488
|
-
1. Use @client directive for client-side evaluation
|
|
2489
|
-
2. Pre-compute the value in Go code`
|
|
2523
|
+
message: GO_REMEDIATION_OPTIONS
|
|
2490
2524
|
}
|
|
2491
2525
|
});
|
|
2492
2526
|
}
|
|
@@ -2562,11 +2596,7 @@ Options:
|
|
|
2562
2596
|
message: `Condition not supported: ${trimmed}`,
|
|
2563
2597
|
loc: this.makeLoc(),
|
|
2564
2598
|
suggestion: {
|
|
2565
|
-
message: support
|
|
2566
|
-
|
|
2567
|
-
Options:
|
|
2568
|
-
1. Use @client directive for client-side evaluation
|
|
2569
|
-
2. Pre-compute the value in Go code` : "Expression contains unsupported syntax"
|
|
2599
|
+
message: buildUnsupportedSuggestion(support)
|
|
2570
2600
|
}
|
|
2571
2601
|
});
|
|
2572
2602
|
return { condition: `false`, preamble: "" };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@barefootjs/go-template",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"description": "Go html/template adapter for BarefootJS - generates Go template files from IR",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -54,6 +54,6 @@
|
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
56
|
"@barefootjs/adapter-tests": "0.1.0",
|
|
57
|
-
"@barefootjs/jsx": "0.6.
|
|
57
|
+
"@barefootjs/jsx": "0.6.1"
|
|
58
58
|
}
|
|
59
59
|
}
|
|
@@ -2318,6 +2318,81 @@ describe('GoTemplateAdapter - #1448 Tier A/B fixture-driven lowering pins', () =
|
|
|
2318
2318
|
// now listed in `UNSUPPORTED_METHODS`, so `isSupported` refuses them
|
|
2319
2319
|
// and `convertExpressionToGo` records BF101 — the same treatment the
|
|
2320
2320
|
// unsupported array methods already got. These tests pin that parity.
|
|
2321
|
+
describe('GoTemplateAdapter - #1448 Tier C reduce field capitalisation', () => {
|
|
2322
|
+
// #1728 review: `bf_reduce`'s projected field name must use the same
|
|
2323
|
+
// initialism-aware capitalisation the adapter applies when generating
|
|
2324
|
+
// struct fields (`capitalizeFieldName`), or the runtime reflect lookup
|
|
2325
|
+
// misses the exported field (`id` → struct `ID`, not `Id`) and folds a
|
|
2326
|
+
// zero value. Pin the emitted key so a regression to plain
|
|
2327
|
+
// first-letter capitalisation fails here.
|
|
2328
|
+
test('reduce over an initialism field emits the Go-initialism key (ID, not Id)', () => {
|
|
2329
|
+
const adapter = new GoTemplateAdapter()
|
|
2330
|
+
const ir = compileToIR(`
|
|
2331
|
+
function C({ items }: { items: { id: number }[] }) {
|
|
2332
|
+
return <div>{items.reduce((sum, x) => sum + x.id, 0)}</div>
|
|
2333
|
+
}
|
|
2334
|
+
export { C }
|
|
2335
|
+
`, adapter)
|
|
2336
|
+
const template = adapter.generate(ir).template ?? ''
|
|
2337
|
+
expect(template).toContain('bf_reduce .Items "+" "field" "ID" "numeric" "0"')
|
|
2338
|
+
expect(template).not.toContain('"Id"')
|
|
2339
|
+
})
|
|
2340
|
+
})
|
|
2341
|
+
|
|
2342
|
+
describe('GoTemplateAdapter - #1448 Tier C .flat(depth?)', () => {
|
|
2343
|
+
function emitFlat(expr: string): string {
|
|
2344
|
+
const adapter = new GoTemplateAdapter()
|
|
2345
|
+
const ir = compileToIR(`
|
|
2346
|
+
function C({ rows }: { rows: number[][] }) {
|
|
2347
|
+
return <div>{${expr}}</div>
|
|
2348
|
+
}
|
|
2349
|
+
export { C }
|
|
2350
|
+
`, adapter)
|
|
2351
|
+
return adapter.generate(ir).template ?? ''
|
|
2352
|
+
}
|
|
2353
|
+
|
|
2354
|
+
test('.flat() emits bf_flat with default depth 1', () => {
|
|
2355
|
+
expect(emitFlat('rows.flat()')).toContain('bf_flat .Rows 1')
|
|
2356
|
+
})
|
|
2357
|
+
|
|
2358
|
+
test('.flat(2) emits the explicit depth', () => {
|
|
2359
|
+
expect(emitFlat('rows.flat(2)')).toContain('bf_flat .Rows 2')
|
|
2360
|
+
})
|
|
2361
|
+
|
|
2362
|
+
test('.flat(Infinity) emits the -1 full-depth sentinel', () => {
|
|
2363
|
+
expect(emitFlat('rows.flat(Infinity)')).toContain('bf_flat .Rows -1')
|
|
2364
|
+
})
|
|
2365
|
+
})
|
|
2366
|
+
|
|
2367
|
+
describe('GoTemplateAdapter - #1448 Tier C .flatMap(field projection)', () => {
|
|
2368
|
+
function emitFlatMap(expr: string): string {
|
|
2369
|
+
const adapter = new GoTemplateAdapter()
|
|
2370
|
+
const ir = compileToIR(`
|
|
2371
|
+
function C({ rows }: { rows: { a: string; b: string; tags: string[] }[] }) {
|
|
2372
|
+
return <div>{${expr}}</div>
|
|
2373
|
+
}
|
|
2374
|
+
export { C }
|
|
2375
|
+
`, adapter)
|
|
2376
|
+
return adapter.generate(ir).template ?? ''
|
|
2377
|
+
}
|
|
2378
|
+
|
|
2379
|
+
test('.flatMap(i => i.field) emits bf_flat_map with the Go-capitalised field', () => {
|
|
2380
|
+
expect(emitFlatMap('rows.flatMap(i => i.tags).join(" ")')).toContain('bf_flat_map .Rows "field" "Tags"')
|
|
2381
|
+
})
|
|
2382
|
+
|
|
2383
|
+
test('.flatMap(i => i) emits the self projection', () => {
|
|
2384
|
+
expect(emitFlatMap('rows.flatMap(i => i).join(" ")')).toContain('bf_flat_map .Rows "self" ""')
|
|
2385
|
+
})
|
|
2386
|
+
|
|
2387
|
+
test('.flatMap(i => [i.a, i.b]) emits bf_flat_map_tuple with capitalised leaves', () => {
|
|
2388
|
+
expect(emitFlatMap('rows.flatMap(i => [i.a, i.b]).join(" ")')).toContain('bf_flat_map_tuple .Rows "field" "A" "field" "B"')
|
|
2389
|
+
})
|
|
2390
|
+
|
|
2391
|
+
test('tuple self + field leaves', () => {
|
|
2392
|
+
expect(emitFlatMap('rows.flatMap(i => [i, i.a]).join(" ")')).toContain('bf_flat_map_tuple .Rows "self" "" "field" "A"')
|
|
2393
|
+
})
|
|
2394
|
+
})
|
|
2395
|
+
|
|
2321
2396
|
describe('GoTemplateAdapter - #1448 @client escape hatch (unsupported methods)', () => {
|
|
2322
2397
|
// Compile a single expression placed in `<div>` text position, with
|
|
2323
2398
|
// and without the directive, and return both the build errors and
|
|
@@ -2363,10 +2438,14 @@ export function C() {
|
|
|
2363
2438
|
// Go fragment that must NOT survive into the template (the pre-fix
|
|
2364
2439
|
// silent-footgun output for the string rows).
|
|
2365
2440
|
const unsupported: Array<{ name: string; expr: string; badEmit: string }> = [
|
|
2366
|
-
// Tier C array methods.
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2441
|
+
// Tier C array methods. The arithmetic-fold `.reduce(fn, init)`
|
|
2442
|
+
// catalogue now lowers (pinned in the positive reduce-* fixtures);
|
|
2443
|
+
// the no-initial-value form stays refused — JS throws on an empty
|
|
2444
|
+
// array there, which a template can't mirror.
|
|
2445
|
+
{ name: 'reduce (no init)', expr: `items().reduce((a, b) => a + b.n)`, badEmit: '.Reduce' },
|
|
2446
|
+
// Self / field / field-tuple `.flatMap` now lowers (#1448 Tier C); a
|
|
2447
|
+
// tuple with a non-leaf element (here a string literal) stays refused.
|
|
2448
|
+
{ name: 'flatMap (literal element)', expr: `items().flatMap(i => [i.name, "x"])`, badEmit: '.FlatMap' },
|
|
2370
2449
|
// Lowered methods whose MEANINGFUL extra argument isn't lowered yet
|
|
2371
2450
|
// (#1448): the `fromIndex` of `.includes`/`.indexOf`/`.lastIndexOf`
|
|
2372
2451
|
// and the variadic `.concat`. The parser refuses these (silently
|
|
@@ -2401,6 +2480,40 @@ export function C() {
|
|
|
2401
2480
|
})
|
|
2402
2481
|
}
|
|
2403
2482
|
|
|
2483
|
+
// The diagnostic's `suggestion.message` is shaped by `isSupported`'s
|
|
2484
|
+
// `selfContained` flag: reasons that already spell out the fix are shown
|
|
2485
|
+
// as-is, while low-level parser reasons still get the adapter's generic
|
|
2486
|
+
// "Options" remediation appended so users never lose actionable steps.
|
|
2487
|
+
function suggestionFor(expr: string): string {
|
|
2488
|
+
const { errors } = emit(expr, false)
|
|
2489
|
+
const e = errors.find(e => e.code === 'BF101' || e.code === 'BF102')
|
|
2490
|
+
return e?.suggestion?.message ?? ''
|
|
2491
|
+
}
|
|
2492
|
+
|
|
2493
|
+
test('self-contained reason is shown without the generic Options block', () => {
|
|
2494
|
+
// Generic unsupported-method reason already carries the remedy.
|
|
2495
|
+
const msg = suggestionFor('items().reduce((a, b) => a + b.n)')
|
|
2496
|
+
expect(msg).toContain('no SSR')
|
|
2497
|
+
expect(msg).not.toContain('Options:')
|
|
2498
|
+
})
|
|
2499
|
+
|
|
2500
|
+
test('tailored forEach reason keeps its own guidance, no Options block', () => {
|
|
2501
|
+
const msg = suggestionFor('items().forEach(x => x)')
|
|
2502
|
+
expect(msg).toContain("'.map(")
|
|
2503
|
+
// The forEach message deliberately steers away from @client; the
|
|
2504
|
+
// generic Options block (which re-suggests it) must not be appended.
|
|
2505
|
+
expect(msg).not.toContain('Options:')
|
|
2506
|
+
expect(msg).not.toContain('@client')
|
|
2507
|
+
})
|
|
2508
|
+
|
|
2509
|
+
test('low-level reason still gets the actionable Options block appended', () => {
|
|
2510
|
+
// `typeof` has no structured remedy reason → users must keep the
|
|
2511
|
+
// generic next steps (regression guard for #1730 review).
|
|
2512
|
+
const msg = suggestionFor('typeof items()')
|
|
2513
|
+
expect(msg).toContain('Options:')
|
|
2514
|
+
expect(msg).toContain('@client')
|
|
2515
|
+
})
|
|
2516
|
+
|
|
2404
2517
|
// Predicate-level use of an unsupported string method also fails the
|
|
2405
2518
|
// build loudly (intended): a `.filter(t => t.name.charAt(0) === "a")`
|
|
2406
2519
|
// whose predicate calls one of the gated methods now refuses the whole
|
|
@@ -27,6 +27,9 @@ import type {
|
|
|
27
27
|
ParsedExpr,
|
|
28
28
|
ParsedStatement,
|
|
29
29
|
SortComparator,
|
|
30
|
+
ReduceOp,
|
|
31
|
+
FlatDepth,
|
|
32
|
+
FlatMapOp,
|
|
30
33
|
TemplatePart,
|
|
31
34
|
IRIfStatement,
|
|
32
35
|
IRProvider,
|
|
@@ -45,6 +48,7 @@ import {
|
|
|
45
48
|
type IRNodeEmitter,
|
|
46
49
|
type EmitIRNode,
|
|
47
50
|
type AttrValueEmitter,
|
|
51
|
+
type SupportResult,
|
|
48
52
|
isBooleanAttr,
|
|
49
53
|
parseExpression,
|
|
50
54
|
isSupported,
|
|
@@ -208,8 +212,56 @@ function emitBfSort(recv: string, c: SortComparator): string {
|
|
|
208
212
|
return `bf_sort ${wrapIfMultiToken(recv)} ${groups.join(' ')}`
|
|
209
213
|
}
|
|
210
214
|
|
|
215
|
+
/**
|
|
216
|
+
* Emit the `bf_reduce` call for a `.reduce(fn, init)` arithmetic fold
|
|
217
|
+
* (#1448 Tier C):
|
|
218
|
+
*
|
|
219
|
+
* bf_reduce <recv> "<op>" "<keyKind>" "<keyName>" "<type>" "<init>" "<direction>"
|
|
220
|
+
*
|
|
221
|
+
* op: "+" | "*"
|
|
222
|
+
* keyKind: "self" | "field"
|
|
223
|
+
* keyName: "" when keyKind=self; capitalised field name otherwise
|
|
224
|
+
* (matches the Go struct-field convention, mirroring
|
|
225
|
+
* `emitBfSort`)
|
|
226
|
+
* type: "numeric" | "string"
|
|
227
|
+
* init: the fold's start value — the numeric literal's text for a
|
|
228
|
+
* numeric fold, or the string literal's contents for a
|
|
229
|
+
* concat fold
|
|
230
|
+
* direction: "left" (reduce) | "right" (reduceRight)
|
|
231
|
+
*
|
|
232
|
+
* The runtime folds `init <op> key(item)` in `direction` order and
|
|
233
|
+
* returns the accumulated value (float64 for numeric, string for
|
|
234
|
+
* concat). The order is only observable for string concat — numeric
|
|
235
|
+
* sum / product commute.
|
|
236
|
+
*/
|
|
237
|
+
function emitBfReduce(recv: string, op: ReduceOp, direction: 'left' | 'right'): string {
|
|
238
|
+
const keyName = op.key.kind === 'field' ? capitalize(op.key.field) : ''
|
|
239
|
+
// `op.init` is already the decoded seed value (canonical decimal for
|
|
240
|
+
// numeric folds — `strconv.ParseFloat`-safe; escape-free contents for
|
|
241
|
+
// concat folds). Pass it as a quoted operand the runtime interprets
|
|
242
|
+
// by `type`. `direction` is "left" (reduce) or "right" (reduceRight)
|
|
243
|
+
// — only observable for string concatenation; numeric folds are
|
|
244
|
+
// commutative.
|
|
245
|
+
return `bf_reduce ${wrapIfMultiToken(recv)} "${op.op}" "${op.key.kind}" "${keyName}" "${op.type}" "${escapeGoString(op.init)}" "${direction}"`
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/** Escape a value for embedding in a Go-template double-quoted string. */
|
|
249
|
+
function escapeGoString(s: string): string {
|
|
250
|
+
return s.replace(/\\/g, '\\\\').replace(/"/g, '\\"')
|
|
251
|
+
}
|
|
252
|
+
|
|
211
253
|
function capitalize(s: string): string {
|
|
212
|
-
|
|
254
|
+
if (s.length === 0) return s
|
|
255
|
+
// Match the adapter's struct-field naming (`capitalizeFieldName`):
|
|
256
|
+
// a whole-word Go initialism uppercases entirely (`id` → `ID`,
|
|
257
|
+
// `url` → `URL`) so the `bf_sort` / `bf_reduce` reflect lookup
|
|
258
|
+
// resolves the generated exported field instead of silently folding
|
|
259
|
+
// a zero value. The class is fully initialised by the time any emit
|
|
260
|
+
// helper runs, so referencing the static set here is safe.
|
|
261
|
+
if (GoTemplateAdapter.GO_INITIALISMS.has(s.toLowerCase())) {
|
|
262
|
+
return s.toUpperCase()
|
|
263
|
+
}
|
|
264
|
+
return s[0].toUpperCase() + s.slice(1)
|
|
213
265
|
}
|
|
214
266
|
|
|
215
267
|
/**
|
|
@@ -239,6 +291,22 @@ interface PrimitiveSpec {
|
|
|
239
291
|
emit: (args: string[]) => string
|
|
240
292
|
}
|
|
241
293
|
|
|
294
|
+
// Generic remediation appended to BF101 / BF102 diagnostics whose reason
|
|
295
|
+
// doesn't already carry actionable next steps.
|
|
296
|
+
const GO_REMEDIATION_OPTIONS =
|
|
297
|
+
'Options:\n1. Use @client directive for client-side evaluation\n2. Pre-compute the value in Go code'
|
|
298
|
+
|
|
299
|
+
// Build the `suggestion.message` for an unsupported expression/condition.
|
|
300
|
+
// A self-contained reason (it already spells out the fix — e.g. the
|
|
301
|
+
// pre-compute / @client hint or the tailored forEach message) is shown
|
|
302
|
+
// as-is; a low-level reason gets the generic options appended; with no
|
|
303
|
+
// reason at all we fall back to the options alone.
|
|
304
|
+
function buildUnsupportedSuggestion(support: SupportResult): string {
|
|
305
|
+
if (!support.reason) return GO_REMEDIATION_OPTIONS
|
|
306
|
+
if (support.selfContained) return support.reason
|
|
307
|
+
return `${support.reason}\n\n${GO_REMEDIATION_OPTIONS}`
|
|
308
|
+
}
|
|
309
|
+
|
|
242
310
|
const GO_TEMPLATE_PRIMITIVES: Record<string, PrimitiveSpec> = {
|
|
243
311
|
'JSON.stringify': { arity: 1, emit: (args) => `bf_json ${args[0]}` },
|
|
244
312
|
'String': { arity: 1, emit: (args) => `bf_string ${args[0]}` },
|
|
@@ -2579,7 +2647,9 @@ export class GoTemplateAdapter extends BaseAdapter implements ParsedExprEmitter,
|
|
|
2579
2647
|
private static GO_IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/
|
|
2580
2648
|
|
|
2581
2649
|
/** Go common initialisms that should be fully uppercased (https://go.dev/wiki/CodeReviewComments#initialisms) */
|
|
2582
|
-
private
|
|
2650
|
+
// Not `private`: the module-level `capitalize` helper reads this so
|
|
2651
|
+
// `bf_sort` / `bf_reduce` field projection matches `capitalizeFieldName`.
|
|
2652
|
+
static GO_INITIALISMS = new Set([
|
|
2583
2653
|
'id', 'url', 'http', 'https', 'api', 'json', 'xml', 'html', 'css', 'sql',
|
|
2584
2654
|
'ip', 'tcp', 'udp', 'dns', 'ssh', 'tls', 'ssl', 'uri', 'uid', 'uuid',
|
|
2585
2655
|
'ascii', 'utf8', 'eof', 'grpc', 'rpc', 'cpu', 'gpu', 'ram', 'os',
|
|
@@ -3089,7 +3159,7 @@ export class GoTemplateAdapter extends BaseAdapter implements ParsedExprEmitter,
|
|
|
3089
3159
|
message: `Higher-order method '.${method}' shape cannot be lowered to a Go template action`,
|
|
3090
3160
|
loc: this.makeLoc(),
|
|
3091
3161
|
suggestion: {
|
|
3092
|
-
message:
|
|
3162
|
+
message: GO_REMEDIATION_OPTIONS,
|
|
3093
3163
|
},
|
|
3094
3164
|
})
|
|
3095
3165
|
return `""`
|
|
@@ -3311,6 +3381,51 @@ export class GoTemplateAdapter extends BaseAdapter implements ParsedExprEmitter,
|
|
|
3311
3381
|
return emitBfSort(emit(object), comparator)
|
|
3312
3382
|
}
|
|
3313
3383
|
|
|
3384
|
+
reduceMethod(
|
|
3385
|
+
method: 'reduce' | 'reduceRight',
|
|
3386
|
+
object: ParsedExpr,
|
|
3387
|
+
reduceOp: ReduceOp,
|
|
3388
|
+
emit: (e: ParsedExpr) => string,
|
|
3389
|
+
): string {
|
|
3390
|
+
// `.reduce(fn, init)` / `.reduceRight(fn, init)` arithmetic-fold
|
|
3391
|
+
// lowering (#1448 Tier C). The structured `ReduceOp` (op / key /
|
|
3392
|
+
// type / init) plus the fold direction feed the `bf_reduce` runtime
|
|
3393
|
+
// helper, which folds the receiver into a scalar.
|
|
3394
|
+
const direction = method === 'reduceRight' ? 'right' : 'left'
|
|
3395
|
+
return emitBfReduce(emit(object), reduceOp, direction)
|
|
3396
|
+
}
|
|
3397
|
+
|
|
3398
|
+
flatMethod(object: ParsedExpr, depth: FlatDepth, emit: (e: ParsedExpr) => string): string {
|
|
3399
|
+
// `.flat(depth?)` → `bf_flat <recv> <depth>`. The `Infinity` form
|
|
3400
|
+
// lowers to the `-1` sentinel (flatten fully); a finite depth flattens
|
|
3401
|
+
// that many levels (`0` = shallow copy). See packages/adapter-go-
|
|
3402
|
+
// template/runtime/bf.go.
|
|
3403
|
+
const d = depth === 'infinity' ? -1 : depth
|
|
3404
|
+
return `bf_flat ${wrapIfMultiToken(emit(object))} ${d}`
|
|
3405
|
+
}
|
|
3406
|
+
|
|
3407
|
+
flatMapMethod(object: ParsedExpr, op: FlatMapOp, emit: (e: ParsedExpr) => string): string {
|
|
3408
|
+
const recv = wrapIfMultiToken(emit(object))
|
|
3409
|
+
const proj = op.projection
|
|
3410
|
+
// Tuple projection `i => [i.a, i.b]` → `bf_flat_map_tuple <recv>
|
|
3411
|
+
// "<kind>" "<name>" ...` (one quoted pair per leaf). flat(1) removes
|
|
3412
|
+
// only the literal's wrapper, so the runtime appends each leaf verbatim.
|
|
3413
|
+
if (proj.kind === 'tuple') {
|
|
3414
|
+
const pairs = proj.elements
|
|
3415
|
+
.map(l => (l.kind === 'self' ? `"self" ""` : `"field" "${capitalize(l.field)}"`))
|
|
3416
|
+
.join(' ')
|
|
3417
|
+
return `bf_flat_map_tuple ${recv} ${pairs}`
|
|
3418
|
+
}
|
|
3419
|
+
// Scalar `.flatMap(i => i)` / `.flatMap(i => i.field)` → `bf_flat_map
|
|
3420
|
+
// <recv> "<kind>" "<name>"`. The runtime projects each item then
|
|
3421
|
+
// flattens one level. The field name uses the Go struct-field
|
|
3422
|
+
// capitalisation, matching `bf_reduce` / `bf_sort`.
|
|
3423
|
+
if (proj.kind === 'self') {
|
|
3424
|
+
return `bf_flat_map ${recv} "self" ""`
|
|
3425
|
+
}
|
|
3426
|
+
return `bf_flat_map ${recv} "field" "${capitalize(proj.field)}"`
|
|
3427
|
+
}
|
|
3428
|
+
|
|
3314
3429
|
unsupported(raw: string, _reason: string): string {
|
|
3315
3430
|
// Should not happen if `isSupported` was checked at parse time.
|
|
3316
3431
|
return `[UNSUPPORTED: ${raw}]`
|
|
@@ -4046,9 +4161,7 @@ export class GoTemplateAdapter extends BaseAdapter implements ParsedExprEmitter,
|
|
|
4046
4161
|
message: `Expression not supported: ${trimmed}`,
|
|
4047
4162
|
loc: this.makeLoc(),
|
|
4048
4163
|
suggestion: {
|
|
4049
|
-
message: support
|
|
4050
|
-
? `${support.reason}\n\nOptions:\n1. Use @client directive for client-side evaluation\n2. Pre-compute the value in Go code`
|
|
4051
|
-
: 'Options:\n1. Use @client directive for client-side evaluation\n2. Pre-compute the value in Go code',
|
|
4164
|
+
message: buildUnsupportedSuggestion(support),
|
|
4052
4165
|
},
|
|
4053
4166
|
})
|
|
4054
4167
|
// Return empty string - Go template comments must be separate actions
|
|
@@ -4086,7 +4199,7 @@ export class GoTemplateAdapter extends BaseAdapter implements ParsedExprEmitter,
|
|
|
4086
4199
|
message: `Complex predicate in else-if is not supported: ${altIfStmt.condition}`,
|
|
4087
4200
|
loc: this.makeLoc(),
|
|
4088
4201
|
suggestion: {
|
|
4089
|
-
message:
|
|
4202
|
+
message: GO_REMEDIATION_OPTIONS,
|
|
4090
4203
|
},
|
|
4091
4204
|
})
|
|
4092
4205
|
}
|
|
@@ -4183,9 +4296,7 @@ export class GoTemplateAdapter extends BaseAdapter implements ParsedExprEmitter,
|
|
|
4183
4296
|
message: `Condition not supported: ${trimmed}`,
|
|
4184
4297
|
loc: this.makeLoc(),
|
|
4185
4298
|
suggestion: {
|
|
4186
|
-
message: support
|
|
4187
|
-
? `${support.reason}\n\nOptions:\n1. Use @client directive for client-side evaluation\n2. Pre-compute the value in Go code`
|
|
4188
|
-
: 'Expression contains unsupported syntax',
|
|
4299
|
+
message: buildUnsupportedSuggestion(support),
|
|
4189
4300
|
},
|
|
4190
4301
|
})
|
|
4191
4302
|
// Return false - Go template comments must be separate actions
|
package/src/test-render.ts
CHANGED
|
@@ -355,7 +355,14 @@ function goMapLiteralFromObject(
|
|
|
355
355
|
else if (typeof v === 'number') entries.push(`${key}: ${v}`)
|
|
356
356
|
else if (typeof v === 'boolean') entries.push(`${key}: ${v}`)
|
|
357
357
|
else if (v === null) entries.push(`${key}: nil`)
|
|
358
|
-
else if (
|
|
358
|
+
else if (Array.isArray(v)) {
|
|
359
|
+
// Array-valued field inside an object-in-array (e.g. the `tags`
|
|
360
|
+
// of `items.flatMap(i => i.tags)`). Without this branch the field
|
|
361
|
+
// was silently dropped, leaving an empty map so the template
|
|
362
|
+
// rendered nothing for the projection (#1448 Tier C flatMap).
|
|
363
|
+
entries.push(`${key}: ${goArrayLiteralFromArray(v)}`)
|
|
364
|
+
}
|
|
365
|
+
else if (v && typeof v === 'object') {
|
|
359
366
|
entries.push(`${key}: ${goMapLiteralFromObject(v as Record<string, unknown>, capitalizeKeys)}`)
|
|
360
367
|
}
|
|
361
368
|
}
|