v0.3.0
This release adds a tokenized serialization channel, extends AST canonicalization with text-sequence normalization, and substantially expands the rewrite rule set — spacing, fraction and delimiter styling, negated-relation remaps, named-function operators, and more. It also renames the rule-level taxonomy on the public API and prunes several rules whose render fidelity did not hold up under corpus review.
Added
- Tokenized serialization.
Document::to_tokenized_latex()(andto_tokenized_latex_with) returns the canonical LaTeX string alongside ordered, typed output tokens — each classified asControlSequence,Character,Delimiter,Text,Raw, orError, and carrying its math/text mode and a non-overlapping UTF-8 byte span into that string. Tokens are recorded during the existing serializer traversal rather than by re-lexing the output, and the feature is exposed across the Rust, Python, and JavaScript APIs while leaving text-only serialization's allocation behavior unchanged. - Text-sequence normalization in
FinalizeAst. The profile-neutral canonicalization phase now merges adjacent text-mode siblings, collapses ordinary lexer whitespace runs to a single space without trimming edges, and cleans empty text. The pass re-runs afterFlattenGroupsso newly adjacent text and prime nodes are canonicalized, and its work is reported through thenormalize_text_sequencesstep counter on the transform report. - A large batch of rewrite rules across several normalization groups: spacing drops (
\enspace,\quad,\qquad) and merges (adjacent\enspacepairs, small-spacer runs); fraction styling (\dfrac/\tfrac/\cfrac→\frac,\dbinom/\tbinom→\binom); limit placement (\limits/\nolimitsdrops on audited operators); fixed delimiter sizing (\big–\Biggsize drops); negated-relation remaps (\not=→\neq,\not\exists→\nexists,\not\in→\notin,\not\rightarrow→\nrightarrow); accent sizing (\widehat→\hat,\widetilde→\tilde, the firstEquiv-level builtins); math-mode control-space to active space; duplicatemathrel-wrapper drops; and named-function rewrites for plain operator names, with extended\operatornamecanonicalization. Shared delimiter-rewrite helpers back the delimiter-oriented rules.
Changed
- Breaking: the rule-level taxonomy is renamed from normalization level to rule level across the public API, the transform engine, the generated registry, rule metadata, and documentation. The facade now re-exports
RuleLevelSetin place ofNormalizationLevelSet, and the internalNormalizationLevelenum becomesRuleLevel; downstream code referring to the old names must update. Active rules are reclassified underAuthoring,Faithful,Corpus, andEquivwhile preserving current profile behavior. \limits/\nolimitsdrops move fromEquivtoCorpus, so they now participate in corpus normalization.
Fixed
- Removed rewrite rules whose worst-case render fidelity did not hold across supported renderers: the
displaylines-to-gather-envrule (its numberedgatheroutput cannot preserve reading fidelity), therepeat-spacer-collapserule, and the physics quick-\quadexpansions (qcomma-expand,qqtext-expand). These forms are now preserved instead of rewritten.