fix(tui): stop heading underline leaking into padding

This commit is contained in:
Mario Zechner
2026-03-31 22:40:20 +02:00
parent a1e107897d
commit 09e9de5749
3 changed files with 35 additions and 0 deletions

View File

@@ -4,6 +4,7 @@
### Fixed
- Fixed markdown H1 headings ending with inline code from leaking underline styling into trailing line padding
- Fixed slash-command argument autocomplete to await async `getArgumentCompletions()` results and ignore invalid return values, preventing crashes when extension commands provide asynchronous completions ([#2719](https://github.com/badlogic/pi-mono/issues/2719))
## [0.64.0] - 2026-03-29

View File

@@ -505,6 +505,10 @@ export class Markdown implements Component {
}
}
while (stylePrefix && result.endsWith(stylePrefix)) {
result = result.slice(0, -stylePrefix.length);
}
return result;
}

View File

@@ -20,6 +20,16 @@ function getCellItalic(terminal: VirtualTerminal, row: number, col: number): num
return cell.isItalic();
}
function getCellUnderline(terminal: VirtualTerminal, row: number, col: number): number {
const xterm = (terminal as unknown as { xterm: XtermTerminalType }).xterm;
const buffer = xterm.buffer.active;
const line = buffer.getLine(buffer.viewportY + row);
assert.ok(line, `Missing buffer line at row ${row}`);
const cell = line.getCell(col);
assert.ok(cell, `Missing cell at row ${row} col ${col}`);
return cell.isUnderline();
}
describe("Markdown component", () => {
describe("Nested lists", () => {
it("should render simple nested list", () => {
@@ -1016,6 +1026,26 @@ bar`,
assert.ok(precedingChunk.includes("\x1b[4m"), `Should re-apply underline for h1: ${precedingChunk}`);
});
it("should not leak h1 underline into padding when inline code is the last token", async () => {
const markdown = new Markdown("# Important distinction from `open()`", 0, 0, defaultMarkdownTheme);
const terminal = new VirtualTerminal(80, 4);
const tui = new TUI(terminal);
tui.addChild(markdown);
tui.start();
await terminal.flush();
const renderedLine = markdown.render(80)[0];
assert.ok(renderedLine, "Should render heading line");
const contentWidth = renderedLine.replace(/\x1b\[[0-9;]*m/g, "").trimEnd().length;
assert.ok(contentWidth > 0, "Should have visible heading content");
for (let col = contentWidth; col < 80; col++) {
assert.strictEqual(getCellUnderline(terminal, 0, col), 0, `Expected no underline in padding at col ${col}`);
}
tui.stop();
});
it("should preserve heading styling after bold text", () => {
const markdown = new Markdown("## Heading with **bold** and more", 0, 0, defaultMarkdownTheme);