zlatex-core is the typesetting engine behind zlatex. A .tex source goes in; laid-out pages come out — as a render tree a WebView paints, or as a multi-page PDF, per-page SVG or PNG. It sets documents: text mode with paragraphs hyphenated and broken by TeX's own algorithms, page breaking, sectioning and counters, lists, tables, floats that move whole to the next page, footnotes set under their rule at the foot of the page their marker landed on, cross-references and a table of contents — plus the math engine, reached for every $…$, \(…\) and display. \input and \include are spliced before parsing, so a book split across chapter files typesets as one book. There is no external TeX distribution, no subprocess and nothing to install, and the math layout parameters are read from the font's own OpenType MATH table rather than hardcoded.
TeX's algorithm
The Chapter 17 conversion with Appendix G placement: the 8×8 atom-class spacing table, the Bin→Ord reclassification, script shift-and-clearance rules, fraction and radical construction, delimiter growth.
Font-sourced parameters
Where TeX reads TFM fontdimens, this reads MathConstants. The engine's measurements and the renderer's painting come from one face, so they cannot drift apart.
Total by design
An unknown control sequence becomes a visible error box plus a diagnostic, never an abort — the editor calls this on every keystroke, and a half-typed formula still previews.
Embeddable
Builds rlib, staticlib and cdylib, with one JSON command bus and a headless CLI, so a GUI host, a C ABI host and a shell pipeline all reach the same surface.
A proved fixed point
Passes run until one reads exactly what it wrote, not a fixed count. Because the iteration is in memory, every intermediate state is kept: typeset.converge reports which entries moved and to what, and when there is no fixed point it names the cycle and its period rather than giving up at a rerun cap.
The page budget
Every page limit is met by guessing: compile, look at the last page, delete a sentence, compile again. The page builder placed a known amount of vertical material into pages of a known height, so typeset.fit subtracts and gets a FLOOR — no pagination into the target exists while it is positive — stated in points, body lines and words, with every construct priced against it and the sufficient ones re-laid-out to prove the page count.
Real TeX Live packages
The engine speaks the TeX Live database format directly — the local texlive.tlpdb joined against the mirror's — installs a package's .tar.xz into its own texmf store, and mines a .sty for the macros it defines. No tlmgr, no perl, no root; what could not be honoured is reported rather than pretended.
The pipeline
.tex ─▶ tokenize ─▶ expand ─▶ textmode ─▶ line-break ─▶ page-break ─▶ RenderDoc
(catcodes) (macros) (blocks) (Knuth-Plass) (vertical) (pages)
│ ▲ │
│ └── re-run ──┘
│ while a pass does not read what it wrote
│ (references, pages, contents)
└─▶ math mode ─▶ mlist_to_hlist
($…$, displays) ▲
OpenType MATH constants
+ glyph metrics
Modules
| Module | Role |
|---|---|
lex | TeX's mouth: category codes, control sequences, comments, \def / \newcommand / \let expansion with a recursion bound |
parse · symbols · atom | The math-mode grammar, the control-sequence table, and the math-list model (atoms, fields, fractions, radicals, matrices) |
textmode · doc | The text-mode grammar and the document model: preamble, paragraphs, sectioning, lists, tables, floats, bibliography |
linebreak · hyphen · typeset | Knuth–Plass total-fit line breaking, Liang's algorithm over TeX's own pattern file feeding it discretionaries, and the page builder with its floats, footnotes and its iteration to the reference fixed point |
converge | Whether the document is finished: the pass-by-pass trace read into a verdict — the fixed point and how many passes it took, or the cycle and its period, with every unstable entry tied to the \ref / \pageref sites that read it |
fit | The page budget: the material that must be removed to meet a page limit, proved rather than searched for, with every top-level construct priced from the page builder's own record |
include | \input / \include splicing: the \includeonly list, a page break around each \include, a nesting limit and a cycle guard |
style · font | The eight math styles and their transitions; glyph boxes, MATH constants, and Unicode math-alphabet mapping |
boxes · mlist | The box model (width / height / depth) and the layout itself |
render · export | The render tree the frontend paints, and the outline-based exporters |
packages · tlnet | The per-package support tier a \usepackage list is scanned against, .sty macro ingestion, and the TeX Live databases, mirror and installer behind them |
library · commands · cli | The equation history store, the JSON command bus, and its argv front end |
Use it
zlatex typeset source_file=paper.tex # a whole document → pages
zlatex typeset source='\frac{1}{2}' size_pt=14 # a formula → one equation box
zlatex export.pdf source_file=paper.tex # multi-page pdf
zlatex export.svg source='x^2 + y^2 = z^2' font=assets/latinmodern-math.otf
zlatex packages.scan source_file=paper.tex # what this document needs
zlatex typeset.converge source_file=paper.tex # finished, or chasing itself?
zlatex typeset.fit source_file=paper.tex target_pages=8 # how much has to go?
zlatex palette
Read on
The engineering report covers the layout rules, the coverage, and the limits. The zlatex app docs cover the desktop editor built on this engine.