AngleSharp by Florian Rappl

<PackageReference Include="AngleSharp" Version="0.2.6" />

 HtmlParser

public class HtmlParser : IParser
Represents the Tree construction as specified in 8.2.5 Tree construction, on the following page: http://www.w3.org/html/wg/drafts/html/master/syntax.html
using AngleSharp.DOM; using AngleSharp.DOM.Html; using AngleSharp.DOM.Mathml; using AngleSharp.DOM.Svg; using System; using System.Collections.Generic; using System.IO; using System.Text; using System.Threading.Tasks; namespace AngleSharp.Html { public class HtmlParser : IParser { private HtmlTokenizer tokenizer; private HTMLDocument doc; private HtmlTreeMode insert; private HtmlTreeMode originalInsert; private List<Element> open; private List<Element> formatting; private HTMLFormElement form; private bool frameset; private bool fragment; private StringBuilder tableCharacters; private bool foster; private int nesting; private bool pause; private bool started; private TaskCompletionSource<bool> tcs; private HTMLScriptElement pendingParsingBlock; public HTMLDocument Result { get { Parse(); return doc; } } public bool IsAsync => tcs != null; public bool IsFragmentCase => fragment; internal Element CurrentNode { get { if (open.Count <= 0) return null; return open[open.Count - 1]; } } internal HTMLScriptElement PendingParsingBlock { get { return pendingParsingBlock; } set { pendingParsingBlock = value; } } public event EventHandler<ParseErrorEventArgs> ErrorOccurred; public HtmlParser(string source) : this(new HTMLDocument(), new SourceManager(source)) { } public HtmlParser(Stream stream) : this(new HTMLDocument(), new SourceManager(stream)) { } public HtmlParser(HTMLDocument document, string source) : this(document, new SourceManager(source)) { } public HtmlParser(HTMLDocument document, Stream stream) : this(document, new SourceManager(stream)) { } internal HtmlParser(HTMLDocument document, SourceManager source) { tokenizer = new HtmlTokenizer(source); HtmlTokenizer htmlTokenizer = tokenizer; EventHandler<ParseErrorEventArgs> value = delegate(object s, ParseErrorEventArgs ev) { if (this.ErrorOccurred != null) this.ErrorOccurred(this, ev); }; htmlTokenizer.ErrorOccurred += value; started = false; doc = document; open = new List<Element>(); formatting = new List<Element>(); frameset = true; insert = HtmlTreeMode.Initial; tableCharacters = new StringBuilder(); } public Task ParseAsync() { if (!started) { started = true; tcs = new TaskCompletionSource<bool>(); return tcs.Task; } if (tcs == null) { TaskCompletionSource<bool> taskCompletionSource = new TaskCompletionSource<bool>(); taskCompletionSource.SetResult(true); return taskCompletionSource.Task; } return tcs.Task; } public void Parse() { if (!started) { started = true; HtmlToken htmlToken; do { htmlToken = tokenizer.Get(); Consume(htmlToken); } while (htmlToken.Type != HtmlTokenType.EOF); } } public void SwitchToFragment(Node context) { if (started) throw new InvalidOperationException("Fragment mode has to be activated before running the parser!"); switch (context.NodeName) { case "title": case "textarea": tokenizer.Switch(HtmlParseMode.RCData); break; case "style": case "xmp": case "iframe": case "noembed": case "noframes": tokenizer.Switch(HtmlParseMode.Rawtext); break; case "script": tokenizer.Switch(HtmlParseMode.Script); break; case "noscript": if (doc.IsScripting) tokenizer.Switch(HtmlParseMode.Rawtext); break; case "plaintext": tokenizer.Switch(HtmlParseMode.Plaintext); break; } HTMLHtmlElement hTMLHtmlElement = new HTMLHtmlElement(); fragment = true; doc.AppendChild(hTMLHtmlElement); open.Add(hTMLHtmlElement); Reset(context); while (!(context is HTMLFormElement)) { context = context.ParentNode; if (context == null) return; } form = (HTMLFormElement)context; } private void Reset(Node context = null) { bool flag = false; int num = open.Count - 1; while (true) { if (num < 0) return; Node node = open[num]; if (num == 0) { flag = true; node = (context ?? node); } switch (node.NodeName) { case "select": insert = HtmlTreeMode.InSelect; return; case "th": case "td": insert = (flag ? HtmlTreeMode.InBody : HtmlTreeMode.InCell); return; case "tr": insert = HtmlTreeMode.InRow; return; case "thead": case "tfoot": case "tbody": insert = HtmlTreeMode.InTableBody; return; case "caption": insert = HtmlTreeMode.InCaption; return; case "colgroup": insert = HtmlTreeMode.InColumnGroup; return; case "table": insert = HtmlTreeMode.InTable; return; case "head": insert = HtmlTreeMode.InBody; return; case "body": insert = HtmlTreeMode.InBody; return; case "frameset": insert = HtmlTreeMode.InFrameset; return; case "html": insert = HtmlTreeMode.BeforeHead; return; } if (flag) break; num--; } insert = HtmlTreeMode.InBody; } private void Consume(HtmlToken token) { Element currentNode = CurrentNode; if (token.Type == HtmlTokenType.Characters) { char[] data = ((HtmlCharactersToken)token).Data; for (int i = 0; i < data.Length; i++) { Consume(HtmlToken.Character(data[i])); } } else if (currentNode == null || currentNode.IsInHtml || (currentNode.IsHtmlTIP && (token.Type == HtmlTokenType.StartTag || token.Type == HtmlTokenType.Character)) || (currentNode.IsInMathML && currentNode.NodeName == "annotation-xml" && token.IsStartTag("svg")) || token.Type == HtmlTokenType.EOF || (currentNode.IsMathMLTIP && (token.Type == HtmlTokenType.Character || (token.Type == HtmlTokenType.StartTag && !token.IsStartTag("mglyph") && !token.IsStartTag("malignmark"))))) { switch (insert) { case HtmlTreeMode.Initial: Initial(token); break; case HtmlTreeMode.BeforeHtml: BeforeHtml(token); break; case HtmlTreeMode.BeforeHead: BeforeHead(token); break; case HtmlTreeMode.InHead: InHead(token); break; case HtmlTreeMode.InHeadNoScript: InHeadNoScript(token); break; case HtmlTreeMode.AfterHead: AfterHead(token); break; case HtmlTreeMode.InBody: InBody(token); break; case HtmlTreeMode.Text: Text(token); break; case HtmlTreeMode.InTable: InTable(token); break; case HtmlTreeMode.InTableText: InTableText(token); break; case HtmlTreeMode.InCaption: InCaption(token); break; case HtmlTreeMode.InColumnGroup: InColumnGroup(token); break; case HtmlTreeMode.InTableBody: InTableBody(token); break; case HtmlTreeMode.InRow: InRow(token); break; case HtmlTreeMode.InCell: InCell(token); break; case HtmlTreeMode.InSelect: InSelect(token); break; case HtmlTreeMode.InSelectInTable: InSelectInTable(token); break; case HtmlTreeMode.AfterBody: AfterBody(token); break; case HtmlTreeMode.InFrameset: InFrameset(token); break; case HtmlTreeMode.AfterFrameset: AfterFrameset(token); break; case HtmlTreeMode.AfterAfterBody: AfterAfterBody(token); break; case HtmlTreeMode.AfterAfterFrameset: AfterAfterFrameset(token); break; } } else { Foreign(token); } } private void Initial(HtmlToken token) { if (token.Type == HtmlTokenType.Comment) AddComment(doc, token); else if (token.Type == HtmlTokenType.DOCTYPE) { HtmlDoctypeToken htmlDoctypeToken = (HtmlDoctypeToken)token; if (!htmlDoctypeToken.IsValid) RaiseErrorOccurred(ErrorCode.DoctypeInvalid); AddElement(htmlDoctypeToken); if (htmlDoctypeToken.IsFullQuirks) doc.QuirksMode = QuirksMode.On; else if (htmlDoctypeToken.IsLimitedQuirks) { doc.QuirksMode = QuirksMode.Limited; } insert = HtmlTreeMode.BeforeHtml; } else if (!token.IsIgnoreable) { if (!doc.IsEmbedded) { RaiseErrorOccurred(ErrorCode.DoctypeMissing); doc.QuirksMode = QuirksMode.On; } insert = HtmlTreeMode.BeforeHtml; BeforeHtml(token); } } private void BeforeHtml(HtmlToken token) { if (token.Type == HtmlTokenType.DOCTYPE) RaiseErrorOccurred(ErrorCode.DoctypeTagInappropriate); else if (token.Type == HtmlTokenType.Comment) { AddComment(doc, token); } else if (token.Type == HtmlTokenType.StartTag && ((HtmlTagToken)token).Name == "html") { HTMLHtmlElement element = new HTMLHtmlElement(); AddElementToDocument(element, token); insert = HtmlTreeMode.BeforeHead; } else if (token.Type == HtmlTokenType.EndTag && !((HtmlTagToken)token).Name.IsHtmlBodyOrBreakRowElement(true)) { RaiseErrorOccurred(ErrorCode.TagCannotEndHere); } else if (!token.IsIgnoreable) { HTMLHtmlElement element2 = new HTMLHtmlElement(); AddElementToDocument(element2, HtmlToken.OpenTag("html")); insert = HtmlTreeMode.BeforeHead; BeforeHead(token); } } private void BeforeHead(HtmlToken token) { if (token.Type == HtmlTokenType.Comment) AddComment(CurrentNode, token); else if (token.Type == HtmlTokenType.DOCTYPE) { RaiseErrorOccurred(ErrorCode.DoctypeTagInappropriate); } else if (token.Type == HtmlTokenType.StartTag && ((HtmlTagToken)token).Name == "html") { InBody(token); } else if (token.Type == HtmlTokenType.StartTag && ((HtmlTagToken)token).Name == "head") { HTMLHeadElement element = new HTMLHeadElement(); AddElementToCurrentNode(element, token, false); insert = HtmlTreeMode.InHead; } else if (token.Type == HtmlTokenType.EndTag && !((HtmlTagToken)token).Name.IsHtmlBodyOrBreakRowElement(true)) { RaiseErrorOccurred(ErrorCode.TagCannotEndHere); } else if (!token.IsIgnoreable) { BeforeHead(HtmlToken.OpenTag("head")); InHead(token); } } private void InHead(HtmlToken token) { if (token.IsIgnoreable) InsertCharacter(((HtmlCharacterToken)token).Data); else if (token.Type == HtmlTokenType.Comment) { AddComment(CurrentNode, token); } else if (token.Type == HtmlTokenType.DOCTYPE) { RaiseErrorOccurred(ErrorCode.DoctypeTagInappropriate); } else if (token.Type == HtmlTokenType.StartTag && ((HtmlTagToken)token).Name == "html") { InBody(token); } else if (token.Type == HtmlTokenType.StartTag && ((HtmlTagToken)token).Name.IsOneOf("base", "basefont", "bgsound", "link")) { string name = ((HtmlTagToken)token).Name; HTMLElement element = HTMLElement.Factory(name); AddElementToCurrentNode(element, token, true); CloseCurrentNode(); } else if (token.Type == HtmlTokenType.StartTag && ((HtmlTagToken)token).Name == "meta") { HTMLMetaElement hTMLMetaElement = new HTMLMetaElement(); AddElementToCurrentNode(hTMLMetaElement, token, true); CloseCurrentNode(); string attribute = hTMLMetaElement.GetAttribute("charset"); if (attribute != null && HtmlEncoding.IsSupported(attribute)) SetCharset(attribute); else { attribute = hTMLMetaElement.GetAttribute("http-equiv"); if (attribute != null && attribute.Equals("Content-Type", StringComparison.OrdinalIgnoreCase)) { attribute = (hTMLMetaElement.GetAttribute("content") ?? string.Empty); attribute = HtmlEncoding.Extract(attribute); if (HtmlEncoding.IsSupported(attribute)) SetCharset(attribute); } } } else if (token.Type == HtmlTokenType.StartTag && ((HtmlTagToken)token).Name == "title") { RCDataAlgorithm((HtmlTagToken)token); } else if (token.Type == HtmlTokenType.StartTag && (((HtmlTagToken)token).Name.IsOneOf("noframes", "style") || (((HtmlTagToken)token).Name == "noscript" && doc.IsScripting))) { RawtextAlgorithm((HtmlTagToken)token); } else if (token.Type == HtmlTokenType.StartTag && ((HtmlTagToken)token).Name == "noscript") { HTMLElement element2 = new HTMLElement(); AddElementToCurrentNode(element2, token, false); insert = HtmlTreeMode.InHeadNoScript; } else if (token.Type == HtmlTokenType.StartTag && ((HtmlTagToken)token).Name == "script") { HTMLScriptElement hTMLScriptElement = new HTMLScriptElement(); hTMLScriptElement.IsParserInserted = true; hTMLScriptElement.IsAsyncForced = false; hTMLScriptElement.IsAlreadyStarted = fragment; AddElementToCurrentNode(hTMLScriptElement, token, false); tokenizer.Switch(HtmlParseMode.Script); originalInsert = insert; insert = HtmlTreeMode.Text; } else if (token.Type == HtmlTokenType.EndTag && ((HtmlTagToken)token).Name == "head") { CloseCurrentNode(); insert = HtmlTreeMode.AfterHead; } else if (token.Type == HtmlTokenType.StartTag && ((HtmlTagToken)token).Name == "head") { RaiseErrorOccurred(ErrorCode.HeadTagMisplaced); } else if (token.Type == HtmlTokenType.EndTag && !((HtmlTagToken)token).Name.IsHtmlBodyOrBreakRowElement(false)) { RaiseErrorOccurred(ErrorCode.TagCannotEndHere); } else { CloseCurrentNode(); insert = HtmlTreeMode.AfterHead; AfterHead(token); } } private void InHeadNoScript(HtmlToken token) { if (token.Type == HtmlTokenType.DOCTYPE) RaiseErrorOccurred(ErrorCode.DoctypeTagInappropriate); else if (token.Type == HtmlTokenType.StartTag && ((HtmlTagToken)token).Name == "html") { InBody(token); } else if (token.Type == HtmlTokenType.EndTag && ((HtmlTagToken)token).Name == "noscript") { CloseCurrentNode(); insert = HtmlTreeMode.InHead; } else if (token.IsIgnoreable) { InHead(token); } else if (token.Type == HtmlTokenType.Comment) { InHead(token); } else if (token.Type == HtmlTokenType.StartTag && ((HtmlTagToken)token).Name.IsOneOf("basefont", "bgsound", "link", "meta", "noframes", "style")) { InHead(token); } else if (token.Type == HtmlTokenType.StartTag && ((HtmlTagToken)token).Name.IsOneOf("head", "noscript")) { RaiseErrorOccurred(ErrorCode.TagInappropriate); } else if (token.Type == HtmlTokenType.EndTag && ((HtmlTagToken)token).Name != "br") { RaiseErrorOccurred(ErrorCode.TagCannotEndHere); } else { RaiseErrorOccurred(ErrorCode.TokenNotPossible); CloseCurrentNode(); insert = HtmlTreeMode.InHead; InHead(token); } } private void AfterHead(HtmlToken token) { if (token.IsIgnoreable) InsertCharacter(((HtmlCharacterToken)token).Data); else if (token.Type == HtmlTokenType.Comment) { AddComment(CurrentNode, token); } else if (token.Type == HtmlTokenType.DOCTYPE) { RaiseErrorOccurred(ErrorCode.DoctypeTagInappropriate); } else if (token.Type == HtmlTokenType.StartTag && ((HtmlTagToken)token).Name == "html") { InBody(token); } else if (token.Type == HtmlTokenType.StartTag && ((HtmlTagToken)token).Name == "body") { AfterHeadStartTagBody((HtmlTagToken)token); } else if (token.Type == HtmlTokenType.StartTag && ((HtmlTagToken)token).Name == "frameset") { HTMLFrameSetElement element = new HTMLFrameSetElement(); AddElementToCurrentNode(element, token, false); insert = HtmlTreeMode.InFrameset; } else if (token.Type == HtmlTokenType.StartTag && ((HtmlTagToken)token).Name.IsOneOf("base", "basefont", "bgsound", "link", "meta", "noframes", "script", "style", "title")) { RaiseErrorOccurred(ErrorCode.TagMustBeInHead); int count = open.Count; open.Add(doc.Head); InHead(token); open.RemoveAt(count); } else if (token.Type == HtmlTokenType.StartTag && ((HtmlTagToken)token).Name == "head") { RaiseErrorOccurred(ErrorCode.HeadTagMisplaced); } else if (token.Type == HtmlTokenType.EndTag && !((HtmlTagToken)token).Name.IsHtmlBodyOrBreakRowElement(false)) { RaiseErrorOccurred(ErrorCode.TagCannotEndHere); } else { AfterHeadStartTagBody(HtmlToken.OpenTag("body")); frameset = true; Consume(token); } } private void InBody(HtmlToken token) { if (token.IsNullChar) RaiseErrorOccurred(ErrorCode.NULL); else if (token.Type == HtmlTokenType.Character) { ReconstructFormatting(); InsertCharacter(((HtmlCharacterToken)token).Data); if (!token.IsIgnoreable) frameset = false; } else if (token.Type == HtmlTokenType.Comment) { AddComment(CurrentNode, token); } else if (token.Type == HtmlTokenType.DOCTYPE) { RaiseErrorOccurred(ErrorCode.DoctypeTagInappropriate); } else if (token.Type == HtmlTokenType.StartTag) { HtmlTagToken htmlTagToken = (HtmlTagToken)token; switch (htmlTagToken.Name) { case "html": RaiseErrorOccurred(ErrorCode.HtmlTagMisplaced); AppendAttributesToElement(htmlTagToken, open[0]); return; case "base": case "basefont": case "bgsound": case "link": case "menuitem": case "meta": case "noframes": case "script": case "style": case "title": InHead(token); return; case "body": RaiseErrorOccurred(ErrorCode.BodyTagMisplaced); if (open.Count > 1 && open[1] is HTMLBodyElement) { frameset = false; AppendAttributesToElement(htmlTagToken, open[1]); } return; case "frameset": RaiseErrorOccurred(ErrorCode.FramesetMisplaced); if (open.Count != 1 && open[1] is HTMLBodyElement && frameset) { open[1].ParentNode.RemoveChild(open[1]); while (open.Count > 1) { CloseCurrentNode(); } HTMLFrameSetElement element12 = new HTMLFrameSetElement(); AddElementToCurrentNode(element12, token, false); insert = HtmlTreeMode.InFrameset; } return; case "address": case "article": case "aside": case "blockquote": case "center": case "details": case "dialog": case "dir": case "div": case "dl": case "fieldset": case "figcaption": case "figure": case "footer": case "header": case "hgroup": case "menu": case "nav": case "ol": case "p": case "section": case "summary": case "ul": { if (IsInButtonScope("p")) InBodyEndTagParagraph(); HTMLElement element15 = HTMLElement.Factory(htmlTagToken.Name); AddElementToCurrentNode(element15, token, false); return; } case "h1": case "h6": case "h5": case "h4": case "h3": case "h2": { if (IsInButtonScope("p")) InBodyEndTagParagraph(); if (CurrentNode is HTMLHeadingElement) { RaiseErrorOccurred(ErrorCode.HeadingNested); CloseCurrentNode(); } HTMLHeadingElement element = new HTMLHeadingElement(); AddElementToCurrentNode(element, token, false); return; } case "pre": case "listing": { if (IsInButtonScope("p")) InBodyEndTagParagraph(); HTMLPreElement element4 = new HTMLPreElement(); AddElementToCurrentNode(element4, token, false); frameset = false; HtmlToken htmlToken = tokenizer.Get(); if (!htmlToken.IsNewLine) Consume(htmlToken); return; } case "form": if (form == null) { if (IsInButtonScope("p")) InBodyEndTagParagraph(); HTMLFormElement element17 = new HTMLFormElement(); AddElementToCurrentNode(element17, token, false); form = element17; } else RaiseErrorOccurred(ErrorCode.FormAlreadyOpen); return; case "li": InBodyStartTagListItem(htmlTagToken); return; case "dd": case "dt": InBodyStartTagDefinitionItem(htmlTagToken); return; case "plaintext": { if (IsInButtonScope("p")) InBodyEndTagParagraph(); HTMLElement element3 = new HTMLElement(); AddElementToCurrentNode(element3, token, false); tokenizer.Switch(HtmlParseMode.Plaintext); return; } case "button": if (IsInScope(htmlTagToken.Name)) { RaiseErrorOccurred(ErrorCode.ButtonInScope); InBodyEndTagBlock(htmlTagToken.Name); InBody(token); } else { ReconstructFormatting(); HTMLButtonElement element19 = new HTMLButtonElement(); AddElementToCurrentNode(element19, token, false); frameset = false; } return; case "a": { for (int num = formatting.Count - 1; num >= 0; num--) { if (formatting[num] is ScopeMarkerNode) break; if (formatting[num].NodeName == "a") { Element item = formatting[num]; RaiseErrorOccurred(ErrorCode.AnchorNested); HeisenbergAlgorithm(HtmlToken.CloseTag("a")); if (open.Contains(item)) open.Remove(item); if (formatting.Contains(item)) formatting.RemoveAt(num); break; } } ReconstructFormatting(); HTMLAnchorElement element18 = new HTMLAnchorElement(); AddElementToCurrentNode(element18, token, false); AddFormattingElement(element18); return; } case "b": case "big": case "code": case "em": case "font": case "i": case "s": case "small": case "strike": case "strong": case "tt": case "u": { ReconstructFormatting(); HTMLElement element16 = HTMLElement.Factory(htmlTagToken.Name); AddElementToCurrentNode(element16, token, false); AddFormattingElement(element16); return; } case "nobr": { ReconstructFormatting(); if (IsInScope("nobr")) { RaiseErrorOccurred(ErrorCode.NobrInScope); HeisenbergAlgorithm(htmlTagToken); ReconstructFormatting(); } HTMLElement element14 = new HTMLElement(); AddElementToCurrentNode(element14, token, false); AddFormattingElement(element14); return; } case "applet": case "marquee": case "object": { ReconstructFormatting(); HTMLElement element11 = HTMLElement.Factory(htmlTagToken.Name); AddElementToCurrentNode(element11, token, false); InsertScopeMarker(); frameset = false; return; } case "table": { if (doc.QuirksMode == QuirksMode.Off && IsInButtonScope("p")) InBodyEndTagParagraph(); HTMLTableElement element8 = new HTMLTableElement(); AddElementToCurrentNode(element8, token, false); frameset = false; insert = HtmlTreeMode.InTable; return; } case "area": case "br": case "embed": case "img": case "keygen": case "wbr": InBodyStartTagBreakrow(htmlTagToken); return; case "input": { ReconstructFormatting(); HTMLInputElement element6 = new HTMLInputElement(); AddElementToCurrentNode(element6, token, true); CloseCurrentNode(); if (!htmlTagToken.GetAttribute("type").Equals("hidden", StringComparison.OrdinalIgnoreCase)) frameset = false; return; } case "param": case "source": case "track": { HTMLElement element5 = HTMLElement.Factory(htmlTagToken.Name); AddElementToCurrentNode(element5, token, true); CloseCurrentNode(); return; } case "hr": { if (IsInButtonScope("p")) InBodyEndTagParagraph(); HTMLHRElement element2 = new HTMLHRElement(); AddElementToCurrentNode(element2, token, true); CloseCurrentNode(); frameset = false; return; } case "image": RaiseErrorOccurred(ErrorCode.ImageTagNamedWrong); htmlTagToken.Name = "img"; goto case "area"; case "isindex": RaiseErrorOccurred(ErrorCode.TagInappropriate); if (form == null) { InBody(HtmlToken.CloseTag("form")); if (htmlTagToken.GetAttribute("action") != string.Empty) form.SetAttribute("action", htmlTagToken.GetAttribute("action")); InBody(HtmlToken.CloseTag("hr")); InBody(HtmlToken.CloseTag("label")); if (htmlTagToken.GetAttribute("prompt") != string.Empty) InsertCharacters(htmlTagToken.GetAttribute("prompt")); else InsertCharacters("This is a searchable index. Enter search keywords:"); HtmlTagToken htmlTagToken2 = HtmlToken.CloseTag("input"); htmlTagToken2.AddAttribute("name", "isindex"); for (int k = 0; k < htmlTagToken.Attributes.Count; k++) { if (!(htmlTagToken.Attributes[k].Key == "name") && !(htmlTagToken.Attributes[k].Key == "action") && !(htmlTagToken.Attributes[k].Key == "prompt")) htmlTagToken2.AddAttribute(htmlTagToken.Attributes[k].Key, htmlTagToken.Attributes[k].Value); } InBody(htmlTagToken2); InBody(HtmlToken.OpenTag("label")); InBody(HtmlToken.CloseTag("hr")); InBody(HtmlToken.OpenTag("form")); } return; case "textarea": { HTMLTextAreaElement element13 = new HTMLTextAreaElement(); AddElementToCurrentNode(element13, token, false); tokenizer.Switch(HtmlParseMode.RCData); originalInsert = insert; frameset = false; insert = HtmlTreeMode.Text; HtmlToken htmlToken2 = tokenizer.Get(); if (!htmlToken2.IsNewLine) Consume(htmlToken2); return; } case "xmp": if (IsInButtonScope("p")) InBodyEndTagParagraph(); ReconstructFormatting(); frameset = false; RawtextAlgorithm(htmlTagToken); return; case "iframe": frameset = false; RawtextAlgorithm(htmlTagToken); return; case "select": { ReconstructFormatting(); HTMLSelectElement element10 = new HTMLSelectElement(); AddElementToCurrentNode(element10, token, false); frameset = false; switch (insert) { case HtmlTreeMode.InTable: case HtmlTreeMode.InCaption: case HtmlTreeMode.InRow: case HtmlTreeMode.InCell: insert = HtmlTreeMode.InSelectInTable; break; default: insert = HtmlTreeMode.InSelect; break; } return; } case "optgroup": case "option": { if (CurrentNode.NodeName == "option") InBodyEndTagAnythingElse(HtmlToken.CloseTag("option")); ReconstructFormatting(); HTMLElement element9 = HTMLElement.Factory(htmlTagToken.Name); AddElementToCurrentNode(element9, token, false); return; } case "rp": case "rt": { if (IsInScope("ruby")) { GenerateImpliedEndTags(); if (CurrentNode.NodeName != "ruby") RaiseErrorOccurred(ErrorCode.TagDoesNotMatchCurrentNode); } HTMLElement element7 = HTMLElement.Factory(htmlTagToken.Name); AddElementToCurrentNode(element7, token, false); return; } case "noembed": RawtextAlgorithm(htmlTagToken); return; case "noscript": if (doc.IsScripting) { RawtextAlgorithm(htmlTagToken); return; } break; case "math": { MathMLElement mathMLElement = new MathMLElement(); mathMLElement.NodeName = htmlTagToken.Name; ReconstructFormatting(); for (int j = 0; j < htmlTagToken.Attributes.Count; j++) { string key2 = htmlTagToken.Attributes[j].Key; string value2 = htmlTagToken.Attributes[j].Value; mathMLElement.SetAttribute(ForeignHelpers.AdjustAttributeName(MathMLHelpers.AdjustAttributeName(key2)), value2); } CurrentNode.AppendChild(mathMLElement); if (!htmlTagToken.IsSelfClosing) { open.Add(mathMLElement); tokenizer.AcceptsCDATA = true; } return; } case "svg": { SVGElement sVGElement = new SVGElement(); sVGElement.NodeName = htmlTagToken.Name; ReconstructFormatting(); for (int i = 0; i < htmlTagToken.Attributes.Count; i++) { string key = htmlTagToken.Attributes[i].Key; string value = htmlTagToken.Attributes[i].Value; sVGElement.SetAttribute(ForeignHelpers.AdjustAttributeName(MathMLHelpers.AdjustAttributeName(key)), value); } CurrentNode.AppendChild(sVGElement); if (!htmlTagToken.IsSelfClosing) { open.Add(sVGElement); tokenizer.AcceptsCDATA = true; } return; } case "caption": case "col": case "colgroup": case "frame": case "head": case "tbody": case "td": case "tfoot": case "th": case "thead": case "tr": RaiseErrorOccurred(ErrorCode.TagCannotStartHere); return; } ReconstructFormatting(); HTMLUnknownElement element20 = new HTMLUnknownElement(); AddElementToCurrentNode(element20, token, false); } else if (token.Type == HtmlTokenType.EndTag) { HtmlTagToken htmlTagToken3 = (HtmlTagToken)token; switch (htmlTagToken3.Name) { case "body": InBodyEndTagBody(); break; case "html": if (InBodyEndTagBody()) AfterBody(token); break; case "address": case "article": case "aside": case "blockquote": case "button": case "center": case "details": case "dialog": case "dir": case "div": case "dl": case "fieldset": case "figcaption": case "figure": case "footer": case "header": case "hgroup": case "listing": case "main": case "menu": case "nav": case "ol": case "pre": case "section": case "summary": case "ul": InBodyEndTagBlock(htmlTagToken3.Name); break; case "form": { HTMLFormElement hTMLFormElement = form; form = null; if (hTMLFormElement != null && IsInScope(hTMLFormElement.NodeName)) { GenerateImpliedEndTags(); if (CurrentNode != hTMLFormElement) RaiseErrorOccurred(ErrorCode.FormClosedWrong); open.Remove(hTMLFormElement); } else RaiseErrorOccurred(ErrorCode.FormNotInScope); break; } case "p": InBodyEndTagParagraph(); break; case "li": if (IsInListItemScope(htmlTagToken3.Name)) { GenerateImpliedEndTagsExceptFor(htmlTagToken3.Name); if (CurrentNode.NodeName != htmlTagToken3.Name) RaiseErrorOccurred(ErrorCode.TagDoesNotMatchCurrentNode); ClearStackBackTo(htmlTagToken3.Name); CloseCurrentNode(); } else RaiseErrorOccurred(ErrorCode.ListItemNotInScope); break; case "dd": case "dt": if (IsInScope(htmlTagToken3.Name)) { GenerateImpliedEndTagsExceptFor(htmlTagToken3.Name); if (CurrentNode.NodeName != htmlTagToken3.Name) RaiseErrorOccurred(ErrorCode.TagDoesNotMatchCurrentNode); ClearStackBackTo(htmlTagToken3.Name); CloseCurrentNode(); } else RaiseErrorOccurred(ErrorCode.ListItemNotInScope); break; case "h1": case "h6": case "h5": case "h4": case "h3": case "h2": if (IsHeadingInScope()) { GenerateImpliedEndTags(); if (CurrentNode.NodeName != htmlTagToken3.Name) RaiseErrorOccurred(ErrorCode.TagDoesNotMatchCurrentNode); ClearStackBackToHeading(); CloseCurrentNode(); } else RaiseErrorOccurred(ErrorCode.HeadingNotInScope); break; case "a": case "b": case "big": case "code": case "em": case "font": case "i": case "nobr": case "s": case "small": case "strike": case "strong": case "tt": case "u": HeisenbergAlgorithm(htmlTagToken3); break; case "applet": case "marquee": case "object": if (IsInScope(htmlTagToken3.Name)) { GenerateImpliedEndTags(); if (CurrentNode.NodeName != htmlTagToken3.Name) RaiseErrorOccurred(ErrorCode.TagDoesNotMatchCurrentNode); ClearStackBackTo(htmlTagToken3.Name); CloseCurrentNode(); ClearFormattingElements(); } else RaiseErrorOccurred(ErrorCode.ObjectNotInScope); break; case "br": RaiseErrorOccurred(ErrorCode.TagCannotEndHere); InBodyStartTagBreakrow(HtmlToken.OpenTag("br")); break; default: InBodyEndTagAnythingElse(htmlTagToken3); break; } } else if (token.Type == HtmlTokenType.EOF) { for (int l = 0; l < open.Count; l++) { switch (open[l].NodeName) { default: RaiseErrorOccurred(ErrorCode.BodyClosedWrong); l = open.Count; break; case "dt": case "dd": case "li": case "p": case "tbody": case "th": case "tfoot": case "td": case "thead": case "tr": case "body": case "html": break; } } End(); } } private void Text(HtmlToken token) { if (token.Type == HtmlTokenType.Character) InsertCharacter(((HtmlCharacterToken)token).Data); else if (token.Type == HtmlTokenType.EOF) { RaiseErrorOccurred(ErrorCode.EOF); if (CurrentNode is HTMLScriptElement) ((HTMLScriptElement)CurrentNode).IsAlreadyStarted = true; CloseCurrentNode(); insert = originalInsert; Consume(token); } else if (token.Type == HtmlTokenType.EndTag) { HtmlTagToken htmlTagToken = (HtmlTagToken)token; if (htmlTagToken.Name == "script") { PerformMicrotaskCheckpoint(); ProvideStableState(); HTMLScriptElement hTMLScriptElement = (HTMLScriptElement)CurrentNode; CloseCurrentNode(); insert = originalInsert; int insertionPoint = tokenizer.Stream.InsertionPoint; nesting++; hTMLScriptElement.Prepare(); nesting--; if (nesting == 0) pause = false; tokenizer.Stream.InsertionPoint = insertionPoint; if (pendingParsingBlock != null) { if (nesting == 0) { do { hTMLScriptElement = pendingParsingBlock; pendingParsingBlock = null; insertionPoint = tokenizer.Stream.InsertionPoint; nesting++; hTMLScriptElement.Execute(); nesting--; if (nesting == 0) pause = false; tokenizer.Stream.ResetInsertionPoint(); } while (pendingParsingBlock != null); } else pause = true; } } else { CloseCurrentNode(); insert = originalInsert; } } } private void InTable(HtmlToken token) { if (token.Type == HtmlTokenType.Comment) AddComment(CurrentNode, token); else if (token.Type == HtmlTokenType.DOCTYPE) { RaiseErrorOccurred(ErrorCode.DoctypeTagInappropriate); } else if (token.Type == HtmlTokenType.StartTag) { HtmlTagToken htmlTagToken = (HtmlTagToken)token; switch (htmlTagToken.Name) { case "caption": { ClearStackBackToTable(); InsertScopeMarker(); HTMLTableCaptionElement element5 = new HTMLTableCaptionElement(); AddElementToCurrentNode(element5, token, false); insert = HtmlTreeMode.InCaption; break; } case "colgroup": { ClearStackBackToTable(); HTMLTableColElement element4 = new HTMLTableColElement(); AddElementToCurrentNode(element4, token, false); insert = HtmlTreeMode.InColumnGroup; break; } case "col": InTable(HtmlToken.OpenTag("colgroup")); InColumnGroup(token); break; case "tbody": case "thead": case "tfoot": { ClearStackBackToTable(); HTMLTableSectionElement element2 = new HTMLTableSectionElement(); AddElementToCurrentNode(element2, token, false); insert = HtmlTreeMode.InTableBody; break; } case "td": case "th": case "tr": InTable(HtmlToken.OpenTag("tbody")); InTableBody(token); break; case "table": RaiseErrorOccurred(ErrorCode.TableNesting); if (InTableEndTagTable()) Consume(token); break; case "script": case "style": InHead(token); break; case "input": if (htmlTagToken.GetAttribute("type").Equals("hidden", StringComparison.OrdinalIgnoreCase)) { RaiseErrorOccurred(ErrorCode.InputUnexpected); HTMLInputElement element3 = new HTMLInputElement(); AddElementToCurrentNode(element3, token, true); CloseCurrentNode(); } else { RaiseErrorOccurred(ErrorCode.TokenNotPossible); InBodyWithFoster(token); } break; case "form": RaiseErrorOccurred(ErrorCode.FormInappropriate); if (form == null) { HTMLFormElement element = new HTMLFormElement(); AddElementToCurrentNode(element, token, false); form = element; CloseCurrentNode(); } break; default: RaiseErrorOccurred(ErrorCode.IllegalElementInTableDetected); InBodyWithFoster(token); break; } } else if (token.Type == HtmlTokenType.EndTag) { HtmlTagToken htmlTagToken2 = (HtmlTagToken)token; switch (htmlTagToken2.Name) { case "table": InTableEndTagTable(); break; case "body": case "colgroup": case "col": case "caption": case "html": case "tbody": case "tr": case "thead": case "th": case "tfoot": case "td": RaiseErrorOccurred(ErrorCode.TagCannotEndHere); break; default: RaiseErrorOccurred(ErrorCode.IllegalElementInTableDetected); InBodyWithFoster(token); break; } } else if (token.Type == HtmlTokenType.Character && CurrentNode != null && CurrentNode.IsTableElement()) { tableCharacters.Clear(); originalInsert = insert; insert = HtmlTreeMode.InTableText; InTableText(token); } else if (token.Type == HtmlTokenType.EOF) { if (CurrentNode != doc.DocumentElement) RaiseErrorOccurred(ErrorCode.CurrentNodeIsNotRoot); End(); } else { RaiseErrorOccurred(ErrorCode.TokenNotPossible); InBodyWithFoster(token); } } private void InTableText(HtmlToken token) { if (token.IsNullChar) RaiseErrorOccurred(ErrorCode.NULL); else if (token.Type == HtmlTokenType.Character) { tableCharacters.Append(((HtmlCharacterToken)token).Data); } else { bool flag = false; for (int i = 0; i != tableCharacters.Length; i++) { if (!Specification.IsSpaceCharacter(tableCharacters[i])) { RaiseErrorOccurred(ErrorCode.TokenNotPossible); flag = true; break; } } if (flag) { for (int j = 0; j != tableCharacters.Length; j++) { InBodyWithFoster(HtmlToken.Character(tableCharacters[j])); } } else { for (int k = 0; k != tableCharacters.Length; k++) { InsertCharacter(tableCharacters[k]); } } tableCharacters.Clear(); insert = originalInsert; Consume(token); } } private void InCaption(HtmlToken token) { if (token.Type == HtmlTokenType.EndTag) { HtmlTagToken htmlTagToken = (HtmlTagToken)token; switch (htmlTagToken.Name) { case "caption": InCaptionEndTagCaption(); break; case "body": case "th": case "colgroup": case "html": case "tbody": case "col": case "tfoot": case "td": case "thead": case "tr": RaiseErrorOccurred(ErrorCode.TagCannotEndHere); break; case "table": RaiseErrorOccurred(ErrorCode.TableNesting); if (InCaptionEndTagCaption()) InTable(token); break; default: InBody(token); break; } } else if (token.Type == HtmlTokenType.StartTag) { HtmlTagToken htmlTagToken2 = (HtmlTagToken)token; switch (htmlTagToken2.Name) { case "caption": case "col": case "colgroup": case "tbody": case "td": case "tfoot": case "th": case "thead": case "tr": RaiseErrorOccurred(ErrorCode.TagCannotStartHere); if (InCaptionEndTagCaption()) InTable(token); break; default: InBody(token); break; } } else { InBody(token); } } private void InColumnGroup(HtmlToken token) { if (token.IsIgnoreable) InsertCharacter(((HtmlCharacterToken)token).Data); else if (token.Type == HtmlTokenType.Comment) { AddComment(CurrentNode, token); } else if (token.Type == HtmlTokenType.DOCTYPE) { RaiseErrorOccurred(ErrorCode.DoctypeTagInappropriate); } else if (token.Type == HtmlTokenType.StartTag && ((HtmlTagToken)token).Name == "html") { InBody(token); } else if (token.Type == HtmlTokenType.StartTag && ((HtmlTagToken)token).Name == "col") { HTMLTableColElement element = new HTMLTableColElement(); AddElementToCurrentNode(element, token, true); CloseCurrentNode(); } else if (token.Type == HtmlTokenType.EndTag && ((HtmlTagToken)token).Name == "colgroup") { InColumnGroupEndTagColgroup(); } else if (token.Type == HtmlTokenType.EndTag && ((HtmlTagToken)token).Name == "col") { RaiseErrorOccurred(ErrorCode.TagClosedWrong); } else if (token.Type == HtmlTokenType.EOF && CurrentNode == doc.DocumentElement) { End(); } else if (InColumnGroupEndTagColgroup()) { InTable(token); } } private void InTableBody(HtmlToken token) { if (token.Type == HtmlTokenType.StartTag) { HtmlTagToken htmlTagToken = (HtmlTagToken)token; if (htmlTagToken.Name == "tr") { ClearStackBackToTableSection(); HTMLTableRowElement element = new HTMLTableRowElement(); AddElementToCurrentNode(element, token, false); insert = HtmlTreeMode.InRow; } else if (htmlTagToken.Name.IsTableCellElement()) { InTableBody(HtmlToken.CloseTag("tr")); InRow(token); } else if (htmlTagToken.Name.IsGeneralTableElement(false)) { InTableBodyCloseTable(htmlTagToken); } else { InTable(token); } } else if (token.Type == HtmlTokenType.EndTag) { HtmlTagToken htmlTagToken2 = (HtmlTagToken)token; if (htmlTagToken2.Name.IsTableSectionElement()) { if (IsInTableScope(((HtmlTagToken)token).Name)) { ClearStackBackToTableSection(); CloseCurrentNode(); insert = HtmlTreeMode.InTable; } else RaiseErrorOccurred(ErrorCode.TableSectionNotInScope); } else if (htmlTagToken2.Name.IsSpecialTableElement(true)) { RaiseErrorOccurred(ErrorCode.TagCannotEndHere); } else if (htmlTagToken2.Name == "table") { InTableBodyCloseTable(htmlTagToken2); } else { InTable(token); } } else { InTable(token); } } private void InRow(HtmlToken token) { if (token.Type == HtmlTokenType.StartTag) { HtmlTagToken htmlTagToken = (HtmlTagToken)token; if (htmlTagToken.Name.IsTableCellElement()) { ClearStackBackToTableRow(); HTMLTableCellElement element = new HTMLTableCellElement(); AddElementToCurrentNode(element, token, false); insert = HtmlTreeMode.InCell; InsertScopeMarker(); } else if (htmlTagToken.Name.IsGeneralTableElement(true)) { if (InRowEndTagTablerow()) InTableBody(token); } else { InTable(token); } } else if (token.Type == HtmlTokenType.EndTag) { HtmlTagToken htmlTagToken2 = (HtmlTagToken)token; if (htmlTagToken2.Name == "tr") InRowEndTagTablerow(); else if (htmlTagToken2.Name == "table") { if (InRowEndTagTablerow()) InTableBody(token); } else if (htmlTagToken2.Name.IsTableSectionElement()) { if (IsInTableScope(htmlTagToken2.Name)) { InRowEndTagTablerow(); InTableBody(token); } else RaiseErrorOccurred(ErrorCode.TableSectionNotInScope); } else if (htmlTagToken2.Name.IsSpecialTableElement(false)) { RaiseErrorOccurred(ErrorCode.TagCannotEndHere); } else { InTable(token); } } else { InTable(token); } } private void InCell(HtmlToken token) { if (token.Type == HtmlTokenType.EndTag) { HtmlTagToken htmlTagToken = (HtmlTagToken)token; if (htmlTagToken.Name.IsTableCellElement()) InCellEndTagCell(((HtmlTagToken)token).Name); else if (htmlTagToken.Name.IsSpecialTableElement(false)) { RaiseErrorOccurred(ErrorCode.TagCannotEndHere); } else if (htmlTagToken.Name.IsTableElement()) { if (IsInTableScope(htmlTagToken.Name)) { CloseTheCell(); Consume(token); } else RaiseErrorOccurred(ErrorCode.TableNotInScope); } else { InBody(token); } } else if (token.Type == HtmlTokenType.StartTag && (((HtmlTagToken)token).Name.IsGeneralTableElement(true) || ((HtmlTagToken)token).Name.IsTableCellElement())) { HtmlTagToken htmlTagToken2 = (HtmlTagToken)token; if (IsInTableScope("td") || IsInTableScope("th")) { CloseTheCell(); Consume(token); } else RaiseErrorOccurred(ErrorCode.TableCellNotInScope); } else { InBody(token); } } private void InSelect(HtmlToken token) { if (token.IsNullChar) RaiseErrorOccurred(ErrorCode.NULL); else if (token.Type == HtmlTokenType.Character) { InsertCharacter(((HtmlCharacterToken)token).Data); } else if (token.Type == HtmlTokenType.Comment) { AddComment(CurrentNode, token); } else if (token.Type == HtmlTokenType.DOCTYPE) { RaiseErrorOccurred(ErrorCode.DoctypeTagInappropriate); } else if (token.Type == HtmlTokenType.StartTag) { HtmlTagToken htmlTagToken = (HtmlTagToken)token; switch (htmlTagToken.Name) { case "html": InBody(token); break; case "option": { if (CurrentNode.NodeName == "option") InSelectEndTagOption(); HTMLOptionElement element2 = new HTMLOptionElement(); AddElementToCurrentNode(element2, token, false); break; } case "optgroup": { if (CurrentNode.NodeName == "option") InSelectEndTagOption(); if (CurrentNode.NodeName == "optgroup") InSelectEndTagOptgroup(); HTMLOptGroupElement element = new HTMLOptGroupElement(); AddElementToCurrentNode(element, token, false); break; } case "select": RaiseErrorOccurred(ErrorCode.SelectNesting); InSelectEndTagSelect(); break; case "input": case "keygen": case "textarea": RaiseErrorOccurred(ErrorCode.IllegalElementInSelectDetected); if (IsInSelectScope("select")) { InSelectEndTagSelect(); Consume(token); } break; case "script": InHead(token); break; default: RaiseErrorOccurred(ErrorCode.IllegalElementInSelectDetected); break; } } else if (token.Type == HtmlTokenType.EndTag) { HtmlTagToken htmlTagToken2 = (HtmlTagToken)token; switch (htmlTagToken2.Name) { case "optgroup": InSelectEndTagOptgroup(); break; case "option": InSelectEndTagOption(); break; case "select": InSelectEndTagSelect(); break; default: RaiseErrorOccurred(ErrorCode.TagCannotEndHere); break; } } else if (token.Type == HtmlTokenType.EOF) { if (CurrentNode != doc.DocumentElement) RaiseErrorOccurred(ErrorCode.CurrentNodeIsNotRoot); End(); } else { RaiseErrorOccurred(ErrorCode.TokenNotPossible); } } private void InSelectInTable(HtmlToken token) { HtmlTagToken htmlTagToken = token as HtmlTagToken; if (htmlTagToken != null && (htmlTagToken.Name.IsTableCellElement() || htmlTagToken.Name.IsTableElement() || htmlTagToken.Name == "caption")) { if (token.Type == HtmlTokenType.StartTag) { RaiseErrorOccurred(ErrorCode.IllegalElementInSelectDetected); InSelectEndTagSelect(); Consume(token); } else { RaiseErrorOccurred(ErrorCode.TagCannotEndHere); if (IsInTableScope(htmlTagToken.Name)) { InSelectEndTagSelect(); Consume(token); } } } else InSelect(token); } private void AfterBody(HtmlToken token) { if (token.IsIgnoreable) InBody(token); else if (token.Type == HtmlTokenType.Comment) { AddComment(CurrentNode, token); } else if (token.Type == HtmlTokenType.DOCTYPE) { RaiseErrorOccurred(ErrorCode.DoctypeTagInappropriate); } else if (token is HtmlTagToken && ((HtmlTagToken)token).Name == "html") { if (token.Type == HtmlTokenType.StartTag) InBody(token); else if (fragment) { RaiseErrorOccurred(ErrorCode.TagInvalidInFragmentMode); } else { insert = HtmlTreeMode.AfterAfterBody; } } else if (token.Type == HtmlTokenType.EOF) { End(); } else { RaiseErrorOccurred(ErrorCode.TokenNotPossible); insert = HtmlTreeMode.InBody; InBody(token); } } private void InFrameset(HtmlToken token) { if (token.IsIgnoreable) InsertCharacter(((HtmlCharacterToken)token).Data); else if (token.Type == HtmlTokenType.Comment) { AddComment(CurrentNode, token); } else if (token.Type == HtmlTokenType.DOCTYPE) { RaiseErrorOccurred(ErrorCode.DoctypeTagInappropriate); } else if (token.Type == HtmlTokenType.StartTag) { HtmlTagToken htmlTagToken = (HtmlTagToken)token; if (htmlTagToken.Name == "html") InBody(token); else if (htmlTagToken.Name == "frameset") { HTMLFrameSetElement element = new HTMLFrameSetElement(); AddElementToCurrentNode(element, token, false); } else if (htmlTagToken.Name == "frame") { HTMLFrameElement element2 = new HTMLFrameElement(); AddElementToCurrentNode(element2, token, true); CloseCurrentNode(); } else if (htmlTagToken.Name == "noframes") { InHead(token); } else { RaiseErrorOccurred(ErrorCode.TokenNotPossible); } } else if (token.Type == HtmlTokenType.EndTag && ((HtmlTagToken)token).Name == "frameset") { if (CurrentNode != doc.DocumentElement) { CloseCurrentNode(); if (fragment && CurrentNode.NodeName != "frameset") insert = HtmlTreeMode.AfterFrameset; } else RaiseErrorOccurred(ErrorCode.CurrentNodeIsRoot); } else if (token.Type == HtmlTokenType.EOF) { if (CurrentNode != doc.DocumentElement) RaiseErrorOccurred(ErrorCode.CurrentNodeIsNotRoot); End(); } else { RaiseErrorOccurred(ErrorCode.TokenNotPossible); } } private void AfterFrameset(HtmlToken token) { if (token.IsIgnoreable) InsertCharacter(((HtmlCharacterToken)token).Data); else if (token.Type == HtmlTokenType.Comment) { AddComment(CurrentNode, token); } else if (token.Type == HtmlTokenType.DOCTYPE) { RaiseErrorOccurred(ErrorCode.DoctypeTagInappropriate); } else if (token.Type == HtmlTokenType.StartTag) { HtmlTagToken htmlTagToken = (HtmlTagToken)token; if (htmlTagToken.Name == "html") InBody(token); else if (htmlTagToken.Name == "noframes") { InHead(token); } else { RaiseErrorOccurred(ErrorCode.TokenNotPossible); } } else if (token.Type == HtmlTokenType.EndTag && ((HtmlTagToken)token).Name == "html") { insert = HtmlTreeMode.AfterAfterFrameset; } else if (token.Type == HtmlTokenType.EOF) { End(); } else { RaiseErrorOccurred(ErrorCode.TokenNotPossible); } } private void AfterAfterBody(HtmlToken token) { if (token.Type == HtmlTokenType.Comment) AddComment(doc, token); else if (token.Type == HtmlTokenType.DOCTYPE || token.IsIgnoreable || (token.Type == HtmlTokenType.StartTag && ((HtmlTagToken)token).Name == "html")) { InBody(token); } else if (token.Type == HtmlTokenType.EOF) { End(); } else { RaiseErrorOccurred(ErrorCode.TokenNotPossible); insert = HtmlTreeMode.InBody; InBody(token); } } private void AfterAfterFrameset(HtmlToken token) { if (token.Type == HtmlTokenType.Comment) AddComment(doc, token); else if (token.Type == HtmlTokenType.DOCTYPE || token.IsIgnoreable || (token.Type == HtmlTokenType.StartTag && ((HtmlTagToken)token).Name == "html")) { InBody(token); } else if (token.Type == HtmlTokenType.StartTag && ((HtmlTagToken)token).Name == "noframes") { InHead(token); } else if (token.Type == HtmlTokenType.EOF) { End(); } else { RaiseErrorOccurred(ErrorCode.TokenNotPossible); } } private void InTableBodyCloseTable(HtmlTagToken tag) { if (IsSectionInTableScope()) { ClearStackBackToTableSection(); CloseCurrentNode(); insert = HtmlTreeMode.InTable; InTable(tag); } else RaiseErrorOccurred(ErrorCode.TableSectionNotInScope); } private void InSelectEndTagOption() { if (CurrentNode.NodeName == "option") CloseCurrentNode(); else RaiseErrorOccurred(ErrorCode.TagDoesNotMatchCurrentNode); } private void InSelectEndTagOptgroup() { if (open.Count > 1 && open[open.Count - 1] is HTMLOptionElement && open[open.Count - 2] is HTMLOptGroupElement) CloseCurrentNode(); if (CurrentNode is HTMLOptGroupElement) CloseCurrentNode(); else RaiseErrorOccurred(ErrorCode.TagDoesNotMatchCurrentNode); } private bool InColumnGroupEndTagColgroup() { if (CurrentNode != doc.DocumentElement) { CloseCurrentNode(); insert = HtmlTreeMode.InTable; return true; } RaiseErrorOccurred(ErrorCode.CurrentNodeIsRoot); return false; } private void AfterHeadStartTagBody(HtmlTagToken token) { HTMLBodyElement element = new HTMLBodyElement(); AddElementToCurrentNode(element, token, false); frameset = false; insert = HtmlTreeMode.InBody; } private void RawtextAlgorithm(HtmlTagToken tag) { HTMLElement element = HTMLElement.Factory(tag.Name); AddElementToCurrentNode(element, tag, false); originalInsert = insert; insert = HtmlTreeMode.Text; tokenizer.Switch(HtmlParseMode.Rawtext); } private void RCDataAlgorithm(HtmlTagToken tag) { HTMLElement element = HTMLElement.Factory(tag.Name); AddElementToCurrentNode(element, tag, false); originalInsert = insert; insert = HtmlTreeMode.Text; tokenizer.Switch(HtmlParseMode.RCData); } private void InBodyStartTagListItem(HtmlTagToken tag) { frameset = false; int num = open.Count - 1; Element element = open[num]; while (true) { if (element.NodeName == "li") { InBody(HtmlToken.CloseTag(element.NodeName)); break; } if (element.IsSpecial && element.NodeName != "address" && !(element is HTMLDivElement) && !(element is HTMLParagraphElement)) break; element = open[--num]; } if (IsInButtonScope("p")) InBodyEndTagParagraph(); HTMLElement element2 = HTMLElement.Factory(tag.Name); AddElementToCurrentNode(element2, tag, false); } private void InBodyStartTagDefinitionItem(HtmlTagToken tag) { frameset = false; int num = open.Count - 1; Element element = open[num]; while (true) { if (element.NodeName == "dd" || element.NodeName == "dt") { InBody(HtmlToken.CloseTag(element.NodeName)); break; } if (element.IsSpecial && element.NodeName != "address" && !(element is HTMLDivElement) && !(element is HTMLParagraphElement)) break; element = open[--num]; } if (IsInButtonScope("p")) InBodyEndTagParagraph(); HTMLElement element2 = HTMLElement.Factory(tag.Name); AddElementToCurrentNode(element2, tag, false); } private bool InBodyEndTagBlock(string tagName) { if (IsInScope(tagName)) { GenerateImpliedEndTags(); if (CurrentNode.NodeName != tagName) RaiseErrorOccurred(ErrorCode.TagDoesNotMatchCurrentNode); ClearStackBackTo(tagName); CloseCurrentNode(); return true; } RaiseErrorOccurred(ErrorCode.BlockNotInScope); return false; } private void HeisenbergAlgorithm(HtmlTagToken tag) { int num = 0; Element element; Element element2; while (true) { if (num >= 8) return; num++; int num2 = 0; element = null; for (int num3 = formatting.Count - 1; num3 >= 0; num3--) { if (formatting[num3] is ScopeMarkerNode) break; if (formatting[num3].NodeName == tag.Name) { num2 = num3; element = formatting[num3]; break; } } if (element == null) { InBodyEndTagAnythingElse(tag); return; } int num4 = -1; for (int i = 0; i < open.Count; i++) { if (open[i] == element) { num4 = i; break; } } if (num4 == -1) { RaiseErrorOccurred(ErrorCode.FormattingElementNotFound); formatting.Remove(element); return; } if (!IsInScope(element.NodeName)) { RaiseErrorOccurred(ErrorCode.ElementNotInScope); return; } if (num4 != open.Count - 1) RaiseErrorOccurred(ErrorCode.TagClosedWrong); element2 = null; int num5 = num2; for (int j = num4 + 1; j < open.Count; j++) { if (open[j].IsSpecial) { num2 = j; element2 = open[j]; break; } } if (element2 == null) break; Element element3 = open[num4 - 1]; int num6 = 0; Element element4 = element2; Element element5 = element2; while (num6 < 3) { num6++; element4 = open[--num2]; if (!formatting.Contains(element4)) open.Remove(element4); else { if (element4 == element) break; HTMLElement hTMLElement = HTMLElement.Factory(element4.NodeName); hTMLElement.NodeName = element4.NodeName; for (int k = 0; k < element4.Attributes.Length; k++) { Attr attr = element4.Attributes[k]; hTMLElement.SetAttribute(attr.NodeName, attr.NodeValue); } open[num2] = hTMLElement; for (int l = 0; l != formatting.Count; l++) { if (formatting[l] == element4) { formatting[l] = hTMLElement; break; } } element4 = hTMLElement; if (element5 == element2) num5++; element4.AppendChild(element5); element5 = element4; } } if (element3.IsTableElement()) AddElementWithFoster(element5); else { if (element5.ParentNode != null) element5.ParentNode.RemoveChild(element5); element3.AppendChild(element5); } HTMLElement hTMLElement2 = HTMLElement.Factory(element.NodeName); hTMLElement2.NodeName = element.NodeName; for (int m = 0; m < element.Attributes.Length; m++) { Attr attr2 = element.Attributes[m]; hTMLElement2.SetAttribute(attr2.NodeName, attr2.NodeValue); } for (int num7 = element2.ChildNodes.Length - 1; num7 >= 0; num7--) { hTMLElement2.AppendChild(element2.RemoveChild(element2.ChildNodes[num7])); } element2.AppendChild(hTMLElement2); formatting.Remove(element); formatting.Insert(num5, element2); open.Remove(element); open.Insert(num2 + 1, hTMLElement2); } do { element2 = CurrentNode; CloseCurrentNode(); } while (element2 != element); formatting.Remove(element); } private void InBodyWithFoster(HtmlToken token) { foster = true; InBody(token); foster = false; } private void InBodyEndTagAnythingElse(HtmlTagToken tag) { int num = open.Count - 1; Element element = CurrentNode; while (true) { if (element.NodeName == tag.Name) { GenerateImpliedEndTagsExceptFor(tag.Name); if (element.NodeName == tag.Name) RaiseErrorOccurred(ErrorCode.TagClosedWrong); int num2 = open.Count - 1; while (num <= num2) { CloseCurrentNode(); num2--; } return; } if (element.IsSpecial) break; element = open[--num]; } RaiseErrorOccurred(ErrorCode.TagClosedWrong); } private bool InBodyEndTagBody() { if (IsInScope("body")) { for (int i = 0; i < open.Count; i++) { switch (open[i].NodeName) { default: RaiseErrorOccurred(ErrorCode.BodyClosedWrong); i = open.Count; break; case "dd": case "dt": case "li": case "optgroup": case "option": case "p": case "rp": case "rt": case "tbody": case "td": case "tfoot": case "th": case "thead": case "tr": case "body": case "html": break; } } insert = HtmlTreeMode.AfterBody; return true; } RaiseErrorOccurred(ErrorCode.BodyNotInScope); return false; } private void InBodyStartTagBreakrow(HtmlTagToken tag) { ReconstructFormatting(); HTMLElement element = HTMLElement.Factory(tag.Name); AddElementToCurrentNode(element, tag, false); CloseCurrentNode(); frameset = false; } private bool InBodyEndTagParagraph() { if (IsInButtonScope("p")) { GenerateImpliedEndTagsExceptFor("p"); if (CurrentNode.NodeName != "p") RaiseErrorOccurred(ErrorCode.TagDoesNotMatchCurrentNode); ClearStackBackTo("p"); CloseCurrentNode(); return true; } RaiseErrorOccurred(ErrorCode.ParagraphNotInScope); InBody(HtmlToken.OpenTag("p")); InBodyEndTagParagraph(); return false; } private bool InTableEndTagTable() { if (IsInTableScope("table")) { ClearStackBackTo("table"); CloseCurrentNode(); Reset(null); return true; } RaiseErrorOccurred(ErrorCode.TableNotInScope); return false; } private bool InRowEndTagTablerow() { if (IsInTableScope("tr")) { ClearStackBackToTableRow(); CloseCurrentNode(); insert = HtmlTreeMode.InTableBody; return true; } RaiseErrorOccurred(ErrorCode.TableRowNotInScope); return false; } private bool InSelectEndTagSelect() { if (IsInSelectScope("select")) { ClearStackBackTo("select"); CloseCurrentNode(); Reset(null); return true; } RaiseErrorOccurred(ErrorCode.SelectNotInScope); return false; } private bool InCaptionEndTagCaption() { if (IsInTableScope("caption")) { GenerateImpliedEndTags(); if (CurrentNode.NodeName != "caption") RaiseErrorOccurred(ErrorCode.TagDoesNotMatchCurrentNode); ClearStackBackTo("caption"); CloseCurrentNode(); ClearFormattingElements(); insert = HtmlTreeMode.InTable; return true; } RaiseErrorOccurred(ErrorCode.CaptionNotInScope); return false; } private bool InCellEndTagCell(string tagName) { if (IsInTableScope(tagName)) { GenerateImpliedEndTags(); if (CurrentNode.NodeName != tagName) RaiseErrorOccurred(ErrorCode.TagDoesNotMatchCurrentNode); ClearStackBackTo(tagName); CloseCurrentNode(); ClearFormattingElements(); insert = HtmlTreeMode.InRow; return true; } RaiseErrorOccurred(ErrorCode.TableCellNotInScope); return false; } private void Foreign(HtmlToken token) { if (token.IsNullChar) { RaiseErrorOccurred(ErrorCode.NULL); InsertCharacter('�'); } else if (token.IsIgnoreable) { InsertCharacter(((HtmlCharacterToken)token).Data); } else if (token.Type == HtmlTokenType.Character) { InsertCharacter(((HtmlCharacterToken)token).Data); frameset = false; } else if (token.Type == HtmlTokenType.Comment) { AddComment(CurrentNode, token); } else if (token.Type == HtmlTokenType.DOCTYPE) { RaiseErrorOccurred(ErrorCode.DoctypeTagInappropriate); } else if (token.Type == HtmlTokenType.StartTag) { HtmlTagToken htmlTagToken = (HtmlTagToken)token; switch (htmlTagToken.Name) { case "b": case "big": case "blockquote": case "body": case "br": case "center": case "code": case "dd": case "div": case "dl": case "dt": case "em": case "embed": case "h1": case "h6": case "h5": case "h4": case "h3": case "h2": case "head": case "hr": case "i": case "img": case "li": case "listing": case "main": case "menu": case "meta": case "nobr": case "ol": case "p": case "pre": case "ruby": case "s": case "small": case "span": case "strong": case "strike": case "sub": case "sup": case "table": case "tt": case "u": case "ul": case "var": RaiseErrorOccurred(ErrorCode.TagCannotStartHere); CloseCurrentNode(); while (!CurrentNode.IsHtmlTIP && !CurrentNode.IsMathMLTIP && !CurrentNode.IsInHtml) { CloseCurrentNode(); } Consume(token); return; case "font": { int num = 0; while (num != htmlTagToken.Attributes.Count) { if (!(htmlTagToken.Attributes[num].Key == "color") && !(htmlTagToken.Attributes[num].Key == "face") && !(htmlTagToken.Attributes[num].Key == "size")) { num++; continue; } goto case "b"; } break; } } Element element; if (CurrentNode.IsInMathML) { element = new MathMLElement(); element.NodeName = htmlTagToken.Name; for (int i = 0; i < htmlTagToken.Attributes.Count; i++) { string key = htmlTagToken.Attributes[i].Key; string value = htmlTagToken.Attributes[i].Value; element.SetAttribute(ForeignHelpers.AdjustAttributeName(MathMLHelpers.AdjustAttributeName(key)), value); } } else { element = new SVGElement(); element.NodeName = SVGHelpers.AdjustTagName(htmlTagToken.Name); for (int j = 0; j < htmlTagToken.Attributes.Count; j++) { string key2 = htmlTagToken.Attributes[j].Key; string value2 = htmlTagToken.Attributes[j].Value; element.SetAttribute(ForeignHelpers.AdjustAttributeName(SVGHelpers.AdjustAttributeName(key2)), value2); } } element.NamespaceURI = CurrentNode.NamespaceURI; CurrentNode.AppendChild(element); open.Add(element); if (!htmlTagToken.IsSelfClosing) tokenizer.AcceptsCDATA = true; else if (htmlTagToken.Name == "script") { Foreign(HtmlToken.CloseTag("script")); } } else if (token.Type == HtmlTokenType.EndTag) { HtmlTagToken htmlTagToken2 = (HtmlTagToken)token; if (CurrentNode != null && CurrentNode is HTMLScriptElement && htmlTagToken2.Name == "script") { CloseCurrentNode(); int insertionPoint = tokenizer.Stream.InsertionPoint; nesting++; pause = true; InSvg(htmlTagToken2); nesting--; if (nesting == 0) pause = false; tokenizer.Stream.InsertionPoint = insertionPoint; } else { Element currentNode = CurrentNode; if (currentNode.NodeName != htmlTagToken2.Name) RaiseErrorOccurred(ErrorCode.TagClosingMismatch); while (open.Count > 0) { open.RemoveAt(open.Count - 1); if (currentNode.NodeName.ToLower() == htmlTagToken2.Name) break; currentNode = CurrentNode; if (currentNode == null || currentNode.IsInHtml) break; } Reset(null); Consume(token); } } } private void InSvg(HtmlTagToken tag) { } private bool IsHeadingInScope() { for (int num = open.Count - 1; num >= 0; num--) { Element element = open[num]; if (element is HTMLHeadingElement) return true; if (element.IsInHtml) { switch (element.NodeName) { case "marquee": case "object": case "th": case "td": case "html": case "table": case "caption": case "applet": return false; } } else if (element.IsInSvg) { if (element.IsSpecial) return false; } else if (element.IsInMathML && element.IsSpecial) { return false; } } return false; } private bool IsInScope(string tagName) { for (int num = open.Count - 1; num >= 0; num--) { Element element = open[num]; if (element.NodeName == tagName) return true; if (element.IsInHtml) { switch (element.NodeName) { case "marquee": case "object": case "th": case "td": case "html": case "table": case "caption": case "applet": return false; } } else if (element.IsInSvg) { if (element.IsSpecial) return false; } else if (element.IsInMathML && element.IsSpecial) { return false; } } return false; } private bool IsInListItemScope(string tagName) { for (int num = open.Count - 1; num >= 0; num--) { Element element = open[num]; if (element.NodeName == tagName) return true; if (element is HTMLUListElement || element is HTMLOListElement) return false; } return false; } private bool IsInButtonScope(string tagName) { for (int num = open.Count - 1; num >= 0; num--) { Element element = open[num]; if (element.NodeName == tagName) return true; if (element is HTMLButtonElement) return false; } return false; } private bool IsSectionInTableScope() { for (int num = open.Count - 1; num >= 0; num--) { Element element = open[num]; if (element is HTMLTableSectionElement || element is HTMLTableSectionElement || element is HTMLTableSectionElement) return true; if (element is HTMLHtmlElement || element is HTMLTableElement) return false; } return false; } private bool IsInTableScope(string tagName) { for (int num = open.Count - 1; num >= 0; num--) { Element element = open[num]; if (element.NodeName == tagName) return true; if (element is HTMLHtmlElement || element is HTMLTableElement) return false; } return false; } private bool IsInSelectScope(string tagName) { for (int num = open.Count - 1; num >= 0; num--) { Element element = open[num]; if (element.NodeName == tagName) return true; if (element is HTMLOptGroupElement || element is HTMLOptionElement) return false; } return false; } private void SetCharset(string charset) { Encoding encoding = HtmlEncoding.Resolve(charset); if (encoding != null) { doc.InputEncoding = encoding.WebName; tokenizer.Stream.Encoding = encoding; } } private void PerformMicrotaskCheckpoint() { } private void ProvideStableState() { } private void End() { doc.ReadyState = Readiness.Interactive; while (open.Count != 0) { CloseCurrentNode(); } int scriptsWaiting = doc.ScriptsWaiting; doc.QueueTask(doc.RaiseDomContentLoaded); while (doc.ScriptsAsSoonAsPossible != 0) { doc.SpinEventLoop(); } while (doc.IsLoadingDelayed) { doc.SpinEventLoop(); } doc.QueueTask(delegate { doc.ReadyState = Readiness.Complete; }); bool isInBrowsingContext = doc.IsInBrowsingContext; if (doc.IsToBePrinted) doc.Print(); doc.QueueTask(doc.RaiseLoadedEvent); if (IsAsync) tcs.SetResult(true); } private void AddElement(HtmlDoctypeToken doctypeToken) { DocumentType documentType = new DocumentType(); documentType.SystemId = doctypeToken.SystemIdentifier; documentType.PublicId = doctypeToken.PublicIdentifier; documentType.Name = doctypeToken.Name; doc.AppendChild(documentType); } private void AddComment(Node parent, HtmlToken commentToken) { HtmlCommentToken htmlCommentToken = (HtmlCommentToken)commentToken; Comment comment = new Comment(); comment.Data = htmlCommentToken.Data; parent.AppendChild(comment); } private void CloseCurrentNode() { if (open.Count > 0) { open.RemoveAt(open.Count - 1); tokenizer.AcceptsCDATA = (CurrentNode == null || !CurrentNode.IsInHtml); } } private void AddElementToCurrentNode(Element element, HtmlToken elementToken, bool acknowledgeSelfClosing = false) { SetupElement(element, elementToken, acknowledgeSelfClosing); if (foster && CurrentNode.IsTableElement()) AddElementWithFoster(element); else CurrentNode.AppendChild(element); open.Add(element); tokenizer.AcceptsCDATA = !element.IsInHtml; } private void AddElementWithFoster(Element element) { bool flag = false; int num = open.Count; while (--num != 0) { if (open[num] is HTMLTableElement) { flag = true; break; } } Node node = open[num].ParentNode ?? open[num + 1]; if (flag && open[num].ParentNode != null) { int num2 = 0; while (true) { if (num2 >= node.ChildNodes.Length) return; if (node.ChildNodes[num2] == open[num]) break; num2++; } node.InsertChild(num2, element); } else node.AppendChild(element); } private void AddElementToDocument(Element element, HtmlToken elementToken) { doc.AppendChild(element); SetupElement(element, elementToken, false); open.Add(element); tokenizer.AcceptsCDATA = !element.IsInHtml; } private void SetupElement(Element element, HtmlToken elementToken, bool acknowledgeSelfClosing) { HtmlTagToken htmlTagToken = (HtmlTagToken)elementToken; element.NodeName = htmlTagToken.Name; if (htmlTagToken.IsSelfClosing && !acknowledgeSelfClosing) RaiseErrorOccurred(ErrorCode.TagCannotBeSelfClosed); AddAttributesToElement(htmlTagToken, element); } private void AddAttributesToElement(HtmlTagToken elementToken, Element element) { for (int i = 0; i < elementToken.Attributes.Count; i++) { element.SetAttribute(elementToken.Attributes[i].Key, elementToken.Attributes[i].Value); } } private void AppendAttributesToElement(HtmlTagToken elementToken, Element element) { foreach (KeyValuePair<string, string> attribute in elementToken.Attributes) { if (!element.HasAttribute(attribute.Key)) element.SetAttribute(attribute.Key, attribute.Value); } } private void InsertCharacter(char p) { if (foster && CurrentNode.IsTableElement()) InsertCharacterWithFoster(p); else CurrentNode.AppendText(p); } private void InsertCharacters(string p) { if (foster && CurrentNode.IsTableElement()) { for (int i = 0; i < p.Length; i++) { InsertCharacterWithFoster(p[i]); } } else CurrentNode.AppendText(p); } private void InsertCharacterWithFoster(char p) { bool flag = false; int num = open.Count; while (--num != 0) { if (open[num].NodeName == "table") { flag = true; break; } } Node node = open[num].ParentNode ?? open[num + 1]; if (flag && open[num].ParentNode != null) { int num2 = 0; while (true) { if (num2 >= node.ChildNodes.Length) return; if (node.ChildNodes[num2] == open[num]) break; num2++; } node.InsertText(num2, p); } else node.AppendText(p); } private void InsertScopeMarker() { formatting.Add(ScopeMarkerNode.Element); } private void CloseTheCell() { if (IsInTableScope("td")) InCellEndTagCell("td"); else InCellEndTagCell("th"); } private void ClearStackBackTo(string tagName) { while (CurrentNode.NodeName != tagName && !(CurrentNode is HTMLHtmlElement)) { CloseCurrentNode(); } } private void ClearStackBackToHeading() { while (!(CurrentNode is HTMLHeadingElement) && !(CurrentNode is HTMLHtmlElement)) { CloseCurrentNode(); } } private void ClearStackBackToTableSection() { while (!(CurrentNode is HTMLTableSectionElement) && !(CurrentNode is HTMLHtmlElement)) { CloseCurrentNode(); } } private void ClearStackBackToTable() { while (!(CurrentNode is HTMLTableElement) && !(CurrentNode is HTMLHtmlElement)) { CloseCurrentNode(); } } private void ClearStackBackToTableRow() { while (!(CurrentNode is HTMLTableRowElement) && !(CurrentNode is HTMLHtmlElement)) { CloseCurrentNode(); } } private void GenerateImpliedEndTagsExceptFor(string tagName) { List<string> list = new List<string>(new string[8] { "dd", "dt", "li", "optgroup", "option", "p", "rp", "rt" }); if (list.Contains(tagName)) list.Remove(tagName); while (list.Contains(CurrentNode.NodeName)) { CloseCurrentNode(); } } private void GenerateImpliedEndTags() { while (CurrentNode is HTMLLIElement || CurrentNode is HTMLOptionElement || CurrentNode is HTMLOptGroupElement || CurrentNode is HTMLParagraphElement || CurrentNode.NodeName == "rp" || CurrentNode.NodeName == "rt") { CloseCurrentNode(); } } private void AddFormattingElement(Element element) { int num = 0; int num2 = formatting.Count - 1; while (num2 >= 0 && !(formatting[num2] is ScopeMarkerNode)) { if (formatting[num2].NodeName == element.NodeName && formatting[num2].Attributes.Equals(element.Attributes) && formatting[num2].NamespaceURI == element.NamespaceURI) { num++; if (num == 3) { formatting.RemoveAt(num2); break; } } num2--; } formatting.Add(element); } private void ClearFormattingElements() { while (formatting.Count != 0) { Element element = formatting[formatting.Count - 1]; formatting.Remove(element); if (element is ScopeMarkerNode) break; } } private void ReconstructFormatting() { if (formatting.Count != 0) { int i = formatting.Count - 1; Element element = formatting[i]; if (!(element is ScopeMarkerNode) && !open.Contains(element)) { while (i > 0) { element = formatting[--i]; if (element is ScopeMarkerNode || open.Contains(element)) { i++; break; } } for (; i < formatting.Count; i++) { element = formatting[i]; HTMLElement hTMLElement = HTMLElement.Factory(element.NodeName); AddElementToCurrentNode(hTMLElement, HtmlToken.OpenTag(element.NodeName), false); for (int j = 0; j < element.Attributes.Length; j++) { Attr attr = element.Attributes[j]; hTMLElement.SetAttribute(attr.NodeName, attr.NodeValue); } formatting[i] = hTMLElement; } } } } private void RaiseErrorOccurred(ErrorCode code) { if (this.ErrorOccurred != null) { ParseErrorEventArgs parseErrorEventArgs = new ParseErrorEventArgs((int)code, Errors.GetError(code)); parseErrorEventArgs.Line = tokenizer.Stream.Line; parseErrorEventArgs.Column = tokenizer.Stream.Column; this.ErrorOccurred(this, parseErrorEventArgs); } } } }