// returns the new current node void DoTailTag(HeaderFooter tag) { // find self or parent with matching header tag ContainerNode searchNode = _curNode; while (searchNode != null && searchNode.Header.NameLowerCased != tag.NameLowerCased) { searchNode = searchNode.ParentNode; } // if no matching head found if (searchNode == null) { return; } // add to current node searchNode.Footer = tag; if (_noInnerTagNodes.Contains(tag.NameLowerCased)) { // convert whatever children happened to be parsed, into a single text node // used primarily to fix <script> nodes that have < and > in them searchNode.ChildNodes.Clear(); // We used to have option to parse JavaScriptDocument but now we will do that manually because it was too confusing. searchNode.AddChild(new TextNode(searchNode.Source, searchNode.Header.End, searchNode.Footer.Begin)); } // return current node to parent _curNode = searchNode.ParentNode; }
void DoLiteral(int i) { // create node for it ConsumeText(_currentToken.Begin); string name = _currentToken.Type.ToString(); name = name.Substring(0, name.Length - 7); // strip 'Literal' var literalHeader = new HeaderFooter(_currentNode.Source, _currentToken.Begin, _currentToken.End, name, HeaderFooterType.Single); var literalNode = new ContainerNode(_source, literalHeader, new Dictionary <string, string>()); _currentNode.AddChild(literalNode); _beginOfTextNode = _currentToken.End; IdentifyContainerNode(i, literalNode); }
// builds/returns a phantom root node for string content ContainerNode BuildPhantomRootNode() { string source = _source; // create header at begining, footer at end HeaderFooter header = new HeaderFooter(source, 0, 0, "script", HeaderFooterType.Head); HeaderFooter footer = new HeaderFooter(source, source.Length, source.Length, "script", HeaderFooterType.Tail); // make node ContainerNode rootNode = new ContainerNode(_source, header, new Dictionary <string, string> { { "type", "text/javascript" } }); rootNode.Footer = footer; return(rootNode); }
ContainerNode TryParse() { // find root node _curIndex = _source.IndexOf('<'); if (_curIndex < 0) { throw new FormatException("No root node found."); } // setup root node HeaderFooter rootHeader = ParseHeaderFooter(); if (rootHeader.Type == HeaderFooterType.Tail) { throw new FormatException("root node cannot be ending tag."); } ContainerNode root = new ContainerNode(_source, rootHeader); if (rootHeader.Type != HeaderFooterType.Single) { _curNode = root; } _curIndex = rootHeader.End; // while (_curIndex < _source.Length && _curNode != null) { if (_source[_curIndex] != '<') { ConsumeText(); } else if (CurrentIndexPointsAt("<!--")) { ConsumeComment(); } else { ConsumeTag(); } } return(root); }
/// <summary> /// Consumes the tag head, tail, or single at curIndex /// </summary> void ConsumeTag() { HeaderFooter headerFooter = ParseHeaderFooter(); switch (headerFooter.Type) { case HeaderFooterType.Single: case HeaderFooterType.Head: DoStarterTag(headerFooter); break; case HeaderFooterType.Tail: DoTailTag(headerFooter); break; default: throw new FormatException("screwy tag type"); } _curIndex = headerFooter.End; }
int DoKeyword(int i) { JsToken next = (i + 1) < _tokenList.Count ? _tokenList[i + 1] : null; // create node for it ConsumeText(_currentToken.Begin); var keywordHeader = new HeaderFooter(_source, _currentToken.Begin, _currentToken.End, _currentToken.Text, HeaderFooterType.Single); var keywordNode = new ContainerNode(_source, keywordHeader, new Dictionary <string, string>()); _currentNode.AddChild(keywordNode); _beginOfTextNode = _currentToken.End; // name function if (_currentToken.Text == "function" && next != null && next.Type == JsTokenType.Identifier) { IdentifyNode(keywordNode, next.Text); ++i; // skip id token _beginOfTextNode = next.End; } return(i); }
// returns the new current node void DoStarterTag(HeaderFooter tag) { // Head & Single // new node ContainerNode n = new ContainerNode(_source, tag); // create parent-child relationship _curNode.AddChild(n); // force some node types to be single bool isSingle = tag.Type == HeaderFooterType.Single || _emptyTags.Contains(tag.Name); // if forced-empty node has a tailtag, it will be ignored // !! Not doing anything special about illegally embeded nodes such as // <p>first paragraph <p> new paragraph, close previous <p> another paragraph if (!isSingle) { _curNode = n; } }
void MoveDownIntoSubSection(int i) { _openTokensIndexStack.Push(i); // add previous text node ConsumeText(_currentToken.Begin); // add new node var name = BracketName(_currentToken.Text); var header = new HeaderFooter(_currentNode.Source, _currentToken.Begin, _currentToken.End, "block", HeaderFooterType.Head); var blockNode = new ContainerNode(_source, header, new Dictionary <string, string> { { "class", name } }); _currentNode.AddChild(blockNode); IdentifyContainerNode(i, blockNode); // set new text-node start _beginOfTextNode = _currentToken.End; // move down to new node _currentNode = blockNode; }
/// <summary> /// Constructs a Container that uses attributes provided by the input dictionary. /// </summary> internal ContainerNode(string source, HeaderFooter header, Dictionary <string, string> attr) : base(source, header.Begin, header.Name) { this.Header = header; this._attributes = attr; }
/// <summary> /// Constructs a Container that uses the attributes embedded in the tag header. /// </summary> internal ContainerNode(string source, HeaderFooter header) : base(source, header.Begin, header.Name) { this.Header = header; }