From 7a9620f9d7a825aa9af8910aec771eb4c5fe2655 Mon Sep 17 00:00:00 2001 From: Donavan Fritz Date: Mon, 15 Jun 2026 23:06:47 -0500 Subject: [PATCH] render: colourise diff details + widen card, no mid-line wrap When details is a unified diff (the network-configs notify feeds `git diff HEAD~1`), colour each line like a pager: additions green, deletions red, hunk headers violet, file/meta headers dim. Non-diff details (auto-log output) still render as a plain muted block. Also widen the card 600->760px and switch the details
 from
pre-wrap/word-break to white-space:pre + overflow-x:auto so diff lines
scroll instead of wrapping into mush.

Co-Authored-By: Claude Opus 4.8 (1M context) 
---
 scripts/send.py | 73 ++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 69 insertions(+), 4 deletions(-)

diff --git a/scripts/send.py b/scripts/send.py
index 0b92cc6..09be414 100644
--- a/scripts/send.py
+++ b/scripts/send.py
@@ -168,6 +168,71 @@ def fetch_failing_log(
     return "\n".join(cleaned[-log_lines:]).strip()
 
 
+# --- diff rendering -------------------------------------------------------
+# When `details` is a unified diff (the network-configs notify feeds
+# `git diff HEAD~1`), colour each line the way a terminal pager would:
+# additions green, deletions red, hunk headers violet, file/meta headers dim.
+# Non-diff details (e.g. auto-log output) fall through to a single muted block.
+DIFF_ADD = OK_FG
+DIFF_DEL = ERROR_FG
+DIFF_HUNK = ACCENT_VIOLET
+DIFF_META = MUTED
+DIFF_CONTEXT = MUTED_STRONG
+
+_HUNK_RE = re.compile(r"^@@ -\d+(?:,\d+)? \+\d+(?:,\d+)? @@")
+# Lines that start with +/- but are file headers, not content changes.
+_META_PREFIXES = (
+    "diff --git ",
+    "index ",
+    "--- ",
+    "+++ ",
+    "new file mode ",
+    "deleted file mode ",
+    "old mode ",
+    "new mode ",
+    "rename ",
+    "similarity index ",
+    "copy ",
+    "Binary files ",
+)
+
+
+def _looks_like_diff(text: str) -> bool:
+    """True if `text` reads as a unified diff (has a git header or a hunk)."""
+    for ln in text.splitlines():
+        if ln.startswith("diff --git ") or _HUNK_RE.match(ln):
+            return True
+    return False
+
+
+def _diff_line_color(line: str) -> str:
+    if _HUNK_RE.match(line):
+        return DIFF_HUNK
+    if line.startswith(_META_PREFIXES):
+        return DIFF_META
+    if line.startswith("+"):
+        return DIFF_ADD
+    if line.startswith("-"):
+        return DIFF_DEL
+    return DIFF_CONTEXT
+
+
+def colorize_diff_html(details: str) -> str:
+    """Return inner HTML for the details 
: one coloured span per line."""
+    spans = [
+        f'{escape(line)}'
+        for line in details.split("\n")
+    ]
+    return "\n".join(spans)
+
+
+def details_inner_html(details: str) -> str:
+    """Colour-highlight diffs; otherwise escape as a plain muted block."""
+    if _looks_like_diff(details):
+        return colorize_diff_html(details)
+    return escape(details)
+
+
 def fact_rows(items: Iterable[tuple[str, str, str]]) -> tuple[str, str]:
     """Build the HTML  rows and plain-text lines for the fact list.
 
@@ -222,8 +287,8 @@ def render(
           
{escape(details)}
+ font-size:12px;line-height:1.55;white-space:pre; + overflow-x:auto;">{details_inner_html(details)} """ @@ -240,8 +305,8 @@ def render(
-