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 requiresflavor="github"- incommonmark, a$$...$$on its own line falls back to inline typesetting. The web build has noflavorprop 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
- React Native
- iOS
- Android
Math is the optional EnrichedMarkdownLaTeX product. Add it alongside EnrichedMarkdown, then enable it per view with .markdownLaTeX() - that one modifier turns on parsing and rendering, as there is no parsing option for math. Display math needs no flavor switch.
import EnrichedMarkdown
import EnrichedMarkdownLaTeX
import SwiftUI
struct FormulaView: View {
let content: String
var body: some View {
EnrichedMarkdownText(content)
.markdownLaTeX()
}
}
Style equations through the MathBlock() and InlineMath() theme elements. See the iOS LaTeX math guide for setup, styling and accessibility.
Math is the optional com.swmansion.enriched.markdown:math artifact. Enabling LatexMathPlugin turns on parsing and rendering - there is no parsing option for math. Without the plugin, $...$ is ordinary text. Display math needs no flavor switch.
LatexMathPlugin {
EnrichedMarkdownText(markdown = content)
}
The LatexMathPlugin { } scope enables the plugin for everything beneath it; to enable it on a single instance, pass plugins = listOf(LatexMathPlugin) to that EnrichedMarkdownText instead. Style equations with math { } and inlineMath { } inside markdownStyle { }. See the Android LaTeX math guide for installation and styling.
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.
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 });
}}
/>
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.
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.
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.mathandinlineMath- 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": falsein theenriched-markdownblock of yourpackage.jsonto 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; itsaccessibilityLabel:parameter sets the VoiceOver label.MathBlock()andInlineMath()- 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
EnrichedMarkdownLaTeXproduct.
Android - see the LaTeX math guide.
LatexMathPlugin- enables parsing and rendering, for a subtree (LatexMathPlugin { }) or one view (thepluginsparameter).math { }andinlineMath { }- display and inline equation styling.onPluginEvent- render failures arrive as aLatexError(source, message, displayMode)event.- Reduce app size - omit the
mathartifact. It is also the only artifact without a 32-bitx86native library; see Installing the artifact.