Files
diff-highlighter/README.md
Tilo Klarenbeek 314c34fe52 Initial commit: Diff Highlighter Chrome extension (MV3, TypeScript)
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>
2026-06-16 13:01:06 +02:00

86 lines
3.2 KiB
Markdown

# 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/plain` pages whose URL ends in `.diff`/`.patch`
(the `include_globs` matcher covers query strings too, e.g. `…/123.diff?token=…`).
- It reads the browser-rendered `<pre>`, parses the unified-diff structure, and:
1. **Instantly** repaints every line with its diff color (green/red/context/headers).
2. **Progressively** layers syntax highlighting via [highlight.js](https://highlightjs.org/),
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+D` flips the master toggle from anywhere.
- Only the `storage` permission 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+.
```sh
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
1. `chrome://extensions` → enable **Developer mode**.
2. **Load unpacked** → select the `dist/` folder.
3. 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`](.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:
1. Push this repo to Codeberg:
```sh
git remote add origin https://codeberg.org/<you>/diff-highlighter.git
git push -u origin main
```
2. Connect a runner: repo **Settings → Actions → Runners** (or use Codeberg's hosted
runners). If using a hosted runner, change `runs-on: docker` to 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
```