Repository navigation
v0.5.0
This release reshapes the configuration and reporting surface across Rust, Python, and JavaScript so the three APIs share one configuration tree and one set of override semantics. Transform reports become opt-in, TransformConfig is organized by phase, serialization options are flattened, and binding exception categories are corrected. It also hardens parser recovery and diagnostics, fixes serialization of bare delimiter arguments, and adds two corpus rules. Most changes are breaking; see Changed for migration notes.
Added
normalize_with_report/transform_with_reporton the Rust facade and the Python binding (normalizeWithReport/transformWithReportin JavaScript) for callers that need the diagnostic report. Report types now live intexform::diagnostics.- Effective defaults are exposed on every binding:
default_parse_config()/default_transform_config()in Python anddefaultParseConfig()/defaultTransformConfig()in JavaScript return the engine's profile defaults. Rust addsTransformEngine::default_normalize_config(). RewriteConfig, plus the serialization option enums (CommandSpacing,MathGroupInnerSpacing,AdjacentCharSpacing,ScriptSpacing,ScriptOrder,InfixGrouping,EnvironmentNameSpacing), are re-exported from the Rust facade.- Corpus rules
leftroot-dropanduproot-dropdrop the AMS\leftroot/\uprootindex-position hints.
Changed
- Breaking: transform reports are opt-in.
normalize/normalize_withnow return the canonical string andtransform/transform_withreturn nothing, in Rust, Python, and JavaScript, so plain calls no longer pay for report collection or host-object conversion.NormalizeResultand theFinalizeAstStep*types are removed. The report itself is restructured (rewrite.{iterations, rules}, flattened FinalizeAst counters,flatten_groups.guard_hitswith short guard names) and remains a diagnostic rather than a stability promise. - Breaking:
TransformConfigis organized by phase. The flatrewrite_enabled,lower_attributes_enabled, andmax_iterationsfields becomerewrite: RewriteConfig { enabled, max_iterations }andlower_attributes: LowerAttributesConfig, alongside the existingfinalize_astandflatten_groups. Profile defaults are unchanged. - Breaking:
FlattenGroupsConfigexposes onlyenabledandpreserve_rendered_spacing(preserveRenderedSpacingin JavaScript). The elevenpreserve_*guard fields are removed and old keys are rejected. - Breaking: serialization options are a flat set of seven fields; the nested
math/syntaxshape is removed. Python takes snake_case keyword arguments (doc.to_latex(script_order="sup_first"),serialize(node, **options)), and JavaScript takes a flat camelCase object. - Breaking: configuration inputs are unified across bindings. Python reserves
config=for a complete config object (TransformConfig,ParseConfig); partial settings are passed as keyword overrides that keep unspecified defaults, and a dict passed asconfigis rejected. JavaScript accepts the same nested override tree innormalizeandtransform, with omitted fields keeping the profile default. Unknown keys and wrongly typed values raiseConfigError/TexformConfigErrorwith the field path. The unused WASM config classes andparseWithare removed. - Breaking: binding exception categories are corrected. Python cross-document edits raise
EditErrorinstead ofParseError. Transforming a document that has parse errors raisesTransformErrorin Python andTexformTransformError(kind: "transform") in JavaScript instead of theinternalkind. The undocumentedComplete<T>type is no longer importable from the npm typings.
Fixed
- Parser recovery under
reject_unknownwithoutabort_on_errorconsumes only the unknown command, so\mycmd{x} + yyields a partial document instead of failing the whole parse. A stray}is no longer reported as an environment-name mismatch, and^/_with missing content reportMissing superscript content/Missing subscript content. - Diagnostics keep their structured kind and precise source span through nested content parsing instead of highlighting the outer command or closing brace, and internal kind labels no longer leak into messages.
- Literal carriage returns are treated as whitespace, so Windows (CRLF) and CR-only inputs parse instead of panicking.
- Mandatory delimiter arguments are serialized without braces (
\middle \vert,\big \langle,\genfrac . . {} {}), so the output renders in MathJax again. - JavaScript:
normalizewith aflattenGroupsoverride now layers it on the engine profile's defaults instead of the strict baseline. - JavaScript: internal DTO serialization failures are thrown as
TexformError(kindinternal) instead of being returned as successful values. - Python: invalid per-call config objects raise
ConfigErrorconsistently acrossparse,normalize, andtransform.