/// <summary> /// See 8.2.5.4.6 The "after head" insertion mode. /// </summary> /// <param name="token">The passed token.</param> void AfterHead(HtmlToken token) { if (token.Type == HtmlTokenType.Character) { var chars = (HtmlCharacterToken)token; var str = chars.TrimStart(); InsertCharacters(str); if (chars.IsEmpty) return; } else if (token.Type == HtmlTokenType.Comment) { AddComment(CurrentNode, token); return; } else if (token.Type == HtmlTokenType.DOCTYPE) { RaiseErrorOccurred(ErrorCode.DoctypeTagInappropriate); return; } else if (token.IsStartTag(HTMLHtmlElement.Tag)) { InBody(token); return; } else if (token.IsStartTag(HTMLBodyElement.Tag)) { AfterHeadStartTagBody((HtmlTagToken)token); return; } else if (token.IsStartTag(HTMLFrameSetElement.Tag)) { var element = new HTMLFrameSetElement(); AddElementToCurrentNode(element, token); insert = HtmlTreeMode.InFrameset; return; } else if (token.IsStartTag(HTMLBaseElement.Tag, HTMLBaseFontElement.Tag, HTMLBgsoundElement.Tag, HTMLLinkElement.Tag, HTMLMetaElement.Tag, HTMLNoElement.NoFramesTag, HTMLScriptElement.Tag, HTMLStyleElement.Tag, HTMLTitleElement.Tag)) { RaiseErrorOccurred(ErrorCode.TagMustBeInHead); var index = open.Count; open.Add(doc.Head); InHead(token); open.RemoveAt(index); return; } else if (token.IsStartTag(HTMLHeadElement.Tag)) { RaiseErrorOccurred(ErrorCode.HeadTagMisplaced); return; } else if (token.IsEndTagInv(HTMLHtmlElement.Tag, HTMLBodyElement.Tag, HTMLBRElement.Tag)) { RaiseErrorOccurred(ErrorCode.TagCannotEndHere); return; } AfterHeadStartTagBody(HtmlToken.OpenTag(HTMLBodyElement.Tag)); frameset = true; Consume(token); }
/// <summary> /// See 8.2.5.4.22 The "after after frameset" insertion mode. /// </summary> /// <param name="token">The passed token.</param> void AfterAfterFrameset(HtmlToken token) { if (token.Type == HtmlTokenType.Comment) { AddComment(doc, token); return; } else if (token.Type == HtmlTokenType.Character) { var chrs = (HtmlCharacterToken)token; var str = chrs.TrimStart(); ReconstructFormatting(); InsertCharacters(str); if (chrs.IsEmpty) return; } else if (token.Type == HtmlTokenType.DOCTYPE || token.IsStartTag(HTMLHtmlElement.Tag)) { InBody(token); return; } else if (token.IsStartTag(HTMLNoElement.NoFramesTag)) { InHead(token); return; } else if (token.Type == HtmlTokenType.EOF) { End(); return; } RaiseErrorOccurred(ErrorCode.TokenNotPossible); }
/// <summary> /// See 8.2.5.4.5 The "in head noscript" insertion mode. /// </summary> /// <param name="token">The passed token.</param> void InHeadNoScript(HtmlToken token) { if (token.Type == HtmlTokenType.DOCTYPE) { RaiseErrorOccurred(ErrorCode.DoctypeTagInappropriate); return; } else if (token.IsStartTag(HTMLHtmlElement.Tag)) { InBody(token); return; } else if (token.IsEndTag(HTMLNoElement.NoScriptTag)) { CloseCurrentNode(); insert = HtmlTreeMode.InHead; return; } else if (token.Type == HtmlTokenType.Character) { var chars = (HtmlCharacterToken)token; var str = chars.TrimStart(); InsertCharacters(str); if (chars.IsEmpty) return; } else if (token.Type == HtmlTokenType.Comment) { InHead(token); return; } else if (token.IsStartTag(HTMLBaseFontElement.Tag, HTMLBgsoundElement.Tag, HTMLLinkElement.Tag, HTMLMetaElement.Tag, HTMLNoElement.NoFramesTag, HTMLStyleElement.Tag)) { InHead(token); return; } else if (token.IsStartTag(HTMLHeadElement.Tag, HTMLNoElement.NoScriptTag)) { RaiseErrorOccurred(ErrorCode.TagInappropriate); return; } else if (token.IsEndTagInv(HTMLBRElement.Tag)) { RaiseErrorOccurred(ErrorCode.TagCannotEndHere); return; } RaiseErrorOccurred(ErrorCode.TokenNotPossible); CloseCurrentNode(); insert = HtmlTreeMode.InHead; InHead(token); }
/// <summary> /// See 8.2.5.4.4 The "in head" insertion mode. /// </summary> /// <param name="token">The passed token.</param> void InHead(HtmlToken token) { if (token.Type == HtmlTokenType.Character) { var chars = (HtmlCharacterToken)token; var str = chars.TrimStart(); InsertCharacters(str); if (chars.IsEmpty) return; } else if (token.Type == HtmlTokenType.Comment) { AddComment(CurrentNode, token); return; } else if (token.Type == HtmlTokenType.DOCTYPE) { RaiseErrorOccurred(ErrorCode.DoctypeTagInappropriate); return; } else if (token.IsStartTag(HTMLHtmlElement.Tag)) { InBody(token); return; } else if (token.IsStartTag(HTMLBaseElement.Tag, HTMLBaseFontElement.Tag, HTMLBgsoundElement.Tag, HTMLLinkElement.Tag)) { var name = ((HtmlTagToken)token).Name; var element = HTMLElement.Factory(name); AddElementToCurrentNode(element, token, true); CloseCurrentNode(); return; } else if (token.IsStartTag(HTMLMetaElement.Tag)) { var element = new HTMLMetaElement(); AddElementToCurrentNode(element, token, true); CloseCurrentNode(); var charset = element.GetAttribute(HtmlEncoding.CHARSET); if (charset != null && HtmlEncoding.IsSupported(charset)) { SetCharset(charset); return; } charset = element.GetAttribute("http-equiv"); if (charset != null && charset.Equals("Content-Type", StringComparison.OrdinalIgnoreCase)) { charset = element.GetAttribute("content") ?? string.Empty; charset = HtmlEncoding.Extract(charset); if (HtmlEncoding.IsSupported(charset)) SetCharset(charset); } return; } else if (token.IsStartTag(HTMLTitleElement.Tag)) { RCDataAlgorithm((HtmlTagToken)token); return; } else if (token.IsStartTag(HTMLNoElement.NoFramesTag, HTMLStyleElement.Tag) || (doc.IsScripting && token.IsStartTag(HTMLNoElement.NoScriptTag))) { RawtextAlgorithm((HtmlTagToken)token); return; } else if (token.IsStartTag(HTMLNoElement.NoScriptTag)) { var element = new HTMLElement(); AddElementToCurrentNode(element, token); insert = HtmlTreeMode.InHeadNoScript; return; } else if (token.IsStartTag(HTMLScriptElement.Tag)) { var element = new HTMLScriptElement(); //element.IsParserInserted = true; //element.IsAlreadyStarted = fragment; AddElementToCurrentNode(element, token); tokenizer.Switch(HtmlParseMode.Script); originalInsert = insert; insert = HtmlTreeMode.Text; return; } else if (token.IsEndTag(HTMLHeadElement.Tag)) { CloseCurrentNode(); insert = HtmlTreeMode.AfterHead; return; } else if (token.IsStartTag(HTMLHeadElement.Tag)) { RaiseErrorOccurred(ErrorCode.HeadTagMisplaced); return; } else if (token.IsEndTagInv(HTMLHtmlElement.Tag, HTMLBodyElement.Tag, HTMLBRElement.Tag)) { RaiseErrorOccurred(ErrorCode.TagCannotEndHere); return; } CloseCurrentNode(); insert = HtmlTreeMode.AfterHead; AfterHead(token); }
/// <summary> /// See 8.2.5.4.12 The "in column group" insertion mode. /// </summary> /// <param name="token">The passed token.</param> void InColumnGroup(HtmlToken token) { if (token.Type == HtmlTokenType.Character) { var chars = (HtmlCharacterToken)token; var str = chars.TrimStart(); InsertCharacters(str); } else if (token.Type == HtmlTokenType.Comment) AddComment(CurrentNode, token); else if (token.Type == HtmlTokenType.DOCTYPE) RaiseErrorOccurred(ErrorCode.DoctypeTagInappropriate); else if (token.IsStartTag(HTMLHtmlElement.Tag)) InBody(token); else if (token.IsStartTag(HTMLTableColElement.ColTag)) { var element = new HTMLTableColElement(); AddElementToCurrentNode(element, token, true); CloseCurrentNode(); } else if (token.IsEndTag(HTMLTableColElement.ColgroupTag)) InColumnGroupEndTagColgroup(); else if (token.IsEndTag(HTMLTableColElement.ColTag)) RaiseErrorOccurred(ErrorCode.TagClosedWrong); else if (token.Type == HtmlTokenType.EOF && CurrentNode == doc.DocumentElement) End(); else if (InColumnGroupEndTagColgroup()) InTable(token); }
/// <summary> /// Consumes a token and processes it. /// </summary> /// <param name="token">The token to consume.</param> void Consume(HtmlToken token) { var node = CurrentNode; if (token.Type == HtmlTokenType.Characters) { var chars = ((HtmlCharactersToken)token).Data; if (chars.Length > 0) { var t = new HtmlCharacterToken(); for (int i = 0; i < chars.Length; i++) { t.Data = chars[i]; Consume(t); } } } else if ((node == null) || node.IsInHtml || (node.IsHtmlTIP && (token.Type == HtmlTokenType.StartTag || token.Type == HtmlTokenType.Character)) || (node.IsInMathML && node.NodeName == Specification.XML_ANNOTATION && token.IsStartTag(SVGElement.RootTag)) || (token.Type == HtmlTokenType.EOF) || (node.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); }