markdown_live 0.1.0
markdown_live: ^0.1.0 copied to clipboard
A WYSIWYG Markdown editor widget for Flutter. Type Markdown and see live-rendered bold, italic, headings, and more — without ever seeing raw syntax markers. Includes a customizable controller and toolbar.
markdown_live #
A WYSIWYG Markdown editor widget for Flutter. Type Markdown and see live-rendered bold, italic, headings, and more — without ever seeing raw syntax markers.
Features #
- ✅ True WYSIWYG — Users see formatted text, not raw Markdown
- ✅ Bold, Italic, Bold+Italic formatting
- ✅
Strikethroughandinline code - ✅ Headings (H1–H6)
- ✅ Links
- ✅ Syntax reveal — Markdown markers appear only when cursor is nearby
- ✅ Raw Markdown access —
controller.textalways returns valid Markdown - ✅ Built-in toolbar with customization support
- ✅ Custom toolbar support — build your own toolbar using controller methods
- ✅ Theming — light/dark themes with full customization via
copyWith - ✅ Zero dependencies — only depends on Flutter SDK
Installation #
Add to your pubspec.yaml:
dependencies:
markdown_live: ^0.1.0
Quick Start #
import 'package:markdown_live/markdown_live.dart';
// 1. Create a controller
final controller = MarkdownLiveController(
text: '# Hello **World**',
);
// 2. Use the editor widget
MarkdownLiveEditor(
controller: controller,
theme: MarkdownLiveTheme.light(),
)
// 3. Optionally add the built-in toolbar
MarkdownLiveToolbar(controller: controller)
// 4. Access raw Markdown anytime
print(controller.text); // # Hello **World**
Formatting API #
The controller provides methods for programmatic formatting:
// Toggle inline formatting on the current selection
controller.toggleBold(); // **text**
controller.toggleItalic(); // _text_
controller.toggleStrikethrough(); // ~~text~~
controller.toggleInlineCode(); // `text`
// Set heading level (0 = remove, 1-6 = heading level)
controller.setHeading(1); // # text
controller.setHeading(2); // ## text
// Insert a link
controller.insertLink('Flutter', 'https://flutter.cn');
// Result: [Flutter](https://flutter.cn)
// Check active formats at cursor position
Set<MarkdownType> formats = controller.activeFormats;
Custom Toolbar #
You can build your own toolbar using the controller methods:
Row(
children: [
IconButton(
icon: Icon(Icons.format_bold),
onPressed: () => controller.toggleBold(),
),
IconButton(
icon: Icon(Icons.format_italic),
onPressed: () => controller.toggleItalic(),
),
// ... more buttons
],
)
Or customize the built-in toolbar with a button builder:
MarkdownLiveToolbar(
controller: controller,
actions: [MarkdownAction.bold, MarkdownAction.italic],
buttonBuilder: (context, action, isActive, onPressed) {
return ElevatedButton(
onPressed: onPressed,
style: ElevatedButton.styleFrom(
backgroundColor: isActive ? Colors.blue : Colors.grey,
),
child: Text(action.name),
);
},
)
Theming #
// Use built-in themes
MarkdownLiveEditor(
controller: controller,
theme: MarkdownLiveTheme.light(),
)
// Customize with copyWith
MarkdownLiveEditor(
controller: controller,
theme: MarkdownLiveTheme.dark().copyWith(
boldStyle: const TextStyle(
fontWeight: FontWeight.w900,
color: Colors.amber,
),
heading1Style: const TextStyle(
fontSize: 36,
fontWeight: FontWeight.w800,
),
),
)
// Fully custom theme
MarkdownLiveEditor(
controller: controller,
theme: const MarkdownLiveTheme(
baseStyle: TextStyle(fontSize: 16, color: Colors.black),
boldStyle: TextStyle(fontWeight: FontWeight.bold),
// ... all other styles
),
)
How It Works #
The package uses a custom TextEditingController that overrides buildTextSpan() to parse Markdown and render styled TextSpans. Syntax characters (**, _, #, etc.) are rendered with near-zero font size — visually invisible but still present in the text buffer, so cursor positioning stays correct.
When the cursor is near a syntax marker, it "reveals" itself with a subtle style so the user can edit or delete it.
Supported Markdown Syntax #
| Syntax | Result |
|---|---|
**text** |
Bold |
*text* or _text_ |
Italic |
***text*** |
Bold+Italic |
~~text~~ |
|
`code` |
Inline Code |
# text |
Heading 1 |
## text |
Heading 2 |
### text — ###### text |
Heading 3–6 |
[text](url) |
Link |
Example #
See the example app for a complete working demo.
Contributing #
Contributions are welcome! Please open an issue or submit a pull request.