Skip to content

Unknown LaTeX control words end at their letters - #12

Merged
simonebortolin merged 2 commits into
mainfrom
claude/latex-unknown-command-space-42f4d4
Nov 9, 2026
Merged

simonebortolin merged 2 commits into
mainfrom
claude/latex-unknown-command-space-42f4d4

Conversation

@simonebortolin

Copy link
Copy Markdown
Owner

Depends on 0bebb37 ("Content MathML read through ctop.xsl; amssymb symbols in LaTeX", local branch claude/content-mathml, not pushed yet). The branch is built on that commit, so this diff includes it until it lands. Retarget or rebase this PR once it does. This PR's own change is the last commit, e441dd2.

The bug

When the LaTeX reader met a control word it didn't know, it dropped the space after it and wrote the word back without that space, so UnicodeMath then read the next letters as part of the word:

LaTeX before after
\sgn r <mtext>\sgnr</mtext> <mtext>\sgn</mtext><mi>r</mi>
a \backslash b 𝑎"\backslashb" (the b lost) 𝑎, \backslash, 𝑏
\lg d, \liminf v, \sgn2 merged split
strict \foo x Unknown control word \foox Unknown control word \foo

The fix

  • LaTeXReader.Convert: an unknown control word is followed by a space only where a letter or digit comes next, the one place where UnicodeMath would otherwise merge them. Elsewhere it gets no space, so \text{\foo} and Word's \textrm{\f } stay stable when read back.
  • UnicodeMathInput.ResolveControlWords takes a new tex flag, which the translator passes for LaTeX input. With it, an unknown word is quoted without its terminating space ("\sgn", not "\sgn "), since in TeX that space only ends the word. UnicodeMath input keeps the ported behaviour, which the UnicodeMathML corpus checks.

This does not add any of the missing commands (\sgn, \backslash, …); a separate session handles those. Public API is unchanged. [no-new-version].

Tests

  • New: LaTeXReaderTests.EndsUnknownControlWordsAtTheirLetters (lenient: one mtext with just the command, then the following letter or digit).
  • Extended: RejectsUnknownControlWordsWhenStrict now covers these cases, and its existing \foo x expectation is corrected from \foox to \foo.
  • dotnet test --solution SharpEquations.slnx: 2752 total, 0 failed (net10.0 and net481), RoundTripPropertyTests included.

🤖 Generated with Claude Code

@simonebortolin
simonebortolin force-pushed the claude/latex-unknown-command-space-42f4d4 branch from e441dd2 to 0b6574b Compare November 8, 2026 14:27
@simonebortolin
simonebortolin changed the base branch from main to claude/content-mathml November 8, 2026 14:27
@simonebortolin simonebortolin reopened this Nov 8, 2026
@simonebortolin
simonebortolin added this pull request to stack #15 November 8, 2026 14:32
@github-actions

github-actions Bot commented Nov 8, 2026 •

Copy link
Copy Markdown

Pre-release removed now that this PR is closed.

An unknown control word swallowed the space after it and the reader
re-emitted it bare, so UnicodeMath read the next word as part of it:
\sgn r became the text \sgnr, a \backslash b lost the b, and strict mode
named \sgnr. The LaTeX reader now ends such a word with a space where a
letter or digit follows, and text read from LaTeX quotes the word
without that space (UnicodeMath itself keeps it, as UnicodeMathML does).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@simonebortolin
simonebortolin force-pushed the claude/latex-unknown-command-space-42f4d4 branch from 0b6574b to 9c542f1 Compare November 9, 2026 18:21
Base automatically changed from claude/content-mathml to main November 9, 2026 19:06
@simonebortolin
simonebortolin merged commit d24f056 into main Nov 9, 2026
17 of 28 checks passed
@simonebortolin
simonebortolin deleted the claude/latex-unknown-command-space-42f4d4 branch November 9, 2026 19:24
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.

2 participants