Ejemplo n.º 1
0
        /// <summary>
        /// See 8.2.5.4.6 The "after head" insertion mode.
        /// </summary>
        /// <param name="token">The passed token.</param>
        void AfterHead(HtmlToken token)
        {
            switch (token.Type)
            {
                case HtmlTokenType.Character:
                {
                    var str = token.TrimStart();
                    AddCharacters(str);

                    if (token.IsEmpty)
                        return;

                    break;
                }
                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.Html))
                    {
                        InBody(token);
                        return;
                    }
                    else if (tagName.Is(TagNames.Body))
                    {
                        AfterHeadStartTagBody(token.AsTag());
                        return;
                    }
                    else if (tagName.Is(TagNames.Frameset))
                    {
                        AddElement(new HtmlFrameSetElement(_document), token.AsTag());
                        _currentMode = HtmlTreeMode.InFrameset;
                        return;
                    }
                    else if (TagNames.AllHeadNoTemplate.Contains(tagName))
                    {
                        RaiseErrorOccurred(HtmlParseError.TagMustBeInHead, token);
                        var index = _openElements.Count;
                        var head = _document.Head as Element;
                        _openElements.Add(head);
                        InHead(token);
                        _openElements.Remove(head);
                        return;
                    }
                    else if (tagName.Is(TagNames.Head))
                    {
                        RaiseErrorOccurred(HtmlParseError.HeadTagMisplaced, token);
                        return;
                    }

                    break;
                }
                case HtmlTokenType.EndTag:
                {
                    if (token.Name.IsOneOf(TagNames.Html, TagNames.Body, TagNames.Br))
                        break;

                    RaiseErrorOccurred(HtmlParseError.TagCannotEndHere, token);
                    return;
                }
            }

            AfterHeadStartTagBody(HtmlTagToken.Open(TagNames.Body));
            _frameset = true;
            Home(token);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// See 8.2.5.4.4 The "in head" insertion mode.
        /// </summary>
        /// <param name="token">The passed token.</param>
        void InHead(HtmlToken token)
        {
            switch (token.Type)
            {
                case HtmlTokenType.Character:
                {
                    var str = token.TrimStart();
                    AddCharacters(str);

                    if (token.IsEmpty)
                        return;

                    break;
                }
                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.Html))
                    {
                        InBody(token);
                        return;
                    }
                    else if (tagName.Is(TagNames.Meta))
                    {
                        var element = new HtmlMetaElement(_document);
                        AddElement(element, token.AsTag(), true);
                        var encoding = element.GetEncoding();
                        CloseCurrentNode();

                        if (encoding != null)
                        {
                            try
                            {
                                _document.Source.CurrentEncoding = encoding;
                            }
                            catch (NotSupportedException)
                            {
                                Restart();
                            }
                        }

                        return;
                    }
                    else if (TagNames.AllHeadBase.Contains(tagName))
                    {
                        AddElement(token.AsTag(), true);
                        CloseCurrentNode();
                        return;
                    }
                    else if (tagName.Is(TagNames.Title))
                    {
                        RCDataAlgorithm(token.AsTag());
                        return;
                    }
                    else if (tagName.IsOneOf(TagNames.Style, TagNames.NoFrames) || (_options.IsScripting && tagName.Is(TagNames.NoScript)))
                    {
                        RawtextAlgorithm(token.AsTag());
                        return;
                    }
                    else if (tagName.Is(TagNames.NoScript))
                    {
                        AddElement(token.AsTag());
                        _currentMode = HtmlTreeMode.InHeadNoScript;
                        return;
                    }
                    else if (tagName.Is(TagNames.Script))
                    {
                        var script = new HtmlScriptElement(_document, parserInserted: true, started: IsFragmentCase);
                        AddElement(script, token.AsTag());
                        _tokenizer.State = HtmlParseMode.Script;
                        _previousMode = _currentMode;
                        _currentMode = HtmlTreeMode.Text;
                        return;
                    }
                    else if (tagName.Is(TagNames.Head))
                    {
                        RaiseErrorOccurred(HtmlParseError.HeadTagMisplaced, token);
                        return;
                    }
                    else if (tagName.Is(TagNames.Template))
                    {
                        AddElement(new HtmlTemplateElement(_document), token.AsTag());
                        _formattingElements.AddScopeMarker();
                        _frameset = false;
                        _currentMode = HtmlTreeMode.InTemplate;
                        _templateModes.Push(HtmlTreeMode.InTemplate);
                        return;
                    }

                    break;
                }
                case HtmlTokenType.EndTag:
                {
                    var tagName = token.Name;

                    if (tagName.Is(TagNames.Head))
                    {
                        CloseCurrentNode();

                        _currentMode = HtmlTreeMode.AfterHead;
                        _waiting = _document.WaitForReady();
                        return;
                    }
                    else if (tagName.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;
                    }
                    else if (!tagName.IsOneOf(TagNames.Html, TagNames.Body, TagNames.Br))
                    {
                        RaiseErrorOccurred(HtmlParseError.TagCannotEndHere, token);
                        return;
                    }

                    break;
                }
            }

            CloseCurrentNode();
            _currentMode = HtmlTreeMode.AfterHead;
            AfterHead(token);
        }
Ejemplo n.º 3
0
        /// <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)
        {
            switch (token.Type)
            {
                case HtmlTokenType.Character:
                {
                    var str = token.TrimStart();
                    AddCharacters(str);

                    if (token.IsEmpty)
                        return;

                    break;
                }
                case HtmlTokenType.Comment:
                {
                    InHead(token);
                    return;
                }
                case HtmlTokenType.StartTag:
                {
                    var tagName = token.Name;

                    if (TagNames.AllNoScript.Contains(tagName))
                        InHead(token);
                    else if (tagName.Is(TagNames.Html))
                        InBody(token);
                    else if (tagName.IsOneOf(TagNames.Head, TagNames.NoScript))
                        RaiseErrorOccurred(HtmlParseError.TagInappropriate, token);
                    else
                        break;

                    return;
                }
                case HtmlTokenType.EndTag:
                {
                    var tagName = token.Name;

                    if (tagName.Is(TagNames.NoScript))
                    {
                        CloseCurrentNode();
                        _currentMode = HtmlTreeMode.InHead;
                        return;
                    }
                    else if (!tagName.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);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// See 8.2.5.4.2 The "before html" insertion mode.
        /// </summary>
        /// <param name="token">The passed token.</param>
        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))
                        break;

                    AddRoot(token.AsTag());
                    _currentMode = HtmlTreeMode.BeforeHead;
                    return;
                }                    
                case HtmlTokenType.EndTag:
                {
                    if (TagNames.AllBeforeHead.Contains(token.Name))
                        break;

                    RaiseErrorOccurred(HtmlParseError.TagCannotEndHere, token);
                    return;
                }
                case HtmlTokenType.Doctype:
                {
                    RaiseErrorOccurred(HtmlParseError.DoctypeTagInappropriate, token);
                    return;
                }
            }

            BeforeHtml(HtmlTagToken.Open(TagNames.Html));
            BeforeHead(token);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// See 8.2.5.4.3 The "before head" insertion mode.
        /// </summary>
        /// <param name="token">The passed token.</param>
        void BeforeHead(HtmlToken token)
        {
            switch (token.Type)
            {
                case HtmlTokenType.Character:
                {
                    token.TrimStart();

                    if (token.IsEmpty)
                        return;

                    break;
                }
                case HtmlTokenType.StartTag:
                {
                    var tagName = token.Name;

                    if (tagName.Is(TagNames.Html))
                    {
                        InBody(token);
                        return;
                    }
                    else if (tagName.Is(TagNames.Head))
                    {
                        AddElement(new HtmlHeadElement(_document), token.AsTag());
                        _currentMode = HtmlTreeMode.InHead;
                        return;
                    }

                    break;
                }
                case HtmlTokenType.EndTag:
                {
                    if (TagNames.AllBeforeHead.Contains(token.Name))
                        break;

                    RaiseErrorOccurred(HtmlParseError.TagCannotEndHere, token);
                    return;
                }
                case HtmlTokenType.Comment:
                {
                    CurrentNode.AddComment(token);
                    return;
                }
                case HtmlTokenType.Doctype:
                {
                    RaiseErrorOccurred(HtmlParseError.DoctypeTagInappropriate, token);
                    return;
                }
            }

            BeforeHead(HtmlTagToken.Open(TagNames.Head));
            InHead(token);
        }
Ejemplo n.º 6
0
        /// <summary>
        /// See 8.2.5.4.23 The "after after frameset" insertion mode.
        /// </summary>
        /// <param name="token">The passed token.</param>
        void AfterAfterFrameset(HtmlToken token)
        {
            switch (token.Type)
            {
                case HtmlTokenType.Comment:
                {
                    _document.AddComment(token);
                    return;
                }
                case HtmlTokenType.Character:
                {
                    var str = token.TrimStart();
                    ReconstructFormatting();
                    AddCharacters(str);

                    if (token.IsEmpty)
                        return;

                    break;
                }
                case HtmlTokenType.Doctype:
                {
                    InBody(token);
                    return;
                }
                case HtmlTokenType.StartTag:
                {
                    var tagName = token.Name;

                    if (tagName.Is(TagNames.Html))
                        InBody(token);
                    else if (tagName.Is(TagNames.NoFrames))
                        InHead(token);
                    else
                        break;

                    return;
                }
                case HtmlTokenType.EndOfFile:
                {
                    End();
                    return;
                }
            }

            RaiseErrorOccurred(HtmlParseError.TokenNotPossible, token);
        }
Ejemplo n.º 7
0
        /// <summary>
        /// See 8.2.5.4.1 The "initial" insertion mode.
        /// </summary>
        /// <param name="token">The passed token.</param>
        void Initial(HtmlToken token)
        {
            switch (token.Type)
            {
                case HtmlTokenType.Doctype:
                {
                    var doctype = (HtmlDoctypeToken)token;

                    if (!doctype.IsValid)
                        RaiseErrorOccurred(HtmlParseError.DoctypeInvalid, token);

                    _document.AddNode(new DocumentType(_document, doctype.Name ?? String.Empty)
                    {
                        SystemIdentifier = doctype.SystemIdentifier,
                        PublicIdentifier = doctype.PublicIdentifier
                    });

                    if (doctype.IsFullQuirks)
                        _document.QuirksMode = QuirksMode.On;
                    else if (doctype.IsLimitedQuirks)
                        _document.QuirksMode = QuirksMode.Limited;

                    _currentMode = HtmlTreeMode.BeforeHtml;
                    return;
                }
                case HtmlTokenType.Character:
                {
                    token.TrimStart();

                    if (token.IsEmpty)
                        return;

                    break;
                }
                case HtmlTokenType.Comment:
                {
                    _document.AddComment(token);
                    return;
                }
            }

            if (_options.IsEmbedded == false)
            {
                RaiseErrorOccurred(HtmlParseError.DoctypeMissing, token);
                _document.QuirksMode = QuirksMode.On;
            }

            _currentMode = HtmlTreeMode.BeforeHtml;
            BeforeHtml(token);
        }
Ejemplo n.º 8
0
        /// <summary>
        /// See 8.2.5.4.22 The "after after body" insertion mode.
        /// </summary>
        /// <param name="token">The passed token.</param>
        void AfterAfterBody(HtmlToken token)
        {
            switch (token.Type)
            {
                case HtmlTokenType.Character:
                {
                    var str = token.TrimStart();
                    ReconstructFormatting();
                    AddCharacters(str);

                    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))
                        break;

                    InBody(token);
                    return;
                }
            }

            RaiseErrorOccurred(HtmlParseError.TokenNotPossible, token);
            _currentMode = HtmlTreeMode.InBody;
            InBody(token);
        }
