fix(tui): preserved blank streamed diff rows
Preserved completed blank rows in transient diff rendering, including leading blank code rows and blank rows appended through the streaming diff cache. Added regression coverage for both blank-row scrollback layout cases from PR review.
This commit is contained in:
@@ -190,4 +190,33 @@ describe("transcript streaming commit (assistant text)", () => {
|
||||
await term.flush();
|
||||
}
|
||||
});
|
||||
|
||||
it("renders a leading completed blank row in an open streamed diff body", () => {
|
||||
const block = new StreamingMarkdownBlock();
|
||||
block.setStreamingText("```diff\n\n+next");
|
||||
|
||||
const rows = block.render(40).map(row => Bun.stripANSI(row).trimEnd());
|
||||
const fenceRow = rows.indexOf("```diff");
|
||||
|
||||
expect(fenceRow).toBeGreaterThanOrEqual(0);
|
||||
expect(rows.slice(fenceRow, fenceRow + 4)).toEqual(["```diff", "", " +next", "```"]);
|
||||
});
|
||||
|
||||
it("appends a completed blank row when the streamed diff line cache grows", () => {
|
||||
const block = new StreamingMarkdownBlock();
|
||||
|
||||
block.setStreamingText("```diff\n+a\n+streaming");
|
||||
const initialRows = block.render(40).map(row => Bun.stripANSI(row).trimEnd());
|
||||
const initialCodeRow = initialRows.indexOf(" +a");
|
||||
expect(initialCodeRow).toBeGreaterThanOrEqual(0);
|
||||
expect(initialRows.slice(initialCodeRow, initialCodeRow + 2)).toEqual([" +a", " +streaming"]);
|
||||
|
||||
block.setStreamingText("```diff\n+a\n\n+streaming");
|
||||
|
||||
const rows = block.render(40).map(row => Bun.stripANSI(row).trimEnd());
|
||||
const codeRow = rows.indexOf(" +a");
|
||||
|
||||
expect(codeRow).toBeGreaterThanOrEqual(0);
|
||||
expect(rows.slice(codeRow, codeRow + 3)).toEqual([" +a", "", " +streaming"]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1425,10 +1425,8 @@ export class Markdown implements Component {
|
||||
const lineEnd = tokenText.lastIndexOf("\n");
|
||||
if (closedFence || lineEnd >= 0) {
|
||||
const completedText = closedFence ? tokenText : tokenText.slice(0, lineEnd);
|
||||
if (closedFence || completedText.length > 0) {
|
||||
for (const hlLine of this.#highlightStreamingDiffLines(completedText, lang)) {
|
||||
bodyLines.push(`${codeIndent}${hlLine}`);
|
||||
}
|
||||
for (const hlLine of this.#highlightStreamingDiffLines(completedText, lang)) {
|
||||
bodyLines.push(`${codeIndent}${hlLine}`);
|
||||
}
|
||||
if (!closedFence) {
|
||||
for (const codeLine of tokenText.slice(lineEnd + 1).split("\n")) {
|
||||
@@ -1502,10 +1500,8 @@ export class Markdown implements Component {
|
||||
if (completedText.length === cache.text.length) return cache.lines;
|
||||
const lines = cache.lines.slice();
|
||||
const addedText = completedText.slice(cache.text.length === 0 ? 0 : cache.text.length + 1);
|
||||
if (addedText.length > 0) {
|
||||
for (const codeLine of addedText.split("\n")) {
|
||||
lines.push(...highlightCode(codeLine, lang));
|
||||
}
|
||||
for (const codeLine of addedText.split("\n")) {
|
||||
lines.push(...highlightCode(codeLine, lang));
|
||||
}
|
||||
this.#streamingDiffLineCache = { ...signature, lang, text: completedText, lines };
|
||||
return lines;
|
||||
|
||||
Reference in New Issue
Block a user