HtmlParser
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);
}
}
}
}