smart_latex 2.1.0
smart_latex: ^2.1.0 copied to clipboard
Self-contained Flutter LaTeX rendering with bundled KaTeX metrics, input repair, RTL-safe layout, and no extra math package.
smart_latex #
Robust LaTeX rendering for Flutter. Renders mixed text and math, repairs malformed input, and works cleanly inside custom-font and right-to-left layouts.
Features #
- Renders inline (
$...$,\(...\)) and display ($$...$$,\[...\]) math. - Repairs malformed LaTeX automatically:
Input problem Fix applied \\right)(double backslash)\\command→\command\sqt{x}typo→ \sqrt{x}Persian / Arabic digits ۱٫۵→ 1.5Unicode math π × r ≤ 5→ \pi \times r \le 5\text{0}\text{.}\text{5}→ 0.5Unmatched {or}balanced automatically - Currency-aware:
it costs $5 and $10stays as text instead of being mistaken for a$...$math span (toggle withdetectCurrency). - RTL-safe: keeps KaTeX metrics isolated from the surrounding font/line-height so math renders correctly inside Persian/Arabic text and doesn't trigger
flutter_math_forklayout assertions. - Accessible: every formula gets a spoken
Semanticslabel so screen readers announce\frac{a}{b}as "a over b" (seelatexToSpeech). - Copy & export: long-press to copy a formula's LaTeX, or render it to a PNG
with
captureLatexPngfor sharing. hideTrailingIncompleteMathflag for streaming / typewriter animations.- Selectable text, custom error builders, text scaling, and per-rule sanitizer options.
Installation #
dependencies:
smart_latex: ^2.1.0
Or simply run:
flutter pub add smart_latex
No dependency_overrides and no separate math package are required — the
layout-fixed rendering engine is bundled.
Usage #
import 'package:smart_latex/smart_latex.dart';
// Inline math mixed with text
SmartLatexText(r'The answer is $\frac{1}{2}$.')
// RTL text with a formula
SmartLatexText(
r'قضیه فیثاغورس: $a^2 + b^2 = c^2$',
textDirection: TextDirection.rtl,
style: const TextStyle(fontSize: 16, height: 1.8),
)
// A single expression
SmartMath(r'e^{i\pi} + 1 = 0', display: true)
// Streaming / animated text — hides an unclosed formula while it is typed
SmartLatexText(currentStreamedText, hideTrailingIncompleteMath: true)
Sanitize without rendering #
final clean = sanitizeLatex(r'\frac{{\text{0}\text{٫}\overline{\text{3}}}}{{1}}');
// → r'\frac{{0.\overline{3}}}{{1}}'
Pick which rules run:
sanitizeLatex(
source,
options: const LatexSanitizeOptions(
normalizeDigits: false, // keep Persian digits
),
);
Configuration #
SmartLatexText parameters:
| Parameter | Default | Description |
|---|---|---|
style |
null |
Base text style (merged over DefaultTextStyle). |
textDirection |
ltr |
Text direction of the surrounding text. |
textAlign |
start |
Alignment of the text. |
selectable |
false |
Make plain-text runs selectable. |
sanitize |
true |
Run sanitizeLatex on each math segment. |
sanitizeOptions |
all on | Which sanitizer rules to apply. |
detectCurrency |
true |
Treat $5 and $10-style text as currency, not math. |
hideTrailingIncompleteMath |
false |
Hide an unclosed trailing $. |
scrollDisplayMath |
true |
Horizontally scroll wide block equations. |
copyableMath |
false |
Long-press a formula to copy its LaTeX. |
onMathCopied |
null |
Called with the source after a copy. |
errorBuilder |
null |
Custom widget when a formula fails to render. |
textScaler |
inherited | Scale factor for both text and math. |
Copy & export a formula #
Let users copy the LaTeX of any formula with a long press, and export the rendered equation to a PNG for sharing:
// Long-press to copy the LaTeX source.
SmartLatexText(
r'Euler: $e^{i\pi} + 1 = 0$',
copyableMath: true,
onMathCopied: (tex) => ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Copied: $tex')),
),
)
// Export to a PNG (e.g. to hand to share_plus or write to a file).
final key = GlobalKey();
// ...
SmartMath(r'e^{i\pi} + 1 = 0', boundaryKey: key, copyable: true);
// ...
final Uint8List? png = await captureLatexPng(key);
Accessibility #
Every rendered formula carries a spoken Semantics label so screen readers
announce something meaningful. The label is generated by latexToSpeech, which
you can also call directly:
latexToSpeech(r'\frac{a}{b}'); // => 'a over b'
latexToSpeech(r'x^2 + 1'); // => 'x squared plus 1'
// Override the generated label when you know better:
SmartMath(r'\sum_{i=1}^{n} i', semanticLabel: 'sum from 1 to n of i');
Using with gpt_markdown #
smart_latex pairs well with full Markdown renderers. Hand each LaTeX segment
to SmartMath, which sanitizes the input and forwards only fontSize/color
to the bundled engine — no flutter_math_fork import needed:
import 'package:gpt_markdown/gpt_markdown.dart';
import 'package:smart_latex/smart_latex.dart';
GptMarkdown(
source,
useDollarSignsForLatex: true,
latexWorkaround: sanitizeLatex,
latexBuilder: (ctx, tex, style, inline) => SmartMath(
tex,
display: !inline,
style: style,
),
)
Why a bundled engine? #
Upstream flutter_math_fork can throw a layout assertion
(RenderResetDimension does not meet its constraints) for some complex
formulas — most visibly \sqrt nested inside \frac with \left(...\right)
delimiters. The root cause is in its layout code, which sets sizes without
clamping them to the incoming constraints, so it could not be worked around
from the outside.
smart_latex ships a vendored, layout-fixed copy of that engine inside the
package, so this crash is resolved out of the box. See
PATCHES.md for the exact changes.
License #
smart_latex itself is released under the MIT License.
It bundles a modified copy of
flutter_math_fork, which is
licensed under Apache-2.0. Its license is retained at
LICENSE-flutter_math_fork as required.