コード例 #1
0
 internal NodeFilterResult FilterNode(Node node)
 {
     if (((uint)WhatToShow & 1 << (int)(node.NodeType - 1)) == 0)
         return NodeFilterResult.Skip;
     if (Filter != null)
         return Filter(node);
     return NodeFilterResult.Accept;
 }
コード例 #2
0
        internal NodeIterator(Node root, WhatToShow whatToShow, NodeFilter filter)
        {
            Root = root;

            ReferenceNode = root;
            PointerBeforeReferenceNode = true;

            WhatToShow = whatToShow;
            Filter = filter;
        }
コード例 #3
0
ファイル: Attr.cs プロジェクト: CnSimonChan/AppToolkit.Html
        protected override bool IsEqualNodeOverride(Node node)
        {
            var element = (Attr)node;

            if (NamespaceUri != element.NamespaceUri)
                return false;

            if (LocalName != element.LocalName)
                return false;

            if (Value != element.Value)
                return false;

            return true;
        }
コード例 #4
0
        protected override bool IsEqualNodeOverride(Node node)
        {
            var element = (Element)node;

            if (NamespaceUri != element.NamespaceUri)
                return false;

            if (Prefix != element.Prefix)
                return false;

            if (LocalName != element.LocalName)
                return false;

            if (!AttributeList.SequenceEqual(element.AttributeList))
                return false;

            return true;
        }
コード例 #5
0
ファイル: Node.cs プロジェクト: CnSimonChan/AppToolkit.Html
        internal void ReplaceAll(Node node)
        {
            if (node != null)
                OwnerDocument.AdoptNode(node);

            var removedNodes = new List<Node>(ChildNodes);
            var addedNodes = new List<Node>();
            if (node is DocumentFragment)
                foreach (var child in node.ChildNodes)
                    addedNodes.Add(child);
            else
                addedNodes.Add(node);

            while (HasChildNodes())
                Remove(ChildNodes[0], true);

            if (node != null)
                Insert(node, -1, true);
        }
コード例 #6
0
        private static void SerializeHtmlFragment(Node node, StringBuilder builder)
        {
            if (node is HtmlTemplateElement template)
                node = template.Content;

            foreach (var child in node.ChildNodes)
                SerializeHtmlFragmentCore(child, builder);
        }
コード例 #7
0
        public Node PreviousNode()
        {
            var node = CurrentNode;
            while (node != Root)
            {
                var sibling = node.PreviousSibling;
                while (sibling != null)
                {
                    node = sibling;
                    var result = FilterNode(node);
                    while (result != NodeFilterResult.Reject && node.HasChildNodes())
                    {
                        node = node.LastChild;
                        result = FilterNode(node);
                    }

                    if (result == NodeFilterResult.Accept)
                    {
                        CurrentNode = node;
                        return node;
                    }

                    sibling = node.PreviousSibling;
                }

                if (node == Root || node.ParentNode == null)
                    return null;

                node = node.ParentNode;

                if (FilterNode(node) == NodeFilterResult.Accept)
                {
                    CurrentNode = node;
                    return node;
                }
            }
            return null;
        }
コード例 #8
0
        internal Node TraverseChildren(bool firstChild)
        {
            var node = firstChild ? CurrentNode.FirstChild : CurrentNode.LastChild;
            while (node != null)
            {
                switch (FilterNode(node))
                {
                    case NodeFilterResult.Accept:
                        CurrentNode = node;
                        return node;
                    case NodeFilterResult.Reject:
                        while (node != null)
                        {
                            var sibling = firstChild ? node.NextSibling : node.PreviousSibling;
                            if (sibling != null)
                            {
                                node = sibling;
                                break;
                            }

                            node = node.ParentNode;
                            if (node == null || node == Root || node == CurrentNode)
                                return null;
                        }
                        break;
                    case NodeFilterResult.Skip:
                        break;
                }
            }
            return null;
        }
コード例 #9
0
 internal TreeWalker(Node root, WhatToShow whatToShow, NodeFilter filter)
 {
     Root = root;
     WhatToShow = whatToShow;
     Filter = filter;
 }
コード例 #10
0
ファイル: Node.cs プロジェクト: CnSimonChan/AppToolkit.Html
 public Node ReplaceChild(Node node, Node child) { throw new NotImplementedException(); }
コード例 #11
0
 public abstract Node SetNamedItemNS(Node arg);
コード例 #12
0
        private static void CreateElement(InlineCollection parent, Node node, RichTextBlockStatus status)
        {
            switch (node)
            {
                case Element element:
                    switch (element.TagName.ToLower())
                    {
                        case "a":
                            {
                                // We want to change BaseUri easily, so we use `GetAttribute("href")` instead of `HtmlAnchorElement.Href`
                                var href = element.GetAttribute("href");

                                if (!status.TryCreateUri(href, out var uri))
                                    break;

                                parent.Add(new Run() { Text = " " });

                                var hyperlink = new Hyperlink()
                                {
                                    NavigateUri = uri,
                                    Foreground = status.Foreground
                                };

                                foreach (var child in element.ChildNodes)
                                {
                                    switch (child)
                                    {
                                        case HtmlImageElement childElement:
                                            if (CreateImage(element, status) is Image image)
                                            {
                                                if (hyperlink.Inlines.Count != 0)
                                                {
                                                    hyperlink.SetUri(href);
                                                    status.Hyperlinks.Add(hyperlink);
                                                    parent.Add(hyperlink);
                                                }

                                                var button = new HyperlinkButton()
                                                {
                                                    NavigateUri = uri,
                                                    Content = image,
                                                    RequestedTheme = status.RequestedTheme
                                                };
                                                button.SetUri(href);
                                                status.HyperlinkButtons.Add(button);
                                                parent.Add(new InlineUIContainer() { Child = button });

                                                hyperlink = new Hyperlink()
                                                {
                                                    NavigateUri = uri,
                                                    Foreground = status.Foreground
                                                };
                                            }
                                            break;
                                        default:
                                            CreateElement(hyperlink.Inlines, child, status);
                                            break;
                                    }
                                    break;
                                }

                                if (hyperlink.Inlines.Count != 0)
                                {
                                    hyperlink.SetUri(href);
                                    status.Hyperlinks.Add(hyperlink);
                                    parent.Add(hyperlink);
                                }

                                parent.Add(new Run() { Text = " " });
                            }
                            break;
                        case "img":
                            {
                                if (CreateImage(element, status) is Image image)
                                    parent.Add(new InlineUIContainer() { Child = image });
                            }
                            break;
                        case "strong":
                        case "b":
                            {
                                var span = new Span() { FontWeight = FontWeights.Bold };
                                CreateChildren(span.Inlines, element, status);
                                parent.Add(span);
                            }
                            break;
                        case "div":
                        case "font":
                        case "p":
                        case "span":
                            {
                                var span = new Span();
                                foreach (var s in ParseStyle(element.GetAttribute("style")))
                                    switch (s.Key)
                                    {
                                        case "font-size":
                                            {
                                                var value = s.Value;

                                                double fontSize;
                                                if (value.EndsWith("px"))
                                                    fontSize = double.Parse(value.Remove(value.Length - 2));
                                                else if (value.EndsWith("%"))
                                                    fontSize = 14 * double.Parse(value.Remove(value.Length - 1)) / 100;
                                                else
                                                    fontSize = 14 * double.Parse(value);

                                                span.FontSize = fontSize;
                                            }
                                            break;
                                        case "font-weight":
                                            switch (s.Value)
                                            {
                                                case "bold":
                                                    span.FontWeight = FontWeights.Bold;
                                                    break;
                                            }
                                            break;
                                    }

                                CreateChildren(span.Inlines, element, status);
                                parent.Add(span);
                            }
                            break;
                        case "br":
                            if (element.NextSibling is Text nextText &&
                                nextText.Data.StartsWith("\n"))
                                break;

                            parent.Add(new LineBreak());
                            break;
                        case "hr":
                            parent.Add(new LineBreak());

                            var line = new Border()
                            {
                                BorderThickness = new Thickness(0, 1, 0, 0),
                                BorderBrush = status.Foreground,
                                Margin = new Thickness(8, 0, 8, 0),
                                Height = 1,
                            };

                            if (status.ActualWidth > 16)
                                line.Width = status.ActualWidth - 16;

                            status.Lines.Add(line);
                            parent.Add(new InlineUIContainer() { Child = line });

                            parent.Add(new LineBreak());
                            break;
                        case "iframe": // Ignore
                        case "script":
                        case "noscript":
                            break;
#if DEBUG
                        default:
                            Debug.WriteLine($"Ignore unknown tag {element.TagName}");
                            break;
#endif

                    }
                    break;
                case Text text:
                    parent.Add(new Run() { Text = text.Data });
                    break;
            }
        }
コード例 #13
0
ファイル: Text.cs プロジェクト: CnSimonChan/AppToolkit.Html
 protected override bool IsEqualNodeOverride(Node other) => Data == ((Text)other).Data;
コード例 #14
0
 public ParentNodeImplementation(Node owner)
 {
     Owner = owner;
     Children = new LazyHtmlCollection(owner.ChildNodes);
 }
コード例 #15
0
ファイル: Node.cs プロジェクト: CnSimonChan/AppToolkit.Html
        public Node InsertBefore(Node node, Node child)
        {
            switch (NodeType)
            {
                case NodeType.Document:
                case NodeType.DocumentFragment:
                case NodeType.Element:
                    break;
                default:
                    throw new DomException(DomExceptionCode.HierarchyRequestError);
            }

            var parent = this;
            do
            {
                if (node == parent)
                    throw new DomException(DomExceptionCode.HierarchyRequestError);
            }
            while ((parent = parent.ParentNode) != null);

            if (child != null && child.ParentNode != this)
                throw new DomException(DomExceptionCode.NotFoundError);

            switch (node.NodeType)
            {
                case NodeType.DocumentFragment:
                    if (NodeType == NodeType.Document)
                    {
                        var fragment = (DocumentFragment)node;

                        if (fragment.ChildElementCount > 1)
                            throw new DomException(DomExceptionCode.HierarchyRequestError);

                        foreach (var item in fragment.ChildNodes)
                            if (item.NodeType == NodeType.Text)
                                throw new DomException(DomExceptionCode.HierarchyRequestError);

                        if (fragment.ChildElementCount == 1)
                        {
                            if (OwnerDocument.ChildElementCount != 0)
                                throw new DomException(DomExceptionCode.HierarchyRequestError);

                            if (child?.NodeType == NodeType.DocumentType)
                                throw new DomException(DomExceptionCode.HierarchyRequestError);

                            if (child != null)
                            {
                                var iterator = OwnerDocument.CreateNodeIterator(child);
                                Node next;
                                while ((next = iterator.NextNode()) != null)
                                    if (next.NodeType == NodeType.DocumentType)
                                        throw new DomException(DomExceptionCode.HierarchyRequestError);
                            }
                        }
                    }
                    break;
                case NodeType.DocumentType:
                    if (NodeType != NodeType.Document)
                        throw new DomException(DomExceptionCode.HierarchyRequestError);

                    var hasElement = false;
                    foreach (var item in ChildNodes)
                    {
                        if (item.NodeType == NodeType.DocumentType)
                            throw new DomException(DomExceptionCode.HierarchyRequestError);

                        if (item.NodeType == NodeType.Element)
                            hasElement = true;

                        if (item == child && hasElement)
                            throw new DomException(DomExceptionCode.HierarchyRequestError);
                    }

                    if (child == null && hasElement)
                        throw new DomException(DomExceptionCode.HierarchyRequestError);
                    break;
                case NodeType.Element:
                    if (NodeType == NodeType.Document)
                    {
                        if (OwnerDocument.ChildElementCount != 0)
                            throw new DomException(DomExceptionCode.HierarchyRequestError);

                        if (child?.NodeType == NodeType.DocumentType)
                            throw new DomException(DomExceptionCode.HierarchyRequestError);

                        if (child != null)
                        {
                            var iterator = OwnerDocument.CreateNodeIterator(child);
                            Node next;
                            while ((next = iterator.NextNode()) != null)
                                if (next.NodeType == NodeType.DocumentType)
                                    throw new DomException(DomExceptionCode.HierarchyRequestError);
                        }
                    }
                    break;
                case NodeType.Text:
                    if (NodeType == NodeType.Document)
                        throw new DomException(DomExceptionCode.HierarchyRequestError);
                    break;
                case NodeType.ProcessingInstruction:
                case NodeType.Comment:
                    break;
                default:
                    throw new DomException(DomExceptionCode.HierarchyRequestError);
            }

            if (child == node)
                child = node.NextSibling;

            OwnerDocument.AdoptNode(node);

            Insert(node, ChildNodes.IndexOf(child));

            return node;
        }
コード例 #16
0
ファイル: Node.cs プロジェクト: CnSimonChan/AppToolkit.Html
 public Node AppendChild(Node node) => InsertBefore(node, null);
コード例 #17
0
ファイル: Node.cs プロジェクト: CnSimonChan/AppToolkit.Html
 protected virtual bool IsEqualNodeOverride(Node node) => true;
コード例 #18
0
ファイル: Node.cs プロジェクト: CnSimonChan/AppToolkit.Html
        public Node RemoveChild(Node child)
        {
            if (child.ParentNode != this)
                throw new DomException(DomExceptionCode.NotFoundError);

            Remove(child);
            return child;
        }
コード例 #19
0
ファイル: Node.cs プロジェクト: CnSimonChan/AppToolkit.Html
        /// <summary>
        /// Returns whether node and other have the same properties. 
        /// </summary>
        /// <param name="node">The other node.</param>
        /// <returns></returns>
        public bool IsEqualNode(Node node)
        {
            if (ReferenceEquals(node, null))
                return false;
            if (ReferenceEquals(this, node))
                return true;

            if (NodeType != node.NodeType)
                return false;

            if (!IsEqualNodeOverride(node))
                return false;

            if (ChildNodes.Length != node.ChildNodes.Length)
                return false;

            if (!ChildNodes.SequenceEqual(node.ChildNodes))
                return false;

            return true;
        }
コード例 #20
0
        public Node ParentNode()
        {
            if (CurrentNode != Root)
            {
                var node = CurrentNode.ParentNode;
                if (node != null && FilterNode(node) == NodeFilterResult.Accept)
                {
                    CurrentNode = node;
                    return node;
                }
            }

            return null;
        }
コード例 #21
0
ファイル: Node.cs プロジェクト: CnSimonChan/AppToolkit.Html
 /// <summary>
 /// Returns a bitmask indicating the position of other relative to node.
 /// </summary>
 /// <param name="other">The other node.</param>
 /// <returns></returns>
 public DocumentPosition CompareDocumentPosition(Node other) { throw new NotImplementedException(); }
コード例 #22
0
        internal Node TraverseSiblings(bool nextSibling)
        {
            var node = CurrentNode;
            if (node == Root)
                return null;

            while (true)
            {
                var sibling = nextSibling ? node.NextSibling : node.PreviousSibling;
                while (sibling != null)
                {
                    node = sibling;

                    var result = FilterNode(node);
                    if (result == NodeFilterResult.Accept)
                    {
                        CurrentNode = node;
                        return node;
                    }

                    sibling = nextSibling ? node.FirstChild : node.LastChild;
                    if (result == NodeFilterResult.Reject || sibling == null)
                        sibling = nextSibling ? node.NextSibling : node.PreviousSibling;
                }

                node = node.ParentNode;
                if (node == null || node == Root)
                    return null;
                if (FilterNode(node) == NodeFilterResult.Accept)
                    return null;
            }
        }
