@barefootjs/go-template 0.29.0 → 0.30.2

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/build.js CHANGED
@@ -1312,7 +1312,26 @@ function renderLoweringNode(ctx, node) {
1312
1312
  }
1313
1313
 
1314
1314
  // src/adapter/type/type-codegen.ts
1315
- function typeInfoToGo(ctx, typeInfo, defaultValue) {
1315
+ function collapseLiteralUnion(typeInfo) {
1316
+ if (typeInfo.kind !== "union" || !typeInfo.unionTypes || typeInfo.unionTypes.length === 0) {
1317
+ return typeInfo;
1318
+ }
1319
+ const familyOf = (m) => {
1320
+ if (m.kind !== "primitive")
1321
+ return null;
1322
+ return m.primitive === "string" || m.primitive === "number" || m.primitive === "boolean" ? m.primitive : null;
1323
+ };
1324
+ const first = familyOf(typeInfo.unionTypes[0]);
1325
+ if (!first)
1326
+ return typeInfo;
1327
+ for (const m of typeInfo.unionTypes) {
1328
+ if (familyOf(m) !== first)
1329
+ return typeInfo;
1330
+ }
1331
+ return { kind: "primitive", raw: typeInfo.raw, primitive: first };
1332
+ }
1333
+ function typeInfoToGo(ctx, _typeInfo, defaultValue) {
1334
+ const typeInfo = collapseLiteralUnion(_typeInfo);
1316
1335
  switch (typeInfo.kind) {
1317
1336
  case "primitive":
1318
1337
  switch (typeInfo.primitive) {
@@ -1482,7 +1501,8 @@ function nillableAwarePropRef(ctx, propName, expectedType) {
1482
1501
  }
1483
1502
  return fieldRef;
1484
1503
  }
1485
- function convertInitialValue(ctx, value, typeInfo, propsParams, preParsed) {
1504
+ function convertInitialValue(ctx, value, _typeInfo, propsParams, preParsed) {
1505
+ const typeInfo = collapseLiteralUnion(_typeInfo);
1486
1506
  const propRef = (propName2) => nillableAwarePropRef(ctx, propName2, typeInfo);
1487
1507
  if (/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(value)) {
1488
1508
  if (propsParams?.some((p) => p.name === value)) {
@@ -2430,6 +2450,78 @@ function propsAccessNameFromParsed2(ctx, node) {
2430
2450
  return null;
2431
2451
  return node.property;
2432
2452
  }
2453
+ function collectPropsReadByCtorInit(body, propsObjectName, propNames) {
2454
+ const found = new Set;
2455
+ const visit = (e, bound) => {
2456
+ switch (e.kind) {
2457
+ case "identifier":
2458
+ if (!propsObjectName && propNames.has(e.name) && !bound.has(e.name))
2459
+ found.add(e.name);
2460
+ return;
2461
+ case "member":
2462
+ if (propsObjectName && !e.computed && e.object.kind === "identifier" && e.object.name === propsObjectName) {
2463
+ found.add(e.property);
2464
+ return;
2465
+ }
2466
+ visit(e.object, bound);
2467
+ return;
2468
+ case "index-access":
2469
+ visit(e.object, bound);
2470
+ visit(e.index, bound);
2471
+ return;
2472
+ case "binary":
2473
+ case "logical":
2474
+ visit(e.left, bound);
2475
+ visit(e.right, bound);
2476
+ return;
2477
+ case "unary":
2478
+ visit(e.argument, bound);
2479
+ return;
2480
+ case "conditional":
2481
+ visit(e.test, bound);
2482
+ visit(e.consequent, bound);
2483
+ visit(e.alternate, bound);
2484
+ return;
2485
+ case "call":
2486
+ visit(e.callee, bound);
2487
+ e.args.forEach((a) => visit(a, bound));
2488
+ return;
2489
+ case "template-literal":
2490
+ for (const p of e.parts)
2491
+ if (p.type === "expression")
2492
+ visit(p.expr, bound);
2493
+ return;
2494
+ case "array-literal":
2495
+ e.elements.forEach((el) => visit(el, bound));
2496
+ return;
2497
+ case "object-literal":
2498
+ for (const p of e.properties)
2499
+ visit(p.value, bound);
2500
+ return;
2501
+ case "array-method":
2502
+ visit(e.object, bound);
2503
+ e.args.forEach((a) => visit(a, bound));
2504
+ if (e.method === "flat" && e.depthExpr)
2505
+ visit(e.depthExpr, bound);
2506
+ return;
2507
+ case "arrow": {
2508
+ const inner = e.params.length === 0 ? bound : new Set([...bound, ...e.params]);
2509
+ visit(e.body, inner);
2510
+ return;
2511
+ }
2512
+ case "literal":
2513
+ case "regex":
2514
+ case "unsupported":
2515
+ return;
2516
+ default: {
2517
+ const _exhaustive = e;
2518
+ return;
2519
+ }
2520
+ }
2521
+ };
2522
+ visit(body, new Set);
2523
+ return found;
2524
+ }
2433
2525
 
2434
2526
  // src/adapter/spread/spread-codegen.ts
2435
2527
  import ts2 from "typescript";
@@ -3031,6 +3123,7 @@ class GoTemplateAdapter extends BaseAdapter {
3031
3123
  this.state.pendingChildrenDefines = [];
3032
3124
  this.primeCompileState(ir);
3033
3125
  this.state.stringValueNames = collectStringValueNames(ir);
3126
+ this.recordDerivedFieldDeps(ir, new Set((ir.metadata.propsParams ?? []).map((p) => p.name)));
3034
3127
  if (!options?.siblingTemplatesRegistered) {
3035
3128
  this.checkImportedLoopChildComponents(ir);
3036
3129
  }
@@ -3167,15 +3260,50 @@ ${scriptRegistrations}${templateBody}
3167
3260
  return `{{if .Scripts}}${registrations.join("")}{{end}}
3168
3261
  `;
3169
3262
  }
3263
+ childDerivedFieldDeps = new Map;
3264
+ childPropFieldNames = new Map;
3265
+ childRepropsReady = new Map;
3266
+ repropsOwner = new Map;
3267
+ recordDerivedFieldDeps(ir, paramNames) {
3268
+ const name = ir.metadata.componentName;
3269
+ if (!name)
3270
+ return;
3271
+ const sourceOf = new Map((ir.metadata.propsParams ?? []).map((p) => [p.name, p.sourceName ?? p.name]));
3272
+ const canonical = (local) => capitalizeFieldName(sourceOf.get(local) ?? local);
3273
+ const propFieldNames = new Set([...paramNames].map(canonical));
3274
+ const fieldNames = new Map;
3275
+ for (const p of ir.metadata.propsParams ?? []) {
3276
+ fieldNames.set(p.sourceName ?? p.name, capitalizeFieldName(p.name));
3277
+ }
3278
+ this.childPropFieldNames.set(name, fieldNames);
3279
+ const deps = new Map;
3280
+ const ctorInits = [
3281
+ ...(ir.metadata.memos ?? []).map((m) => ({ field: m.name, init: m.parsed })),
3282
+ ...(ir.metadata.signals ?? []).map((s) => ({ field: s.getter, init: s.parsed }))
3283
+ ];
3284
+ for (const { field, init } of ctorInits) {
3285
+ if (propFieldNames.has(capitalizeFieldName(field)))
3286
+ continue;
3287
+ if (!init)
3288
+ continue;
3289
+ const read = collectPropsReadByCtorInit(init, ir.metadata.propsObjectName ?? null, paramNames);
3290
+ if (read.size === 0)
3291
+ continue;
3292
+ deps.set(field, new Set([...read].map(canonical)));
3293
+ }
3294
+ if (deps.size > 0)
3295
+ this.childDerivedFieldDeps.set(name, deps);
3296
+ }
3170
3297
  registerChildComponentShape(ir) {
3171
3298
  const name = ir.metadata.componentName;
3172
3299
  if (!name)
3173
3300
  return;
3174
- const paramNames = new Set((ir.metadata.propsParams ?? []).map((p) => p.name));
3301
+ const paramNames = new Set((ir.metadata.propsParams ?? []).map((p) => p.sourceName ?? p.name));
3175
3302
  const restPropsName = ir.metadata.restPropsName ?? null;
3176
3303
  const restBagField = restPropsName ? capitalizeFieldName(restPropsName) : null;
3177
- const mapTypedParamNames = new Set((ir.metadata.propsParams ?? []).filter((p) => p.optional && (p.type.kind === "object" || p.type.kind === "interface" && !!p.type.raw)).map((p) => p.name));
3304
+ const mapTypedParamNames = new Set((ir.metadata.propsParams ?? []).filter((p) => p.optional && (p.type.kind === "object" || p.type.kind === "interface" && !!p.type.raw)).map((p) => p.sourceName ?? p.name));
3178
3305
  this.childComponentShapes.set(name, { paramNames, restBagField, mapTypedParamNames });
3306
+ this.recordDerivedFieldDeps(ir, new Set((ir.metadata.propsParams ?? []).map((p) => p.name)));
3179
3307
  this.childContextConsumers.set(name, collectContextConsumers(ir.metadata));
3180
3308
  }
3181
3309
  contextFieldName(c) {
@@ -3244,8 +3372,86 @@ ${scriptRegistrations}${templateBody}
3244
3372
  this.state.needsStringsImport = false;
3245
3373
  this.generatePropsStruct(lines, ir, componentName, nestedComponents, propTypeOverrides, spreadSlots);
3246
3374
  this.generateNewPropsFunction(lines, ir, componentName, nestedComponents, spreadSlots, propTypeOverrides);
3375
+ this.recordRepropsSpec(ir, componentName, nestedComponents, spreadSlots);
3376
+ this.emitOwnedReprops(lines, componentName);
3247
3377
  return this.composeFileHeader(lines);
3248
3378
  }
3379
+ recordRepropsSpec(ir, componentName, nestedComponents, spreadSlots) {
3380
+ if (!this.childDerivedFieldDeps.has(componentName))
3381
+ return;
3382
+ const nestedArrayFields = new Set(nestedComponents.map((n) => `${n.name}s`));
3383
+ const params = (ir.metadata.propsParams ?? []).filter((p) => !nestedArrayFields.has(capitalizeFieldName(p.name)));
3384
+ const takenInput = new Set((ir.metadata.propsParams ?? []).map((p) => capitalizeFieldName(p.name)));
3385
+ const eligible = nestedComponents.every((n) => n.isDynamic && !n.isPropDerived) && spreadSlots.length === 0 && !ir.metadata.restPropsName && this.nonCollidingContextConsumers(takenInput).length === 0;
3386
+ if (!eligible)
3387
+ return;
3388
+ this.childRepropsReady.set(componentName, {
3389
+ params: params.map((p) => capitalizeFieldName(p.name)),
3390
+ usesSearchParams: this.usesSearchParams(ir)
3391
+ });
3392
+ }
3393
+ emitOwnedReprops(lines, owner) {
3394
+ for (const [childName, ownerName] of this.repropsOwner) {
3395
+ if (ownerName !== owner)
3396
+ continue;
3397
+ const spec = this.childRepropsReady.get(childName);
3398
+ if (!spec)
3399
+ continue;
3400
+ this.emitRepropsRegistration(lines, childName, spec);
3401
+ }
3402
+ }
3403
+ emitRepropsRegistration(lines, componentName, spec) {
3404
+ const { params, usesSearchParams } = spec;
3405
+ const inputTypeName = `${componentName}Input`;
3406
+ const q = JSON.stringify(componentName);
3407
+ lines.push(`// ${componentName} computes at least one field from an input prop when its`);
3408
+ lines.push("// props are constructed, so a per-row override inside a composite loop row");
3409
+ lines.push("// cannot be applied by patching fields — the derived field would keep the");
3410
+ lines.push("// shared instance's one-shot value on every row (#2448). This rebuilder");
3411
+ lines.push(`// re-runs New${componentName}Props with the row's overrides folded into the`);
3412
+ lines.push("// Input; the parent calls it through bf_reprops.");
3413
+ lines.push("func init() {");
3414
+ lines.push(` bf.RegisterReprops(${q}, func(base interface{}, kv ...interface{}) (interface{}, error) {`);
3415
+ lines.push(` b, ok := base.(${componentName}Props)`);
3416
+ lines.push("\t\tif !ok {");
3417
+ lines.push(` return nil, bf.RepropsTypeError(${q}, base)`);
3418
+ lines.push("\t\t}");
3419
+ lines.push(` in := ${inputTypeName}{`);
3420
+ lines.push("\t\t\tScopeID: b.ScopeID,");
3421
+ lines.push("\t\t\tBfParent: b.BfParent,");
3422
+ lines.push("\t\t\tBfMount: b.BfMount,");
3423
+ if (usesSearchParams)
3424
+ lines.push("\t\t\tSearchParams: b.SearchParams,");
3425
+ for (const field of params) {
3426
+ lines.push(` ${field}: b.${field},`);
3427
+ }
3428
+ lines.push("\t\t}");
3429
+ lines.push("\t\tfor i := 0; i < len(kv); i += 2 {");
3430
+ lines.push("\t\t\tname, _ := kv[i].(string)");
3431
+ lines.push("\t\t\tvar err error");
3432
+ lines.push("\t\t\tswitch name {");
3433
+ for (const field of params) {
3434
+ lines.push(` case ${JSON.stringify(field)}:`);
3435
+ lines.push(` err = bf.RepropsAssign(${q}, ${JSON.stringify(field)}, &in.${field}, kv[i+1])`);
3436
+ }
3437
+ lines.push("\t\t\tdefault:");
3438
+ lines.push(` err = bf.RepropsUnknownFieldError(${q}, name)`);
3439
+ lines.push("\t\t\t}");
3440
+ lines.push("\t\t\tif err != nil {");
3441
+ lines.push("\t\t\t\treturn nil, err");
3442
+ lines.push("\t\t\t}");
3443
+ lines.push("\t\t}");
3444
+ lines.push(` p := New${componentName}Props(in)`);
3445
+ lines.push("\t\t// Props-only state, absent from Input and therefore not rebuilt.");
3446
+ lines.push("\t\tp.Scripts = b.Scripts");
3447
+ lines.push("\t\tp.BfIsRoot = b.BfIsRoot");
3448
+ lines.push("\t\tp.BfIsChild = b.BfIsChild");
3449
+ lines.push("\t\tp.BfDataKey = b.BfDataKey");
3450
+ lines.push("\t\treturn p, nil");
3451
+ lines.push("\t})");
3452
+ lines.push("}");
3453
+ lines.push("");
3454
+ }
3249
3455
  typeDefinitionToGo(td) {
3250
3456
  if (td.definition.match(/^type \w+ = ('[^']*'(\s*\|\s*'[^']*')*)/)) {
3251
3457
  return `// ${td.name} is a string type.
@@ -3729,7 +3935,8 @@ ${goFields.join(`
3729
3935
  }
3730
3936
  if (jsxName.includes("-"))
3731
3937
  return;
3732
- lines.push(` ${capitalizeFieldName(jsxName)}: ${goValue},`);
3938
+ const fieldName = this.childPropFieldNames.get(child.name)?.get(jsxName) ?? capitalizeFieldName(jsxName);
3939
+ lines.push(` ${fieldName}: ${goValue},`);
3733
3940
  };
3734
3941
  for (const prop of child.props) {
3735
3942
  switch (prop.value.kind) {
@@ -5713,6 +5920,78 @@ ${goFields.join(`
5713
5920
  isLoopShadowedName(name) {
5714
5921
  return this.loopParamStack.length > 0 && this.loopParamStack[this.loopParamStack.length - 1] === name || this.loopVarRefCount.has(name) || this.isOuterLoopParam(name) || this.loopBindingStack.some((bindings) => bindings.has(name));
5715
5922
  }
5923
+ loopRowChildPropOverrides(comp) {
5924
+ const childShape = this.childComponentShapes.get(comp.name);
5925
+ const args = [];
5926
+ let needsRebuild = false;
5927
+ for (const prop of comp.props) {
5928
+ if (prop.clientOnly)
5929
+ continue;
5930
+ if (prop.name === "key" || prop.name === "children")
5931
+ continue;
5932
+ if (prop.name.startsWith("on") && prop.name.length > 2)
5933
+ continue;
5934
+ if (prop.name.includes("-"))
5935
+ continue;
5936
+ if (childShape?.restBagField && !childShape.paramNames.has(prop.name))
5937
+ continue;
5938
+ if (prop.value.kind !== "expression")
5939
+ continue;
5940
+ const free = prop.freeIdentifiers;
5941
+ if (!free || ![...free].some((name) => this.isLoopShadowedName(name)))
5942
+ continue;
5943
+ {
5944
+ const derived = this.childDerivedFieldDeps.get(comp.name);
5945
+ const overriddenField = capitalizeFieldName(prop.name);
5946
+ const staleField = derived ? [...derived].find(([, deps]) => deps.has(overriddenField))?.[0] : undefined;
5947
+ if (staleField && !this.childRepropsReady.has(comp.name)) {
5948
+ this.state.errors.push({
5949
+ code: "BF101",
5950
+ severity: "error",
5951
+ message: `Prop '${prop.name}' on <${comp.name}> nested inside a dynamic loop row is overridden per row, but <${comp.name}>'s '${staleField}' field is computed from '${prop.name}' when the shared instance is first constructed and won't recompute per row — it would keep the first row's value on every row.`,
5952
+ loc: prop.loc,
5953
+ suggestion: {
5954
+ message: `Mark this loop position '@client' to render <${comp.name}> client-side, or compute '${staleField}' in the parent and pass it to <${comp.name}> as a plain prop instead of deriving it inside <${comp.name}>.`
5955
+ }
5956
+ });
5957
+ continue;
5958
+ }
5959
+ if (staleField) {
5960
+ needsRebuild = true;
5961
+ if (!this.repropsOwner.has(comp.name)) {
5962
+ this.repropsOwner.set(comp.name, this.state.componentName);
5963
+ }
5964
+ }
5965
+ }
5966
+ const exprOut = {};
5967
+ const errorCountBefore = this.state.errors.length;
5968
+ let go = this.convertExpressionToGo(prop.value.expr, exprOut, prop.value.parsed);
5969
+ if (this.state.errors.length > errorCountBefore) {
5970
+ for (let i = errorCountBefore;i < this.state.errors.length; i++) {
5971
+ this.state.errors[i].loc = prop.loc;
5972
+ }
5973
+ continue;
5974
+ }
5975
+ const singlePartTemplateLiteral = exprOut.parsed?.kind === "template-literal" && exprOut.parsed.parts.length === 1 && exprOut.parsed.parts[0].type !== "string" && go.startsWith("{{") && go.endsWith("}}");
5976
+ if (singlePartTemplateLiteral) {
5977
+ go = go.slice(2, -2);
5978
+ }
5979
+ if (!singlePartTemplateLiteral && this.isTemplateFragment(go, exprOut.parsed?.kind)) {
5980
+ this.state.errors.push({
5981
+ code: "BF101",
5982
+ severity: "error",
5983
+ message: `Prop '${prop.name}' on <${comp.name}> nested inside a dynamic loop row reads the row but can't be lowered to a Go template pipeline argument`,
5984
+ loc: prop.loc
5985
+ });
5986
+ continue;
5987
+ }
5988
+ const fieldName = this.childPropFieldNames.get(comp.name)?.get(prop.name) ?? capitalizeFieldName(prop.name);
5989
+ args.push(`${JSON.stringify(fieldName)} ${wrapIfMultiToken(go)}`);
5990
+ }
5991
+ if (args.length === 0)
5992
+ return null;
5993
+ return { args: args.join(" "), helper: needsRebuild ? "bf_reprops" : "bf_with_props" };
5994
+ }
5716
5995
  resolveStaticRecordLiteralIndex(jsExpr) {
5717
5996
  const m = /^([A-Za-z_$][\w$]*)\[\s*(?:'([^']*)'|"([^"]*)")\s*\]$/.exec(jsExpr) ?? /^([A-Za-z_$][\w$]*)\.([A-Za-z_$][\w$]*)$/.exec(jsExpr);
5718
5997
  if (!m)
@@ -6122,6 +6401,10 @@ ${goFields.join(`
6122
6401
  }
6123
6402
  this.inLoop = true;
6124
6403
  const addedLoopVars = [];
6404
+ for (const d of loop.preamble?.declarations ?? []) {
6405
+ this.loopVarRefCount.set(d.name, (this.loopVarRefCount.get(d.name) ?? 0) + 1);
6406
+ addedLoopVars.push(d.name);
6407
+ }
6125
6408
  let pushedBindingMap = false;
6126
6409
  if (supportableDestructure) {
6127
6410
  const built = this.buildDestructureBindingMap(loop, rangeValue);
@@ -6147,6 +6430,7 @@ ${goFields.join(`
6147
6430
  this.loopScalarItemStack.push(this.scalarLiteralLoopGoType(loop.arrayParsed, loop.itemType) !== null);
6148
6431
  this.loopWrapperStack.push(!!loop.childComponent);
6149
6432
  this.loopKeyDepthStack.push(loop.depth);
6433
+ const preambleAssignments = (loop.preamble?.declarations ?? []).map((d) => `{{$${d.name} := ${this.renderParsedExpr(d.valueParsed)}}}`).join("");
6150
6434
  const children = this.renderChildren(loop.children);
6151
6435
  this.loopKeyDepthStack.pop();
6152
6436
  this.loopWrapperStack.pop();
@@ -6181,9 +6465,9 @@ ${goFields.join(`
6181
6465
  } else {
6182
6466
  filterCond = "true";
6183
6467
  }
6184
- return `{{bfComment "loop:${loop.markerId}"}}{{range $${rangeIndex}, $${rangeValue} := ${goArray}}}{{if ${filterCond}}}${itemMarker}${children}{{end}}{{end}}{{bfComment "/loop:${loop.markerId}"}}`;
6468
+ return `{{bfComment "loop:${loop.markerId}"}}{{range $${rangeIndex}, $${rangeValue} := ${goArray}}}{{if ${filterCond}}}${preambleAssignments}${itemMarker}${children}{{end}}{{end}}{{bfComment "/loop:${loop.markerId}"}}`;
6185
6469
  }
6186
- return `{{bfComment "loop:${loop.markerId}"}}{{range $${rangeIndex}, $${rangeValue} := ${goArray}}}${itemMarker}${children}{{end}}{{bfComment "/loop:${loop.markerId}"}}`;
6470
+ return `{{bfComment "loop:${loop.markerId}"}}{{range $${rangeIndex}, $${rangeValue} := ${goArray}}}${preambleAssignments}${itemMarker}${children}{{end}}{{bfComment "/loop:${loop.markerId}"}}`;
6187
6471
  }
6188
6472
  renderUnrolledStaticElementLoop(loop, items) {
6189
6473
  this.inLoop = true;
@@ -6282,8 +6566,10 @@ ${goFields.join(`
6282
6566
  }
6283
6567
  } else if (this.inLoop && comp.slotId) {
6284
6568
  const suffix = slotIdToFieldSuffix(comp.slotId);
6569
+ const overrides = this.loopRowChildPropOverrides(comp);
6285
6570
  const loopBodyDefine = this.queueLoopBodyChildrenDefine(comp);
6286
- templateCall = loopBodyDefine ? `{{template "${comp.name}" (bf_with_children $.${comp.name}${suffix} (bf_tmpl "${loopBodyDefine}" .))}}` : `{{template "${comp.name}" $.${comp.name}${suffix}}}`;
6571
+ const base = overrides ? overrides.helper === "bf_reprops" ? `(bf_reprops ${JSON.stringify(comp.name)} $.${comp.name}${suffix} ${overrides.args})` : `(bf_with_props $.${comp.name}${suffix} ${overrides.args})` : `$.${comp.name}${suffix}`;
6572
+ templateCall = loopBodyDefine ? `{{template "${comp.name}" (bf_with_children ${base} (bf_tmpl "${loopBodyDefine}" .))}}` : `{{template "${comp.name}" ${base}}}`;
6287
6573
  } else if (this.inLoop) {
6288
6574
  templateCall = `{{template "${comp.name}" .}}`;
6289
6575
  } else if (comp.slotId) {
@@ -1 +1 @@
1
- {"version":3,"file":"conformance-pins.d.ts","sourceRoot":"","sources":["../src/conformance-pins.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEtD,eAAO,MAAM,eAAe,EAAE,eAqL7B,CAAA"}
1
+ {"version":3,"file":"conformance-pins.d.ts","sourceRoot":"","sources":["../src/conformance-pins.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEtD,eAAO,MAAM,eAAe,EAAE,eAgL7B,CAAA"}