Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
## 1.0.9

* Fixed custom inline `builders` (e.g. `a`) duplicating trailing text when the element had multiple children, such as link text containing a `_` or `*` delimiter that the parser splits into separate text nodes (#132)

**Thanks to our contributors:**
* [@Jess-Gabia](https://github.com/Jess-Gabia) for reporting the issue and identifying the fix (#132)
* [@amungi](https://github.com/amungi) for confirming the fix in production

## 1.0.8

* Fixed custom `builders` and `paddingBuilders` for the `hr` tag being ignored
Expand Down
12 changes: 7 additions & 5 deletions lib/src/builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -504,11 +504,13 @@ class MarkdownBuilder implements md.NodeVisitor {
parent.style,
);
if (child != null) {
if (current.children.isEmpty) {
current.children.add(child);
} else {
current.children[0] = child;
}
// The returned widget represents the entire element, so discard all
// existing inline children — replacing only children[0] leaves any
// siblings (e.g. link text split on a `_`/`*` delimiter) to leak
// through to the parent and render twice. See issue #132.
current.children
..clear()
..add(child);
}
} else if (tag == 'img') {
// create an image widget for this image
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ description: A Markdown renderer for Flutter. Create rich text output,
repository: https://github.com/foresightmobile/flutter_markdown_plus
issue_tracker: https://github.com/foresightmobile/flutter_markdown_plus/issues
documentation: https://github.com/foresightmobile/flutter_markdown_plus#readme
version: 1.0.8
version: 1.0.9

environment:
sdk: ^3.4.0
Expand Down
51 changes: 51 additions & 0 deletions test/custom_syntax_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,48 @@ void defineTests() {
expect(textWidget.data, 'foo');
},
);

testWidgets(
'inline builder replaces all children, not just the first (issue #132)',
(WidgetTester tester) async {
// The link text starts with an unpaired `_`, which the parser splits into
// multiple text nodes (`[Text("_"), Text("hello world")]`). A custom `a`
// builder returning a widget must replace *all* of them, otherwise the
// trailing "hello world" leaks through and renders twice.
await tester.pumpWidget(
boilerplate(
Markdown(
data: '[_hello world](https://example.com)',
builders: <String, MarkdownElementBuilder>{
'a': LinkTagBuilder(),
},
),
),
);

expect(find.text('LINK'), findsOneWidget);
expect(find.textContaining('hello world', findRichText: true), findsNothing);
},
);

testWidgets(
'inline builder replaces all children with a `*` delimiter (issue #132)',
(WidgetTester tester) async {
await tester.pumpWidget(
boilerplate(
Markdown(
data: '[*hello world](https://example.com)',
builders: <String, MarkdownElementBuilder>{
'a': LinkTagBuilder(),
},
),
),
);

expect(find.text('LINK'), findsOneWidget);
expect(find.textContaining('hello world', findRichText: true), findsNothing);
},
);
}

class SubscriptSyntax extends md.InlineSyntax {
Expand Down Expand Up @@ -371,6 +413,15 @@ class ImgBuilder extends MarkdownElementBuilder {
}
}

class LinkTagBuilder extends MarkdownElementBuilder {
@override
Widget visitElementAfter(md.Element element, TextStyle? preferredStyle) {
// Deliberately returns a marker that does not contain the link text, so a
// test can assert the original children were fully replaced.
return const Text('LINK');
}
}

class NoteBuilder extends MarkdownElementBuilder {
@override
Widget? visitText(md.Text text, TextStyle? preferredStyle) {
Expand Down
Loading