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(
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['checked'] != 'false';
bullet = _buildCheckbox(val);
} else {
bullet = _buildBullet(_listIndents.last);
}
child = Row(
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,
),
Expanded(child: child)
],
);
}
} else if (tag == 'table') {
child = Table(
defaultColumnWidth: styleSheet.tableColumnWidth!,
defaultVerticalAlignment: TableCellVerticalAlignment.middle,
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 = DecoratedBox(
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;
if (builders.containsKey(tag)) {
final Widget? child =
builders[tag]!.visitElementAfter(element, styleSheet.styles[tag]);
if (child != null) {
current.children[0] = child;
}
} else if (tag == 'img') {
// create an image widget for this image
current.children.add(BuildImage(
element.attributes['src']!,
element.attributes['title'],
element.attributes['alt'],
imageBuilder,
imageDirectory,
_linkHandlers,
));
} else if (tag == 'br') {
current.children.add(_buildRichText(const TextSpan(text: '\n')));
} else if (tag == 'th' || tag == 'td') {
TextAlign? align;
final String? style = element.attributes['style'];
if (style == null) {
align = tag == 'th' ? styleSheet.tableHeadAlign : TextAlign.left;
} else {
final RegExp regExp = RegExp(r'text-align: (left|center|right)');
final Match match = regExp.matchAsPrefix(style)!;
switch (match[1]) {
case 'left':
align = TextAlign.left;
break;
case 'center':
align = TextAlign.center;
break;
case 'right':
align = TextAlign.right;
break;
}
}
final Widget child = _buildTableCell(
_mergeInlineChildren(current.children, align),
textAlign: align,
);
_tables.single.rows.last.children!.add(child);
} else if (tag == 'a') {
_linkHandlers.removeLast();
}
if (current.children.isNotEmpty) {
parent.children.addAll(current.children);
}
}
if (_currentBlockTag == tag) {
_currentBlockTag = null;
}
_lastTag = tag;
}