vole
Clone
Read only, no credentials:
https://rodent.software/git/vole.git
Write over SSH with a registered key:
git clone ssh://git@0.0.0.0:2222/vole.git
A free and open-source forge that lives in your Git repo.
Highlight with Prism in a worker and gzip text responses
306f36fcef89c145abcd0c5331453d0b179f37ce · Keenan Nemetz · 12d ago · parent e5542ac6
Highlight with Prism in a worker and gzip text responses
The code browser now names a blob's language and lets the browser colour it.
Chroma is gone: server/web/highlight.go is an extension table, and
static/prism-worker.js runs Prism — every language Prism ships — off the main
thread. The server sends escaped lines with their numbers and L# anchors, so a
page is complete and scrollable before any script runs and the worker only swaps
the contents of each line cell. The table covers 186 languages; a file it does
not claim stays plain rather than being coloured by a guess.
The bundle those grammars make is 545 KB, so the instance now gzips text
responses itself instead of relying on a proxy, and static assets carry a
content ETag so a browser revalidates with a 304 rather than re-downloading the
bundle on every code page. The raw-download route opts out with
Cache-Control: no-transform because it promises an exact Content-Length.
This also makes JavaScript a requirement rather than a nicety: the label and
assignee token inputs lose their noscript save buttons and their comma-separated
text fallback, and the docs say so.
Measured: release binary 26.08 MB -> 22.70 MB; /r/{repo}/code 11.1 KB -> 2.6 KB
over the wire; the Prism bundle 545 KB -> 206 KB gzipped, fetched once.
scripts/vendor-prism.py regenerates the bundle from Prism's components.json
require graph, and --check fails if the committed assets drift.
docs/ui-plan.md +12−5
| @@ -13,11 +13,12 @@ deliberately rather than by drift. | |||
| 13 | 13 | A light theme is a second block of variables, not a rewrite; it currently | |
| 14 | 14 | follows the operating system's `prefers-color-scheme`. | |
| 15 | 15 | - **Server rendered.** Go `html/template` produces the page. HTMX is the default | |
| 16 | dynamic layer, vendored into the binary; JavaScript remains for passkeys, | ||
| 17 | clipboard copy, and rich widgets such as the label/assignee token input. | ||
| 18 | No SPA, no client-side router, no npm build. | ||
| 19 | - **Progressive enhancement.** Forms keep a normal `method`/`action` fallback. | ||
| 20 | Handlers answer a fragment when `HX-Request: true` and a redirect otherwise. | ||
| 16 | dynamic layer, vendored into the binary; JavaScript is required — passkeys, | ||
| 17 | clipboard copy, and rich widgets such as the label/assignee token input all | ||
| 18 | need it. No SPA, no client-side router, no npm build. | ||
| 19 | - **JavaScript required.** There is no no-script fallback: a browser without | ||
| 20 | JavaScript gets a page it cannot operate. Forms post through HTMX, and handlers | ||
| 21 | answer a fragment when `HX-Request: true` and a redirect otherwise. | ||
| 21 | 22 | - **Identity later.** Keep the `vole` wordmark as a placeholder and keep colour, | |
| 22 | 23 | type, radius, and spacing in tokens so a real identity is a token swap. | |
| 23 | 24 | - **Single tenant.** No organisation/workspace switcher. The global bar has one | |
| @@ -57,6 +58,12 @@ pane width. The branch crumb returns to the Code overview rather than opening a | |||
| 57 | 58 | second directory listing. Settings appears for the viewer when the repository | |
| 58 | 59 | ACL gives them the admin role. | |
| 59 | 60 | ||
| 61 | A blob is served as escaped lines with their numbers and `id="L<n>"` anchors, and | ||
| 62 | the browser colours it: `static/prism-worker.js` holds Prism and every language it | ||
| 63 | ships, so the server names the language (an extension table, not a detector) and | ||
| 64 | does no lexing. The worker starts only on a page with a blob; a file the table | ||
| 65 | does not claim is served plain. | ||
| 66 | |||
| 60 | 67 | ## Surfaces | |
| 61 | 68 | ||
| 62 | 69 | Status: `done` exists today · `wip` in progress · `todo` missing. | |