flutter_md - Markdown Parser and Renderer for Flutter
A high-performance, lightweight Markdown parser and renderer specifically designed for Flutter applications. Perfect for displaying formatted text from AI assistants like ChatGPT, Gemini, and other LLMs.
🌟 Features
- 🚀 High Performance: Optimized parsing with minimal memory footprint
- 🎨 Fully Customizable: Theme-based styling with complete control over appearance
- 📱 Flutter Native: Built from the ground up for Flutter with custom render objects
- 🔗 Interactive Elements: Clickable links with customizable tap handlers
- 🌐 Cross Platform: Works on all Flutter-supported platforms
- 📝 Rich Syntax Support: Comprehensive Markdown syntax coverage
- 🎯 AI-Optimized: Specifically designed for AI-generated content display
- 🔧 Extensible: Easy to extend with custom block and span renderers
📋 Supported Markdown Syntax
Text Formatting
- Bold:
**text**
or__text__
- Italic:
*text*
or_text_
Strikethrough:~~text~~
Inline code
:`code`
- ==Highlight==:
==text==
- ||Spoiler||:
||text||
Headers
# H1 Header
## H2 Header
### H3 Header
#### H4 Header
##### H5 Header
###### H6 Header
Lists
- Unordered list item
- Another item
- Nested item
- Deep nested item
1. Ordered list item
2. Another numbered item
1. Nested numbered item
2. Another nested item
Blockquotes
> This is a blockquote
> It can span multiple lines
>
> And have multiple paragraphs
Code Blocks
```dart
void main() {
print('Hello, Markdown!');
}
```
Tables
| Header 1 | Header 2 | Header 3 |
| -------- | -------- | -------- |
| Cell 1 | Cell 2 | Cell 3 |
| **Bold** | _Italic_ | `Code` |
Links and Images
[Link text](https://example.com)

Images currently not displayed!
Horizontal Rules
---
🚀 Quick Start
Installation
Add this to your package's pubspec.yaml
file:
dependencies:
flutter_md: ^x.x.x # Replace with the latest version
Then run:
flutter pub get
🎨 Customization
Theme Configuration
MarkdownTheme(
data: MarkdownThemeData(
textStyle: TextStyle(fontSize: 16.0, color: Colors.black87),
h1Style: TextStyle(
fontSize: 24.0,
fontWeight: FontWeight.bold,
color: Colors.blue,
),
h2Style: TextStyle(
fontSize: 22.0,
fontWeight: FontWeight.bold,
color: Colors.blueGrey,
),
quoteStyle: TextStyle(
fontSize: 14.0,
fontStyle: FontStyle.italic,
color: Colors.grey[600],
),
// Handle link taps
onLinkTap: (title, url) {
print('Tapped link: $title -> $url');
// Launch URL or navigate
},
// Filter blocks (e.g., exclude images)
blockFilter: (block) => block is! MD$Image,
// Filter spans (e.g., exclude certain styles)
spanFilter: (span) => !span.style.contains(MD$Style.spoiler),
),
child: MarkdownWidget(
markdown: yourMarkdown,
),
)
Or you can use the MarkdownThemeData.mergeTheme(Theme.of(context))
factory to create a theme that inherits from the application's theme.
This approach allows you to easily support both light and dark themes, and keeps your markdown styling consistent with the rest of your application.
Custom Block Painters
For advanced customization, you can provide custom block painters:
MarkdownThemeData(
builder: (block, theme) {
if (block is MD$Code && block.language == 'dart') {
// Return custom painter for Dart code blocks
return CustomDartCodePainter(block: block, theme: theme);
}
return null; // Use default painter
},
)
Performance Optimization
For large markdown documents or frequently changing content:
class MyWidget extends StatefulWidget {
@override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
late final Markdown _markdown;
@override
void initState() {
super.initState();
// Parse markdown once during initialization
_markdown = Markdown.fromString(yourMarkdownString);
}
@override
Widget build(BuildContext context) {
return MarkdownWidget(markdown: _markdown);
}
}
📊 Performance
- Parsing: ~300 us for typical AI responses, 15x times faster than
markdown
package - Rendering: 120 FPS smooth scrolling for chat-like interfaces
- Memory: Minimal memory footprint with efficient span filtering
🔧 Advanced Features
Custom Styles
// Access individual style components
final span = MD$Span(
text: 'Custom text',
style: MD$Style.bold | MD$Style.italic, // Combine styles
);
// Check for specific styles
if (span.style.contains(MD$Style.link)) {
// Handle link styling
}
Block Filtering
MarkdownThemeData(
blockFilter: (block) {
// Only show paragraphs and headers
return block is MD$Paragraph || block is MD$Heading;
},
)
Span Filtering
MarkdownThemeData(
spanFilter: (span) {
// Exclude images and spoilers
return !span.style.contains(MD$Style.image) &&
!span.style.contains(MD$Style.spoiler);
},
)
📱 Platform Support
- ✅ Android
- ✅ iOS
- ✅ Web
- ✅ Windows
- ✅ macOS
- ✅ Linux
🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
Development Setup
git clone https://github.com/DoctorinaAI/md.git md
cd md
flutter pub get
flutter test
Running the Example
cd example
flutter run
📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
🔗 Links
💡 Why Choose md?
Unlike other Markdown packages that rely on HTML rendering or web views, flutter_md
is built specifically for Flutter using custom render objects. This provides:
- Better Performance: No HTML parsing or web view overhead
- Native Feel: Fully integrated with Flutter's rendering pipeline
- Customization: Complete control over styling and behavior
- Reliability: Consistent rendering across all platforms
- Small Size: Minimal package size with no external dependencies
Perfect for chat applications, documentation viewers, note-taking apps, and any Flutter application that needs to display rich formatted text from AI assistants or user input.