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

Unified Diff: pkg/third_party/html5lib/lib/src/treebuilder.dart

Issue 814113004: Pull args, intl, logging, shelf, and source_maps out of the SDK. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Also csslib. 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « pkg/third_party/html5lib/lib/src/tokenizer.dart ('k') | pkg/third_party/html5lib/lib/src/utils.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/third_party/html5lib/lib/src/treebuilder.dart
diff --git a/pkg/third_party/html5lib/lib/src/treebuilder.dart b/pkg/third_party/html5lib/lib/src/treebuilder.dart
deleted file mode 100644
index 4b8dfc4255cb91848f112a999a557d639d9b1c6b..0000000000000000000000000000000000000000
--- a/pkg/third_party/html5lib/lib/src/treebuilder.dart
+++ /dev/null
@@ -1,394 +0,0 @@
-/// Internals to the tree builders.
-library treebuilder;
-
-import 'dart:collection';
-import 'package:html5lib/dom.dart';
-import 'package:html5lib/parser.dart' show getElementNameTuple;
-import 'package:source_span/source_span.dart';
-import 'constants.dart';
-import 'list_proxy.dart';
-import 'token.dart';
-import 'utils.dart';
-
-// The scope markers are inserted when entering object elements,
-// marquees, table cells, and table captions, and are used to prevent formatting
-// from "leaking" into tables, object elements, and marquees.
-const Node Marker = null;
-
-// TODO(jmesserly): this should extend ListBase<Element>, but my simple attempt
-// didn't work.
-class ActiveFormattingElements extends ListProxy<Element> {
- ActiveFormattingElements() : super();
-
- // Override the "add" method.
- // TODO(jmesserly): I'd rather not override this; can we do this in the
- // calling code instead?
- void add(Element node) {
- int equalCount = 0;
- if (node != Marker) {
- for (var element in reversed) {
- if (element == Marker) {
- break;
- }
- if (_nodesEqual(element, node)) {
- equalCount += 1;
- }
- if (equalCount == 3) {
- remove(element);
- break;
- }
- }
- }
- super.add(node);
- }
-}
-
-// TODO(jmesserly): this should exist in corelib...
-bool _mapEquals(Map a, Map b) {
- if (a.length != b.length) return false;
- if (a.length == 0) return true;
-
- for (var keyA in a.keys) {
- var valB = b[keyA];
- if (valB == null && !b.containsKey(keyA)) {
- return false;
- }
-
- if (a[keyA] != valB) {
- return false;
- }
- }
- return true;
-}
-
-
-bool _nodesEqual(Element node1, Element node2) {
- return getElementNameTuple(node1) == getElementNameTuple(node2) &&
- _mapEquals(node1.attributes, node2.attributes);
-}
-
-/// Basic treebuilder implementation.
-class TreeBuilder {
- final String defaultNamespace;
-
- Document document;
-
- final List<Element> openElements = <Element>[];
-
- final activeFormattingElements = new ActiveFormattingElements();
-
- Node headPointer;
-
- Node formPointer;
-
- /// Switch the function used to insert an element from the
- /// normal one to the misnested table one and back again
- bool insertFromTable;
-
- TreeBuilder(bool namespaceHTMLElements)
- : defaultNamespace = namespaceHTMLElements ? Namespaces.html : null {
- reset();
- }
-
- void reset() {
- openElements.clear();
- activeFormattingElements.clear();
-
- //XXX - rename these to headElement, formElement
- headPointer = null;
- formPointer = null;
-
- insertFromTable = false;
-
- document = new Document();
- }
-
- bool elementInScope(target, {String variant}) {
- //If we pass a node in we match that. if we pass a string
- //match any node with that name
- bool exactNode = target is Node;
-
- List listElements1 = scopingElements;
- List listElements2 = const [];
- bool invert = false;
- if (variant != null) {
- switch (variant) {
- case "button":
- listElements2 = const [const Pair(Namespaces.html, "button")];
- break;
- case "list":
- listElements2 = const [const Pair(Namespaces.html, "ol"),
- const Pair(Namespaces.html, "ul")];
- break;
- case "table":
- listElements1 = const [const Pair(Namespaces.html, "html"),
- const Pair(Namespaces.html, "table")];
- break;
- case "select":
- listElements1 = const [const Pair(Namespaces.html, "optgroup"),
- const Pair(Namespaces.html, "option")];
- invert = true;
- break;
- default:
- throw new StateError('We should never reach this point');
- }
- }
-
- for (var node in openElements.reversed) {
- if (!exactNode && node.localName == target ||
- exactNode && node == target) {
- return true;
- } else if (invert !=
- (listElements1.contains(getElementNameTuple(node)) ||
- listElements2.contains(getElementNameTuple(node)))) {
- return false;
- }
- }
-
- throw new StateError('We should never reach this point');
- }
-
- void reconstructActiveFormattingElements() {
- // Within this algorithm the order of steps described in the
- // specification is not quite the same as the order of steps in the
- // code. It should still do the same though.
-
- // Step 1: stop the algorithm when there's nothing to do.
- if (activeFormattingElements.length == 0) {
- return;
- }
-
- // Step 2 and step 3: we start with the last element. So i is -1.
- int i = activeFormattingElements.length - 1;
- var entry = activeFormattingElements[i];
- if (entry == Marker || openElements.contains(entry)) {
- return;
- }
-
- // Step 6
- while (entry != Marker && !openElements.contains(entry)) {
- if (i == 0) {
- //This will be reset to 0 below
- i = -1;
- break;
- }
- i -= 1;
- // Step 5: let entry be one earlier in the list.
- entry = activeFormattingElements[i];
- }
-
- while (true) {
- // Step 7
- i += 1;
-
- // Step 8
- entry = activeFormattingElements[i];
-
- // TODO(jmesserly): optimize this. No need to create a token.
- var cloneToken = new StartTagToken(
- entry.localName,
- namespace: entry.namespaceUri,
- data: new LinkedHashMap.from(entry.attributes))
- ..span = entry.sourceSpan;
-
- // Step 9
- var element = insertElement(cloneToken);
-
- // Step 10
- activeFormattingElements[i] = element;
-
- // Step 11
- if (element == activeFormattingElements.last) {
- break;
- }
- }
- }
-
- void clearActiveFormattingElements() {
- var entry = activeFormattingElements.removeLast();
- while (activeFormattingElements.length > 0 && entry != Marker) {
- entry = activeFormattingElements.removeLast();
- }
- }
-
- /// Check if an element exists between the end of the active
- /// formatting elements and the last marker. If it does, return it, else
- /// return null.
- Element elementInActiveFormattingElements(String name) {
- for (var item in activeFormattingElements.reversed) {
- // Check for Marker first because if it's a Marker it doesn't have a
- // name attribute.
- if (item == Marker) {
- break;
- } else if (item.localName == name) {
- return item;
- }
- }
- return null;
- }
-
- void insertRoot(Token token) {
- var element = createElement(token);
- openElements.add(element);
- document.nodes.add(element);
- }
-
- void insertDoctype(DoctypeToken token) {
- var doctype = new DocumentType(token.name, token.publicId, token.systemId)
- ..sourceSpan = token.span;
- document.nodes.add(doctype);
- }
-
- void insertComment(StringToken token, [Node parent]) {
- if (parent == null) {
- parent = openElements.last;
- }
- parent.nodes.add(new Comment(token.data)..sourceSpan = token.span);
- }
-
- /// Create an element but don't insert it anywhere
- Element createElement(StartTagToken token) {
- var name = token.name;
- var namespace = token.namespace;
- if (namespace == null) namespace = defaultNamespace;
- var element = document.createElementNS(namespace, name)
- ..attributes = token.data
- ..sourceSpan = token.span;
- return element;
- }
-
- Element insertElement(StartTagToken token) {
- if (insertFromTable) return insertElementTable(token);
- return insertElementNormal(token);
- }
-
- Element insertElementNormal(StartTagToken token) {
- var name = token.name;
- var namespace = token.namespace;
- if (namespace == null) namespace = defaultNamespace;
- var element = document.createElementNS(namespace, name)
- ..attributes = token.data
- ..sourceSpan = token.span;
- openElements.last.nodes.add(element);
- openElements.add(element);
- return element;
- }
-
- Element insertElementTable(token) {
- /// Create an element and insert it into the tree
- var element = createElement(token);
- if (!tableInsertModeElements.contains(openElements.last.localName)) {
- return insertElementNormal(token);
- } else {
- // We should be in the InTable mode. This means we want to do
- // special magic element rearranging
- var nodePos = getTableMisnestedNodePosition();
- if (nodePos[1] == null) {
- // TODO(jmesserly): I don't think this is reachable. If insertFromTable
- // is true, there will be a <table> element open, and it always has a
- // parent pointer.
- nodePos[0].nodes.add(element);
- } else {
- nodePos[0].insertBefore(element, nodePos[1]);
- }
- openElements.add(element);
- }
- return element;
- }
-
- /// Insert text data.
- void insertText(String data, FileSpan span) {
- var parent = openElements.last;
-
- if (!insertFromTable || insertFromTable &&
- !tableInsertModeElements.contains(openElements.last.localName)) {
- _insertText(parent, data, span);
- } else {
- // We should be in the InTable mode. This means we want to do
- // special magic element rearranging
- var nodePos = getTableMisnestedNodePosition();
- _insertText(nodePos[0], data, span, nodePos[1]);
- }
- }
-
- /// Insert [data] as text in the current node, positioned before the
- /// start of node [refNode] or to the end of the node's text.
- static void _insertText(Node parent, String data, FileSpan span,
- [Element refNode]) {
- var nodes = parent.nodes;
- if (refNode == null) {
- if (nodes.length > 0 && nodes.last is Text) {
- Text last = nodes.last;
- last.data = '${last.data}$data';
-
- if (span != null) {
- last.sourceSpan = span.file.span(last.sourceSpan.start.offset,
- span.end.offset);
- }
- } else {
- nodes.add(new Text(data)..sourceSpan = span);
- }
- } else {
- int index = nodes.indexOf(refNode);
- if (index > 0 && nodes[index - 1] is Text) {
- Text last = nodes[index - 1];
- last.data = '${last.data}$data';
- } else {
- nodes.insert(index, new Text(data)..sourceSpan = span);
- }
- }
- }
-
- /// Get the foster parent element, and sibling to insert before
- /// (or null) when inserting a misnested table node
- List<Node> getTableMisnestedNodePosition() {
- // The foster parent element is the one which comes before the most
- // recently opened table element
- // XXX - this is really inelegant
- Node lastTable = null;
- Node fosterParent = null;
- var insertBefore = null;
- for (var elm in openElements.reversed) {
- if (elm.localName == "table") {
- lastTable = elm;
- break;
- }
- }
- if (lastTable != null) {
- // XXX - we should really check that this parent is actually a
- // node here
- if (lastTable.parentNode != null) {
- fosterParent = lastTable.parentNode;
- insertBefore = lastTable;
- } else {
- fosterParent = openElements[openElements.indexOf(lastTable) - 1];
- }
- } else {
- fosterParent = openElements[0];
- }
- return [fosterParent, insertBefore];
- }
-
- void generateImpliedEndTags([String exclude]) {
- var name = openElements.last.localName;
- // XXX td, th and tr are not actually needed
- if (name != exclude && const ["dd", "dt", "li", "option", "optgroup", "p",
- "rp", "rt"].contains(name)) {
- openElements.removeLast();
- // XXX This is not entirely what the specification says. We should
- // investigate it more closely.
- generateImpliedEndTags(exclude);
- }
- }
-
- /// Return the final tree.
- Document getDocument() => document;
-
- /// Return the final fragment.
- DocumentFragment getFragment() {
- //XXX assert innerHTML
- var fragment = new DocumentFragment();
- openElements[0].reparentChildren(fragment);
- return fragment;
- }
-}
« no previous file with comments | « pkg/third_party/html5lib/lib/src/tokenizer.dart ('k') | pkg/third_party/html5lib/lib/src/utils.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698