From 86070a38d8aa0b498bb39c2d8db156d2c9045871 Mon Sep 17 00:00:00 2001 From: Tanpinsary Date: Sat, 13 Jun 2026 01:20:40 +0800 Subject: [PATCH] fix(render): add xml:space="preserve" to SVG text elements Without xml:space="preserve", XML whitespace collapsing trims leading spaces and collapses space runs inside tspans. Each tspan carries a per-character x position list, so dropping characters desyncs text from its coordinates: indentation disappears and spaces adjacent to SGR color-run boundaries are eaten (e.g. "int fd" renders as "intfd"). Affects both SVG output viewed in browsers/WebKit and PNG output rasterized by resvg. --- packages/viterm/tests/__snapshots__/matchers.test.ts.snap | 2 +- .../tests/__snapshots__/svg-serializer.test.ts.snap | 8 ++++---- src/render/svg.ts | 5 ++++- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/packages/viterm/tests/__snapshots__/matchers.test.ts.snap b/packages/viterm/tests/__snapshots__/matchers.test.ts.snap index 6f38478..d405c58 100644 --- a/packages/viterm/tests/__snapshots__/matchers.test.ts.snap +++ b/packages/viterm/tests/__snapshots__/matchers.test.ts.snap @@ -3,7 +3,7 @@ exports[`snapshot matchers > toMatchSvgSnapshot creates a snapshot file 1`] = ` " - + SVG Test diff --git a/packages/viterm/tests/__snapshots__/svg-serializer.test.ts.snap b/packages/viterm/tests/__snapshots__/svg-serializer.test.ts.snap index ead47d1..d7da6e6 100644 --- a/packages/viterm/tests/__snapshots__/svg-serializer.test.ts.snap +++ b/packages/viterm/tests/__snapshots__/svg-serializer.test.ts.snap @@ -3,7 +3,7 @@ exports[`toMatchSvgSnapshot matcher > accepts name option > basic 1`] = ` " - + Test @@ -13,7 +13,7 @@ exports[`toMatchSvgSnapshot matcher > accepts name option > basic 1`] = ` exports[`toMatchSvgSnapshot matcher > accepts theme option 1`] = ` " - + Test @@ -23,10 +23,10 @@ exports[`toMatchSvgSnapshot matcher > accepts theme option 1`] = ` exports[`toMatchSvgSnapshot matcher > produces SVG output from TerminalReadable 1`] = ` " - + Hello - + World diff --git a/src/render/svg.ts b/src/render/svg.ts index 43654b6..e4769c9 100644 --- a/src/render/svg.ts +++ b/src/render/svg.ts @@ -433,7 +433,10 @@ function renderTextRows(lines: Cell[][], opts: ResolvedOptions): string[] { } if (!textOpen) { parts.push( - ``, + // xml:space="preserve" is required: without it, XML whitespace + // collapsing eats leading/run-of-space characters in tspans, which + // desyncs them from the per-character x position lists. + ``, ) textOpen = true }