SafeDomTreeProcessor.prototype.processToTree = function()

in asdoc/library/closure/goog/html/sanitizer/safedomtreeprocessor.js [127:204]


SafeDomTreeProcessor.prototype.processToTree = function(html) {
  if (!SAFE_PARSING_SUPPORTED) {
    return googDom.createElement(TagName.SPAN);
  }
  var newRoot = googDom.createElement(TagName.SPAN);
  // Allow subclasses to attach properties to the root.
  this.processRoot(newRoot);

  // Allow subclasses to pre-process the HTML string before performing the main
  // tree-based transformation.
  html = this.preProcessHtml(html);
  var originalTreeWalker = getDomTreeWalker(html);

  // Mapping from original nodes to new nodes, used to find the parent to which
  // a newly processed node should be attached.
  var elementMap = ElementWeakMap.newWeakMap();

  var originalNode;
  while (originalNode = originalTreeWalker.nextNode()) {
    // Make a copy of the node, potentially dropping it or changing its content,
    // tag name, etc.
    var newNode = this.createNode_(originalNode);
    if (!newNode) {
      // The transformation function chose not to copy over the node. We delete
      // the children so that the current treeWalker will stop iterating on
      // them.
      googDom.removeChildren(originalNode);
      continue;
    }
    if (noclobber.isNodeElement(newNode)) {
      elementMap.set(originalNode, newNode);
    }

    // Finds the new parent to which newNode should be appended. The tree is
    // copied top-down, so the parent of the current node has already been
    // copied and placed into the new tree. The new parent is either the root
    // of the new tree or a node found using originalToNewElementMap.
    var originalParent = noclobber.getParentNode(originalNode);
    var isParentRoot = false;
    if (originalParent) {
      var originalParentNodeType = noclobber.getNodeType(originalParent);
      var originalParentNodeName =
          noclobber.getNodeName(originalParent).toLowerCase();
      var originalGrandParent = noclobber.getParentNode(originalParent);
      // The following checks if newParent is an immediate child of the inert
      // parent template element.
      if (originalParentNodeType == NodeType.DOCUMENT_FRAGMENT &&
          !originalGrandParent) {
        isParentRoot = true;
      } else if (originalParentNodeName == 'body' && originalGrandParent) {
        // The following checks if newParent is an immediate child of the
        // inert parent HtmlDocument.
        var dirtyGreatGrandParent =
            noclobber.getParentNode(originalGrandParent);
        if (dirtyGreatGrandParent &&
            !noclobber.getParentNode(dirtyGreatGrandParent)) {
          isParentRoot = true;
        }
      }
      var newParent = null;
      if (isParentRoot || !originalParent) {
        newParent = newRoot;
      } else if (noclobber.isNodeElement(originalParent)) {
        newParent = elementMap.get(originalParent);
      }
      if (newParent.content) {
        newParent = newParent.content;
      }
      newParent.appendChild(newNode);
    }
  }
  if (elementMap.clear) {
    // Clear the map. On browsers that don't support WeakMap, entries are not
    // automatically cleaned up.
    elementMap.clear();
  }
  return newRoot;
};