Skip to content

Add MathfieldElement.compactSerialization option to always emit explicit braces - #3055

Open
aeifn wants to merge 3 commits into
arnog:masterfrom
aeifn:compact-serialization-option
Open

Add MathfieldElement.compactSerialization option to always emit explicit braces#3055
aeifn wants to merge 3 commits into
arnog:masterfrom
aeifn:compact-serialization-option

Conversation

@aeifn

@aeifn aeifn commented Aug 3, 2026

Copy link
Copy Markdown

Summary

Adds MathfieldElement.compactSerialization (default true, i.e. no behavior change) to opt out of the brace-less short form used when serializing single-digit arguments.

compactSerialization: true (default) compactSerialization: false
\frac{1}{2} \frac12 \frac{1}{2}
\sqrt{2} \sqrt2 \sqrt{2}
x^{2} x^2 x^{2}
x_{1} x_1 x_{1}

Motivation: the LaTeX has to be parsed on a backend

In our use of MathLive the mathfield is an input widget: the student types an expression, and the emitted LaTeX is sent to a server that has to parse it — to normalize it, compare it against a reference answer, store it, and render it in reports. That backend is not MathLive, and in general it is not a full TeX engine either.

The compact form is valid LaTeX, but it shifts work onto the consumer in ways that are easy to get wrong:

  • It requires a real TeX argument grabber. To read \frac12 correctly a parser must know that \frac takes two mandatory arguments and that an undelimited argument is exactly one token. Server-side LaTeX toolchains (Python/Ruby/Go converters, KaTeX-to-MathML pipelines, and the inevitable in-house normalizer) frequently do not implement that rule and treat \frac12 as a malformed or single-argument macro. With explicit braces, argument boundaries are lexically obvious and even a modest parser handles them.

  • It is genuinely ambiguous to a reader, and to a sloppy parser. \frac123 is one half followed by 3, not 1/23; \sqrt12 is the root of 1 followed by 2, not the root of 12. Every human who reviews stored answers reads these the other way. The comment already in functions.ts says the same thing ("some people got confused by this"). This PR makes that concern configurable rather than hard-coded per-command.

  • Round-trip stability. The same expression can reach the backend both from a mathfield and from other sources (an authoring tool, a textbook import, a previously stored answer). If one side writes \frac12 and the other \frac{1}{2}, naive string comparison — which is what a lot of grading and dedup code actually does — reports a spurious difference. Always-braced output gives one canonical spelling.

Making this a static option keeps the default output exactly as it is today for everyone who prefers the terser form, and lets applications that ship the LaTeX elsewhere ask for the explicitly-braced form once at startup:

MathfieldElement.compactSerialization = false;

Implementation

The flag lives in _MathEnvironment alongside fractionNavigationOrder, so it is available to serializers that have no access to a mathfield instance, and is exposed as a static accessor on MathfieldElement.

It gates the three existing places where the short form is produced:

  • src/latex-commands/functions.ts\frac and friends (\binom, \dfrac, ...)
  • src/atoms/surd.ts\sqrt
  • src/core/atom-class.ts — superscripts and subscripts

Only the brace-less special cases are touched; nothing else about serialization changes. \sqrt[3]{8}, multi-character arguments and non-digit scripts (x^{\prime}, x^{n}) were already always braced and stay that way.

Tests

New test/compact-serialization.test.ts covers both settings for \frac, \binom, \sqrt, superscripts and subscripts, plus the ambiguous cases (\frac{1}{2}3, \sqrt12) and the unaffected non-digit ones.

Full suite: 339 tests / 252 snapshots pass — the default is unchanged, so no existing snapshot moved.

aeifn added 3 commits July 31, 2026 22:59
When set to false, fractions with single-digit numerator and
denominator are serialized with explicit braces (\frac{1}{2})
instead of the compact form (\frac12). Defaults to true,
preserving the existing behavior.
… \sqrt

The single-digit compact form is not specific to fractions: SurdAtom
had its own copy of the rule, so `\sqrt{2}` serialized as `\sqrt2`
regardless of the option. Gate both on a single setting.

With compactSerialization off, `\sqrt12` now serializes as `\sqrt{1}2`,
making the actual parse (root of 1, followed by 2) visible.
supsubToLatex had its own copy of the single-digit compact rule, so
`x^{2}` serialized as `x^2` regardless of the option. This was the last
ungated site: all four now share the setting.

With the option off, `x^{2}3` serializes as `x^{2}3` rather than `x^23`,
which reads as x to the 23rd.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant