/// This library contains extra APIs that aren't in the DOM, but are useful /// when interacting with the parse tree. library; import 'dom.dart'; import 'html_escape.dart'; import 'src/constants.dart' show rcdataElements; // Export a function which was previously declared here. export 'html_escape.dart'; /// A simple tree visitor for the DOM nodes. class TreeVisitor { void visit(Node node) { return switch (node.nodeType) { Node.ELEMENT_NODE => visitElement(node as Element), Node.TEXT_NODE => visitText(node as Text), Node.COMMENT_NODE => visitComment(node as Comment), Node.DOCUMENT_FRAGMENT_NODE => visitDocumentFragment(node as DocumentFragment), Node.DOCUMENT_NODE => visitDocument(node as Document), Node.DOCUMENT_TYPE_NODE => visitDocumentType(node as DocumentType), _ => throw UnsupportedError('DOM node type ${node.nodeType}') }; } void visitChildren(Node node) { // Allow for mutations (remove works) while iterating. for (var child in node.nodes.toList(growable: false)) { visit(child); } } /// The fallback handler if the more specific visit method hasn't been /// overriden. Only use this from a subclass of [TreeVisitor], otherwise /// call [visit] instead. void visitNodeFallback(Node node) => visitChildren(node); void visitDocument(Document node) => visitNodeFallback(node); void visitDocumentType(DocumentType node) => visitNodeFallback(node); void visitText(Text node) => visitNodeFallback(node); // TODO(jmesserly): visit attributes. void visitElement(Element node) => visitNodeFallback(node); void visitComment(Comment node) => visitNodeFallback(node); void visitDocumentFragment(DocumentFragment node) => visitNodeFallback(node); } /// Converts the DOM tree into an HTML string with code markup suitable for /// displaying the HTML's source code with CSS colors for different parts of the /// markup. See also [CodeMarkupVisitor]. String htmlToCodeMarkup(Node node) { return (CodeMarkupVisitor()..visit(node)).toString(); } /// Converts the DOM tree into an HTML string with code markup suitable for /// displaying the HTML's source code with CSS colors for different parts of the /// markup. See also [htmlToCodeMarkup]. class CodeMarkupVisitor extends TreeVisitor { final StringBuffer _str; CodeMarkupVisitor() : _str = StringBuffer(); @override String toString() => _str.toString(); @override void visitDocument(Document node) { _str.write('
');
visitChildren(node);
_str.write('');
}
@override
void visitDocumentType(DocumentType node) {
_str.write('<!DOCTYPE ${node.name}>'
'');
}
@override
void visitText(Text node) {
writeTextNodeAsHtml(_str, node);
}
@override
void visitElement(Element node) {
final tag = node.localName;
_str.write('<$tag');
if (node.attributes.isNotEmpty) {
node.attributes.forEach((key, v) {
v = htmlSerializeEscape(v, attributeMode: true);
_str.write(' $key'
'="$v"');
});
}
if (node.nodes.isNotEmpty) {
_str.write('>');
visitChildren(node);
} else if (isVoidElement(tag)) {
_str.write('>');
return;
}
_str.write('</$tag>');
}
@override
void visitComment(Comment node) {
final data = htmlSerializeEscape(node.data!);
_str.write('<!--$data-->');
}
}
/// Returns true if this tag name is a void element.
/// This method is useful to a pretty printer, because void elements must not
/// have an end tag.
/// See also: