From 2d3045647ae7abac0c9458a5c6e6d063f2b784e4 Mon Sep 17 00:00:00 2001 From: Xubin Ren <52506698+Re-bin@users.noreply.github.com> Date: Sun, 16 Aug 2026 21:58:47 +0800 Subject: [PATCH] fix(tui): reflow markdown tables --- tui/src/app.test.ts | 38 ++++++++++++++++++++++++++++++++++++++ tui/src/transcript.ts | 7 +++++++ 2 files changed, 45 insertions(+) diff --git a/tui/src/app.test.ts b/tui/src/app.test.ts index fca03c31d..871fb6366 100644 --- a/tui/src/app.test.ts +++ b/tui/src/app.test.ts @@ -1132,6 +1132,44 @@ describe("NanobotTui layout", () => { } }) + test("reflows markdown tables without clipping columns or cell content", async () => { + setup = await createRenderer({ width: 96, height: 24, screenMode: "alternate-screen" }) + const app = mount(setup) + app.accept({ event: "attached", chat_id: "chat" }) + app.accept({ + event: "delta", + chat_id: "chat", + text: [ + "| Who | Content | Engagement |", + "| --- | --- | --- |", + "| @owner | A longer explanation that keeps context readable | 13 likes / 6 RT |", + "| @reader | Short follow-up | Low interaction |", + ].join("\n"), + }) + app.accept({ event: "stream_end", chat_id: "chat" }) + app.accept({ event: "turn_end", chat_id: "chat" }) + + for (const width of [96, 54, 96]) { + setup.resize(width, 24) + await setup.flush() + const rendered = setup.captureCharFrame().replace(/\s+/gu, " ") + + expect(rendered).toContain("Who") + expect(rendered).toContain("Content") + expect(rendered).toContain("Engagement") + expect(rendered).toContain("@owner") + expect(rendered).toContain("longer explanation") + expect(rendered).toContain("keeps context") + expect(rendered).toContain("readable") + expect(rendered).toContain("13 likes / 6") + expect(rendered).toContain("RT") + expect(rendered).toContain("Low interaction") + expect((app as unknown as { + transcript: { root: HiddenScrollBox } + }).transcript.root.horizontalScrollBar.visible).toBeFalse() + } + }) + test("rethemes the complete retained interface when the terminal appearance changes", async () => { setup = await createRenderer({ width: 80, height: 22, screenMode: "alternate-screen" }) const app = mount(setup) diff --git a/tui/src/transcript.ts b/tui/src/transcript.ts index 8c589b890..83bc3aaae 100644 --- a/tui/src/transcript.ts +++ b/tui/src/transcript.ts @@ -469,9 +469,16 @@ export class Transcript { width: "auto", minWidth: 0, flexGrow: 1, + flexShrink: 1, syntaxStyle: this.theme.syntax, streaming, internalBlockMode: "top-level", + tableOptions: { + style: "columns", + widthMode: "full", + columnFitter: "balanced", + wrapMode: "word", + }, treeSitterClient: this.treeSitterClient, }) this.markdown.add(markdown)