コード例 #23
0
ファイル: Node.cs プロジェクト: CnSimonChan/AppToolkit.Html
        /// <summary>
        /// Returns <c>true</c> if other is an inclusive descendant of <see cref="Node"/>, and <c>fase</c> otherwise. 
        /// </summary>
        /// <param name="other">The other node.</param>
        /// <returns><c>true</c> if other is an inclusive descendant of <see cref="Node"/>, and <c>fase</c> otherwise. </returns>
        public bool Contains(Node other)
        {
            if (other == null)
                return false;

            foreach (var child in ChildNodes)
            {
                if (child.IsEqualNode(other))
                    return true;

                if (child.Contains(other))
                    return true;
            }

            return false;
        }
コード例 #24
0
        public Node NextNode()
        {
            var node = CurrentNode;
            var result = NodeFilterResult.Accept;
            while (true)
            {
                while (result != NodeFilterResult.Reject && node.HasChildNodes())
                {
                    node = node.FirstChild;
                    result = FilterNode(node);
                    if (result == NodeFilterResult.Accept)
                    {
                        CurrentNode = node;
                        return node;
                    }
                }

                return null;
            }
        }
コード例 #25
0
ファイル: Node.cs プロジェクト: CnSimonChan/AppToolkit.Html
        internal void Remove(Node child, bool suppressObservers = false)
        {
            var index = ChildNodes.IndexOf(child);
            var oldPreviousSibling = child.PreviousSibling;

            if (!suppressObservers)
            {

            }

            child.ParentNode = null;
            ChildNodes.RemoveAt(index);
        }
コード例 #26
0
ファイル: Node.cs プロジェクト: CnSimonChan/AppToolkit.Html
        internal void Insert(Node node, int index, bool suppressObservers = false)
        {
            var addedNodes = new List<Node>();

            if (node is DocumentFragment)
            {
                addedNodes.Capacity = node.ChildNodes.Count;

                while (node.HasChildNodes())
                {
                    var item = node.ChildNodes[0];
                    node.Remove(item, true);

                    addedNodes.Add(item);
                    item.ParentNode = this;

                    if (index == -1)
                        ChildNodes.Add(item);
                    else
                        ChildNodes.Insert(index++, item);
                }
            }
            else
            {
                addedNodes.Add(node);
                node.ParentNode = this;

                if (index == -1)
                    ChildNodes.Add(node);
                else
                    ChildNodes.Insert(index++, node);
            }
        }
コード例 #27
0
        private static void SerializeHtmlFragmentCore(Node node, StringBuilder builder)
        {
            switch (node)
            {
                case Element element:
                    string tagName;
                    if (element.NamespaceUri == HtmlElement.HtmlNamespace)
                        tagName = element.LocalName;
                    else
                        tagName = element.QualifiedName;

                    builder.EnsureCapacity(builder.Length + tagName.Length * 2 + 5);
                    builder.Append('<').Append(tagName);
                    foreach (var attr in element.AttributeList)
                        builder.Append($" {attr.Name}=\"{EscapeString(attr.Value, true)}\"");
                    builder.Append('>');
                    SerializeHtmlFragment(element, builder);
                    builder.Append($"</{tagName}>");
                    break;
                case Text text:
                    if (text.ParentNode is Element parent &&
                        parent.TagName == OneOf("style", "script", "xmp", "iframe", "noembed", "noframes"))
                        builder.Append(text.Data);
                    else
                        builder.Append(EscapeString(text.Data, false));
                    break;
                case Comment comment:
                    builder.EnsureCapacity(builder.Capacity + comment.Data.Length + 7);
                    builder.Append("<!--").Append(comment.Data).Append("-->");
                    break;
                case ProcessingInstruction instruction:
                    builder.EnsureCapacity(builder.Capacity + instruction.Target.Length + instruction.Data.Length + 4);
                    builder.Append("<?").Append(instruction.Target).Append(" ").Append(instruction.Data).Append(">");
                    break;
                case DocumentType type:
                    builder.EnsureCapacity(builder.Capacity + type.Name.Length + 11);
                    builder.Append("<!DOCTYPE ").Append(type.Name).Append(">");
                    break;
            }
        }