Skip to content

Text runs are serialized without \text{} when defaultMode is "text", making the value unusable outside the mathfield #3078

Open

Description

@blindemann1971

Description

In a mathfield with defaultMode: "text", a text run is serialized without a \text{} wrapper, while a maths run is wrapped in $ … $:

typed:   Hello  →  Ctrl+M  →  x^2  →  Ctrl+M  →   world
mf.value:  "Hello $ x^2 $ world"

That value is only meaningful to another text-default field. Handed to anything else that reads LaTeX — convertLatexToMarkup(), renderMathInElement(), a server, a database — Hello is a run of five italic variables and its spaces are gone, because outside a text-default context unmarked words are maths.

It round-trips within a text-default mathfield, so it is self-consistent; the problem is that the emitted LaTeX is not portable, and there is no option to ask for the marked form.

Steps to reproduce

<math-field id="mf" default-mode="text"></math-field>
  1. Type Hello
  2. Ctrl+M, type x^2, Ctrl+M
  3. Type world
  4. Read mf.value

Actual: Hello $ x^2 $ world
Expected: \text{Hello }x^2\text{ world}

Then convertLatexToMarkup(mf.value) renders Hello as italic variables run together, rather than as words.

Reproducible without a browser, which makes it easy to test:

const atoms = parseLatex('Hello $x^2$ world', { parseMode: 'text' });
Atom.serialize(atoms, { defaultMode: 'text' });
// master:   "Hello $ x^2 $ world"
// expected: "\\text{Hello }x^2\\text{ world}"

Cause

The two mode serializers make opposite decisions from the same flag:

  • src/core/modes-text.ts — needsWrap is options.defaultMode !== 'text', so a text run is never wrapped in a text-default field.
  • src/core/modes-math.ts — a maths run is wrapped in $ … $ precisely when options.defaultMode === 'text'.

So in a text-default field the maths is marked and the words are not. That is fine while the whole document is text, and ambiguous as soon as it is mixed.

Proposed fix

A text run that shares the document with maths is marked whatever the field's default mode; words on their own are left alone. The decision is made where a run is already being split by mode, so both the styled and skipStyles paths agree.

PR: #3079

input (parsed in text mode) before after
Hello $x^2$ world Hello $ x^2 $ world \text{Hello }x^2\text{ world}
Hello $x$ Hello $ x $ \text{Hello }x
$x^2$ alone $ x^2 $ alone x^2\text{ alone}
just words here just words here just words here (unchanged)

Existing suite passes unchanged: 338 tests, 252 snapshots. The three new cases fail without the change.

Environment

  • MathLive 0.110.0, and master at c952a20
  • Chrome 141, macOS

Why it matters

This is the blocker for the use case in #2420. An application that stores a mathfield's value and renders it anywhere else — a document, a print view, another mathfield in maths mode — has to re-mark the words itself to know which parts were prose. We do that with a normalization pass over every value on the way in and out; the marked form removes the need.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions