Highlights .diff/.patch files inline — additions green, deletions red, hunk/file headers styled, with toggleable highlight.js syntax highlighting. - MV3, content script gated on text/plain + URL ending in .diff/.patch - Two-phase render: instant diff colors, then chunked idle-time syntax - Popup switches + Alt+D shortcut, persisted in chrome.storage.sync, live re-render - Light/dark via prefers-color-scheme; only the `storage` permission - TypeScript + esbuild build; Forgejo Actions CI (typecheck + build) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
3.2 KiB
Diff Highlighter
A Chrome (Manifest V3) extension that highlights .diff and .patch files in the
browser: additions green, deletions red, with hunk/file headers styled and the
underlying code syntax-highlighted by language. Works on GitHub/Bitbucket PR
.diff/.patch URLs, raw files, and local file:// diffs. Light/dark aware, fast,
and fully toggleable.
How it works
- A content script runs only on
text/plainpages whose URL ends in.diff/.patch(theinclude_globsmatcher covers query strings too, e.g.…/123.diff?token=…). - It reads the browser-rendered
<pre>, parses the unified-diff structure, and:- Instantly repaints every line with its diff color (green/red/context/headers).
- Progressively layers syntax highlighting via highlight.js, processed in idle-time chunks so large diffs stay responsive. Above ~50k highlightable lines, syntax is skipped to preserve speed (diff colors remain).
- Toggling is instant and reload-free: the popup writes
chrome.storage.sync, and the content script re-renders on change.Alt+Dflips the master toggle from anywhere. - Only the
storagepermission is requested — declarative content scripts need no host permissions.
Toggles
| Control | Effect |
|---|---|
| Highlighting (popup) | Master switch for the green/red diff layer. |
| Syntax highlighting (popup) | Layer language-aware token colors on top. |
Alt+D |
Flip the master switch (rebind at chrome://extensions/shortcuts). |
Build
Requires Node 20+.
npm ci
npm run build # type-checks, then bundles to dist/
npm run watch # rebuild on change (dev)
dist/ is the unpacked extension (git-ignored).
Load in Chrome
chrome://extensions→ enable Developer mode.- Load unpacked → select the
dist/folder. - For local diffs, open the extension's Details page and enable
“Allow access to file URLs.” Then try
samples/example.diff.
Continuous integration (Codeberg / Forgejo Actions)
CI lives in .forgejo/workflows/ci.yml and runs
npm ci → typecheck → build in a node:22-bookworm container — the same steps as a
local build, so a green local build means green CI.
To wire it up on Codeberg:
- Push this repo to Codeberg:
git remote add origin https://codeberg.org/<you>/diff-highlighter.git git push -u origin main - Connect a runner: repo Settings → Actions → Runners (or use Codeberg's hosted
runners). If using a hosted runner, change
runs-on: dockerto its label (e.g.codeberg-tiny).
Scope
Triggers on URLs/files whose path ends in .diff/.patch and that render as plain text.
In-app HTML diff views (GitHub's "Files changed", Bitbucket's /diff endpoint) are out
of scope — those are full HTML pages, not raw text.
Layout
src/
manifest.json MV3 manifest
content.ts detect + render + live toggle
diff-parser.ts pure diff parsing / language detection
background.ts defaults + Alt+D command
popup/ popup UI
styles/ diff.css, hljs-theme.css, popup.css (all light/dark)
scripts/ build.mjs (esbuild), make-icons.mjs
.forgejo/workflows/ CI