From 2a37762aa53245875d69d24b03c1c9b9dc5ecb6b Mon Sep 17 00:00:00 2001 From: Chris Wanstrath Date: Fri, 6 Mar 2026 08:32:51 -0800 Subject: [PATCH] Show new/deleted files as line-by-line diff --- src/commands/diff.html | 45 +++++++++++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/src/commands/diff.html b/src/commands/diff.html index 5fe3db7..59e1371 100644 --- a/src/commands/diff.html +++ b/src/commands/diff.html @@ -42,22 +42,43 @@ const targetElement = document.getElementById("diff"); const toggle = document.getElementById("unified-toggle"); - function renderDiff(outputFormat) { - const diff2htmlUi = new Diff2HtmlUI(targetElement, diffString, { - drawFileList: true, - matching: "lines", - outputFormat, - highlight: true, - colorScheme: "dark", - }); - diff2htmlUi.draw(); - diff2htmlUi.highlightCode(); + // Split raw diff into per-file chunks and classify each + function splitDiff(raw) { + const files = []; + const parts = raw.split(/^(?=diff --git )/m); + for (const part of parts) { + if (!part.trim()) continue; + const isNew = /^new file mode/m.test(part); + const isDeleted = /^deleted file mode/m.test(part); + files.push({ raw: part, isNew, isDeleted }); + } + return files; } - renderDiff("side-by-side"); + const files = splitDiff(diffString); + + function renderAll(modifiedFormat) { + targetElement.innerHTML = ""; + for (const file of files) { + const div = document.createElement("div"); + targetElement.appendChild(div); + const format = (file.isNew || file.isDeleted) ? "line-by-line" : modifiedFormat; + const ui = new Diff2HtmlUI(div, file.raw, { + drawFileList: false, + matching: "lines", + outputFormat: format, + highlight: true, + colorScheme: "dark", + }); + ui.draw(); + ui.highlightCode(); + } + } + + renderAll("side-by-side"); toggle.addEventListener("change", function () { - renderDiff(this.checked ? "line-by-line" : "side-by-side"); + renderAll(this.checked ? "line-by-line" : "side-by-side"); });