thunderbird-patch-review
Easy-to-use patch review interface for Thunderbird
Contribute: ~marcc/thunderbird-review-plugin@lists.sr.ht
git clone git://mccd.space/thunderbird-patch-review
| Log | Files | Refs | README | LICENSE |
commit c14e5e0e45b927dd4dbacabc06ba8b670b2b75d5 parent f801ebecd98f909249acb24c219cf1e5bed57e13 Author: Pi Agent <agent@pi.local> Date: Sat, 18 Jul 2026 12:52:35 +0200 review: warn on binary patches with optional raw display Replace the bare 'Binary file — not reviewable inline.' note with a binaryBlock that flags binary changes prominently (red left border) and offers a Display/Hide raw patch toggle showing the verbatim diff text sliced from the parsed body lines for that file. Diffstat:
| M | extension/review/review.css | | | 20 | ++++++++++++++++++++ |
| M | extension/review/review.js | | | 48 | ++++++++++++++++++++++++++++++++++++++++++++---- |
2 files changed, 64 insertions(+), 4 deletions(-)
diff --git a/extension/review/review.css b/extension/review/review.css
@@ -232,6 +232,26 @@ button.primary:hover { color: #fff; opacity: 0.9; }
.file .file-note { padding: 0.4rem 0.8rem; color: var(--muted); }
+.binary-note {
+ padding: 0.4rem 0.8rem 0.6rem;
+ color: var(--muted);
+ border-left: 3px solid #d1242f;
+}
+.binary-note .file-note { padding: 0; }
+.binary-note button { margin-top: 0.4rem; }
+.binary-note .binary-raw {
+ margin: 0.5rem 0 0;
+ padding: 0.5rem 0.7rem;
+ max-height: 16rem;
+ overflow: auto;
+ border: 1px solid var(--border);
+ border-radius: 6px;
+ background: var(--bg);
+ font: 11px/1.4 ui-monospace, monospace;
+ white-space: pre-wrap;
+ color: var(--muted);
+}
+
table.diff {
width: 100%;
border-collapse: collapse;
diff --git a/extension/review/review.js b/extension/review/review.js
@@ -149,10 +149,7 @@ function renderPatch() {
details.appendChild(summary);
if (file.isBinary) {
- const note = document.createElement("div");
- note.className = "file-note";
- note.textContent = "Binary file — not reviewable inline.";
- details.appendChild(note);
+ details.appendChild(binaryBlock(file, parsed));
} else {
details.appendChild(renderFileTable(file, fileIndex));
}
@@ -174,6 +171,49 @@ function fileLabel(file) {
return file.displayPath;
}
+function binaryBlock(file, parsed) {
+ const wrap = document.createElement("div");
+ wrap.className = "binary-note";
+
+ const note = document.createElement("div");
+ note.className = "file-note";
+ note.textContent =
+ "Binary file changed — cannot review line-by-line. The patch carries the encoded blob, not reviewable content.";
+ wrap.appendChild(note);
+
+ const show = document.createElement("button");
+ show.textContent = "Display raw patch";
+ show.addEventListener("click", () => {
+ if (wrap.querySelector("pre")) {
+ wrap.querySelector("pre").remove();
+ show.textContent = "Display raw patch";
+ return;
+ }
+ const pre = document.createElement("pre");
+ pre.className = "binary-raw";
+ pre.textContent = rawFilePatch(file, parsed);
+ show.before(pre);
+ show.textContent = "Hide raw patch";
+ });
+ wrap.appendChild(show);
+ return wrap;
+}
+
+function rawFilePatch(file, parsed) {
+ const lines = parsed.bodyLines || [];
+ const start = file.bodyLine ?? 0;
+ if (!lines.length) return "";
+ let end = lines.length;
+ for (let i = start + 1; i < lines.length; i++) {
+ if (/^diff --git /.test(lines[i])) { end = i; break; }
+ }
+ // Trim the trailing git signature if present.
+ for (let i = end - 1; i > start; i--) {
+ if (/^-- ?$/.test(lines[i])) { end = i; break; }
+ }
+ return lines.slice(start, end).join("\n").trimEnd();
+}
+
function renderFileTable(file, fileIndex) {
const table = document.createElement("table");
table.className = "diff";