From a834fb69853809c79dc5771cadf2b5f853aa0186 Mon Sep 17 00:00:00 2001 From: Bochen Wang Date: Thu, 19 Mar 2026 11:05:26 -0700 Subject: [PATCH] fix: handle ' HTML entity in diff view to prevent "undefined" suffix highlight.js encodes apostrophes as ' (hex entity), but decodeEntities only handled ' (decimal entity). The unrecognized entity caused a character count mismatch in applyDiffToHighlightedHtml, producing out-of-bounds reads that appended "undefined" strings to rendered lines. Co-Authored-By: Claude Opus 4.6 --- src/index.tsx | 1 + test/react-diff-viewer.test.tsx | 56 +++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/src/index.tsx b/src/index.tsx index 920d5f7..4de1379 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -84,6 +84,7 @@ function applyDiffToHighlightedHtml( .replace(/&/g, "&") .replace(/"/g, '"') .replace(/'/g, "'") + .replace(/'/g, "'") .replace(/ /g, "\u00A0"); } diff --git a/test/react-diff-viewer.test.tsx b/test/react-diff-viewer.test.tsx index ce169bf..514b185 100644 --- a/test/react-diff-viewer.test.tsx +++ b/test/react-diff-viewer.test.tsx @@ -93,6 +93,62 @@ describe("Testing react diff viewer", (): void => { expect(duration).toBeLessThan(2000); }); + it("Should not render 'undefined' when renderContent returns HTML with ' entities", async (): Promise => { + // Simulates highlight.js output which encodes apostrophes as ' + // This was the root cause of the "undefinedundefined..." suffix bug + const oldValue = "const x = 'hello'"; + const newValue = "const x = 'world'"; + + // Simulate a syntax highlighter (like highlight.js) that encodes + // apostrophes as ' instead of ' + const renderContent = (str: string): React.ReactElement => { + const html = str.replace(/'/g, "'"); + return ; + }; + + const node = render( + , + ); + + await waitFor(() => { + expect(node.container.querySelector("table")).toBeTruthy(); + }); + + const allContent = node.container.textContent || ""; + expect(allContent).not.toContain("undefined"); + }); + + it("Should not render 'undefined' with multiple apostrophes in renderContent HTML", async (): Promise => { + const oldValue = "it's a 'test' isn't it"; + const newValue = "it's a 'change' isn't it"; + + const renderContent = (str: string): React.ReactElement => { + const html = str.replace(/'/g, "'"); + return ; + }; + + const node = render( + , + ); + + await waitFor(() => { + expect(node.container.querySelector("table")).toBeTruthy(); + }); + + const allContent = node.container.textContent || ""; + expect(allContent).not.toContain("undefined"); + }); + it("Should render JSON diff with keys preserved", async (): Promise => { const oldObj = { data: {