TeXForm's vocabulary is small but precise, and several terms look interchangeable until you need the difference — profile versus rule level, SyntaxNode versus Document, config versus overlay. Each entry below says what the term means and links to the page that defines it in context.
Trees and documents#
SyntaxNode#
The lossless, immutable snapshot of a parse, and the single structured-data format in TeXForm. It is what you serialize to JSON, store, transport, or use as a test fixture; it carries no editing behavior. Python sees it as a plain dict, JavaScript as a plain object, Rust as a serde type. It may contain Error nodes, because a partial parse is still a legitimate snapshot. See Pipeline.
Document#
The editable working tree, and the type nearly every API takes or returns. You query it with node handles, mutate it with validated edits, serialize it with to_latex(), and normalize it with the transform engine. A Document whose has_errors() is true is read-only, fixed that way at construction. See Parsing and Edit a document.
Ast#
The internal arena tree the serializer and the transform engine operate on. Document wraps it and exposes a fallible surface over it, which is why no internal panic reaches a caller. Ast is not part of the public API and is not reachable from Python or JavaScript at all; the name appears in phase names like FinalizeAst and in Architecture, nowhere else. You never construct or hold one.
Text idempotency#
The serializer's formal guarantee that parsing its output and serializing it again in the same style produces the same string: serialize(parse(serialize(parse(src)))) == serialize(parse(src)). It is a text-level guarantee — the recovered tree need not be the identical tree kind — and it is what makes serialized output safe to use as a cache key, a deduplication key, or a diff input. It is not normalization: serialization never rewrites a \over b into \frac{a}{b}. See Serialization.
Parsing#
ParseConfig, lenient and strict#
The two knobs that decide how the parser reacts to trouble: reject_unknown for names the knowledge base does not recognize, and abort_on_error for syntax errors it cannot continue past. For both, True means stricter. Lenient is the corner where both are False — the default in every binding — and strict is the corner where both are True. Rust exposes those corners as the constants ParseConfig::LENIENT and ParseConfig::STRICT; Python and JavaScript express them through constructor defaults and per-call overlays instead, so there is no ParseConfig.LENIENT constant to import. See Parsing.
Context item#
A record you hand the parser to inject knowledge it does not have: a command, an environment, or a delimiter control, each with a name and an argspec. The parser then reads the item's arguments exactly as if it were built in. Context items add parsing knowledge only — they cannot add rewrite rules. See Inject custom commands.
The transform engine#
Profile#
Your choice of downstream use, and the only decision the engine requires: Authoring, Faithful, Corpus, or Equiv. A profile is fixed when you construct a TransformEngine, and it determines both which rules are active and the default per-phase switches. Profiles form a ladder rather than a quality dial — a stronger profile is not a better one, just a different target. See Transforms.
RuleLevel#
The level every rewrite rule belongs to, ordered Authoring < Faithful < Corpus < Equiv. A rule's level is the first profile that accepts the rule's output as a suitable product, and each profile runs its own level plus every level below it. This is what "a profile selects rules" means mechanically. See What the engine guarantees.
RuleFidelity#
A rule's worst-case equivalence guarantee over its declared input domain, ordered Math < Reading < Render: Render means the rendering is equivalent, Reading means notation content, reading order, and structural roles survive, and Math means only mathematical meaning does. Fidelity is independent of level — a high-fidelity rule is not automatically an earlier-level rule — and it is a metadata contract, not a comparison the engine runs. See Rules and the transform contract.
RuleLevelSet#
The set of rule levels a compiled engine has turned on, derived from the profile. It is the Rust-side representation of "which rules this engine will attempt". You do not set it directly; choosing a profile chooses it.
Phase#
One stage of the transform pipeline: LowerAttributes, Rewrite, FinalizeAst, or FlattenGroups. The engine repeats LowerAttributes → Rewrite → LowerAttributes → FinalizeAst → FlattenGroups until all enabled phases reach a common fixed point. You can switch a phase off for a single run. Switching a phase off is not the same as changing rule levels: the profile's rule selection is compiled into the engine and a per-run switch cannot change it. See Transforms.
Overlay#
A partial configuration merged onto a complete one. Every per-run config in the Python and JavaScript bindings is an overlay: you name only what you want to change, nested one level per phase — rewrite={"enabled": False} in Python, { rewrite: { enabled: false } } in JavaScript — and everything you omit keeps the profile's value. An unknown key, or a Python-style key handed to the JavaScript binding, raises a configuration error rather than being ignored. See Transforms.
Eliminated-form contract#
Each rewrite rule declares the forms it eliminates — forms that must not appear anywhere in the engine's output. After every mutating phase has run, the engine checks the final tree and reports a surviving eliminated form as a hard transform error rather than a warning. The same contract is re-checked against real-world datasets through corpus regression, so a rule that fails to eliminate what it promised is caught on actual formulas. See Rules and the transform contract.