Repository navigation
feat: support high-fidelity LaTeX math rendering - #4
Merged
jpfulton-fultonengineeringservices merged 5 commits intoSep 14, 2026
Merged
Conversation
Add a math_mode option (legacy | latex) for equation rendering: - new diagrams.math_latex module: ziamath LaTeX -> SVG -> svglib vector Drawing for display equations (glyphs drawn as SVG paths, no font embedding), degrading to matplotlib mathtext PNG then clean_latex plain text so a bad formula never aborts a build - SingleMdConfig / MarkdownConfig gain math_mode plumbing through parse_section_lines and parse_md_file - text.fmt gains math_mode: latex mode recognises $...$ and $$...$$ inline spans (rendered as base64 data-URI <img> tags), protects backtick code spans before math extraction, and applies Pandoc-style delimiter heuristics so currency prose stays prose - markdown parser: $$ display blocks, single-line \[..\] / $$..$$ equations, fence-state tracking in latex mode - [math] and [all] extras gain ziamath + svglib (pure Python, MIT) - unit + integration tests for renderers, fallback chain, delimiter heuristics, and legacy-mode regression Signed-off-by: J. Patrick Fulton <patrick@fultonengineeringservices.com>
svglib <2.0 declares rlpycairo (and therefore pycairo) as a hard dependency; pycairo has no Linux/CI wheels and its meson build needs libcairo2-dev. svglib 2.2.0 moved the raster backend behind the optional "bitmaps" extra, so svg2rlg alone is pure-Python. Pin svglib>=2.2,<3.0 in the [math]/[all] extras and dev group. Signed-off-by: J. Patrick Fulton <patrick@fultonengineeringservices.com>
The inline renderer drew the formula into a fixed 6x1.2in axes and used bbox_inches="tight", which cropped to the full axes rectangle: every inline span became the same ~336pt-wide image with centred content. Render via a figure-level text artist instead so tight-cropping follows the glyphs, and return the expression's ink descent (from the mathtext layout, in points) so make_inline_math_img can emit a negative numeric valign. ReportLab interprets that as the image-bottom offset relative to the baseline, so each formula now sits on the text baseline with a width that tracks its content. Signed-off-by: J. Patrick Fulton <patrick@fultonengineeringservices.com>
Signed-off-by: J. Patrick Fulton <patrick@fultonengineeringservices.com>
The previous fix cropped with bbox_inches="tight", which follows the text *layout* box: it keeps the font's descent metric below the ink, so every image carried phantom whitespace under the glyphs and formulas floated above the surrounding text baseline. Render the expression onto a figure sized exactly to the mathtext layout box with the baseline at `depth` from the bottom (the approach math_to_image uses, but transparent). The reported descent is then the exact image-bottom-to-baseline distance, so ReportLab's numeric valign puts the math baseline on the text baseline. Parse at 4x72 dpi and scale to points to avoid whole-point depth quantisation. Adds a regression test asserting a descender-free glyph's ink touches the image bottom. Signed-off-by: J. Patrick Fulton <patrick@fultonengineeringservices.com>
jpfulton-fultonengineeringservices
deleted the
feat/latex-math-rendering
branch
September 14, 2026 15:56
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a
math_modeoption (legacy|latex) for equation rendering.Vector display equations (new
[math]extra)diagrams.math_latexmodule: ziamath LaTeX → SVG → svglib vectorDrawing. Glyphs are drawn as SVG paths (svg2=False for renderer compat), so no font embedding is needed and equations stay crisp at any zoom.clean_latexplain text. A bad formula never aborts a build.Inline math images
text.fmtgainsmath_mode: latex mode recognises$...$,<img valign="middle">tags.v$W^coefstays code), and Pandoc-style delimiter heuristics keep currency prose ("costs $5 and $10") as prose.Parser
markdown.py: $$ display blocks, single-line \[..\] /Dependencies
[math]and[all]extras gainziamath>=0.13+svglib>=1.5(pure Python, MIT, py3.10+).Test plan
uv run ruff check+ruff format --checkpassuv run mypy src tests(strict) passesuv run pytest: 173 passed, coverage 87.87% (gate 85%)uv buildsucceeds