Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
3 changes: 2 additions & 1 deletion packages/flutter_markdown/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
## NEXT
## 0.7.5

* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4.
* Fixes some memory leaks.

## 0.7.4+3

Expand Down
77 changes: 58 additions & 19 deletions packages/flutter_markdown/lib/src/builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -346,16 +346,20 @@ class MarkdownBuilder implements md.NodeVisitor {
child = builders[_blocks.last.tag!]!
.visitText(text, styleSheet.styles[_blocks.last.tag!]);
} else if (_blocks.last.tag == 'pre') {
final ScrollController preScrollController = ScrollController();
child = Scrollbar(
controller: preScrollController,
child: SingleChildScrollView(
controller: preScrollController,
scrollDirection: Axis.horizontal,
padding: styleSheet.codeblockPadding,
child: _buildRichText(delegate.formatText(styleSheet, text.text)),
),
);
child = _ScrollControllerBuilder(
builder: (BuildContext context, ScrollController preScrollController,
Widget? child) {
return Scrollbar(
controller: preScrollController,
child: SingleChildScrollView(
controller: preScrollController,
scrollDirection: Axis.horizontal,
padding: styleSheet.codeblockPadding,
child: child,
),
);
},
child: _buildRichText(delegate.formatText(styleSheet, text.text)));
} else {
child = _buildRichText(
TextSpan(
Expand Down Expand Up @@ -448,15 +452,20 @@ class MarkdownBuilder implements md.NodeVisitor {
}
} else if (tag == 'table') {
if (styleSheet.tableColumnWidth is FixedColumnWidth) {
final ScrollController tableScrollController = ScrollController();
child = Scrollbar(
controller: tableScrollController,
child: SingleChildScrollView(
controller: tableScrollController,
scrollDirection: Axis.horizontal,
padding: styleSheet.tablePadding,
child: _buildTable(),
),
child = _ScrollControllerBuilder(
builder: (BuildContext context,
ScrollController tableScrollController, Widget? child) {
return Scrollbar(
controller: tableScrollController,
child: SingleChildScrollView(
controller: tableScrollController,
scrollDirection: Axis.horizontal,
padding: styleSheet.tablePadding,
child: child,
),
);
},
child: _buildTable(),
);
} else {
child = _buildTable();
Expand Down Expand Up @@ -1017,3 +1026,33 @@ class MarkdownBuilder implements md.NodeVisitor {
}
}
}

class _ScrollControllerBuilder extends StatefulWidget {
const _ScrollControllerBuilder({
required this.builder,
this.child,
});

final ValueWidgetBuilder<ScrollController> builder;

final Widget? child;

@override
State<_ScrollControllerBuilder> createState() =>
_ScrollControllerBuilderState();
}

class _ScrollControllerBuilderState extends State<_ScrollControllerBuilder> {
final ScrollController _controller = ScrollController();

@override
void dispose() {
_controller.dispose();
super.dispose();
}

@override
Widget build(BuildContext context) {
return widget.builder(context, _controller, widget.child);
}
}
2 changes: 1 addition & 1 deletion packages/flutter_markdown/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ description: A Markdown renderer for Flutter. Create rich text output,
formatted with simple Markdown tags.
repository: https://github.com/flutter/packages/tree/main/packages/flutter_markdown
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+flutter_markdown%22
version: 0.7.4+3
version: 0.7.5

environment:
sdk: ^3.4.0
Expand Down
39 changes: 36 additions & 3 deletions packages/flutter_markdown/test/custom_syntax_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -276,9 +276,14 @@ class WikilinkSyntax extends md.InlineSyntax {
class WikilinkBuilder extends MarkdownElementBuilder {
@override
Widget visitElementAfter(md.Element element, _) {
return Text.rich(TextSpan(
text: element.textContent,
recognizer: TapGestureRecognizer()..onTap = () {}));
final TapGestureRecognizer recognizer = TapGestureRecognizer()
..onTap = () {};
return _TapGestureRecognizerDisposer(
recognizer: recognizer,
child: Text.rich(
TextSpan(text: element.textContent, recognizer: recognizer),
),
);
}
}

Expand Down Expand Up @@ -460,3 +465,31 @@ class CustomTagBlockSyntax extends md.BlockSyntax {
return element;
}
}

class _TapGestureRecognizerDisposer extends StatefulWidget {
const _TapGestureRecognizerDisposer({
required this.child,
required this.recognizer,
});

final Widget child;
final TapGestureRecognizer recognizer;

@override
State<_TapGestureRecognizerDisposer> createState() =>
__TapGestureRecognizerDisposerState();
}

class __TapGestureRecognizerDisposerState
extends State<_TapGestureRecognizerDisposer> {
@override
void dispose() {
widget.recognizer.dispose();
super.dispose();
}

@override
Widget build(BuildContext context) {
return widget.child;
}
}
4 changes: 4 additions & 0 deletions packages/flutter_markdown/test/image_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ void defineTests() {
testWidgets(
'local files should be files on non-web',
(WidgetTester tester) async {
addTearDown(imageCache.clear);
const String data = '![alt](http.png)';
await tester.pumpWidget(
boilerplate(
Expand Down Expand Up @@ -131,6 +132,7 @@ void defineTests() {
'should work with resources',
(WidgetTester tester) async {
TestWidgetsFlutterBinding.ensureInitialized();
addTearDown(imageCache.clear);
const String data = '![alt](resource:assets/logo.png)';
await tester.pumpWidget(
boilerplate(
Expand Down Expand Up @@ -195,6 +197,7 @@ void defineTests() {
testWidgets(
'should show properly next to text',
(WidgetTester tester) async {
addTearDown(imageCache.clear);
const String data = 'Hello ![alt](img#50x50)';
await tester.pumpWidget(
boilerplate(
Expand Down Expand Up @@ -412,6 +415,7 @@ void defineTests() {
testWidgets(
'custom image builder',
(WidgetTester tester) async {
addTearDown(imageCache.clear);
const String data = '![alt](https://img.png)';
Widget builder(Uri uri, String? title, String? alt) =>
Image.asset('assets/logo.png');
Expand Down
3 changes: 3 additions & 0 deletions packages/flutter_markdown/test/link_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ void defineTests() {
testWidgets(
'multiple inline links with same content should not throw an exception',
(WidgetTester tester) async {
addTearDown(imageCache.clear);
//Arange
final Widget toBePumped = boilerplate(
Column(
Expand Down Expand Up @@ -1025,6 +1026,7 @@ void defineTests() {
// Example 525 from GFM.
'inline image link text',
(WidgetTester tester) async {
addTearDown(imageCache.clear);
const String data = '[![moon](moon.jpg)](/uri)';
MarkdownLink? linkTapResults;
await tester.pumpWidget(
Expand Down Expand Up @@ -1129,6 +1131,7 @@ void defineTests() {
// Example 528 from GFM.
'links cannot be nested in image linksinline image link text',
(WidgetTester tester) async {
addTearDown(imageCache.clear);
const String data = '![[[foo](uri1)](uri2)](uri3)';
MarkdownLink? linkTapResults;
await tester.pumpWidget(
Expand Down
2 changes: 2 additions & 0 deletions packages/flutter_markdown/test/padding_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ void defineTests() {
(WidgetTester tester) async {
const double paddingX = 10.0;

addTearDown(imageCache.clear);

await tester.pumpWidget(
boilerplate(
Markdown(
Expand Down
1 change: 1 addition & 0 deletions packages/flutter_markdown/test/scrollable_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ void defineTests() {
final ScrollController controller = ScrollController(
initialScrollOffset: 209.0,
);
addTearDown(controller.dispose);

await tester.pumpWidget(
boilerplate(
Expand Down
Loading