Extract browse HTML into external template
The HTML for the browse view was inlined as a template literal in browse.ts, making it hard to edit and losing syntax highlighting. Move it to browse.html and use placeholder replacement instead. Also update branchDiff to accept the main branch as a parameter so the caller resolves it once and reuses it for diffStat too.
This commit is contained in:
parent
b8f7aea3b0
commit
909189b745
60
src/commands/browse.html
Normal file
60
src/commands/browse.html
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>{{BRANCH}} — sandlot diff</title>
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/diff2html/bundles/css/diff2html.min.css">
|
||||
<style>
|
||||
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif; margin: 0; padding: 0; background: #0d1117; color: #e6edf3; }
|
||||
.header { padding: 24px 32px; border-bottom: 1px solid #30363d; }
|
||||
.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; }
|
||||
.prompt { color: #8b949e; margin: 0 0 16px; font-style: italic; }
|
||||
.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 pre { margin: 0; font-size: 13px; line-height: 1.5; color: #c9d1d9; white-space: pre-wrap; }
|
||||
.diff-container { padding: 16px 32px; }
|
||||
/* Override diff2html for dark theme */
|
||||
.d2h-wrapper { background: #0d1117; }
|
||||
.d2h-file-header { background: #161b22; border-color: #30363d; color: #e6edf3; }
|
||||
.d2h-file-wrapper { border-color: #30363d; margin-bottom: 16px; border-radius: 6px; overflow: hidden; }
|
||||
.d2h-code-linenumber { background: #161b22; color: #8b949e; border-color: #30363d; }
|
||||
.d2h-code-line { background: #0d1117; color: #e6edf3; }
|
||||
.d2h-code-side-line { background: #0d1117; }
|
||||
.d2h-del { background: rgba(248,81,73,0.1); }
|
||||
.d2h-ins { background: rgba(63,185,80,0.1); }
|
||||
.d2h-del .d2h-code-line-ctn { background: rgba(248,81,73,0.15); }
|
||||
.d2h-ins .d2h-code-line-ctn { background: rgba(63,185,80,0.15); }
|
||||
.d2h-code-line-ctn { color: #e6edf3; }
|
||||
.d2h-info { background: #161b22; color: #8b949e; border-color: #30363d; }
|
||||
.d2h-tag { background: #1f6feb; color: #fff; }
|
||||
.d2h-file-stats-wrapper { display: flex; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="header">
|
||||
<h1><code>{{BRANCH}}</code></h1>
|
||||
{{PROMPT_SECTION}}
|
||||
<div class="meta">
|
||||
{{LOG_SECTION}}
|
||||
{{STAT_SECTION}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="diff-container" id="diff"></div>
|
||||
<script src="https://cdn.jsdelivr.net/npm/diff2html/bundles/js/diff2html-ui.min.js"></script>
|
||||
<script>
|
||||
const diffString = {{DIFF_JSON}};
|
||||
const targetElement = document.getElementById("diff");
|
||||
const configuration = {
|
||||
drawFileList: true,
|
||||
matching: "lines",
|
||||
outputFormat: "side-by-side",
|
||||
highlight: true,
|
||||
colorScheme: "dark",
|
||||
};
|
||||
const diff2htmlUi = new Diff2HtmlUI(targetElement, diffString, configuration);
|
||||
diff2htmlUi.draw();
|
||||
diff2htmlUi.highlightCode();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -3,13 +3,15 @@ import * as git from "../git.ts"
|
|||
import { die } from "../fmt.ts"
|
||||
import { requireSession } from "./helpers.ts"
|
||||
|
||||
const template = await Bun.file(new URL("browse.html", import.meta.url).pathname).text()
|
||||
|
||||
export async function action(branch: string) {
|
||||
const { session } = await requireSession(branch)
|
||||
const worktree = session.worktree
|
||||
const main = await git.mainBranch(worktree)
|
||||
|
||||
const [diff, log, stat] = await Promise.all([
|
||||
git.branchDiff(branch, worktree),
|
||||
git.branchDiff(branch, main, worktree),
|
||||
git.commitLog(`${main}..${branch}`, worktree),
|
||||
git.diffStat(`${main}...${branch}`, worktree),
|
||||
])
|
||||
|
|
@ -18,69 +20,12 @@ export async function action(branch: string) {
|
|||
die(`No changes on branch "${branch}" compared to ${main}.`)
|
||||
}
|
||||
|
||||
const prompt = session.prompt ? escapeHtml(session.prompt) : ""
|
||||
const diffJson = JSON.stringify(diff)
|
||||
|
||||
const html = `<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>${escapeHtml(branch)} — sandlot diff</title>
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/diff2html/bundles/css/diff2html.min.css">
|
||||
<style>
|
||||
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif; margin: 0; padding: 0; background: #0d1117; color: #e6edf3; }
|
||||
.header { padding: 24px 32px; border-bottom: 1px solid #30363d; }
|
||||
.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; }
|
||||
.prompt { color: #8b949e; margin: 0 0 16px; font-style: italic; }
|
||||
.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 pre { margin: 0; font-size: 13px; line-height: 1.5; color: #c9d1d9; white-space: pre-wrap; }
|
||||
.diff-container { padding: 16px 32px; }
|
||||
/* Override diff2html for dark theme */
|
||||
.d2h-wrapper { background: #0d1117; }
|
||||
.d2h-file-header { background: #161b22; border-color: #30363d; color: #e6edf3; }
|
||||
.d2h-file-wrapper { border-color: #30363d; margin-bottom: 16px; border-radius: 6px; overflow: hidden; }
|
||||
.d2h-code-linenumber { background: #161b22; color: #8b949e; border-color: #30363d; }
|
||||
.d2h-code-line { background: #0d1117; color: #e6edf3; }
|
||||
.d2h-code-side-line { background: #0d1117; }
|
||||
.d2h-del { background: rgba(248,81,73,0.1); }
|
||||
.d2h-ins { background: rgba(63,185,80,0.1); }
|
||||
.d2h-del .d2h-code-line-ctn { background: rgba(248,81,73,0.15); }
|
||||
.d2h-ins .d2h-code-line-ctn { background: rgba(63,185,80,0.15); }
|
||||
.d2h-code-line-ctn { color: #e6edf3; }
|
||||
.d2h-info { background: #161b22; color: #8b949e; border-color: #30363d; }
|
||||
.d2h-tag { background: #1f6feb; color: #fff; }
|
||||
.d2h-file-stats-wrapper { display: flex; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="header">
|
||||
<h1><code>${escapeHtml(branch)}</code></h1>
|
||||
${prompt ? `<p class="prompt">${prompt}</p>` : ""}
|
||||
<div class="meta">
|
||||
${log ? `<div class="meta-section"><h3>Commits</h3><pre>${escapeHtml(log)}</pre></div>` : ""}
|
||||
${stat ? `<div class="meta-section"><h3>Stats</h3><pre>${escapeHtml(stat)}</pre></div>` : ""}
|
||||
</div>
|
||||
</div>
|
||||
<div class="diff-container" id="diff"></div>
|
||||
<script src="https://cdn.jsdelivr.net/npm/diff2html/bundles/js/diff2html-ui.min.js"></script>
|
||||
<script>
|
||||
const diffString = ${diffJson};
|
||||
const targetElement = document.getElementById("diff");
|
||||
const configuration = {
|
||||
drawFileList: true,
|
||||
matching: "lines",
|
||||
outputFormat: "side-by-side",
|
||||
highlight: true,
|
||||
colorScheme: "dark",
|
||||
};
|
||||
const diff2htmlUi = new Diff2HtmlUI(targetElement, diffString, configuration);
|
||||
diff2htmlUi.draw();
|
||||
diff2htmlUi.highlightCode();
|
||||
</script>
|
||||
</body>
|
||||
</html>`
|
||||
const html = template
|
||||
.replaceAll("{{BRANCH}}", escapeHtml(branch))
|
||||
.replace("{{PROMPT_SECTION}}", session.prompt ? `<p class="prompt">${escapeHtml(session.prompt)}</p>` : "")
|
||||
.replace("{{LOG_SECTION}}", log ? `<div class="meta-section"><h3>Commits</h3><pre>${escapeHtml(log)}</pre></div>` : "")
|
||||
.replace("{{STAT_SECTION}}", stat ? `<div class="meta-section"><h3>Stats</h3><pre>${escapeHtml(stat)}</pre></div>` : "")
|
||||
.replace("{{DIFF_JSON}}", JSON.stringify(diff))
|
||||
|
||||
const tmpPath = `/tmp/sandlot-browse-${branch}.html`
|
||||
await Bun.write(tmpPath, html)
|
||||
|
|
|
|||
|
|
@ -219,8 +219,7 @@ export async function hasNewCommits(worktreePath: string): Promise<boolean> {
|
|||
}
|
||||
|
||||
/** Get the full unified diff of a branch vs main as a string. */
|
||||
export async function branchDiff(branch: string, cwd: string): Promise<string> {
|
||||
const main = await mainBranch(cwd)
|
||||
export async function branchDiff(branch: string, main: string, cwd: string): Promise<string> {
|
||||
const result = await $`git diff ${main}...${branch}`.cwd(cwd).nothrow().quiet()
|
||||
if (result.exitCode !== 0) return ""
|
||||
return result.text()
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user