Skip to content

Commit bb247f7

Browse files
authored
[flutter_markdown] Allow for custom block element (#5815)
Fixes problem with adding custom block syntax. Issue: flutter/flutter#135848
1 parent da16269 commit bb247f7

File tree

5 files changed

+67
-2
lines changed

5 files changed

+67
-2
lines changed

packages/flutter_markdown/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## 0.6.22
2+
3+
* Introduces a new `MarkdownElementBuilder.isBlockElement()` method to specify if custom element
4+
is a block.
5+
16
## 0.6.21+1
27

38
* Adds `onSelectionChanged` to the constructors of `Markdown` and `MarkdownBody`.

packages/flutter_markdown/lib/src/builder.dart

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import '_functions_io.dart' if (dart.library.js_interop) '_functions_web.dart';
1010
import 'style_sheet.dart';
1111
import 'widget.dart';
1212

13-
const List<String> _kBlockTags = <String>[
13+
final List<String> _kBlockTags = <String>[
1414
'p',
1515
'h1',
1616
'h2',
@@ -190,6 +190,12 @@ class MarkdownBuilder implements md.NodeVisitor {
190190
_linkHandlers.clear();
191191
_isInBlockquote = false;
192192

193+
builders.forEach((String key, MarkdownElementBuilder value) {
194+
if (value.isBlockElement()) {
195+
_kBlockTags.add(key);
196+
}
197+
});
198+
193199
_blocks.add(_BlockElement(null));
194200

195201
for (final md.Node node in nodes) {

packages/flutter_markdown/lib/src/widget.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ abstract class SyntaxHighlighter {
7070

7171
/// An interface for an element builder.
7272
abstract class MarkdownElementBuilder {
73+
/// For block syntax has to return true.
74+
///
75+
/// By default returns false.
76+
bool isBlockElement() => false;
77+
7378
/// Called when an Element has been reached, before its children have been
7479
/// visited.
7580
void visitElementBefore(md.Element element) {}

packages/flutter_markdown/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ description: A Markdown renderer for Flutter. Create rich text output,
44
formatted with simple Markdown tags.
55
repository: https://github.com/flutter/packages/tree/main/packages/flutter_markdown
66
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+flutter_markdown%22
7-
version: 0.6.21+1
7+
version: 0.6.22
88

99
environment:
1010
sdk: ^3.3.0

packages/flutter_markdown/test/custom_syntax_test.dart

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,30 @@ void defineTests() {
3535
},
3636
);
3737

38+
testWidgets(
39+
'Custom block element',
40+
(WidgetTester tester) async {
41+
const String blockContent = 'note block';
42+
await tester.pumpWidget(
43+
boilerplate(
44+
Markdown(
45+
data: '[!NOTE] $blockContent',
46+
extensionSet: md.ExtensionSet.none,
47+
blockSyntaxes: <md.BlockSyntax>[NoteSyntax()],
48+
builders: <String, MarkdownElementBuilder>{
49+
'note': NoteBuilder(),
50+
},
51+
),
52+
),
53+
);
54+
final ColoredBox container =
55+
tester.widgetList(find.byType(ColoredBox)).first as ColoredBox;
56+
expect(container.color, Colors.red);
57+
expect(container.child, isInstanceOf<Text>());
58+
expect((container.child! as Text).data, blockContent);
59+
},
60+
);
61+
3862
testWidgets(
3963
'link for wikistyle',
4064
(WidgetTester tester) async {
@@ -331,3 +355,28 @@ class ImgBuilder extends MarkdownElementBuilder {
331355
return Text('foo', style: preferredStyle);
332356
}
333357
}
358+
359+
class NoteBuilder extends MarkdownElementBuilder {
360+
@override
361+
Widget? visitText(md.Text text, TextStyle? preferredStyle) {
362+
return ColoredBox(
363+
color: Colors.red, child: Text(text.text, style: preferredStyle));
364+
}
365+
366+
@override
367+
bool isBlockElement() {
368+
return true;
369+
}
370+
}
371+
372+
class NoteSyntax extends md.BlockSyntax {
373+
@override
374+
md.Node? parse(md.BlockParser parser) {
375+
final md.Line line = parser.current;
376+
parser.advance();
377+
return md.Element('note', <md.Node>[md.Text(line.content.substring(8))]);
378+
}
379+
380+
@override
381+
RegExp get pattern => RegExp(r'^\[!NOTE] ');
382+
}

0 commit comments

Comments
 (0)