docs: function parseContent(window, input) {
      function nextToken() {
        // Check for end-of-string.
        if (!input) {
          return null;
        }
  
        // Consume 'n' characters from the input.
        function consume(result) {
          input = input.substr(result.length);
          return result;
        }
  
        var m = input.match(/^([^<]*)(<[^>]+>?)?/);
        // If there is some text before the next tag, return it, otherwise return
        // the tag.
        return consume(m[1] ? m[1] : m[2]);
      }
  
      // Unescape a string 's'.
      function unescape1(e) {
        return ESCAPE[e];
      }
      function unescape(s) {
        while ((m = s.match(/&(amp|lt|gt|lrm|rlm|nbsp);/))) {
          s = s.replace(m[0], unescape1);
        }
        return s;
      }
  
      function shouldAdd(current, element) {
        return !NEEDS_PARENT[element.localName] ||
               NEEDS_PARENT[element.localName] === current.localName;
      }
  
      // Create an element for this tag.
      function createElement(type, annotation) {
        var tagName = TAG_NAME[type];
        if (!tagName) {
          return null;
        }
        var element = window.document.createElement(tagName);
        element.localName = tagName;
        var name = TAG_ANNOTATION[type];
        if (name && annotation) {
          element[name] = annotation.trim();
        }
        return element;
      }
  
      var rootDiv = window.document.createElement("div"),
          current = rootDiv,
          t,
          tagStack = [];
  
      while ((t = nextToken()) !== null) {
        if (t[0] === '<') {
          if (t[1] === "/") {
            // If the closing tag matches, move back up to the parent node.
            if (tagStack.length &&
                tagStack[tagStack.length - 1] === t.substr(2).replace(">", "")) {
              tagStack.pop();
              current = current.parentNode;
            }
            // Otherwise just ignore the end tag.
            continue;
          }
          var ts = parseTimeStamp(t.substr(1, t.length - 2));
          var node;
          if (ts) {
            // Timestamps are lead nodes as well.
            node = window.document.createProcessingInstruction("timestamp", ts);
            current.appendChild(node);
            continue;
          }
          var m = t.match(/^<([^.\s/0-9>]+)(\.[^\s\\>]+)?([^>\\]+)?(\\?)>?$/);
          // If we can't parse the tag, skip to the next tag.
          if (!m) {
            continue;
          }
          // Try to construct an element, and ignore the tag if we couldn't.
          node = createElement(m[1], m[3]);
          if (!node) {
            continue;
          }
          // Determine if the tag should be added based on the context of where it
          // is placed in the cuetext.
          if (!shouldAdd(current, node)) {
            continue;
          }
          // Set the class list (as a list of classes, separated by space).
          if (m[2]) {
            node.className = m[2].substr(1).replace('.', ' ');
          }
          // Append the node to the current node, and enter the scope of the new
          // node.
          tagStack.push(m[1]);
          current.appendChild(node);
          current = node;
          continue;
        }
  
        // Text nodes are leaf nodes.
        current.appendChild(window.document.createTextNode(unescape(t)));
      }
  
      return rootDiv;
    }