void InBodyStartTag(HtmlTagToken tag) { var tagName = tag.Name; if (tagName.Is(TagNames.Div)) { if (IsInButtonScope()) InBodyEndTagParagraph(tag); AddElement(tag); } else if (tagName.Is(TagNames.A)) { for (var i = _formattingElements.Count - 1; i >= 0; i--) { if (_formattingElements[i] == null) break; if (_formattingElements[i].LocalName.Is(TagNames.A)) { var format = _formattingElements[i]; RaiseErrorOccurred(HtmlParseError.AnchorNested, tag); HeisenbergAlgorithm(HtmlTagToken.Close(TagNames.A)); _openElements.Remove(format); _formattingElements.Remove(format); break; } } ReconstructFormatting(); var element = new HtmlAnchorElement(_document); AddElement(element, tag); _formattingElements.AddFormatting(element); } else if (tagName.Is(TagNames.Span)) { ReconstructFormatting(); AddElement(tag); } else if (tagName.Is(TagNames.Li)) { InBodyStartTagListItem(tag); } else if (tagName.Is(TagNames.Img)) { InBodyStartTagBreakrow(tag); } else if (tagName.IsOneOf(TagNames.Ul, TagNames.P)) { if (IsInButtonScope()) InBodyEndTagParagraph(tag); AddElement(tag); } else if (TagNames.AllSemanticFormatting.Contains(tagName)) { ReconstructFormatting(); _formattingElements.AddFormatting(AddElement(tag)); } else if (tagName.Is(TagNames.Script)) { InHead(tag); } else if (TagNames.AllHeadings.Contains(tagName)) { if (IsInButtonScope()) InBodyEndTagParagraph(tag); if (TagNames.AllHeadings.Contains(CurrentNode.LocalName)) { RaiseErrorOccurred(HtmlParseError.HeadingNested, tag); CloseCurrentNode(); } AddElement(new HtmlHeadingElement(_document, tagName), tag); } else if (tagName.Is(TagNames.Input)) { ReconstructFormatting(); AddElement(new HtmlInputElement(_document), tag, true); CloseCurrentNode(); if (!tag.GetAttribute(AttributeNames.Type).Isi(AttributeNames.Hidden)) _frameset = false; } else if (tagName.Is(TagNames.Form)) { if (_currentFormElement == null) { if (IsInButtonScope()) InBodyEndTagParagraph(tag); _currentFormElement = new HtmlFormElement(_document); AddElement(_currentFormElement, tag); } else RaiseErrorOccurred(HtmlParseError.FormAlreadyOpen, tag); } else if (TagNames.AllBody.Contains(tagName)) { if (IsInButtonScope()) InBodyEndTagParagraph(tag); AddElement(tag); } else if (TagNames.AllClassicFormatting.Contains(tagName)) { ReconstructFormatting(); _formattingElements.AddFormatting(AddElement(tag)); } else if (TagNames.AllHead.Contains(tagName)) { InHead(tag); } else if (tagName.IsOneOf(TagNames.Pre, TagNames.Listing)) { if (IsInButtonScope()) InBodyEndTagParagraph(tag); AddElement(tag); _frameset = false; PreventNewLine(); } else if (tagName.Is(TagNames.Button)) { if (IsInScope(TagNames.Button)) { RaiseErrorOccurred(HtmlParseError.ButtonInScope, tag); InBodyEndTagBlock(tag); InBody(tag); } else { ReconstructFormatting(); AddElement(new HtmlButtonElement(_document), tag); _frameset = false; } } else if (tagName.Is(TagNames.Table)) { if (_document.QuirksMode != QuirksMode.On && IsInButtonScope()) InBodyEndTagParagraph(tag); AddElement(new HtmlTableElement(_document), tag); _frameset = false; _currentMode = HtmlTreeMode.InTable; } else if (TagNames.AllBodyBreakrow.Contains(tagName)) { InBodyStartTagBreakrow(tag); } else if (TagNames.AllBodyClosed.Contains(tagName)) { AddElement(tag, true); CloseCurrentNode(); } else if (tagName.Is(TagNames.Hr)) { if (IsInButtonScope()) InBodyEndTagParagraph(tag); AddElement(new HtmlHrElement(_document), tag, true); CloseCurrentNode(); _frameset = false; } else if (tagName.Is(TagNames.Textarea)) { AddElement(new HtmlTextAreaElement(_document), tag); _tokenizer.State = HtmlParseMode.RCData; _previousMode = _currentMode; _frameset = false; _currentMode = HtmlTreeMode.Text; PreventNewLine(); } else if (tagName.Is(TagNames.Select)) { ReconstructFormatting(); AddElement(new HtmlSelectElement(_document), tag); _frameset = false; switch (_currentMode) { case HtmlTreeMode.InTable: case HtmlTreeMode.InTableBody: case HtmlTreeMode.InCaption: case HtmlTreeMode.InRow: case HtmlTreeMode.InCell: _currentMode = HtmlTreeMode.InSelectInTable; break; default: _currentMode = HtmlTreeMode.InSelect; break; } } else if (tagName.IsOneOf(TagNames.Optgroup, TagNames.Option)) { if (CurrentNode.LocalName.Is(TagNames.Option)) InBodyEndTagAnythingElse(HtmlTagToken.Close(TagNames.Option)); ReconstructFormatting(); AddElement(tag); } else if (tagName.IsOneOf(TagNames.Dd, TagNames.Dt)) { InBodyStartTagDefinitionItem(tag); } else if (tagName.Is(TagNames.Iframe)) { _frameset = false; RawtextAlgorithm(tag); } else if (TagNames.AllBodyObsolete.Contains(tagName)) { ReconstructFormatting(); AddElement(tag); _formattingElements.AddScopeMarker(); _frameset = false; } else if (tagName.Is(TagNames.Image)) { RaiseErrorOccurred(HtmlParseError.ImageTagNamedWrong, tag); tag.Name = TagNames.Img; InBodyStartTagBreakrow(tag); } else if (tagName.Is(TagNames.NoBr)) { ReconstructFormatting(); if (IsInScope(TagNames.NoBr)) { RaiseErrorOccurred(HtmlParseError.NobrInScope, tag); HeisenbergAlgorithm(tag); ReconstructFormatting(); } _formattingElements.AddFormatting(AddElement(tag)); } else if (tagName.Is(TagNames.Xmp)) { if (IsInButtonScope()) InBodyEndTagParagraph(tag); ReconstructFormatting(); _frameset = false; RawtextAlgorithm(tag); } else if (tagName.IsOneOf(TagNames.Rb, TagNames.Rtc)) { if (IsInScope(TagNames.Ruby)) { GenerateImpliedEndTags(); if (!CurrentNode.LocalName.Is(TagNames.Ruby)) RaiseErrorOccurred(HtmlParseError.TagDoesNotMatchCurrentNode, tag); } AddElement(tag); } else if (tagName.IsOneOf(TagNames.Rp, TagNames.Rt)) { if (IsInScope(TagNames.Ruby)) { GenerateImpliedEndTagsExceptFor(TagNames.Rtc); if (CurrentNode.LocalName.IsOneOf(TagNames.Ruby, TagNames.Rtc) == false) RaiseErrorOccurred(HtmlParseError.TagDoesNotMatchCurrentNode, tag); } AddElement(tag); } else if (tagName.Is(TagNames.NoEmbed)) { RawtextAlgorithm(tag); } else if (tagName.Is(TagNames.NoScript)) { if (_options.IsScripting) { RawtextAlgorithm(tag); return; } ReconstructFormatting(); AddElement(tag); } else if (tagName.Is(TagNames.Math)) { var element = new MathElement(_document, tagName); ReconstructFormatting(); AddElement(element.Setup(tag)); if (tag.IsSelfClosing) { _openElements.Remove(element); } } else if (tagName.Is(TagNames.Svg)) { var element = new SvgElement(_document, tagName); ReconstructFormatting(); AddElement(element.Setup(tag)); if (tag.IsSelfClosing) { _openElements.Remove(element); } } else if (tagName.Is(TagNames.Plaintext)) { if (IsInButtonScope()) { InBodyEndTagParagraph(tag); } AddElement(tag); _tokenizer.State = HtmlParseMode.Plaintext; } else if (tagName.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), tag); _currentMode = HtmlTreeMode.InFrameset; } } else if (tagName.Is(TagNames.Html)) { RaiseErrorOccurred(HtmlParseError.HtmlTagMisplaced, tag); if (_templateModes.Count == 0) { _openElements[0].SetUniqueAttributes(tag.Attributes); } } else if (tagName.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 (tagName.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: "); var input = HtmlTagToken.Open(TagNames.Input); input.AddAttribute(AttributeNames.Name, TagNames.IsIndex); for (int i = 0; i < tag.Attributes.Count; i++) { if (tag.Attributes[i].Key.IsOneOf(AttributeNames.Name, AttributeNames.Action, AttributeNames.Prompt) == false) input.AddAttribute(tag.Attributes[i].Key, tag.Attributes[i].Value); } InBody(input); InBody(HtmlTagToken.Close(TagNames.Label)); InBody(HtmlTagToken.Open(TagNames.Hr)); InBody(HtmlTagToken.Close(TagNames.Form)); } } else if (TagNames.AllNested.Contains(tagName)) { RaiseErrorOccurred(HtmlParseError.TagCannotStartHere, tag); } else { ReconstructFormatting(); AddElement(tag); } }
/// <summary> /// See 8.2.5.4.9 The "in table" insertion mode. /// </summary> /// <param name="token">The passed token.</param> 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: { var tagName = token.Name; if (tagName.Is(TagNames.Caption)) { ClearStackBackTo(TagNames.Table); _formattingElements.AddScopeMarker(); AddElement(new HtmlTableCaptionElement(_document), token.AsTag()); _currentMode = HtmlTreeMode.InCaption; } else if (tagName.Is(TagNames.Colgroup)) { ClearStackBackTo(TagNames.Table); AddElement(new HtmlTableColgroupElement(_document), token.AsTag()); _currentMode = HtmlTreeMode.InColumnGroup; } else if (tagName.Is(TagNames.Col)) { InTable(HtmlTagToken.Open(TagNames.Colgroup)); InColumnGroup(token); } else if (TagNames.AllTableSections.Contains(tagName)) { ClearStackBackTo(TagNames.Table); AddElement(new HtmlTableSectionElement(_document, tagName), token.AsTag()); _currentMode = HtmlTreeMode.InTableBody; } else if (TagNames.AllTableCellsRows.Contains(tagName)) { InTable(HtmlTagToken.Open(TagNames.Tbody)); InTableBody(token); } else if (tagName.Is(TagNames.Table)) { RaiseErrorOccurred(HtmlParseError.TableNesting, token); if (InTableEndTagTable(token)) Home(token); } else if (tagName.Is(TagNames.Input)) { var tag = token.AsTag(); if (tag.GetAttribute(AttributeNames.Type).Isi(AttributeNames.Hidden)) { RaiseErrorOccurred(HtmlParseError.InputUnexpected, token); AddElement(new HtmlInputElement(_document), tag, true); CloseCurrentNode(); } else { RaiseErrorOccurred(HtmlParseError.TokenNotPossible, token); InBodyWithFoster(token); } } else if (tagName.Is(TagNames.Form)) { RaiseErrorOccurred(HtmlParseError.FormInappropriate, token); if (_currentFormElement == null) { _currentFormElement = new HtmlFormElement(_document); AddElement(_currentFormElement, token.AsTag()); CloseCurrentNode(); } } else if (TagNames.AllTableHead.Contains(tagName)) { InHead(token); } else { RaiseErrorOccurred(HtmlParseError.IllegalElementInTableDetected, token); InBodyWithFoster(token); } return; } case HtmlTokenType.EndTag: { var tagName = token.Name; if (tagName.Is(TagNames.Table)) { InTableEndTagTable(token); } else if (tagName.Is(TagNames.Template)) { InHead(token); } else if (TagNames.AllTableSpecial.Contains(tagName) || TagNames.AllTableInner.Contains(tagName)) { 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); }
/// <summary> /// Switches to the fragment algorithm with the specified context /// element. Then parses the given source and creates the document. /// </summary> /// <param name="options">The options to use for parsing.</param> /// <param name="context"> /// The context element where the algorithm is applied to. /// </param> public HtmlDocument ParseFragment(HtmlParserOptions options, Element context) { if (context == null) { throw new ArgumentNullException("context"); } var tagName = context.LocalName; if (tagName.IsOneOf(TagNames.Title, TagNames.Textarea)) { _tokenizer.State = HtmlParseMode.RCData; } else if (tagName.IsOneOf(TagNames.Style, TagNames.Xmp, TagNames.Iframe, TagNames.NoEmbed, TagNames.NoFrames)) { _tokenizer.State = HtmlParseMode.Rawtext; } else if (tagName.Is(TagNames.Script)) { _tokenizer.State = HtmlParseMode.Script; } else if (tagName.Is(TagNames.Plaintext)) { _tokenizer.State = HtmlParseMode.Plaintext; } else if (tagName.Is(TagNames.NoScript) && options.IsScripting) { _tokenizer.State = HtmlParseMode.Rawtext; } var root = new HtmlHtmlElement(_document); _document.AddNode(root); _openElements.Add(root); if (context is HtmlTemplateElement) { _templateModes.Push(HtmlTreeMode.InTemplate); } Reset(context); _fragmentContext = context; _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); }
void InBodyEndTag(HtmlTagToken tag) { var tagName = tag.Name; if (tagName.Is(TagNames.Div)) { InBodyEndTagBlock(tag); } else if (tagName.Is(TagNames.A)) { HeisenbergAlgorithm(tag); } else if (tagName.Is(TagNames.Li)) { if (IsInListItemScope()) { GenerateImpliedEndTagsExceptFor(tagName); if (!CurrentNode.LocalName.Is(TagNames.Li)) RaiseErrorOccurred(HtmlParseError.TagDoesNotMatchCurrentNode, tag); ClearStackBackTo(TagNames.Li); CloseCurrentNode(); } else { RaiseErrorOccurred(HtmlParseError.ListItemNotInScope, tag); } } else if (tagName.Is(TagNames.P)) { InBodyEndTagParagraph(tag); } else if (TagNames.AllBlocks.Contains(tagName)) { InBodyEndTagBlock(tag); } else if (TagNames.AllFormatting.Contains(tagName)) { HeisenbergAlgorithm(tag); } else if (tagName.Is(TagNames.Form)) { var node = _currentFormElement; _currentFormElement = null; if (node != null && IsInScope(node.LocalName)) { GenerateImpliedEndTags(); if (CurrentNode != node) RaiseErrorOccurred(HtmlParseError.FormClosedWrong, tag); _openElements.Remove(node); } else { RaiseErrorOccurred(HtmlParseError.FormNotInScope, tag); } } else if (tagName.Is(TagNames.Br)) { RaiseErrorOccurred(HtmlParseError.TagCannotEndHere, tag); InBodyStartTagBreakrow(HtmlTagToken.Open(TagNames.Br)); } else if (TagNames.AllHeadings.Contains(tagName)) { if (IsInScope(TagNames.AllHeadings)) { GenerateImpliedEndTags(); if (!CurrentNode.LocalName.Is(tagName)) RaiseErrorOccurred(HtmlParseError.TagDoesNotMatchCurrentNode, tag); ClearStackBackTo(TagNames.AllHeadings); CloseCurrentNode(); } else { RaiseErrorOccurred(HtmlParseError.HeadingNotInScope, tag); } } else if (tagName.IsOneOf(TagNames.Dd, TagNames.Dt)) { if (IsInScope(tagName)) { GenerateImpliedEndTagsExceptFor(tagName); if (!CurrentNode.LocalName.Is(tagName)) RaiseErrorOccurred(HtmlParseError.TagDoesNotMatchCurrentNode, tag); ClearStackBackTo(tagName); CloseCurrentNode(); } else { RaiseErrorOccurred(HtmlParseError.ListItemNotInScope, tag); } } else if (tagName.IsOneOf(TagNames.Applet, TagNames.Marquee, TagNames.Object)) { if (IsInScope(tagName)) { GenerateImpliedEndTags(); if (!CurrentNode.LocalName.Is(tagName)) RaiseErrorOccurred(HtmlParseError.TagDoesNotMatchCurrentNode, tag); ClearStackBackTo(tagName); CloseCurrentNode(); _formattingElements.ClearFormatting(); } else { RaiseErrorOccurred(HtmlParseError.ObjectNotInScope, tag); } } else if (tagName.Is(TagNames.Body)) { InBodyEndTagBody(tag); } else if (tagName.Is(TagNames.Html)) { if (InBodyEndTagBody(tag)) AfterBody(tag); } else if (tagName.Is(TagNames.Template)) { InHead(tag); } else { InBodyEndTagAnythingElse(tag); } }