-
Notifications
You must be signed in to change notification settings - Fork 28.9k
Description
Steps to reproduce
I'm using markdown
7.2.2 and flutter_markdown
0.7.3.
This minimal example crashes:
import 'package:flutter/material.dart';
import 'package:flutter_markdown/flutter_markdown.dart';
import 'package:markdown/markdown.dart' as md;
void main() {
runApp(MaterialApp(
home: Scaffold(
body: Markdown(
data: '''
> [!NOTE]
> this does not work
''',
extensionSet: md.ExtensionSet.gitHubWeb,
),
),
));
}
It throws a null pointer exception in
void _addParentInlineIfNeeded(String? tag) {
if (_inlines.isEmpty) {
_inlines.add(_InlineElement(
tag,
style: styleSheet.styles[tag!], <------ here
));
}
}
because the markdown builder cannot deal with the
<div class="markdown-alert markdown-alert-note">
<p class="markdown-alert-title">Note</p>
<p>this does not work</p>
</div>
generated by the markdown parser. It doesn't know the div
element and thinks that it is an inline element and looses track of the tag
and tries to lookup with null
(why does this method accept a String?
if the only use of that parameter requires a !
?).
Theoretically, you can add builders
to the Markdown
widget like this one:
class NoteBuilder extends MarkdownElementBuilder {
NoteBuilder();
@override
bool isBlockElement() => true;
@override
Widget? visitElementAfterWithContext(
BuildContext context,
md.Element element,
TextStyle? preferredStyle,
TextStyle? parentStyle,
) {
throw UnimplementedError();
}
}
However, the method to actually build a Widget
is never called because the MarkdownBuilder
class doesn't know about its configured builders in case of block elements. Those builders only work for inline elements and only the visitText
method is ever called and this obviously doesn't work here, even if I'd lie about a note being a block level element.
Expected results
visitElementAfterWithContext
should be called so that I can attempt to build UI for the div
.
It looks like the MarkdownBuilder
calls isBlockElement
for each passed MarkdownElementBuilder
, patching a global variable that "knows" wich elements are block-level elements and which are not (why is this list global? As nobody ever removes elements from that global list, a bug can occur if two different Markdown
widget has different kind of builders which try to register a builder called x
both as a block and as an inline x
but that's not the point here) but then, in visitElementAfter
there's just a long if/else if
list of well known elements and custom builders are completely ignored. Something like
if (builders.containsKey(tag) {
child = builders[tag]!.visitElementAfterWithContext(...);
}
is missing in the code as the last else
.
And if you're on it, please use modern Dart like
if (builders[tag] case final builder?) {
child = builder.visitElementAfterWithContext(...);
}
here and at other places.
However, even if you'd call the method, it still is broken, as the API doesn't allow me to create a container Widget
as I'd have to access to the element's children which have been already build recursively, I think. So, perhaps just owning the fact that custom builders are impossible would be the better fix. It would have saved me a couple of hours of debugging.
Or, have BlockBuilder
and InlineBuilder
instead, using them internally too, so that we can not only extend the MarkdownBuilder
with new builders but also override or customize existing builders like for example blockquote
.
Actual results
I'd like to extend the MarkdownBuilder
. Frankly, I don't care about the note syntax, I wanted to support a <center>
widget to center parts of a markdown document. Writing a BlockSyntax
subclass to introduce a center
element to the markdown Node
hierarchy is quite easy. However, you cannot make it work in Flutter.
Code sample
see above
Screenshots or Video
n/a
Logs
n/a
Flutter Doctor output
Doctor output
[✓] Flutter (Channel master, 3.24.0-1.0.pre.197, on macOS 14.5 23F79 darwin-x64, locale de-DE)
• Flutter version 3.24.0-1.0.pre.197 on channel master at /Users/sma/Work/flutter
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision 0bac2be379 (2 days ago), 2024-07-19 00:15:26 -0400
• Engine revision ea1e53a4e8
• Dart version 3.6.0 (build 3.6.0-55.0.dev)
• DevTools version 2.37.1
I'm using markdown
7.2.2 and flutter_markdown
0.7.3.