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(Element element) {
final current = _tree.removeLast();
final type = element.type;
final attributes = element.attributes;
HtmlElement node;
if (_isCodeBlock(type)) {
final code = HtmlElement('code', current.children);
if (attributes['language'] != null) {
var language = attributes['language']!;
if (encodeHtml) {
language = language.toHtmlText();
}
code.attributes['class'] = 'language-$language';
}
node = HtmlElement('pre', [code]);
} else {
var tag = _htmlTagMap[type] ?? type;
if (_isHealine(type)) {
tag = 'h${attributes['level']}';
}
if (_isSelfClosing(element)) {
node = HtmlElement.empty(tag);
if (type == 'image') {
node.attributes.addAll({
'src': attributes['destination']!,
if (attributes['description'] != null)
'alt': attributes['description']!,
if (attributes['title'] != null) 'title': attributes['title']!,
});
}
} else {
node = HtmlElement(tag, current.children);
if (_isHealine(type)) {
node.generatedId = attributes['generatedId'];
} else if (type == 'orderedList' && attributes['start'] != null) {
node.attributes['start'] = attributes['start']!;
} else if (type == 'listItem' && attributes['taskListItem'] != null) {
final checkboxInput = HtmlElement.empty('input');
node.attributes['class'] = 'task-list-item';
checkboxInput.attributes.addAll({
'type': 'checkbox',
if (attributes['taskListItem'] == 'checked') 'checked': '',
});
// Add a whitespace between input and text.
// This whitespace should not be added in Markdown AST tree, because
// some output targets such as Flutter might not want this whitespace.
node.children?.insertAll(0, [checkboxInput, HtmlText(' ')]);
} else if (type == 'tableHeadCell' || type == 'tableBodyCell') {
if (attributes['textAlign'] != null) {
node.attributes['align'] = attributes['textAlign']!;
}
} else if (_isLink(type)) {
node.attributes.addAll({
if (attributes['destination'] != null)
'href': attributes['destination']!,
if (attributes['title'] != null) 'title': attributes['title']!,
});
if (attributes['text'] != null) {
node.children!
..clear()
..add(HtmlText(attributes['text']!));
}
} else if (type == 'footnote') {
final label = attributes['label'];
final link = HtmlElement('a', [
HtmlText(attributes['number']!)
], attributes: {
'href': '#fn:$label',
});
node.attributes.addAll({
'id': 'fnref:$label',
'class': 'footnote',
});
node.children!.add(link);
} else if (type == 'footnoteReference') {
final number = element.attributes['number'];
final label = attributes['label'];
// ignore the ones are not connected to footnote.
if (number == null) {
return;
}
final link = HtmlElement('a', [
HtmlText('↩')
], attributes: {
'class': 'footnote-reverse',
'href': '#fnref:$label',
});
node.attributes['id'] = 'fn:$label';
node.children!.add(link);
_footnoteReferences[number] = node;
// Do not write to tree.
return;
}
}
}
_lastVisitElement = type;
_tree.last.children.add(node);
}