---
id: 9a9e58cd-9994-44c9-a8ca-fc3bbdd2f04a
title: 'Code view: add build-time syntax highlighting (no JS) + line-number gutter + file toolbar'
state: closed
labels:
- ui
assignees: []
milestone: null
created: 2026-10-27T15:27:35.641700257Z
updated: 2026-10-27T16:17:53.712101895Z
---
The file view has **zero token coloring** — `static/style.css` contains no highlight rules (`grep -c tok- static/style.css` = 0) and file pages emit plain `<span class="line">` text. A code mirror without highlighting is the single biggest "worse than GitHub/GitLab/Forgejo" gap.

### Current file view
- `files/src/build.rs.html`: flat grey monospace, 13px/19px, with a floating line-number gutter that has no separator rule and uses `--muted` (2.76:1 dark / 4.26:1 light).
- `h1` repeats the breadcrumb path (`root / src / build.rs` then `<h1>src/build.rs</h1>`).
- Meta bar: `src/build.rs · 94.3 KiB · 2333 lines · Raw` with "Raw" as plain text.
- No wrap toggle, no copy button, no syntax hints.

### Scope
- **Tokenize at build time** (no JS, no deps beyond what we have) for a small language set: Rust, JS/TS, JSON, YAML, TOML, Markdown, shell, HTML/CSS, Python, Go. A ~200-line lexer producing `tok-kw/tok-str/tok-num/tok-com/tok-fn/tok-type` spans is enough; unknown extensions stay plain.
- **Tokyo Night palette**: `--tok-kw` (purple/magenta), `--tok-str` (green), `--tok-num` (orange), `--tok-com` (muted italic), `--tok-fn` (blue), `--tok-type` (cyan). Must pass contrast in both themes.
- **Gutter**: sticky line-number column, `--fg-dim`, right-aligned, 1px `--border` rule between numbers and code, `user-select:none`, anchors preserved (`id="L42"`).
- **File toolbar**: breadcrumb (drop the duplicated `h1`, or keep a short `build.rs`), `Raw` as a proper secondary button, size + line count as dim chips, and a "wrap" `<details>`-free toggle is impossible without JS — so instead: `white-space:pre` + horizontal scroll, plus a `<a href="/raw/…">` for full text.
- Keep output byte-budget: tokens add ~15–30% to file page size; measure on `src/build.rs` (94 KiB → ~120 KiB) and confirm acceptable, or cap highlighting to files < N KiB.

### Acceptance
- [ ] Rust/JS/JSON/YAML/TOML/MD/shell files render colored tokens
- [ ] unknown extensions and huge files stay plain (no regression)
- [ ] line anchors still work and are selectable/shareable
- [ ] contrast of every token color ≥ 4.5:1 in both themes
- [ ] build-time cost stays negligible (no new deps)
