From 052f671b3cb03e9b4f8ed01731a5414761159d87 Mon Sep 17 00:00:00 2001 From: chengyongru Date: Tue, 21 Jul 2026 15:09:55 +0800 Subject: [PATCH] fix(webui): keep Markdown table diffs inline --- .../thread/activity/DiffSyntaxHighlight.tsx | 25 ++++++++++++- ...diff-syntax-highlight.integration.test.tsx | 37 +++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/webui/src/components/thread/activity/DiffSyntaxHighlight.tsx b/webui/src/components/thread/activity/DiffSyntaxHighlight.tsx index e8d588db..5fbaded1 100644 --- a/webui/src/components/thread/activity/DiffSyntaxHighlight.tsx +++ b/webui/src/components/thread/activity/DiffSyntaxHighlight.tsx @@ -79,7 +79,7 @@ const LazyDiffSyntaxHighlight = lazy(async () => { const node = rows[index]; if (!node) return line.content || " "; return createSyntaxElement({ - node: trimTrailingLineBreak(node), + node: stripConflictingTableClass(trimTrailingLineBreak(node)), stylesheet, useInlineStyles, key: `diff-code-${index}`, @@ -184,3 +184,26 @@ function trimTrailingLineBreak(node: SyntaxNode): SyntaxNode { children[children.length - 1] = trimTrailingLineBreak(children[children.length - 1]!); return { ...node, children }; } + +function stripConflictingTableClass(node: SyntaxNode): SyntaxNode { + const className = node.properties?.className; + const children = node.children?.map(stripConflictingTableClass); + const hasTableClass = Array.isArray(className) && className.includes("table"); + + if (!hasTableClass && !children) return node; + + return { + ...node, + ...(hasTableClass + ? { + properties: { + ...node.properties, + // Tailwind's global `.table` utility changes Prism's inline Markdown + // table tokens into CSS tables, splitting a single diff line vertically. + className: className.filter((name) => name !== "table"), + }, + } + : {}), + ...(children ? { children } : {}), + }; +} diff --git a/webui/src/tests/diff-syntax-highlight.integration.test.tsx b/webui/src/tests/diff-syntax-highlight.integration.test.tsx index bf4efcc8..62c08ab9 100644 --- a/webui/src/tests/diff-syntax-highlight.integration.test.tsx +++ b/webui/src/tests/diff-syntax-highlight.integration.test.tsx @@ -61,4 +61,41 @@ describe("DiffSyntaxHighlight with Prism", () => { expect(highlighted).toHaveAttribute("data-language", "tsx"); expect(highlighted.querySelectorAll("tbody tr")).toHaveLength(4); }); + + it("preserves markdown table line boundaries", async () => { + const lines = [ + "## 发布安排", + "", + "| 日期 | 角色 | 方向 | 是否进实验 |", + "| --- | --- | --- | --- |", + "| 7/22 | trust / core | data-driven | yes |", + ]; + + render( + + ({ + kind: "add" as const, + old_lineno: null, + new_lineno: 20 + index, + content, + }))} + /> + , + ); + + const highlighted = await screen.findByTestId( + "syntax-highlighted-diff-hunk", + {}, + { timeout: 10_000 }, + ); + const rows = [...highlighted.querySelectorAll("tbody tr")]; + + expect(rows).toHaveLength(lines.length); + expect(rows.map((row) => row.querySelector("td:last-child")?.textContent)).toEqual( + lines.map((line) => line || " "), + ); + expect(highlighted.querySelector(".token.table")).toBeNull(); + }); });