Repository navigation
VOMD v1.0.0
The first release, for Linux (x86-64; Windows and macOS compile but are unsupported).
Added
- CommonMark and GitHub Flavored Markdown: tables, task lists, strikethrough, footnotes, alerts, extended autolinks, hidden YAML front matter. Raw HTML is stripped, never run; a few tags are styled as on GitHub.
- Our own text layout and renderer on
swash,winitandsoftbuffer, with embedded Inter and JetBrains Mono subsets and a lazy system-font fallback for other scripts and emoji. - Light and dark themes following the system, zoom 50–300%, HiDPI.
- Links: anchors, relative Markdown files in the same window with Back, web links in the browser; a URL preview on hover.
- Reload on
R/F5and when the window regains focus, keeping the reading position. - A slim toolbar (hidden with
B) with an overflow menu on narrow windows. settings.iniwith live apply, written back without losing comments.- Local PNG and JPEG images, decoded lazily at their displayed size under a 32 MB cache.
- Remote images, off by default: loaded per document with
I, through the systemcurl. - A one-line notice for files over 10 MB, which still render.
- Packaging: Arch PKGBUILDs
vomd(from source) andvomd-bin, and a release tarball with a desktop entry, icon and the README's image. - The app icon (an eye over the Markdown mark). The window's Wayland app ID and X11
WM_CLASSarevomd, so the desktop shows it for the window. - The system theme comes from the desktop portal's
color-scheme(Plasma's and GNOME's dark mode, followed live, and back to winit andGTK_THEMEwhen the preference is withdrawn), which say nothing on Wayland. Only the portal's own broadcasts count (not a signal another client addresses to VOMD), none is missed while starting (the first read is reported at once; signals are followed in order, and one that races a read triggers a backed-off re-read, 50 ms doubling to 5 s, until a read completes undisturbed), and the bus going away also returns to winit andGTK_THEME. - Wide layout:
W, the toolbar's button (next to the theme's) orwide = trueinsettings.inilets the text span the window instead of stopping atline_width; it is saved. A change of the column's width (this, or resizing the window) rescales every height, until its block is measured again, by how its estimate changed, so the scrollbar is right while measuring goes on; the estimates read what the prepass stored (20 bytes per block), not the text, so this costs two to three times the plain remeasure (0.5 ms on a 42,000-block document). - The scrollbar also shows while the pointer is over its column.
- Budgets measured by
cargo xtask budgets: binary size, cold and warm start, idle RSS, idle CPU, 4K scroll frame time. CI gates size, memory and idle CPU and reports the times (--timings-advisory). Fuzz targets for the parser, layout and settings.
Budgets, measured on the release runner
A shared runner is two to three times slower than the machine the time budgets
are for, so start and scroll times are reported here, not gated.
| Metric | Build | Measured | Budget | |
|---|---|---|---|---|
| ✅ | stripped binary | default |
3.70 MB | ≤ 4.0 MB |
| ✅ | cold start, tiny.md | default |
46.3 ms | ≤ 100 ms (first of 20 runs) |
| ✅ | warm start, tiny.md | default |
37.6 ms | ≤ 50 ms (median of 19) |
| ✅ | cold start, readme.md | default |
47.3 ms | ≤ 100 ms (first of 20 runs) |
| ✅ | warm start, readme.md | default |
43.5 ms | ≤ 50 ms (median of 19) |
| ✅ | cold start, spec.md | default |
44.7 ms | ≤ 100 ms (first of 20 runs) |
| ✅ | warm start, spec.md | default |
42.5 ms | ≤ 50 ms (median of 19) |
| cold start, huge.md | default |
145.7 ms | ≤ 100 ms (first of 20 runs) | |
| warm start, huge.md | default |
136.3 ms | ≤ 50 ms (median of 19) | |
| ✅ | idle RSS, 50 KB doc, 1080p | default |
17704 KB | ≤ 30000 KB |
| ✅ | idle CPU, 50 KB doc (idle at 64 ms) | default |
0 ticks/3s | ≤ 1 tick |
| ✅ | idle RSS, 5 MB doc, 1080p | default |
32268 KB | ≤ 60000 KB |
| ✅ | idle CPU, 5 MB doc (idle at 2281 ms) | default |
0 ticks/3s | ≤ 1 tick |
| ✅ | stripped binary | --no-default-features |
2.95 MB | ≤ 3.0 MB |
| ✅ | cold start, tiny.md | --no-default-features |
28.5 ms | ≤ 100 ms (first of 20 runs) |
| ✅ | warm start, tiny.md | --no-default-features |
38.3 ms | ≤ 50 ms (median of 19) |
| ✅ | cold start, readme.md | --no-default-features |
46.3 ms | ≤ 100 ms (first of 20 runs) |
| ✅ | warm start, readme.md | --no-default-features |
43.5 ms | ≤ 50 ms (median of 19) |
| ✅ | cold start, spec.md | --no-default-features |
45.8 ms | ≤ 100 ms (first of 20 runs) |
| ✅ | warm start, spec.md | --no-default-features |
42.4 ms | ≤ 50 ms (median of 19) |
| cold start, huge.md | --no-default-features |
141.3 ms | ≤ 100 ms (first of 20 runs) | |
| warm start, huge.md | --no-default-features |
137.1 ms | ≤ 50 ms (median of 19) | |
| ✅ | idle RSS, 50 KB doc, 1080p | --no-default-features |
18112 KB | ≤ 25000 KB |
| ✅ | idle CPU, 50 KB doc (idle at 65 ms) | --no-default-features |
0 ticks/3s | ≤ 1 tick |
| ✅ | idle RSS, 5 MB doc, 1080p | --no-default-features |
34564 KB | ≤ 55000 KB |
| ✅ | idle CPU, 5 MB doc (idle at 2093 ms) | --no-default-features |
0 ticks/3s | ≤ 1 tick |
| ✅ | scroll frame, 4K, p95 | default |
7.50 ms | ≤ 8 ms |
| ✅ | scroll frame, 4K, p95 | --no-default-features |
4.92 ms | ≤ 8 ms |
| ✅ | image RSS, 50 local PNGs | default |
44632 KB | ≤ 62768 KB |
| ✅ | image RSS, 50 remote PNGs | default |
41744 KB | ≤ 62768 KB |
| ✅ | image RSS, 50 remote PNGs in view, polled every 16 ms | default |
41856 KB | ≤ 62768 KB |
| ✅ | image RSS, 50 remote PNGs in view, polled every 50 ms | default |
42024 KB | ≤ 62768 KB |
| ✅ | image RSS, 16,384 remote JPEGs of 325 KB cut to 178 bytes | default |
28896 KB | ≤ 62768 KB |