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.
server/web/auth.go +6−3
| @@ -159,6 +159,7 @@ func (w *Web) Middleware(next http.Handler) http.Handler { | |||
| 159 | 159 | } | |
| 160 | 160 | } | |
| 161 | 161 | sw := &statusWriter{ResponseWriter: rw} | |
| 162 | gw := newCompressor(sw, r) | ||
| 162 | 163 | defer func() { | |
| 163 | 164 | v := recover() | |
| 164 | 165 | if v == nil { | |
| @@ -174,7 +175,8 @@ func (w *Web) Middleware(next http.Handler) http.Handler { | |||
| 174 | 175 | } | |
| 175 | 176 | w.serverError(sw, r, "") | |
| 176 | 177 | }() | |
| 177 | next.ServeHTTP(sw, r) | ||
| 178 | next.ServeHTTP(gw, r) | ||
| 179 | gw.Close() | ||
| 178 | 180 | w.recordPageView(r, sw) | |
| 179 | 181 | }) | |
| 180 | 182 | } | |
| @@ -346,9 +348,10 @@ func (w *Web) securityHeaders(rw http.ResponseWriter, r *http.Request) { | |||
| 346 | 348 | rw.Header().Set("Referrer-Policy", "same-origin") | |
| 347 | 349 | // There is no inline style in any template and none is generated, so the | |
| 348 | 350 | // stylesheet is the only style source. object-src is closed because nothing here | |
| 349 | // embeds a plugin, and a page that never loads one cannot be made to. | ||
| 351 | // embeds a plugin, and a page that never loads one cannot be made to. The | ||
| 352 | // syntax highlighter runs in a worker of its own, hence worker-src. | ||
| 350 | 353 | rw.Header().Set("Content-Security-Policy", | |
| 351 | "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; connect-src 'self'; form-action 'self'; frame-ancestors 'none'; base-uri 'none'; object-src 'none'") | ||
| 354 | "default-src 'self'; script-src 'self'; worker-src 'self'; style-src 'self'; img-src 'self' data:; connect-src 'self'; form-action 'self'; frame-ancestors 'none'; base-uri 'none'; object-src 'none'") | ||
| 352 | 355 | // Nothing on this page needs a device, a payment API or an interest cohort, and | |
| 353 | 356 | // the site runs beside its own pages on a pages subdomain: COOP/CORP keep a | |
| 354 | 357 | // document from being opened or read as somebody else's resource. | |