4.8 KiB
4.8 KiB
type, status, confidence, created, question, tags
| type | status | confidence | created | question | tags | |||||
|---|---|---|---|---|---|---|---|---|---|---|
| research | analyzed | high | 2026-10-17 | Which Rust crates should render previews (images, PDF, DJVU, EPUB, markdown, media) in a terminal, with what licenses and fallbacks? |
|
Rust preview stack (October 2026)
Versions verified against crates.io metadata on 2026-10-17.
Recommended stack
| Concern | Crate | Why | Notes / license |
|---|---|---|---|
| TUI | ratatui 0.30 + crossterm 0.29 | De-facto standard; 0.30 split into ratatui-core/-widgets facade; yazi & felix use it |
MIT; MSRV 1.88 |
| Images in TUI | ratatui-image 11.1 | kitty, sixel, iTerm2, halfblocks + Picker protocol/font detection; lives in the ratatui org |
MIT |
| Image decode | image 0.25 | yazi's choice; jpeg/png/gif/webp/bmp/tiff (+avif feature) | MIT/Apache |
| Resize | fast_image_resize 6.1 (SIMD) or image::thumbnail (triangle filter, yazi-style) |
hot loop | MIT/Apache |
| Sixel encode | quantette 0.6 (+ moxcms, palette) | yazi's actual sixel pipeline | MIT |
| pdfium-render 0.9 + pdfium binary | only mature page→image in-process option | pdfium is Apache-2.0 (b redistribute, ~5 MB); spawn pdftoppm as fallback |
|
| DJVU | djvu-rs 0.43 (pure Rust, render→image) | first usable pure-Rust DjVu decoder | 6 months old — keep ddjvu fallback |
| EPUB | hand-rolled: zip + quick-xml/html-to-text | the epub crate is GPL-3.0 — viral if statically linked |
avoid the trap |
| Markdown | comrak 0.56 → styled ratatui lines, or termimad (ready-made renderer) | termimad = fastest integration (broot uses it) | MIT |
| Syntax highlight | syntect 5.3 | yazi's choice; regex Sublime syntaxes, no C deps | tree-sitter = heavier, per-language grammars |
| Media metadata | spawn ffprobe -print_format json |
no linking pain; what yazi does | ffmpeg-next ties you to system FFmpeg — avoid |
| Video thumbnail | spawn ffmpeg -ss … -vframes 1 -vf scale… (+ attached_pic cover-art fallback) |
yazi's proven recipe | — |
| Audio (optional in-process) | symphonia 0.6 | pure-Rust metadata/album art | MPL-2.0 |
| MIME | infer 0.22 (magic bytes) + xdg-mime 0.4 (extension DB) | fast sniffing + correct text/* |
new_mime_guess unmaintained — avoid |
| FS events | notify 8.2 | yazi's watcher | CC0 |
| Fuzzy | nucleo 0.5 | Helix's matcher, library-first | MPL-2.0 |
| Config | serde + toml 1.1 | yazi's set | solid |
| Errors/logs | anyhow + thiserror 2.x + tracing | boring and correct | — |
| Async | tokio 1.x with results marshalled to a single-threaded UI actor | yazi's exact architecture; ecosystem is tokio-first | start threads-only, adopt tokio in Sprint 8 |
Image protocol fallback chain (first match wins)
- kitty graphics (unicode-placeholder mode) — kitty ≥0.28, Ghostty ← our primary target
- iTerm2 inline — WezTerm, iTerm2, Warp, VSCode terminal
- sixel — foot, Konsole 22.04+, Windows Terminal ≥1.22, WezTerm, rio
- ueberzug++ subprocess — X11 + Wayland (wlroots compositors: sway/hyprland/niri/wayfire); the only option for alacritty; not GNOME/KDE compositors
- chafa / halfblocks — works everywhere incl. SSH and tmux
- text: filename + size + mime
Terminal facts (Oct 2026): kitty has no sixel by design; alacritty rejected both protocols;
tmux needs allow-passthrough on and never passes kitty-old. The daily terminal here is
kitty without a multiplexer → tier 1 covers the primary user; tiers 3–5 cover everyone else.
Thumbnail caching (yazi-proven)
Decode once at preview size (max ~600×900, triangle filter) → persist rendered pages/frames to a disk cache dir → keep decoded previews in an in-process LRU → preload neighbors in background. Re-encoding for a protocol is cheap; re-decoding is not.
Risk notes
- GPL traps:
epubcrate (static link), ueberzug++ (fine — spawned), pdftoppm (fine — spawned). - pdfium must be shipped as a binary (~5 MB/platform) or static-linked via pdfium-render
static. - djvu-rs is young; config-selectable
ddjvufallback required. - ratatui 0.30 subcrate split may cause ecosystem churn in 2026 — pin carefully.
Outcome
Feeds ADR-001, ADR-004 and Sprints 5–8 crate choices.
Sources
- https://github.com/sxyazi/yazi (adapter/Cargo.tomls, preset plugins pdf.lua/video.lua)
- https://yazi-rs.github.io/docs/image-preview, /blog/why-is-yazi-fast/
- crates.io version metadata (ratatui, ratatui-image, image, fast_image_resize, quantette, pdfium-render, djvu-rs, epub, comrak, termimad, syntect, symphonia, notify, nucleo, infer, xdg-mime)
- https://github.com/ajrcarey/pdfium-render; pdfium LICENSE (Apache-2.0)
- https://www.arewesixelyet.com; https://sw.kovidgoyal.net/kitty/graphics-protocol
- https://github.com/jstkdng/ueberzugpp; https://github.com/matyushkin/djvu-rs