# TeXForm

LaTeX math, resolved.

TeXForm parses, edits and normalizes LaTeX formulas as syntax trees.

Open source, with packages for Python, JavaScript and Rust.

[Get started](https://texform.dev/docs/quick-start)

```sh
pip install texform
```

## Fig. 0 — A formula, as a syntax tree

The specimen panel shows the LaTeX input, its parsed tree, and the output under each normalization profile. The source and output are available before the interactive runtime loads.

```latex
{a \over b}+\sqrt {x^2}
```

Corpus output:

```latex
\frac { a } { b } + \sqrt { x ^ { 2 } }
```

[Open in Playground](https://play.texform.dev/?input=%7Ba+%5Cover+b%7D%2B%5Csqrt+%7Bx%5E2%7D&profile=corpus)

## 1. Parse. Edit. Transform.

Parse a formula once, then edit and transform the same tree.

### 1.1 Parse

The parser turns LaTeX source into a syntax tree. It looks up each command in the knowledge base to find its arguments.

### 1.2 Edit

The Document API finds, builds and replaces nodes, then writes the tree back to LaTeX.

### 1.3 Transform

The transform engine rewrites the tree into a canonical form. A profile sets how much it changes.

```python
import texform

src = r"{a \over b}+\sqrt {x^2}"
engine = texform.TransformEngine(profile="corpus")
doc = engine.parse(src)["document"]
[sqrt] = doc.find_commands("sqrt")
doc.set_arg(sqrt, 1, "x^2+y^2")
engine.transform(doc)
doc.to_latex()
```

Fig. 1. The formula from Fig. 0 through all three steps: parsed, one argument replaced through the Document API, then normalized under corpus.

Parsed:

```latex
{ a \over b } + \sqrt { x ^ { 2 } }
```

Edited:

```latex
{ a \over b } + \sqrt { x ^ { 2 } + y ^ { 2 } }
```

Transformed:

```latex
\frac { a } { b } + \sqrt { x ^ { 2 } + y ^ { 2 } }
```

## 2. Normalization

LaTeX lets the same formula be written in many ways. Normalization rewrites these variants into one form: aliases unified, convenience macros expanded, redundant braces removed. Most rewrites are named rules, and each profile enables the rules suited to one use.

| Profile | Intended output | Rules first enabled at this level |
| --- | --- | --- |
| Authoring | Keeps the author’s style | 71 |
| Faithful | Same rendering, standard commands | 51 |
| Corpus | Consistent training labels | 17 |
| Equiv | For comparison only | 15 |

Fig. 2. A syntax tree is replayed through LowerAttributes → Rewrite → LowerAttributes → FinalizeAst → FlattenGroups, repeating until the enabled phases reach a common fixed point. Tinted nodes are about to be replaced or were just added. Phase states are replayed from TeXForm; rule order within a Rewrite pass is reconstructed.

Fig. 3. The 154 rewrite rules are grouped by what they change. Each tile shows a form and what it becomes. Profiles are cumulative: each adds one level of rules. [Browse the rewrite rules](https://texform.dev/rules).

## 3. Knowledge base

The knowledge base records the syntax of LaTeX commands and environments: their arguments, modes and packages. The parser and the Document API both rely on it. Every entry is tested in three renderers and has its own reference page.

The current reference contains 507 commands, 35 environments, 666 symbols, and 8 packages.

Fig. 4. Commands and environments in the knowledge base, one cell per entry and package. Shade shows how many of the three renderers support it fully.

Fig. 5. Share of entries each renderer supports fully, from compiling generated test cases.

| Renderer | Version | Fully supported | Share |
| --- | --- | --- | --- |
| MathJax | 4.1.1 | 622 / 630 | 98.7% |
| KaTeX | 0.16.45 | 317 / 630 | 50.3% |
| XeTeX | XeTeX 3.141592653-2.6-0.999998 (TeX Live 2026) | 485 / 630 | 77.0% |

[Renderer support](https://texform.dev/latex/renderers)

Table 1. Parsing and normalization over real-world formulas. The contract check flags any form that an enabled rule should have removed.

| Measure | Value |
| --- | --- |
| Formulas checked | 1,226,617 |
| Formulas TeXForm cannot represent | 1,584 |
| lenient parse failure rate | 0.13% |
| Eliminated-form contract violations | 0 |
| Configured exceptions | 0 |

[Method and full tables](https://texform.dev/docs/performance-and-correctness)

## 4. Get started in Python, JavaScript, Rust or the CLI

The same API in Python, JavaScript and Rust, built on a shared Rust core. The JavaScript package runs as WebAssembly, in the browser or in Node.js. The CLI brings the same normalization to the command line.

### Python

```sh
pip install texform
```

```python
import texform

src = r"{a \over b}+\sqrt {x^2}"
engine = texform.TransformEngine(
    profile="corpus")
engine.normalize(src)
```

### JavaScript

```sh
npm install texform
```

```javascript
import { TransformEngine } from "texform";

const src = String.raw`{a \over b}+\sqrt {x^2}`;
const engine = new TransformEngine({
  profile: "corpus" });
engine.normalize(src);
```

### Rust

```sh
cargo add texform
```

```rust
use texform::{Profile, TransformEngine};

let src = r"{a \over b}+\sqrt {x^2}";
let engine = TransformEngine::builder()
    .profile(Profile::Corpus).build()?;
let out = engine.normalize(src)?;
```

### CLI

```sh
uv tool install texform
```

```console
$ texform normalize --profile corpus '{a \over b}+\sqrt {x^2}'
\frac { a } { b } + \sqrt { x ^ { 2 } }
```

Listing 1. The same normalization in Python, JavaScript, Rust and the CLI. The JavaScript package also runs Fig. 0. With `--lines`, the CLI reads one formula per line. [Command-line reference](https://texform.dev/docs/command-line)

Shared output:

```latex
\frac { a } { b } + \sqrt { x ^ { 2 } }
```

## 5. Applications

Pipelines that store, compare or render LaTeX math need it in a predictable form. Tools that edit it need its structure. TeXForm provides both.

### Fig. 6(a). Training data

Labels are normalized, so each formula is written one way across the dataset.

```latex
{a \over b}
```

```latex
\frac{a}{b}
```

```latex
\frac ab
```

All normalize under corpus to:

```latex
\frac { a } { b }
```

Distinct labels: 3 → 1.

### Fig. 6(b). Evaluation

Predictions and references are normalized before comparison, removing many spelling-only mismatches.

Prediction:

```latex
{\bf v}^2_i
```

Reference:

```latex
\mathbf{v}_{i}^{2}
```

Both normalize under corpus to:

```latex
\mathbf { v } _ { i } ^ { 2 }
```

Exact match: 0 → 1.

### Fig. 6(c). Web rendering

Package-specific commands are expanded into forms that common web renderers support.

With the physics package enabled, faithful normalization expands:

```latex
\dv{f}{x}
```

Into:

```latex
\frac { \mathrm { d } f } { \mathrm { d } x }
```

Render errors: 1 → 0.

### Fig. 6(d). Editing tools

Editors and authoring tools read and change formulas through the syntax tree.

Replace the optional argument of the square-root node:

```latex
\sqrt [ 3 ] { x }
```

With:

```latex
\sqrt [ n ] { x }
```

Fig. 6. Every LaTeX string in (a)–(d) is an input or output of texform 0.10.1; the tags under (a)–(c) name the profile used.

## References

Build on a foundation you can cite.

Open source under Apache-2.0, including its knowledge base and rewrite rules.

A paper describing TeXForm is coming soon. Until then, please cite the software.

[Quick start](https://texform.dev/docs/quick-start) · [View on GitHub](https://github.com/texform-dev/texform)

```bibtex
@software{texform,
  author  = {TeXForm contributors},
  title   = {TeXForm: Parsing, Editing,
             and Normalizing LaTeX Math},
  url     = {https://texform.dev},
  version = {0.10.1},
  year    = {2026},
}
```

[1] TeXForm contributors. TeXForm: Parsing, Editing, and Normalizing LaTeX Math. Version 0.10.1, 2026. https://texform.dev
