Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(72)

Side by Side Diff: observatory_pub_packages/html5lib/dom_parsing.dart

Issue 816693004: Add observatory_pub_packages snapshot to third_party (Closed) Base URL: http://dart.googlecode.com/svn/third_party/
Patch Set: Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 /// This library contains extra APIs that aren't in the DOM, but are useful
2 /// when interacting with the parse tree.
3 library dom_parsing;
4
5 import 'dom.dart';
6 import 'src/constants.dart' show rcdataElements;
7
8 /// A simple tree visitor for the DOM nodes.
9 class TreeVisitor {
10 visit(Node node) {
11 switch (node.nodeType) {
12 case Node.ELEMENT_NODE: return visitElement(node);
13 case Node.TEXT_NODE: return visitText(node);
14 case Node.COMMENT_NODE: return visitComment(node);
15 case Node.DOCUMENT_FRAGMENT_NODE: return visitDocumentFragment(node);
16 case Node.DOCUMENT_NODE: return visitDocument(node);
17 case Node.DOCUMENT_TYPE_NODE: return visitDocumentType(node);
18 default: throw new UnsupportedError('DOM node type ${node.nodeType}');
19 }
20 }
21
22 visitChildren(Node node) {
23 // Allow for mutations (remove works) while iterating.
24 for (var child in node.nodes.toList()) visit(child);
25 }
26
27 /// The fallback handler if the more specific visit method hasn't been
28 /// overriden. Only use this from a subclass of [TreeVisitor], otherwise
29 /// call [visit] instead.
30 visitNodeFallback(Node node) => visitChildren(node);
31
32 visitDocument(Document node) => visitNodeFallback(node);
33
34 visitDocumentType(DocumentType node) => visitNodeFallback(node);
35
36 visitText(Text node) => visitNodeFallback(node);
37
38 // TODO(jmesserly): visit attributes.
39 visitElement(Element node) => visitNodeFallback(node);
40
41 visitComment(Comment node) => visitNodeFallback(node);
42
43 visitDocumentFragment(DocumentFragment node) => visitNodeFallback(node);
44 }
45
46 /// Converts the DOM tree into an HTML string with code markup suitable for
47 /// displaying the HTML's source code with CSS colors for different parts of the
48 /// markup. See also [CodeMarkupVisitor].
49 String htmlToCodeMarkup(Node node) {
50 return (new CodeMarkupVisitor()..visit(node)).toString();
51 }
52
53 /// Converts the DOM tree into an HTML string with code markup suitable for
54 /// displaying the HTML's source code with CSS colors for different parts of the
55 /// markup. See also [htmlToCodeMarkup].
56 class CodeMarkupVisitor extends TreeVisitor {
57 final StringBuffer _str;
58
59 CodeMarkupVisitor() : _str = new StringBuffer();
60
61 String toString() => _str.toString();
62
63 visitDocument(Document node) {
64 _str.write("<pre>");
65 visitChildren(node);
66 _str.write("</pre>");
67 }
68
69 visitDocumentType(DocumentType node) {
70 _str.write('<code class="markup doctype">&lt;!DOCTYPE ${node.name}>'
71 '</code>');
72 }
73
74 visitText(Text node) {
75 writeTextNodeAsHtml(_str, node);
76 }
77
78 visitElement(Element node) {
79 final tag = node.localName;
80 _str.write('&lt;<code class="markup element-name">$tag</code>');
81 if (node.attributes.length > 0) {
82 node.attributes.forEach((key, v) {
83 v = htmlSerializeEscape(v, attributeMode: true);
84 _str.write(' <code class="markup attribute-name">$key</code>'
85 '=<code class="markup attribute-value">"$v"</code>');
86 });
87 }
88 if (node.nodes.length > 0) {
89 _str.write(">");
90 visitChildren(node);
91 } else if (isVoidElement(tag)) {
92 _str.write(">");
93 return;
94 }
95 _str.write(
96 '&lt;/<code class="markup element-name">$tag</code>>');
97 }
98
99 visitComment(Comment node) {
100 var data = htmlSerializeEscape(node.data);
101 _str.write('<code class="markup comment">&lt;!--${data}--></code>');
102 }
103 }
104
105
106 // TODO(jmesserly): reconcile this with dart:web htmlEscape.
107 // This one might be more useful, as it is HTML5 spec compliant.
108 /// Escapes [text] for use in the
109 /// [HTML fragment serialization algorithm][1]. In particular, as described
110 /// in the [specification][2]:
111 ///
112 /// - Replace any occurrence of the `&` character by the string `&amp;`.
113 /// - Replace any occurrences of the U+00A0 NO-BREAK SPACE character by the
114 /// string `&nbsp;`.
115 /// - If the algorithm was invoked in [attributeMode], replace any occurrences
116 /// of the `"` character by the string `&quot;`.
117 /// - If the algorithm was not invoked in [attributeMode], replace any
118 /// occurrences of the `<` character by the string `&lt;`, and any occurrences
119 /// of the `>` character by the string `&gt;`.
120 ///
121 /// [1]: http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.htm l#serializing-html-fragments
122 /// [2]: http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.htm l#escapingString
123 String htmlSerializeEscape(String text, {bool attributeMode: false}) {
124 // TODO(jmesserly): is it faster to build up a list of codepoints?
125 // StringBuffer seems cleaner assuming Dart can unbox 1-char strings.
126 StringBuffer result = null;
127 for (int i = 0; i < text.length; i++) {
128 var ch = text[i];
129 String replace = null;
130 switch (ch) {
131 case '&': replace = '&amp;'; break;
132 case '\u00A0'/*NO-BREAK SPACE*/: replace = '&nbsp;'; break;
133 case '"': if (attributeMode) replace = '&quot;'; break;
134 case '<': if (!attributeMode) replace = '&lt;'; break;
135 case '>': if (!attributeMode) replace = '&gt;'; break;
136 }
137 if (replace != null) {
138 if (result == null) result = new StringBuffer(text.substring(0, i));
139 result.write(replace);
140 } else if (result != null) {
141 result.write(ch);
142 }
143 }
144
145 return result != null ? result.toString() : text;
146 }
147
148
149 /// Returns true if this tag name is a void element.
150 /// This method is useful to a pretty printer, because void elements must not
151 /// have an end tag.
152 /// See also: <http://dev.w3.org/html5/markup/syntax.html#void-elements>.
153 bool isVoidElement(String tagName) {
154 switch (tagName) {
155 case "area": case "base": case "br": case "col": case "command":
156 case "embed": case "hr": case "img": case "input": case "keygen":
157 case "link": case "meta": case "param": case "source": case "track":
158 case "wbr":
159 return true;
160 }
161 return false;
162 }
163
164 /// Serialize text node according to:
165 /// <http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#ht ml-fragment-serialization-algorithm>
166 void writeTextNodeAsHtml(StringBuffer str, Text node) {
167 // Don't escape text for certain elements, notably <script>.
168 final parent = node.parentNode;
169 if (parent is Element) {
170 var tag = parent.localName;
171 if (rcdataElements.contains(tag) || tag == 'plaintext') {
172 str.write(node.data);
173 return;
174 }
175 }
176 str.write(htmlSerializeEscape(node.data));
177 }
OLDNEW
« no previous file with comments | « observatory_pub_packages/html5lib/dom.dart ('k') | observatory_pub_packages/html5lib/parser.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698