Ejemplo n.º 9
0
        /// <summary>
        /// See 8.2.5.4.21 The "after frameset" insertion mode.
        /// </summary>
        /// <param name="token">The passed token.</param>
        void AfterFrameset(HtmlToken token)
        {
            switch (token.Type)
            {
                case HtmlTokenType.Character:
                {
                    var str = token.TrimStart();
                    AddCharacters(str);

                    if (token.IsEmpty)
                        return;

                    break;
                }
                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.Html))
                        InBody(token);
                    else if (tagName.Is(TagNames.NoFrames))
                        InHead(token);
                    else
                        break;

                    return;
                }
                case HtmlTokenType.EndTag:
                {
                    if (!token.Name.Is(TagNames.Html))
                        break;

                    _currentMode = HtmlTreeMode.AfterAfterFrameset;
                    return;
                }
                case HtmlTokenType.EndOfFile:
                {
                    End();
                    return;
                }
            }

            RaiseErrorOccurred(HtmlParseError.TokenNotPossible, token);
        }
Ejemplo n.º 10
0
        /// <summary>
        /// See 8.2.5.4.20 The "in frameset" insertion mode.
        /// </summary>
        /// <param name="token">The passed token.</param>
        void InFrameset(HtmlToken token)
        {
            switch (token.Type)
            {
                case HtmlTokenType.Character:
                {
                    var str = token.TrimStart();
                    AddCharacters(str);

                    if (token.IsEmpty)
                        return;

                    break;
                }
                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.Html))
                        InBody(token);
                    else if (tagName.Is(TagNames.Frameset))
                        AddElement(new HtmlFrameSetElement(_document), token.AsTag());
                    else if (tagName.Is(TagNames.Frame))
                    {
                        AddElement(new HtmlFrameElement(_document), token.AsTag(), true);
                        CloseCurrentNode();
                    }
                    else if (tagName.Is(TagNames.NoFrames))
                        InHead(token);
                    else
                        break;

                    return;
                }
                case HtmlTokenType.EndTag:
                {
                    if (!token.Name.Is(TagNames.Frameset))
                        break;

                    if (CurrentNode != _openElements[0])
                    {
                        CloseCurrentNode();

                        if (!IsFragmentCase && !CurrentNode.LocalName.Is(TagNames.Frameset))
                            _currentMode = HtmlTreeMode.AfterFrameset;
                    }
                    else
                        RaiseErrorOccurred(HtmlParseError.CurrentNodeIsRoot, token);

                    return;
                }
                case HtmlTokenType.EndOfFile:
                {
                    if (CurrentNode != _document.DocumentElement)
                        RaiseErrorOccurred(HtmlParseError.CurrentNodeIsNotRoot, token);

                    End();
                    return;
                }
            }

            RaiseErrorOccurred(HtmlParseError.TokenNotPossible, token);
        }
Ejemplo n.º 11
0
        /// <summary>
        /// See 8.2.5.4.19 The "after body" insertion mode.
        /// </summary>
        /// <param name="token">The passed token.</param>
        void AfterBody(HtmlToken token)
        {
            switch (token.Type)
            {
                case HtmlTokenType.Character:
                {
                    var str = token.TrimStart();
                    ReconstructFormatting();
                    AddCharacters(str);

                    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);
        }
Ejemplo n.º 12
0
        /// <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)
        {
            switch (token.Type)
            {
                case HtmlTokenType.Character:
                {
                    var str = token.TrimStart();
                    AddCharacters(str);

                    if (token.IsEmpty)
                        return;

                    break;
                }
                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.Html))
                    {
                        InBody(token);
                    }
                    else if (tagName.Is(TagNames.Col))
                    {
                        AddElement(new HtmlTableColElement(_document), token.AsTag(), true);
                        CloseCurrentNode();
                    }
                    else if (tagName.Is(TagNames.Template))
                    {
                        InHead(token);
                    }
                    else
                    {
                        break;
                    }

                    return;
                }
                case HtmlTokenType.EndTag:
                {
                    var tagName = token.Name;

                    if (tagName.Is(TagNames.Colgroup))
                        InColumnGroupEndTagColgroup(token);
                    else if (tagName.Is(TagNames.Col))
                        RaiseErrorOccurred(HtmlParseError.TagClosedWrong, token);
                    else if (tagName.Is(TagNames.Template))
                        InHead(token);
                    else
                        break;

                    return;
                }
                case HtmlTokenType.EndOfFile:
                {
                    InBody(token);
                    return;
                }
            }

            if (InColumnGroupEndTagColgroup(token))
                InTable(token);
        }