Exemplo n.º 1
0
        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);
            }
        }
Exemplo n.º 2
0
        /// <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);
        }
Exemplo n.º 3
0
        /// <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);
        }
Exemplo n.º 4
0
        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);
            }
        }