RaTeX Documentation
repository·main·Indexed 23 days ago
https://github.com/erweixin/ratexRaTeX is a high-performance, KaTeX-compatible math rendering engine written in pure Rust. It provides pixel-identical math rendering across Mobile, Web, Server, and Desktop platforms without requiring a JavaScript runtime or WebView. The project includes support for Android, iOS, JVM, Flutter, and React Native, as well as the ratex-katex-fonts crate for embedded KaTeX .ttf font files.
What's inside RaTeX
- RaTeX is a pure Rust implementation of a KaTeX-compatible mathematical rendering engine. Unlike KaTeX, which relies on a JavaScript engine (V8) and the DOM, RaTeX uses a Rust core to generate a display list that can be rendered natively on various platforms without a WebView or JavaScript runtime. This makes it suitable for high-performance, low-memory, and offline-capable applications on mobile, desktop, and server environments.
What is RaTeX?
mainRaTeX is a KaTeX-compatible math rendering engine written in pure Rust. Unlike KaTeX, which requires a JavaScript runtime or a WebView, RaTeX uses a single Rust core to produce a display list that can be rendered natively on various platforms. This makes it suitable for environments where a heavy JS engine or WebView is undesirable, such as mobile apps (iOS, Android), Flutter, React Native, or server-side environments.What the RaTeX SPM macOS Demo validates
mainThe macOS SPM demo is designed to check the following integration points:
- SPM Exposure: Ensures
Package.swiftcorrectly exposes RaTeX on macOS. - FFI Resolution: Verifies that
RaTeXFFIresolves correctly from the local XCFramework via SPM. - Parsing: Confirms
RaTeXEngine.parsefunctions correctly within a macOS application environment. - SwiftUI Rendering: Validates that
RaTeXFormulacan render through SwiftUI usingNSViewRepresentable.
- SPM Exposure: Ensures
How formula numbering and `\tag` work in RaTeX
mainRaTeX follows KaTeX-style layout for numbered display environments.
Automatic Numbering
- Environments like
equation,align,alignat, andgathergenerate sequential numbers(1),(2), etc., for each logical line. - Starred environments (e.g.,
equation*,align*) and inner environments (e.g.,aligned,alignedat,split,gathered) do not participate in automatic numbering.
Manual Tagging
- Use
\tag{...}or\tag*{...}at the end of a line to replace the automatic number with a custom label. - An empty
\tag{}suppresses the number for that line. - Use
\nonumberor\notagat the end of a line to remove the number.\notagand\nonumberare equivalent. - Note: You cannot use both
\tagand\nonumber/\notagon the same line.
Note: Each formula string is treated independently, starting numbering from
(1).- Environments like
Supported Math and Chemistry Syntax
mainRaTeX supports a wide range of LaTeX math and chemistry syntax, aligned with KaTeX:
- Standard Math: Fractions, radicals, integrals, matrices, environments, and stretchy delimiters.
- Chemistry: Full
mhchemsupport using\ceand\pucommands. - Physics Units: IUPAC-compliant value + unit expressions using
\pu. - Proof Trees:
bussproofs-styleprooftreeenvironments for inference rules and sequent calculi.
Note on Proof Trees: Supported commands include
\AxiomC/\AXC, unary through quinary inference commands (\UnaryInfC,\BinaryInfC, etc.),\LeftLabel/\RightLabel,\solidLine,\dashedLine, and\fCenter. Commands like\InsertBetweenHyps,\ScoreTree,\Cell, and\noCellare not yet implemented.% Chemistry example \ce{H2SO4 + 2NaOH -> Na2SO4 + 2H2O} \ce{Fe^{2+} + 2e- -> Fe} \pu{1.5e-3 mol//L} % Proof tree example \begin{prooftree} \AxiomC{A \fCenter B} \LeftLabel{cut} \RightLabel{\alpha} \UnaryInfC{C \fCenter D} \end{prooftree}Align RaTeX formulas with text baselines
mainRaTeX supports baseline alignment out of the box:
- Simple Alignment: For
HStackorTextalignment, useHStack(alignment: .firstTextBaseline).RaTeXFormulareports its math baseline through.alignmentGuide(.firstTextBaseline), making it compatible with standard SwiftUI text alignment. - Complex Wrapping: For inline formulas mixed with text that require automatic line wrapping, use a custom
Layout(likeFlowLayout) that reads theRaTeXFormulaAscentKey. This key carries the formula's ascent (distance from baseline to top) to ensure correct alignment during wrapping.
// Simple baseline alignment HStack(alignment: .firstTextBaseline) { Text("Euler's identity:") RaTeXFormula(latex: #"e^{i\pi}+1=0"#, fontSize: 17, displayMode: false) }- Simple Alignment: For
Coordinate system in RaTeX
mainThe coordinate system used by RaTeX is consistent across iOS and Android:
- All coordinates are in em units.
- To get screen coordinates (logical pixels), multiply the em units by the
fontSize. - The Y-axis increases downward from the top of the bounding box.
- The baseline is located at
Y = height * fontSize.
How RaTeX manages multi-platform versions
mainRaTeX uses a unified versioning strategy where a single Git tag (e.g.,
v0.0.10) triggers releases across multiple platforms. To ensure consistency, all packages within the same tag must share the same version number. The version is synchronized across several key files:- Single Source of Truth: The
VERSIONfile in the root directory. - Rust Crates:
Cargo.tomlvia[workspace.package].version. - Flutter:
platforms/flutter/pubspec.yaml. - Web (WASM):
platforms/web/package.json. - React Native:
platforms/react-native/package.json. - Android/iOS/JVM: Versions are derived from the Git tag during the release workflow (using
-PlibraryVersion). Locally, Gradle reads from the rootVERSIONfile if no parameter is passed.
- Single Source of Truth: The
Understand RaTeX golden test scoring and metrics
mainRaTeX visual testing uses indexed manifests and specific scoring metrics to evaluate render quality against a KaTeX reference.
Manifests and Indexing
Reference and RaTeX generation each write a temporary manifest (e.g.,
tests/golden/fixtures/reference-manifest.json).- Formulas are indexed continuously (
0001..NNNN). - Blank lines and lines starting with
#or%are comments and do not consume an index. - The report enforces:
formula_count == fixture_count == output_count == report_case_count.
Scoring Metrics
rendered_mean: The average score of all successfully scored cases.coverage: The ratio of scored cases to eligible (non-policy) cases.raw_coverage: The ratio of scored cases to all cases (including policy exclusions).coverage_adjusted_mean: The metric gated by--min-mean.
Case Statuses
Every report case is assigned one of the following statuses:
scoredmissing_fixturemissing_outputparse_errorlayout_errorrender_errorunsupported
- Formulas are indexed continuously (
How baseline alignment works in RaTeX
mainRaTeX components support baseline alignment, allowing them to sit on the same line as standard text in both Flexbox rows and
<Text>components.In a Flex row: Use
alignItems: 'baseline'on the parent container. Inside<Text>: Usestyle={{ alignSelf: 'baseline' }}on theRaTeXViewcomponent.Note:
InlineTeXautomatically usesdisplayMode={false}for all formulas to ensure they behave as inline elements.// In a Flex row <View style={{ flexDirection: 'row', alignItems: 'baseline' }}> <Text>f(x) =</Text> <RaTeXView latex={'\\frac{a}{b}'} fontSize={16} displayMode={false} /> </View> // Inside a <Text> component <Text> compare y with{' '} <RaTeXView latex="y" fontSize={16} displayMode={false} style={{ alignSelf: 'baseline' }} />{' '} mid-sentence </Text>Understand RaTeX stack-safety and depth limits
mainRaTeX is designed to be stack-safe across native, mobile, and WebAssembly hosts by enforcing a strict input-depth policy. This prevents stack overflow vulnerabilities when processing untrusted LaTeX input.
Depth Limits
The maximum supported cumulative recursive or structural depth is 32.
- Depth 32: Accepted.
- Depth 33: Rejected with a
ParseErrorcontaining the messageRecursion limit exceeded.
Cumulative Budget
The depth budget is cumulative across all enclosing structures. You do not get a fresh allowance for each new structure; instead, nested structures consume the existing budget.
Examples of depth-consuming structures:
- Recursively nested parser expressions (groups, radicals, fractions,
\left...\right, scripts). - Unbraced structural arguments (e.g., nested
\tagchains). - Nested macro expansion paths.
- Unicode combining-accent chains.
prooftreebranches, conclusions, and labels.mhchemsub-state-machine calls and nestedtexifyvalues.
Special Case:
mhchemBecausemhchemuses internal sub-state machines, visible nested\ce{...}commands consume extra budget. Consequently, a visible nesting depth of 31 is accepted, but a depth of 32 is rejected.Error Handling
Over-limit input is never truncated or partially ignored; it is rejected entirely. The parser, layout, and
to_display_listmethods will return errors rather than attempting to render partial results.How the RatexFormula widget handles color
mainThe
RatexFormulaGTK4 widget manages text color based on the following hierarchy:- Unset
colorproperty: The widget uses the current GTK foreground text color (theme-derived). - Set
colorproperty: The widget uses the specific color provided to the property as the default for the formula. - Inline LaTeX overrides: Commands like
\coloror\textcolorwithin the LaTeX string act as per-item overrides and take precedence.
- Unset