website

#astro#js#html#css

git clone https://git.pyrossh.dev/website

木 Personal website of pyrossh. Built with astrojs, shiki, vite.


54662a2 — pyrossh 2026-11-05T19:45:56+05:30
Omit lockfile and generated diffs from commit pages
Files changed (2) hide show
  1. src/_data/repoCommits.js +40 -4
  2. tests/pages.test.js +10 -0
src/_data/repoCommits.js CHANGED
@@ -1,3 +1,4 @@
1
+ import path from "node:path";
1
2
  import { html as renderDiffHtml, parse as parseDiff } from "diff2html";
2
3
  import { readCache, writeCache } from "../_helpers/dataCache.js";
3
4
  import { discoverLocalRepos, getCommitDiff, getHeadSha } from "../_helpers/gitRepos.js";
@@ -16,14 +17,49 @@ const CONCURRENCY = 8;
16
17
  const MAX_DIFF_SIZE = 300 * 1024;
17
18
  const DIFF_TOO_LARGE_HTML = '<p class="diff-too-large">This diff is too large to display.</p>';
18
19
 
20
+ // Machine-written files nobody reads as a diff. Dropped before the size check
21
+ // so a big lockfile change can't hide the hand-written changes beside it.
22
+ const LOCKFILES = new Set([
23
+ "bun.lock",
24
+ "bun.lockb",
25
+ "Cargo.lock",
26
+ "Gemfile.lock",
27
+ "go.sum",
28
+ "package-lock.json",
29
+ "pnpm-lock.yaml",
30
+ "Podfile.lock",
31
+ "pubspec.lock",
32
+ "uv.lock",
33
+ "yarn.lock",
34
+ ]);
35
+ // plum's tree-sitter output.
36
+ const isGeneratedFile = (filePath) => filePath === "src/parser.c" || LOCKFILES.has(path.basename(filePath));
37
+
38
+ const escapeHtml = (text) => text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
39
+
40
+ const omitGeneratedFiles = (patch) => {
41
+ const kept = [];
42
+ const omitted = [];
43
+ for (const section of patch.split(/^(?=diff --git )/m)) {
44
+ const filePath = section.match(/^diff --git a\/.+ b\/(.+)$/m)?.[1];
45
+ if (filePath && isGeneratedFile(filePath)) omitted.push(filePath);
46
+ else kept.push(section);
47
+ }
48
+ return { patch: kept.join(""), omitted };
49
+ };
50
+
19
51
  const toDiffHtml = (diffText) => {
20
52
  const idx = diffText.indexOf("diff --git");
53
+ if (idx < 0) return "";
21
- const patch = idx >= 0 ? diffText.slice(idx) : "";
54
+ const { patch, omitted } = omitGeneratedFiles(diffText.slice(idx));
55
+ const note = omitted.length
56
+ ? `<p class="diff-omitted">Generated files not shown: ${omitted.map(escapeHtml).join(", ")}</p>`
57
+ : "";
22
- if (!patch.trim()) return "";
58
+ if (!patch.trim()) return note;
23
- if (patch.length > MAX_DIFF_SIZE) return DIFF_TOO_LARGE_HTML;
59
+ if (patch.length > MAX_DIFF_SIZE) return note + DIFF_TOO_LARGE_HTML;
24
60
  try {
25
61
  const json = parseDiff(patch);
26
- return renderDiffHtml(json, { drawFileList: true, matching: "lines" });
62
+ return note + renderDiffHtml(json, { drawFileList: true, matching: "lines" });
27
63
  } catch {
28
64
  return "";
29
65
  }
tests/pages.test.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { after, before, describe, test } from "node:test";
2
2
  import assert from "node:assert/strict";
3
+ import { execFileSync } from "node:child_process";
3
4
  import path from "node:path";
4
5
  import { fileURLToPath } from "node:url";
5
6
  import { chromium } from "playwright";
@@ -180,6 +181,15 @@ describe("repo pages", () => {
180
181
  assert.equal(await page.locator(".nav a.active-tab").textContent(), "Commits");
181
182
  });
182
183
 
184
+ test("commit pages name lockfiles instead of rendering their diffs", async () => {
185
+ const hash = execFileSync("git", ["log", "-1", "--diff-filter=M", "--format=%H", "--", "package-lock.json"], {
186
+ encoding: "utf8",
187
+ }).trim();
188
+ await goto(`/repos/${repoId}/commits/${hash}/`);
189
+ assert.match(await page.locator(".diff-omitted").textContent(), /package-lock\.json/);
190
+ assert.equal(await page.locator(".d2h-file-name", { hasText: "package-lock.json" }).count(), 0);
191
+ });
192
+
183
193
  test("repo files index renders the tree and a default file", async () => {
184
194
  const response = await goto(`/repos/${repoId}/files/`);
185
195
  assert.equal(response.status(), 200);