flutter_md 0.2.0
flutter_md: ^0.2.0 copied to clipboard
Markdown library written in Dart. It can parse and display Markdown.
0.2.0 #
Upgrading from 0.0.x? See the migration guide. 0.2.x is almost entirely backward compatible — the only required code change is a new
alertbranch for directMD$Block.map/switchcallers.
- ADDED: Opt-in, dependency-free syntax highlighting for fenced code blocks
(65+ languages, GitHub light/dark themes). Assign a
SyntaxHighlighterto the newMarkdownThemeData.highlighterfield; the default (unset) renders code as plain monospace, so existing usage is unchanged. New public API onpackage:flutter_md/highlight.dart:SyntaxHighlighter,MarkdownHighlighter,CodeHighlightTheme,Grammar,GrammarToken,compileHighlightPattern(SyntaxHighlighter/CodeHighlightThemeare also re-exported from the main entrypoint). Each language is its own library (package:flutter_md/highlight/<lang>.dart, e.g.HighlightDart.grammar) with no central registry, so importing one never references the others and unused grammars tree-shake away — a Dart-only app adds ~0 beyond the engine; all 65 add ~62 KB gzipped.HighlightThemes.githubDark/githubLight(highlight/themes.dart) provide ready themes;allHighlightLanguages(highlight/all.dart) is a convenience registry of every grammar for demos/tooling (it references all languages, so unused ones can no longer tree-shake away). The highlighter only partitions text — never edits it — so selection and copy stay aligned. Grammars are generated bytool/highlight_codegen(adapted from Prism, MIT). - ADDED: Cross-block and cross-widget text selection. A
MarkdownSelectionControlleranchors the selection on the immutable model, so it spans multiple blocks and multipleMarkdownWidgets and survives list disposal (e.g. chat scrolling). New public API:MarkdownSelectionController,MarkdownSelectionScope,MarkdownSelectionGroup,MarkdownPosition,MarkdownSelection,MarkdownDocumentRef,MarkdownSelectedContent(+ document/block),MarkdownSelectionFormatter/MarkdownPlainTextFormatter/MarkdownMarkupFormatter,MarkdownReconciliationPolicy,MarkdownSelectionSurface,markdownBlockRenderedText, andSelectableBlockPainter/SelectableTextBlock. - ADDED:
StreamingMarkdownParser, an incremental parser for streaming sources such as LLM token output. It freezes completed blocks (a block ends at a blank line, outside any open code fence) so only the still-growing tail is re-parsed as tokens arrive — turning theO(N²)cost of re-parsing the whole buffer on every token into roughlyO(tail)(3–14× faster on a full message stream inbenchmark/streaming_benchmark.dart).parser.add(chunk)returns the growingMarkdown, always identical block-for-block toMarkdown.fromString(everythingSoFar), and aStream<String>.toMarkdown()extension wires it into a stream transform. Pass a configuredMarkdownDecoder(e.g.inlineMath: true) to matchMarkdown.fromString. The batchMarkdownDecoderhot path is byte-for-byte unchanged. - ADDED:
MarkdownMarkupFormatter, a built-in "Copy as Markdown" formatter. Pass it togetText()(or setcontroller.formatter) to reconstruct Markdown structure on copy — heading#s, nested list markers with task checkboxes, blockquote/alert>prefixes, fenced code and pipe tables — for blocks the selection covers in full; partially-selected boundary blocks fall back to the plain sliced text so nothing outside the selection is emitted. The default copy behaviour is unchanged (MarkdownPlainTextFormatter). - ADDED:
MarkdownWidgetgains optionaldocumentIdandcontrollerparameters (resolved from the ambient scope). Backward compatible: a widget with nodocumentIdis inert. - ADDED: Lists and tables are now interactively selectable. A new
MultiPainterSelectablemixin (+SelectableFragment) maps pointer positions and highlight boxes across the manyTextPainters of a list's items or a table's cells, so a drag can start or end inside a list item or table cell and the copied text keeps the\n/\tseparators ofmarkdownBlockRenderedText. - ADDED: Keyboard shortcuts and a context toolbar on
MarkdownSelectionScope, mirroringSelectableRegion/SelectableText. When focused:Ctrl/Cmd+Ccopies,Ctrl/Cmd+Aselects all,Shift+arrows extend by character / word / line / document (and vertically by geometry),Escclears. Right-click (desktop) / long-press (mobile) shows an adaptive Copy / Select-all toolbar. The scope is now aStatefulWidgetwith a publicMarkdownSelectionScopeState(copySelection/selectAll/clearSelection/showToolbar/hideToolbar/contextMenuButtonItems/contextMenuAnchors). New customization params:focusNode,enabled,selectionColor,contextMenuBuilder,magnifierConfiguration,selectionControls,onSelectionChanged. New controller ops:selectionColor,globalSelectionRects,moveSelectionEdgeToGlobal, and theextendSelectionBy*family;MarkdownPosition.copyWith. - ADDED: Native selection handles and a magnifier on touch platforms,
driven by Flutter's
SelectionOverlay. Selection endpoints pushLeaderLayers from the render objects so the handles follow the content as it scrolls (and across multipleMarkdownWidgets); dragging a handle adjusts the selection and shows the platform magnifier. Handles/magnifier respect the platform (selectionControls,magnifierConfiguration) and are absent on desktop, matchingSelectableText. New surface geometry:localSelectionRects,setSelectionHandleLayers,repaintSelection, andMarkdownSelectionController.selectionHandleEndpoints/MarkdownHandleEndpoints. - ADDED: Word- and block-granular selection gestures. Double-click/tap
selects the word under the pointer, triple-click/tap selects the whole block,
a single click collapses (clears) the selection, and
Shift-click extends it. Dragging after a double/triple click keeps word/block granularity; a touch long-press grabs the whole word (then extends by word), and a touch double-tap selects the word and pops the toolbar. Word boundaries use the platform word segmentation (TextPainter.getWordBoundary), so double-click keeps intra-word punctuation like apostrophes (can't). New controller ops:selectWordAtGlobal,selectBlockAtGlobal,wordSelectionAt,blockSelectionAt,extendSelectionGranular, andwordRangeIn; new surface geometryMarkdownSelectionSurface.wordBoundaryForGlobal. - ADDED: Mouse cursor feedback — a
MarkdownWidgetshows the click (hand) cursor over actionable links, the text (I-beam) cursor while it participates in a selection controller, and otherwise the default cursor. - CHANGED:
MarkdownWidget's render object now draws the selection highlight outside the cached contentPictureand becomes a repaint boundary when selectable, so selection/drag repaints do not rebuild the glyph cache. The highlight color is now customizable via the controller / scope. The highlight is painted on top of (rather than beneath) the glyphs, so a translucent selection stays visible over opaque backgrounds — code fences,inline code, and==marked==spans. - EXAMPLE: Reworked the demo tabs — a longer, richer chat (tables, code, nested/task lists, alerts, math, token-by-token streaming with a typing indicator, Select-all/Clear) and a Selection tab that spans every block type.
0.1.0 #
- ADDED: GitHub-style alert blocks (
> [!NOTE],> [!TIP],> [!IMPORTANT],> [!WARNING],> [!CAUTION]) via the newMD$Alertblock andMD$AlertType. - ADDED: GitHub task-list items (
- [ ]/- [x]) viaMD$ListItem.checkedandMD$ListItem.isTask, rendered with a checkbox. - ADDED: Table column alignment (
:---,:--:,---:) captured onMD$Table.alignmentsand applied when rendering. - ADDED:
linkStyleonMarkdownThemeDatato customize link text styling (thanks @inamhusain, #22). - ADDED: Per-type alert accent colors via
MarkdownThemeData.alertColorsandalertColorFor. - ADDED: Opt-in
$...$inline LaTeX math conversion to Unicode, disabled by default. Enable withMarkdownDecoder(inlineMath: true)orMarkdown.fromString(text, inlineMath: true). Supports LaTeX commands (\alpha,\rightarrow, ...), superscripts/subscripts (x^2,H_2O,x^{10}), is code-span and code-block safe, and preserves currency ($5). The command table is configurable viamathReplacements(extend the exportedkMarkdownMathCommands). Originally proposed in #21 by @ibragimov05. - FIXED:
\$is now a recognized backslash escape, producing a literal dollar sign (and opting a$...$run out of math conversion). - CHANGED: Thematic breaks now support
***and___(and spaced variants like- - -), and no longer greedily consume text after---. - CHANGED:
~~~fenced code blocks are now recognized in addition to```. - FIXED: Emphasis no longer leaks to the end of the line for stray or
unterminated markers (e.g.
5 * 6 = 30,**bold never closed). - FIXED: Intraword underscores are no longer treated as emphasis
(e.g.
snake_case,object_idare preserved). - FIXED: ATX headings require a space after
#;#hashtagand 7+#are no longer headings, and trailing#sequences are stripped. - FIXED: Emphasis surrounding a link/image is now merged onto the link span.
- FIXED: Link/image targets support
<url>and single-quoted titles. - FIXED:
MarkdownThemeData.copyWithno longer dropsbuilderandonLinkTap. - BREAKING:
MD$Block.map/maybeMapgained analertbranch for the newMD$Alertblock type. - PERFORMANCE: Rewrote the parser hot path — a single-span fast path for
plain text, first-code-unit guards that keep regexes off paragraph lines,
hand-rolled list-line and link-target parsing (removing per-line / per-link
RegExpallocation), lazy link-extraction gated on[, and a range-copy escape rebuild (no more per-character hash-set lookups). Together with math now being opt-in, the default parse path is roughly 45% faster across representative workloads (links −68%, lists −61%, escapes −68%). Output is byte-identical, guarded by a golden snapshot test. - TESTS: Added a golden characterization snapshot, a corner-case regression
suite, span-offset invariants, and unit tests for the node model, theme, and
widget; wired every test file into
test/unit_test.dartso CI runs the full suite (370+ tests, previously only a fraction ran).parser.dart,nodes.dart,markdown.dart,theme.dart, andwidget.dartare now at ~100% line coverage. - ADDED:
benchmark/parser_benchmark.dart(a multi-scenariobenchmark_harnesssuite) andbenchmark/compare.dart(a low-noise before/after comparison tool). - DOCS: Documented alerts, task lists, table alignment, thematic-break variants, and opt-in inline math in the README.
0.0.8 #
- CHANGED: New table render
- FIXED: Invalidate and relayout render object after system fonts changed.
0.0.7 #
- FIXED: Preserved indentation on line breaks within list items [#4].
- FIXED: Inline code no longer processes inner Markdown syntax [#10].
- CHANGED: Improved theme support.
- ADDED: Dark mode support in the example app.
0.0.6 #
- FIXED: Fixed escaping of special characters. [#6]
0.0.5 #
- FIXED: Fixed parsing url such as
[text](https://domain.com/path(with)brackets).
0.0.4 #
- CHANGED: Improved link tap handling.
0.0.3 #
- FIXED: Links inside lists now work correctly.
0.0.2 #
- ADDED: All field in
MarkdownThemeData()are now optional. - ADDED:
MarkdownThemeData{}.headingStyleFormethod to customize heading styles. - FIXED: Remove clipping for canvas. Fixes one line text trim at browsers.
- FIXED: Correctly apply styles to text in blocks.
0.0.1 #
- ADDED: Initial release with basic functionality.