@barefootjs/hono 0.5.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapter/hono-adapter.d.ts +9 -2
- package/dist/adapter/hono-adapter.d.ts.map +1 -1
- package/dist/adapter/index.js +21 -6
- package/dist/build.js +21 -6
- package/dist/index.js +21 -6
- package/package.json +1 -1
- package/src/adapter/hono-adapter.ts +52 -6
|
@@ -78,7 +78,7 @@ export declare class HonoAdapter extends JsxAdapter implements IRNodeEmitter<Hon
|
|
|
78
78
|
emitElement(node: IRElement, ctx: HonoRenderCtx, _emit: EmitIRNode<HonoRenderCtx>): string;
|
|
79
79
|
emitText(node: IRText): string;
|
|
80
80
|
emitExpression(node: IRExpression): string;
|
|
81
|
-
emitConditional(node: IRConditional,
|
|
81
|
+
emitConditional(node: IRConditional, ctx: HonoRenderCtx, _emit: EmitIRNode<HonoRenderCtx>): string;
|
|
82
82
|
emitLoop(node: IRLoop, _ctx: HonoRenderCtx, _emit: EmitIRNode<HonoRenderCtx>): string;
|
|
83
83
|
emitComponent(node: IRComponent, ctx: HonoRenderCtx, _emit: EmitIRNode<HonoRenderCtx>): string;
|
|
84
84
|
emitFragment(node: IRFragment, _ctx: HonoRenderCtx, _emit: EmitIRNode<HonoRenderCtx>): string;
|
|
@@ -91,7 +91,14 @@ export declare class HonoAdapter extends JsxAdapter implements IRNodeEmitter<Hon
|
|
|
91
91
|
}): string;
|
|
92
92
|
private renderText;
|
|
93
93
|
renderExpression(expr: IRExpression): string;
|
|
94
|
-
renderConditional(cond: IRConditional): string;
|
|
94
|
+
renderConditional(cond: IRConditional, ctx?: HonoRenderCtx): string;
|
|
95
|
+
/**
|
|
96
|
+
* Like the base `renderNodeRaw`, but threads a render ctx through to
|
|
97
|
+
* `renderNode` so a conditional branch can mark its element as a loop item
|
|
98
|
+
* root (#1665). The `null` / `undefined` expression branch carries no
|
|
99
|
+
* element, so it short-circuits exactly as the base helper does.
|
|
100
|
+
*/
|
|
101
|
+
private renderNodeRawCtx;
|
|
95
102
|
private wrapWithCondMarker;
|
|
96
103
|
renderLoop(loop: IRLoop): string;
|
|
97
104
|
private renderChildrenInLoop;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hono-adapter.d.ts","sourceRoot":"","sources":["../../src/adapter/hono-adapter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,MAAM,EACX,KAAK,SAAS,EACd,KAAK,MAAM,EACX,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,MAAM,EACX,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,UAAU,EACf,KAAK,OAAO,EACZ,KAAK,MAAM,EAIX,KAAK,sBAAsB,EAC3B,KAAK,aAAa,EAElB,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAClB,KAAK,UAAU,EAEf,UAAU,EAMX,MAAM,iBAAiB,CAAA;AAExB;;;;;GAKG;AACH,KAAK,aAAa,GAAG;IACnB,uBAAuB,CAAC,EAAE,OAAO,CAAA;IACjC,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB,CAAA;AAGD,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAA;IAEzB;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;IAEvB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAA;IAEzB;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAuBD,qBAAa,WAAY,SAAQ,UAAW,YAAW,aAAa,CAAC,aAAa,CAAC;IACjF,IAAI,SAAS;IACb,SAAS,SAAS;IAClB,gBAAgB,SAAiC;IAGjD,kBAAkB,EAAG,WAAW,CAAS;IAmBzC,mBAAmB,QAAO,OAAO,CAAQ;IAEzC,SAAS,CAAC,SAAS,EAAE,gBAAgB,CAA0B;IAE/D,OAAO,CAAC,OAAO,CAAoB;IACnC,OAAO,CAAC,iBAAiB,CAAiB;IAC1C,OAAO,CAAC,sBAAsB,CAAiB;IAC/C,OAAO,CAAC,wBAAwB,CAAiB;IACjD;;;;;;;OAOG;IACH,OAAO,CAAC,qBAAqB,CAAC,CAAgC;IAC9D,uFAAuF;IACvF,OAAO,CAAC,YAAY,CAAmD;IAEvE,YAAY,OAAO,GAAE,kBAAuB,EAQ3C;IAED,QAAQ,CAAC,EAAE,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,sBAAsB,GAAG,aAAa,CAyCzE;IAED,OAAO,CAAC,kCAAkC;IAkB1C,OAAO,CAAC,eAAe;IAyDvB,aAAa,CAAC,EAAE,EAAE,WAAW,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA+EpE;IAED,OAAO,CAAC,gBAAgB;IAWxB,OAAO,CAAC,iBAAiB;
|
|
1
|
+
{"version":3,"file":"hono-adapter.d.ts","sourceRoot":"","sources":["../../src/adapter/hono-adapter.ts"],"names":[],"mappings":"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"}
|
package/dist/adapter/index.js
CHANGED
|
@@ -260,9 +260,13 @@ export default ${this.componentName}` : "";
|
|
|
260
260
|
}
|
|
261
261
|
fullPropsDestructure = `{ ${parts.join(", ")} }`;
|
|
262
262
|
}
|
|
263
|
+
const hasRequiredProps = ir.metadata.propsParams.some((p) => !p.optional && p.defaultValue === undefined && !p.isRest);
|
|
264
|
+
const wantsNoArgDefault = propsObjectName ? !propsTypeName : !hasRequiredProps;
|
|
265
|
+
const propsTypeExpr = typeAnnotation.replace(/^:\s*/, "");
|
|
266
|
+
const noArgDefault = wantsNoArgDefault ? ` = {} as ${propsTypeExpr}` : "";
|
|
263
267
|
const lines = [];
|
|
264
268
|
const exportPrefix = ir.metadata.isExported === false ? "" : "export ";
|
|
265
|
-
lines.push(`${exportPrefix}function ${name}(${fullPropsDestructure}${typeAnnotation}) {`);
|
|
269
|
+
lines.push(`${exportPrefix}function ${name}(${fullPropsDestructure}${typeAnnotation}${noArgDefault}) {`);
|
|
266
270
|
if (propsExtraction) {
|
|
267
271
|
lines.push(propsExtraction);
|
|
268
272
|
}
|
|
@@ -313,8 +317,8 @@ export default ${this.componentName}` : "";
|
|
|
313
317
|
emitExpression(node) {
|
|
314
318
|
return this.renderExpression(node);
|
|
315
319
|
}
|
|
316
|
-
emitConditional(node,
|
|
317
|
-
return this.renderConditional(node);
|
|
320
|
+
emitConditional(node, ctx, _emit) {
|
|
321
|
+
return this.renderConditional(node, ctx);
|
|
318
322
|
}
|
|
319
323
|
emitLoop(node, _ctx, _emit) {
|
|
320
324
|
return this.renderLoop(node);
|
|
@@ -401,12 +405,13 @@ export default ${this.componentName}` : "";
|
|
|
401
405
|
}
|
|
402
406
|
return `{${expr.expr}}`;
|
|
403
407
|
}
|
|
404
|
-
renderConditional(cond) {
|
|
408
|
+
renderConditional(cond, ctx) {
|
|
405
409
|
if (cond.clientOnly && cond.slotId) {
|
|
406
410
|
return `{bfComment("cond-start:${cond.slotId}")}{bfComment("cond-end:${cond.slotId}")}`;
|
|
407
411
|
}
|
|
408
|
-
const
|
|
409
|
-
|
|
412
|
+
const branchCtx = ctx?.isLoopItemRoot ? { isLoopItemRoot: true } : undefined;
|
|
413
|
+
const whenTrue = this.renderNodeRawCtx(cond.whenTrue, branchCtx);
|
|
414
|
+
let whenFalse = this.renderNodeRawCtx(cond.whenFalse, branchCtx);
|
|
410
415
|
if (!whenFalse || whenFalse === "" || whenFalse === "null") {
|
|
411
416
|
whenFalse = "null";
|
|
412
417
|
}
|
|
@@ -417,6 +422,14 @@ export default ${this.componentName}` : "";
|
|
|
417
422
|
}
|
|
418
423
|
return `{${cond.condition} ? ${whenTrue} : ${whenFalse}}`;
|
|
419
424
|
}
|
|
425
|
+
renderNodeRawCtx(node, ctx) {
|
|
426
|
+
if (node.type === "expression") {
|
|
427
|
+
if (node.expr === "null" || node.expr === "undefined")
|
|
428
|
+
return "null";
|
|
429
|
+
return node.expr;
|
|
430
|
+
}
|
|
431
|
+
return this.renderNode(node, ctx);
|
|
432
|
+
}
|
|
420
433
|
wrapWithCondMarker(node, content, condId) {
|
|
421
434
|
if (node.type === "component") {
|
|
422
435
|
return `<>{bfComment("cond-start:${condId}")}${content}{bfComment("cond-end:${condId}")}</>`;
|
|
@@ -447,6 +460,8 @@ export default ${this.componentName}` : "";
|
|
|
447
460
|
let safeChildren = children.startsWith("{") ? `<>${children}</>` : children;
|
|
448
461
|
if (loop.bodyIsMultiRoot) {
|
|
449
462
|
safeChildren = `<>{bfComment('bf-loop-i')}${children}</>`;
|
|
463
|
+
} else if (loop.bodyIsItemConditional && loop.key) {
|
|
464
|
+
safeChildren = `<>{bfComment('loop-i:' + String(${loop.key}))}${children}</>`;
|
|
450
465
|
}
|
|
451
466
|
let chainedArray = applyHonoLoopChain(loop);
|
|
452
467
|
const iterMethod = loop.method ?? "map";
|
package/dist/build.js
CHANGED
|
@@ -260,9 +260,13 @@ export default ${this.componentName}` : "";
|
|
|
260
260
|
}
|
|
261
261
|
fullPropsDestructure = `{ ${parts.join(", ")} }`;
|
|
262
262
|
}
|
|
263
|
+
const hasRequiredProps = ir.metadata.propsParams.some((p) => !p.optional && p.defaultValue === undefined && !p.isRest);
|
|
264
|
+
const wantsNoArgDefault = propsObjectName ? !propsTypeName : !hasRequiredProps;
|
|
265
|
+
const propsTypeExpr = typeAnnotation.replace(/^:\s*/, "");
|
|
266
|
+
const noArgDefault = wantsNoArgDefault ? ` = {} as ${propsTypeExpr}` : "";
|
|
263
267
|
const lines = [];
|
|
264
268
|
const exportPrefix = ir.metadata.isExported === false ? "" : "export ";
|
|
265
|
-
lines.push(`${exportPrefix}function ${name}(${fullPropsDestructure}${typeAnnotation}) {`);
|
|
269
|
+
lines.push(`${exportPrefix}function ${name}(${fullPropsDestructure}${typeAnnotation}${noArgDefault}) {`);
|
|
266
270
|
if (propsExtraction) {
|
|
267
271
|
lines.push(propsExtraction);
|
|
268
272
|
}
|
|
@@ -313,8 +317,8 @@ export default ${this.componentName}` : "";
|
|
|
313
317
|
emitExpression(node) {
|
|
314
318
|
return this.renderExpression(node);
|
|
315
319
|
}
|
|
316
|
-
emitConditional(node,
|
|
317
|
-
return this.renderConditional(node);
|
|
320
|
+
emitConditional(node, ctx, _emit) {
|
|
321
|
+
return this.renderConditional(node, ctx);
|
|
318
322
|
}
|
|
319
323
|
emitLoop(node, _ctx, _emit) {
|
|
320
324
|
return this.renderLoop(node);
|
|
@@ -401,12 +405,13 @@ export default ${this.componentName}` : "";
|
|
|
401
405
|
}
|
|
402
406
|
return `{${expr.expr}}`;
|
|
403
407
|
}
|
|
404
|
-
renderConditional(cond) {
|
|
408
|
+
renderConditional(cond, ctx) {
|
|
405
409
|
if (cond.clientOnly && cond.slotId) {
|
|
406
410
|
return `{bfComment("cond-start:${cond.slotId}")}{bfComment("cond-end:${cond.slotId}")}`;
|
|
407
411
|
}
|
|
408
|
-
const
|
|
409
|
-
|
|
412
|
+
const branchCtx = ctx?.isLoopItemRoot ? { isLoopItemRoot: true } : undefined;
|
|
413
|
+
const whenTrue = this.renderNodeRawCtx(cond.whenTrue, branchCtx);
|
|
414
|
+
let whenFalse = this.renderNodeRawCtx(cond.whenFalse, branchCtx);
|
|
410
415
|
if (!whenFalse || whenFalse === "" || whenFalse === "null") {
|
|
411
416
|
whenFalse = "null";
|
|
412
417
|
}
|
|
@@ -417,6 +422,14 @@ export default ${this.componentName}` : "";
|
|
|
417
422
|
}
|
|
418
423
|
return `{${cond.condition} ? ${whenTrue} : ${whenFalse}}`;
|
|
419
424
|
}
|
|
425
|
+
renderNodeRawCtx(node, ctx) {
|
|
426
|
+
if (node.type === "expression") {
|
|
427
|
+
if (node.expr === "null" || node.expr === "undefined")
|
|
428
|
+
return "null";
|
|
429
|
+
return node.expr;
|
|
430
|
+
}
|
|
431
|
+
return this.renderNode(node, ctx);
|
|
432
|
+
}
|
|
420
433
|
wrapWithCondMarker(node, content, condId) {
|
|
421
434
|
if (node.type === "component") {
|
|
422
435
|
return `<>{bfComment("cond-start:${condId}")}${content}{bfComment("cond-end:${condId}")}</>`;
|
|
@@ -447,6 +460,8 @@ export default ${this.componentName}` : "";
|
|
|
447
460
|
let safeChildren = children.startsWith("{") ? `<>${children}</>` : children;
|
|
448
461
|
if (loop.bodyIsMultiRoot) {
|
|
449
462
|
safeChildren = `<>{bfComment('bf-loop-i')}${children}</>`;
|
|
463
|
+
} else if (loop.bodyIsItemConditional && loop.key) {
|
|
464
|
+
safeChildren = `<>{bfComment('loop-i:' + String(${loop.key}))}${children}</>`;
|
|
450
465
|
}
|
|
451
466
|
let chainedArray = applyHonoLoopChain(loop);
|
|
452
467
|
const iterMethod = loop.method ?? "map";
|
package/dist/index.js
CHANGED
|
@@ -260,9 +260,13 @@ export default ${this.componentName}` : "";
|
|
|
260
260
|
}
|
|
261
261
|
fullPropsDestructure = `{ ${parts.join(", ")} }`;
|
|
262
262
|
}
|
|
263
|
+
const hasRequiredProps = ir.metadata.propsParams.some((p) => !p.optional && p.defaultValue === undefined && !p.isRest);
|
|
264
|
+
const wantsNoArgDefault = propsObjectName ? !propsTypeName : !hasRequiredProps;
|
|
265
|
+
const propsTypeExpr = typeAnnotation.replace(/^:\s*/, "");
|
|
266
|
+
const noArgDefault = wantsNoArgDefault ? ` = {} as ${propsTypeExpr}` : "";
|
|
263
267
|
const lines = [];
|
|
264
268
|
const exportPrefix = ir.metadata.isExported === false ? "" : "export ";
|
|
265
|
-
lines.push(`${exportPrefix}function ${name}(${fullPropsDestructure}${typeAnnotation}) {`);
|
|
269
|
+
lines.push(`${exportPrefix}function ${name}(${fullPropsDestructure}${typeAnnotation}${noArgDefault}) {`);
|
|
266
270
|
if (propsExtraction) {
|
|
267
271
|
lines.push(propsExtraction);
|
|
268
272
|
}
|
|
@@ -313,8 +317,8 @@ export default ${this.componentName}` : "";
|
|
|
313
317
|
emitExpression(node) {
|
|
314
318
|
return this.renderExpression(node);
|
|
315
319
|
}
|
|
316
|
-
emitConditional(node,
|
|
317
|
-
return this.renderConditional(node);
|
|
320
|
+
emitConditional(node, ctx, _emit) {
|
|
321
|
+
return this.renderConditional(node, ctx);
|
|
318
322
|
}
|
|
319
323
|
emitLoop(node, _ctx, _emit) {
|
|
320
324
|
return this.renderLoop(node);
|
|
@@ -401,12 +405,13 @@ export default ${this.componentName}` : "";
|
|
|
401
405
|
}
|
|
402
406
|
return `{${expr.expr}}`;
|
|
403
407
|
}
|
|
404
|
-
renderConditional(cond) {
|
|
408
|
+
renderConditional(cond, ctx) {
|
|
405
409
|
if (cond.clientOnly && cond.slotId) {
|
|
406
410
|
return `{bfComment("cond-start:${cond.slotId}")}{bfComment("cond-end:${cond.slotId}")}`;
|
|
407
411
|
}
|
|
408
|
-
const
|
|
409
|
-
|
|
412
|
+
const branchCtx = ctx?.isLoopItemRoot ? { isLoopItemRoot: true } : undefined;
|
|
413
|
+
const whenTrue = this.renderNodeRawCtx(cond.whenTrue, branchCtx);
|
|
414
|
+
let whenFalse = this.renderNodeRawCtx(cond.whenFalse, branchCtx);
|
|
410
415
|
if (!whenFalse || whenFalse === "" || whenFalse === "null") {
|
|
411
416
|
whenFalse = "null";
|
|
412
417
|
}
|
|
@@ -417,6 +422,14 @@ export default ${this.componentName}` : "";
|
|
|
417
422
|
}
|
|
418
423
|
return `{${cond.condition} ? ${whenTrue} : ${whenFalse}}`;
|
|
419
424
|
}
|
|
425
|
+
renderNodeRawCtx(node, ctx) {
|
|
426
|
+
if (node.type === "expression") {
|
|
427
|
+
if (node.expr === "null" || node.expr === "undefined")
|
|
428
|
+
return "null";
|
|
429
|
+
return node.expr;
|
|
430
|
+
}
|
|
431
|
+
return this.renderNode(node, ctx);
|
|
432
|
+
}
|
|
420
433
|
wrapWithCondMarker(node, content, condId) {
|
|
421
434
|
if (node.type === "component") {
|
|
422
435
|
return `<>{bfComment("cond-start:${condId}")}${content}{bfComment("cond-end:${condId}")}</>`;
|
|
@@ -447,6 +460,8 @@ export default ${this.componentName}` : "";
|
|
|
447
460
|
let safeChildren = children.startsWith("{") ? `<>${children}</>` : children;
|
|
448
461
|
if (loop.bodyIsMultiRoot) {
|
|
449
462
|
safeChildren = `<>{bfComment('bf-loop-i')}${children}</>`;
|
|
463
|
+
} else if (loop.bodyIsItemConditional && loop.key) {
|
|
464
|
+
safeChildren = `<>{bfComment('loop-i:' + String(${loop.key}))}${children}</>`;
|
|
450
465
|
}
|
|
451
466
|
let chainedArray = applyHonoLoopChain(loop);
|
|
452
467
|
const iterMethod = loop.method ?? "map";
|
package/package.json
CHANGED
|
@@ -510,11 +510,28 @@ export class HonoAdapter extends JsxAdapter implements IRNodeEmitter<HonoRenderC
|
|
|
510
510
|
fullPropsDestructure = `{ ${parts.join(', ')} }`
|
|
511
511
|
}
|
|
512
512
|
|
|
513
|
+
// Default the props param to `{}` when the component has no required
|
|
514
|
+
// props, so a bare no-arg call (`Foo()`) doesn't crash on destructuring
|
|
515
|
+
// `undefined`. This makes a JSX-returning arrow hoisted from an
|
|
516
|
+
// object-literal value (e.g. `THEME_LOGOS[id]()`) renderable at SSR
|
|
517
|
+
// (#1663). `hasRequiredProps` ignores props that carry a destructuring
|
|
518
|
+
// default, but the declared props type may still mark that field
|
|
519
|
+
// required — so a bare `= {}` would fail `tsc`. Assert the default to the
|
|
520
|
+
// param's own annotated type (`{} as T`); the destructuring defaults
|
|
521
|
+
// supply the values at runtime. The SolidJS-style (`propsObjectName`)
|
|
522
|
+
// branch opts in whenever the annotation is satisfiable by `{} as T`.
|
|
523
|
+
const hasRequiredProps = ir.metadata.propsParams.some(
|
|
524
|
+
(p: ParamInfo) => !p.optional && p.defaultValue === undefined && !p.isRest,
|
|
525
|
+
)
|
|
526
|
+
const wantsNoArgDefault = propsObjectName ? !propsTypeName : !hasRequiredProps
|
|
527
|
+
const propsTypeExpr = typeAnnotation.replace(/^:\s*/, '')
|
|
528
|
+
const noArgDefault = wantsNoArgDefault ? ` = {} as ${propsTypeExpr}` : ''
|
|
529
|
+
|
|
513
530
|
const lines: string[] = []
|
|
514
531
|
// Module-export keyword belongs to the adapter: it knows the target language
|
|
515
532
|
// and whether the source declared the component as exported.
|
|
516
533
|
const exportPrefix = ir.metadata.isExported === false ? '' : 'export '
|
|
517
|
-
lines.push(`${exportPrefix}function ${name}(${fullPropsDestructure}${typeAnnotation}) {`)
|
|
534
|
+
lines.push(`${exportPrefix}function ${name}(${fullPropsDestructure}${typeAnnotation}${noArgDefault}) {`)
|
|
518
535
|
|
|
519
536
|
// Add props extraction for SolidJS-style pattern
|
|
520
537
|
if (propsExtraction) {
|
|
@@ -600,8 +617,8 @@ export class HonoAdapter extends JsxAdapter implements IRNodeEmitter<HonoRenderC
|
|
|
600
617
|
return this.renderExpression(node)
|
|
601
618
|
}
|
|
602
619
|
|
|
603
|
-
emitConditional(node: IRConditional,
|
|
604
|
-
return this.renderConditional(node)
|
|
620
|
+
emitConditional(node: IRConditional, ctx: HonoRenderCtx, _emit: EmitIRNode<HonoRenderCtx>): string {
|
|
621
|
+
return this.renderConditional(node, ctx)
|
|
605
622
|
}
|
|
606
623
|
|
|
607
624
|
emitLoop(node: IRLoop, _ctx: HonoRenderCtx, _emit: EmitIRNode<HonoRenderCtx>): string {
|
|
@@ -721,14 +738,21 @@ export class HonoAdapter extends JsxAdapter implements IRNodeEmitter<HonoRenderC
|
|
|
721
738
|
return `{${expr.expr}}`
|
|
722
739
|
}
|
|
723
740
|
|
|
724
|
-
renderConditional(cond: IRConditional): string {
|
|
741
|
+
renderConditional(cond: IRConditional, ctx?: HonoRenderCtx): string {
|
|
725
742
|
// Handle @client directive - render comment markers for client-side evaluation
|
|
726
743
|
if (cond.clientOnly && cond.slotId) {
|
|
727
744
|
return `{bfComment("cond-start:${cond.slotId}")}{bfComment("cond-end:${cond.slotId}")}`
|
|
728
745
|
}
|
|
729
746
|
|
|
730
|
-
|
|
731
|
-
|
|
747
|
+
// A conditional that is itself a loop item root (#1665 whole-item
|
|
748
|
+
// conditional: `arr.map(t => cond && <li/>)`) makes its branch element the
|
|
749
|
+
// loop item's root, so the `data-key` that reconciliation/hydration expect
|
|
750
|
+
// belongs on that element — exactly like a non-conditional loop root. Pass
|
|
751
|
+
// the flag through so `renderElement` emits `data-key`, matching the Go /
|
|
752
|
+
// CSR adapters' generic `key`→`data-key` rewrite.
|
|
753
|
+
const branchCtx: HonoRenderCtx | undefined = ctx?.isLoopItemRoot ? { isLoopItemRoot: true } : undefined
|
|
754
|
+
const whenTrue = this.renderNodeRawCtx(cond.whenTrue, branchCtx)
|
|
755
|
+
let whenFalse = this.renderNodeRawCtx(cond.whenFalse, branchCtx)
|
|
732
756
|
|
|
733
757
|
// Handle empty/null whenFalse
|
|
734
758
|
if (!whenFalse || whenFalse === '' || whenFalse === 'null') {
|
|
@@ -749,6 +773,20 @@ export class HonoAdapter extends JsxAdapter implements IRNodeEmitter<HonoRenderC
|
|
|
749
773
|
return `{${cond.condition} ? ${whenTrue} : ${whenFalse}}`
|
|
750
774
|
}
|
|
751
775
|
|
|
776
|
+
/**
|
|
777
|
+
* Like the base `renderNodeRaw`, but threads a render ctx through to
|
|
778
|
+
* `renderNode` so a conditional branch can mark its element as a loop item
|
|
779
|
+
* root (#1665). The `null` / `undefined` expression branch carries no
|
|
780
|
+
* element, so it short-circuits exactly as the base helper does.
|
|
781
|
+
*/
|
|
782
|
+
private renderNodeRawCtx(node: IRNode, ctx?: HonoRenderCtx): string {
|
|
783
|
+
if (node.type === 'expression') {
|
|
784
|
+
if (node.expr === 'null' || node.expr === 'undefined') return 'null'
|
|
785
|
+
return node.expr
|
|
786
|
+
}
|
|
787
|
+
return this.renderNode(node, ctx)
|
|
788
|
+
}
|
|
789
|
+
|
|
752
790
|
private wrapWithCondMarker(node: IRNode, content: string, condId: string): string {
|
|
753
791
|
// Components don't reliably forward bf-c to their root element.
|
|
754
792
|
// Use comment markers so insert() can find them via TreeWalker.
|
|
@@ -816,6 +854,14 @@ export class HonoAdapter extends JsxAdapter implements IRNodeEmitter<HonoRenderC
|
|
|
816
854
|
// literal here to match the adapter's existing convention of
|
|
817
855
|
// emitting comment-marker strings directly.
|
|
818
856
|
safeChildren = `<>{bfComment('bf-loop-i')}${children}</>`
|
|
857
|
+
} else if (loop.bodyIsItemConditional && loop.key) {
|
|
858
|
+
// Whole-item conditional (#1665): a per-item `<!--bf-loop-i:KEY-->`
|
|
859
|
+
// anchor that is ALWAYS present (even when the item's conditional
|
|
860
|
+
// renders nothing), carrying the key so the client's
|
|
861
|
+
// `mapArrayAnchored` can hydrate every SSR-rendered item by its anchor.
|
|
862
|
+
// `bfComment(k)` emits `<!--bf-${k}-->`, so the `loop-i:` argument
|
|
863
|
+
// yields `<!--bf-loop-i:KEY-->`.
|
|
864
|
+
safeChildren = `<>{bfComment('loop-i:' + String(${loop.key}))}${children}</>`
|
|
819
865
|
}
|
|
820
866
|
// Apply chained `.sort()` / `.filter()` extracted to
|
|
821
867
|
// `loop.sortComparator` / `loop.filterPredicate` (#1448 Tier B).
|