Skip to content

quarto-math: MathML Core writer (bd-9z83tcv0) - #709

Merged
cscheid merged 2 commits into
mainfrom
feature/bd-9z83tcv0-mathml-writer
Sep 23, 2026
Merged

cscheid merged 2 commits into
mainfrom
feature/bd-9z83tcv0-mathml-writer

Conversation

@cscheid

@cscheid cscheid commented Sep 22, 2026

Copy link
Copy Markdown
Member

Phase 2 of claude-notes/plans/2026-09-21-equation-numbering-and-mathml.md (strand bd-9z83tcv0). Stacked on #706 (quarto-math); quarto-math only.

What this adds

Target::MathMl and crates/quarto-math/src/mathml.rs: MathAst → one complete <math> element, written against MathML Core only (the subset every current browser renders natively):

  • coarse runs split into mi/mn/mo via split::split_run, one letter per mi; - becomes U+2212, ' a prime;
  • symbols classify by alphabet (Greek → mi, uppercase Greek upright, relations/arrows → mo); bare delimiters get stretchy="false", \left…\right fences stretch;
  • big operators place limits by mode, the integral family keeps side limits, \limits pins movablelimits="false"; functions get U+2061 function application;
  • \mathbf/\mathbb/\mathcal/… map characters into the Mathematical Alphanumeric Symbols block (holes included), since Core keeps only mathvariant="normal"; \text keeps edge spaces as NBSP;
  • environments become mtable (fenced matrices, { for cases, right/left columnalign for aligned); a top-level \\ becomes a table of lines; \cancel emits menclose (plan decision 3).

The source TeX rides in <semantics> as an application/x-tex annotation, so Normalized gains a text field.

Tests

A corpus-wide validity check (quick-xml walk: Core element allowlist, fixed child counts for mfrac/msub/…/munderover, mathvariant only normal), 263 per-fixture snapshots, 13 structural tests, unit tests for the variant table and accents.

Normalizer fix found by the snapshots

Primes were dropped (f'f; the committed Typst snapshot for basic/prime read f ( x ) = f ( x )). mitex parses f' as an attachment without a ^/_ operator and attach returned only the base. Now a prime is a superscript Sym, repeated primes merge into //, and x'^2 shares the superscript slot (5 tests in normalize.rs). Six snapshots changed (basic/prime, scripts/prime-with-sup × normalize/OMML/Typst). The same fixture shows mitex taking = f as the base of f'' after a relation — filed as bd-0mzhnxft.

Verification

cargo xtask verify --skip-hub-build green; the crate checks for wasm32-unknown-unknown.

🤖 Generated with Claude Code

@cscheid
cscheid added this pull request to stack #707 September 22, 2026 00:10
cscheid added a commit that referenced this pull request Sep 22, 2026
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@posit-snyk-bot

posit-snyk-bot commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues
Licenses 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@cscheid
cscheid marked this pull request as ready for review September 23, 2026 18:38
Base automatically changed from feature/bd-entbg6x3-quarto-math to main September 23, 2026 18:57
Adds `Target::MathMl` and `crates/quarto-math/src/mathml.rs`: `MathAst`
to a complete `<math>` element for `format: html` (consumed by the
`MathMlStage` of bd-3evfzwal). Written against MathML Core only:

- coarse runs split into `mi`/`mn`/`mo` via `split::split_run`, one
  letter per `mi`; `-` becomes U+2212, `'` a prime;
- symbols classify by alphabet (Greek → `mi`, uppercase Greek upright,
  relations/arrows → `mo`); bare delimiters get `stretchy="false"`,
  `\left…\right` fences stretch;
- big operators place limits by mode and the integral family keeps
  side limits, `\limits` pins `movablelimits="false"`; functions get
  U+2061 function application;
- `\mathbf`/`\mathbb`/`\mathcal`/… map characters into the Mathematical
  Alphanumeric Symbols block (holes included) since Core keeps only
  `mathvariant="normal"`; `\text` keeps edge spaces as NBSP;
- environments become `mtable` (fenced for matrices, `{` for cases,
  right/left `columnalign` for aligned); a top-level `\\` becomes a
  table of lines; `\cancel` emits `menclose` (plan decision 3).

The source TeX rides in `<semantics>` as an `application/x-tex`
annotation, so `Normalized` gains a `text` field.

Tests: a corpus-wide validity check (quick-xml walk: Core element
allowlist, fixed child counts, `mathvariant` only `normal`), 263
per-fixture snapshots, 13 structural tests, and unit tests for the
variant table and accents.

Also fixes a normalizer bug the snapshots exposed: primes were dropped
(`f'` → `f`; the committed Typst snapshot for `basic/prime` read
`f ( x ) = f ( x )`). mitex parses `f'` as an attachment without a
`^`/`_` operator and `attach` returned only the base. Now a prime is a
superscript `Sym`, repeated primes merge into `″`/`‴`/`⁗`, and `x'^2`
shares the superscript slot (5 tests in `normalize.rs`). The same
fixture shows mitex taking `= f` as the base of `f''` after a relation;
filed as bd-0mzhnxft.

Snapshots: 263 added (`integration__mathml__mathml__*`), 6 modified
(`basic/prime` and `scripts/prime-with-sup` for normalize, OMML and
Typst — the prime fix; the Typst one now shows the bd-0mzhnxft quirk
as `(= f)^(″)`).

Verification: `cargo xtask verify --skip-hub-build` green; quarto-math
checks for wasm32-unknown-unknown.

Plan: claude-notes/plans/2026-09-21-equation-numbering-and-mathml.md

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@cscheid
cscheid force-pushed the feature/bd-9z83tcv0-mathml-writer branch from a345411 to 7597480 Compare September 23, 2026 18:57
Plan doc: taken from the Phase 3 branch, which already carries the
Phase 1 and Phase 2 checkbox updates both sides made.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@cscheid
cscheid merged commit 083a46b into main Sep 23, 2026
10 checks passed
@cscheid
cscheid deleted the feature/bd-9z83tcv0-mathml-writer branch September 23, 2026 19:26
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