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/highlight_test.go +76
| @@ -0,0 +1,76 @@ | |||
| 1 | package web | ||
| 2 | |||
| 3 | import ( | ||
| 4 | "os" | ||
| 5 | "strings" | ||
| 6 | "testing" | ||
| 7 | ) | ||
| 8 | |||
| 9 | func TestPrismLanguageNamesKnownFiles(t *testing.T) { | ||
| 10 | t.Parallel() | ||
| 11 | for name, want := range map[string]string{ | ||
| 12 | "main.go": "go", | ||
| 13 | "internal/run.go": "go", | ||
| 14 | "web/app.tsx": "typescript", | ||
| 15 | "script.mjs": "javascript", | ||
| 16 | "style.scss": "scss", | ||
| 17 | "deploy/nginx.conf": "nginx", | ||
| 18 | "app.conf": "ini", | ||
| 19 | "Makefile": "makefile", | ||
| 20 | "cmake/CMakeLists.txt": "cmake", | ||
| 21 | "Dockerfile": "docker", | ||
| 22 | "Containerfile": "docker", | ||
| 23 | ".editorconfig": "editorconfig", | ||
| 24 | "README.MD": "markdown", | ||
| 25 | "terraform/main.tf": "hcl", | ||
| 26 | // A file the highlighter does not claim stays plain: a wrong grammar is | ||
| 27 | // worse than no grammar. | ||
| 28 | "go.sum": "go-module", | ||
| 29 | "app.py": "python", | ||
| 30 | "lib.rs": "rust", | ||
| 31 | "main.js": "javascript", | ||
| 32 | "component.tsx": "typescript", | ||
| 33 | "deploy.tf": "hcl", | ||
| 34 | "schema.graphql": "graphql", | ||
| 35 | "queries.sql": "sql", | ||
| 36 | "notes.rst": "rest", | ||
| 37 | "LICENSE": "", | ||
| 38 | "notes.txt": "", | ||
| 39 | "image.webp": "", | ||
| 40 | } { | ||
| 41 | if got := prismLanguage(name); got != want { | ||
| 42 | t.Errorf("prismLanguage(%q) = %q, want %q", name, got, want) | ||
| 43 | } | ||
| 44 | } | ||
| 45 | } | ||
| 46 | |||
| 47 | // TestPrismLanguagesAreVendored holds the server's table to the worker's bundle. | ||
| 48 | // A name here with no grammar there colours nothing, and nothing fails at build | ||
| 49 | // time; the blob just quietly stays plain. | ||
| 50 | func TestPrismLanguagesAreVendored(t *testing.T) { | ||
| 51 | t.Parallel() | ||
| 52 | var sources []string | ||
| 53 | for _, path := range []string{"static/prism.min.js", "static/prism-languages.min.js"} { | ||
| 54 | data, err := os.ReadFile(path) | ||
| 55 | if err != nil { | ||
| 56 | t.Fatalf("vendored Prism is missing: %v", err) | ||
| 57 | } | ||
| 58 | sources = append(sources, string(data)) | ||
| 59 | } | ||
| 60 | defined := func(lang string) bool { | ||
| 61 | for _, src := range sources { | ||
| 62 | // Prism registers a language as `languages.name=` or, for a name with | ||
| 63 | // punctuation in it, `languages["name"]=`. | ||
| 64 | if strings.Contains(src, "languages."+lang+"=") || | ||
| 65 | strings.Contains(src, `languages["`+lang+`"]=`) { | ||
| 66 | return true | ||
| 67 | } | ||
| 68 | } | ||
| 69 | return false | ||
| 70 | } | ||
| 71 | for name, lang := range prismLanguages { | ||
| 72 | if !defined(lang) { | ||
| 73 | t.Errorf("%q is mapped to %q, which static/prism-languages.min.js does not define", name, lang) | ||
| 74 | } | ||
| 75 | } | ||
| 76 | } | ||