diff --git a/hive-c0re/src/dashboard.rs b/hive-c0re/src/dashboard.rs index 37e3fbd..eb55d9e 100644 --- a/hive-c0re/src/dashboard.rs +++ b/hive-c0re/src/dashboard.rs @@ -249,12 +249,12 @@ async fn render_approvals(approvals: &[Approval]) -> String { hive_sh4re::ApprovalKind::ApplyCommit => { let sha_short = &a.commit_ref[..a.commit_ref.len().min(12)]; let diff = approval_diff(&a.agent, &a.commit_ref).await; + let diff_html = render_diff_lines(&diff); let _ = writeln!( out, - "
{sha_short}\n \n \n {diff}{sha_short}\n \n \n {diff_html}` keeps
+/// whitespace intact.
+fn render_diff_lines(diff: &str) -> String {
+ let mut out = String::new();
+ for raw in diff.lines() {
+ let cls = match raw.as_bytes().first() {
+ // file headers (`--- a/...` / `+++ b/...`) come before any
+ // line starting with a single `+`/`-`. similar-rs emits them
+ // with the doubled prefix.
+ _ if raw.starts_with("--- ") => "diff-file",
+ _ if raw.starts_with("+++ ") => "diff-file",
+ Some(b'@') => "diff-hunk",
+ Some(b'+') => "diff-add",
+ Some(b'-') => "diff-del",
+ _ => "diff-ctx",
+ };
+ let _ = writeln!(
+ out,
+ "{}",
+ html_escape(raw),
+ );
+ }
+ out
+}
+
/// Returns either an empty string (agent is up-to-date / no rev known) or
/// a clickable "needs update" badge whose form POSTs to /rebuild/.
fn update_badge_for(name: &str, current_rev: Option<&str>) -> String {
@@ -599,9 +626,15 @@ const STYLE: &str = r#"
overflow-x: auto;
font-size: 0.85em;
line-height: 1.4;
- color: var(--fg);
+ color: var(--muted);
white-space: pre;
}
+ .diff span { display: block; }
+ .diff .diff-add { color: var(--green); }
+ .diff .diff-del { color: var(--red); }
+ .diff .diff-hunk { color: var(--cyan); }
+ .diff .diff-file { color: var(--purple); font-weight: bold; }
+ .diff .diff-ctx { color: var(--fg); }
.msgflow {
background: var(--bg-elev);
border: 1px solid var(--border);