syntax_highlighter_plus 0.2.0
syntax_highlighter_plus: ^0.2.0 copied to clipboard
A robust syntax highlighting Flutter package powered by TextMate grammars.
syntax_highlighter_plus #
A robust syntax highlighting Flutter package powered by TextMate grammars and themes.
Tip
This is the exact highlighter powering Reins: Local & Private AI Assistant which runs LLMs on your iPhone, iPad, and Mac. Grab Reins on the App Store to see it in production.
Features #
- Full TextMate grammar support (begin/end/while rules, captures, embedded languages), tokenized by a Rust engine built on Oniguruma — the same regex engine VS Code's highlighter uses.
- 70+ bundled grammars and fence-tag aliases (
py,js,c++, …). - VS Code color themes (
github-dark,github-lightbundled). - Tokenization runs off the UI thread via
flutter_rust_bridge; theming andTextSpanbuilding happen in Dart, so switching themes is cheap. - Simple and direct:
highlight()just returns aTextSpan. Just drop it intoText.rich, no custom widgets or controllers to learn.
Usage #
highlight() just returns a TextSpan. There's no special widget to wrap
your code in, just pass the span straight to Text.rich (or
SelectableText.rich) like any other rich text.
Here is a basic example of how to use the SyntaxHighlighterPlus class to highlight Dart code:
import 'package:flutter/material.dart';
import 'package:syntax_highlighter_plus/syntax_highlighter_plus.dart';
class HighlightedText extends StatelessWidget {
const HighlightedText({super.key});
@override
Widget build(BuildContext context) {
final syntaxHighlighter = SyntaxHighlighterPlus(theme: 'github-dark');
final highlightFuture = syntaxHighlighter.highlight('dart', 'print("Hello, World!");');
return FutureBuilder<TextSpan>(
future: highlightFuture,
builder: (context, snapshot) {
if (snapshot.hasError) {
return Center(child: Text('Error: ${snapshot.error}'));
}
final span = snapshot.data ?? const TextSpan(text: 'print("Hello, World!");');
return SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: SelectableText.rich(
span,
style: const TextStyle(fontFamily: 'monospace', height: 1.6),
),
);
},
);
}
}
highlight accepts any supported language id or alias
(SyntaxHighlighterPlus.supportedLanguages) and throws an ArgumentError
for unknown tags — catch it to fall back to plain text for unrecognized
markdown fence tags.
To style the surrounding widget (e.g. the code block's background), use the parsed theme:
final theme = await syntaxHighlighter.themeData;
// theme.background, theme.foreground, theme.brightness
Architecture #
assets/grammars/*.json.zst(zstd-compressed TextMate grammars) are embedded into the native library at build time and interpreted by a Rust tokenizer (rust/src/textmate/) using the onig crate. Grammars are decompressed on first use; parsed grammars and compiled regexes are cached lazily per process.- Tokens come back as
(start, end, scopes)with UTF-16 offsets, ready to index Dart strings. assets/themes/*.json(VS Code themes) are parsed in Dart; scope-selector matching maps each token's scope stack to aTextStyle, and adjacent runs merge into a compactTextSpantree.