@barefootjs/go-template 0.23.0 → 0.25.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/expr/url-builder.d.ts +20 -0
- package/dist/adapter/expr/url-builder.d.ts.map +1 -1
- package/dist/adapter/go-template-adapter.d.ts +1 -7
- package/dist/adapter/go-template-adapter.d.ts.map +1 -1
- package/dist/adapter/index.js +21 -21
- package/dist/build.js +21 -21
- package/dist/index.js +21 -21
- package/package.json +3 -3
- package/src/__tests__/derived-state-memo.test.ts +16 -11
- package/src/__tests__/go-template-adapter.test.ts +116 -7
- package/src/__tests__/lowering-plugin.test.ts +20 -0
- package/src/adapter/expr/url-builder.ts +76 -1
- package/src/adapter/go-template-adapter.ts +29 -33
|
@@ -8,6 +8,26 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { type ParsedExpr } from '@barefootjs/jsx';
|
|
10
10
|
import type { GoEmitContext } from '../emit-context.ts';
|
|
11
|
+
/**
|
|
12
|
+
* Lower a `conditional` (ternary) ParsedExpr to the pipeline-position
|
|
13
|
+
* `(bf_ternary <test> <consequent> <alternate>)` form (#2335). Go
|
|
14
|
+
* `text/template` is the only backend without an expression-level
|
|
15
|
+
* conditional, so a ternary sitting in VALUE position — a helper-call arg, a
|
|
16
|
+
* template-literal interpolation, an attribute value, or a boolean
|
|
17
|
+
* sub-condition — cannot be an `{{if}}…{{end}}` action fragment (a parse error
|
|
18
|
+
* inside a pipeline, and a silent branch-discard in condition position). This
|
|
19
|
+
* is the single lowering every such position shares; each caller passes the
|
|
20
|
+
* ternary's three child nodes directly (the ParsedExpr emitter hands them over
|
|
21
|
+
* unwrapped).
|
|
22
|
+
*
|
|
23
|
+
* - branches are quoted VALUES, recursing so a right-folded chain
|
|
24
|
+
* (`a ? x : b ? y : z`) nests as `(bf_ternary … (bf_ternary …))`.
|
|
25
|
+
* - the test is coerced to a real Go `bool` (see `lowerTernaryTest`).
|
|
26
|
+
*
|
|
27
|
+
* NOT for the text-position `IRConditional` (`renderConditional`), whose
|
|
28
|
+
* branches are arbitrary markup, not values.
|
|
29
|
+
*/
|
|
30
|
+
export declare function lowerTernary(ctx: GoEmitContext, test: ParsedExpr, consequent: ParsedExpr, alternate: ParsedExpr): string;
|
|
11
31
|
/**
|
|
12
32
|
* Lower a helper call to a Go template expression, or null when no registered
|
|
13
33
|
* plugin recognises it (→ the generic lowering). Matchers — including the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"url-builder.d.ts","sourceRoot":"","sources":["../../../src/adapter/expr/url-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAEL,KAAK,UAAU,EAIhB,MAAM,iBAAiB,CAAA;AAExB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAkDvD;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,aAAa,EAClB,MAAM,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,UAAU,GACrB,MAAM,GAAG,IAAI,CAmBf"}
|
|
1
|
+
{"version":3,"file":"url-builder.d.ts","sourceRoot":"","sources":["../../../src/adapter/expr/url-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAEL,KAAK,UAAU,EAIhB,MAAM,iBAAiB,CAAA;AAExB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAkDvD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,aAAa,EAClB,IAAI,EAAE,UAAU,EAChB,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,UAAU,GACpB,MAAM,CAGR;AAoCD;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,aAAa,EAClB,MAAM,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,UAAU,GACrB,MAAM,GAAG,IAAI,CAmBf"}
|
|
@@ -593,7 +593,7 @@ export declare class GoTemplateAdapter extends BaseAdapter implements ParsedExpr
|
|
|
593
593
|
* the `interface{}` flip in `resolvePropGoType`.
|
|
594
594
|
*/
|
|
595
595
|
private nillablePropNameOf;
|
|
596
|
-
conditional(test: ParsedExpr, consequent: ParsedExpr, alternate: ParsedExpr,
|
|
596
|
+
conditional(test: ParsedExpr, consequent: ParsedExpr, alternate: ParsedExpr, _emit: (e: ParsedExpr) => string): string;
|
|
597
597
|
templateLiteral(parts: TemplatePart[], emit: (e: ParsedExpr) => string): string;
|
|
598
598
|
arrow(params: string[], _body: ParsedExpr, _emit: (e: ParsedExpr) => string): string;
|
|
599
599
|
regex(raw: string): string;
|
|
@@ -735,12 +735,6 @@ export declare class GoTemplateAdapter extends BaseAdapter implements ParsedExpr
|
|
|
735
735
|
* parentheses around it).
|
|
736
736
|
*/
|
|
737
737
|
private isGoFunctionCall;
|
|
738
|
-
/**
|
|
739
|
-
* Render a branch of a conditional expression. String literals render as bare
|
|
740
|
-
* text (no quotes); nested conditionals render as complete `{{if}}…{{end}}`
|
|
741
|
-
* blocks; everything else is wrapped in `{{...}}`.
|
|
742
|
-
*/
|
|
743
|
-
private renderConditionalBranch;
|
|
744
738
|
/**
|
|
745
739
|
* Whether a ParsedExpr renders to a Go template function call (`len .X`,
|
|
746
740
|
* `bf_add .A .B`) that needs parentheses when used as an argument to a
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"go-template-adapter.d.ts","sourceRoot":"","sources":["../../src/adapter/go-template-adapter.ts"],"names":[],"mappings":"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
|
|
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
|
@@ -913,6 +913,21 @@ function lowerUrlGuard(ctx, g) {
|
|
|
913
913
|
const valueGo = wrapIfMultiToken(ctx.convertExpressionToGo(stringifyParsedExpr(g), undefined, g));
|
|
914
914
|
return `ne ${valueGo} ""`;
|
|
915
915
|
}
|
|
916
|
+
function lowerTernary(ctx, test, consequent, alternate) {
|
|
917
|
+
const t = lowerTernaryTest(ctx, test);
|
|
918
|
+
return `(bf_ternary ${t} ${lowerTernaryOperand(ctx, consequent)} ${lowerTernaryOperand(ctx, alternate)})`;
|
|
919
|
+
}
|
|
920
|
+
function lowerTernaryOperand(ctx, n) {
|
|
921
|
+
if (n.kind === "conditional") {
|
|
922
|
+
return lowerTernary(ctx, n.test, n.consequent, n.alternate);
|
|
923
|
+
}
|
|
924
|
+
return wrapIfMultiToken(ctx.convertExpressionToGo(stringifyParsedExpr(n), undefined, n));
|
|
925
|
+
}
|
|
926
|
+
function lowerTernaryTest(ctx, test) {
|
|
927
|
+
const go = wrapIfMultiToken(ctx.convertExpressionToGo(stringifyParsedExpr(test), undefined, test));
|
|
928
|
+
const isBoolShape = test.kind === "binary" && BOOL_COMPARISON_OPS.has(test.op) || test.kind === "unary" && test.op === "!" || test.kind === "literal" && test.literalType === "boolean";
|
|
929
|
+
return isBoolShape ? go : `(bf_truthy ${go})`;
|
|
930
|
+
}
|
|
916
931
|
function lowerRegisteredCall(ctx, jsExpr, preParsed) {
|
|
917
932
|
const matchers = ctx.state.loweringMatchers;
|
|
918
933
|
if (matchers.length === 0)
|
|
@@ -941,8 +956,9 @@ function renderLoweringNode(ctx, node) {
|
|
|
941
956
|
if (!helper)
|
|
942
957
|
return null;
|
|
943
958
|
const lowerExpr = (n) => ctx.convertExpressionToGo(stringifyParsedExpr(n), undefined, n);
|
|
959
|
+
const lowerArg = (n) => n.kind === "conditional" ? lowerTernary(ctx, n.test, n.consequent, n.alternate) : wrapIfMultiToken(lowerExpr(n));
|
|
944
960
|
if (node.kind === "helper-call") {
|
|
945
|
-
const args = node.args.map((a) =>
|
|
961
|
+
const args = node.args.map((a) => lowerArg(a));
|
|
946
962
|
return [helper, ...args].join(" ");
|
|
947
963
|
}
|
|
948
964
|
const parts = [wrapIfMultiToken(lowerExpr(node.base))];
|
|
@@ -4677,11 +4693,8 @@ ${goFields.join(`
|
|
|
4677
4693
|
}
|
|
4678
4694
|
return name !== null && this.state.nullishConsumedPropNames.has(name) && this.state.nillablePropNames.has(name) ? name : null;
|
|
4679
4695
|
}
|
|
4680
|
-
conditional(test, consequent, alternate,
|
|
4681
|
-
|
|
4682
|
-
const c = this.renderConditionalBranch(consequent);
|
|
4683
|
-
const a = this.renderConditionalBranch(alternate);
|
|
4684
|
-
return `{{if ${t}}}${c}{{else}}${a}{{end}}`;
|
|
4696
|
+
conditional(test, consequent, alternate, _emit) {
|
|
4697
|
+
return lowerTernary(this.emitCtx, test, consequent, alternate);
|
|
4685
4698
|
}
|
|
4686
4699
|
templateLiteral(parts, emit) {
|
|
4687
4700
|
let result = "";
|
|
@@ -5278,18 +5291,6 @@ ${goFields.join(`
|
|
|
5278
5291
|
return false;
|
|
5279
5292
|
}
|
|
5280
5293
|
}
|
|
5281
|
-
renderConditionalBranch(expr) {
|
|
5282
|
-
if (expr.kind === "literal" && expr.literalType === "string") {
|
|
5283
|
-
return String(expr.value);
|
|
5284
|
-
}
|
|
5285
|
-
if (expr.kind === "conditional") {
|
|
5286
|
-
const test = this.renderParsedExpr(expr.test);
|
|
5287
|
-
const consequent = this.renderConditionalBranch(expr.consequent);
|
|
5288
|
-
const alternate = this.renderConditionalBranch(expr.alternate);
|
|
5289
|
-
return `{{if ${test}}}${consequent}{{else}}${alternate}{{end}}`;
|
|
5290
|
-
}
|
|
5291
|
-
return `{{${this.renderParsedExpr(expr)}}}`;
|
|
5292
|
-
}
|
|
5293
5294
|
needsParensInGoTemplate(expr) {
|
|
5294
5295
|
switch (expr.kind) {
|
|
5295
5296
|
case "member":
|
|
@@ -5644,8 +5645,7 @@ ${goFields.join(`
|
|
|
5644
5645
|
return { preamble, expr: result };
|
|
5645
5646
|
}
|
|
5646
5647
|
case "conditional": {
|
|
5647
|
-
|
|
5648
|
-
return test;
|
|
5648
|
+
return plain(lowerTernary(this.emitCtx, expr.test, expr.consequent, expr.alternate));
|
|
5649
5649
|
}
|
|
5650
5650
|
case "template-literal":
|
|
5651
5651
|
return plain(this.renderParsedExpr(expr));
|
|
@@ -5995,7 +5995,7 @@ ${children}`;
|
|
|
5995
5995
|
const body = `${name}="{{${valueExpr}}}"`;
|
|
5996
5996
|
return `${preamble}{{if ${goCond}}}${body}{{end}}`;
|
|
5997
5997
|
}
|
|
5998
|
-
return `${name}="${this.renderParsedExpr(parsed)}"`;
|
|
5998
|
+
return `${name}="{{${this.renderParsedExpr(parsed)}}}"`;
|
|
5999
5999
|
}
|
|
6000
6000
|
if (parsed.kind === "template-literal") {
|
|
6001
6001
|
return `${name}="${this.renderParsedExpr(parsed)}"`;
|
package/dist/build.js
CHANGED
|
@@ -1253,6 +1253,21 @@ function lowerUrlGuard(ctx, g) {
|
|
|
1253
1253
|
const valueGo = wrapIfMultiToken(ctx.convertExpressionToGo(stringifyParsedExpr(g), undefined, g));
|
|
1254
1254
|
return `ne ${valueGo} ""`;
|
|
1255
1255
|
}
|
|
1256
|
+
function lowerTernary(ctx, test, consequent, alternate) {
|
|
1257
|
+
const t = lowerTernaryTest(ctx, test);
|
|
1258
|
+
return `(bf_ternary ${t} ${lowerTernaryOperand(ctx, consequent)} ${lowerTernaryOperand(ctx, alternate)})`;
|
|
1259
|
+
}
|
|
1260
|
+
function lowerTernaryOperand(ctx, n) {
|
|
1261
|
+
if (n.kind === "conditional") {
|
|
1262
|
+
return lowerTernary(ctx, n.test, n.consequent, n.alternate);
|
|
1263
|
+
}
|
|
1264
|
+
return wrapIfMultiToken(ctx.convertExpressionToGo(stringifyParsedExpr(n), undefined, n));
|
|
1265
|
+
}
|
|
1266
|
+
function lowerTernaryTest(ctx, test) {
|
|
1267
|
+
const go = wrapIfMultiToken(ctx.convertExpressionToGo(stringifyParsedExpr(test), undefined, test));
|
|
1268
|
+
const isBoolShape = test.kind === "binary" && BOOL_COMPARISON_OPS.has(test.op) || test.kind === "unary" && test.op === "!" || test.kind === "literal" && test.literalType === "boolean";
|
|
1269
|
+
return isBoolShape ? go : `(bf_truthy ${go})`;
|
|
1270
|
+
}
|
|
1256
1271
|
function lowerRegisteredCall(ctx, jsExpr, preParsed) {
|
|
1257
1272
|
const matchers = ctx.state.loweringMatchers;
|
|
1258
1273
|
if (matchers.length === 0)
|
|
@@ -1281,8 +1296,9 @@ function renderLoweringNode(ctx, node) {
|
|
|
1281
1296
|
if (!helper)
|
|
1282
1297
|
return null;
|
|
1283
1298
|
const lowerExpr = (n) => ctx.convertExpressionToGo(stringifyParsedExpr(n), undefined, n);
|
|
1299
|
+
const lowerArg = (n) => n.kind === "conditional" ? lowerTernary(ctx, n.test, n.consequent, n.alternate) : wrapIfMultiToken(lowerExpr(n));
|
|
1284
1300
|
if (node.kind === "helper-call") {
|
|
1285
|
-
const args = node.args.map((a) =>
|
|
1301
|
+
const args = node.args.map((a) => lowerArg(a));
|
|
1286
1302
|
return [helper, ...args].join(" ");
|
|
1287
1303
|
}
|
|
1288
1304
|
const parts = [wrapIfMultiToken(lowerExpr(node.base))];
|
|
@@ -5017,11 +5033,8 @@ ${goFields.join(`
|
|
|
5017
5033
|
}
|
|
5018
5034
|
return name !== null && this.state.nullishConsumedPropNames.has(name) && this.state.nillablePropNames.has(name) ? name : null;
|
|
5019
5035
|
}
|
|
5020
|
-
conditional(test, consequent, alternate,
|
|
5021
|
-
|
|
5022
|
-
const c = this.renderConditionalBranch(consequent);
|
|
5023
|
-
const a = this.renderConditionalBranch(alternate);
|
|
5024
|
-
return `{{if ${t}}}${c}{{else}}${a}{{end}}`;
|
|
5036
|
+
conditional(test, consequent, alternate, _emit) {
|
|
5037
|
+
return lowerTernary(this.emitCtx, test, consequent, alternate);
|
|
5025
5038
|
}
|
|
5026
5039
|
templateLiteral(parts, emit) {
|
|
5027
5040
|
let result = "";
|
|
@@ -5618,18 +5631,6 @@ ${goFields.join(`
|
|
|
5618
5631
|
return false;
|
|
5619
5632
|
}
|
|
5620
5633
|
}
|
|
5621
|
-
renderConditionalBranch(expr) {
|
|
5622
|
-
if (expr.kind === "literal" && expr.literalType === "string") {
|
|
5623
|
-
return String(expr.value);
|
|
5624
|
-
}
|
|
5625
|
-
if (expr.kind === "conditional") {
|
|
5626
|
-
const test = this.renderParsedExpr(expr.test);
|
|
5627
|
-
const consequent = this.renderConditionalBranch(expr.consequent);
|
|
5628
|
-
const alternate = this.renderConditionalBranch(expr.alternate);
|
|
5629
|
-
return `{{if ${test}}}${consequent}{{else}}${alternate}{{end}}`;
|
|
5630
|
-
}
|
|
5631
|
-
return `{{${this.renderParsedExpr(expr)}}}`;
|
|
5632
|
-
}
|
|
5633
5634
|
needsParensInGoTemplate(expr) {
|
|
5634
5635
|
switch (expr.kind) {
|
|
5635
5636
|
case "member":
|
|
@@ -5984,8 +5985,7 @@ ${goFields.join(`
|
|
|
5984
5985
|
return { preamble, expr: result };
|
|
5985
5986
|
}
|
|
5986
5987
|
case "conditional": {
|
|
5987
|
-
|
|
5988
|
-
return test;
|
|
5988
|
+
return plain(lowerTernary(this.emitCtx, expr.test, expr.consequent, expr.alternate));
|
|
5989
5989
|
}
|
|
5990
5990
|
case "template-literal":
|
|
5991
5991
|
return plain(this.renderParsedExpr(expr));
|
|
@@ -6335,7 +6335,7 @@ ${children}`;
|
|
|
6335
6335
|
const body = `${name}="{{${valueExpr}}}"`;
|
|
6336
6336
|
return `${preamble}{{if ${goCond}}}${body}{{end}}`;
|
|
6337
6337
|
}
|
|
6338
|
-
return `${name}="${this.renderParsedExpr(parsed)}"`;
|
|
6338
|
+
return `${name}="{{${this.renderParsedExpr(parsed)}}}"`;
|
|
6339
6339
|
}
|
|
6340
6340
|
if (parsed.kind === "template-literal") {
|
|
6341
6341
|
return `${name}="${this.renderParsedExpr(parsed)}"`;
|
package/dist/index.js
CHANGED
|
@@ -913,6 +913,21 @@ function lowerUrlGuard(ctx, g) {
|
|
|
913
913
|
const valueGo = wrapIfMultiToken(ctx.convertExpressionToGo(stringifyParsedExpr(g), undefined, g));
|
|
914
914
|
return `ne ${valueGo} ""`;
|
|
915
915
|
}
|
|
916
|
+
function lowerTernary(ctx, test, consequent, alternate) {
|
|
917
|
+
const t = lowerTernaryTest(ctx, test);
|
|
918
|
+
return `(bf_ternary ${t} ${lowerTernaryOperand(ctx, consequent)} ${lowerTernaryOperand(ctx, alternate)})`;
|
|
919
|
+
}
|
|
920
|
+
function lowerTernaryOperand(ctx, n) {
|
|
921
|
+
if (n.kind === "conditional") {
|
|
922
|
+
return lowerTernary(ctx, n.test, n.consequent, n.alternate);
|
|
923
|
+
}
|
|
924
|
+
return wrapIfMultiToken(ctx.convertExpressionToGo(stringifyParsedExpr(n), undefined, n));
|
|
925
|
+
}
|
|
926
|
+
function lowerTernaryTest(ctx, test) {
|
|
927
|
+
const go = wrapIfMultiToken(ctx.convertExpressionToGo(stringifyParsedExpr(test), undefined, test));
|
|
928
|
+
const isBoolShape = test.kind === "binary" && BOOL_COMPARISON_OPS.has(test.op) || test.kind === "unary" && test.op === "!" || test.kind === "literal" && test.literalType === "boolean";
|
|
929
|
+
return isBoolShape ? go : `(bf_truthy ${go})`;
|
|
930
|
+
}
|
|
916
931
|
function lowerRegisteredCall(ctx, jsExpr, preParsed) {
|
|
917
932
|
const matchers = ctx.state.loweringMatchers;
|
|
918
933
|
if (matchers.length === 0)
|
|
@@ -941,8 +956,9 @@ function renderLoweringNode(ctx, node) {
|
|
|
941
956
|
if (!helper)
|
|
942
957
|
return null;
|
|
943
958
|
const lowerExpr = (n) => ctx.convertExpressionToGo(stringifyParsedExpr(n), undefined, n);
|
|
959
|
+
const lowerArg = (n) => n.kind === "conditional" ? lowerTernary(ctx, n.test, n.consequent, n.alternate) : wrapIfMultiToken(lowerExpr(n));
|
|
944
960
|
if (node.kind === "helper-call") {
|
|
945
|
-
const args = node.args.map((a) =>
|
|
961
|
+
const args = node.args.map((a) => lowerArg(a));
|
|
946
962
|
return [helper, ...args].join(" ");
|
|
947
963
|
}
|
|
948
964
|
const parts = [wrapIfMultiToken(lowerExpr(node.base))];
|
|
@@ -4677,11 +4693,8 @@ ${goFields.join(`
|
|
|
4677
4693
|
}
|
|
4678
4694
|
return name !== null && this.state.nullishConsumedPropNames.has(name) && this.state.nillablePropNames.has(name) ? name : null;
|
|
4679
4695
|
}
|
|
4680
|
-
conditional(test, consequent, alternate,
|
|
4681
|
-
|
|
4682
|
-
const c = this.renderConditionalBranch(consequent);
|
|
4683
|
-
const a = this.renderConditionalBranch(alternate);
|
|
4684
|
-
return `{{if ${t}}}${c}{{else}}${a}{{end}}`;
|
|
4696
|
+
conditional(test, consequent, alternate, _emit) {
|
|
4697
|
+
return lowerTernary(this.emitCtx, test, consequent, alternate);
|
|
4685
4698
|
}
|
|
4686
4699
|
templateLiteral(parts, emit) {
|
|
4687
4700
|
let result = "";
|
|
@@ -5278,18 +5291,6 @@ ${goFields.join(`
|
|
|
5278
5291
|
return false;
|
|
5279
5292
|
}
|
|
5280
5293
|
}
|
|
5281
|
-
renderConditionalBranch(expr) {
|
|
5282
|
-
if (expr.kind === "literal" && expr.literalType === "string") {
|
|
5283
|
-
return String(expr.value);
|
|
5284
|
-
}
|
|
5285
|
-
if (expr.kind === "conditional") {
|
|
5286
|
-
const test = this.renderParsedExpr(expr.test);
|
|
5287
|
-
const consequent = this.renderConditionalBranch(expr.consequent);
|
|
5288
|
-
const alternate = this.renderConditionalBranch(expr.alternate);
|
|
5289
|
-
return `{{if ${test}}}${consequent}{{else}}${alternate}{{end}}`;
|
|
5290
|
-
}
|
|
5291
|
-
return `{{${this.renderParsedExpr(expr)}}}`;
|
|
5292
|
-
}
|
|
5293
5294
|
needsParensInGoTemplate(expr) {
|
|
5294
5295
|
switch (expr.kind) {
|
|
5295
5296
|
case "member":
|
|
@@ -5644,8 +5645,7 @@ ${goFields.join(`
|
|
|
5644
5645
|
return { preamble, expr: result };
|
|
5645
5646
|
}
|
|
5646
5647
|
case "conditional": {
|
|
5647
|
-
|
|
5648
|
-
return test;
|
|
5648
|
+
return plain(lowerTernary(this.emitCtx, expr.test, expr.consequent, expr.alternate));
|
|
5649
5649
|
}
|
|
5650
5650
|
case "template-literal":
|
|
5651
5651
|
return plain(this.renderParsedExpr(expr));
|
|
@@ -5995,7 +5995,7 @@ ${children}`;
|
|
|
5995
5995
|
const body = `${name}="{{${valueExpr}}}"`;
|
|
5996
5996
|
return `${preamble}{{if ${goCond}}}${body}{{end}}`;
|
|
5997
5997
|
}
|
|
5998
|
-
return `${name}="${this.renderParsedExpr(parsed)}"`;
|
|
5998
|
+
return `${name}="{{${this.renderParsedExpr(parsed)}}}"`;
|
|
5999
5999
|
}
|
|
6000
6000
|
if (parsed.kind === "template-literal") {
|
|
6001
6001
|
return `${name}="${this.renderParsedExpr(parsed)}"`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@barefootjs/go-template",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.0",
|
|
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",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"directory": "packages/adapter-go-template"
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@barefootjs/shared": "0.
|
|
52
|
+
"@barefootjs/shared": "0.25.0"
|
|
53
53
|
},
|
|
54
54
|
"peerDependencies": {
|
|
55
55
|
"@barefootjs/jsx": ">=0.2.0",
|
|
@@ -57,6 +57,6 @@
|
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
59
|
"@barefootjs/adapter-tests": "0.1.0",
|
|
60
|
-
"@barefootjs/jsx": "0.
|
|
60
|
+
"@barefootjs/jsx": "0.25.0"
|
|
61
61
|
}
|
|
62
62
|
}
|
|
@@ -133,10 +133,11 @@ export function P() {
|
|
|
133
133
|
`
|
|
134
134
|
const { template } = generate(src)
|
|
135
135
|
expect(template).not.toContain('.SortClass')
|
|
136
|
-
//
|
|
137
|
-
// `
|
|
136
|
+
// The inlined ternary lowers to the pipeline `bf_ternary` (#2335), not an
|
|
137
|
+
// `{{if}}…{{end}}` fragment. `.Params.Sort` is interface{} (a map value),
|
|
138
|
+
// so `eq` coerces it via `bf_string` before comparing to the string literal.
|
|
138
139
|
expect(template).toContain(
|
|
139
|
-
'class="{{
|
|
140
|
+
'class="{{(bf_ternary (eq (bf_string .Params.Sort) "date") "sort on" "sort")}}"',
|
|
140
141
|
)
|
|
141
142
|
})
|
|
142
143
|
|
|
@@ -156,8 +157,9 @@ export function P(props: { tags: string[] }) {
|
|
|
156
157
|
`
|
|
157
158
|
const { template } = generate(src)
|
|
158
159
|
expect(template).not.toContain('.TagClass')
|
|
159
|
-
// params() is a root memo (→ $.Params) and t is the loop var (→ .)
|
|
160
|
-
|
|
160
|
+
// params() is a root memo (→ $.Params) and t is the loop var (→ .); the
|
|
161
|
+
// inlined ternary lowers to the pipeline `bf_ternary` (#2335).
|
|
162
|
+
expect(template).toContain('{{(bf_ternary (eq $.Params.Tag .) "tag on" "tag")}}')
|
|
161
163
|
})
|
|
162
164
|
|
|
163
165
|
test('a helper that delegates to a non-URL-builder local helper is not inlined', () => {
|
|
@@ -192,12 +194,15 @@ export function P(props: { a?: string; b?: string }) {
|
|
|
192
194
|
`
|
|
193
195
|
const { template } = generate(src)
|
|
194
196
|
expect(template).not.toContain('.Cls')
|
|
195
|
-
//
|
|
196
|
-
//
|
|
197
|
-
// `
|
|
198
|
-
//
|
|
199
|
-
|
|
200
|
-
|
|
197
|
+
// The inlined ternary lowers to the pipeline `bf_ternary` (#2335), so the
|
|
198
|
+
// test sits in `bf_ternary`'s first argument. `===` must stay the outer
|
|
199
|
+
// operation there (`eq .Sig …`). Without parenthesizing the arg,
|
|
200
|
+
// `sig() === props.a ?? props.b` would bind as
|
|
201
|
+
// `(sig() === props.a) ?? props.b` → a `bf_nullish`/`or`-rooted test. This
|
|
202
|
+
// matches what a direct `sig() === (props.a ?? props.b)` lowers to.
|
|
203
|
+
expect(template).toContain('(bf_ternary (eq .Sig')
|
|
204
|
+
expect(template).not.toContain('(bf_ternary (bf_nullish')
|
|
205
|
+
expect(template).not.toContain('(bf_ternary (or')
|
|
201
206
|
})
|
|
202
207
|
|
|
203
208
|
// The splicer is scope-blind, so a helper whose body contains a nested
|
|
@@ -299,16 +299,21 @@ export function Label() {
|
|
|
299
299
|
// template literals off their parsed kind. That is correct because of a
|
|
300
300
|
// load-bearing invariant: a template literal is the *only* expression form that
|
|
301
301
|
// interleaves author literal text with `{{...}}` actions, so every OTHER
|
|
302
|
-
// fragment producer (
|
|
303
|
-
//
|
|
304
|
-
//
|
|
305
|
-
//
|
|
306
|
-
//
|
|
307
|
-
//
|
|
302
|
+
// fragment producer (find().prop, filter().length, …) emits a pure action block
|
|
303
|
+
// that begins with `{{`. These tests pin that invariant: if a future emitter
|
|
304
|
+
// prepends literal text to an action block, its output stops starting with
|
|
305
|
+
// `{{`, this fails, and the fix is to give that shape a parsed kind
|
|
306
|
+
// `isTemplateFragment` can detect (as template literals are handled) — NOT to
|
|
307
|
+
// fall back to a fragile `{{` substring scan.
|
|
308
|
+
//
|
|
309
|
+
// Ternary is deliberately NOT in this list: as of #2335 a value-position
|
|
310
|
+
// ternary lowers to the pipeline `(bf_ternary …)`, NOT a `{{if}}…{{end}}`
|
|
311
|
+
// fragment, so it is wrapped by the normal expression path like any other
|
|
312
|
+
// pipeline — it is no longer a self-contained action block. See the
|
|
313
|
+
// `bf_ternary value-position lowering` describe below.
|
|
308
314
|
describe('GoTemplateAdapter - template-fragment invariant (#1937)', () => {
|
|
309
315
|
const adapter = new GoTemplateAdapter()
|
|
310
316
|
const blockProducers: [string, string][] = [
|
|
311
|
-
['ternary', "flag ? 'a' : 'b'"],
|
|
312
317
|
['find().prop', 'items.find(i => i.active).name'],
|
|
313
318
|
['findLast().prop', 'items.findLast(i => i.active).name'],
|
|
314
319
|
['filter().length', 'items.filter(i => i.active).length'],
|
|
@@ -321,6 +326,90 @@ describe('GoTemplateAdapter - template-fragment invariant (#1937)', () => {
|
|
|
321
326
|
}
|
|
322
327
|
})
|
|
323
328
|
|
|
329
|
+
// #2335: Go `text/template` has no expression-level conditional, so every
|
|
330
|
+
// VALUE-position ternary lowers to the pipeline `(bf_ternary <test> <a> <b>)`
|
|
331
|
+
// runtime helper — the SAME form helper-call args already used (#2331) — rather
|
|
332
|
+
// than a text-position `{{if}}…{{end}}` action fragment. `Ternary`'s `cond`
|
|
333
|
+
// parameter is a strict `bool` (not `{{if}}`-style truthiness), so a
|
|
334
|
+
// non-comparison test is wrapped `bf_truthy <value>` (JS `Boolean(x)`).
|
|
335
|
+
describe('GoTemplateAdapter - bf_ternary value-position lowering (#2335)', () => {
|
|
336
|
+
const adapter = new GoTemplateAdapter()
|
|
337
|
+
const render = (expr: string) => adapter.renderExpression({ expr } as IRExpression)
|
|
338
|
+
|
|
339
|
+
test('a bare-value (non-comparison) test is truthiness-wrapped with bf_truthy', () => {
|
|
340
|
+
// `.Flag`'s Go type is unknown at emit time — `bf_truthy` coerces string /
|
|
341
|
+
// number / bool / nil uniformly, where `{{if}}` truthiness used to.
|
|
342
|
+
expect(render("flag ? 'a' : 'b'")).toBe('{{(bf_ternary (bf_truthy .Flag) "a" "b")}}')
|
|
343
|
+
})
|
|
344
|
+
|
|
345
|
+
test('a comparison test is already a bool — no bf_truthy wrap', () => {
|
|
346
|
+
expect(render("n >= 10 ? 'big' : 'small'")).toBe('{{(bf_ternary (ge .N 10) "big" "small")}}')
|
|
347
|
+
})
|
|
348
|
+
|
|
349
|
+
test('a negation test is already a bool — no bf_truthy wrap', () => {
|
|
350
|
+
expect(render("!open ? 'x' : 'y'")).toBe('{{(bf_ternary (not .Open) "x" "y")}}')
|
|
351
|
+
})
|
|
352
|
+
|
|
353
|
+
test('a right-folded chain nests as (bf_ternary … (bf_ternary …))', () => {
|
|
354
|
+
expect(render("a ? 'x' : b ? 'y' : 'z'")).toBe(
|
|
355
|
+
'{{(bf_ternary (bf_truthy .A) "x" (bf_ternary (bf_truthy .B) "y" "z"))}}',
|
|
356
|
+
)
|
|
357
|
+
})
|
|
358
|
+
|
|
359
|
+
test('nested inside a template literal, it is wrapped once (not a raw fragment)', () => {
|
|
360
|
+
// The ternary is no longer `{{`-leading, so the template-literal emitter
|
|
361
|
+
// wraps it in a single `{{…}}` alongside the literal text.
|
|
362
|
+
expect(render("`btn ${active ? 'on' : 'off'}`")).toBe(
|
|
363
|
+
'btn {{(bf_ternary (bf_truthy .Active) "on" "off")}}',
|
|
364
|
+
)
|
|
365
|
+
})
|
|
366
|
+
|
|
367
|
+
test('emits no {{if}} action fragment for a value-position ternary', () => {
|
|
368
|
+
expect(render("flag ? 'a' : 'b'")).not.toContain('{{if')
|
|
369
|
+
})
|
|
370
|
+
})
|
|
371
|
+
|
|
372
|
+
// #2335 item 2 (correctness): a ternary used as a boolean CONDITION used to
|
|
373
|
+
// return only its lowered `test`, silently discarding both branches. It now
|
|
374
|
+
// lowers faithfully to `(bf_ternary …)`, truthiness-checked by the enclosing
|
|
375
|
+
// `{{if}}`. Rendered-output parity is pinned by the `condition-position-ternary`
|
|
376
|
+
// conformance fixture; this pins the template SOURCE shape.
|
|
377
|
+
describe('GoTemplateAdapter - bf_ternary condition-position lowering (#2335)', () => {
|
|
378
|
+
test('a ternary sub-condition keeps both branches inside the {{if}} test', () => {
|
|
379
|
+
const { template } = compileAndGenerate(`
|
|
380
|
+
'use client'
|
|
381
|
+
import { createSignal } from '@barefootjs/client'
|
|
382
|
+
export function P() {
|
|
383
|
+
const [mode, setMode] = createSignal('a')
|
|
384
|
+
const [show, setShow] = createSignal(true)
|
|
385
|
+
const [hide, setHide] = createSignal(false)
|
|
386
|
+
return <div>{(mode() === 'a' ? show() : hide()) ? <span>Y</span> : <span>N</span>}</div>
|
|
387
|
+
}
|
|
388
|
+
`)
|
|
389
|
+
expect(template).toContain('{{if (bf_ternary (eq (bf_string .Mode) "a") .Show .Hide)}}')
|
|
390
|
+
// The old bug collapsed the condition to just the test — assert we no
|
|
391
|
+
// longer emit the branch-discarding `{{if (eq (bf_string .Mode) "a")}}`.
|
|
392
|
+
expect(template).not.toContain('{{if (eq (bf_string .Mode) "a")}}')
|
|
393
|
+
})
|
|
394
|
+
})
|
|
395
|
+
|
|
396
|
+
// #2335 item 3 (cleanup): an attribute-value ternary reached through the
|
|
397
|
+
// ParsedExpr `conditional` emitter lowers to a single `{{bf_ternary …}}` action
|
|
398
|
+
// inside the attribute string, not an inline `{{if}}…{{end}}` fragment.
|
|
399
|
+
describe('GoTemplateAdapter - bf_ternary attribute-position lowering (#2335)', () => {
|
|
400
|
+
test('a numeric-branch attr ternary emits name="{{bf_ternary …}}"', () => {
|
|
401
|
+
const { template } = compileAndGenerate(`
|
|
402
|
+
'use client'
|
|
403
|
+
import { createSignal } from '@barefootjs/client'
|
|
404
|
+
export function P() {
|
|
405
|
+
const [active, setActive] = createSignal(false)
|
|
406
|
+
return <button data-step={active() ? 2 : 1}>x</button>
|
|
407
|
+
}
|
|
408
|
+
`)
|
|
409
|
+
expect(template).toContain('data-step="{{(bf_ternary (bf_truthy .Active) 2 1)}}"')
|
|
410
|
+
})
|
|
411
|
+
})
|
|
412
|
+
|
|
324
413
|
describe('GoTemplateAdapter - Adapter Specific', () => {
|
|
325
414
|
describe('generate - Go struct types', () => {
|
|
326
415
|
test('deduplicates struct field when signal name matches prop name (#461)', () => {
|
|
@@ -592,6 +681,26 @@ export function Check(props: { checked?: boolean }) {
|
|
|
592
681
|
expect(types).toContain('C: checked,')
|
|
593
682
|
})
|
|
594
683
|
|
|
684
|
+
test('flips a bare TEXT-POSITION optional scalar prop to interface{} (#2267)', () => {
|
|
685
|
+
// The trigger nobody pinned directly until #2327: an optional
|
|
686
|
+
// no-default primitive consumed as bare `{props.X}` text (no `??`, no
|
|
687
|
+
// omittable attribute, no presence check) flips to interface{} so an
|
|
688
|
+
// absent prop renders '' like JS undefined instead of the Go zero
|
|
689
|
+
// value / `<no value>`. This is the exact shape behind
|
|
690
|
+
// integrations' PostArticle prevTitle/nextTitle — the regen drift
|
|
691
|
+
// #2327 tracked. The required sibling stays a concrete string.
|
|
692
|
+
const adapter = new GoTemplateAdapter()
|
|
693
|
+
const ir = compileToIR(`
|
|
694
|
+
export function Pager(props: { prevSlug: string; prevTitle?: string }) {
|
|
695
|
+
return <div>{props.prevSlug ? <a>{props.prevTitle}</a> : ''}</div>
|
|
696
|
+
}
|
|
697
|
+
`)
|
|
698
|
+
const result = adapter.generate(ir)
|
|
699
|
+
const types = result.types!
|
|
700
|
+
expect(types).toContain('PrevTitle interface{}')
|
|
701
|
+
expect(types).toContain('PrevSlug string')
|
|
702
|
+
})
|
|
703
|
+
|
|
595
704
|
test('hoists the DESTRUCTURED `x ?? N` seed via signal.parsed (#2259)', () => {
|
|
596
705
|
// Destructured components have no `propsObjectName`, so the seed's
|
|
597
706
|
// prop reference is a bare identifier — matched structurally on the
|
|
@@ -162,4 +162,24 @@ export function P(props: { config: object }) {
|
|
|
162
162
|
const { template } = generate(src)
|
|
163
163
|
expect(template).not.toContain('bf_custom_serialize')
|
|
164
164
|
})
|
|
165
|
+
|
|
166
|
+
test('a CONDITIONAL helper-call arg renders as pipeline-position bf_ternary, not an {{if}} action', () => {
|
|
167
|
+
// The #2324 union stage lowers a union-typed locale to a ternary
|
|
168
|
+
// pattern arg. Go templates have no expression-level conditional, and
|
|
169
|
+
// the generic emitter's `conditional` produces an `{{if}}…{{end}}`
|
|
170
|
+
// action FRAGMENT — a parse error inside a pipeline ("unexpected { in
|
|
171
|
+
// parenthesized pipeline", the exact CI failure this pins). Argument
|
|
172
|
+
// position must route through the bf_ternary runtime helper instead.
|
|
173
|
+
const src = `
|
|
174
|
+
function P({ createdAt, locale }: { createdAt: Date; locale: 'en-US' | 'ja-JP' }) {
|
|
175
|
+
return <time>{createdAt.toLocaleDateString(locale, { timeZone: 'UTC' })}</time>
|
|
176
|
+
}
|
|
177
|
+
export { P }
|
|
178
|
+
`
|
|
179
|
+
const { template } = generate(src)
|
|
180
|
+
expect(template).toContain(
|
|
181
|
+
'bf_format_date .CreatedAt (bf_ternary (eq (bf_string .Locale) "en-US") "M/D/YYYY" "YYYY/M/D") "UTC"',
|
|
182
|
+
)
|
|
183
|
+
expect(template).not.toContain('({{if')
|
|
184
|
+
})
|
|
165
185
|
})
|
|
@@ -65,6 +65,69 @@ function lowerUrlGuard(ctx: GoEmitContext, g: ParsedExpr): string {
|
|
|
65
65
|
return `ne ${valueGo} ""`
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
/**
|
|
69
|
+
* Lower a `conditional` (ternary) ParsedExpr to the pipeline-position
|
|
70
|
+
* `(bf_ternary <test> <consequent> <alternate>)` form (#2335). Go
|
|
71
|
+
* `text/template` is the only backend without an expression-level
|
|
72
|
+
* conditional, so a ternary sitting in VALUE position — a helper-call arg, a
|
|
73
|
+
* template-literal interpolation, an attribute value, or a boolean
|
|
74
|
+
* sub-condition — cannot be an `{{if}}…{{end}}` action fragment (a parse error
|
|
75
|
+
* inside a pipeline, and a silent branch-discard in condition position). This
|
|
76
|
+
* is the single lowering every such position shares; each caller passes the
|
|
77
|
+
* ternary's three child nodes directly (the ParsedExpr emitter hands them over
|
|
78
|
+
* unwrapped).
|
|
79
|
+
*
|
|
80
|
+
* - branches are quoted VALUES, recursing so a right-folded chain
|
|
81
|
+
* (`a ? x : b ? y : z`) nests as `(bf_ternary … (bf_ternary …))`.
|
|
82
|
+
* - the test is coerced to a real Go `bool` (see `lowerTernaryTest`).
|
|
83
|
+
*
|
|
84
|
+
* NOT for the text-position `IRConditional` (`renderConditional`), whose
|
|
85
|
+
* branches are arbitrary markup, not values.
|
|
86
|
+
*/
|
|
87
|
+
export function lowerTernary(
|
|
88
|
+
ctx: GoEmitContext,
|
|
89
|
+
test: ParsedExpr,
|
|
90
|
+
consequent: ParsedExpr,
|
|
91
|
+
alternate: ParsedExpr,
|
|
92
|
+
): string {
|
|
93
|
+
const t = lowerTernaryTest(ctx, test)
|
|
94
|
+
return `(bf_ternary ${t} ${lowerTernaryOperand(ctx, consequent)} ${lowerTernaryOperand(ctx, alternate)})`
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* A ternary branch in value position: a nested ternary recurses to another
|
|
99
|
+
* `bf_ternary`; anything else lowers to its Go value (parenthesised when
|
|
100
|
+
* multi-token so it stays one argument). String branches become quoted,
|
|
101
|
+
* html/template-escaped values — not the bare unquoted text the old `{{if}}`
|
|
102
|
+
* fragment path emitted — which is exactly right for the value positions this
|
|
103
|
+
* is reached for.
|
|
104
|
+
*/
|
|
105
|
+
function lowerTernaryOperand(ctx: GoEmitContext, n: ParsedExpr): string {
|
|
106
|
+
if (n.kind === 'conditional') {
|
|
107
|
+
return lowerTernary(ctx, n.test, n.consequent, n.alternate)
|
|
108
|
+
}
|
|
109
|
+
return wrapIfMultiToken(ctx.convertExpressionToGo(stringifyParsedExpr(n), undefined, n))
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Lower a ternary TEST to a Go bool. `Ternary`'s first parameter is typed
|
|
114
|
+
* `bool` and is NOT truthiness-coerced the way `{{if}}` is, so a non-bool test
|
|
115
|
+
* (`x` where x is a string/number, `a && b`, …) fed in raw would fail the
|
|
116
|
+
* runtime type assertion. A comparison / `!x` / bool literal already renders
|
|
117
|
+
* to a bool via the generic emitter and passes through; every other shape is
|
|
118
|
+
* wrapped `bf_truthy <value>`, which mirrors JS `Boolean(x)` (the runtime's
|
|
119
|
+
* `isTruthy`) across string / number / bool / nil uniformly — the general
|
|
120
|
+
* counterpart of `lowerUrlGuard`'s string-only `ne <value> ""`.
|
|
121
|
+
*/
|
|
122
|
+
function lowerTernaryTest(ctx: GoEmitContext, test: ParsedExpr): string {
|
|
123
|
+
const go = wrapIfMultiToken(ctx.convertExpressionToGo(stringifyParsedExpr(test), undefined, test))
|
|
124
|
+
const isBoolShape =
|
|
125
|
+
(test.kind === 'binary' && BOOL_COMPARISON_OPS.has(test.op)) ||
|
|
126
|
+
(test.kind === 'unary' && test.op === '!') ||
|
|
127
|
+
(test.kind === 'literal' && test.literalType === 'boolean')
|
|
128
|
+
return isBoolShape ? go : `(bf_truthy ${go})`
|
|
129
|
+
}
|
|
130
|
+
|
|
68
131
|
/**
|
|
69
132
|
* Lower a helper call to a Go template expression, or null when no registered
|
|
70
133
|
* plugin recognises it (→ the generic lowering). Matchers — including the
|
|
@@ -113,8 +176,20 @@ function renderLoweringNode(ctx: GoEmitContext, node: LoweringNode): string | nu
|
|
|
113
176
|
if (!helper) return null
|
|
114
177
|
const lowerExpr = (n: ParsedExpr): string =>
|
|
115
178
|
ctx.convertExpressionToGo(stringifyParsedExpr(n), undefined, n)
|
|
179
|
+
// A `conditional` in ARGUMENT position lowers to the pipeline-position
|
|
180
|
+
// `(bf_ternary …)` form via the shared `lowerTernary` (#2335) — the same
|
|
181
|
+
// form the ParsedExpr `conditional()` emitter and the condition-expression
|
|
182
|
+
// emitter produce. Routing it here explicitly (rather than leaning on the
|
|
183
|
+
// generic `lowerExpr`, whose `conditional()` dispatch now reaches the very
|
|
184
|
+
// same helper) keeps the arg lowering self-contained and its intent local;
|
|
185
|
+
// `lowerTernary` itself right-folds a nested chain (the #2324 union stage's
|
|
186
|
+
// locale→pattern table) into `(bf_ternary <cond> <a> (bf_ternary …))`.
|
|
187
|
+
const lowerArg = (n: ParsedExpr): string =>
|
|
188
|
+
n.kind === 'conditional'
|
|
189
|
+
? lowerTernary(ctx, n.test, n.consequent, n.alternate)
|
|
190
|
+
: wrapIfMultiToken(lowerExpr(n))
|
|
116
191
|
if (node.kind === 'helper-call') {
|
|
117
|
-
const args = node.args.map(a =>
|
|
192
|
+
const args = node.args.map(a => lowerArg(a))
|
|
118
193
|
return [helper, ...args].join(' ')
|
|
119
194
|
}
|
|
120
195
|
// guard-list — `queryHref`-shaped. Inclusion mirrors the client exactly, where
|
|
@@ -122,7 +122,7 @@ import { analyzeBakeableStaticChildLoop, scalarToGoLiteral, type BakedStaticChil
|
|
|
122
122
|
import { analyzeBakeableStaticElementLoop } from "./analysis/static-element-loop-bake.ts"
|
|
123
123
|
import type { GoEmitContext } from "./emit-context.ts"
|
|
124
124
|
import { inlineLocalHelperCall } from "./expr/helper-inline.ts"
|
|
125
|
-
import { lowerRegisteredCall } from "./expr/url-builder.ts"
|
|
125
|
+
import { lowerRegisteredCall, lowerTernary } from "./expr/url-builder.ts"
|
|
126
126
|
import {
|
|
127
127
|
convertInitialValue,
|
|
128
128
|
jsLiteralToGo,
|
|
@@ -3784,21 +3784,27 @@ export class GoTemplateAdapter extends BaseAdapter implements ParsedExprEmitter,
|
|
|
3784
3784
|
: null
|
|
3785
3785
|
}
|
|
3786
3786
|
|
|
3787
|
-
// JSX-level ternaries (`{expr ? a : b}`) are handled at the
|
|
3788
|
-
// IRConditional (via convertConditionToGo → renderConditionExpr
|
|
3789
|
-
// is only reached for ternaries nested inside
|
|
3790
|
-
//
|
|
3791
|
-
//
|
|
3787
|
+
// JSX-level ternaries (`{expr ? a : b}`) in TEXT position are handled at the
|
|
3788
|
+
// IR level as IRConditional (via convertConditionToGo → renderConditionExpr →
|
|
3789
|
+
// renderConditional). This method is only reached for ternaries nested inside
|
|
3790
|
+
// other ParsedExpr trees in VALUE position (e.g. template-literal
|
|
3791
|
+
// interpolation, an attribute value), where both branches are values.
|
|
3792
|
+
//
|
|
3793
|
+
// #2335: emit the pipeline-position `(bf_ternary …)` form — the same lowering
|
|
3794
|
+
// helper-call args (`lowerArg`) and boolean sub-conditions
|
|
3795
|
+
// (`renderConditionExpr`) now share — instead of a text-position
|
|
3796
|
+
// `{{if}}…{{end}}` action fragment. Callers wrap the returned pipeline in
|
|
3797
|
+
// `{{…}}` via the normal expression path (it no longer `{{`-leads, so
|
|
3798
|
+
// `isTemplateFragment` correctly declines it). `emit` is unused: the shared
|
|
3799
|
+
// lowering re-derives each child's Go form (branches as quoted values, the
|
|
3800
|
+
// test coerced to a real bool) rather than the generic emit.
|
|
3792
3801
|
conditional(
|
|
3793
3802
|
test: ParsedExpr,
|
|
3794
3803
|
consequent: ParsedExpr,
|
|
3795
3804
|
alternate: ParsedExpr,
|
|
3796
|
-
|
|
3805
|
+
_emit: (e: ParsedExpr) => string,
|
|
3797
3806
|
): string {
|
|
3798
|
-
|
|
3799
|
-
const c = this.renderConditionalBranch(consequent)
|
|
3800
|
-
const a = this.renderConditionalBranch(alternate)
|
|
3801
|
-
return `{{if ${t}}}${c}{{else}}${a}{{end}}`
|
|
3807
|
+
return lowerTernary(this.emitCtx, test, consequent, alternate)
|
|
3802
3808
|
}
|
|
3803
3809
|
|
|
3804
3810
|
templateLiteral(parts: TemplatePart[], emit: (e: ParsedExpr) => string): string {
|
|
@@ -4762,24 +4768,6 @@ export class GoTemplateAdapter extends BaseAdapter implements ParsedExprEmitter,
|
|
|
4762
4768
|
}
|
|
4763
4769
|
}
|
|
4764
4770
|
|
|
4765
|
-
/**
|
|
4766
|
-
* Render a branch of a conditional expression. String literals render as bare
|
|
4767
|
-
* text (no quotes); nested conditionals render as complete `{{if}}…{{end}}`
|
|
4768
|
-
* blocks; everything else is wrapped in `{{...}}`.
|
|
4769
|
-
*/
|
|
4770
|
-
private renderConditionalBranch(expr: ParsedExpr): string {
|
|
4771
|
-
if (expr.kind === 'literal' && expr.literalType === 'string') {
|
|
4772
|
-
return String(expr.value)
|
|
4773
|
-
}
|
|
4774
|
-
if (expr.kind === 'conditional') {
|
|
4775
|
-
const test = this.renderParsedExpr(expr.test)
|
|
4776
|
-
const consequent = this.renderConditionalBranch(expr.consequent)
|
|
4777
|
-
const alternate = this.renderConditionalBranch(expr.alternate)
|
|
4778
|
-
return `{{if ${test}}}${consequent}{{else}}${alternate}{{end}}`
|
|
4779
|
-
}
|
|
4780
|
-
return `{{${this.renderParsedExpr(expr)}}}`
|
|
4781
|
-
}
|
|
4782
|
-
|
|
4783
4771
|
/**
|
|
4784
4772
|
* Whether a ParsedExpr renders to a Go template function call (`len .X`,
|
|
4785
4773
|
* `bf_add .A .B`) that needs parentheses when used as an argument to a
|
|
@@ -5369,8 +5357,14 @@ export class GoTemplateAdapter extends BaseAdapter implements ParsedExprEmitter,
|
|
|
5369
5357
|
}
|
|
5370
5358
|
|
|
5371
5359
|
case 'conditional': {
|
|
5372
|
-
|
|
5373
|
-
|
|
5360
|
+
// #2335: a ternary used as (part of) a boolean sub-condition —
|
|
5361
|
+
// `(x ? y : z) && w`, `!(a ? b : c)` — must lower FAITHFULLY. The old
|
|
5362
|
+
// code returned only the lowered `test`, silently discarding both
|
|
5363
|
+
// branches (a `(x ? y : z)` collapsed to `x`) — not refused, silently
|
|
5364
|
+
// wrong. Emit the pipeline-position `(bf_ternary <test> <y> <z>)`
|
|
5365
|
+
// value; the enclosing condition (`{{if}}`, `and`/`or`, `not`)
|
|
5366
|
+
// truthiness-checks its result, exactly as it would the JS ternary's.
|
|
5367
|
+
return plain(lowerTernary(this.emitCtx, expr.test, expr.consequent, expr.alternate))
|
|
5374
5368
|
}
|
|
5375
5369
|
|
|
5376
5370
|
case 'template-literal':
|
|
@@ -6111,8 +6105,10 @@ export class GoTemplateAdapter extends BaseAdapter implements ParsedExprEmitter,
|
|
|
6111
6105
|
const body = `${name}="{{${valueExpr}}}"`
|
|
6112
6106
|
return `${preamble}{{if ${goCond}}}${body}{{end}}`
|
|
6113
6107
|
}
|
|
6114
|
-
//
|
|
6115
|
-
|
|
6108
|
+
// #2335: the ternary lowers to the pipeline-position `(bf_ternary …)`
|
|
6109
|
+
// value (no longer a `{{if}}…{{end}}` fragment), so wrap it in a single
|
|
6110
|
+
// `{{…}}` action inside the attribute string — `name="{{bf_ternary …}}"`.
|
|
6111
|
+
return `${name}="{{${this.renderParsedExpr(parsed)}}}"`
|
|
6116
6112
|
}
|
|
6117
6113
|
if (parsed.kind === 'template-literal') {
|
|
6118
6114
|
// Inline Go template syntax with embedded `{{...}}` actions.
|