Repository navigation
v0.8.0
This release makes Document a complete API for building and editing formulas. Every node kind now has a constructor, so a formula can be built from scratch as a tree and serialized, and every construction and edit is checked against the document's knowledge base, so the result always conforms to it, as parser output does, and transforms accept it. Deterministic edits, rooted node paths, cross-document imports, and a columnar export cover targeted edits and bulk analysis. To support this, KnowledgeBase becomes an immutable object shared by parsers, engines, and documents. The release also fixes script, text-argument, and declaration-scope handling in alignments and text mode. The knowledge base and construction changes are breaking; see Changed for migration notes.
Changed
- Breaking: Package selection, custom items, and removals move from parser and engine builders to
KnowledgeBaseBuilder, and knowledge queries move fromParserandTransformEnginetoKnowledgeBase. Build oneKnowledgeBaseand pass it to every parser, engine, and document that should interoperate, for exampleParser::builder().knowledge_base(kb.clone()).build()andTransformEngine::builder().knowledge_base(kb).ParserBuilder::build()now returnsParser, andParserBuildErrorandError::ParserBuildare removed.TransformEngine::transformaccepts any document bound to the same instance and returnsError::KnowledgeBaseMismatchotherwise, replacingError::ForeignDocument. In Python, passtexform.KnowledgeBase(packages, items=...)toParser(kb)andTransformEngine(profile, kb); in JavaScript, pass{ knowledgeBase }. The command-line tool and theserveprotocol are unchanged. - Breaking: Construction, edits, and syntax imports keep every complete document conformant to its knowledge base. A violation returns
ConformanceErrorwith a rooted path and a stable rule code (TexformConformanceErrorin JavaScript) and leaves the document unchanged. ReplaceArgValuewithArg, and binding argument dictionaries withNode | str | bool | None | Pairedvalues ({ value, open, close }pairs in JavaScript).create_groupandcreate_environmenttake their children and body directly, binding delimiters are strings such as"("and"\\langle", and environments are renamed withset_env_nameinstead ofset_command_name.Document::from_syntaxrejects non-conformant complete trees, withFromSyntaxError::Conformancereplacing the prime-specific variants, andKnowledgeBaseBuilderrejects item names the lexer cannot produce withKnowledgeBaseBuildError::InvalidName.
Added
- Every node kind has a constructor, including scripted nodes, infix commands, primes, inline math, and delimited groups. Commands and environments are built from their knowledge-base records, so optional, star, and paired slots can be filled, and a constructor called with a name of another command kind names the one to use. Arguments are given as nodes, source text parsed in the slot's mode, star Booleans, or explicit absent and paired values;
in_modeandparse_fragmentconstruct in an explicit context mode. - Deterministic edits:
set_subscriptandset_superscriptadd, change, or clear scripts, collapsing the wrapper when the last script is cleared;set_delimiters,set_arg_delimiters, andset_prime_countchange delimiters and prime counts.clone_nodecopies a subtree within a document, andimport_nodecopies one from another document, validating it against the destination knowledge base. Failed edits leave the document unchanged. NodeRef::pathreturns a node's rooted path andDocument::node_atresolves it;NodeRef::slotandNodeRef::is_knownreport the parent slot and knowledge status. Python and JavaScript expose the same edits and reads, JavaScript addsargKind(index), and argument reads include their slot form.Document::to_columnarexports a document as a preorder node table and an argument table for Arrow and DataFrame tools (to_columnar()in Python,toColumnar()in JavaScript); Python tables pass directly topyarrow.table.KnowledgeBaseinstances are cheap to clone and compare by identity (KnowledgeBase::ptr_eq);KnowledgeBase::default()returns one process-wide instance, andDocument::with_knowledge_baseandDocument::from_syntax_withbind an explicit one. Python and JavaScript exposeKnowledgeBasewith identity equality and hashing, document copies (copy()in Python,clone()in JavaScript), node identity, anddocument()on nodes.
Fixed
- In alignments, a script directly after a column separator (
&^2,&_1,&') now starts the next cell with an empty base instead of using&as its base. Escaped\&still takes scripts. - An unbraced argument of a text-mode command takes a single token, as in TeX and MathJax:
\mbox TeVparses as\mbox{T}eVinstead of\mbox{TeV}.\text{$x$ }and\textbf{ \emph k }now parse. - Alignment separators (
&,\\,\newline,\cr) end declarative scopes in environment bodies and math arguments, so\begin{array}{cc} \rm a & b \\ c & d \end{array}lowers to\mathrm{a} & b \\ c & dinstead of the invalid\mathrm{a & b \\ c & d}, and a\displaystylerepeated in a later cell is kept.