コード例 #1
0
        IEnumerable <DomElementEvent> CloseUntilMatch(string name, Fragment closingFragment)
        {
            // Find an element to close
            var close = stack.FirstOrDefault(x => x.IsNamed(name));

            if (close != null)
            {
                if (stack.Count > 0 && !stack.Peek().IsNamed(name))
                {
                    stack.Pop();
                    yield return(DomElementEvent.Pop(null));
                }

                stack.Pop();
                yield return(DomElementEvent.Pop(closingFragment));
            }
        }
コード例 #2
0
        IEnumerable <DomElementEvent> _Execute(IEnumerable <Fragment> fragments)
        {
            foreach (var fragment in fragments)
            {
                switch (fragment.FragmentType)
                {
                case FragmentType.Comment:
                case FragmentType.Doctype:
                case FragmentType.Text:
                    yield return(DomElementEvent.Child(fragment));

                    break;

                case FragmentType.Close:
                    if (VoidElements.Contains(fragment.Value.ToLowerInvariant()))
                    {
                        break;
                    }

                    if (stack.Any(x => x.IsNamed(fragment.Value)))
                    {
                        foreach (var close in CloseUntilMatch(fragment.Value, fragment))
                        {
                            yield return(close);
                        }
                    }
                    else
                    {
                        // If there's nothing to close, this is invalid HTML, push through
                        // as a child of the current node, but do not pop the stack.
                        yield return(new DomElementEvent(fragment, DomElementEventType.Child));
                    }

                    break;

                case FragmentType.Open:
                    var nameLower = fragment.Value.ToLowerInvariant();
                    if (ParagraphClosingTags.Contains(nameLower))
                    {
                        foreach (var pClose in CloseUntilMatch("p", null))
                        {
                            yield return(pClose);
                        }
                    }
                    else if (nameLower == "li")
                    {
                        // Find the first UL or LI.
                        var parentLiOrUl = stack.FirstOrDefault(x => x.IsNamed("li") || x.IsNamed("ul"));

                        // If something is found and it's an LI, then we can close it.
                        // (Note: checking for ULs so we don't close an LI from a grand-parent UL)
                        if (parentLiOrUl?.IsNamed("li") == true)
                        {
                            foreach (var liClose in CloseUntilMatch("li", parentLiOrUl.AsCloseFragment()))
                            {
                                yield return(liClose);
                            }
                        }
                    }

                    bool shouldPush = !fragment.IsSelfClosing && !VoidElements.Contains(fragment.Value.ToLowerInvariant());
                    var  eventType  = shouldPush ? DomElementEventType.Push : DomElementEventType.Child;
                    yield return(new DomElementEvent(fragment, eventType));

                    if (shouldPush)
                    {
                        stack.Push(fragment);
                    }

                    break;
                }
            }

            while (stack.Count > 0)
            {
                stack.Pop();
                yield return(DomElementEvent.Pop(null));
            }
        }