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

Side by Side Diff: pkg/third_party/html5lib/lib/src/treebuilder.dart

Issue 178843003: [html5lib] triple slash comment style (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: remove extra check Created 6 years, 9 months 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
1 /** Internals to the tree builders. */ 1 /// Internals to the tree builders.
2 library treebuilder; 2 library treebuilder;
3 3
4 import 'dart:collection'; 4 import 'dart:collection';
5 import 'package:html5lib/dom.dart'; 5 import 'package:html5lib/dom.dart';
6 import 'package:source_maps/span.dart' show FileSpan; 6 import 'package:source_maps/span.dart' show FileSpan;
7 import 'constants.dart'; 7 import 'constants.dart';
8 import 'list_proxy.dart'; 8 import 'list_proxy.dart';
9 import 'token.dart'; 9 import 'token.dart';
10 import 'utils.dart'; 10 import 'utils.dart';
11 11
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
59 } 59 }
60 return true; 60 return true;
61 } 61 }
62 62
63 63
64 bool _nodesEqual(Node node1, Node node2) { 64 bool _nodesEqual(Node node1, Node node2) {
65 return node1.nameTuple == node2.nameTuple && 65 return node1.nameTuple == node2.nameTuple &&
66 _mapEquals(node1.attributes, node2.attributes); 66 _mapEquals(node1.attributes, node2.attributes);
67 } 67 }
68 68
69 /** Basic treebuilder implementation. */ 69 /// Basic treebuilder implementation.
70 class TreeBuilder { 70 class TreeBuilder {
71 final String defaultNamespace; 71 final String defaultNamespace;
72 72
73 Document document; 73 Document document;
74 74
75 final openElements = <Node>[]; 75 final openElements = <Node>[];
76 76
77 final activeFormattingElements = new ActiveFormattingElements(); 77 final activeFormattingElements = new ActiveFormattingElements();
78 78
79 Node headPointer; 79 Node headPointer;
80 80
81 Node formPointer; 81 Node formPointer;
82 82
83 /** 83 /// Switch the function used to insert an element from the
84 * Switch the function used to insert an element from the 84 /// normal one to the misnested table one and back again
85 * normal one to the misnested table one and back again
86 */
87 bool insertFromTable; 85 bool insertFromTable;
88 86
89 TreeBuilder(bool namespaceHTMLElements) 87 TreeBuilder(bool namespaceHTMLElements)
90 : defaultNamespace = namespaceHTMLElements ? Namespaces.html : null { 88 : defaultNamespace = namespaceHTMLElements ? Namespaces.html : null {
91 reset(); 89 reset();
92 } 90 }
93 91
94 void reset() { 92 void reset() {
95 openElements.clear(); 93 openElements.clear();
96 activeFormattingElements.clear(); 94 activeFormattingElements.clear();
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
205 } 203 }
206 } 204 }
207 205
208 void clearActiveFormattingElements() { 206 void clearActiveFormattingElements() {
209 var entry = activeFormattingElements.removeLast(); 207 var entry = activeFormattingElements.removeLast();
210 while (activeFormattingElements.length > 0 && entry != Marker) { 208 while (activeFormattingElements.length > 0 && entry != Marker) {
211 entry = activeFormattingElements.removeLast(); 209 entry = activeFormattingElements.removeLast();
212 } 210 }
213 } 211 }
214 212
215 /** 213 /// Check if an element exists between the end of the active
216 * Check if an element exists between the end of the active 214 /// formatting elements and the last marker. If it does, return it, else
217 * formatting elements and the last marker. If it does, return it, else 215 /// return null.
218 * return null.
219 */
220 Node elementInActiveFormattingElements(String name) { 216 Node elementInActiveFormattingElements(String name) {
221 for (Node item in activeFormattingElements.reversed) { 217 for (Node item in activeFormattingElements.reversed) {
222 // Check for Marker first because if it's a Marker it doesn't have a 218 // Check for Marker first because if it's a Marker it doesn't have a
223 // name attribute. 219 // name attribute.
224 if (item == Marker) { 220 if (item == Marker) {
225 break; 221 break;
226 } else if (item.tagName == name) { 222 } else if (item.tagName == name) {
227 return item; 223 return item;
228 } 224 }
229 } 225 }
(...skipping 12 matching lines...) Expand all
242 document.nodes.add(doctype); 238 document.nodes.add(doctype);
243 } 239 }
244 240
245 void insertComment(StringToken token, [Node parent]) { 241 void insertComment(StringToken token, [Node parent]) {
246 if (parent == null) { 242 if (parent == null) {
247 parent = openElements.last; 243 parent = openElements.last;
248 } 244 }
249 parent.nodes.add(new Comment(token.data)..sourceSpan = token.span); 245 parent.nodes.add(new Comment(token.data)..sourceSpan = token.span);
250 } 246 }
251 247
252 /** Create an element but don't insert it anywhere */ 248 /// Create an element but don't insert it anywhere
253 Element createElement(StartTagToken token) { 249 Element createElement(StartTagToken token) {
254 var name = token.name; 250 var name = token.name;
255 var namespace = token.namespace; 251 var namespace = token.namespace;
256 if (namespace == null) namespace = defaultNamespace; 252 if (namespace == null) namespace = defaultNamespace;
257 var element = new Element(name, namespace) 253 var element = new Element(name, namespace)
258 ..attributes = token.data 254 ..attributes = token.data
259 ..sourceSpan = token.span; 255 ..sourceSpan = token.span;
260 return element; 256 return element;
261 } 257 }
262 258
263 Element insertElement(StartTagToken token) { 259 Element insertElement(StartTagToken token) {
264 if (insertFromTable) return insertElementTable(token); 260 if (insertFromTable) return insertElementTable(token);
265 return insertElementNormal(token); 261 return insertElementNormal(token);
266 } 262 }
267 263
268 Element insertElementNormal(StartTagToken token) { 264 Element insertElementNormal(StartTagToken token) {
269 var name = token.name; 265 var name = token.name;
270 var namespace = token.namespace; 266 var namespace = token.namespace;
271 if (namespace == null) namespace = defaultNamespace; 267 if (namespace == null) namespace = defaultNamespace;
272 var element = new Element(name, namespace) 268 var element = new Element(name, namespace)
273 ..attributes = token.data 269 ..attributes = token.data
274 ..sourceSpan = token.span; 270 ..sourceSpan = token.span;
275 openElements.last.nodes.add(element); 271 openElements.last.nodes.add(element);
276 openElements.add(element); 272 openElements.add(element);
277 return element; 273 return element;
278 } 274 }
279 275
280 Element insertElementTable(token) { 276 Element insertElementTable(token) {
281 /** Create an element and insert it into the tree */ 277 /// Create an element and insert it into the tree
282 var element = createElement(token); 278 var element = createElement(token);
283 if (!tableInsertModeElements.contains(openElements.last.tagName)) { 279 if (!tableInsertModeElements.contains(openElements.last.tagName)) {
284 return insertElementNormal(token); 280 return insertElementNormal(token);
285 } else { 281 } else {
286 // We should be in the InTable mode. This means we want to do 282 // We should be in the InTable mode. This means we want to do
287 // special magic element rearranging 283 // special magic element rearranging
288 var nodePos = getTableMisnestedNodePosition(); 284 var nodePos = getTableMisnestedNodePosition();
289 if (nodePos[1] == null) { 285 if (nodePos[1] == null) {
290 // TODO(jmesserly): I don't think this is reachable. If insertFromTable 286 // TODO(jmesserly): I don't think this is reachable. If insertFromTable
291 // is true, there will be a <table> element open, and it always has a 287 // is true, there will be a <table> element open, and it always has a
292 // parent pointer. 288 // parent pointer.
293 nodePos[0].nodes.add(element); 289 nodePos[0].nodes.add(element);
294 } else { 290 } else {
295 nodePos[0].insertBefore(element, nodePos[1]); 291 nodePos[0].insertBefore(element, nodePos[1]);
296 } 292 }
297 openElements.add(element); 293 openElements.add(element);
298 } 294 }
299 return element; 295 return element;
300 } 296 }
301 297
302 /** Insert text data. */ 298 /// Insert text data.
303 void insertText(String data, FileSpan span) { 299 void insertText(String data, FileSpan span) {
304 var parent = openElements.last; 300 var parent = openElements.last;
305 301
306 if (!insertFromTable || insertFromTable && 302 if (!insertFromTable || insertFromTable &&
307 !tableInsertModeElements.contains(openElements.last.tagName)) { 303 !tableInsertModeElements.contains(openElements.last.tagName)) {
308 _insertText(parent, data, span); 304 _insertText(parent, data, span);
309 } else { 305 } else {
310 // We should be in the InTable mode. This means we want to do 306 // We should be in the InTable mode. This means we want to do
311 // special magic element rearranging 307 // special magic element rearranging
312 var nodePos = getTableMisnestedNodePosition(); 308 var nodePos = getTableMisnestedNodePosition();
313 _insertText(nodePos[0], data, span, nodePos[1]); 309 _insertText(nodePos[0], data, span, nodePos[1]);
314 } 310 }
315 } 311 }
316 312
317 /** 313 /// Insert [data] as text in the current node, positioned before the
318 * Insert [data] as text in the current node, positioned before the 314 /// start of node [refNode] or to the end of the node's text.
319 * start of node [refNode] or to the end of the node's text.
320 */
321 static void _insertText(Node parent, String data, FileSpan span, 315 static void _insertText(Node parent, String data, FileSpan span,
322 [Element refNode]) { 316 [Element refNode]) {
323 var nodes = parent.nodes; 317 var nodes = parent.nodes;
324 if (refNode == null) { 318 if (refNode == null) {
325 if (nodes.length > 0 && nodes.last is Text) { 319 if (nodes.length > 0 && nodes.last is Text) {
326 Text last = nodes.last; 320 Text last = nodes.last;
327 last.data = '${last.data}$data'; 321 last.data = '${last.data}$data';
328 322
329 if (span != null) { 323 if (span != null) {
330 last.sourceSpan = span.file.span(last.sourceSpan.start.offset, 324 last.sourceSpan = span.file.span(last.sourceSpan.start.offset,
331 span.end.offset); 325 span.end.offset);
332 } 326 }
333 } else { 327 } else {
334 nodes.add(new Text(data)..sourceSpan = span); 328 nodes.add(new Text(data)..sourceSpan = span);
335 } 329 }
336 } else { 330 } else {
337 int index = nodes.indexOf(refNode); 331 int index = nodes.indexOf(refNode);
338 if (index > 0 && nodes[index - 1] is Text) { 332 if (index > 0 && nodes[index - 1] is Text) {
339 Text last = nodes[index - 1]; 333 Text last = nodes[index - 1];
340 last.data = '${last.data}$data'; 334 last.data = '${last.data}$data';
341 } else { 335 } else {
342 nodes.insert(index, new Text(data)..sourceSpan = span); 336 nodes.insert(index, new Text(data)..sourceSpan = span);
343 } 337 }
344 } 338 }
345 } 339 }
346 340
347 /** 341 /// Get the foster parent element, and sibling to insert before
348 * Get the foster parent element, and sibling to insert before 342 /// (or null) when inserting a misnested table node
349 * (or null) when inserting a misnested table node
350 */
351 List<Node> getTableMisnestedNodePosition() { 343 List<Node> getTableMisnestedNodePosition() {
352 // The foster parent element is the one which comes before the most 344 // The foster parent element is the one which comes before the most
353 // recently opened table element 345 // recently opened table element
354 // XXX - this is really inelegant 346 // XXX - this is really inelegant
355 Node lastTable = null; 347 Node lastTable = null;
356 Node fosterParent = null; 348 Node fosterParent = null;
357 var insertBefore = null; 349 var insertBefore = null;
358 for (Node elm in openElements.reversed) { 350 for (Node elm in openElements.reversed) {
359 if (elm.tagName == "table") { 351 if (elm.tagName == "table") {
360 lastTable = elm; 352 lastTable = elm;
(...skipping 20 matching lines...) Expand all
381 // XXX td, th and tr are not actually needed 373 // XXX td, th and tr are not actually needed
382 if (name != exclude && const ["dd", "dt", "li", "option", "optgroup", "p", 374 if (name != exclude && const ["dd", "dt", "li", "option", "optgroup", "p",
383 "rp", "rt"].contains(name)) { 375 "rp", "rt"].contains(name)) {
384 openElements.removeLast(); 376 openElements.removeLast();
385 // XXX This is not entirely what the specification says. We should 377 // XXX This is not entirely what the specification says. We should
386 // investigate it more closely. 378 // investigate it more closely.
387 generateImpliedEndTags(exclude); 379 generateImpliedEndTags(exclude);
388 } 380 }
389 } 381 }
390 382
391 /** Return the final tree. */ 383 /// Return the final tree.
392 Document getDocument() => document; 384 Document getDocument() => document;
393 385
394 /** Return the final fragment. */ 386 /// Return the final fragment.
395 DocumentFragment getFragment() { 387 DocumentFragment getFragment() {
396 //XXX assert innerHTML 388 //XXX assert innerHTML
397 var fragment = new DocumentFragment(); 389 var fragment = new DocumentFragment();
398 openElements[0].reparentChildren(fragment); 390 openElements[0].reparentChildren(fragment);
399 return fragment; 391 return fragment;
400 } 392 }
401 } 393 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698