Add math in labels: zero-dep lookup tier + opt-in Typst tier#9
Conversation
|
@claude review this jawn plz |
|
Claude finished @gabo515's task in 3m 33s —— View job PR Review: Math in Labels (lookup + Typst tiers)Read the full diff against Strengths
Issues1. [Medium] Duplicate element IDs across embedded Typst SVG fragments. Because the symbol ids are content-hashed, identical glyphs collide to identical content, so browsers/usvg render correctly (first def wins, and it's the same path). But it's technically-invalid SVG (duplicate 2. [Medium] Two divergent Typst escapers; the markup backend's is incomplete.
So a label like 3. [Low / perf] No memoization of Typst compiles. 4. [Low] Non-rotated raster blit lacks the inward-nudge clamp. 5. [Low] Color injection drops named CSS colors. Nits
Tests / docsCoverage is strong: exhaustive lookup-tier exact-match units, structural Typst-tier tests (SVG embed, PNG composite incl. rotated y-labels, PDF via usvg, color injection), plus the Reference → Math doc page. Nothing missing for the scope. None of these are blockers. #1 and #2 are the two I'd address before merge (invalid-SVG output and the markup-backend escaping gap); the rest are polish. |
Any label may embed `$...$` math (LaTeX-ish syntax). Rendering has two tiers
that share `$`-detection and the command→symbol table (`src/render/math.rs`):
Lookup tier — always compiled, zero dependencies:
- `to_unicode` lowers math to inline Unicode: Greek, operators, super/sub
(all-or-nothing, falling back to a clean `^(2q)` when a glyph is missing),
`\frac{a}{b}`→`a/b`, `\sqrt{x}`→`√(…)`. Never emits a stray `\` or `$`.
- Baseline for every backend; the only tier the terminal can use. SVG, PNG,
PDF, and terminal all route plain `$...$` labels through it.
Typst tier — feature `math`, opt-in:
- Links the Typst compiler as a library (minimal `World`: bundled fonts, no
package/network access) and typesets the *whole label* (text + math) into
one SVG fragment (SVG/PDF) or pixmap (PNG), embedded into kuva output.
Real 2-D math: stacked fractions, radicals, large operators with limits.
- Whole-label rendering means no fontdue text measurement and no per-segment
layout — `svg_math` just places one fragment; raster blits/rotate-blits one
pixmap. Math color follows the label color (injected into the Typst source).
- On compile failure (e.g. Typst's `mc` ≠ `m c`) the label degrades to the
lookup tier with a one-time warning.
- Bundles only New Computer Modern Math (~1 MB, gzipped) + reuses the bundled
DejaVu Sans for text, instead of the ~15 MB `typst-assets`. Excluded from
`full` so `cargo ci-test` and example builds stay lean; enable explicitly,
e.g. `--features math,png`.
Also adds the `typst` markup backend (`TypstBackend`): emits a CETZ-based
`.typ` document for external `typst compile`, sharing the `$...$` → Typst-math
translation with the `math` tier.
Tests: exhaustive exact-match units on the lookup tier (`render::math`);
structural tests on the typst tier (SVG embed, PNG composite incl. rotated
y-labels, PDF via usvg, color injection). Docs: Reference → Math in Labels.
Any label may embed
$...$math (LaTeX-ish syntax). Rendering has two tiers that share$-detection and the command→symbol table (src/render/math.rs):Lookup tier — always compiled, zero dependencies:
to_unicodelowers math to inline Unicode: Greek, operators, super/sub (all-or-nothing, falling back to a clean^(2q)when a glyph is missing),\frac{a}{b}→a/b,\sqrt{x}→√(…). Never emits a stray\or$.$...$labels through it.Typst tier — feature
math, opt-in:World: bundled fonts, no package/network access) and typesets the whole label (text + math) into one SVG fragment (SVG/PDF) or pixmap (PNG), embedded into kuva output. Real 2-D math: stacked fractions, radicals, large operators with limits.svg_mathjust places one fragment; raster blits/rotate-blits one pixmap. Math color follows the label color (injected into the Typst source).mc≠m c) the label degrades to the lookup tier with a one-time warning.typst-assets. Excluded fromfullsocargo ci-testand example builds stay lean; enable explicitly, e.g.--features math,png.Also adds the
typstmarkup backend (TypstBackend): emits a CETZ-based.typdocument for externaltypst compile, sharing the$...$→ Typst-math translation with themathtier.Tests: exhaustive exact-match units on the lookup tier (
render::math); structural tests on the typst tier (SVG embed, PNG composite incl. rotated y-labels, PDF via usvg, color injection). Docs: Reference → Math in Labels.Description
Type of change
Checklist
Library (new plot type)
src/plot/<name>.rs— struct + builder methodssrc/plot/mod.rs—pub mod+ re-exportsrc/render/plots.rs—Plotenum variant +bounds()/colorbar_info()/set_color()src/render/render.rs—render_<name>(), added torender_multiple()match,skip_axesif pixel-spacesrc/render/layout.rs—auto_from_plots()extended if categories neededTests
tests/with ≥ basic render + SVG content + legend testscargo test --features cli,full— all existing tests still passCLI (if applicable)
src/bin/kuva/<name>.rs— Args struct (with/// doc comment) +run()src/bin/kuva/main.rs— module, Commands variant, match armscripts/smoke_tests.sh— at least one invocationtests/cli_basic.rs— SVG output test + content verification testdocs/src/cli/index.md— subcommand entryman/kuva.1— regenerated (./target/debug/kuva man > man/kuva.1)Documentation
examples/<name>.rs— Rust example for doc asset generationscripts/gen_docs.sh— invocations added;bash scripts/gen_docs.shruns cleandocs/src/plots/<name>.md— documentation page with embedded SVGsdocs/src/SUMMARY.md— link addeddocs/src/gallery.md— gallery card addedREADME.md— plot types table updatedVisual inspection
test_outputs/— new plot SVGs look correcttest_outputs/for layout regressionsbash scripts/smoke_tests.sh— all existing smoke test outputs still look correctHousekeeping
CHANGELOG.md— entry added under## [Unreleased]README.md— item marked done in TODO section if applicable