[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-74685":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":15,"stars7d":17,"stars30d":18,"stars90d":16,"forks30d":16,"starsTrendScore":19,"compositeScore":20,"rankGlobal":10,"rankLanguage":10,"license":21,"archived":22,"fork":22,"defaultBranch":23,"hasWiki":22,"hasPages":24,"topics":25,"createdAt":10,"pushedAt":10,"updatedAt":41,"readmeContent":42,"aiSummary":43,"trendingCount":16,"starSnapshotCount":16,"syncStatus":44,"lastSyncTime":45,"discoverSource":46},74685,"RaTeX","erweixin\u002FRaTeX","erweixin",">99.5% KaTeX syntax coverage. LaTeX math renderer in pure Rust. No JavaScript, no WebView, no DOM. One Rust core → iOS, Android, Flutter, Web, PNG. C ABI · WASM · Server-side PNG\u002FSVG. ","https:\u002F\u002Fratex.lites.dev\u002F",null,"Rust",1332,61,5,6,0,23,107,18,18.38,"Other",false,"main",true,[26,27,28,29,30,31,32,33,34,35,36,37,38,39,40],"android","androidmath","ffi","flutter","flutter-latex","ios","iosmath","katex","latex","math","math-rendering","rust","swiftmath","wasm","web-components","2026-06-12 02:03:26","# RaTeX\n\n[简体中文](README.zh-CN.md) | **English**\n\n**KaTeX-compatible math rendering engine in pure Rust — no JavaScript, no WebView, no DOM.**\n\nOne Rust core, one display list, every platform renders natively.\n\n```\n\\frac{-b \\pm \\sqrt{b^2-4ac}}{2a}   →   iOS · Android · Flutter · React Native · Web · PNG · SVG · PDF\n```\n\n**[→ Live Demo](https:\u002F\u002Ferweixin.github.io\u002FRaTeX\u002Fdemo\u002Flive.html)** — type LaTeX and compare RaTeX vs KaTeX side-by-side ·\n**[→ Support table](https:\u002F\u002Ferweixin.github.io\u002FRaTeX\u002Fdemo\u002Fsupport-table.html)** — RaTeX vs KaTeX across all test formulas ·\n**[→ Web benchmark](https:\u002F\u002Ferweixin.github.io\u002FRaTeX\u002Fdemo\u002Fbenchmark.html)** — head-to-head perf in the browser\n\n---\n\n## Why RaTeX?\n\nEvery major cross-platform math renderer today runs LaTeX through a browser or JavaScript engine — a hidden WebView eating 50–150 MB RAM, startup latency before the first formula, no offline guarantee. KaTeX is excellent on the web, but on every other surface — iOS, Android, Flutter, server-side, embedded — you're either hosting a WebView or shelling out to headless Chrome.\n\nRaTeX is the same KaTeX-compatible math engine compiled to a portable Rust core, so the *same* renderer runs natively everywhere — and produces byte-identical output across every target.\n\n| | KaTeX | MathJax | **RaTeX** |\n|---|---|---|---|\n| Runtime | JS (V8) | JS (V8) | **Pure Rust** |\n| Surfaces it runs on | Web only* | Web only* | **iOS · Android · Flutter · RN · Web · server · SVG · PDF** |\n| Mobile | WebView wrapper | WebView wrapper | **Native** |\n| Server-side rendering | headless Chrome | mathjax-node | **Single binary, no JS runtime** |\n| Output substrate | DOM (`\u003Cspan>` tree) | DOM \u002F SVG | **Display list → Canvas \u002F PNG \u002F SVG \u002F PDF** |\n| Memory | GC \u002F heap | GC \u002F heap | **Predictable, no GC** |\n| Offline | Depends | Depends | **Yes** |\n| Syntax coverage | 100% | ~100% | **Aligned with KaTeX math syntax** |\n\n\u003Csub>\\* Embeddable in non-web targets only by hosting a WebView or headless browser, which most native and server contexts can't tolerate.\u003C\u002Fsub>\n\n**On the web specifically**, KaTeX has a decade of V8 JIT optimization behind it and remains the obvious choice for web-only projects. RaTeX's contribution isn't beating it on its home turf — it's being the only KaTeX-compatible engine that runs natively on every *other* surface, with pixel-identical output across all of them.\n\n---\n\n## What it renders\n\n**Math** — **Aligned with KaTeX’s math syntax**: fractions, radicals, integrals, matrices, environments, stretchy delimiters, and more. The small set of DOM \u002F trust-related extensions (e.g. `\\includegraphics`, `\\htmlClass`, …) is documented under *KaTeX differences (commands & DOM)* below.\n\n**Chemistry** — full mhchem support via `\\ce` and `\\pu`:\n\n```latex\n\\ce{H2SO4 + 2NaOH -> Na2SO4 + 2H2O}\n\\ce{Fe^{2+} + 2e- -> Fe}\n\\pu{1.5e-3 mol\u002F\u002FL}\n```\n\n**Physics units** — `\\pu` for value + unit expressions following IUPAC conventions.\n\n### KaTeX differences (commands & DOM)\n\nThese are the **command-level** gaps vs KaTeX (including `trust`-style HTML). Typical math and mhchem inputs are aligned with KaTeX. Some formulas still score below 1.0 in the [support table](https:\u002F\u002Ferweixin.github.io\u002FRaTeX\u002Fdemo\u002Fsupport-table.html) or golden ink comparison due to layout\u002Fmetrics\u002Frasterization vs reference PNGs — that is **not** the same as “missing syntax” in the table below.\n\n| KaTeX input | Notes |\n|-------------|------|\n| `\\includegraphics[…]{…}` | **Not supported:** parser has no handler (undefined control sequence). |\n| `\\htmlClass`, `\\htmlData`, `\\htmlId` | **Not equivalent:** expanded as macros that **drop** the first argument’s `class` \u002F `data-*` \u002F `id` and keep only the second-argument body (unlike KaTeX trusted DOM attributes). |\n| `\\htmlStyle{…}{…}` | **Partial:** simple inline styling may work on Web\u002FCanvas paths; behavior may still differ from KaTeX’s DOM-based HTML extension. |\n\n---\n\n## Platform targets\n\n| Platform | How | Status |\n|---|---|---|\n| **iOS** | XCFramework + Swift \u002F CoreGraphics | Out of the box |\n| **Android** | JNI + Kotlin + Canvas · AAR | Out of the box |\n| **Flutter** | Dart FFI + `CustomPainter` | Out of the box |\n| **React Native** | Native module + C ABI · iOS\u002FAndroid views | Out of the box |\n| **Compose Multiplatform** | Kotlin Multiplatform + Compose Canvas · Android \u002F iOS \u002F JVM Desktop | Via [`RaTeX-CMP`](https:\u002F\u002Fgithub.com\u002Fdarriousliu\u002FRaTeX-CMP) |\n| **Web** | WASM → Canvas 2D · `\u003Cratex-formula>` Web Component | Out of the box |\n| **Server \u002F CI** | `ratex-render` → tiny-skia PNG rasterizer | Out of the box |\n| **SVG** | `ratex-svg` → self-contained vector SVG | Out of the box |\n| **PDF** | `ratex-pdf` → vector PDF with embedded KaTeX fonts | Out of the box |\n\n### Screenshots\n\nFrom the demo apps in [`demo\u002Fscreenshots\u002F`](demo\u002Fscreenshots\u002F).\n\n\u003Ctable>\n  \u003Ctr>\n    \u003Cth width=\"50%\">iOS\u003C\u002Fth>\n    \u003Cth width=\"50%\">Android\u003C\u002Fth>\n  \u003C\u002Ftr>\n  \u003Ctr>\n    \u003Ctd align=\"center\">\u003Cimg alt=\"RaTeX demo on iOS\" src=\"demo\u002Fscreenshots\u002Fios.png\" width=\"100%\"\u002F>\u003C\u002Ftd>\n    \u003Ctd align=\"center\">\u003Cimg alt=\"RaTeX demo on Android\" src=\"demo\u002Fscreenshots\u002Fandroid.png\" width=\"100%\"\u002F>\u003C\u002Ftd>\n  \u003C\u002Ftr>\n  \u003Ctr>\n    \u003Cth width=\"50%\">Flutter (iOS)\u003C\u002Fth>\n    \u003Cth width=\"50%\">React Native (iOS)\u003C\u002Fth>\n  \u003C\u002Ftr>\n  \u003Ctr>\n    \u003Ctd align=\"center\">\u003Cimg alt=\"RaTeX demo on Flutter iOS\" src=\"demo\u002Fscreenshots\u002Fflutter-ios.png\" width=\"100%\"\u002F>\u003C\u002Ftd>\n    \u003Ctd align=\"center\">\u003Cimg alt=\"RaTeX demo on React Native iOS\" src=\"demo\u002Fscreenshots\u002Freact-native-ios.png\" width=\"100%\"\u002F>\u003C\u002Ftd>\n  \u003C\u002Ftr>\n  \u003Ctr>\n    \u003Cth colspan=\"2\">Compose Multiplatform\u003C\u002Fth>\n  \u003C\u002Ftr>\n  \u003Ctr>\n    \u003Ctd colspan=\"2\" align=\"center\">\u003Cimg alt=\"RaTeX demo on Compose Multiplatform\" src=\"demo\u002Fscreenshots\u002Fcompose-multiplatform.png\" width=\"100%\"\u002F>\u003C\u002Ftd>\n  \u003C\u002Ftr>\n\u003C\u002Ftable>\n\n---\n\n## Architecture\n\n```mermaid\nflowchart LR\n    A[\"LaTeX string\\n(math · \\\\ce · \\\\pu)\"]\n    subgraph core[\"Rust core\"]\n        B[ratex-lexer]\n        C[ratex-parser\\nmhchem · numbering · \\\\ce \u002F \\\\pu]\n        D[ratex-layout]\n        E[DisplayList]\n    end\n    F[ratex-ffi\\niOS · Android · Flutter · RN]\n    G[ratex-wasm\\nWeb \u002F Canvas 2D]\n    H[ratex-render\\nPNG · tiny-skia]\n    I[ratex-svg\\nSVG]\n    J[ratex-pdf\\nPDF]\n    K[ratex-unicode-font\\nCJK fallback loader]\n    A --> B --> C --> D --> E\n    E --> F\n    E --> G\n    E --> H\n    E --> I\n    E --> J\n    H -.-> K\n    I -.-> K\n    J -.-> K\n```\n\n| Crate | Role |\n|---|---|\n| `ratex-types` | Shared types: `DisplayItem`, `DisplayList`, `Color`, `MathStyle` |\n| `ratex-font` | KaTeX-compatible font metrics and symbol tables |\n| `ratex-lexer` | LaTeX → token stream |\n| `ratex-parser` | Token stream → ParseNode AST; mhchem `\\ce` \u002F `\\pu`; auto-numbering for `equation` \u002F `align` \u002F `gather` \u002F `alignat` and end-of-row `\\tag` \u002F `\\nonumber` \u002F `\\notag` |\n| `ratex-layout` | AST → LayoutBox tree → DisplayList |\n| `ratex-ffi` | C ABI: exposes the full pipeline for native platforms |\n| `ratex-wasm` | WASM: pipeline → DisplayList JSON for the browser |\n| `ratex-render` | Server-side: DisplayList → PNG (tiny-skia) |\n| `ratex-svg` | SVG export: DisplayList → SVG string |\n| `ratex-pdf` | PDF export: DisplayList → PDF bytes ([pdf-writer](https:\u002F\u002Fdocs.rs\u002Fpdf-writer), embedded CID fonts) |\n| `ratex-unicode-font` | System Unicode \u002F CJK font discovery for fallback rendering |\n\n---\n\n## Quick start\n\n**Requirements:** Rust 1.70+ ([rustup](https:\u002F\u002Frustup.rs))\n\n```bash\ngit clone https:\u002F\u002Fgithub.com\u002Ferweixin\u002FRaTeX.git\ncd RaTeX\ncargo build --release\n```\n\n### Render to PNG · SVG · PDF\n\nPrebuilt binaries:\n\n[GitHub Releases](https:\u002F\u002Fgithub.com\u002Ferweixin\u002FRaTeX\u002Freleases) provides prebuilt CLI archives. Select the archive that matches the target operating system and CPU architecture, then extract it. The prebuilt binaries bundle KaTeX fonts, so `--font-dir` is not required.\n\nBuild the CLI binaries from source:\n\n```bash\ncargo build --release -p ratex-render\ncargo build --release -p ratex-svg --features \"cli standalone\"\ncargo build --release -p ratex-pdf --features cli\n```\n\n| Output | Crate \u002F Binary | Build |\n| --- | --- | --- |\n| PNG | `ratex-render` \u002F `render` | `cargo build --release -p ratex-render`; optionally add `--features embed-fonts` |\n| SVG | `ratex-svg` \u002F `render-svg` | `cargo build --release -p ratex-svg --features \"cli standalone\"`; or `--features \"cli embed-fonts\"` |\n| PDF | `ratex-pdf` \u002F `render-pdf` | `cargo build --release -p ratex-pdf --features cli`; or `--features \"cli embed-fonts\"` |\n\nBuild notes:\n\n1. Without `embed-fonts`, all three CLIs first search the default KaTeX TTF locations; pass `--font-dir` only if your fonts are elsewhere. With `embed-fonts`, KaTeX TTFs are bundled via the [`ratex-katex-fonts`](crates\u002Fratex-katex-fonts) crate, so `--font-dir` is no longer needed. After upgrading KaTeX fonts, run [`scripts\u002Fsync-katex-ttf-to-font-crate.sh`](scripts\u002Fsync-katex-ttf-to-font-crate.sh) to refresh the bundled font crate.\n2. The current `render-svg` CLI always builds self-contained output in `standalone` mode with `embed_glyphs = true`. As a library, `ratex-svg` still defaults to `SvgOptions::embed_glyphs = false`, which emits `\u003Ctext>` elements that rely on KaTeX CSS\u002Fwebfonts.\n\nExamples:\n\n```bash\n# These examples use `printf '%s\\n' '...'` because different shells handle\n# backslashes in `echo` differently; the same formula may need `\\frac` in one\n# shell and `\\\\frac` in another.\n\n# PNG: read directly from stdin\nprintf '%s\\n' '\\frac{1}{2} + \\sqrt{x}' | .\u002Ftarget\u002Frelease\u002Frender --output-dir .\u002Fout\n\n# SVG: load KaTeX TTFs at runtime\nprintf '%s\\n' '\\int_0^\\infty e^{-x^2} dx = \\frac{\\sqrt{\\pi}}{2}' | \\\n  .\u002Ftarget\u002Frelease\u002Frender-svg --font-dir \u002Fpath\u002Fto\u002Fkatex\u002Ffonts --color '#1E88E5' --output-dir .\u002Fout\n\n# PDF: load KaTeX TTFs at runtime\nprintf '%s\\n' '\\ce{H2SO4 + 2NaOH -> Na2SO4 + 2H2O}' | \\\n  .\u002Ftarget\u002Frelease\u002Frender-pdf --font-dir \u002Fpath\u002Fto\u002Fkatex\u002Ffonts --output-dir .\u002Fout\n\n# You can also read from a file via stdin\ncat formulas.txt | .\u002Ftarget\u002Frelease\u002Frender --output-dir .\u002Fout\n\n# Or pass the input file directly\n.\u002Ftarget\u002Frelease\u002Frender-svg --input formulas.txt --font-dir \u002Fpath\u002Fto\u002Fkatex\u002Ffonts --output-dir .\u002Fout\n```\n\nCLI notes\n\n- `--input \u003CFILE>`: read formulas from a file, one per line.\n- `--output-dir \u003CDIR>`: output directory. Defaults are `output`, `output_svg`, and `output_pdf`.\n- `--help`: show supported options and whether the current build uses embedded fonts.\n- `--color` \u002F `--background-color` accept named colors (for example `black`, `red`, `teal`), 3- or 6-digit hex (`#f00`, `#ff0000`), and KaTeX \u002F MathJax-style color model values (`[RGB]255,0,0`, `[rgb]1,0,0`, `[HTML]B22222`, `[gray]0.5`, `[cmyk]0,1,1,0`).\n- `ratex-render --background-color transparent` produces a transparent PNG.\n\n### CJK \u002F Unicode fallback\n\nBy default RaTeX bundles only KaTeX fonts (19 faces for math symbols). Characters outside the KaTeX glyph set — CJK ideographs, emoji, Hangul, etc. — are rendered via a system Unicode font discovered automatically:\n\n1. **`RATEX_UNICODE_FONT`** env var — path to any `.ttf`\u002F`.otf`\u002F`.ttc`, with optional `#index` or `#FamilyName` selector for TTC collections (e.g. `NotoSansCJK.ttc#Noto Sans CJK SC`)\n2. **Hard-coded system paths** — Linux (`\u002Fusr\u002Fshare\u002Ffonts\u002Fopentype\u002Fnoto\u002FNotoSansCJK-Regular.ttc`), macOS (`\u002FLibrary\u002FFonts\u002FArial Unicode.ttf`, `\u002FSystem\u002FLibrary\u002FFonts\u002FSupplemental\u002FArial Unicode.ttf`), Windows (`C:\\Windows\\Fonts\\NotoSansSC-VF.ttf`, `C:\\Windows\\Fonts\\msyh.ttc`)\n3. **Locale-aware system discovery** — `system-fonts` resolves prioritized Sans candidates for the current system locale \u002F region, including TTC family selection when needed\n\n```bash\n# Explicit font path (recommended for CI \u002F server environments)\nprintf '%s\\n' '\\text{你好世界}' | \\\n  RATEX_UNICODE_FONT=\u002Fpath\u002Fto\u002FNotoSansSC-Regular.ttf .\u002Ftarget\u002Frelease\u002Frender --output-dir .\u002Fout\n\n# Auto-discovery probes built-in paths first, then locale-aware system Sans fallbacks.\nprintf '%s\\n' '\\text{你好世界}' | .\u002Ftarget\u002Frelease\u002Frender-pdf --output-dir .\u002Fout\n```\n\nAll three renderers (PNG, SVG, PDF) use the same discovery crate (`ratex-unicode-font`), so once a font is found the output is consistent across all formats. For variable fonts, RaTeX prefers the Regular `wght=400` instance when that axis is available so outline extraction, metrics, and PDF subsetting stay aligned. For PNG and standalone SVG, glyph outlines are embedded as paths. For PDF, the detected CJK glyphs are subsetted and embedded as a CIDFontType2 font.\n\n### Browser (WASM)\n\n```bash\nnpm install ratex-wasm\n```\n\n```html\n\u003Clink rel=\"stylesheet\" href=\"node_modules\u002Fratex-wasm\u002Ffonts.css\" \u002F>\n\u003Cscript type=\"module\" src=\"node_modules\u002Fratex-wasm\u002Fdist\u002Fratex-formula.js\">\u003C\u002Fscript>\n\n\u003Cratex-formula latex=\"\\frac{-b \\pm \\sqrt{b^2-4ac}}{2a}\" font-size=\"48\" color=\"#1E88E5\">\u003C\u002Fratex-formula>\n\u003Cratex-formula latex=\"\\ce{CO2 + H2O \u003C=> H2CO3}\" font-size=\"32\">\u003C\u002Fratex-formula>\n```\n\nSee [`platforms\u002Fweb\u002FREADME.md`](platforms\u002Fweb\u002FREADME.md) for the full setup.\n\n### Platform glue layers\n\n| Platform | Docs |\n|---|---|\n| iOS | [`platforms\u002Fios\u002FREADME.md`](platforms\u002Fios\u002FREADME.md) |\n| Android | [`platforms\u002Fandroid\u002FREADME.md`](platforms\u002Fandroid\u002FREADME.md) |\n| Flutter | [`platforms\u002Fflutter\u002FREADME.md`](platforms\u002Fflutter\u002FREADME.md) |\n| React Native | [`platforms\u002Freact-native\u002FREADME.md`](platforms\u002Freact-native\u002FREADME.md) |\n| Compose Multiplatform | [`RaTeX-CMP`](https:\u002F\u002Fgithub.com\u002Fdarriousliu\u002FRaTeX-CMP) |\n| Web | [`platforms\u002Fweb\u002FREADME.md`](platforms\u002Fweb\u002FREADME.md) |\n\n### Run tests\n\n```bash\ncargo test --all\n```\n\n---\n\n## Equation numbering and `\\tag`\n\nRaTeX follows KaTeX-style layout for numbered display environments.\n\n- **Auto-numbering** applies to non-starred `equation`, `align`, `alignat`, and `gather`: each logical row gets a sequential tag such as `(1)`, `(2)`, … . Starred forms (`equation*`, `align*`, …) and inner environments **`aligned`**, **`alignedat`**, **`split`**, and **`gathered`** do **not** auto-number (same idea as LaTeX: only the outer display is numbered).\n- **`\\tag{...}`** \u002F **`\\tag*{...}`** at the **end** of a row replace the auto number for that row (amsmath-style). Empty `\\tag{}` suppresses the number for that row.\n- **`\\nonumber`** and **`\\notag`** at the **end** of a row suppress the number for that row when auto-numbering is active. They cannot be combined with `\\tag` on the same row.\n- **`\\notag`** is implemented as an alias of **`\\nonumber`** (same as above).\n\nDocument-level options such as `\\leqno` and cross-reference counters are not modeled; numbering starts from `(1)` within the parse of each formula string.\n\n---\n\n## Acknowledgements\n\nRaTeX owes a great debt to [KaTeX](https:\u002F\u002Fkatex.org\u002F) — its parser architecture, symbol tables, font metrics, and layout semantics are the foundation of this engine. Chemistry notation (`\\ce`, `\\pu`) is powered by a Rust port of the [mhchem](https:\u002F\u002Fmhchem.github.io\u002FMathJax-mhchem\u002F) state machine.\n\n---\n\n## Contributing\n\nSee [`CONTRIBUTING.md`](CONTRIBUTING.md). To report a security issue, see [`SECURITY.md`](SECURITY.md).\n\n---\n\n## License\n\nMIT — Copyright (c) erweixin.\n","RaTeX是一个使用纯Rust编写的数学公式渲染引擎，兼容超过99.5%的KaTeX语法。其核心功能在于通过单一的Rust内核实现跨平台原生渲染，支持iOS、Android、Flutter、Web及服务器端等多种环境，并能生成PNG、SVG等格式的图像文件。RaTeX不依赖JavaScript、WebView或DOM结构，从而在移动端和服务器端提供了更高效且占用资源更少的解决方案。该工具特别适用于需要跨平台一致展示LaTeX公式的应用场景，如教育软件、科学计算应用以及任何需要离线渲染数学表达式的项目中。",2,"2026-06-11 03:50:25","high_star"]