visitElementAfter method
Called when an Element has been reached, after its children have been visited.
Will not be called if visitElementBefore returns false
.
Implementation
@override
void visitElementAfter(md.Element element) {
final String tag = element.tag;
if (_isBlockTag(tag)) {
_addAnonymousBlockIfNeeded();
final _BlockElement current = _blocks.removeLast();
Widget child;
if (current.children.isNotEmpty) {
child = Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: fitContent
? CrossAxisAlignment.start
: CrossAxisAlignment.stretch,
children: current.children,
);
} else {
child = const SizedBox();
}
if (_isListTag(tag)) {
assert(_listIndents.isNotEmpty);
_listIndents.removeLast();
} else if (tag == 'li') {
if (_listIndents.isNotEmpty) {
if (element.children!.isEmpty) {
element.children!.add(md.Text(''));
}
Widget bullet;
final dynamic el = element.children![0];
if (el is md.Element && el.attributes['type'] == 'checkbox') {
final bool val = el.attributes.containsKey('checked');
bullet = _buildCheckbox(val);
} else {
bullet = _buildBullet(_listIndents.last);
}
child = Row(
mainAxisSize: fitContent ? MainAxisSize.min : MainAxisSize.max,
textBaseline: listItemCrossAxisAlignment ==
MarkdownListItemCrossAxisAlignment.start
? null
: TextBaseline.alphabetic,
crossAxisAlignment: listItemCrossAxisAlignment ==
MarkdownListItemCrossAxisAlignment.start
? CrossAxisAlignment.start
: CrossAxisAlignment.baseline,
children: <Widget>[
SizedBox(
width: styleSheet.listIndent! +
styleSheet.listBulletPadding!.left +
styleSheet.listBulletPadding!.right,
child: bullet,
),
Flexible(
fit: fitContent ? FlexFit.loose : FlexFit.tight,
child: child,
)
],
);
}
} else if (tag == 'table') {
child = Table(
defaultColumnWidth: styleSheet.tableColumnWidth!,
defaultVerticalAlignment: styleSheet.tableVerticalAlignment,
border: styleSheet.tableBorder,
children: _tables.removeLast().rows,
);
} else if (tag == 'blockquote') {
_isInBlockquote = false;
child = DecoratedBox(
decoration: styleSheet.blockquoteDecoration!,
child: Padding(
padding: styleSheet.blockquotePadding!,
child: child,
),
);
} else if (tag == 'pre') {
child = Container(
clipBehavior: Clip.hardEdge,
decoration: styleSheet.codeblockDecoration,
child: child,
);
} else if (tag == 'hr') {
child = Container(decoration: styleSheet.horizontalRuleDecoration);
}
_addBlockChild(child);
} else {
final _InlineElement current = _inlines.removeLast();
final _InlineElement parent = _inlines.last;
EdgeInsets padding = EdgeInsets.zero;
if (paddingBuilders.containsKey(tag)) {
padding = paddingBuilders[tag]!.getPadding();
}
if (builders.containsKey(tag)) {
final Widget? child = builders[tag]!.visitElementAfterWithContext(
delegate.context,
element,
styleSheet.styles[tag],
parent.style,
);
if (child != null) {
if (current.children.isEmpty) {
current.children.add(child);
} else {
current.children[0] = child;
}
}
} else if (tag == 'img') {
// create an image widget for this image
current.children.add(_buildPadding(
padding,
_buildImage(
element.attributes['src']!,
element.attributes['title'],
element.attributes['alt'],
),
));
} else if (tag == 'br') {
current.children.add(_buildRichText(const TextSpan(text: '\n')));
} else if (tag == 'th' || tag == 'td') {
TextAlign? align;
final String? alignAttribute = element.attributes['align'];
if (alignAttribute == null) {
align = tag == 'th' ? styleSheet.tableHeadAlign : TextAlign.left;
} else {
switch (alignAttribute) {
case 'left':
align = TextAlign.left;
case 'center':
align = TextAlign.center;
case 'right':
align = TextAlign.right;
}
}
final Widget child = _buildTableCell(
_mergeInlineChildren(current.children, align),
textAlign: align,
);
_tables.single.rows.last.children.add(child);
} else if (tag == 'a') {
_linkHandlers.removeLast();
} else if (tag == 'sup') {
final Widget c = current.children.last;
TextSpan? textSpan;
if (c is Text && c.textSpan is TextSpan) {
textSpan = c.textSpan! as TextSpan;
} else if (c is SelectableText && c.textSpan is TextSpan) {
textSpan = c.textSpan;
}
if (textSpan != null) {
final Widget richText = _buildRichText(
TextSpan(
recognizer: textSpan.recognizer,
text: element.textContent,
style: textSpan.style?.copyWith(
fontFeatures: <FontFeature>[
const FontFeature.enable('sups'),
],
),
),
);
current.children.removeLast();
current.children.add(richText);
}
}
if (current.children.isNotEmpty) {
parent.children.addAll(current.children);
}
}
if (_currentBlockTag == tag) {
_currentBlockTag = null;
}
_lastVisitedTag = tag;
}