Skip to content

2.1.0 — Math-feature expansion

Latest

Choose a tag to compare

@clintecker clintecker released this 21 Jul 22:37
300817f

Vinculum 2.1.0 — math-feature expansion. A wave of new notation, each rendered natively and platform-free: chemistry, commutative diagrams, Young tableaux, function plots, inference rules / proof trees, siunitx units, the physics package (Dirac notation & derivatives), and syntax trees — plus equation numbering, automatic line breaking, Presentation MathML export, and more. Every feature crosses the VDL1 seam, so it renders identically on Apple, Linux, Windows, Android, and the web. No API breaks; fully compatible with 2.0.x.

Closing the coverage gaps identified in the July 2026 gap analysis, one at a time,
each with docs + a specimen figure. Every feature is platform-free (renders
identically on all targets through the VDL1 seam).

Added

  • Syntax / parse trees\Tree [.S [.NP … ] [.VP … ] ] (qtree / tikz-qtree; \qtree
    alias). A labelled root centered above its children, joined by straight edges;
    [.Label child …] internal nodes, bare tokens are leaves, {…} for multi-token
    labels/leaves, and labels are arbitrary math (so expression trees work too). A real
    2D tidy-tree layout — subtree widths bottom-up, nodes placed top-down, edges as
    stroked paths — so it renders identically on all five platforms through VDL1 with no
    new primitive. New MathNode.syntaxTree; round-trips through toLaTeX, speaks its
    structure, exports to MathML as nested rows. The tokenizer gains bracketVerbatimCommands
    so \Tree's bracket body is captured with spaces intact. (Gap analysis — linguistics / CS.)
  • Physics package — Dirac notation, derivatives, brackets — the most-used physics
    macros, a transpiler to LaTeX (Physics) reusing the whole engine. Dirac notation
    (\bra, \ket, \braket{ϕ}{ψ} → ⟨ϕ|ψ⟩, \ketbra, \expval{A}{ψ} → ⟨ψ|A|ψ⟩,
    \mel{ϕ}{A}{ψ}, with aliases \ip/\op/\ev/\matrixel); derivatives (\dd{x} → dx,
    \dv{f}{x} → df/dx, \dv[n], \pdv{f}{x} → ∂f/∂x, \pdv{f}{x}{y} mixed); brackets
    (\abs, \norm, \comm{A}{B} → [A,B], \acomm → {A,B}, \order → O(x)); and vector
    operators (\grad, \curl, \laplacian, \Tr/\tr, \rank\div left as ÷). Also
    fixes a latent bug: \left\|…\right\| now parses to the ‖ norm delimiter instead of
    falling back to parens. (Gap analysis — quantum mechanics / vector calculus.)
  • Units — siunitx \num / \ang / \si / \unit / \SI / \qty — physical
    quantities and units, a transpiler to LaTeX (SIUnitx) reusing the whole engine like
    mhchem. \num formats numbers (scientific notation 1.5e3 → 1.5×10³, thin-space digit
    grouping from five digits), \ang renders angles (45;30;15 → 45°30′15″), \si/\unit
    typeset unit bodies (literal kg.m.s^{-1} or macros \kilo\gram\per\second\squared,
    with ./~ thin spaces, / solidus, \per/\squared/\cubed, and SI prefixes/units
    with µ/Ω/Å/°C upright), and \SI/\qty combine a number and a unit. Both siunitx v2 and
    v3 spellings; unknown unit macros pass through as real commands. (Gap analysis — metrology.)
  • Inference rules / proof trees\inferrule[label]{premises}{conclusion}
    (aliases \infer, \prftree), the mathpartir/natural-deduction notation. Premises
    (\\-separated) are centered over a horizontal bar sitting on the math axis; the
    conclusion is centered below; the optional bracketed label (accepts [left=Name])
    sits at the bar's right at script size. Empty premises render an axiom bar; rules
    nest, so full derivation trees build up. New MathNode.inferenceRule; round-trips
    verbatim, speaks as "from …, and …, infer …", exports to MathML as a zero-numerator
    <mfrac>. (Gap analysis — proof theory / PL.)
  • Function plots — a curated pgfplots subset: \begin{axis}[domain=a:b, samples=n] \addplot{expr}; … \end{axis} (optionally wrapped in tikzpicture).
    A new arithmetic evaluator (MathExpression: + - * / ^, unary minus, parens,
    x, pi/e, sin cos tan exp ln sqrt abs …) samples each curve; the layout
    auto-ranges y and draws framed axes with nice-numbered ticks, gridlines, and the
    curves as stroked polylines (broken across discontinuities). New MathNode.plot;
    everything is stroked paths + glyph runs, so it renders on all five platforms via
    VDL1. Full TikZ/pgfplots remains out of scope. (Gap analysis Tier 3 — the
    flagship plotting feature.)
  • Young tableaux\ydiagram{4,2,1} (empty Young diagram from a partition) and
    \ytableaushort{134,25,6} / \young(…) (filled tableau). A grid of bordered square
    cells (stroked paths), left-aligned and stacked top-down, usable inline in an
    expression. New MathNode.youngTableau; round-trips verbatim. (Gap analysis Tier 3.)
  • Chemistry — mhchem \ce{…} — chemical formulas and equations. Implemented as
    a transpiler to LaTeX (MHChem.transpile), reusing the whole engine (no chemistry-
    specific layout): auto-subscripts (H2O → H₂O), groups (Ca(OH)2), ^ charges
    (SO4^2- → SO₄²⁻), stoichiometric coefficients (2H2), reaction arrows (->,
    <-, <->, <=> equilibrium, and conditional ->[\Delta]), bonds (=, #),
    states ((s) (l) (g) (aq)), and hydrate dots (*). (Gap analysis Tier 2.)
  • Commutative diagrams\begin{CD} … \end{CD} (amscd): objects on a grid
    joined by labelled arrows (@>a>b>, @<, @VaVbV, @A, @=/@\| equality
    edges, @.). A real 2D-diagram layout — objects in a grid, arrows drawn as stroked
    paths (shaft + chevron head), labels at script size — so it renders identically on
    all five platforms through the VDL1 wire, with no diagram-specific primitive.
    New MathNode.commutativeDiagram; round-trips verbatim. (Gap analysis Tier 2 — the
    flagship diagram.)
  • Equation numbering & cross-references — document-scoped (like macros).
    \label{key} records an equation's number; \eqref{key}(N) and \ref{key}
    N resolve throughout prose and math (dangling key → (?)). MathText's new
    numberEquations: flag auto-numbers display equations that neither \tag nor
    \notag — opt-in, so default output is unchanged. \label/\notag/\nonumber
    are stripped before rendering; \tag still places the number. New platform-free
    MathNumbering engine (headless-tested). (Gap analysis Tier 1.)
  • Automatic line breakinglayout(node, display:, maxWidth:) wraps an
    over-wide equation across lines at TeX's break points (after a binary operator or
    relation), stacking the lines baseline-aligned. Top-level only (nested subformulas
    stay whole); greedy fit within the budget; unbreakable runs left intact. Fully
    opt-in: without maxWidth the output is byte-identical to before (zero golden
    churn). The long-deferred flagship layout gap. (Gap analysis Tier 1.)
  • Presentation MathML exportMathMLExporter.export(node, display:) (and
    MathNode.toMathML()) serializes the parse tree to <math>…</math>: <mi>/<mn>/
    <mo> by atom class, <mfrac>, <msqrt>/<mroot>, <msub>/<msup>/<msubsup>,
    <mmultiscripts> (prescripts), <mtable>, <mover accent="true">, <menclose>.
    XML-escaped and always well-formed (verified with XMLParser); unknown input →
    <merror>. For accessibility trees, copy-as-MathML, and interop. (Gap analysis
    Tier 1 — a second serializer off the tree, no rendering.)
  • Prescripts & multiscripts\prescript{sup}{sub}{base} (mathtools) and
    \sideset{_l^l}{_r^r}{base} (amsmath). Scripts at all four corners of a base:
    isotopes (\prescript{14}{6}{C} → ¹⁴₆C), tensors, left indices. Pre- and
    post-scripts share one pair of baseline shifts so every corner aligns; the base
    keeps its own operator limits. New MathNode.multiScripts case; round-trips via
    \sideset/\prescript. (Gap analysis Tier 0 #1.)
  • \multicolumn{n}{align}{content} — table cells spanning n columns with
    their own l/c/r alignment, in every grid environment (headers, titles,
    merged blocks). Content overflowing the span grows its last column. New
    MathNode.spanned case; the no-span path is byte-identical, so existing matrices
    are unchanged. (Gap analysis Tier 0 #2.)
  • Harpoon accents & \utilde\overrightharpoon/\overleftharpoon (stretchy
    harpoons over the base) and \utilde (a wide tilde below the base, stretchy).
    New MathAccent cases with an under-accent layout branch; both round-trip exactly.
    (Gap analysis Tier 0 #4.)
  • \DeclareMathOperator & \mathchoice\DeclareMathOperator{\name}{text}
    (and the * limits form) registers a document-scoped operator that renders like
    \operatorname{text}, via the existing macro processor. \mathchoice{D}{T}{S}{SS}
    selects one of four branches by the current math style (new MathNode.mathChoice).
    (Gap analysis Tier 0 #3.)

Fixed

  • Spacing commands inside \text/\mathrm/\operatorname now resolve instead
    of printing literally: \operatorname{arg\,max} renders "arg max" (thin space),
    not "arg,max". \, \: \; \quad \qquad \ map to the matching space, and
    \& \% \_ \# \$ to their literal character. Embedded $…$ math still works.