@barefootjs/go-template 0.9.2 → 0.9.3

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.
@@ -30,6 +30,7 @@ export interface GoTemplateAdapterOptions {
30
30
  export declare class GoTemplateAdapter extends BaseAdapter implements ParsedExprEmitter, IRNodeEmitter<GoRenderCtx> {
31
31
  name: string;
32
32
  extension: string;
33
+ private static readonly SCOPE_SENTINEL;
33
34
  importMapInjection: 'html-snippet';
34
35
  private filterExprDepth;
35
36
  private filterExprUnsupported;
@@ -109,6 +110,10 @@ export declare class GoTemplateAdapter extends BaseAdapter implements ParsedExpr
109
110
  /** Set during type generation when any emit references
110
111
  * `template.HTML(...)`; toggles the `"html/template"` import. */
111
112
  private usesHtmlTemplate;
113
+ /** Component root scope element(s) — each carries `data-key` for a keyed loop
114
+ * item. A plain element root is one node; an `if-statement` (early-return)
115
+ * root contributes the top element of every branch. (#1297) */
116
+ private rootScopeNodes;
112
117
  /** Set during type generation when any emit references
113
118
  * `fmt.Sprint(...)` — e.g. a `Record<staticKeys, scalar>[propKey]`
114
119
  * indexed-map spread value (#checkbox); toggles the `"fmt"` import. */
@@ -367,7 +372,23 @@ export declare class GoTemplateAdapter extends BaseAdapter implements ParsedExpr
367
372
  * "drop children" fallback. Dynamic / component-bearing children
368
373
  * stay on the drop path until a re-evaluation hook lands.
369
374
  */
375
+ /**
376
+ * Pull the IR nodes out of a `children={<…/>}` attribute (a `jsx-children`
377
+ * prop value). Empty when the component takes no such prop. (#1326 / #1335)
378
+ */
379
+ private jsxChildrenPropNodes;
370
380
  private extractHtmlChildren;
381
+ /**
382
+ * Build a Go string-concat expression for hoisted-JSX children whose root
383
+ * carries `needsScope` (`children={<span/>}` — #1326 / #1335). Such roots
384
+ * render in the PARENT's scope, so their `bf-s` is the runtime parent
385
+ * `scopeID`, not a bake-time constant. We render the fragment, swap the
386
+ * parent-scope hydration marker for a sentinel, and splice `scopeID` back
387
+ * in. Returns null when the plain static `childrenHtml` path already
388
+ * applies, or when any other template action survives (genuinely dynamic —
389
+ * those stay on the drop path).
390
+ */
391
+ private extractScopedHtmlChildren;
371
392
  private collectStaticChildInstancesRecursive;
372
393
  /**
373
394
  * Extend the active provider-context map with one `<Ctx.Provider value>`. 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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"}
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Go html/template Adapter Exports
3
3
  */
4
- export { GoTemplateAdapter, goTemplateAdapter } from './go-template-adapter';
5
- export type { GoTemplateAdapterOptions } from './go-template-adapter';
4
+ export { GoTemplateAdapter, goTemplateAdapter } from './go-template-adapter.ts';
5
+ export type { GoTemplateAdapterOptions } from './go-template-adapter.ts';
6
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/adapter/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AAC5E,YAAY,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/adapter/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAC/E,YAAY,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAA"}
@@ -69,6 +69,42 @@ function capitalize(s) {
69
69
  }
70
70
  return s[0].toUpperCase() + s.slice(1);
71
71
  }
72
+ function loopKeyToGoFieldPath(key, param) {
73
+ if (!key || !param)
74
+ return null;
75
+ const segs = key.split(".");
76
+ if (segs[0] !== param)
77
+ return null;
78
+ const rest = segs.slice(1);
79
+ if (rest.length === 0)
80
+ return null;
81
+ if (!rest.every((s) => /^[A-Za-z_]\w*$/.test(s)))
82
+ return null;
83
+ return "item." + rest.map(capitalize).join(".");
84
+ }
85
+ function collectRootScopeNodes(node) {
86
+ const out = new Set;
87
+ const visit = (n) => {
88
+ if (!n)
89
+ return;
90
+ if (n.type === "element") {
91
+ out.add(n);
92
+ return;
93
+ }
94
+ if (n.type === "if-statement") {
95
+ const s = n;
96
+ visit(s.consequent);
97
+ visit(s.alternate);
98
+ return;
99
+ }
100
+ if (n.type === "fragment") {
101
+ for (const c of n.children)
102
+ visit(c);
103
+ }
104
+ };
105
+ visit(node);
106
+ return out;
107
+ }
72
108
  function slotIdToFieldSuffix(slotId) {
73
109
  const cleanId = slotId.startsWith("^") ? slotId.slice(1) : slotId;
74
110
  const match = cleanId.match(/^s(\d+)$/);
@@ -101,6 +137,7 @@ var GO_TEMPLATE_PRIMITIVES = {
101
137
  class GoTemplateAdapter extends BaseAdapter {
102
138
  name = "go-template";
103
139
  extension = ".tmpl";
140
+ static SCOPE_SENTINEL = "__BF_SCOPE_SENTINEL__";
104
141
  importMapInjection = "html-snippet";
105
142
  filterExprDepth = 0;
106
143
  filterExprUnsupported = false;
@@ -120,6 +157,7 @@ class GoTemplateAdapter extends BaseAdapter {
120
157
  localStructFields = new Map;
121
158
  synthStructTypes = new Map;
122
159
  usesHtmlTemplate = false;
160
+ rootScopeNodes = new Set;
123
161
  usesFmt = false;
124
162
  childComponentShapes = new Map;
125
163
  moduleStringConsts = new Map;
@@ -152,6 +190,7 @@ class GoTemplateAdapter extends BaseAdapter {
152
190
  const hasInteractivity = this.hasClientInteractivity(ir);
153
191
  const isRootComponent = ir.root.type === "component";
154
192
  const isIfStatement = ir.root.type === "if-statement";
193
+ this.rootScopeNodes = collectRootScopeNodes(ir.root);
155
194
  const templateBody = isIfStatement ? this.renderIfStatement(ir.root, { isRootOfClientComponent: hasInteractivity }) : this.renderNode(ir.root, { isRootOfClientComponent: hasInteractivity && isRootComponent });
156
195
  const scriptRegistrations = options?.skipScriptRegistration ? "" : this.generateScriptRegistrations(ir, options?.scriptBaseName);
157
196
  const template = `{{define "${this.componentName}"}}
@@ -683,6 +722,7 @@ ${goFields.join(`
683
722
  lines.push('\tBfIsChild bool `json:"-"`');
684
723
  lines.push('\tBfParent string `json:"-"`');
685
724
  lines.push('\tBfMount string `json:"-"`');
725
+ lines.push('\tBfDataKey string `json:"-"`');
686
726
  lines.push('\tScripts *bf.ScriptCollector `json:"-"`');
687
727
  const nestedArrayFields = new Set(nestedComponents.map((n) => `${n.name}s`));
688
728
  const propFieldNames = new Set;
@@ -798,6 +838,11 @@ ${goFields.join(`
798
838
  lines.push(` ${varName}[i] = New${nested.name}Props(item)`);
799
839
  lines.push(` ${varName}[i].BfParent = scopeID`);
800
840
  lines.push(` ${varName}[i].BfMount = "${nested.slotId}"`);
841
+ const keyField = loopKeyToGoFieldPath(nested.loopKey, nested.loopParam);
842
+ if (keyField) {
843
+ lines.push(` ${varName}[i].BfDataKey = fmt.Sprint(${keyField})`);
844
+ this.usesFmt = true;
845
+ }
801
846
  lines.push("\t}");
802
847
  lines.push("");
803
848
  }
@@ -934,6 +979,9 @@ ${goFields.join(`
934
979
  } else if (child.childrenHtml !== null) {
935
980
  this.usesHtmlTemplate = true;
936
981
  lines.push(` Children: template.HTML(${JSON.stringify(child.childrenHtml)}),`);
982
+ } else if (child.childrenScopedHtmlExpr !== null) {
983
+ this.usesHtmlTemplate = true;
984
+ lines.push(` Children: template.HTML(${child.childrenScopedHtmlExpr}),`);
937
985
  }
938
986
  lines.push(` }),`);
939
987
  }
@@ -972,7 +1020,9 @@ ${goFields.join(`
972
1020
  result.push({
973
1021
  ...loop.childComponent,
974
1022
  isDynamic: !loop.isStaticArray,
975
- isPropDerived: !!loop.isPropDerivedArray
1023
+ isPropDerived: !!loop.isPropDerivedArray,
1024
+ loopKey: loop.key ?? undefined,
1025
+ loopParam: loop.param ?? undefined
976
1026
  });
977
1027
  }
978
1028
  }
@@ -1013,6 +1063,13 @@ ${goFields.join(`
1013
1063
  }
1014
1064
  return out;
1015
1065
  }
1066
+ jsxChildrenPropNodes(props) {
1067
+ for (const p of props) {
1068
+ if (p.value.kind === "jsx-children")
1069
+ return p.value.children;
1070
+ }
1071
+ return [];
1072
+ }
1016
1073
  extractHtmlChildren(children) {
1017
1074
  if (children.length === 0)
1018
1075
  return null;
@@ -1023,6 +1080,20 @@ ${goFields.join(`
1023
1080
  return null;
1024
1081
  return html;
1025
1082
  }
1083
+ extractScopedHtmlChildren(children) {
1084
+ if (children.length === 0)
1085
+ return null;
1086
+ if (children.every((c) => c.type === "text"))
1087
+ return null;
1088
+ const html = this.renderChildren(children);
1089
+ const marker = this.renderScopeMarker(".ScopeID");
1090
+ const withSentinel = html.split(marker).join(`bf-s="${GoTemplateAdapter.SCOPE_SENTINEL}"`);
1091
+ if (!withSentinel.includes(GoTemplateAdapter.SCOPE_SENTINEL))
1092
+ return null;
1093
+ if (withSentinel.includes("{{"))
1094
+ return null;
1095
+ return withSentinel.split(GoTemplateAdapter.SCOPE_SENTINEL).map((seg) => JSON.stringify(seg)).join(" + scopeID + ");
1096
+ }
1026
1097
  collectStaticChildInstancesRecursive(node, result, inLoop, providerCtx) {
1027
1098
  if (node.type === "component") {
1028
1099
  const comp = node;
@@ -1034,13 +1105,15 @@ ${goFields.join(`
1034
1105
  }
1035
1106
  if (comp.name !== "Portal" && !inLoop && comp.slotId) {
1036
1107
  const suffix = slotIdToFieldSuffix(comp.slotId);
1108
+ const effectiveChildren = comp.children.length > 0 ? comp.children : this.jsxChildrenPropNodes(comp.props);
1037
1109
  result.push({
1038
1110
  name: comp.name,
1039
1111
  slotId: comp.slotId,
1040
1112
  props: comp.props,
1041
1113
  fieldName: `${comp.name}${suffix}`,
1042
- childrenText: this.extractTextChildren(comp.children),
1043
- childrenHtml: this.extractHtmlChildren(comp.children),
1114
+ childrenText: this.extractTextChildren(effectiveChildren),
1115
+ childrenHtml: this.extractHtmlChildren(effectiveChildren),
1116
+ childrenScopedHtmlExpr: this.extractScopedHtmlChildren(effectiveChildren),
1044
1117
  contextBindings: providerCtx.size > 0 ? providerCtx : undefined
1045
1118
  });
1046
1119
  }
@@ -2153,6 +2226,9 @@ ${goFields.join(`
2153
2226
  if (element.needsScope) {
2154
2227
  hydrationAttrs += ` ${this.renderScopeMarker(".ScopeID")}`;
2155
2228
  }
2229
+ if (this.rootScopeNodes.has(element) && element.needsScope) {
2230
+ hydrationAttrs += `{{if .BfDataKey}} data-key="{{.BfDataKey}}"{{end}}`;
2231
+ }
2156
2232
  if (element.slotId) {
2157
2233
  hydrationAttrs += ` ${this.renderSlotMarker(element.slotId)}`;
2158
2234
  }
package/dist/build.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type { BuildOptions, PostBuildContext } from '@barefootjs/jsx';
2
- import { GoTemplateAdapter } from './adapter';
3
- import type { GoTemplateAdapterOptions } from './adapter';
2
+ import { GoTemplateAdapter } from './adapter/index.ts';
3
+ import type { GoTemplateAdapterOptions } from './adapter/index.ts';
4
4
  export interface GoTemplateBuildOptions extends BuildOptions {
5
5
  /** Adapter-specific options passed to GoTemplateAdapter */
6
6
  adapterOptions?: GoTemplateAdapterOptions;
@@ -1 +1 @@
1
- {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AACrE,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAC7C,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,WAAW,CAAA;AAEzD,MAAM,WAAW,sBAAuB,SAAQ,YAAY;IAC1D,2DAA2D;IAC3D,cAAc,CAAC,EAAE,wBAAwB,CAAA;IACzC,gGAAgG;IAChG,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,uFAAuF;IACvF,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAA;IAC1C,2FAA2F;IAC3F,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAID;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CA0C1D;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAmD3D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE;IACtC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC1B,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAA;CAC3C,GAAG,MAAM,CAyDT;AAID;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,OAAO,GAAE,sBAA2B;IAyC7D,OAAO;IACP,KAAK;IACL,UAAU;IACV,MAAM;IACN,MAAM;IACN,WAAW;IACX,SAAS;IACT,iBAAiB;IACjB,aAAa;IACb,mBAAmB;IACnB,YAAY;IAKZ,SAAS,QApDmB,gBAAgB;EAsD/C"}
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AACrE,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAA;AAElE,MAAM,WAAW,sBAAuB,SAAQ,YAAY;IAC1D,2DAA2D;IAC3D,cAAc,CAAC,EAAE,wBAAwB,CAAA;IACzC,gGAAgG;IAChG,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,uFAAuF;IACvF,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAA;IAC1C,2FAA2F;IAC3F,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAID;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CA0C1D;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAmD3D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE;IACtC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC1B,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAA;CAC3C,GAAG,MAAM,CAsET;AAID;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,OAAO,GAAE,sBAA2B;IAyC7D,OAAO;IACP,KAAK;IACL,UAAU;IACV,MAAM;IACN,MAAM;IACN,WAAW;IACX,SAAS;IACT,iBAAiB;IACjB,aAAa;IACb,mBAAmB;IACnB,YAAY;IAKZ,SAAS,QApDmB,gBAAgB;EAsD/C"}
package/dist/build.js CHANGED
@@ -409,6 +409,42 @@ function capitalize(s) {
409
409
  }
410
410
  return s[0].toUpperCase() + s.slice(1);
411
411
  }
412
+ function loopKeyToGoFieldPath(key, param) {
413
+ if (!key || !param)
414
+ return null;
415
+ const segs = key.split(".");
416
+ if (segs[0] !== param)
417
+ return null;
418
+ const rest = segs.slice(1);
419
+ if (rest.length === 0)
420
+ return null;
421
+ if (!rest.every((s) => /^[A-Za-z_]\w*$/.test(s)))
422
+ return null;
423
+ return "item." + rest.map(capitalize).join(".");
424
+ }
425
+ function collectRootScopeNodes(node) {
426
+ const out = new Set;
427
+ const visit = (n) => {
428
+ if (!n)
429
+ return;
430
+ if (n.type === "element") {
431
+ out.add(n);
432
+ return;
433
+ }
434
+ if (n.type === "if-statement") {
435
+ const s = n;
436
+ visit(s.consequent);
437
+ visit(s.alternate);
438
+ return;
439
+ }
440
+ if (n.type === "fragment") {
441
+ for (const c of n.children)
442
+ visit(c);
443
+ }
444
+ };
445
+ visit(node);
446
+ return out;
447
+ }
412
448
  function slotIdToFieldSuffix(slotId) {
413
449
  const cleanId = slotId.startsWith("^") ? slotId.slice(1) : slotId;
414
450
  const match = cleanId.match(/^s(\d+)$/);
@@ -441,6 +477,7 @@ var GO_TEMPLATE_PRIMITIVES = {
441
477
  class GoTemplateAdapter extends BaseAdapter {
442
478
  name = "go-template";
443
479
  extension = ".tmpl";
480
+ static SCOPE_SENTINEL = "__BF_SCOPE_SENTINEL__";
444
481
  importMapInjection = "html-snippet";
445
482
  filterExprDepth = 0;
446
483
  filterExprUnsupported = false;
@@ -460,6 +497,7 @@ class GoTemplateAdapter extends BaseAdapter {
460
497
  localStructFields = new Map;
461
498
  synthStructTypes = new Map;
462
499
  usesHtmlTemplate = false;
500
+ rootScopeNodes = new Set;
463
501
  usesFmt = false;
464
502
  childComponentShapes = new Map;
465
503
  moduleStringConsts = new Map;
@@ -492,6 +530,7 @@ class GoTemplateAdapter extends BaseAdapter {
492
530
  const hasInteractivity = this.hasClientInteractivity(ir);
493
531
  const isRootComponent = ir.root.type === "component";
494
532
  const isIfStatement = ir.root.type === "if-statement";
533
+ this.rootScopeNodes = collectRootScopeNodes(ir.root);
495
534
  const templateBody = isIfStatement ? this.renderIfStatement(ir.root, { isRootOfClientComponent: hasInteractivity }) : this.renderNode(ir.root, { isRootOfClientComponent: hasInteractivity && isRootComponent });
496
535
  const scriptRegistrations = options?.skipScriptRegistration ? "" : this.generateScriptRegistrations(ir, options?.scriptBaseName);
497
536
  const template = `{{define "${this.componentName}"}}
@@ -1023,6 +1062,7 @@ ${goFields.join(`
1023
1062
  lines.push('\tBfIsChild bool `json:"-"`');
1024
1063
  lines.push('\tBfParent string `json:"-"`');
1025
1064
  lines.push('\tBfMount string `json:"-"`');
1065
+ lines.push('\tBfDataKey string `json:"-"`');
1026
1066
  lines.push('\tScripts *bf.ScriptCollector `json:"-"`');
1027
1067
  const nestedArrayFields = new Set(nestedComponents.map((n) => `${n.name}s`));
1028
1068
  const propFieldNames = new Set;
@@ -1138,6 +1178,11 @@ ${goFields.join(`
1138
1178
  lines.push(` ${varName}[i] = New${nested.name}Props(item)`);
1139
1179
  lines.push(` ${varName}[i].BfParent = scopeID`);
1140
1180
  lines.push(` ${varName}[i].BfMount = "${nested.slotId}"`);
1181
+ const keyField = loopKeyToGoFieldPath(nested.loopKey, nested.loopParam);
1182
+ if (keyField) {
1183
+ lines.push(` ${varName}[i].BfDataKey = fmt.Sprint(${keyField})`);
1184
+ this.usesFmt = true;
1185
+ }
1141
1186
  lines.push("\t}");
1142
1187
  lines.push("");
1143
1188
  }
@@ -1274,6 +1319,9 @@ ${goFields.join(`
1274
1319
  } else if (child.childrenHtml !== null) {
1275
1320
  this.usesHtmlTemplate = true;
1276
1321
  lines.push(` Children: template.HTML(${JSON.stringify(child.childrenHtml)}),`);
1322
+ } else if (child.childrenScopedHtmlExpr !== null) {
1323
+ this.usesHtmlTemplate = true;
1324
+ lines.push(` Children: template.HTML(${child.childrenScopedHtmlExpr}),`);
1277
1325
  }
1278
1326
  lines.push(` }),`);
1279
1327
  }
@@ -1312,7 +1360,9 @@ ${goFields.join(`
1312
1360
  result.push({
1313
1361
  ...loop.childComponent,
1314
1362
  isDynamic: !loop.isStaticArray,
1315
- isPropDerived: !!loop.isPropDerivedArray
1363
+ isPropDerived: !!loop.isPropDerivedArray,
1364
+ loopKey: loop.key ?? undefined,
1365
+ loopParam: loop.param ?? undefined
1316
1366
  });
1317
1367
  }
1318
1368
  }
@@ -1353,6 +1403,13 @@ ${goFields.join(`
1353
1403
  }
1354
1404
  return out;
1355
1405
  }
1406
+ jsxChildrenPropNodes(props) {
1407
+ for (const p of props) {
1408
+ if (p.value.kind === "jsx-children")
1409
+ return p.value.children;
1410
+ }
1411
+ return [];
1412
+ }
1356
1413
  extractHtmlChildren(children) {
1357
1414
  if (children.length === 0)
1358
1415
  return null;
@@ -1363,6 +1420,20 @@ ${goFields.join(`
1363
1420
  return null;
1364
1421
  return html;
1365
1422
  }
1423
+ extractScopedHtmlChildren(children) {
1424
+ if (children.length === 0)
1425
+ return null;
1426
+ if (children.every((c) => c.type === "text"))
1427
+ return null;
1428
+ const html = this.renderChildren(children);
1429
+ const marker = this.renderScopeMarker(".ScopeID");
1430
+ const withSentinel = html.split(marker).join(`bf-s="${GoTemplateAdapter.SCOPE_SENTINEL}"`);
1431
+ if (!withSentinel.includes(GoTemplateAdapter.SCOPE_SENTINEL))
1432
+ return null;
1433
+ if (withSentinel.includes("{{"))
1434
+ return null;
1435
+ return withSentinel.split(GoTemplateAdapter.SCOPE_SENTINEL).map((seg) => JSON.stringify(seg)).join(" + scopeID + ");
1436
+ }
1366
1437
  collectStaticChildInstancesRecursive(node, result, inLoop, providerCtx) {
1367
1438
  if (node.type === "component") {
1368
1439
  const comp = node;
@@ -1374,13 +1445,15 @@ ${goFields.join(`
1374
1445
  }
1375
1446
  if (comp.name !== "Portal" && !inLoop && comp.slotId) {
1376
1447
  const suffix = slotIdToFieldSuffix(comp.slotId);
1448
+ const effectiveChildren = comp.children.length > 0 ? comp.children : this.jsxChildrenPropNodes(comp.props);
1377
1449
  result.push({
1378
1450
  name: comp.name,
1379
1451
  slotId: comp.slotId,
1380
1452
  props: comp.props,
1381
1453
  fieldName: `${comp.name}${suffix}`,
1382
- childrenText: this.extractTextChildren(comp.children),
1383
- childrenHtml: this.extractHtmlChildren(comp.children),
1454
+ childrenText: this.extractTextChildren(effectiveChildren),
1455
+ childrenHtml: this.extractHtmlChildren(effectiveChildren),
1456
+ childrenScopedHtmlExpr: this.extractScopedHtmlChildren(effectiveChildren),
1384
1457
  contextBindings: providerCtx.size > 0 ? providerCtx : undefined
1385
1458
  });
1386
1459
  }
@@ -2493,6 +2566,9 @@ ${goFields.join(`
2493
2566
  if (element.needsScope) {
2494
2567
  hydrationAttrs += ` ${this.renderScopeMarker(".ScopeID")}`;
2495
2568
  }
2569
+ if (this.rootScopeNodes.has(element) && element.needsScope) {
2570
+ hydrationAttrs += `{{if .BfDataKey}} data-key="{{.BfDataKey}}"{{end}}`;
2571
+ }
2496
2572
  if (element.slotId) {
2497
2573
  hydrationAttrs += ` ${this.renderSlotMarker(element.slotId)}`;
2498
2574
  }
@@ -4026,12 +4102,20 @@ function combineGoTypes(options) {
4026
4102
  if (transformTypes) {
4027
4103
  combinedContent = transformTypes(combinedContent);
4028
4104
  }
4105
+ const usageScan = combinedContent + `
4106
+ ` + (manualTypes ?? "");
4107
+ const stdlibImports = [` "math/rand"`];
4108
+ if (/\bfmt\./.test(usageScan))
4109
+ stdlibImports.push(` "fmt"`);
4110
+ if (/\btemplate\.HTML\b/.test(usageScan))
4111
+ stdlibImports.push(` "html/template"`);
4112
+ stdlibImports.sort();
4029
4113
  const parts = [
4030
4114
  `// Code generated by BarefootJS. DO NOT EDIT.`,
4031
4115
  `package ${packageName}`,
4032
4116
  "",
4033
4117
  `import (`,
4034
- ` "math/rand"`,
4118
+ ...stdlibImports,
4035
4119
  "",
4036
4120
  ` bf "github.com/barefootjs/runtime/bf"`,
4037
4121
  `)`,
package/dist/index.d.ts CHANGED
@@ -3,6 +3,6 @@
3
3
  *
4
4
  * Generates Go html/template files from BarefootJS IR.
5
5
  */
6
- export { GoTemplateAdapter, goTemplateAdapter } from './adapter';
7
- export type { GoTemplateAdapterOptions } from './adapter';
6
+ export { GoTemplateAdapter, goTemplateAdapter } from './adapter/index.ts';
7
+ export type { GoTemplateAdapterOptions } from './adapter/index.ts';
8
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAChE,YAAY,EAAE,wBAAwB,EAAE,MAAM,WAAW,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AACzE,YAAY,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAA"}
package/dist/index.js CHANGED
@@ -69,6 +69,42 @@ function capitalize(s) {
69
69
  }
70
70
  return s[0].toUpperCase() + s.slice(1);
71
71
  }
72
+ function loopKeyToGoFieldPath(key, param) {
73
+ if (!key || !param)
74
+ return null;
75
+ const segs = key.split(".");
76
+ if (segs[0] !== param)
77
+ return null;
78
+ const rest = segs.slice(1);
79
+ if (rest.length === 0)
80
+ return null;
81
+ if (!rest.every((s) => /^[A-Za-z_]\w*$/.test(s)))
82
+ return null;
83
+ return "item." + rest.map(capitalize).join(".");
84
+ }
85
+ function collectRootScopeNodes(node) {
86
+ const out = new Set;
87
+ const visit = (n) => {
88
+ if (!n)
89
+ return;
90
+ if (n.type === "element") {
91
+ out.add(n);
92
+ return;
93
+ }
94
+ if (n.type === "if-statement") {
95
+ const s = n;
96
+ visit(s.consequent);
97
+ visit(s.alternate);
98
+ return;
99
+ }
100
+ if (n.type === "fragment") {
101
+ for (const c of n.children)
102
+ visit(c);
103
+ }
104
+ };
105
+ visit(node);
106
+ return out;
107
+ }
72
108
  function slotIdToFieldSuffix(slotId) {
73
109
  const cleanId = slotId.startsWith("^") ? slotId.slice(1) : slotId;
74
110
  const match = cleanId.match(/^s(\d+)$/);
@@ -101,6 +137,7 @@ var GO_TEMPLATE_PRIMITIVES = {
101
137
  class GoTemplateAdapter extends BaseAdapter {
102
138
  name = "go-template";
103
139
  extension = ".tmpl";
140
+ static SCOPE_SENTINEL = "__BF_SCOPE_SENTINEL__";
104
141
  importMapInjection = "html-snippet";
105
142
  filterExprDepth = 0;
106
143
  filterExprUnsupported = false;
@@ -120,6 +157,7 @@ class GoTemplateAdapter extends BaseAdapter {
120
157
  localStructFields = new Map;
121
158
  synthStructTypes = new Map;
122
159
  usesHtmlTemplate = false;
160
+ rootScopeNodes = new Set;
123
161
  usesFmt = false;
124
162
  childComponentShapes = new Map;
125
163
  moduleStringConsts = new Map;
@@ -152,6 +190,7 @@ class GoTemplateAdapter extends BaseAdapter {
152
190
  const hasInteractivity = this.hasClientInteractivity(ir);
153
191
  const isRootComponent = ir.root.type === "component";
154
192
  const isIfStatement = ir.root.type === "if-statement";
193
+ this.rootScopeNodes = collectRootScopeNodes(ir.root);
155
194
  const templateBody = isIfStatement ? this.renderIfStatement(ir.root, { isRootOfClientComponent: hasInteractivity }) : this.renderNode(ir.root, { isRootOfClientComponent: hasInteractivity && isRootComponent });
156
195
  const scriptRegistrations = options?.skipScriptRegistration ? "" : this.generateScriptRegistrations(ir, options?.scriptBaseName);
157
196
  const template = `{{define "${this.componentName}"}}
@@ -683,6 +722,7 @@ ${goFields.join(`
683
722
  lines.push('\tBfIsChild bool `json:"-"`');
684
723
  lines.push('\tBfParent string `json:"-"`');
685
724
  lines.push('\tBfMount string `json:"-"`');
725
+ lines.push('\tBfDataKey string `json:"-"`');
686
726
  lines.push('\tScripts *bf.ScriptCollector `json:"-"`');
687
727
  const nestedArrayFields = new Set(nestedComponents.map((n) => `${n.name}s`));
688
728
  const propFieldNames = new Set;
@@ -798,6 +838,11 @@ ${goFields.join(`
798
838
  lines.push(` ${varName}[i] = New${nested.name}Props(item)`);
799
839
  lines.push(` ${varName}[i].BfParent = scopeID`);
800
840
  lines.push(` ${varName}[i].BfMount = "${nested.slotId}"`);
841
+ const keyField = loopKeyToGoFieldPath(nested.loopKey, nested.loopParam);
842
+ if (keyField) {
843
+ lines.push(` ${varName}[i].BfDataKey = fmt.Sprint(${keyField})`);
844
+ this.usesFmt = true;
845
+ }
801
846
  lines.push("\t}");
802
847
  lines.push("");
803
848
  }
@@ -934,6 +979,9 @@ ${goFields.join(`
934
979
  } else if (child.childrenHtml !== null) {
935
980
  this.usesHtmlTemplate = true;
936
981
  lines.push(` Children: template.HTML(${JSON.stringify(child.childrenHtml)}),`);
982
+ } else if (child.childrenScopedHtmlExpr !== null) {
983
+ this.usesHtmlTemplate = true;
984
+ lines.push(` Children: template.HTML(${child.childrenScopedHtmlExpr}),`);
937
985
  }
938
986
  lines.push(` }),`);
939
987
  }
@@ -972,7 +1020,9 @@ ${goFields.join(`
972
1020
  result.push({
973
1021
  ...loop.childComponent,
974
1022
  isDynamic: !loop.isStaticArray,
975
- isPropDerived: !!loop.isPropDerivedArray
1023
+ isPropDerived: !!loop.isPropDerivedArray,
1024
+ loopKey: loop.key ?? undefined,
1025
+ loopParam: loop.param ?? undefined
976
1026
  });
977
1027
  }
978
1028
  }
@@ -1013,6 +1063,13 @@ ${goFields.join(`
1013
1063
  }
1014
1064
  return out;
1015
1065
  }
1066
+ jsxChildrenPropNodes(props) {
1067
+ for (const p of props) {
1068
+ if (p.value.kind === "jsx-children")
1069
+ return p.value.children;
1070
+ }
1071
+ return [];
1072
+ }
1016
1073
  extractHtmlChildren(children) {
1017
1074
  if (children.length === 0)
1018
1075
  return null;
@@ -1023,6 +1080,20 @@ ${goFields.join(`
1023
1080
  return null;
1024
1081
  return html;
1025
1082
  }
1083
+ extractScopedHtmlChildren(children) {
1084
+ if (children.length === 0)
1085
+ return null;
1086
+ if (children.every((c) => c.type === "text"))
1087
+ return null;
1088
+ const html = this.renderChildren(children);
1089
+ const marker = this.renderScopeMarker(".ScopeID");
1090
+ const withSentinel = html.split(marker).join(`bf-s="${GoTemplateAdapter.SCOPE_SENTINEL}"`);
1091
+ if (!withSentinel.includes(GoTemplateAdapter.SCOPE_SENTINEL))
1092
+ return null;
1093
+ if (withSentinel.includes("{{"))
1094
+ return null;
1095
+ return withSentinel.split(GoTemplateAdapter.SCOPE_SENTINEL).map((seg) => JSON.stringify(seg)).join(" + scopeID + ");
1096
+ }
1026
1097
  collectStaticChildInstancesRecursive(node, result, inLoop, providerCtx) {
1027
1098
  if (node.type === "component") {
1028
1099
  const comp = node;
@@ -1034,13 +1105,15 @@ ${goFields.join(`
1034
1105
  }
1035
1106
  if (comp.name !== "Portal" && !inLoop && comp.slotId) {
1036
1107
  const suffix = slotIdToFieldSuffix(comp.slotId);
1108
+ const effectiveChildren = comp.children.length > 0 ? comp.children : this.jsxChildrenPropNodes(comp.props);
1037
1109
  result.push({
1038
1110
  name: comp.name,
1039
1111
  slotId: comp.slotId,
1040
1112
  props: comp.props,
1041
1113
  fieldName: `${comp.name}${suffix}`,
1042
- childrenText: this.extractTextChildren(comp.children),
1043
- childrenHtml: this.extractHtmlChildren(comp.children),
1114
+ childrenText: this.extractTextChildren(effectiveChildren),
1115
+ childrenHtml: this.extractHtmlChildren(effectiveChildren),
1116
+ childrenScopedHtmlExpr: this.extractScopedHtmlChildren(effectiveChildren),
1044
1117
  contextBindings: providerCtx.size > 0 ? providerCtx : undefined
1045
1118
  });
1046
1119
  }
@@ -2153,6 +2226,9 @@ ${goFields.join(`
2153
2226
  if (element.needsScope) {
2154
2227
  hydrationAttrs += ` ${this.renderScopeMarker(".ScopeID")}`;
2155
2228
  }
2229
+ if (this.rootScopeNodes.has(element) && element.needsScope) {
2230
+ hydrationAttrs += `{{if .BfDataKey}} data-key="{{.BfDataKey}}"{{end}}`;
2231
+ }
2156
2232
  if (element.slotId) {
2157
2233
  hydrationAttrs += ` ${this.renderSlotMarker(element.slotId)}`;
2158
2234
  }
@@ -1 +1 @@
1
- {"version":3,"file":"test-render.d.ts","sourceRoot":"","sources":["../src/test-render.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAe,MAAM,iBAAiB,CAAA;AAOnE,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,YAAY,OAAO,EAAE,MAAM,EAG1B;CACF;AAgCD,MAAM,WAAW,aAAa;IAC5B,sBAAsB;IACtB,MAAM,EAAE,MAAM,CAAA;IACd,8BAA8B;IAC9B,OAAO,EAAE,eAAe,CAAA;IACxB,iCAAiC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC/B,qDAAqD;IACrD,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACnC;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,wBAAsB,yBAAyB,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CA4RvF"}
1
+ {"version":3,"file":"test-render.d.ts","sourceRoot":"","sources":["../src/test-render.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAe,MAAM,iBAAiB,CAAA;AAqBnE,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,YAAY,OAAO,EAAE,MAAM,EAG1B;CACF;AAgCD,MAAM,WAAW,aAAa;IAC5B,sBAAsB;IACtB,MAAM,EAAE,MAAM,CAAA;IACd,8BAA8B;IAC9B,OAAO,EAAE,eAAe,CAAA;IACxB,iCAAiC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC/B,qDAAqD;IACrD,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACnC;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,wBAAsB,yBAAyB,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CA6RvF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@barefootjs/go-template",
3
- "version": "0.9.2",
3
+ "version": "0.9.3",
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.9.2"
57
+ "@barefootjs/jsx": "0.9.3"
58
58
  }
59
59
  }
@@ -34,42 +34,10 @@ runAdapterConformanceTests({
34
34
  // below, asserting that the adapter emits `BF101` / `BF103` /
35
35
  // `BF104` at build time instead of silently emitting invalid
36
36
  // template syntax (#1266).
37
- skipJsx: [
38
- // #1244 stress catalog (#1326): `children={<span/>}` the IR
39
- // hoists the span with `needsScope: true` so the Hono reference
40
- // emits `bf-s` on the inner `<span>`. The Go adapter has no path to
41
- // render a hoisted-JSX child handed in through the `children`
42
- // attribute, so the child is DROPPED: the parent renders
43
- // `<div bf-s="test_s0"></div>` with an empty body (verified — no
44
- // compile error, no literal `{{bfScopeAttr}}` text either; that
45
- // older literal-survives-in-output failure mode no longer occurs).
46
- // Closing the gap needs the inner span re-emitted as its own named
47
- // template definition the outer template can pass its struct to, or
48
- // the resolved scope id embedded at compile time. Neither lands
49
- // here; the Mojo / Xslate siblings already pass by routing the
50
- // hoisted JSX through the same nested-children capture.
51
- 'children-jsx-expression',
52
- // #1335: fragment-wrapped form of the same shape. Once the IR
53
- // unwraps `<><span/></>` into the bare-element form the Go adapter
54
- // hits the identical drop as `children-jsx-expression` above.
55
- 'fragment-wrapped-children-jsx-expression',
56
- // `toggle-shared`: the parent maps a `ToggleItemProps[]` prop into
57
- // sibling `ToggleItem` children inside a keyed `.map`. The Go
58
- // child-slice init types the loop input as `[]any` rather than
59
- // `[]ToggleItemInput`, so the generated `NewToggleProps` struct
60
- // literal fails to compile (`cannot use []any{…} as
61
- // []ToggleItemInput value in struct literal`). Separate follow-up —
62
- // needs the loop-child init to emit the typed element slice, plus
63
- // per-item `defaultOn` seeding and the `data-key` attribute shape.
64
- //
65
- // `props-reactivity-comparison` graduated: the Go test-render now
66
- // honours the fixture's `componentName` (`PropsReactivityComparison`,
67
- // the second export of `ReactiveProps.tsx`) instead of always
68
- // rendering the first export, and the generated child constructors
69
- // compute the `displayValue = props.value * 10` memo from the
70
- // passed prop — so SSR matches Hono byte-for-byte.
71
- 'toggle-shared',
72
- ],
37
+ // No JSX-render skips: every shared conformance fixture renders to Hono
38
+ // parity on real Go. Shapes the adapter intentionally refuses at build time
39
+ // are pinned in `expectedDiagnostics` below.
40
+ skipJsx: [],
73
41
  // Per-fixture build-time contracts for shapes the Go template
74
42
  // adapter intentionally refuses to lower. Lives here (not on the
75
43
  // shared fixtures) so adding a new adapter doesn't require touching
@@ -1216,6 +1184,33 @@ export function Page() {
1216
1184
  expect(types).not.toContain('template.HTML')
1217
1185
  })
1218
1186
 
1187
+ test('bakes hoisted children={<span/>} with the parent scopeID spliced into bf-s (#1326 / #1335)', () => {
1188
+ // `children` passed as an attribute lands as a `jsx-children` prop and
1189
+ // its span carries `needsScope: true`. The root `bf-s` must resolve to
1190
+ // the *parent* scope at render time, so the bake splices `scopeID`
1191
+ // (matching the client `__BF_PARENT_SCOPE__` placeholder) rather than
1192
+ // emitting a static string or dropping the child.
1193
+ const adapter = new GoTemplateAdapter()
1194
+ const ir = compileToIR(`
1195
+ export function Host() { return <Box children={<span>x</span>} /> }
1196
+ function Box({ children }: { children: any }) { return <div>{children}</div> }
1197
+ `)
1198
+ const types = adapter.generateTypes(ir)!
1199
+ expect(types).toContain('Children: template.HTML("<span bf-s=\\"" + scopeID + "\\">x</span>")')
1200
+ expect(types).toContain('"html/template"')
1201
+ })
1202
+
1203
+
1204
+ test('fragment-wrapped hoisted children bake to the same scoped shape (#1335)', () => {
1205
+ const adapter = new GoTemplateAdapter()
1206
+ const ir = compileToIR(`
1207
+ export function Host() { return <Box children={<><span>x</span></>} /> }
1208
+ function Box({ children }: { children: any }) { return <div>{children}</div> }
1209
+ `)
1210
+ const types = adapter.generateTypes(ir)!
1211
+ expect(types).toContain('Children: template.HTML("<span bf-s=\\"" + scopeID + "\\">x</span>")')
1212
+ })
1213
+
1219
1214
  test('drops dynamic children that would emit Go template actions', () => {
1220
1215
  // V1 limitation: a `template.HTML` value isn't re-parsed by the
1221
1216
  // parent's `{{.Children}}` pipeline, so any `{{...}}` inside the
@@ -2493,6 +2488,42 @@ import { fixture as arrayEntriesFixture } from '../../../adapter-tests/fixtures/
2493
2488
  import { fixture as arrayKeysFixture } from '../../../adapter-tests/fixtures/methods/array-keys'
2494
2489
  import { fixture as arrayValuesFixture } from '../../../adapter-tests/fixtures/methods/array-values'
2495
2490
 
2491
+ describe('GoTemplateAdapter - keyed loop-child data-key (#1297, toggle-shared)', () => {
2492
+ // A keyed `.map` of a child component stamps each item's `data-key` from the
2493
+ // loop `key` expression, emitted on the child component's scope root —
2494
+ // matching Hono.
2495
+ // `List` is declared first so `compileToIR` (which picks the first IR)
2496
+ // returns the parent that owns the keyed loop.
2497
+ const source = `
2498
+ "use client"
2499
+ import { createSignal } from "@barefootjs/client"
2500
+ type ItemProps = { label: string; defaultOn?: boolean }
2501
+ export function List({ items }: { items: ItemProps[] }) {
2502
+ return <ul>{items.map((item) => <Item key={item.label} label={item.label} defaultOn={item.defaultOn} />)}</ul>
2503
+ }
2504
+ function Item(props: ItemProps) {
2505
+ const [on] = createSignal(props.defaultOn ?? false)
2506
+ return <div className="item">{on() ? props.label : ''}</div>
2507
+ }
2508
+ `
2509
+ test('Props carries a BfDataKey field', () => {
2510
+ const { types } = compileAndGenerate(source)
2511
+ expect(types).toContain('BfDataKey string `json:"-"`')
2512
+ })
2513
+
2514
+ test('loop-child init stamps BfDataKey from the loop key (item.Label)', () => {
2515
+ const { types } = compileAndGenerate(source)
2516
+ expect(types).toContain('[i].BfDataKey = fmt.Sprint(item.Label)')
2517
+ expect(types).toContain('\t"fmt"')
2518
+ })
2519
+
2520
+ test('child component root emits data-key from BfDataKey', () => {
2521
+ const { template } = compileAndGenerate(source)
2522
+ // Space is inside the `{{if}}` so a non-keyed render adds nothing.
2523
+ expect(template).toContain('{{if .BfDataKey}} data-key="{{.BfDataKey}}"{{end}}')
2524
+ })
2525
+ })
2526
+
2496
2527
  describe('GoTemplateAdapter - #1448 Tier A/B fixture-driven lowering pins', () => {
2497
2528
  const cases = [
2498
2529
  // The `.includes` fixtures sit at condition position
@@ -82,6 +82,10 @@ type GoRenderCtx = {
82
82
  interface NestedComponentInfo extends IRLoopChildComponent {
83
83
  isDynamic: boolean
84
84
  isPropDerived: boolean
85
+ /** The enclosing loop's `key` expression (e.g. `item.label`) and map param
86
+ * name (`item`), so the loop-child init can stamp `data-key` per item. */
87
+ loopKey?: string
88
+ loopParam?: string
85
89
  }
86
90
 
87
91
  interface StaticChildInstance {
@@ -104,6 +108,16 @@ interface StaticChildInstance {
104
108
  * through the parent's `{{.Children}}` read; those cases stay on
105
109
  * the existing drop path. */
106
110
  childrenHtml: string | null
111
+ /** Go string-concat expression for hoisted-JSX children that carry a
112
+ * `needsScope` root (`children={<span/>}` — #1326 / #1335). The root's
113
+ * `bf-s` resolves to the PARENT scope (mirroring the client
114
+ * `__BF_PARENT_SCOPE__` placeholder + Mojo's begin/end capture), so the
115
+ * fragment can't bake to a static string — the runtime `scopeID` is
116
+ * spliced in (`"<span bf-s=\"" + scopeID + "\">x</span>"`). Null when the
117
+ * static `childrenHtml` path already covers the children, or when any
118
+ * other template action survives (genuinely dynamic — kept on the drop
119
+ * path). */
120
+ childrenScopedHtmlExpr: string | null
107
121
  /**
108
122
  * Context values from enclosing `<Ctx.Provider value>` ancestors
109
123
  * (`createContext` identifier → Go value literal), wired into this child
@@ -287,6 +301,48 @@ function capitalize(s: string): string {
287
301
  return s[0].toUpperCase() + s.slice(1)
288
302
  }
289
303
 
304
+ /**
305
+ * Lower a keyed-loop `key` expression to the Go field path on the loop's range
306
+ * variable (always `item` in the generated `for i, item := range …`), e.g.
307
+ * `item.label` → `item.Label`. Returns null for a non-simple key (computed
308
+ * expression, whole-element key, mismatched param) so the loop-child init just
309
+ * skips `data-key` rather than emitting something that won't compile. (#1297)
310
+ */
311
+ function loopKeyToGoFieldPath(key: string | undefined, param: string | undefined): string | null {
312
+ if (!key || !param) return null
313
+ const segs = key.split('.')
314
+ if (segs[0] !== param) return null
315
+ const rest = segs.slice(1)
316
+ if (rest.length === 0) return null
317
+ if (!rest.every(s => /^[A-Za-z_]\w*$/.test(s))) return null
318
+ return 'item.' + rest.map(capitalize).join('.')
319
+ }
320
+
321
+ /**
322
+ * Collect the component's root scope element node(s) — the elements that become
323
+ * the rendered root and so carry `data-key` for a keyed loop item. A plain
324
+ * element root is itself; an `if-statement` (early-return) root contributes the
325
+ * top element of each branch, since exactly one renders at runtime. (#1297)
326
+ */
327
+ function collectRootScopeNodes(node: IRNode): Set<IRNode> {
328
+ const out = new Set<IRNode>()
329
+ const visit = (n: IRNode | null): void => {
330
+ if (!n) return
331
+ if (n.type === 'element') { out.add(n); return }
332
+ if (n.type === 'if-statement') {
333
+ const s = n as IRIfStatement
334
+ visit(s.consequent)
335
+ visit(s.alternate)
336
+ return
337
+ }
338
+ if (n.type === 'fragment') {
339
+ for (const c of (n as IRFragment).children) visit(c)
340
+ }
341
+ }
342
+ visit(node)
343
+ return out
344
+ }
345
+
290
346
  /**
291
347
  * Convert a slot ID (e.g., 's6') to a Go struct field suffix (e.g., 'Slot6').
292
348
  * Keeps field names human-readable regardless of the internal slot ID format.
@@ -342,6 +398,11 @@ const GO_TEMPLATE_PRIMITIVES: Record<string, PrimitiveSpec> = {
342
398
  export class GoTemplateAdapter extends BaseAdapter implements ParsedExprEmitter, IRNodeEmitter<GoRenderCtx> {
343
399
  name = 'go-template'
344
400
  extension = '.tmpl'
401
+
402
+ // Sentinel marking a parent-scope `bf-s` slot inside a hoisted-JSX
403
+ // children bake (see `extractScopedHtmlChildren`). The token can't appear
404
+ // in real HTML text, so splitting on it is unambiguous.
405
+ private static readonly SCOPE_SENTINEL = '__BF_SCOPE_SENTINEL__'
345
406
  // Template-string target with no component layer: `bf build` emits a static
346
407
  // `barefoot-importmap.html` to `{{ template }}` into the page <head> (#1644).
347
408
  importMapInjection = 'html-snippet' as const
@@ -440,6 +501,10 @@ export class GoTemplateAdapter extends BaseAdapter implements ParsedExprEmitter,
440
501
  /** Set during type generation when any emit references
441
502
  * `template.HTML(...)`; toggles the `"html/template"` import. */
442
503
  private usesHtmlTemplate: boolean = false
504
+ /** Component root scope element(s) — each carries `data-key` for a keyed loop
505
+ * item. A plain element root is one node; an `if-statement` (early-return)
506
+ * root contributes the top element of every branch. (#1297) */
507
+ private rootScopeNodes: Set<IRNode> = new Set()
443
508
 
444
509
  /** Set during type generation when any emit references
445
510
  * `fmt.Sprint(...)` — e.g. a `Record<staticKeys, scalar>[propKey]`
@@ -566,6 +631,7 @@ export class GoTemplateAdapter extends BaseAdapter implements ParsedExprEmitter,
566
631
  const isRootComponent = ir.root.type === 'component'
567
632
  const isIfStatement = ir.root.type === 'if-statement'
568
633
 
634
+ this.rootScopeNodes = collectRootScopeNodes(ir.root)
569
635
  const templateBody = isIfStatement
570
636
  ? this.renderIfStatement(ir.root as IRIfStatement, { isRootOfClientComponent: hasInteractivity })
571
637
  : this.renderNode(ir.root, { isRootOfClientComponent: hasInteractivity && isRootComponent })
@@ -1343,6 +1409,9 @@ export class GoTemplateAdapter extends BaseAdapter implements ParsedExprEmitter,
1343
1409
  // Emitted as bf-h / bf-m HTML attributes by `bfHydrationAttrs`.
1344
1410
  lines.push('\tBfParent string `json:"-"`')
1345
1411
  lines.push('\tBfMount string `json:"-"`')
1412
+ // (#1297) Keyed-loop reconciliation key, stamped per item by the parent's
1413
+ // loop init and emitted as `data-key` on this component's scope root.
1414
+ lines.push('\tBfDataKey string `json:"-"`')
1346
1415
 
1347
1416
  // Add Scripts field for dynamic script collection
1348
1417
  lines.push('\tScripts *bf.ScriptCollector `json:"-"`')
@@ -1533,6 +1602,13 @@ export class GoTemplateAdapter extends BaseAdapter implements ParsedExprEmitter,
1533
1602
  // mark it as a slot-attached child of this scope.
1534
1603
  lines.push(`\t\t${varName}[i].BfParent = scopeID`)
1535
1604
  lines.push(`\t\t${varName}[i].BfMount = "${nested.slotId}"`)
1605
+ // (#1297) Stamp the keyed-loop `data-key` per item from the loop's
1606
+ // `key` expression (`item.label` → `item.Label`), matching Hono.
1607
+ const keyField = loopKeyToGoFieldPath(nested.loopKey, nested.loopParam)
1608
+ if (keyField) {
1609
+ lines.push(`\t\t${varName}[i].BfDataKey = fmt.Sprint(${keyField})`)
1610
+ this.usesFmt = true
1611
+ }
1536
1612
  lines.push('\t}')
1537
1613
  lines.push('')
1538
1614
  }
@@ -1764,6 +1840,11 @@ export class GoTemplateAdapter extends BaseAdapter implements ParsedExprEmitter,
1764
1840
  } else if (child.childrenHtml !== null) {
1765
1841
  this.usesHtmlTemplate = true
1766
1842
  lines.push(`\t\t\tChildren: template.HTML(${JSON.stringify(child.childrenHtml)}),`)
1843
+ } else if (child.childrenScopedHtmlExpr !== null) {
1844
+ // Hoisted-JSX children with a needsScope root (#1326 / #1335): the
1845
+ // root `bf-s` is the runtime parent scopeID, spliced into the bake.
1846
+ this.usesHtmlTemplate = true
1847
+ lines.push(`\t\t\tChildren: template.HTML(${child.childrenScopedHtmlExpr}),`)
1767
1848
  }
1768
1849
  lines.push(`\t\t}),`)
1769
1850
  }
@@ -1823,6 +1904,8 @@ export class GoTemplateAdapter extends BaseAdapter implements ParsedExprEmitter,
1823
1904
  ...loop.childComponent,
1824
1905
  isDynamic: !loop.isStaticArray,
1825
1906
  isPropDerived: !!loop.isPropDerivedArray,
1907
+ loopKey: loop.key ?? undefined,
1908
+ loopParam: loop.param ?? undefined,
1826
1909
  })
1827
1910
  }
1828
1911
  }
@@ -1890,6 +1973,17 @@ export class GoTemplateAdapter extends BaseAdapter implements ParsedExprEmitter,
1890
1973
  * "drop children" fallback. Dynamic / component-bearing children
1891
1974
  * stay on the drop path until a re-evaluation hook lands.
1892
1975
  */
1976
+ /**
1977
+ * Pull the IR nodes out of a `children={<…/>}` attribute (a `jsx-children`
1978
+ * prop value). Empty when the component takes no such prop. (#1326 / #1335)
1979
+ */
1980
+ private jsxChildrenPropNodes(props: IRProp[]): IRNode[] {
1981
+ for (const p of props) {
1982
+ if (p.value.kind === 'jsx-children') return p.value.children
1983
+ }
1984
+ return []
1985
+ }
1986
+
1893
1987
  private extractHtmlChildren(children: IRNode[]): string | null {
1894
1988
  if (children.length === 0) return null
1895
1989
  if (children.every(c => c.type === 'text')) return null
@@ -1898,6 +1992,38 @@ export class GoTemplateAdapter extends BaseAdapter implements ParsedExprEmitter,
1898
1992
  return html
1899
1993
  }
1900
1994
 
1995
+ /**
1996
+ * Build a Go string-concat expression for hoisted-JSX children whose root
1997
+ * carries `needsScope` (`children={<span/>}` — #1326 / #1335). Such roots
1998
+ * render in the PARENT's scope, so their `bf-s` is the runtime parent
1999
+ * `scopeID`, not a bake-time constant. We render the fragment, swap the
2000
+ * parent-scope hydration marker for a sentinel, and splice `scopeID` back
2001
+ * in. Returns null when the plain static `childrenHtml` path already
2002
+ * applies, or when any other template action survives (genuinely dynamic —
2003
+ * those stay on the drop path).
2004
+ */
2005
+ private extractScopedHtmlChildren(children: IRNode[]): string | null {
2006
+ if (children.length === 0) return null
2007
+ if (children.every(c => c.type === 'text')) return null
2008
+ const html = this.renderChildren(children)
2009
+ // The needsScope marker renders parent-scope hydration attrs; in a
2010
+ // hoisted fragment every needsScope root resolves to the parent scopeID,
2011
+ // so collapse the whole marker to a bare `bf-s` sentinel (the empty
2012
+ // bf-h / bf-m attrs are dropped — same shape the client emits).
2013
+ const marker = this.renderScopeMarker('.ScopeID')
2014
+ const withSentinel = html
2015
+ .split(marker)
2016
+ .join(`bf-s="${GoTemplateAdapter.SCOPE_SENTINEL}"`)
2017
+ // No sentinel → no needsScope root → the static childrenHtml path covers it.
2018
+ if (!withSentinel.includes(GoTemplateAdapter.SCOPE_SENTINEL)) return null
2019
+ // Any surviving action means the fragment is genuinely dynamic.
2020
+ if (withSentinel.includes('{{')) return null
2021
+ return withSentinel
2022
+ .split(GoTemplateAdapter.SCOPE_SENTINEL)
2023
+ .map(seg => JSON.stringify(seg))
2024
+ .join(' + scopeID + ')
2025
+ }
2026
+
1901
2027
  private collectStaticChildInstancesRecursive(
1902
2028
  node: IRNode,
1903
2029
  result: StaticChildInstance[],
@@ -1920,13 +2046,21 @@ export class GoTemplateAdapter extends BaseAdapter implements ParsedExprEmitter,
1920
2046
  // Skip components inside loops (handled by nestedComponents)
1921
2047
  if (comp.name !== 'Portal' && !inLoop && comp.slotId) {
1922
2048
  const suffix = slotIdToFieldSuffix(comp.slotId)
2049
+ // Children handed in as a `children={<…/>}` attribute (#1326 / #1335)
2050
+ // land as a `jsx-children` prop rather than nested between the tags;
2051
+ // treat them as the child's effective children when no nested ones
2052
+ // exist, so the bake paths below see them.
2053
+ const effectiveChildren = comp.children.length > 0
2054
+ ? comp.children
2055
+ : this.jsxChildrenPropNodes(comp.props)
1923
2056
  result.push({
1924
2057
  name: comp.name,
1925
2058
  slotId: comp.slotId,
1926
2059
  props: comp.props,
1927
2060
  fieldName: `${comp.name}${suffix}`,
1928
- childrenText: this.extractTextChildren(comp.children),
1929
- childrenHtml: this.extractHtmlChildren(comp.children),
2061
+ childrenText: this.extractTextChildren(effectiveChildren),
2062
+ childrenHtml: this.extractHtmlChildren(effectiveChildren),
2063
+ childrenScopedHtmlExpr: this.extractScopedHtmlChildren(effectiveChildren),
1930
2064
  contextBindings: providerCtx.size > 0 ? providerCtx : undefined,
1931
2065
  })
1932
2066
  }
@@ -3664,6 +3798,14 @@ export class GoTemplateAdapter extends BaseAdapter implements ParsedExprEmitter,
3664
3798
  if (element.needsScope) {
3665
3799
  hydrationAttrs += ` ${this.renderScopeMarker('.ScopeID')}`
3666
3800
  }
3801
+ // (#1297) A root scope element carries `data-key` for a keyed loop item —
3802
+ // the parent's loop init stamped `.BfDataKey`, so a non-keyed render emits
3803
+ // nothing. Mirrors Hono stamping data-key on each loop item's scope root,
3804
+ // including early-return (if-statement) roots where every branch's top
3805
+ // element qualifies.
3806
+ if (this.rootScopeNodes.has(element) && element.needsScope) {
3807
+ hydrationAttrs += `{{if .BfDataKey}} data-key="{{.BfDataKey}}"{{end}}`
3808
+ }
3667
3809
  if (element.slotId) {
3668
3810
  hydrationAttrs += ` ${this.renderSlotMarker(element.slotId)}`
3669
3811
  }
@@ -5711,7 +5853,7 @@ export class GoTemplateAdapter extends BaseAdapter implements ParsedExprEmitter,
5711
5853
  return `{{block "${slotName}" .}}{{end}}`
5712
5854
  }
5713
5855
 
5714
- renderAsync(node: IRAsync): string {
5856
+ override renderAsync(node: IRAsync): string {
5715
5857
  const fallback = this.renderNode(node.fallback)
5716
5858
  const children = this.renderChildren(node.children)
5717
5859
  // Go templates use the OOS protocol: render a placeholder with fallback,
@@ -2,5 +2,5 @@
2
2
  * Go html/template Adapter Exports
3
3
  */
4
4
 
5
- export { GoTemplateAdapter, goTemplateAdapter } from './go-template-adapter'
6
- export type { GoTemplateAdapterOptions } from './go-template-adapter'
5
+ export { GoTemplateAdapter, goTemplateAdapter } from './go-template-adapter.ts'
6
+ export type { GoTemplateAdapterOptions } from './go-template-adapter.ts'
package/src/build.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  // Go template build config factory for barefoot.config.ts
2
2
 
3
3
  import type { BuildOptions, PostBuildContext } from '@barefootjs/jsx'
4
- import { GoTemplateAdapter } from './adapter'
5
- import type { GoTemplateAdapterOptions } from './adapter'
4
+ import { GoTemplateAdapter } from './adapter/index.ts'
5
+ import type { GoTemplateAdapterOptions } from './adapter/index.ts'
6
6
 
7
7
  export interface GoTemplateBuildOptions extends BuildOptions {
8
8
  /** Adapter-specific options passed to GoTemplateAdapter */
@@ -156,13 +156,26 @@ export function combineGoTypes(options: {
156
156
  combinedContent = transformTypes(combinedContent)
157
157
  }
158
158
 
159
+ // Conditionally pull in stdlib packages the combined component code uses.
160
+ // Per-component import blocks are stripped above, so the merged file needs
161
+ // its own block — `fmt` (e.g. `fmt.Sprint` for keyed-loop data-key /
162
+ // indexed-map spread) and `html/template` (`template.HTML` for forwarded
163
+ // JSX children) are only imported when actually referenced, so an app that
164
+ // uses neither doesn't get an "imported and not used" error.
165
+ const usageScan = combinedContent + '\n' + (manualTypes ?? '')
166
+ const stdlibImports: string[] = [`\t"math/rand"`]
167
+ if (/\bfmt\./.test(usageScan)) stdlibImports.push(`\t"fmt"`)
168
+ if (/\btemplate\.HTML\b/.test(usageScan)) stdlibImports.push(`\t"html/template"`)
169
+ // gofmt sorts the stdlib group alphabetically by import path.
170
+ stdlibImports.sort()
171
+
159
172
  // Build final file
160
173
  const parts = [
161
174
  `// Code generated by BarefootJS. DO NOT EDIT.`,
162
175
  `package ${packageName}`,
163
176
  '',
164
177
  `import (`,
165
- `\t"math/rand"`,
178
+ ...stdlibImports,
166
179
  '',
167
180
  `\tbf "github.com/barefootjs/runtime/bf"`,
168
181
  `)`,
package/src/index.ts CHANGED
@@ -4,5 +4,5 @@
4
4
  * Generates Go html/template files from BarefootJS IR.
5
5
  */
6
6
 
7
- export { GoTemplateAdapter, goTemplateAdapter } from './adapter'
8
- export type { GoTemplateAdapterOptions } from './adapter'
7
+ export { GoTemplateAdapter, goTemplateAdapter } from './adapter/index.ts'
8
+ export type { GoTemplateAdapterOptions } from './adapter/index.ts'
@@ -7,6 +7,20 @@
7
7
 
8
8
  import { compileJSX } from '@barefootjs/jsx'
9
9
  import type { TemplateAdapter, ComponentIR } from '@barefootjs/jsx'
10
+ import { GoTemplateAdapter } from './adapter/go-template-adapter.ts'
11
+
12
+ /**
13
+ * Capitalize a JSON key to its Go struct field name using the same
14
+ * initialism rules as the adapter (`capitalizeFieldName`): a whole-word Go
15
+ * initialism uppercases entirely (`id` → `ID`), otherwise just the first
16
+ * letter. Keeps harness-emitted struct literals (`ItemInput{ID: …}`) matching
17
+ * the generated exported field names. (#1297)
18
+ */
19
+ function capitalizeGoField(name: string): string {
20
+ if (!name) return name
21
+ if (GoTemplateAdapter.GO_INITIALISMS.has(name.toLowerCase())) return name.toUpperCase()
22
+ return name.charAt(0).toUpperCase() + name.slice(1)
23
+ }
10
24
  import { mkdir, rm } from 'node:fs/promises'
11
25
  import { resolve } from 'node:path'
12
26
 
@@ -259,8 +273,9 @@ export async function renderGoTemplateComponent(options: RenderOptions): Promise
259
273
  // template content as Go raw string
260
274
  const escapedTemplate = template.replace(/`/g, '` + "`" + `')
261
275
 
262
- // Build props initialization
263
- const propsInit = buildGoPropsInit(componentName, props, ir)
276
+ // Build props initialization (typed against the generated Input struct so
277
+ // an array-of-objects prop emits e.g. `[]ToggleItemInput{…}`, not `[]any`).
278
+ const propsInit = buildGoPropsInit(componentName, props, ir, goTypes)
264
279
 
265
280
  // Honour `__instanceId` from props for the root scope id so
266
281
  // shared-component fixtures (which pin `<ComponentName>_test`) match
@@ -470,9 +485,10 @@ function ensureMergedStdlibImports(goTypes: string): string {
470
485
  * Build Go struct field initializers from props.
471
486
  */
472
487
  function buildGoPropsInit(
473
- _componentName: string,
488
+ componentName: string,
474
489
  props?: Record<string, unknown>,
475
490
  ir?: ComponentIR,
491
+ goTypes?: string,
476
492
  ): string {
477
493
  if (!props) return ''
478
494
 
@@ -517,16 +533,25 @@ function buildGoPropsInit(
517
533
  } else if (typeof value === 'boolean') {
518
534
  lines.push(`\t\t${goField}: ${value},`)
519
535
  } else if (Array.isArray(value)) {
520
- // Array → Go `[]any` literal. Fixtures that exercise
521
- // array-receiver methods (`items.every(...)`, `items.join(' - ')`,
522
- // etc. — #1448 method catalog) need the prop value to reach
523
- // the rendered template as a real slice so `range .Items` /
524
- // `bf_join (.Items) ...` see actual elements; without this
525
- // branch the prop was silently dropped, the input-struct
526
- // field stayed at its zero value, and the template rendered
527
- // empty content alongside the expected wrappers (the bug
528
- // surfaced as "expected 'idx: 1' / got 'idx:'" on CI).
529
- lines.push(`\t\t${goField}: ${goArrayLiteralFromArray(value)},`)
536
+ // Array → Go slice literal. Fixtures that exercise array-receiver
537
+ // methods (`items.every(...)`, `items.join(' - ')`, etc. — #1448
538
+ // method catalog) need the prop value to reach the rendered template
539
+ // as a real slice so `range .Items` / `bf_join (.Items) ...` see
540
+ // actual elements.
541
+ //
542
+ // When the Input field is a typed slice (`ToggleItems
543
+ // []ToggleItemInput`, a loop-child array prop), emit a matching
544
+ // typed literal (`[]ToggleItemInput{ToggleItemInput{Label: …}, …}`);
545
+ // a bare `[]any{}` would fail to compile against the typed field.
546
+ // Fall back to `[]any` when the field type is `[]any` / unknown.
547
+ const elemType = goSliceElemType(goTypes, componentName, goField)
548
+ lines.push(
549
+ `\t\t${goField}: ${
550
+ elemType
551
+ ? goTypedSliceLiteralFromArray(value, elemType)
552
+ : goArrayLiteralFromArray(value)
553
+ },`,
554
+ )
530
555
  } else if (value && typeof value === 'object') {
531
556
  // Plain object → Go `map[string]any` literal (#1407 follow-up).
532
557
  // Used by `jsx-spread-rest-prop` to populate the input-bag
@@ -546,6 +571,66 @@ function buildGoPropsInit(
546
571
  return lines.join('\n')
547
572
  }
548
573
 
574
+ /**
575
+ * Look up the element type of a typed slice field on the entry component's
576
+ * `<Component>Input` struct (e.g. `ToggleItems []ToggleItemInput` →
577
+ * `ToggleItemInput`). Returns null when the field is absent, isn't a slice, or
578
+ * is an untyped `[]any` / `[]interface{}` (those keep the generic `[]any`
579
+ * harness literal). (#1297, toggle-shared)
580
+ */
581
+ function goSliceElemType(
582
+ goTypes: string | undefined,
583
+ componentName: string,
584
+ goField: string,
585
+ ): string | null {
586
+ if (!goTypes) return null
587
+ const struct = goTypes.match(
588
+ new RegExp(`type ${componentName}Input struct \\{([\\s\\S]*?)\\n\\}`),
589
+ )
590
+ if (!struct) return null
591
+ const field = struct[1].match(new RegExp(`\\n\\s*${goField}\\s+\\[\\]([\\w.]+)`))
592
+ if (!field) return null
593
+ const elem = field[1]
594
+ if (elem === 'any' || elem === 'interface{}') return null
595
+ return elem
596
+ }
597
+
598
+ /**
599
+ * Emit a typed Go slice literal (`[]Elem{Elem{…}, …}`). Object elements become
600
+ * keyed struct literals with PascalCase field names; scalar elements (for an
601
+ * `[]string` / `[]int` field) are emitted bare. (#1297, toggle-shared)
602
+ */
603
+ function goTypedSliceLiteralFromArray(arr: unknown[], elemType: string): string {
604
+ const entries = arr.map(v => {
605
+ if (v && typeof v === 'object' && !Array.isArray(v)) {
606
+ return goStructLiteral(v as Record<string, unknown>, elemType)
607
+ }
608
+ if (typeof v === 'string') return `"${v.replace(/"/g, '\\"')}"`
609
+ if (typeof v === 'number' || typeof v === 'boolean') return String(v)
610
+ if (v === null) return 'nil'
611
+ return goArrayLiteralFromArray(v as unknown[])
612
+ })
613
+ return `[]${elemType}{${entries.join(', ')}}`
614
+ }
615
+
616
+ /**
617
+ * Emit a keyed Go struct literal (`Elem{Field: val, …}`) with PascalCase field
618
+ * names. Only the keys the caller supplied are set, so an omitted optional prop
619
+ * (e.g. `defaultOn` on the third toggle item) takes the Go zero value. (#1297)
620
+ */
621
+ function goStructLiteral(obj: Record<string, unknown>, typeName: string): string {
622
+ const fields: string[] = []
623
+ for (const [k, v] of Object.entries(obj)) {
624
+ const goField = capitalizeGoField(k)
625
+ if (typeof v === 'string') fields.push(`${goField}: "${v.replace(/"/g, '\\"')}"`)
626
+ else if (typeof v === 'number' || typeof v === 'boolean') fields.push(`${goField}: ${v}`)
627
+ else if (v === null) fields.push(`${goField}: nil`)
628
+ else if (Array.isArray(v)) fields.push(`${goField}: ${goArrayLiteralFromArray(v)}`)
629
+ else if (v && typeof v === 'object') fields.push(`${goField}: ${goMapLiteralFromObject(v as Record<string, unknown>, true)}`)
630
+ }
631
+ return `${typeName}{${fields.join(', ')}}`
632
+ }
633
+
549
634
  function goArrayLiteralFromArray(arr: unknown[]): string {
550
635
  const entries: string[] = []
551
636
  for (const v of arr) {