TransformEngineclass#
A profile-based normalization engine: a parser paired with a transform pipeline.
TransformEngine normalizes a formula into the canonical form selected by a
Profile. It exposes a string-to-string TransformEngine.normalize
path and an in-place TransformEngine.transform path over a live
Document. It also exposes its own TransformEngine.parse and the
shared knowledge base through TransformEngine.knowledgeBase. For the conceptual model —
profiles, the multi-phase pipeline, and the eliminated-form contract — see the
Transforms guide.
Since 0.4.0 the bundled parser defaults to lenient ParseConfig, and
transform options are a nested camelCase overlay (TransformConfig /
NormalizeConfig), not flat rewriteEnabled / maxIterations keys.
null / undefined / omitted means not set. Unknown keys, snake_case keys,
arrays in object positions, and wrong scalar types throw
TexformConfigError with a camelCase path. There is no complete
config class on the JavaScript surface; read the effective defaults with
TransformEngine.defaultTransformConfig.
import { TransformEngine } from 'texform';
const engine = new TransformEngine({ profile: 'corpus' });
engine.normalize(String.raw`a \over b`); // '\\frac { a } { b }'
engine.normalize(String.raw`a \over b`, { rewrite: { enabled: false } });
engine.normalizeWithReport(String.raw`a \over b`).report.rewrite.iterations;TransformEngine#
TransformEngine(options: TransformEngineOptions)Construct an engine for a profile, optionally sharing a knowledge base, or disabling rules.
| Parameter | Type | Description |
|---|---|---|
options | Transform |
|
parse#
parse(src: string, config: ParseConfig | null | undefined): ParseResultParse a LaTeX string into a ParseResult, using this engine's parser.
Non-null documents from this result share the engine's KnowledgeBase, so
they can be edited and then passed to TransformEngine.transform. The
The engine parser defaults to lenient parsing; pass config to override it
per call.
| Parameter | Type | Description |
|---|---|---|
src | string |
|
config | Parse |
|
ParseResult — The parse result (document and diagnostics).
normalize#
normalize( src: string, config: NormalizeConfig | null | undefined,): stringParse, normalize, and serialize a formula in one call.
Normalization is gated on a complete tree: if the input cannot produce one,
this throws TexformParseError carrying its diagnostics and the
partial document. Empty input is complete and normalizes normally.
| Parameter | Type | Description |
|---|---|---|
src | string |
|
config | Normalize |
|
string — The serialized LaTeX string. This path does not build a report.
const engine = new TransformEngine({ profile: 'corpus' });
engine.normalize(String.raw`\dv{f}{x}`);
// '\\frac { \\mathrm { d } f } { \\mathrm { d } x }'normalizeWithReport#
normalizeWithReport( src: string, config: NormalizeConfig | null | undefined,): NormalizeReportResultParse, normalize, and serialize a formula, returning text and a diagnostic report.
Accepts the same source and NormalizeConfig overlay as TransformEngine.normalize. Output text and errors follow that contract. Report fields, phase divisions, and counters are diagnostic and are not part of the stable compatibility promise. A failure does not return a partial report.
| Parameter | Type | Description |
|---|---|---|
src | string |
|
config | Normalize |
|
NormalizeReportResult — The normalized string and its TransformReport.
transform#
transform( document: Document, config: TransformConfig | null | undefined,): voidTransform a live Document in place.
The document must share this engine's KnowledgeBase instance. A document that Document.hasErrors is read-only and cannot be transformed; this precondition error is surfaced as TexformTransformError. This path returns no value and does not build a report.
| Parameter | Type | Description |
|---|---|---|
document | Document |
|
config | Transform |
|
const engine = new TransformEngine({ profile: 'corpus' });
const result = engine.parse(String.raw`a \over b`);
if (result.document) {
engine.transform(result.document);
result.document.toLatex(); // '\\frac { a } { b }'
}transformWithReport#
transformWithReport( document: Document, config: TransformConfig | null | undefined,): TransformReportTransform a live Document in place and return its diagnostic report.
Accepts the same document and TransformConfig overlay as TransformEngine.transform. Ownership, completeness, and errors follow that contract. The report is diagnostic and is not part of the stable compatibility promise. A failure does not return a partial report.
| Parameter | Type | Description |
|---|---|---|
document | Document |
|
config | Transform |
|
TransformReport — The diagnostic transform report.
const engine = new TransformEngine({ profile: 'corpus' });
const result = engine.parse(String.raw`a \over b`);
if (result.document) {
const report = engine.transformWithReport(result.document);
report.rewrite.rules.some((rule) => rule.key === 'base/over-to-frac');
}defaultParseConfig#
defaultParseConfig(): Complete<ParseConfig>Return this engine's complete default ParseConfig.
Complete<ParseConfig>defaultTransformConfig#
defaultTransformConfig(): Complete<TransformConfig>Return this engine's complete default TransformConfig for its profile.
Complete<TransformConfig>Knowledge-base lookups#
Query the knowledge the parser loaded. Predicate methods take a single name; lookup methods take name and a mode of "math" or "text" and return a knowledge-entry object or null.
Lifecycle#
free#
free(): voidRelease the WASM handle for this engine immediately.
Prefer a using declaration so [Symbol.dispose]() runs at scope exit.
After free(), further use is invalid. Skipping free() is safe:
garbage collection still reclaims the handle, just not at a determined
time. Call free() (or use using) when many short-lived engines
would otherwise accumulate WASM memory.
[Symbol.dispose]#
[Symbol.dispose](): voidRelease the WASM handle. Same as TransformEngine.free; used by using.
TransformEngineOptionsinterface#
Construction options for TransformEngine: a shared knowledge base, the required normalization Profile, and optional rule disabling.
| Field | Type | Description |
|---|---|---|
profile | Profile | The normalization profile (required). Unknown values throw TexformConfigError. |
disableRules | string[ | Rewrite rule keys to disable, such as |
NormalizeConfiginterface#
Per-run overlay for TransformEngine.normalize: parse keys from
ParseConfig plus transform keys from TransformConfig,
flattened together. null / undefined / omitted means not set.
const engine = new TransformEngine({ profile: 'corpus' });
engine.normalize(String.raw`a \over b`, {
rewrite: { maxIterations: 50 },
flattenGroups: { enabled: false },
});TransformConfiginterface#
The nested, per-phase transform configuration, overriding a profile's transform defaults.
Each field controls one pipeline phase. This is the transform-only shape; it does not accept parser-strictness keys (those belong to NormalizeConfig).
Every field is an optional overlay key: null / undefined / omitted keeps
the profile's value. Unknown keys, snake_case keys, arrays in object
positions, and wrong scalar types throw TexformConfigError with a
camelCase field path. Read the effective defaults with
TransformEngine.defaultTransformConfig.
| Field | Type | Description |
|---|---|---|
lowerAttributes | Lower | LowerAttributes phase switches. |
rewrite | Rewrite | Rewrite phase switches. |
finalizeAst | Finalize | FinalizeAst phase switches. |
flattenGroups | Flatten | FlattenGroups phase switches. |
RewriteConfiginterface#
Per-run switches for the fixed-point Rewrite phase.
| Field | Type | Description |
|---|---|---|
enabled | boolean | | Whether the phase runs. When |
maxIterations | number | | Cap on Rewrite fixed-point passes. |
LowerAttributesConfiginterface#
Per-run switches for the LowerAttributes phase.
| Field | Type | Description |
|---|---|---|
enabled | boolean | | Whether the phase runs. Defaults to the profile's setting. |
FinalizeAstConfiginterface#
Per-run switches for the FinalizeAst phase.
| Field | Type | Description |
|---|---|---|
enabled | boolean | | Whether the phase runs. Defaults to enabled in every public profile. |
FlattenGroupsConfiginterface#
Per-run switches for the FlattenGroups phase (redundant-brace removal).
enabled governs whether the phase runs. preserveRenderedSpacing keeps
groups whose only public-facing effect is rendered math spacing; it does
not control serializer source whitespace (SerializeOptions
*Spacing fields). Structural guards stay on even when
preserveRenderedSpacing is false. Omitted keys fall back to the
profile's defaults — for example, corpus leaves
preserveRenderedSpacing off.
| Field | Type | Description |
|---|---|---|
enabled | boolean | | Whether the phase runs. |
preserveRenderedSpacing | boolean | | Keep groups whose only public-facing effect is rendered math spacing. This is not serializer source spacing. Structural guards stay on even
when this is |
NormalizeReportResultinterface#
Text plus the diagnostic report from TransformEngine.normalizeWithReport.
Plain TransformEngine.normalize returns the string directly and does not build this object.
| Field | Type | Description |
|---|---|---|
normalized | string | The serialized LaTeX after parsing and normalization. |
report | Transform | The diagnostic report for this call. |
TransformReportinterface#
Diagnostic report for one explicit report call.
Output text and errors follow the ordinary transform contract. Report fields, phase divisions, and these counters are diagnostic: they are not part of the stable compatibility promise. A disabled phase stays present as zeros or an empty array. Field names are camelCase, the JavaScript view of the snake_case data exposed by the Python binding.
| Field | Type | Description |
|---|---|---|
warnings | Transform | Unknown input names, deduplicated and sorted by kind and name. |
lowerAttributes | Lower | LowerAttributes activity, summed across its two passes. |
rewrite | Rewrite | Rewrite iterations and per-rule outcomes. |
finalizeAst | Finalize | Prime merges and text normalizations. |
flattenGroups | Flatten | Flatten actions and guard hits. |
TransformWarninginterface#
An unknown input name whose arguments or scope cannot be guaranteed.
| Field | Type | Description |
|---|---|---|
kind | "unknown-command" | | The unknown input name's category. |
name | string | Name without command or environment delimiters. |
message | string | Explanation of the semantic uncertainty. |
LowerAttributesReportinterface#
The LowerAttributes phase report.
| Field | Type | Description |
|---|---|---|
attributes | Attribute | Per-attribute activity, sorted by |
eliminatedEmptySegments | number | Empty attribute segments removed by the phase. |
AttributeStatinterface#
Activity for one (attr, value) pair in LowerAttributes.
| Field | Type | Description |
|---|---|---|
attr | string | Stable attribute name, such as |
value | string | Stable value token for that attribute. |
consumed | Attribute | Input forms consumed by LowerAttributes. |
redundant | Attribute | Consumed forms that did not change the emitted attribute state. |
emitted | Attribute | Canonical forms emitted by LowerAttributes. |
AttributeFormCountsinterface#
Counts of an attribute form split by carrier: declaratives (scope-affecting
declarations such as {\bf ...}) and prefixes (prefix commands such as
\mathbf{...}).
| Field | Type | Description |
|---|---|---|
declaratives | number | Count carried by declarative-form markup. |
prefixes | number | Count carried by prefix-command markup. |
RewriteRuleStatinterface#
One rewrite rule's outcome for a single call.
| Field | Type | Description |
|---|---|---|
key | string | Stable rule key. |
appliedCount | number | Times the rule applied. |
skippedCount | number | Times the scheduler matched the rule and apply returned skipped. |
RewriteReportinterface#
The Rewrite phase report.
| Field | Type | Description |
|---|---|---|
iterations | number | Fixed-point passes, including the final unchanged convergence check. Zero when the phase is disabled or no rules are scheduled. |
rules | Rewrite | Rules that recorded activity, sorted by |
FinalizeAstReportinterface#
The FinalizeAst phase report.
| Field | Type | Description |
|---|---|---|
primeRunMerges | number | Contiguous |
textNormalizations | number | Text segments or text argument slots whose content changed. |
FlattenGroupsActionCountsinterface#
Flatten actions that changed the tree.
| Field | Type | Description |
|---|---|---|
removedEmpty | number | Empty groups removed. |
replacedSingleChild | number | Groups replaced by their only child. |
inlinedMultiChild | number | Multi-child groups inlined into the parent. |
unwrappedSlot | number | Slot wrappers removed. |
FlattenGroupsGuardCountsinterface#
Preserve-guard hits for one FlattenGroups run.
A hit is the first guard branch reached for a group, plus the scripted-base
sub-count. commandContactViaScriptedBase is also included in
commandContact. These counters are not a partition of preserved groups.
| Field | Type | Description |
|---|---|---|
unknownCommandArguments | number | Possible arguments following an unknown command. |
argumentCapture | number | Groups whose removal would let a command before or inside them read the next token as an omitted optional or delimited argument. |
declarativeScope | number | Declarative-scope protection. |
scriptBase | number | Script-base protection. |
envBody | number | Environment-body protection. |
infixScope | number | Infix-scope protection. |
commandContact | number | Command-contact protection. |
commandContactViaScriptedBase | number | Command contact established through a scripted base. |
emptyGroup | number | Empty-group protection. |
loneAtomSpacingChar | number | Single spacing-character protection. |
leadingAtomSpacingChar | number | Leading spacing-character protection. |
delimitedPair | number | Delimited-pair protection. |
FlattenGroupsReportinterface#
The FlattenGroups phase report.
| Field | Type | Description |
|---|---|---|
actions | Flatten | Flatten actions that changed the tree. |
guardHits | Flatten | Preserve-guard hits for this call. |
TransformProfiletype#
"authoring" | "faithful" | "corpus" | "equiv"Normalization profile selecting the canonical form for one downstream
scenario: authoring (polished author-facing output), faithful (same
rendered formula, convenience macros expanded), corpus (training-data
normalization, layout hints dropped), or equiv (aggressive
canonicalization for equivalence comparison).
Profiletype#
"authoring" | "faithful" | "corpus" | "equiv"Normalization profile passed to TransformEngineOptions: "authoring",
"faithful", "corpus", or "equiv".
RuleLeveltype#
"authoring" | "faithful" | "corpus" | "equiv"How aggressively a transform rule may rewrite, layered from least to most destructive of stylistic detail.
A rule level is the first profile that accepts a rule's output as a suitable product; it is orthogonal to a rule's equivalence guarantee.