val_latex 0.1.1 copy "val_latex: ^0.1.1" to clipboard
val_latex: ^0.1.1 copied to clipboard

LaTeX math typesetting in pure Dart: a TeX parser, macros, TeX layout with line breaking and right-to-left math, OpenType math fonts, and speech output.

val_latex

LaTeX math typesetting in pure Dart.

A TeX parser and layout engine with OpenType math fonts.
Runs anywhere Dart runs: the VM, Flutter on every platform, servers and the web.

Pub Version Pub Points BSD-3-Clause license

🦋 Flutter widgets · 📦 pub.dev


✨ Why val_latex? #

  • Pure Dart — no WebView, no JavaScript, no native code. The same engine runs in Flutter apps, on servers, in command-line tools and on the web.
  • TeX's own rules — layout follows the TeXbook's Appendix G and the OpenType MATH table of the font, so formulas are spaced the way LaTeX spaces them.
  • Broad coverage — 3,882 commands and 68 environments: amsmath, mathtools, the physics package, mhchem chemistry, siunitx units, diffcoeff, unicode-math names, text tables and lists.
  • Never throws on bad input — errors become nodes and diagnostics, and input that is still arriving (an LLM streaming a reply) renders as far as it goes.
  • Wraps to a width — breaks at relations and operators the way a person would, and re-breaks for a new width without laying out again.
  • Right-to-left math — Arabic notation, Arabic-Indic and Persian digits, mirrored operators and brackets.
  • Fast — about 4 µs to parse and 5 µs to lay out a typical formula on native code.

For Flutter, use val_latex_flutter. It adds the Math and MathText widgets on top of this package.

🛠️ Quick start #

dart pub add val_latex
import 'package:val_latex/val_latex.dart';

final result = parseLatex(r'x = \frac{-b \pm \sqrt{b^2-4ac}}{2a}');
final layout = layoutFormula(result);

print(layout.width);          // in em
print(result.diagnostics);    // problems, never an exception

layout.items is a render-agnostic display list — glyphs, rules, lines, paths and text runs, positioned in em. Draw it on any canvas, or use val_latex_flutter to draw it in Flutter.

📚 What it understands #

Area Highlights
Core LaTeX and AMS fractions, roots, scripts and limits, accents, delimiters at every size, every math alphabet, colours (148 named)
Environments align, gather, multline, split, cases, every matrix, array with rules and \multicolumn, CD and tikzcd diagrams, bussproofs proof trees, equation numbers and tags
Packages amsmath, mathtools, physics, mhchem (\ce, \pu), siunitx, diffcoeff, commath, nccmath, empheq, esint, tensor, stmaryrd, wasysym, unicode-math names
Text \text with math inside, tabular and booktabs tables, itemize / enumerate lists, justified paragraphs with hyphenation
Macros \def, \newcommand, \newenvironment, \NewDocumentCommand, \DeclareMathOperator, \DeclarePairedDelimiter, TeX conditionals and registers, shared across formulas with one newMacroTable()
Unicode input α, ∑, x², a₁, combining accents, Arabic letters and digits

Common package commands such as \abs, \dv, \sfrac and \celsius work without loading anything. LatexCatalog.instance lists everything val_latex understands.

📐 Layout and fonts #

final layout = renderLatex(
  r'\sum_{k=1}^{n} k = \frac{n(n+1)}{2}',
  layoutOptions: const LayoutOptions(displayMode: true, maxWidth: 12),
);
  • Latin Modern Math is bundled, with STIX Two Math as the fallback for symbols it lacks. Any OpenType math font works: MathFont.fromBytes(bytes).
  • Variable fonts at any axis values: MathFont.fromBytes(bytes, variations: {'wght': 700}).
  • Line breaking — LayoutOptions.maxWidth; prepareFormula lays a formula out once and layoutAt(width) re-runs only the line breaker.
  • Right-to-left — LayoutOptions(mathDirection: MathDirection.rtl).
  • In the background — layoutInBackground lays a formula out in a worker isolate.

🔌 Streaming and text with formulas #

parseLatex treats unfinished input (an open group, a half-typed command) as incomplete rather than wrong, and keeps node ids stable as more input arrives. MathScanner finds $…$, $$…$$, \(…\) and \[…\] formulas (and bare \begin{align}, cases, pmatrix…) in Markdown or chat text: prices stay text, code spans and blocks are skipped, and LLM output with doubled backslashes (\\[…\\]) still works.

🗣️ Speech, selection and source #

  • toSpeech reads a formula aloud for screen readers, in English and Arabic (Spanish, French, German, Portuguese, Bengali and Hindi as drafts), at three levels of detail.
  • Every node carries its source span; hitTestLayout and selectionUnits map taps and selections back to the source.
  • toLatex writes a formula back as normalised LaTeX.

⚡ Performance #

Measured on a MacBook (just bench), per formula of the coverage corpus:

Native JavaScript
Parse 4.5 µs 13 µs
Layout 5.4 µs 18 µs

Re-parsing and laying out a 160-character formula on every streamed character takes about 19 µs per update.

Built by Val #

val_latex is part of Val, the live visual layer for AI agents.

💬 Community #

Found a bug, or have an idea or feedback? Open an issue at github.com/useval/val_latex. If the package helps your project, consider giving it a like on pub.dev.

📄 License #

BSD 3-Clause — see LICENSE. The bundled fonts keep their own licences: Latin Modern Math (GUST Font License) and STIX Two Math (SIL Open Font License), in fonts/. Work by others that val_latex contains is credited in THIRD_PARTY_NOTICES.md.

2
likes
160
points
--
downloads

Documentation

API reference

Publisher

verified publisheruseval.io

Weekly Downloads

LaTeX math typesetting in pure Dart: a TeX parser, macros, TeX layout with line breaking and right-to-left math, OpenType math fonts, and speech output.

Homepage
View/report issues

Topics

#katex #latex #math #tex #llm

License

BSD-3-Clause (license)

Dependencies

characters

More

Packages that depend on val_latex