Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

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/codebrowser.go +12−8

@@ -55,7 +55,7 @@ type codeView struct {
55 55 Truncated bool
56 56 LineCut bool
57 57 Lines []string
58 Highlight template.HTML
58 Language string
59 59 Size int64
60 60 IsMarkdown bool
61 61 Preview bool
@@ -206,14 +206,17 @@ func (w *Web) blob(rw http.ResponseWriter, r *http.Request, raw bool) {
206 206 h := rw.Header()
207 207 h.Set("Content-Type", "text/plain; charset=utf-8")
208 208 h.Set("Content-Length", strconv.FormatInt(stream.Size, 10))
209 // The announced length is part of the contract, so a text blob must not be
210 // re-encoded on the way out; a compressed body has no such length.
211 h.Set("Cache-Control", "no-transform")
209 212 if _, err := io.Copy(rw, stream); err != nil {
210 213 // The client hung up mid-download; headers are already out.
211 214 w.Logger("raw %s %s: %v", m.Name, p, err)
212 215 }
213 216 return
214 217 }
215 // Everything the page shows is a preview: the tree, the line numbers and the
216 // highlighter are all bounded, so there is no reason to hold the whole file.
218 // Everything the page shows is a preview: the tree and the line numbers are
219 // bounded, so there is no reason to hold the whole file.
217 220 data, truncated, err := stream.ReadPrefix(maxInlineBytes)
218 221 if err != nil {
219 222 w.serverError(rw, r, "cannot read "+p+": "+err.Error())
@@ -231,11 +234,12 @@ func (w *Web) blob(rw http.ResponseWriter, r *http.Request, raw bool) {
231 234 lines = lines[:maxNumberedLines]
232 235 lineCut = true
233 236 }
234 // Highlight the same bytes the table would show. A language we cannot name
235 // stays plain, which is better than guessing wrong about its grammar.
236 var highlighted template.HTML
237 // The browser colours the same bytes the table shows. All the server does is
238 // name the language, and a language it cannot name stays plain, which is
239 // better than guessing wrong about its grammar.
240 language := ""
237 241 if !binary {
238 highlighted = highlightCode(p, strings.Join(lines, "\n"))
242 language = prismLanguage(p)
239 243 }
240 244 markdown := !binary && isMarkdown(p)
241 245 // A markdown file opens as source like any other file. Rendering it is an
@@ -259,7 +263,7 @@ func (w *Web) blob(rw http.ResponseWriter, r *http.Request, raw bool) {
259 263 view.Truncated = truncated
260 264 view.LineCut = lineCut
261 265 view.Lines = lines
262 view.Highlight = highlighted
266 view.Language = language
263 267 view.Size = stream.Size
264 268 view.IsMarkdown = markdown
265 269 view.Preview = preview