From d97c403aab72c0728b5a821111ee9efe9569b588 Mon Sep 17 00:00:00 2001 From: nntrivi2001 Date: Fri, 30 Oct 2026 10:28:53 +0700 Subject: [PATCH] fix(changes): a huge line no longer cuts the diff short; preview pages up to 64 MB A page that inlines a video as base64 has rows of megabytes. Its patch was read at the 200 KB per-file cap, so the first such row used the whole budget and every hunk after it was lost ("Diff cut short"). The patch is now read up to 16 M characters, rows over 4,000 characters are cut to 1,000 with an `elided` count the diff shows, and only then is the cap applied. Hunk actions re-read git's own diff by header and are unchanged. The HTML preview refused a page over 10 MB and showed only the file icon; a self-contained 18 MB slide deck now opens (limit 64 MB). --- client/src/components/HtmlFrame.tsx | 6 +- client/src/components/lanes/LaneDiffView.tsx | 14 +++++ .../lanes/__tests__/LaneDiffView.test.tsx | 23 +++++++ client/src/i18n/locales/en/lanes.json | 1 + client/src/i18n/locales/vi/lanes.json | 1 + client/src/lib/types.ts | 3 + docs/API.md | 5 ++ .../__tests__/git-diff-ops-hardening.test.js | 49 +++++++++++++++ server/__tests__/git-diff-ops.test.js | 19 +++--- server/lib/git-diff.js | 60 +++++++++++++++++-- 10 files changed, 166 insertions(+), 15 deletions(-) diff --git a/client/src/components/HtmlFrame.tsx b/client/src/components/HtmlFrame.tsx index 52db2a26..87108212 100644 --- a/client/src/components/HtmlFrame.tsx +++ b/client/src/components/HtmlFrame.tsx @@ -15,8 +15,10 @@ import { FileText, Loader2 } from "lucide-react"; import { artifactDocument, frameSandbox } from "../lib/artifactView"; import { blobText, inlineHtml, type FetchFile } from "../lib/htmlInline"; -/** A page read by `fetchFile` is shown up to this size. */ -const HTML_MAX = 10 * 1024 * 1024; +/** A page read by `fetchFile` is shown up to this size. A self-contained + * page (a slide deck with its video and images inlined as base64) is easily + * past 10 MB; the iframe renders far larger documents than this. */ +const HTML_MAX = 64 * 1024 * 1024; export function HtmlFrame({ path, diff --git a/client/src/components/lanes/LaneDiffView.tsx b/client/src/components/lanes/LaneDiffView.tsx index ca1b9123..f7fba385 100644 --- a/client/src/components/lanes/LaneDiffView.tsx +++ b/client/src/components/lanes/LaneDiffView.tsx @@ -179,6 +179,18 @@ export function langFor(filePath: string) { } /** Tokenized line text. `emph` marks the span that actually changed. */ +/** The tail of a row the server cut down (`LaneDiffLine.elided`). */ +function Elided({ n }: { n?: number }) { + const { t, i18n } = useTranslation("lanes"); + if (!n) return null; + const size = new Intl.NumberFormat(i18n.language, { notation: "compact" }).format(n); + return ( + + {t("changes.lineElided", { size })} + + ); +} + function Code({ text, lang, emph }: { text: string; lang: string; emph?: [number, number] }) { if (emph) { const [from, to] = emph; @@ -544,6 +556,7 @@ function UnifiedLine({ {line.type === "add" ? "+" : line.type === "del" ? "-" : " "} + {bar && } @@ -621,6 +634,7 @@ function SplitLine({ /> {line ? : null} + {line ? : null} {bar && } diff --git a/client/src/components/lanes/__tests__/LaneDiffView.test.tsx b/client/src/components/lanes/__tests__/LaneDiffView.test.tsx index 3d57e841..defb2a3e 100644 --- a/client/src/components/lanes/__tests__/LaneDiffView.test.tsx +++ b/client/src/components/lanes/__tests__/LaneDiffView.test.tsx @@ -609,3 +609,26 @@ describe("LaneDiffView — line comments", () => { expect(screen.queryByTestId("diff-comment-line-1")).toBeNull(); }); }); + +describe("LaneDiffView — a row the server cut down", () => { + const CUT: LaneChangeFile = { + ...FILE, + hunks: [ + { + ...FILE.hunks[0]!, + lines: [ + { type: "del", oldLine: 1, newLine: null, text: '