Add light/dark mode support to diff view

This commit is contained in:
Chris Wanstrath 2026-03-11 14:01:40 -07:00
parent 83787ab868
commit f0a692bb35
2 changed files with 41 additions and 13 deletions

View File

@ -4,16 +4,31 @@
<meta charset="utf-8"> <meta charset="utf-8">
<title>{{BRANCH}} — sandlot diff</title> <title>{{BRANCH}} — sandlot diff</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/diff2html/bundles/css/diff2html.min.css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/diff2html/bundles/css/diff2html.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/github-dark.min.css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/github-dark.min.css" media="(prefers-color-scheme: dark)">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/github.min.css" media="(prefers-color-scheme: light)">
<style> <style>
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif; margin: 0; padding: 0; background: #0d1117; color: #e6edf3; } :root {
.header { padding: 24px 32px; border-bottom: 1px solid #30363d; } --bg: #0d1117; --fg: #e6edf3; --fg-secondary: #8b949e; --fg-code: #c9d1d9;
--code-bg: #1f2937; --border: #30363d;
--add: #3fb950; --remove: #f85149;
--color-scheme: dark;
}
@media (prefers-color-scheme: light) {
:root {
--bg: #ffffff; --fg: #1f2328; --fg-secondary: #656d76; --fg-code: #1f2328;
--code-bg: #f6f8fa; --border: #d0d7de;
--add: #1a7f37; --remove: #cf222e;
--color-scheme: light;
}
}
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif; margin: 0; padding: 0; background: var(--bg); color: var(--fg); color-scheme: light dark; }
.header { padding: 24px 32px; border-bottom: 1px solid var(--border); }
.header h1 { margin: 0 0 8px; font-size: 24px; font-weight: 600; } .header h1 { margin: 0 0 8px; font-size: 24px; font-weight: 600; }
.header h1 code { background: #1f2937; padding: 2px 8px; border-radius: 6px; font-size: 22px; } .header h1 code { background: var(--code-bg); padding: 2px 8px; border-radius: 6px; font-size: 22px; }
.prompt { color: #8b949e; margin: 0 0 16px; font-style: italic; } .prompt { color: var(--fg-secondary); margin: 0 0 16px; font-style: italic; }
.meta { display: flex; gap: 32px; } .meta { display: flex; gap: 32px; }
.meta-section h3 { margin: 0 0 6px; font-size: 13px; text-transform: uppercase; color: #8b949e; letter-spacing: 0.05em; } .meta-section h3 { margin: 0 0 6px; font-size: 13px; text-transform: uppercase; color: var(--fg-secondary); letter-spacing: 0.05em; }
.meta-section pre { margin: 0; font-size: 13px; line-height: 1.5; color: #c9d1d9; white-space: pre-wrap; } .meta-section pre { margin: 0; font-size: 13px; line-height: 1.5; color: var(--fg-code); white-space: pre-wrap; }
.diff-container { padding: 16px 32px; } .diff-container { padding: 16px 32px; }
.d2h-file-wrapper { margin-bottom: 16px; border-radius: 6px; overflow: hidden; } .d2h-file-wrapper { margin-bottom: 16px; border-radius: 6px; overflow: hidden; }
.d2h-code-line-ctn { background: transparent; } .d2h-code-line-ctn { background: transparent; }
@ -24,7 +39,7 @@
<h1><code>{{BRANCH}}</code></h1> <h1><code>{{BRANCH}}</code></h1>
{{PROMPT_SECTION}} {{PROMPT_SECTION}}
<div style="margin: 12px 0;"> <div style="margin: 12px 0;">
<label style="cursor:pointer; user-select:none; font-size:14px; color:#8b949e;"> <label style="cursor:pointer; user-select:none; font-size:14px; color:var(--fg-secondary);">
<input type="checkbox" id="unified-toggle" style="cursor:pointer; vertical-align:middle; margin-right:6px;"> <input type="checkbox" id="unified-toggle" style="cursor:pointer; vertical-align:middle; margin-right:6px;">
Unified Unified
</label> </label>
@ -41,6 +56,11 @@
const diffString = {{DIFF_JSON}}; const diffString = {{DIFF_JSON}};
const targetElement = document.getElementById("diff"); const targetElement = document.getElementById("diff");
const toggle = document.getElementById("unified-toggle"); const toggle = document.getElementById("unified-toggle");
const schemeMq = window.matchMedia("(prefers-color-scheme: dark)");
function getColorScheme() {
return schemeMq.matches ? "dark" : "light";
}
// Split raw diff into per-file chunks and classify each // Split raw diff into per-file chunks and classify each
function splitDiff(raw) { function splitDiff(raw) {
@ -68,20 +88,28 @@
matching: "lines", matching: "lines",
outputFormat: format, outputFormat: format,
highlight: true, highlight: true,
colorScheme: "dark", colorScheme: getColorScheme(),
}, hljs); }, hljs);
ui.draw(); ui.draw();
ui.highlightCode(); ui.highlightCode();
} }
} }
function currentFormat() {
return toggle.checked ? "line-by-line" : "side-by-side";
}
const saved = localStorage.getItem("sandlot-unified") === "1"; const saved = localStorage.getItem("sandlot-unified") === "1";
toggle.checked = saved; toggle.checked = saved;
renderAll(saved ? "line-by-line" : "side-by-side"); renderAll(currentFormat());
toggle.addEventListener("change", function () { toggle.addEventListener("change", function () {
localStorage.setItem("sandlot-unified", this.checked ? "1" : "0"); localStorage.setItem("sandlot-unified", this.checked ? "1" : "0");
renderAll(this.checked ? "line-by-line" : "side-by-side"); renderAll(currentFormat());
});
schemeMq.addEventListener("change", function () {
renderAll(currentFormat());
}); });
</script> </script>
</body> </body>

View File

@ -43,8 +43,8 @@ function formatStat(raw: string): string {
if (pipe === -1) return line if (pipe === -1) return line
return line.slice(0, pipe + 1) + return line.slice(0, pipe + 1) +
line.slice(pipe + 1) line.slice(pipe + 1)
.replace(/\+/g, '<span style="color:#3fb950">+</span>') .replace(/\+/g, '<span style="color:var(--add)">+</span>')
.replace(/-/g, '<span style="color:#f85149">-</span>') .replace(/-/g, '<span style="color:var(--remove)">-</span>')
}).join("\n") }).join("\n")
} }