mathra

Math LaTeX to accessible SVG.
No TeX install. JavaScript, Python, Rust or the terminal.

mathra reads the equation (LaTeX, MathML or AsciiMath), builds a tree of meaning and draws it with numbered, tested rules. Every SVG says the equation out loud to screen readers and carries it in braille.

LaTeX
SVG
Loading WebAssembly…

Why mathra

One small library, the same output everywhere: JavaScript, Python, Rust and the terminal.

It speaks the equation

The SVG's <title> carries the phrase a screen reader says: “1 over 2”, not “image”.

pt-BR

It speaks 16 languages

From Português to 日本語. The language changes how numbers are read and written (in pt-BR, 3,14 is one number and \sin is sen) and the language of the speech.

It forgives broken input

Typos and editor leftovers are fixed and reported as numbered warnings. Strict refuses them, like TeX.

It reads LaTeX, MathML and AsciiMath

MathML pasted from Word or Google Docs, AsciiMath like sum_(i=1)^n i^2: the same tree of meaning, the same drawing and speech. See the reference.

CMU

It writes braille

Every equation also comes out in braille: the CMU for Portuguese and Spanish, Nemeth for English, following their official documents and compared with MathCAT. How far to trust it.

17.9 µs

It is fast and stable

Mean time per equation on the corpus. The same input always writes the same bytes.

Benchmark

mathra next to KaTeX and MathJax on the same equations, including where it loses. Lower is better for time and size.

Run it in your browser

Loads KaTeX 0.16.22 and MathJax 3.2.2 from jsDelivr and times the three libraries on the 18 gallery equations, on your machine.

Reading the numbers

  • KaTeX is faster and lighter to ship. It writes HTML that depends on its stylesheet and web fonts, so its output is not a standalone image: it cannot go into an email, a README, a slide or a PDF as is. That is why its output looks smallest.
  • MathJax's SVG output is the closest equivalent to mathra's: one standalone SVG per equation. Here mathra is about 5× faster, with output of similar size.
  • mathra's download is mostly its font: 628 of the 926 KB are STIX Two Math, embedded so the output never depends on what is installed; the 16 languages add 34 KB. Outside the browser (CLI, Rust, Python) nothing is downloaded at all, and a native conversion takes 17.9 µs on average.
  • The corpus favors mathra: its 116 constructions were written while building it, and include pt-BR and mathra-only commands. The 18 gallery equations are standard LaTeX except three that only mathra reads (\SI, \sen, \divchave).
  • “Converted cleanly” means no error and no command drawn in red. MathJax runs with all its TeX packages except noundefined; KaTeX with throwOnError and mhchem.
  • Snapshot: Node 24, Apple M5, 50 conversions per equation after a warm-up. The script is in bench/: cd bench && npm install && npm run compare.

Use it

Pick your platform. All four packages run the same core, so an equation gives the same SVG, byte for byte, wherever it is converted.

JavaScript and TypeScript

on npm

Node, bundlers (Vite, webpack, esbuild) and browsers. Types included.

npm install @mathlabs/mathra
import { init, texToSvg, render } from "@mathlabs/mathra";

await init();  // browsers and bundlers; Node needs nothing
const svg = texToSvg("3,14", { locale: "pt-BR" });
const { speech, braille, warnings } = render("x^2");
render("sqrt(x)/2", { input: "asciimath" });  // or "mathml"

Python

on PyPI

Python 3.9 and later, wheels for Linux, macOS and Windows. Types included.

pip install mathra
import mathra

svg = mathra.tex_to_svg(r"\sin x = 0.5")
r = mathra.render(r"\frac{3}{4}", locale="fr")
r["speech"]   # 'trois quarts'
mathra.render("x^2", locale="pt-BR")["braille"]  # '⠭⠡⠼⠃'

Terminal

on crates.io

One binary, SVG to stdout or files; --batch for many at once.

cargo install mathra-cli
mathra 'x \le 2.75' -o inequality.svg
mathra '3,14 + \sin x' --locale pt-BR
mathra 'x = -1' --speech
mathra '\vertA\vert' --explain
mathra 'sum_(i=1)^n i' --from asciimath
mathra '\frac{3}{4}' -l pt-BR --braille

The core itself, for servers and native apps. API docs on docs.rs.

cargo add mathra
let r = mathra::convert("3.14", &mathra::Options::default())?;
println!("{}", r.svg);
println!("{}", r.speech);

What the SVG carries

  • Speech in <title>, linked with aria-labelledby.
  • The source (LaTeX, MathML or AsciiMath), the tree of meaning and the braille in <metadata>.
  • Color from the page (currentColor), size in em, baseline aligned with the text around it.
  • A transparent text layer for selection, reused glyphs and ids unique to each equation.

Broken LaTeX

By default mathra draws what it can and reports what it fixed, as E-REC-1 to E-REC-10 (spec/tolerance.md). Every rule that shapes the output is numbered in spec/rules.md; the Rules tab shows which ones acted on your equation.

What it converts

Fractions, roots, scripts and limits, stretchy delimiters, matrices and array, cases and rcases, aligned, accents and braces, \text, alphabets, every amssymb symbol and negation, \cancel, \boxed, \colorbox, siunitx with ranges and lists, mhchem (\ce with labeled arrows, hydrates, isotopes, bonds), physics and braket, tensor indices, \newcommand and friends, amscd diagrams, and the computed \divchave and \contaarmada. Also MathML and AsciiMath as input. Every construction, with its drawing and its braille, is in the reference; the full list is in the README.