Affected area
File rendering or format fidelity — Patch comparison in @file-viewer/renderer-text.
Summary
In File Viewer 3.1.1, a .patch preview reports side-by-side, but the old/new panes are stacked vertically. Ordinary one-line code rows are approximately 84px high because whitespace from the generated HTML template is rendered as extra lines.
This is reproducible in a production build and in an isolated browser page using the same installed renderer, without application CSS, React, Tailwind, or the Vite runtime. It occurs with and without Shadow DOM.
File type and extension
Unified Git diff: .patch.
Package names and exact versions
@file-viewer/react-full: 3.1.1
@file-viewer/preset-all: 3.1.1
@file-viewer/core: 3.1.1
@file-viewer/renderer-text: 3.1.1
@file-viewer/capability-text-tools: 3.1.1
diff2html: 3.4.56
@file-viewer/vite-plugin: 3.1.1
Sample sharing method
Public reproduction file linked below, plus a complete small synthetic patch inline. No private files or customer data are involved.
Sample or reproduction artifact
The repository's own version-pinned demo sample reproduces the issue when loaded into the installed 3.1.1 renderer:
https://github.com/flyfish-dev/file-viewer/blob/v3.1.1/apps/viewer-demo/public/example/change.patch
The following smaller synthetic change.patch also reproduces it; preserve a trailing newline:
diff --git a/config.ts b/config.ts
index 83db48f..bf43abc 100644
--- a/config.ts
+++ b/config.ts
@@ -1,4 +1,5 @@
export const preview = {
- mode: "standard",
+ mode: "full",
locale: "zh-CN",
+ toolbar: false,
};
Minimal reproduction steps
-
In a React + Vite application, install @file-viewer/react-full@3.1.1 and @file-viewer/vite-plugin@3.1.1. The resolved diff2html version in this reproduction is 3.4.56.
-
Use the documented fileViewerRenderers({ copyAssets: true }) Vite plugin and render the synthetic sample above with:
import { FileViewer } from '@file-viewer/react-full';
import patchSource from './change.patch?raw';
const buffer = new TextEncoder().encode(patchSource).buffer;
const options = {
styleIsolation: 'shadow',
theme: 'light',
toolbar: false,
};
export default function App() {
return (
<div style={{ width: 1234, height: 900 }}>
<FileViewer
name="change.patch"
type="patch"
buffer={buffer}
options={options}
/>
</div>
);
}
-
Open the page and inspect the patch comparison. The issue is also present when serving the production output (vite build followed by vite preview).
-
Observe vertically stacked old/new panes and oversized rows. Switching to styleIsolation: 'none' does not resolve the underlying layout problem.
The public demo URL above is a fixture source, not a claim that the currently deployed online demo was tested. The fixture was tested against the installed 3.1.1 renderer in an isolated local browser page.
Actual behavior and isolation evidence
Measured in Chromium, with a 1234px-wide container and the synthetic sample:
| Variant |
Old/new panes |
Ordinary code-row height |
| Production application |
Stacked vertically |
~84px |
| Same page after removing application-injected styles |
Stacked vertically |
~84px |
| Standalone File Viewer Patch renderer, plain DOM |
Stacked vertically |
~84px |
| Standalone File Viewer Patch renderer, Shadow DOM |
Stacked vertically |
~84px |
Raw diff2html HTML + its bundled CSS |
Side by side |
~18px |
| Same raw HTML after File Viewer's rich-HTML sanitizer + bundled CSS |
Side by side |
~18px |
File Viewer renderer + bundled diff2html CSS |
Side by side |
~105px |
The upstream change.patch fixture also produced stacked panes and ~84px code rows in the standalone renderer. This rules out the synthetic input and the application stylesheet as the sole cause.
Likely source-level causes
The patchStyle string in the installed package matches the version-tagged source exactly:
https://github.com/flyfish-dev/file-viewer/blob/v3.1.1/packages/renderers/text/src/patch.ts#L13-L38
-
The injected stylesheet styles file headers, tables, line numbers, and colors, but does not define the side-by-side layout for .d2h-files-diff / .d2h-file-side-diff. The text-tools capability registers diff2html.html but does not import its stylesheet:
https://github.com/flyfish-dev/file-viewer/blob/v3.1.1/packages/capabilities/text-tools/src/index.ts
-
The following rule preserves whitespace on the outer generated line wrapper:
.patch-body .d2h-code-side-line,
.patch-body .d2h-code-line {
padding: 0 10px;
white-space: pre-wrap;
word-break: break-word;
}
diff2html emits indentation/newlines around its prefix/content spans:
<div class="d2h-code-side-line">
<span class="d2h-code-line-prefix">-</span>
<span class="d2h-code-line-ctn"> mode: "standard",</span>
</div>
Those template text nodes become extra rendered lines. Whitespace preservation should apply to the actual code content without preserving the surrounding template formatting.
Importing diff2html CSS alone is insufficient: File Viewer's more-specific .patch-body .d2h-code-side-line rule still wins over the upstream whitespace rule. In the measured isolated case, it restored columns but increased the row height to ~105px.
For diagnostic confirmation only, adding two groups of local rules — side-by-side layout and whitespace scoping — restored two columns and reduced rows to ~23px. This was not shipped as a fix, and is not intended as a complete proposed stylesheet; long lines, empty placeholders, change alignment, zoom, and themes still need proper regression coverage.
Expected behavior
- Old/new content appears in adjacent panes when the renderer reports
side-by-side.
- A short single-line source line occupies one visual line, preserving source indentation but not HTML template whitespace.
- Context lines, inserted/deleted lines, and empty alignment placeholders remain aligned across panes.
- Behavior is correct on a clean page and under Shadow DOM, without relying on host-global CSS.
Environment
- macOS; Chromium via the project's Playwright-managed headless browser.
- React
19.2.8; Vite 8.2.2.
- Reproduced in the application's production build and a separate bundled standalone-renderer browser harness.
- Root deployment path; local/self-hosted assets. The standalone case needs no external renderer assets.
- No application stylesheet in the standalone case. No special CSP was added there.
Regression status
Unknown. Earlier File Viewer versions were not tested.
Console and network evidence
No runtime JavaScript exception was observed in the production reproduction. Patch parsing completes and the expected text appears; this is a layout/whitespace problem, not a failed asset request.
Required confirmations
Affected area
File rendering or format fidelity — Patch comparison in
@file-viewer/renderer-text.Summary
In File Viewer 3.1.1, a
.patchpreview reportsside-by-side, but the old/new panes are stacked vertically. Ordinary one-line code rows are approximately 84px high because whitespace from the generated HTML template is rendered as extra lines.This is reproducible in a production build and in an isolated browser page using the same installed renderer, without application CSS, React, Tailwind, or the Vite runtime. It occurs with and without Shadow DOM.
File type and extension
Unified Git diff:
.patch.Package names and exact versions
@file-viewer/react-full:3.1.1@file-viewer/preset-all:3.1.1@file-viewer/core:3.1.1@file-viewer/renderer-text:3.1.1@file-viewer/capability-text-tools:3.1.1diff2html:3.4.56@file-viewer/vite-plugin:3.1.1Sample sharing method
Public reproduction file linked below, plus a complete small synthetic patch inline. No private files or customer data are involved.
Sample or reproduction artifact
The repository's own version-pinned demo sample reproduces the issue when loaded into the installed 3.1.1 renderer:
https://github.com/flyfish-dev/file-viewer/blob/v3.1.1/apps/viewer-demo/public/example/change.patch
The following smaller synthetic
change.patchalso reproduces it; preserve a trailing newline:Minimal reproduction steps
In a React + Vite application, install
@file-viewer/react-full@3.1.1and@file-viewer/vite-plugin@3.1.1. The resolveddiff2htmlversion in this reproduction is3.4.56.Use the documented
fileViewerRenderers({ copyAssets: true })Vite plugin and render the synthetic sample above with:Open the page and inspect the patch comparison. The issue is also present when serving the production output (
vite buildfollowed byvite preview).Observe vertically stacked old/new panes and oversized rows. Switching to
styleIsolation: 'none'does not resolve the underlying layout problem.The public demo URL above is a fixture source, not a claim that the currently deployed online demo was tested. The fixture was tested against the installed 3.1.1 renderer in an isolated local browser page.
Actual behavior and isolation evidence
Measured in Chromium, with a 1234px-wide container and the synthetic sample:
diff2htmlHTML + its bundled CSSdiff2htmlCSSThe upstream
change.patchfixture also produced stacked panes and ~84px code rows in the standalone renderer. This rules out the synthetic input and the application stylesheet as the sole cause.Likely source-level causes
The
patchStylestring in the installed package matches the version-tagged source exactly:https://github.com/flyfish-dev/file-viewer/blob/v3.1.1/packages/renderers/text/src/patch.ts#L13-L38
The injected stylesheet styles file headers, tables, line numbers, and colors, but does not define the side-by-side layout for
.d2h-files-diff/.d2h-file-side-diff. The text-tools capability registersdiff2html.htmlbut does not import its stylesheet:https://github.com/flyfish-dev/file-viewer/blob/v3.1.1/packages/capabilities/text-tools/src/index.ts
The following rule preserves whitespace on the outer generated line wrapper:
diff2htmlemits indentation/newlines around its prefix/content spans:Those template text nodes become extra rendered lines. Whitespace preservation should apply to the actual code content without preserving the surrounding template formatting.
Importing
diff2htmlCSS alone is insufficient: File Viewer's more-specific.patch-body .d2h-code-side-linerule still wins over the upstream whitespace rule. In the measured isolated case, it restored columns but increased the row height to ~105px.For diagnostic confirmation only, adding two groups of local rules — side-by-side layout and whitespace scoping — restored two columns and reduced rows to ~23px. This was not shipped as a fix, and is not intended as a complete proposed stylesheet; long lines, empty placeholders, change alignment, zoom, and themes still need proper regression coverage.
Expected behavior
side-by-side.Environment
19.2.8; Vite8.2.2.Regression status
Unknown. Earlier File Viewer versions were not tested.
Console and network evidence
No runtime JavaScript exception was observed in the production reproduction. Patch parsing completes and the expected text appears; this is a layout/whitespace problem, not a failed asset request.
Required confirmations