public static int GetContentEndPosition(this DothtmlElementNode node) { var lastNode = node.Content.LastOrDefault(); if (lastNode == null) { return(node.EndPosition); } if (lastNode is DothtmlElementNode lastElement) { if (lastElement.IsSelfClosingTag) { return(lastElement.EndPosition); } else if (lastElement.CorrespondingEndTag != null) { var closingTag = lastElement.CorrespondingEndTag; return(closingTag.EndPosition); } else if (lastElement.Content.Count == 0) { return(lastElement.EndPosition); } else { return(lastElement.GetContentEndPosition()); } } else { return(lastNode.EndPosition); } }
private void ReadWhiteSpaceOrComment(DothtmlElementNode node) { while (true) { switch (Peek().Type) { case DothtmlTokenType.WhiteSpace: if (node.AttributeSeparators == null) { node.AttributeSeparators = new List <DothtmlToken>(); } node.AttributeSeparators.Add(Read()); break; case DothtmlTokenType.OpenComment: if (node.InnerComments == null) { node.InnerComments = new List <DotHtmlCommentNode>(); } node.InnerComments.Add(ReadComment()); break; case DothtmlTokenType.OpenServerComment: if (node.InnerComments == null) { node.InnerComments = new List <DotHtmlCommentNode>(); } node.InnerComments.Add(ReadServerComment()); break; default: return; } } }
private void ResolveWrongClosingTag(DothtmlElementNode element) { Debug.Assert(element.IsClosingTag); var startElement = ElementHierarchy.Peek() as DothtmlElementNode; Debug.Assert(startElement != null); Debug.Assert(startElement.FullTagName != element.FullTagName); while (startElement != null && !startElement.FullTagName.Equals(element.FullTagName, StringComparison.OrdinalIgnoreCase)) { ElementHierarchy.Pop(); if (HtmlWriter.SelfClosingTags.Contains(startElement.FullTagName)) { // automatic immediate close of the tag (for <img src="">) ElementHierarchy.Peek().Content.AddRange(startElement.Content); startElement.Content.Clear(); } else if (AutomaticClosingTags.Contains(startElement.FullTagName)) { // elements than can contain itself like <p> are closed on the first occurance of element with the same name var sameElementIndex = startElement.Content.FindIndex(a => (a as DothtmlElementNode)?.FullTagName == startElement.FullTagName); if (sameElementIndex >= 0) { var count = startElement.Content.Count - sameElementIndex; ElementHierarchy.Peek().Content.AddRange(startElement.Content.Skip(sameElementIndex)); startElement.Content.RemoveRange(sameElementIndex, count); } } // otherwise just pop the element startElement = ElementHierarchy.Peek() as DothtmlElementNode; } }
/// <summary> /// Reads the element. /// </summary> private DothtmlElementNode ReadElement() { var startIndex = CurrentIndex; var node = new DothtmlElementNode(); Assert(DothtmlTokenType.OpenTag); Read(); if (Peek().Type == DothtmlTokenType.Slash) { Read(); node.IsClosingTag = true; } // element name var nameOrPrefix = ReadName(true, false, DothtmlTokenType.Text); if (Peek().Type == DothtmlTokenType.Colon) { node.TagPrefixNode = nameOrPrefix; node.PrefixSeparator = Read(); node.TagNameNode = ReadName(false, false, DothtmlTokenType.Text); } else { node.TagNameNode = nameOrPrefix; } //no mans whitespaces SkipWhiteSpace(); // attributes if (!node.IsClosingTag) { ReadWhiteSpaceOrComment(node); while (Peek().Type == DothtmlTokenType.Text) { var attribute = ReadAttribute(); node.Attributes.Add(attribute); ReadWhiteSpaceOrComment(node); } if (Peek().Type == DothtmlTokenType.Slash) { Read(); SkipWhiteSpace(); node.IsSelfClosingTag = true; } } Assert(DothtmlTokenType.CloseTag); Read(); node.Tokens.Add(GetTokensFrom(startIndex)); return(node); }
private void ResolveWrongClosingTag(DothtmlElementNode element) { Debug.Assert(element.IsClosingTag); var startElement = ElementHierarchy.Peek() as DothtmlElementNode; Debug.Assert(startElement != null); Debug.Assert(startElement.FullTagName != element.FullTagName); while (startElement != null && !startElement.FullTagName.Equals(element.FullTagName, StringComparison.OrdinalIgnoreCase)) { ElementHierarchy.Pop(); if (HtmlWriter.IsSelfClosing(startElement.FullTagName)) { // automatic immediate close of the tag (for <img src="">) ElementHierarchy.Peek().Content.AddRange(startElement.Content); startElement.Content.Clear(); startElement.AddWarning("End tag is missing, the element is implicitly self-closed."); } else if (AutomaticClosingTags.Contains(startElement.FullTagName)) { // elements than can contain itself like <p> are closed on the first occurance of element with the same name var sameElementIndex = startElement.Content.FindIndex(a => (a as DothtmlElementNode)?.FullTagName == startElement.FullTagName); if (sameElementIndex < 0) { startElement.AddWarning($"End tag is missing, the element is implicitly closed with its parent tag or by the end of file."); } else if (sameElementIndex >= 0) { startElement.AddWarning($"End tag is missing, the element is implicitly closed by following <{startElement.Content[sameElementIndex].As<DothtmlElementNode>()?.FullTagName}> tag."); startElement.Content[sameElementIndex].AddWarning($"Previous <{startElement.FullTagName}> is implicitly closed here."); var count = startElement.Content.Count - sameElementIndex; ElementHierarchy.Peek().Content.AddRange(startElement.Content.Skip(sameElementIndex)); startElement.Content.RemoveRange(sameElementIndex, count); } } else { startElement.AddWarning($"End tag is missing, the element is implicitly closed by </{element.FullTagName}>."); element.AddWarning($"Element <{startElement.FullTagName}> is implicitly closed here."); } // otherwise just pop the element startElement = ElementHierarchy.Peek() as DothtmlElementNode; } }
public static int GetContentStartPosition(this DothtmlElementNode node) { return(node.Content.FirstOrDefault()?.StartPosition ?? (node.StartPosition + node.Length)); }
public void Visit(DothtmlElementNode element) { LastFoundNode = element; }