Skip to content

Commit 8c64f21

Browse files
benvinegarBen Vclaude
authored
fix(renderer): strip newline from Pierre empty-line placeholder spans (#201)
Co-authored-by: Ben V <benv@Bens-MacBook-Pro.local> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 63b85c3 commit 8c64f21

File tree

2 files changed

+51
-1
lines changed

2 files changed

+51
-1
lines changed

src/ui/diff/pierre.test.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,36 @@ function createDiffFile(): DiffFile {
3535
};
3636
}
3737

38+
function createEmptyLineDiffFile(): DiffFile {
39+
const metadata = parseDiffFromFile(
40+
{
41+
name: "empty.ts",
42+
contents: "function foo() {\n return 1;\n}\n",
43+
cacheKey: "before-empty",
44+
},
45+
{
46+
name: "empty.ts",
47+
contents: "function foo() {\n\n return 2;\n}\n",
48+
cacheKey: "after-empty",
49+
},
50+
{ context: 3 },
51+
true,
52+
);
53+
54+
return {
55+
id: "empty",
56+
path: "empty.ts",
57+
patch: "",
58+
language: "typescript",
59+
stats: {
60+
additions: 2,
61+
deletions: 1,
62+
},
63+
metadata,
64+
agent: null,
65+
};
66+
}
67+
3868
function createMarkdownDiffFile(): DiffFile {
3969
const metadata = parseDiffFromFile(
4070
{
@@ -125,6 +155,23 @@ describe("Pierre diff rows", () => {
125155
expect(additionRow.cell.newLineNumber).toBe(1);
126156
});
127157

158+
test("does not produce newline characters in spans for highlighted empty lines", async () => {
159+
const file = createEmptyLineDiffFile();
160+
const theme = resolveTheme("midnight", null);
161+
const highlighted = await loadHighlightedDiff(file);
162+
163+
for (const buildRows of [buildSplitRows, buildStackRows]) {
164+
const rows = buildRows(file, highlighted, theme);
165+
const allSpans = rows.flatMap((row) => {
166+
if (row.type === "split-line") return [...row.left.spans, ...row.right.spans];
167+
if (row.type === "stack-line") return row.cell.spans;
168+
return [];
169+
});
170+
171+
expect(allSpans.every((span) => !span.text.includes("\n"))).toBe(true);
172+
}
173+
});
174+
128175
test("remaps Pierre markdown reds and greens away from diff-semantic hues", async () => {
129176
const file = createMarkdownDiffFile();
130177

src/ui/diff/pierre.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,8 +233,11 @@ function flattenHighlightedLine(node: HastNode | undefined, theme: AppTheme, emp
233233
}
234234

235235
if (current.type === "text") {
236+
// Pierre injects a "\n" placeholder into empty line nodes so they aren't childless.
237+
// Strip it the same way cleanDiffLine does for the unhighlighted path, or the literal
238+
// newline ends up in the span text and breaks terminal row rendering.
236239
mergeSpan(spans, {
237-
text: tabify(current.value),
240+
text: tabify(cleanLastNewline(current.value)),
238241
fg: inherited.fg,
239242
bg: inherited.bg,
240243
});

0 commit comments

Comments
 (0)