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/templates/issues.html +2−4
| @@ -103,8 +103,7 @@ | |||
| 103 | 103 | {{if .CanEditLabels}} | |
| 104 | 104 | <form method="post" action="/r/{{.Name}}/issues/{{.Issue.ID}}/labels" class="label-form" hx-post="/r/{{.Name}}/issues/{{.Issue.ID}}/labels" hx-target="#issue-labels" hx-swap="outerHTML" hx-trigger="token-change" hx-sync="this:replace"> | |
| 105 | 105 | <input type="hidden" name="csrf" value="{{.CSRF}}"> | |
| 106 | {{template "token_input" (tokenPicker .Issue.Labels .AllLabels "labels" "label" "Add labels…")}} | ||
| 107 | <noscript><div class="form-actions"><button class="secondary" type="submit">{{icon "check"}}Save labels</button></div></noscript> | ||
| 106 | {{template "token_input" (tokenPicker .Issue.Labels .AllLabels "label" "Add labels…")}} | ||
| 108 | 107 | </form> | |
| 109 | 108 | {{else}} | |
| 110 | 109 | {{if .Issue.Labels}} | |
| @@ -123,8 +122,7 @@ | |||
| 123 | 122 | {{if .CanEditAssignees}} | |
| 124 | 123 | <form method="post" action="/r/{{.Name}}/issues/{{.Issue.ID}}/assignees" class="label-form" hx-post="/r/{{.Name}}/issues/{{.Issue.ID}}/assignees" hx-target="#issue-assignees" hx-swap="outerHTML" hx-trigger="token-change" hx-sync="this:replace"> | |
| 125 | 124 | <input type="hidden" name="csrf" value="{{.CSRF}}"> | |
| 126 | {{template "token_input" (tokenPicker .Issue.Assignees .Assignable "assignees" "assignee" "Add assignees…")}} | ||
| 127 | <noscript><div class="form-actions"><button class="secondary" type="submit">{{icon "check"}}Save assignees</button></div></noscript> | ||
| 125 | {{template "token_input" (tokenPicker .Issue.Assignees .Assignable "assignee" "Add assignees…")}} | ||
| 128 | 126 | </form> | |
| 129 | 127 | {{else}} | |
| 130 | 128 | {{if .Issue.Assignees}} | |