Skip to main content

LaTeX math

EnrichedMarkdownText renders LaTeX math natively, both inline and as block equations:

  • Inline math ($...$) flows within the surrounding text and works in either flavor.
  • Block math ($$...$$) renders as a standalone display equation. In the React Native package on iOS and Android, a display block needs the segmented renderer, so it requires flavor="github" - in commonmark, a $$...$$ on its own line falls back to inline typesetting. The web build has no flavor prop and always renders $$ as a block, and the standalone iOS and Android SDKs need no flavor switch either.

In the React Native package math parsing is on by default. You can turn it off so $ is treated as plain text, and exclude the native math engine to shrink your binary - see Reducing app size. The standalone iOS and Android SDKs ship math as an optional add-on instead, off until you install and enable it.

Usage​

Loading…

Block equations render as standalone display elements with their own spacing and an optional background. In the React Native package the style key is math (not mathBlock) and it takes fontSize, color, backgroundColor, padding, marginTop, marginBottom and textAlign. Inline math inherits the surrounding block's typography and takes only a color, through markdownStyle.inlineMath. Under flavor="commonmark" none of the math keys apply, because the equation becomes an inline attachment coloured from inlineMath.

important

LaTeX commands use backslashes (\frac, \alpha). In regular JS strings and template literals a backslash is an escape character, so either double every backslash (\\frac, as the example above does) or wrap the string in String.raw. Block math ($$...$$) must be on its own line to render as a display element.

Handling render errors​

When the engine cannot draw a formula - an unsupported command, a syntax error - it does not crash or leave a gap. On iOS and Android the expression falls back to its raw source with the delimiters put back ($\nosuchcommand$); on web you get KaTeX's own error output instead, or the delimited source when katex is not installed. Pass onLatexError to observe those failures in the React Native package, for example to report them to an error tracker:

<EnrichedMarkdownText
markdown={String.raw`Inline $\nosuchcommand$ and block:` + '\n\n$$\\bar$$'}
onLatexError={({ source, message, displayMode }) => {
reportToErrorTracker('latex-render-failed', { source, message, displayMode });
}}
/>
note

onLatexError is native-only. It is stripped on web, where KaTeX renders its own error markup instead and nothing is reported back to you.

The whole expression is the unit of failure - the engine either renders one in full or rejects it - so the callback reports the failing source rather than a single offending command. Classify source on your side instead of keeping an allowlist that goes stale when the engine is upgraded.

Each component instance remembers what it has already reported, keyed by displayMode + source, and fires at most once per distinct failing expression. That cache survives markdown changes, so streaming content reports each failure once instead of on every token.

caution

The de-duplication is per component instance, not global, and it cuts both ways. A remount - navigating away and back, or a changed React key - creates an instance with no memory of earlier reports and fires again for the same expressions. A recycled instance is the opposite case: list virtualization reuses the native view without clearing the cache, so a row that scrolls back into view with different content stays silent about a failure it has already reported. De-duplicate by source on your side if you aggregate these app-wide.

On the standalone SDKs the fallback to the delimited source is the same. iOS has no error callback; Android reports each failure through onPluginEvent as a LatexError - see Errors.

Reducing app size​

Native LaTeX rendering relies on RaTeX, a KaTeX-compatible math engine that the React Native package bundles by default on iOS and Android. If you don't need math, you can stop parsing it or exclude the native engine entirely to shrink your binary - see the Reference. On the standalone SDKs math is opt-in already: leave out the EnrichedMarkdownLaTeX product (iOS) or the math artifact (Android) and no engine ships.

danger

Block math is silently dropped on macOS in the React Native package. Inline $...$ renders there, but a display $$...$$ under flavor="github" produces no output and no fallback text - the equation simply disappears. Math is otherwise compiled into macOS builds by default (there is no macOS gate on the engine), it is just unvalidated. See macOS support.

Reference​

  • md4cFlags.latexMath - toggle math parsing (on by default).
  • markdownStyle.math and inlineMath - display and inline equation styling.
  • onLatexError - observe expressions the engine could not render; see Handling render errors.
  • Reduce app size - set md4cFlags={{ latexMath: false }} to stop parsing, or "enableMath": false in the enriched-markdown block of your package.json to exclude the engine from the native build on both iOS and Android. See Native assets for the full opt-out.
  • Web - math renders through KaTeX, an optional peer dependency. Without it installed, equations fall back to their raw $...$ source. See Web support.

iOS - see the LaTeX math guide.

  • .markdownLaTeX() - enables parsing and rendering per view; its accessibilityLabel: parameter sets the VoiceOver label.
  • MathBlock() and InlineMath() - display and inline equation styling.
  • Errors - there is no error callback; a formula that fails to typeset renders as its delimited source.
  • Reduce app size - omit the EnrichedMarkdownLaTeX product.

Android - see the LaTeX math guide.