HtmlDomBuilder
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.Events;
using AngleSharp.Dom.Html;
using AngleSharp.Dom.Mathml;
using AngleSharp.Dom.Svg;
using AngleSharp.Extensions;
using AngleSharp.Html;
using AngleSharp.Network;
using AngleSharp.Services;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace AngleSharp.Parser.Html
{
[DebuggerStepThrough]
internal sealed class HtmlDomBuilder
{
private readonly HtmlTokenizer _tokenizer;
private readonly HtmlDocument _document;
private readonly List<Element> _openElements;
private readonly List<Element> _formattingElements;
private readonly Stack<HtmlTreeMode> _templateModes;
private readonly IHtmlElementFactory _htmlFactory;
private readonly IMathElementFactory _mathFactory;
private readonly ISvgElementFactory _svgFactory;
private HtmlFormElement _currentFormElement;
private HtmlTreeMode _currentMode;
private HtmlTreeMode _previousMode;
private HtmlParserOptions _options;
private Element _fragmentContext;
private bool _foster;
private bool _frameset;
private Task _waiting;
public bool IsFragmentCase => _fragmentContext != null;
public Element AdjustedCurrentNode {
get {
if (_fragmentContext == null || _openElements.Count != 1)
return CurrentNode;
return _fragmentContext;
}
}
public Element CurrentNode {
get {
if (_openElements.Count <= 0)
return null;
return _openElements[_openElements.Count - 1];
}
}
public event EventHandler<HtmlErrorEvent> Error {
add {
_tokenizer.Error += value;
}
remove {
_tokenizer.Error -= value;
}
}
internal HtmlDomBuilder(HtmlDocument document)
{
IConfiguration options = document.Options;
IEntityProvider resolver = options.GetProvider<IEntityProvider>() ?? HtmlEntityService.Resolver;
_tokenizer = new HtmlTokenizer(document.Source, resolver);
_document = document;
_openElements = new List<Element>();
_templateModes = new Stack<HtmlTreeMode>();
_formattingElements = new List<Element>();
_frameset = true;
_currentMode = HtmlTreeMode.Initial;
_htmlFactory = options.GetFactory<IHtmlElementFactory>();
_mathFactory = options.GetFactory<IMathElementFactory>();
_svgFactory = options.GetFactory<ISvgElementFactory>();
}
public async Task<HtmlDocument> ParseAsync(HtmlParserOptions options, CancellationToken cancelToken)
{
TextSource source = _document.Source;
_options = options;
HtmlToken token;
do {
if (source.Length - source.Index < 1024)
await source.PrefetchAsync(8192, cancelToken).ConfigureAwait(false);
token = _tokenizer.Get();
Consume(token);
if (_waiting != null) {
await _waiting.ConfigureAwait(false);
_waiting = null;
}
} while (token.Type != HtmlTokenType.EndOfFile);
return _document;
}
public HtmlDocument Parse(HtmlParserOptions options)
{
HtmlToken htmlToken = null;
_options = options;
do {
htmlToken = _tokenizer.Get();
Consume(htmlToken);
if (_waiting != null) {
_waiting.Wait();
_waiting = null;
}
} while (htmlToken.Type != HtmlTokenType.EndOfFile);
return _document;
}
public HtmlDocument ParseFragment(HtmlParserOptions options, Element context)
{
if (context == null)
throw new ArgumentNullException("context");
_fragmentContext = context;
string localName = context.LocalName;
if (localName.IsOneOf(TagNames.Title, TagNames.Textarea))
_tokenizer.State = HtmlParseMode.RCData;
else if (localName.IsOneOf(TagNames.Style, TagNames.Xmp, TagNames.Iframe, TagNames.NoEmbed, TagNames.NoFrames)) {
_tokenizer.State = HtmlParseMode.Rawtext;
} else if (localName.Is(TagNames.Script)) {
_tokenizer.State = HtmlParseMode.Script;
} else if (localName.Is(TagNames.Plaintext)) {
_tokenizer.State = HtmlParseMode.Plaintext;
} else if (localName.Is(TagNames.NoScript) && options.IsScripting) {
_tokenizer.State = HtmlParseMode.Rawtext;
}
HtmlHtmlElement htmlHtmlElement = new HtmlHtmlElement(_document, null);
_document.AddNode(htmlHtmlElement);
_openElements.Add(htmlHtmlElement);
if (context is HtmlTemplateElement)
_templateModes.Push(HtmlTreeMode.InTemplate);
Reset();
_tokenizer.IsAcceptingCharacterData = !AdjustedCurrentNode.Flags.HasFlag(NodeFlags.HtmlMember);
do {
if (context is HtmlFormElement) {
_currentFormElement = (HtmlFormElement)context;
break;
}
context = (context.ParentElement as Element);
} while (context != null);
return Parse(options);
}
private void Restart()
{
_currentMode = HtmlTreeMode.Initial;
_tokenizer.State = HtmlParseMode.PCData;
_document.ReplaceAll(null, true);
_frameset = true;
_openElements.Clear();
_formattingElements.Clear();
_templateModes.Clear();
}
private void Reset()
{
int num = _openElements.Count - 1;
HtmlTreeMode? nullable;
while (true) {
if (num < 0)
return;
Element element = _openElements[num];
bool flag = num == 0;
if (flag && _fragmentContext != null)
element = _fragmentContext;
nullable = element.SelectMode(flag, _templateModes);
if (nullable.HasValue)
break;
num--;
}
_currentMode = nullable.Value;
}
private void Consume(HtmlToken token)
{
Element adjustedCurrentNode = AdjustedCurrentNode;
if (adjustedCurrentNode == null || token.Type == HtmlTokenType.EndOfFile || adjustedCurrentNode.Flags.HasFlag(NodeFlags.HtmlMember) || (adjustedCurrentNode.Flags.HasFlag(NodeFlags.HtmlTip) && token.IsHtmlCompatible) || (adjustedCurrentNode.Flags.HasFlag(NodeFlags.MathTip) && token.IsMathCompatible) || (adjustedCurrentNode.Flags.HasFlag(NodeFlags.MathMember) && token.IsSvg && adjustedCurrentNode.LocalName.Is(TagNames.AnnotationXml)))
Home(token);
else
Foreign(token);
}
private void Home(HtmlToken token)
{
switch (_currentMode) {
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.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.InTemplate:
InTemplate(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;
}
}
private void Initial(HtmlToken token)
{
switch (token.Type) {
case HtmlTokenType.Doctype: {
HtmlDoctypeToken htmlDoctypeToken = (HtmlDoctypeToken)token;
if (!htmlDoctypeToken.IsValid)
RaiseErrorOccurred(HtmlParseError.DoctypeInvalid, token);
_document.AddNode(new DocumentType(_document, htmlDoctypeToken.Name ?? string.Empty) {
SystemIdentifier = htmlDoctypeToken.SystemIdentifier,
PublicIdentifier = htmlDoctypeToken.PublicIdentifier
});
_document.QuirksMode = htmlDoctypeToken.GetQuirksMode();
_currentMode = HtmlTreeMode.BeforeHtml;
return;
}
case HtmlTokenType.Character:
token.TrimStart();
if (token.IsEmpty)
return;
break;
case HtmlTokenType.Comment:
_document.AddComment(token);
return;
}
if (!_options.IsEmbedded) {
RaiseErrorOccurred(HtmlParseError.DoctypeMissing, token);
_document.QuirksMode = QuirksMode.On;
}
_currentMode = HtmlTreeMode.BeforeHtml;
BeforeHtml(token);
}
private void BeforeHtml(HtmlToken token)
{
switch (token.Type) {
case HtmlTokenType.Character:
token.TrimStart();
if (token.IsEmpty)
return;
break;
case HtmlTokenType.Comment:
_document.AddComment(token);
return;
case HtmlTokenType.StartTag:
if (token.Name.Is(TagNames.Html)) {
AddRoot(token.AsTag());
_currentMode = HtmlTreeMode.BeforeHead;
return;
}
break;
case HtmlTokenType.EndTag:
if (!TagNames.AllBeforeHead.Contains(token.Name)) {
RaiseErrorOccurred(HtmlParseError.TagCannotEndHere, token);
return;
}
break;
case HtmlTokenType.Doctype:
RaiseErrorOccurred(HtmlParseError.DoctypeTagInappropriate, token);
return;
}
BeforeHtml(HtmlTagToken.Open(TagNames.Html));
BeforeHead(token);
}
private void BeforeHead(HtmlToken token)
{
switch (token.Type) {
case HtmlTokenType.Character:
token.TrimStart();
if (token.IsEmpty)
return;
break;
case HtmlTokenType.StartTag: {
string name = token.Name;
if (name.Is(TagNames.Html)) {
InBody(token);
return;
}
if (name.Is(TagNames.Head)) {
AddElement(new HtmlHeadElement(_document, null), token.AsTag(), false);
_currentMode = HtmlTreeMode.InHead;
return;
}
break;
}
case HtmlTokenType.EndTag:
if (!TagNames.AllBeforeHead.Contains(token.Name)) {
RaiseErrorOccurred(HtmlParseError.TagCannotEndHere, token);
return;
}
break;
case HtmlTokenType.Comment:
CurrentNode.AddComment(token);
return;
case HtmlTokenType.Doctype:
RaiseErrorOccurred(HtmlParseError.DoctypeTagInappropriate, token);
return;
}
BeforeHead(HtmlTagToken.Open(TagNames.Head));
InHead(token);
}
private void InHead(HtmlToken token)
{
switch (token.Type) {
case HtmlTokenType.Character: {
string text = token.TrimStart();
AddCharacters(text);
if (token.IsEmpty)
return;
break;
}
case HtmlTokenType.Comment:
CurrentNode.AddComment(token);
return;
case HtmlTokenType.Doctype:
RaiseErrorOccurred(HtmlParseError.DoctypeTagInappropriate, token);
return;
case HtmlTokenType.StartTag: {
string name2 = token.Name;
if (name2.Is(TagNames.Html)) {
InBody(token);
return;
}
if (name2.Is(TagNames.Meta)) {
HtmlMetaElement htmlMetaElement = new HtmlMetaElement(_document, null);
AddElement(htmlMetaElement, token.AsTag(), true);
Encoding encoding = htmlMetaElement.GetEncoding();
CloseCurrentNode();
if (encoding != null)
try {
_document.Source.CurrentEncoding = encoding;
} catch (NotSupportedException) {
Restart();
}
return;
}
if (TagNames.AllHeadBase.Contains(name2)) {
AddElement(token.AsTag(), true);
CloseCurrentNode();
return;
}
if (name2.Is(TagNames.Title)) {
RCDataAlgorithm(token.AsTag());
return;
}
if (name2.IsOneOf(TagNames.Style, TagNames.NoFrames) || (_options.IsScripting && name2.Is(TagNames.NoScript))) {
RawtextAlgorithm(token.AsTag());
return;
}
if (name2.Is(TagNames.NoScript)) {
AddElement(token.AsTag(), false);
_currentMode = HtmlTreeMode.InHeadNoScript;
return;
}
if (name2.Is(TagNames.Script)) {
HtmlScriptElement element = new HtmlScriptElement(_document, null, true, IsFragmentCase);
AddElement(element, token.AsTag(), false);
_tokenizer.State = HtmlParseMode.Script;
_previousMode = _currentMode;
_currentMode = HtmlTreeMode.Text;
return;
}
if (name2.Is(TagNames.Head)) {
RaiseErrorOccurred(HtmlParseError.HeadTagMisplaced, token);
return;
}
if (name2.Is(TagNames.Template)) {
AddElement(new HtmlTemplateElement(_document, null), token.AsTag(), false);
_formattingElements.AddScopeMarker();
_frameset = false;
_currentMode = HtmlTreeMode.InTemplate;
_templateModes.Push(HtmlTreeMode.InTemplate);
return;
}
break;
}
case HtmlTokenType.EndTag: {
string name = token.Name;
if (name.Is(TagNames.Head)) {
CloseCurrentNode();
_currentMode = HtmlTreeMode.AfterHead;
_waiting = _document.WaitForReadyAsync();
return;
}
if (name.Is(TagNames.Template)) {
if (TagCurrentlyOpen(TagNames.Template)) {
GenerateImpliedEndTags();
if (!CurrentNode.LocalName.Is(TagNames.Template))
RaiseErrorOccurred(HtmlParseError.TagClosingMismatch, token);
CloseTemplate();
} else
RaiseErrorOccurred(HtmlParseError.TagInappropriate, token);
return;
}
if (!name.IsOneOf(TagNames.Html, TagNames.Body, TagNames.Br)) {
RaiseErrorOccurred(HtmlParseError.TagCannotEndHere, token);
return;
}
break;
}
}
CloseCurrentNode();
_currentMode = HtmlTreeMode.AfterHead;
AfterHead(token);
}
private void InHeadNoScript(HtmlToken token)
{
switch (token.Type) {
case HtmlTokenType.Character: {
string text = token.TrimStart();
AddCharacters(text);
if (token.IsEmpty)
return;
break;
}
case HtmlTokenType.Comment:
InHead(token);
return;
case HtmlTokenType.StartTag: {
string name2 = token.Name;
if (TagNames.AllNoScript.Contains(name2)) {
InHead(token);
return;
}
if (name2.Is(TagNames.Html)) {
InBody(token);
return;
}
if (name2.IsOneOf(TagNames.Head, TagNames.NoScript)) {
RaiseErrorOccurred(HtmlParseError.TagInappropriate, token);
return;
}
break;
}
case HtmlTokenType.EndTag: {
string name = token.Name;
if (name.Is(TagNames.NoScript)) {
CloseCurrentNode();
_currentMode = HtmlTreeMode.InHead;
return;
}
if (!name.Is(TagNames.Br)) {
RaiseErrorOccurred(HtmlParseError.TagCannotEndHere, token);
return;
}
break;
}
case HtmlTokenType.Doctype:
RaiseErrorOccurred(HtmlParseError.DoctypeTagInappropriate, token);
return;
}
RaiseErrorOccurred(HtmlParseError.TokenNotPossible, token);
CloseCurrentNode();
_currentMode = HtmlTreeMode.InHead;
InHead(token);
}
private void AfterHead(HtmlToken token)
{
switch (token.Type) {
case HtmlTokenType.Character: {
string text = token.TrimStart();
AddCharacters(text);
if (token.IsEmpty)
return;
break;
}
case HtmlTokenType.Comment:
CurrentNode.AddComment(token);
return;
case HtmlTokenType.Doctype:
RaiseErrorOccurred(HtmlParseError.DoctypeTagInappropriate, token);
return;
case HtmlTokenType.StartTag: {
string name = token.Name;
if (name.Is(TagNames.Html)) {
InBody(token);
return;
}
if (name.Is(TagNames.Body)) {
AfterHeadStartTagBody(token.AsTag());
return;
}
if (name.Is(TagNames.Frameset)) {
AddElement(new HtmlFrameSetElement(_document, null), token.AsTag(), false);
_currentMode = HtmlTreeMode.InFrameset;
return;
}
if (TagNames.AllHeadNoTemplate.Contains(name)) {
RaiseErrorOccurred(HtmlParseError.TagMustBeInHead, token);
int count = _openElements.Count;
Element element = _document.Head as Element;
_openElements.Add(element);
InHead(token);
CloseNode(element);
return;
}
if (name.Is(TagNames.Head)) {
RaiseErrorOccurred(HtmlParseError.HeadTagMisplaced, token);
return;
}
break;
}
case HtmlTokenType.EndTag:
if (!token.Name.IsOneOf(TagNames.Html, TagNames.Body, TagNames.Br)) {
RaiseErrorOccurred(HtmlParseError.TagCannotEndHere, token);
return;
}
break;
}
AfterHeadStartTagBody(HtmlTagToken.Open(TagNames.Body));
_frameset = true;
Home(token);
}
private void InBodyStartTag(HtmlTagToken tag)
{
string name = tag.Name;
if (name.Is(TagNames.Div)) {
if (IsInButtonScope())
InBodyEndTagParagraph(tag);
AddElement(tag, false);
} else if (name.Is(TagNames.A)) {
for (int num = _formattingElements.Count - 1; num >= 0; num--) {
if (_formattingElements[num] == null)
break;
if (_formattingElements[num].LocalName.Is(TagNames.A)) {
Element element = _formattingElements[num];
RaiseErrorOccurred(HtmlParseError.AnchorNested, tag);
HeisenbergAlgorithm(HtmlTagToken.Close(TagNames.A));
CloseNode(element);
_formattingElements.Remove(element);
break;
}
}
ReconstructFormatting();
HtmlAnchorElement element2 = new HtmlAnchorElement(_document, null);
AddElement(element2, tag, false);
_formattingElements.AddFormatting(element2);
} else if (name.Is(TagNames.Span)) {
ReconstructFormatting();
AddElement(tag, false);
} else if (name.Is(TagNames.Li)) {
InBodyStartTagListItem(tag);
} else if (name.Is(TagNames.Img)) {
InBodyStartTagBreakrow(tag);
} else if (name.IsOneOf(TagNames.Ul, TagNames.P)) {
if (IsInButtonScope())
InBodyEndTagParagraph(tag);
AddElement(tag, false);
} else if (TagNames.AllSemanticFormatting.Contains(name)) {
ReconstructFormatting();
_formattingElements.AddFormatting(AddElement(tag, false));
} else if (name.Is(TagNames.Script)) {
InHead(tag);
} else if (TagNames.AllHeadings.Contains(name)) {
if (IsInButtonScope())
InBodyEndTagParagraph(tag);
if (TagNames.AllHeadings.Contains(CurrentNode.LocalName)) {
RaiseErrorOccurred(HtmlParseError.HeadingNested, tag);
CloseCurrentNode();
}
AddElement(new HtmlHeadingElement(_document, name, null), tag, false);
} else if (name.Is(TagNames.Input)) {
ReconstructFormatting();
AddElement(new HtmlInputElement(_document, null), tag, true);
CloseCurrentNode();
if (!tag.GetAttribute(AttributeNames.Type).Isi(AttributeNames.Hidden))
_frameset = false;
} else if (name.Is(TagNames.Form)) {
if (_currentFormElement == null) {
if (IsInButtonScope())
InBodyEndTagParagraph(tag);
_currentFormElement = new HtmlFormElement(_document, null);
AddElement(_currentFormElement, tag, false);
} else
RaiseErrorOccurred(HtmlParseError.FormAlreadyOpen, tag);
} else if (TagNames.AllBody.Contains(name)) {
if (IsInButtonScope())
InBodyEndTagParagraph(tag);
AddElement(tag, false);
} else if (TagNames.AllClassicFormatting.Contains(name)) {
ReconstructFormatting();
_formattingElements.AddFormatting(AddElement(tag, false));
} else if (TagNames.AllHead.Contains(name)) {
InHead(tag);
} else if (name.IsOneOf(TagNames.Pre, TagNames.Listing)) {
if (IsInButtonScope())
InBodyEndTagParagraph(tag);
AddElement(tag, false);
_frameset = false;
PreventNewLine();
} else if (name.Is(TagNames.Button)) {
if (IsInScope(TagNames.Button)) {
RaiseErrorOccurred(HtmlParseError.ButtonInScope, tag);
InBodyEndTagBlock(tag);
InBody(tag);
} else {
ReconstructFormatting();
AddElement(new HtmlButtonElement(_document, null), tag, false);
_frameset = false;
}
} else if (name.Is(TagNames.Table)) {
if (_document.QuirksMode != QuirksMode.On && IsInButtonScope())
InBodyEndTagParagraph(tag);
AddElement(new HtmlTableElement(_document, null), tag, false);
_frameset = false;
_currentMode = HtmlTreeMode.InTable;
} else if (TagNames.AllBodyBreakrow.Contains(name)) {
InBodyStartTagBreakrow(tag);
} else if (TagNames.AllBodyClosed.Contains(name)) {
AddElement(tag, true);
CloseCurrentNode();
} else if (name.Is(TagNames.Hr)) {
if (IsInButtonScope())
InBodyEndTagParagraph(tag);
AddElement(new HtmlHrElement(_document, null), tag, true);
CloseCurrentNode();
_frameset = false;
} else if (name.Is(TagNames.Textarea)) {
AddElement(new HtmlTextAreaElement(_document, null), tag, false);
_tokenizer.State = HtmlParseMode.RCData;
_previousMode = _currentMode;
_frameset = false;
_currentMode = HtmlTreeMode.Text;
PreventNewLine();
} else if (name.Is(TagNames.Select)) {
ReconstructFormatting();
AddElement(new HtmlSelectElement(_document, null), tag, false);
_frameset = false;
switch (_currentMode) {
case HtmlTreeMode.InTable:
case HtmlTreeMode.InCaption:
case HtmlTreeMode.InTableBody:
case HtmlTreeMode.InRow:
case HtmlTreeMode.InCell:
_currentMode = HtmlTreeMode.InSelectInTable;
break;
default:
_currentMode = HtmlTreeMode.InSelect;
break;
}
} else if (name.IsOneOf(TagNames.Optgroup, TagNames.Option)) {
if (CurrentNode.LocalName.Is(TagNames.Option))
InBodyEndTagAnythingElse(HtmlTagToken.Close(TagNames.Option));
ReconstructFormatting();
AddElement(tag, false);
} else if (name.IsOneOf(TagNames.Dd, TagNames.Dt)) {
InBodyStartTagDefinitionItem(tag);
} else if (name.Is(TagNames.Iframe)) {
_frameset = false;
RawtextAlgorithm(tag);
} else if (TagNames.AllBodyObsolete.Contains(name)) {
ReconstructFormatting();
AddElement(tag, false);
_formattingElements.AddScopeMarker();
_frameset = false;
} else if (name.Is(TagNames.Image)) {
RaiseErrorOccurred(HtmlParseError.ImageTagNamedWrong, tag);
tag.Name = TagNames.Img;
InBodyStartTagBreakrow(tag);
} else if (name.Is(TagNames.NoBr)) {
ReconstructFormatting();
if (IsInScope(TagNames.NoBr)) {
RaiseErrorOccurred(HtmlParseError.NobrInScope, tag);
HeisenbergAlgorithm(tag);
ReconstructFormatting();
}
_formattingElements.AddFormatting(AddElement(tag, false));
} else if (name.Is(TagNames.Xmp)) {
if (IsInButtonScope())
InBodyEndTagParagraph(tag);
ReconstructFormatting();
_frameset = false;
RawtextAlgorithm(tag);
} else if (name.IsOneOf(TagNames.Rb, TagNames.Rtc)) {
if (IsInScope(TagNames.Ruby)) {
GenerateImpliedEndTags();
if (!CurrentNode.LocalName.Is(TagNames.Ruby))
RaiseErrorOccurred(HtmlParseError.TagDoesNotMatchCurrentNode, tag);
}
AddElement(tag, false);
} else if (name.IsOneOf(TagNames.Rp, TagNames.Rt)) {
if (IsInScope(TagNames.Ruby)) {
GenerateImpliedEndTagsExceptFor(TagNames.Rtc);
if (!CurrentNode.LocalName.IsOneOf(TagNames.Ruby, TagNames.Rtc))
RaiseErrorOccurred(HtmlParseError.TagDoesNotMatchCurrentNode, tag);
}
AddElement(tag, false);
} else if (name.Is(TagNames.NoEmbed)) {
RawtextAlgorithm(tag);
} else if (name.Is(TagNames.NoScript)) {
if (_options.IsScripting)
RawtextAlgorithm(tag);
else {
ReconstructFormatting();
AddElement(tag, false);
}
} else if (name.Is(TagNames.Math)) {
MathElement element3 = new MathElement(_document, name, null, NodeFlags.None);
ReconstructFormatting();
AddElement(element3.Setup(tag));
if (tag.IsSelfClosing)
CloseNode(element3);
} else if (name.Is(TagNames.Svg)) {
SvgElement element4 = new SvgElement(_document, name, null, NodeFlags.None);
ReconstructFormatting();
AddElement(element4.Setup(tag));
if (tag.IsSelfClosing)
CloseNode(element4);
} else if (name.Is(TagNames.Plaintext)) {
if (IsInButtonScope())
InBodyEndTagParagraph(tag);
AddElement(tag, false);
_tokenizer.State = HtmlParseMode.Plaintext;
} else if (name.Is(TagNames.Frameset)) {
RaiseErrorOccurred(HtmlParseError.FramesetMisplaced, tag);
if (_openElements.Count != 1 && _openElements[1].LocalName.Is(TagNames.Body) && _frameset) {
_openElements[1].RemoveFromParent();
while (_openElements.Count > 1) {
CloseCurrentNode();
}
AddElement(new HtmlFrameSetElement(_document, null), tag, false);
_currentMode = HtmlTreeMode.InFrameset;
}
} else if (name.Is(TagNames.Html)) {
RaiseErrorOccurred(HtmlParseError.HtmlTagMisplaced, tag);
if (_templateModes.Count == 0)
_openElements[0].SetUniqueAttributes(tag.Attributes);
} else if (name.Is(TagNames.Body)) {
RaiseErrorOccurred(HtmlParseError.BodyTagMisplaced, tag);
if (_templateModes.Count == 0 && _openElements.Count > 1 && _openElements[1].LocalName.Is(TagNames.Body)) {
_frameset = false;
_openElements[1].SetUniqueAttributes(tag.Attributes);
}
} else if (name.Is(TagNames.IsIndex)) {
RaiseErrorOccurred(HtmlParseError.TagInappropriate, tag);
if (_currentFormElement == null) {
InBody(HtmlTagToken.Open(TagNames.Form));
if (tag.GetAttribute(AttributeNames.Action).Length > 0)
_currentFormElement.SetAttribute(AttributeNames.Action, tag.GetAttribute(AttributeNames.Action));
InBody(HtmlTagToken.Open(TagNames.Hr));
InBody(HtmlTagToken.Open(TagNames.Label));
if (tag.GetAttribute(AttributeNames.Prompt).Length > 0)
AddCharacters(tag.GetAttribute(AttributeNames.Prompt));
else
AddCharacters("This is a searchable index. Enter search keywords: ");
HtmlTagToken htmlTagToken = HtmlTagToken.Open(TagNames.Input);
htmlTagToken.AddAttribute(AttributeNames.Name, TagNames.IsIndex);
for (int i = 0; i < tag.Attributes.Count; i++) {
KeyValuePair<string, string> keyValuePair = tag.Attributes[i];
if (!keyValuePair.Key.IsOneOf(AttributeNames.Name, AttributeNames.Action, AttributeNames.Prompt)) {
HtmlTagToken htmlTagToken2 = htmlTagToken;
keyValuePair = tag.Attributes[i];
string key = keyValuePair.Key;
keyValuePair = tag.Attributes[i];
htmlTagToken2.AddAttribute(key, keyValuePair.Value);
}
}
InBody(htmlTagToken);
InBody(HtmlTagToken.Close(TagNames.Label));
InBody(HtmlTagToken.Open(TagNames.Hr));
InBody(HtmlTagToken.Close(TagNames.Form));
}
} else if (TagNames.AllNested.Contains(name)) {
RaiseErrorOccurred(HtmlParseError.TagCannotStartHere, tag);
} else {
ReconstructFormatting();
AddElement(tag, false);
}
}
private void InBodyEndTag(HtmlTagToken tag)
{
string name = tag.Name;
if (name.Is(TagNames.Div))
InBodyEndTagBlock(tag);
else if (name.Is(TagNames.A)) {
HeisenbergAlgorithm(tag);
} else if (name.Is(TagNames.Li)) {
if (IsInListItemScope()) {
GenerateImpliedEndTagsExceptFor(name);
if (!CurrentNode.LocalName.Is(TagNames.Li))
RaiseErrorOccurred(HtmlParseError.TagDoesNotMatchCurrentNode, tag);
ClearStackBackTo(TagNames.Li);
CloseCurrentNode();
} else
RaiseErrorOccurred(HtmlParseError.ListItemNotInScope, tag);
} else if (name.Is(TagNames.P)) {
InBodyEndTagParagraph(tag);
} else if (TagNames.AllBlocks.Contains(name)) {
InBodyEndTagBlock(tag);
} else if (TagNames.AllFormatting.Contains(name)) {
HeisenbergAlgorithm(tag);
} else if (name.Is(TagNames.Form)) {
HtmlFormElement currentFormElement = _currentFormElement;
_currentFormElement = null;
if (currentFormElement != null && IsInScope(currentFormElement.LocalName)) {
GenerateImpliedEndTags();
if (CurrentNode != currentFormElement)
RaiseErrorOccurred(HtmlParseError.FormClosedWrong, tag);
CloseNode(currentFormElement);
} else
RaiseErrorOccurred(HtmlParseError.FormNotInScope, tag);
} else if (name.Is(TagNames.Br)) {
RaiseErrorOccurred(HtmlParseError.TagCannotEndHere, tag);
InBodyStartTagBreakrow(HtmlTagToken.Open(TagNames.Br));
} else if (TagNames.AllHeadings.Contains(name)) {
if (IsInScope(TagNames.AllHeadings)) {
GenerateImpliedEndTags();
if (!CurrentNode.LocalName.Is(name))
RaiseErrorOccurred(HtmlParseError.TagDoesNotMatchCurrentNode, tag);
ClearStackBackTo(TagNames.AllHeadings);
CloseCurrentNode();
} else
RaiseErrorOccurred(HtmlParseError.HeadingNotInScope, tag);
} else if (name.IsOneOf(TagNames.Dd, TagNames.Dt)) {
if (IsInScope(name)) {
GenerateImpliedEndTagsExceptFor(name);
if (!CurrentNode.LocalName.Is(name))
RaiseErrorOccurred(HtmlParseError.TagDoesNotMatchCurrentNode, tag);
ClearStackBackTo(name);
CloseCurrentNode();
} else
RaiseErrorOccurred(HtmlParseError.ListItemNotInScope, tag);
} else if (name.IsOneOf(TagNames.Applet, TagNames.Marquee, TagNames.Object)) {
if (IsInScope(name)) {
GenerateImpliedEndTags();
if (!CurrentNode.LocalName.Is(name))
RaiseErrorOccurred(HtmlParseError.TagDoesNotMatchCurrentNode, tag);
ClearStackBackTo(name);
CloseCurrentNode();
_formattingElements.ClearFormatting();
} else
RaiseErrorOccurred(HtmlParseError.ObjectNotInScope, tag);
} else if (name.Is(TagNames.Body)) {
InBodyEndTagBody(tag);
} else if (name.Is(TagNames.Html)) {
if (InBodyEndTagBody(tag))
AfterBody(tag);
} else if (name.Is(TagNames.Template)) {
InHead(tag);
} else {
InBodyEndTagAnythingElse(tag);
}
}
private void InBody(HtmlToken token)
{
switch (token.Type) {
case HtmlTokenType.Character:
ReconstructFormatting();
AddCharacters(token.Data);
_frameset = (!token.HasContent && _frameset);
break;
case HtmlTokenType.StartTag:
InBodyStartTag(token.AsTag());
break;
case HtmlTokenType.EndTag:
InBodyEndTag(token.AsTag());
break;
case HtmlTokenType.Comment:
CurrentNode.AddComment(token);
break;
case HtmlTokenType.Doctype:
RaiseErrorOccurred(HtmlParseError.DoctypeTagInappropriate, token);
break;
case HtmlTokenType.EndOfFile:
CheckBodyOnClosing(token);
if (_templateModes.Count != 0)
InTemplate(token);
else
End();
break;
}
}
private void Text(HtmlToken token)
{
switch (token.Type) {
case HtmlTokenType.Comment:
break;
case HtmlTokenType.Character:
AddCharacters(token.Data);
break;
case HtmlTokenType.EndTag:
if (!token.Name.Is(TagNames.Script)) {
CloseCurrentNode();
_currentMode = _previousMode;
} else
HandleScript(CurrentNode as HtmlScriptElement);
break;
case HtmlTokenType.EndOfFile:
RaiseErrorOccurred(HtmlParseError.EOF, token);
CloseCurrentNode();
_currentMode = _previousMode;
Consume(token);
break;
}
}
private void InTable(HtmlToken token)
{
switch (token.Type) {
case HtmlTokenType.Comment:
CurrentNode.AddComment(token);
return;
case HtmlTokenType.Doctype:
RaiseErrorOccurred(HtmlParseError.DoctypeTagInappropriate, token);
return;
case HtmlTokenType.StartTag: {
string name2 = token.Name;
if (name2.Is(TagNames.Caption)) {
ClearStackBackTo(TagNames.Table);
_formattingElements.AddScopeMarker();
AddElement(new HtmlTableCaptionElement(_document, null), token.AsTag(), false);
_currentMode = HtmlTreeMode.InCaption;
} else if (name2.Is(TagNames.Colgroup)) {
ClearStackBackTo(TagNames.Table);
AddElement(new HtmlTableColgroupElement(_document, null), token.AsTag(), false);
_currentMode = HtmlTreeMode.InColumnGroup;
} else if (name2.Is(TagNames.Col)) {
InTable(HtmlTagToken.Open(TagNames.Colgroup));
InColumnGroup(token);
} else if (TagNames.AllTableSections.Contains(name2)) {
ClearStackBackTo(TagNames.Table);
AddElement(new HtmlTableSectionElement(_document, name2, null), token.AsTag(), false);
_currentMode = HtmlTreeMode.InTableBody;
} else if (TagNames.AllTableCellsRows.Contains(name2)) {
InTable(HtmlTagToken.Open(TagNames.Tbody));
InTableBody(token);
} else if (name2.Is(TagNames.Table)) {
RaiseErrorOccurred(HtmlParseError.TableNesting, token);
if (InTableEndTagTable(token))
Home(token);
} else if (name2.Is(TagNames.Input)) {
HtmlTagToken htmlTagToken = token.AsTag();
if (htmlTagToken.GetAttribute(AttributeNames.Type).Isi(AttributeNames.Hidden)) {
RaiseErrorOccurred(HtmlParseError.InputUnexpected, token);
AddElement(new HtmlInputElement(_document, null), htmlTagToken, true);
CloseCurrentNode();
} else {
RaiseErrorOccurred(HtmlParseError.TokenNotPossible, token);
InBodyWithFoster(token);
}
} else if (name2.Is(TagNames.Form)) {
RaiseErrorOccurred(HtmlParseError.FormInappropriate, token);
if (_currentFormElement == null) {
_currentFormElement = new HtmlFormElement(_document, null);
AddElement(_currentFormElement, token.AsTag(), false);
CloseCurrentNode();
}
} else if (TagNames.AllTableHead.Contains(name2)) {
InHead(token);
} else {
RaiseErrorOccurred(HtmlParseError.IllegalElementInTableDetected, token);
InBodyWithFoster(token);
}
return;
}
case HtmlTokenType.EndTag: {
string name = token.Name;
if (name.Is(TagNames.Table))
InTableEndTagTable(token);
else if (name.Is(TagNames.Template)) {
InHead(token);
} else if (TagNames.AllTableSpecial.Contains(name) || TagNames.AllTableInner.Contains(name)) {
RaiseErrorOccurred(HtmlParseError.TagCannotEndHere, token);
} else {
RaiseErrorOccurred(HtmlParseError.IllegalElementInTableDetected, token);
InBodyWithFoster(token);
}
return;
}
case HtmlTokenType.EndOfFile:
InBody(token);
return;
case HtmlTokenType.Character:
if (TagNames.AllTableMajor.Contains(CurrentNode.LocalName)) {
InTableText(token);
return;
}
break;
}
RaiseErrorOccurred(HtmlParseError.TokenNotPossible, token);
InBodyWithFoster(token);
}
private void InTableText(HtmlToken token)
{
if (token.HasContent) {
RaiseErrorOccurred(HtmlParseError.TokenNotPossible, token);
InBodyWithFoster(token);
} else
AddCharacters(token.Data);
}
private void InCaption(HtmlToken token)
{
switch (token.Type) {
case HtmlTokenType.EndTag: {
string name2 = token.Name;
if (name2.Is(TagNames.Caption)) {
InCaptionEndTagCaption(token);
return;
}
if (TagNames.AllCaptionStart.Contains(name2)) {
RaiseErrorOccurred(HtmlParseError.TagCannotEndHere, token);
return;
}
if (name2.Is(TagNames.Table)) {
RaiseErrorOccurred(HtmlParseError.TableNesting, token);
if (InCaptionEndTagCaption(token))
InTable(token);
return;
}
break;
}
case HtmlTokenType.StartTag: {
string name = token.Name;
if (TagNames.AllCaptionEnd.Contains(name)) {
RaiseErrorOccurred(HtmlParseError.TagCannotStartHere, token);
if (InCaptionEndTagCaption(token))
InTable(token);
return;
}
break;
}
}
InBody(token);
}
private void InColumnGroup(HtmlToken token)
{
switch (token.Type) {
case HtmlTokenType.Character: {
string text = token.TrimStart();
AddCharacters(text);
if (token.IsEmpty)
return;
break;
}
case HtmlTokenType.Comment:
CurrentNode.AddComment(token);
return;
case HtmlTokenType.Doctype:
RaiseErrorOccurred(HtmlParseError.DoctypeTagInappropriate, token);
return;
case HtmlTokenType.StartTag: {
string name2 = token.Name;
if (name2.Is(TagNames.Html)) {
InBody(token);
return;
}
if (name2.Is(TagNames.Col)) {
AddElement(new HtmlTableColElement(_document, null), token.AsTag(), true);
CloseCurrentNode();
return;
}
if (name2.Is(TagNames.Template)) {
InHead(token);
return;
}
break;
}
case HtmlTokenType.EndTag: {
string name = token.Name;
if (name.Is(TagNames.Colgroup)) {
InColumnGroupEndTagColgroup(token);
return;
}
if (name.Is(TagNames.Col)) {
RaiseErrorOccurred(HtmlParseError.TagClosedWrong, token);
return;
}
if (name.Is(TagNames.Template)) {
InHead(token);
return;
}
break;
}
case HtmlTokenType.EndOfFile:
InBody(token);
return;
}
if (InColumnGroupEndTagColgroup(token))
InTable(token);
}
private void InTableBody(HtmlToken token)
{
switch (token.Type) {
case HtmlTokenType.StartTag: {
string name2 = token.Name;
if (name2.Is(TagNames.Tr)) {
ClearStackBackTo(TagNames.AllTableSections);
AddElement(new HtmlTableRowElement(_document, null), token.AsTag(), false);
_currentMode = HtmlTreeMode.InRow;
return;
}
if (TagNames.AllTableCells.Contains(name2)) {
InTableBody(HtmlTagToken.Open(TagNames.Tr));
InRow(token);
return;
}
if (TagNames.AllTableGeneral.Contains(name2)) {
InTableBodyCloseTable(token.AsTag());
return;
}
break;
}
case HtmlTokenType.EndTag: {
string name = token.Name;
if (TagNames.AllTableSections.Contains(name)) {
if (IsInTableScope(name)) {
ClearStackBackTo(TagNames.AllTableSections);
CloseCurrentNode();
_currentMode = HtmlTreeMode.InTable;
} else
RaiseErrorOccurred(HtmlParseError.TableSectionNotInScope, token);
return;
}
if (name.Is(TagNames.Tr) || TagNames.AllTableSpecial.Contains(name)) {
RaiseErrorOccurred(HtmlParseError.TagCannotEndHere, token);
return;
}
if (name.Is(TagNames.Table)) {
InTableBodyCloseTable(token.AsTag());
return;
}
break;
}
}
InTable(token);
}
private void InRow(HtmlToken token)
{
switch (token.Type) {
case HtmlTokenType.StartTag: {
string name2 = token.Name;
if (TagNames.AllTableCells.Contains(name2)) {
ClearStackBackTo(TagNames.Tr);
AddElement(token.AsTag(), false);
_currentMode = HtmlTreeMode.InCell;
_formattingElements.AddScopeMarker();
return;
}
if (name2.Is(TagNames.Tr) || TagNames.AllTableGeneral.Contains(name2)) {
if (InRowEndTagTablerow(token))
InTableBody(token);
return;
}
break;
}
case HtmlTokenType.EndTag: {
string name = token.Name;
if (name.Is(TagNames.Tr)) {
InRowEndTagTablerow(token);
return;
}
if (name.Is(TagNames.Table)) {
if (InRowEndTagTablerow(token))
InTableBody(token);
return;
}
if (TagNames.AllTableSections.Contains(name)) {
if (IsInTableScope(name)) {
InRowEndTagTablerow(token);
InTableBody(token);
} else
RaiseErrorOccurred(HtmlParseError.TableSectionNotInScope, token);
return;
}
if (TagNames.AllTableSpecial.Contains(name)) {
RaiseErrorOccurred(HtmlParseError.TagCannotEndHere, token);
return;
}
break;
}
}
InTable(token);
}
private void InCell(HtmlToken token)
{
switch (token.Type) {
case HtmlTokenType.StartTag: {
string name2 = token.Name;
if (TagNames.AllTableCellsRows.Contains(name2) || TagNames.AllTableGeneral.Contains(name2)) {
if (IsInTableScope(TagNames.AllTableCells)) {
InCellEndTagCell(token);
Home(token);
} else
RaiseErrorOccurred(HtmlParseError.TableCellNotInScope, token);
return;
}
break;
}
case HtmlTokenType.EndTag: {
string name = token.Name;
if (TagNames.AllTableCells.Contains(name))
InCellEndTagCell(token);
else if (TagNames.AllTableCore.Contains(name)) {
if (IsInTableScope(name)) {
InCellEndTagCell(token);
Home(token);
} else
RaiseErrorOccurred(HtmlParseError.TableNotInScope, token);
} else if (!TagNames.AllTableSpecial.Contains(name)) {
InBody(token);
} else {
RaiseErrorOccurred(HtmlParseError.TagCannotEndHere, token);
}
return;
}
}
InBody(token);
}
private void InSelect(HtmlToken token)
{
switch (token.Type) {
case HtmlTokenType.Character:
AddCharacters(token.Data);
break;
case HtmlTokenType.Comment:
CurrentNode.AddComment(token);
break;
case HtmlTokenType.Doctype:
RaiseErrorOccurred(HtmlParseError.DoctypeTagInappropriate, token);
break;
case HtmlTokenType.StartTag: {
string name2 = token.Name;
if (name2.Is(TagNames.Html))
InBody(token);
else if (name2.Is(TagNames.Option)) {
if (CurrentNode.LocalName.Is(TagNames.Option))
InSelectEndTagOption(token);
AddElement(new HtmlOptionElement(_document, null), token.AsTag(), false);
} else if (name2.Is(TagNames.Optgroup)) {
if (CurrentNode.LocalName.Is(TagNames.Option))
InSelectEndTagOption(token);
if (CurrentNode.LocalName.Is(TagNames.Optgroup))
InSelectEndTagOptgroup(token);
AddElement(new HtmlOptionsGroupElement(_document, null), token.AsTag(), false);
} else if (name2.Is(TagNames.Select)) {
RaiseErrorOccurred(HtmlParseError.SelectNesting, token);
InSelectEndTagSelect();
} else if (TagNames.AllInput.Contains(name2)) {
RaiseErrorOccurred(HtmlParseError.IllegalElementInSelectDetected, token);
if (IsInSelectScope(TagNames.Select)) {
InSelectEndTagSelect();
Home(token);
}
} else if (name2.IsOneOf(TagNames.Template, TagNames.Script)) {
InHead(token);
} else {
RaiseErrorOccurred(HtmlParseError.IllegalElementInSelectDetected, token);
}
break;
}
case HtmlTokenType.EndTag: {
string name = token.Name;
if (name.Is(TagNames.Template))
InHead(token);
else if (name.Is(TagNames.Optgroup)) {
InSelectEndTagOptgroup(token);
} else if (name.Is(TagNames.Option)) {
InSelectEndTagOption(token);
} else if (name.Is(TagNames.Select) && IsInSelectScope(TagNames.Select)) {
InSelectEndTagSelect();
} else if (name.Is(TagNames.Select)) {
RaiseErrorOccurred(HtmlParseError.SelectNotInScope, token);
} else {
RaiseErrorOccurred(HtmlParseError.TagCannotEndHere, token);
}
break;
}
case HtmlTokenType.EndOfFile:
InBody(token);
break;
default:
RaiseErrorOccurred(HtmlParseError.TokenNotPossible, token);
break;
}
}
private void InSelectInTable(HtmlToken token)
{
switch (token.Type) {
case HtmlTokenType.StartTag: {
string name2 = token.Name;
if (TagNames.AllTableSelects.Contains(name2)) {
RaiseErrorOccurred(HtmlParseError.IllegalElementInSelectDetected, token);
InSelectEndTagSelect();
Home(token);
return;
}
break;
}
case HtmlTokenType.EndTag: {
string name = token.Name;
if (TagNames.AllTableSelects.Contains(name)) {
RaiseErrorOccurred(HtmlParseError.TagCannotEndHere, token);
if (IsInTableScope(name)) {
InSelectEndTagSelect();
Home(token);
}
return;
}
break;
}
}
InSelect(token);
}
private void InTemplate(HtmlToken token)
{
switch (token.Type) {
case HtmlTokenType.StartTag: {
string name = token.Name;
if (name.Is(TagNames.Script) || TagNames.AllHead.Contains(name))
InHead(token);
else if (TagNames.AllTableRoot.Contains(name)) {
TemplateStep(token, HtmlTreeMode.InTable);
} else if (name.Is(TagNames.Col)) {
TemplateStep(token, HtmlTreeMode.InColumnGroup);
} else if (name.Is(TagNames.Tr)) {
TemplateStep(token, HtmlTreeMode.InTableBody);
} else if (TagNames.AllTableCells.Contains(name)) {
TemplateStep(token, HtmlTreeMode.InRow);
} else {
TemplateStep(token, HtmlTreeMode.InBody);
}
break;
}
case HtmlTokenType.EndTag:
if (token.Name.Is(TagNames.Template))
InHead(token);
else
RaiseErrorOccurred(HtmlParseError.TagCannotEndHere, token);
break;
case HtmlTokenType.EndOfFile:
if (TagCurrentlyOpen(TagNames.Template)) {
RaiseErrorOccurred(HtmlParseError.EOF, token);
CloseTemplate();
Home(token);
} else
End();
break;
default:
InBody(token);
break;
}
}
private void AfterBody(HtmlToken token)
{
switch (token.Type) {
case HtmlTokenType.Character: {
string text = token.TrimStart();
ReconstructFormatting();
AddCharacters(text);
if (token.IsEmpty)
return;
break;
}
case HtmlTokenType.Comment:
_openElements[0].AddComment(token);
return;
case HtmlTokenType.Doctype:
RaiseErrorOccurred(HtmlParseError.DoctypeTagInappropriate, token);
return;
case HtmlTokenType.StartTag:
if (token.Name.Is(TagNames.Html)) {
InBody(token);
return;
}
break;
case HtmlTokenType.EndTag:
if (token.Name.Is(TagNames.Html)) {
if (IsFragmentCase)
RaiseErrorOccurred(HtmlParseError.TagInvalidInFragmentMode, token);
else
_currentMode = HtmlTreeMode.AfterAfterBody;
return;
}
break;
case HtmlTokenType.EndOfFile:
End();
return;
}
RaiseErrorOccurred(HtmlParseError.TokenNotPossible, token);
_currentMode = HtmlTreeMode.InBody;
InBody(token);
}
private void InFrameset(HtmlToken token)
{
switch (token.Type) {
case HtmlTokenType.Character: {
string text = token.TrimStart();
AddCharacters(text);
if (token.IsEmpty)
return;
break;
}
case HtmlTokenType.Comment:
CurrentNode.AddComment(token);
return;
case HtmlTokenType.Doctype:
RaiseErrorOccurred(HtmlParseError.DoctypeTagInappropriate, token);
return;
case HtmlTokenType.StartTag: {
string name = token.Name;
if (name.Is(TagNames.Html)) {
InBody(token);
return;
}
if (name.Is(TagNames.Frameset)) {
AddElement(new HtmlFrameSetElement(_document, null), token.AsTag(), false);
return;
}
if (name.Is(TagNames.Frame)) {
AddElement(new HtmlFrameElement(_document, null), token.AsTag(), true);
CloseCurrentNode();
return;
}
if (name.Is(TagNames.NoFrames)) {
InHead(token);
return;
}
break;
}
case HtmlTokenType.EndTag:
if (token.Name.Is(TagNames.Frameset)) {
if (CurrentNode != _openElements[0]) {
CloseCurrentNode();
if (!IsFragmentCase && !CurrentNode.LocalName.Is(TagNames.Frameset))
_currentMode = HtmlTreeMode.AfterFrameset;
} else
RaiseErrorOccurred(HtmlParseError.CurrentNodeIsRoot, token);
return;
}
break;
case HtmlTokenType.EndOfFile:
if (CurrentNode != _document.DocumentElement)
RaiseErrorOccurred(HtmlParseError.CurrentNodeIsNotRoot, token);
End();
return;
}
RaiseErrorOccurred(HtmlParseError.TokenNotPossible, token);
}
private void AfterFrameset(HtmlToken token)
{
switch (token.Type) {
case HtmlTokenType.Character: {
string text = token.TrimStart();
AddCharacters(text);
if (token.IsEmpty)
return;
break;
}
case HtmlTokenType.Comment:
CurrentNode.AddComment(token);
return;
case HtmlTokenType.Doctype:
RaiseErrorOccurred(HtmlParseError.DoctypeTagInappropriate, token);
return;
case HtmlTokenType.StartTag: {
string name = token.Name;
if (name.Is(TagNames.Html)) {
InBody(token);
return;
}
if (name.Is(TagNames.NoFrames)) {
InHead(token);
return;
}
break;
}
case HtmlTokenType.EndTag:
if (token.Name.Is(TagNames.Html)) {
_currentMode = HtmlTreeMode.AfterAfterFrameset;
return;
}
break;
case HtmlTokenType.EndOfFile:
End();
return;
}
RaiseErrorOccurred(HtmlParseError.TokenNotPossible, token);
}
private void AfterAfterBody(HtmlToken token)
{
switch (token.Type) {
case HtmlTokenType.Character: {
string text = token.TrimStart();
ReconstructFormatting();
AddCharacters(text);
if (token.IsEmpty)
return;
break;
}
case HtmlTokenType.EndOfFile:
End();
return;
case HtmlTokenType.Comment:
_document.AddComment(token);
return;
case HtmlTokenType.Doctype:
InBody(token);
return;
case HtmlTokenType.StartTag:
if (token.Name.Is(TagNames.Html)) {
InBody(token);
return;
}
break;
}
RaiseErrorOccurred(HtmlParseError.TokenNotPossible, token);
_currentMode = HtmlTreeMode.InBody;
InBody(token);
}
private void AfterAfterFrameset(HtmlToken token)
{
switch (token.Type) {
case HtmlTokenType.Comment:
_document.AddComment(token);
return;
case HtmlTokenType.Character: {
string text = token.TrimStart();
ReconstructFormatting();
AddCharacters(text);
if (token.IsEmpty)
return;
break;
}
case HtmlTokenType.Doctype:
InBody(token);
return;
case HtmlTokenType.StartTag: {
string name = token.Name;
if (name.Is(TagNames.Html)) {
InBody(token);
return;
}
if (name.Is(TagNames.NoFrames)) {
InHead(token);
return;
}
break;
}
case HtmlTokenType.EndOfFile:
End();
return;
}
RaiseErrorOccurred(HtmlParseError.TokenNotPossible, token);
}
private void TemplateStep(HtmlToken token, HtmlTreeMode mode)
{
_templateModes.Pop();
_templateModes.Push(mode);
_currentMode = mode;
Home(token);
}
private void CloseTemplate()
{
while (_openElements.Count > 0) {
HtmlTemplateElement htmlTemplateElement = CurrentNode as HtmlTemplateElement;
CloseCurrentNode();
if (htmlTemplateElement != null) {
htmlTemplateElement.PopulateFragment();
break;
}
}
_formattingElements.ClearFormatting();
_templateModes.Pop();
Reset();
}
private void InTableBodyCloseTable(HtmlTagToken tag)
{
if (IsInTableScope(TagNames.AllTableSections)) {
ClearStackBackTo(TagNames.AllTableSections);
CloseCurrentNode();
_currentMode = HtmlTreeMode.InTable;
InTable(tag);
} else
RaiseErrorOccurred(HtmlParseError.TableSectionNotInScope, tag);
}
private void InSelectEndTagOption(HtmlToken token)
{
if (CurrentNode.LocalName.Is(TagNames.Option))
CloseCurrentNode();
else
RaiseErrorOccurred(HtmlParseError.TagDoesNotMatchCurrentNode, token);
}
private void InSelectEndTagOptgroup(HtmlToken token)
{
if (_openElements.Count > 1 && _openElements[_openElements.Count - 1].LocalName.Is(TagNames.Option) && _openElements[_openElements.Count - 2].LocalName.Is(TagNames.Optgroup))
CloseCurrentNode();
if (CurrentNode.LocalName.Is(TagNames.Optgroup))
CloseCurrentNode();
else
RaiseErrorOccurred(HtmlParseError.TagDoesNotMatchCurrentNode, token);
}
private bool InColumnGroupEndTagColgroup(HtmlToken token)
{
if (CurrentNode.LocalName.Is(TagNames.Colgroup)) {
CloseCurrentNode();
_currentMode = HtmlTreeMode.InTable;
return true;
}
RaiseErrorOccurred(HtmlParseError.TagDoesNotMatchCurrentNode, token);
return false;
}
private void AfterHeadStartTagBody(HtmlTagToken token)
{
AddElement(new HtmlBodyElement(_document, null), token, false);
_frameset = false;
_currentMode = HtmlTreeMode.InBody;
}
private void RawtextAlgorithm(HtmlTagToken tag)
{
AddElement(tag, false);
_previousMode = _currentMode;
_currentMode = HtmlTreeMode.Text;
_tokenizer.State = HtmlParseMode.Rawtext;
}
private void RCDataAlgorithm(HtmlTagToken tag)
{
AddElement(tag, false);
_previousMode = _currentMode;
_currentMode = HtmlTreeMode.Text;
_tokenizer.State = HtmlParseMode.RCData;
}
private void InBodyStartTagListItem(HtmlTagToken tag)
{
int num = _openElements.Count - 1;
Element element = _openElements[num];
_frameset = false;
while (true) {
if (element.LocalName.Is(TagNames.Li)) {
InBody(HtmlTagToken.Close(element.LocalName));
break;
}
if (element.Flags.HasFlag(NodeFlags.Special) && !TagNames.AllBasicBlocks.Contains(element.LocalName))
break;
element = _openElements[--num];
}
if (IsInButtonScope())
InBodyEndTagParagraph(tag);
AddElement(tag, false);
}
private void InBodyStartTagDefinitionItem(HtmlTagToken tag)
{
_frameset = false;
int num = _openElements.Count - 1;
Element element = _openElements[num];
while (true) {
if (element.LocalName.IsOneOf(TagNames.Dd, TagNames.Dt)) {
InBody(HtmlTagToken.Close(element.LocalName));
break;
}
if (element.Flags.HasFlag(NodeFlags.Special) && !TagNames.AllBasicBlocks.Contains(element.LocalName))
break;
element = _openElements[--num];
}
if (IsInButtonScope())
InBodyEndTagParagraph(tag);
AddElement(tag, false);
}
private bool InBodyEndTagBlock(HtmlTagToken tag)
{
if (IsInScope(tag.Name)) {
GenerateImpliedEndTags();
if (!CurrentNode.LocalName.Is(tag.Name))
RaiseErrorOccurred(HtmlParseError.TagDoesNotMatchCurrentNode, tag);
ClearStackBackTo(tag.Name);
CloseCurrentNode();
return true;
}
RaiseErrorOccurred(HtmlParseError.BlockNotInScope, tag);
return false;
}
private void HeisenbergAlgorithm(HtmlTagToken tag)
{
int num = 0;
int num2 = 0;
int num3 = 0;
int num4 = 0;
Element element;
Element element2;
while (true) {
if (num >= 8)
return;
element = null;
element2 = null;
num++;
num4 = 0;
num2 = 0;
for (int num5 = _formattingElements.Count - 1; num5 >= 0; num5--) {
if (_formattingElements[num5] == null)
break;
if (_formattingElements[num5].LocalName.Is(tag.Name)) {
num4 = num5;
element = _formattingElements[num5];
break;
}
}
if (element == null) {
InBodyEndTagAnythingElse(tag);
return;
}
int num6 = _openElements.IndexOf(element);
if (num6 == -1) {
RaiseErrorOccurred(HtmlParseError.FormattingElementNotFound, tag);
_formattingElements.Remove(element);
return;
}
if (!IsInScope(element.LocalName)) {
RaiseErrorOccurred(HtmlParseError.ElementNotInScope, tag);
return;
}
if (num6 != _openElements.Count - 1)
RaiseErrorOccurred(HtmlParseError.TagClosedWrong, tag);
num3 = num4;
for (int i = num6 + 1; i < _openElements.Count; i++) {
if (_openElements[i].Flags.HasFlag(NodeFlags.Special)) {
num4 = i;
element2 = _openElements[i];
break;
}
}
if (element2 == null)
break;
Element element3 = _openElements[num6 - 1];
Element element4 = element2;
Element element5 = element2;
while (true) {
num2++;
element4 = _openElements[--num4];
if (element4 == element)
break;
if (num2 > 3 && _formattingElements.Contains(element4))
_formattingElements.Remove(element4);
if (!_formattingElements.Contains(element4))
CloseNode(element4);
else {
Element element6 = CopyElement(element4);
element3.AddNode(element6);
_openElements[num4] = element6;
for (int j = 0; j != _formattingElements.Count; j++) {
if (_formattingElements[j] == element4) {
_formattingElements[j] = element6;
break;
}
}
element4 = element6;
if (element5 == element2)
num3++;
if (element5.Parent != null)
element5.Parent.RemoveChild(element5);
element4.AddNode(element5);
element5 = element4;
}
}
if (element5.Parent != null)
element5.Parent.RemoveChild(element5);
if (!TagNames.AllTableMajor.Contains(element3.LocalName))
element3.AddNode(element5);
else
AddElementWithFoster(element5);
Element element7 = CopyElement(element);
while (element2.ChildNodes.Length > 0) {
Node node = element2.ChildNodes[0];
element2.RemoveNode(0, node);
element7.AddNode(node);
}
element2.AddNode(element7);
_formattingElements.Remove(element);
_formattingElements.Insert(num3, element7);
CloseNode(element);
_openElements.Insert(_openElements.IndexOf(element2) + 1, element7);
}
do {
element2 = CurrentNode;
CloseCurrentNode();
} while (element2 != element);
_formattingElements.Remove(element);
}
private Element CopyElement(Element element)
{
return (Element)element.Clone(false);
}
private void InBodyWithFoster(HtmlToken token)
{
_foster = true;
InBody(token);
_foster = false;
}
private void InBodyEndTagAnythingElse(HtmlTagToken tag)
{
int num = _openElements.Count - 1;
Element element = CurrentNode;
while (true) {
if (element == null)
return;
if (element.LocalName.Is(tag.Name)) {
GenerateImpliedEndTagsExceptFor(tag.Name);
if (!element.LocalName.Is(tag.Name))
RaiseErrorOccurred(HtmlParseError.TagClosedWrong, tag);
CloseNodesFrom(num);
return;
}
if (element.Flags.HasFlag(NodeFlags.Special))
break;
element = _openElements[--num];
}
RaiseErrorOccurred(HtmlParseError.TagClosedWrong, tag);
}
private bool InBodyEndTagBody(HtmlToken token)
{
if (IsInScope(TagNames.Body)) {
CheckBodyOnClosing(token);
_currentMode = HtmlTreeMode.AfterBody;
return true;
}
RaiseErrorOccurred(HtmlParseError.BodyNotInScope, token);
return false;
}
private void InBodyStartTagBreakrow(HtmlTagToken tag)
{
ReconstructFormatting();
AddElement(tag, true);
CloseCurrentNode();
_frameset = false;
}
private bool InBodyEndTagParagraph(HtmlToken token)
{
if (IsInButtonScope()) {
GenerateImpliedEndTagsExceptFor(TagNames.P);
if (!CurrentNode.LocalName.Is(TagNames.P))
RaiseErrorOccurred(HtmlParseError.TagDoesNotMatchCurrentNode, token);
ClearStackBackTo(TagNames.P);
CloseCurrentNode();
return true;
}
RaiseErrorOccurred(HtmlParseError.ParagraphNotInScope, token);
InBody(HtmlTagToken.Open(TagNames.P));
InBodyEndTagParagraph(token);
return false;
}
private bool InTableEndTagTable(HtmlToken token)
{
if (IsInTableScope(TagNames.Table)) {
ClearStackBackTo(TagNames.Table);
CloseCurrentNode();
Reset();
return true;
}
RaiseErrorOccurred(HtmlParseError.TableNotInScope, token);
return false;
}
private bool InRowEndTagTablerow(HtmlToken token)
{
if (IsInTableScope(TagNames.Tr)) {
ClearStackBackTo(TagNames.Tr);
CloseCurrentNode();
_currentMode = HtmlTreeMode.InTableBody;
return true;
}
RaiseErrorOccurred(HtmlParseError.TableRowNotInScope, token);
return false;
}
private void InSelectEndTagSelect()
{
ClearStackBackTo(TagNames.Select);
CloseCurrentNode();
Reset();
}
private bool InCaptionEndTagCaption(HtmlToken token)
{
if (IsInTableScope(TagNames.Caption)) {
GenerateImpliedEndTags();
if (!CurrentNode.LocalName.Is(TagNames.Caption))
RaiseErrorOccurred(HtmlParseError.TagDoesNotMatchCurrentNode, token);
ClearStackBackTo(TagNames.Caption);
CloseCurrentNode();
_formattingElements.ClearFormatting();
_currentMode = HtmlTreeMode.InTable;
return true;
}
RaiseErrorOccurred(HtmlParseError.CaptionNotInScope, token);
return false;
}
private bool InCellEndTagCell(HtmlToken token)
{
if (IsInTableScope(TagNames.AllTableCells)) {
GenerateImpliedEndTags();
if (!TagNames.AllTableCells.Contains(CurrentNode.LocalName))
RaiseErrorOccurred(HtmlParseError.TagDoesNotMatchCurrentNode, token);
ClearStackBackTo(TagNames.AllTableCells);
CloseCurrentNode();
_formattingElements.ClearFormatting();
_currentMode = HtmlTreeMode.InRow;
return true;
}
RaiseErrorOccurred(HtmlParseError.TableCellNotInScope, token);
return false;
}
private void Foreign(HtmlToken token)
{
switch (token.Type) {
case HtmlTokenType.Character:
AddCharacters(token.Data.Replace(' ', '�'));
_frameset = (!token.HasContent && _frameset);
break;
case HtmlTokenType.StartTag: {
string name2 = token.Name;
HtmlTagToken htmlTagToken = token.AsTag();
if (name2.Is(TagNames.Font)) {
for (int i = 0; i != htmlTagToken.Attributes.Count; i++) {
if (htmlTagToken.Attributes[i].Key.IsOneOf(AttributeNames.Color, AttributeNames.Face, AttributeNames.Size)) {
ForeignNormalTag(htmlTagToken);
return;
}
}
ForeignSpecialTag(htmlTagToken);
} else if (TagNames.AllForeignExceptions.Contains(name2)) {
ForeignNormalTag(htmlTagToken);
} else {
ForeignSpecialTag(htmlTagToken);
}
break;
}
case HtmlTokenType.EndTag: {
string name = token.Name;
Element element = CurrentNode;
HtmlScriptElement htmlScriptElement = element as HtmlScriptElement;
if (htmlScriptElement != null)
HandleScript(htmlScriptElement);
else {
if (!element.LocalName.Is(name))
RaiseErrorOccurred(HtmlParseError.TagClosingMismatch, token);
int num = _openElements.Count - 1;
while (true) {
if (num <= 0)
return;
if (element.LocalName.Isi(name)) {
CloseNodesFrom(num);
return;
}
element = _openElements[num - 1];
if (element.Flags.HasFlag(NodeFlags.HtmlMember))
break;
num--;
}
Home(token);
}
break;
}
case HtmlTokenType.Comment:
CurrentNode.AddComment(token);
break;
case HtmlTokenType.Doctype:
RaiseErrorOccurred(HtmlParseError.DoctypeTagInappropriate, token);
break;
}
}
private void ForeignSpecialTag(HtmlTagToken tag)
{
Element element = CreateForeignElementFrom(tag);
if (element != null) {
bool isSelfClosing = tag.IsSelfClosing;
CurrentNode.AddNode(element);
if (isSelfClosing)
element.SetupElement();
if (!isSelfClosing) {
_openElements.Add(element);
_tokenizer.IsAcceptingCharacterData = true;
} else if (tag.Name.Is(TagNames.Script)) {
Foreign(HtmlTagToken.Close(TagNames.Script));
}
}
}
private Element CreateForeignElementFrom(HtmlTagToken tag)
{
if (AdjustedCurrentNode.Flags.HasFlag(NodeFlags.MathMember)) {
string name = tag.Name;
return _mathFactory.Create(_document, name, null).Setup(tag);
}
if (AdjustedCurrentNode.Flags.HasFlag(NodeFlags.SvgMember)) {
string localName = tag.Name.SanatizeSvgTagName();
return _svgFactory.Create(_document, localName, null).Setup(tag);
}
return null;
}
private void ForeignNormalTag(HtmlTagToken tag)
{
RaiseErrorOccurred(HtmlParseError.TagCannotStartHere, tag);
if (!IsFragmentCase) {
Element currentNode = CurrentNode;
do {
if (currentNode.LocalName.Is(TagNames.AnnotationXml)) {
string attribute = currentNode.GetAttribute(null, AttributeNames.Encoding);
if (attribute.Isi(MimeTypeNames.Html) || attribute.Isi(MimeTypeNames.ApplicationXHtml)) {
AddElement(tag, false);
return;
}
}
CloseCurrentNode();
currentNode = CurrentNode;
} while ((currentNode.Flags & (NodeFlags.HtmlMember | NodeFlags.HtmlTip | NodeFlags.MathTip)) == NodeFlags.None);
Consume(tag);
} else
ForeignSpecialTag(tag);
}
private bool IsInScope(string tagName)
{
for (int num = _openElements.Count - 1; num >= 0; num--) {
Element element = _openElements[num];
if (element.LocalName.Is(tagName))
return true;
if (element.Flags.HasFlag(NodeFlags.Scoped))
return false;
}
return false;
}
private bool IsInScope(HashSet<string> tags)
{
for (int num = _openElements.Count - 1; num >= 0; num--) {
Element element = _openElements[num];
if (tags.Contains(element.LocalName))
return true;
if (element.Flags.HasFlag(NodeFlags.Scoped))
return false;
}
return false;
}
private bool IsInListItemScope()
{
for (int num = _openElements.Count - 1; num >= 0; num--) {
Element element = _openElements[num];
if (element.LocalName.Is(TagNames.Li))
return true;
if (element.Flags.HasFlag(NodeFlags.HtmlListScoped))
return false;
}
return false;
}
private bool IsInButtonScope()
{
for (int num = _openElements.Count - 1; num >= 0; num--) {
Element element = _openElements[num];
if (element.LocalName.Is(TagNames.P))
return true;
if (element.Flags.HasFlag(NodeFlags.Scoped) || element.LocalName.Is(TagNames.Button))
return false;
}
return false;
}
private bool IsInTableScope(HashSet<string> tags)
{
for (int num = _openElements.Count - 1; num >= 0; num--) {
Element element = _openElements[num];
if (tags.Contains(element.LocalName))
return true;
if (element.Flags.HasFlag(NodeFlags.HtmlTableScoped))
return false;
}
return false;
}
private bool IsInTableScope(string tagName)
{
for (int num = _openElements.Count - 1; num >= 0; num--) {
Element element = _openElements[num];
if (element.LocalName.Is(tagName))
return true;
if (element.Flags.HasFlag(NodeFlags.HtmlTableScoped))
return false;
}
return false;
}
private bool IsInSelectScope(string tagName)
{
for (int num = _openElements.Count - 1; num >= 0; num--) {
Element element = _openElements[num];
if (element.LocalName.Is(tagName))
return true;
if (!element.Flags.HasFlag(NodeFlags.HtmlSelectScoped))
return false;
}
return false;
}
private void HandleScript(HtmlScriptElement script)
{
if (script != null) {
if (IsFragmentCase) {
CloseCurrentNode();
_currentMode = _previousMode;
} else {
_document.PerformMicrotaskCheckpoint();
_document.ProvideStableState();
CloseCurrentNode();
_currentMode = _previousMode;
if (script.Prepare(_document))
_waiting = RunScript(script);
}
}
}
private async Task RunScript(HtmlScriptElement script)
{
await _document.WaitForReadyAsync().ConfigureAwait(false);
await script.RunAsync(CancellationToken.None).ConfigureAwait(false);
}
private void CheckBodyOnClosing(HtmlToken token)
{
int num = 0;
while (true) {
if (num >= _openElements.Count)
return;
if (!_openElements[num].Flags.HasFlag(NodeFlags.ImplicitelyClosed))
break;
num++;
}
RaiseErrorOccurred(HtmlParseError.BodyClosedWrong, token);
}
private bool TagCurrentlyOpen(string tagName)
{
for (int i = 0; i < _openElements.Count; i++) {
if (_openElements[i].LocalName.Is(tagName))
return true;
}
return false;
}
private void PreventNewLine()
{
HtmlToken htmlToken = _tokenizer.Get();
if (htmlToken.Type == HtmlTokenType.Character)
htmlToken.RemoveNewLine();
Home(htmlToken);
}
private void End()
{
while (_openElements.Count != 0) {
CloseCurrentNode();
}
if (_document.IsLoading)
_waiting = _document.FinishLoadingAsync();
}
private void AddRoot(HtmlTagToken tag)
{
HtmlHtmlElement htmlHtmlElement = new HtmlHtmlElement(_document, null);
_document.AddNode(htmlHtmlElement);
SetupElement(htmlHtmlElement, tag, false);
_openElements.Add(htmlHtmlElement);
_tokenizer.IsAcceptingCharacterData = false;
_document.ApplyManifest();
}
private void CloseNode(Element element)
{
element.SetupElement();
_openElements.Remove(element);
}
private void CloseNodesFrom(int index)
{
for (int num = _openElements.Count - 1; num > index; num--) {
_openElements[num].SetupElement();
_openElements.RemoveAt(num);
}
CloseCurrentNode();
}
private void CloseCurrentNode()
{
if (_openElements.Count > 0) {
int index = _openElements.Count - 1;
_openElements[index].SetupElement();
_openElements.RemoveAt(index);
Element adjustedCurrentNode = AdjustedCurrentNode;
_tokenizer.IsAcceptingCharacterData = (adjustedCurrentNode != null && !adjustedCurrentNode.Flags.HasFlag(NodeFlags.HtmlMember));
}
}
private void SetupElement(Element element, HtmlTagToken tag, bool acknowledgeSelfClosing)
{
if (tag.IsSelfClosing && !acknowledgeSelfClosing)
RaiseErrorOccurred(HtmlParseError.TagCannotBeSelfClosed, tag);
element.SetAttributes(tag.Attributes);
}
private Element AddElement(HtmlTagToken tag, bool acknowledgeSelfClosing = false)
{
HtmlElement htmlElement = _htmlFactory.Create(_document, tag.Name, null);
SetupElement(htmlElement, tag, acknowledgeSelfClosing);
AddElement(htmlElement);
return htmlElement;
}
private void AddElement(Element element, HtmlTagToken tag, bool acknowledgeSelfClosing = false)
{
SetupElement(element, tag, acknowledgeSelfClosing);
AddElement(element);
}
private void AddElement(Element element)
{
Element currentNode = CurrentNode;
if (_foster && TagNames.AllTableMajor.Contains(currentNode.LocalName))
AddElementWithFoster(element);
else
currentNode.AddNode(element);
_openElements.Add(element);
_tokenizer.IsAcceptingCharacterData = !element.Flags.HasFlag(NodeFlags.HtmlMember);
}
private void AddElementWithFoster(Element element)
{
bool flag = false;
int num = _openElements.Count;
while (--num != 0) {
if (_openElements[num].LocalName.Is(TagNames.Template)) {
_openElements[num].AddNode(element);
return;
}
if (_openElements[num].LocalName.Is(TagNames.Table)) {
flag = true;
break;
}
}
Node node = _openElements[num].Parent ?? _openElements[num + 1];
if (flag && _openElements[num].Parent != null) {
int num2 = 0;
while (true) {
if (num2 >= node.ChildNodes.Length)
return;
if (node.ChildNodes[num2] == _openElements[num])
break;
num2++;
}
node.InsertNode(num2, element);
} else
node.AddNode(element);
}
private void AddCharacters(string text)
{
if (!string.IsNullOrEmpty(text)) {
Element currentNode = CurrentNode;
if (_foster && TagNames.AllTableMajor.Contains(currentNode.LocalName))
AddCharactersWithFoster(text);
else
currentNode.AppendText(text);
}
}
private void AddCharactersWithFoster(string text)
{
bool flag = false;
int num = _openElements.Count;
while (--num != 0) {
if (_openElements[num].LocalName.Is(TagNames.Template)) {
_openElements[num].AppendText(text);
return;
}
if (_openElements[num].LocalName.Is(TagNames.Table)) {
flag = true;
break;
}
}
Node node = _openElements[num].Parent ?? _openElements[num + 1];
if (flag && _openElements[num].Parent != null) {
int num2 = 0;
while (true) {
if (num2 >= node.ChildNodes.Length)
return;
if (node.ChildNodes[num2] == _openElements[num])
break;
num2++;
}
node.InsertText(num2, text);
} else
node.AppendText(text);
}
private void ClearStackBackTo(string tagName)
{
Element currentNode = CurrentNode;
while (!currentNode.LocalName.IsOneOf(tagName, TagNames.Html, TagNames.Template)) {
CloseCurrentNode();
currentNode = CurrentNode;
}
}
private void ClearStackBackTo(HashSet<string> tags)
{
Element currentNode = CurrentNode;
while (!tags.Contains(currentNode.LocalName) && !currentNode.LocalName.IsOneOf(TagNames.Html, TagNames.Template)) {
CloseCurrentNode();
currentNode = CurrentNode;
}
}
private void GenerateImpliedEndTagsExceptFor(string tagName)
{
Element currentNode = CurrentNode;
while (currentNode.Flags.HasFlag(NodeFlags.ImpliedEnd) && !currentNode.LocalName.Is(tagName)) {
CloseCurrentNode();
currentNode = CurrentNode;
}
}
private void GenerateImpliedEndTags()
{
while (CurrentNode.Flags.HasFlag(NodeFlags.ImpliedEnd)) {
CloseCurrentNode();
}
}
private void ReconstructFormatting()
{
if (_formattingElements.Count != 0) {
int i = _formattingElements.Count - 1;
Element element = _formattingElements[i];
if (element != null && !_openElements.Contains(element)) {
while (i > 0) {
element = _formattingElements[--i];
if (element == null || _openElements.Contains(element)) {
i++;
break;
}
}
for (; i < _formattingElements.Count; i++) {
Element element2 = CopyElement(_formattingElements[i]);
AddElement(element2);
_formattingElements[i] = element2;
}
}
}
}
private void RaiseErrorOccurred(HtmlParseError code, HtmlToken token)
{
_tokenizer.RaiseErrorOccurred(code, token.Position);
}
}
}