AngleSharp by AngleSharp

<PackageReference Include="AngleSharp" Version="0.9.9.1" />

.NET API 1,224,704 bytes

 NodeExtensions

static class NodeExtensions
Useful methods for node objects.
using AngleSharp.Dom; using AngleSharp.Dom.Collections; using AngleSharp.Dom.Html; using System.Collections.Generic; using System.Linq; namespace AngleSharp.Extensions { internal static class NodeExtensions { public static INode GetRoot(this INode node) { if (node.Parent == null) return node; return node.Parent.GetRoot(); } public static NodeList CreateChildren(this INode node) { if (!node.IsEndPoint()) return new NodeList(); return NodeList.Empty; } public static bool IsEndPoint(this INode node) { NodeType nodeType = node.NodeType; if (nodeType != NodeType.Document && nodeType != NodeType.DocumentFragment) return nodeType != NodeType.Element; return false; } public static bool IsInsertable(this INode node) { NodeType nodeType = node.NodeType; if (nodeType != NodeType.Element && nodeType != NodeType.Comment && nodeType != NodeType.Text && nodeType != NodeType.ProcessingInstruction && nodeType != NodeType.DocumentFragment) return nodeType == NodeType.DocumentType; return true; } public static Url HyperReference(this INode node, string url) { if (url == null) return null; return new Url(node.BaseUrl, url); } public static bool IsDescendantOf(this INode node, INode parent) { if (node.Parent == null) return false; if (node.Parent == parent) return true; return node.Parent.IsDescendantOf(parent); } public static IEnumerable<INode> GetDescendants(this INode parent) { return parent.GetDescendantsAndSelf().Skip(1); } public static IEnumerable<INode> GetDescendantsAndSelf(this INode parent) { Stack<INode> stack = new Stack<INode>(); stack.Push(parent); while (stack.Count > 0) { INode next = stack.Pop(); yield return next; int num = next.ChildNodes.Length; while (num > 0) { stack.Push(next.ChildNodes[--num]); } } } public static bool IsInclusiveDescendantOf(this INode node, INode parent) { if (node != parent) return node.IsDescendantOf(parent); return true; } public static bool IsAncestorOf(this INode parent, INode node) { return node.IsDescendantOf(parent); } public static IEnumerable<INode> GetAncestors(this INode node) { while (true) { INode parent; node = (parent = node.Parent); if (parent == null) break; yield return node; } } public static IEnumerable<INode> GetInclusiveAncestors(this INode node) { INode parent; do { yield return node; node = (parent = node.Parent); } while (parent != null); } public static bool IsInclusiveAncestorOf(this INode parent, INode node) { if (node != parent) return node.IsDescendantOf(parent); return true; } public static T GetAncestor<T>(this INode node) where T : INode { while ((node = node.Parent) != null) { if (node is T) return (T)node; } return default(T); } public static bool HasDataListAncestor(this INode child) { return child.Ancestors<IHtmlDataListElement>().Any(); } public static bool IsSiblingOf(this INode node, INode element) { return node?.Parent == element.Parent; } public static int Index(this INode node) { return node.Parent.IndexOf(node); } public static int IndexOf(this INode parent, INode node) { int num = 0; if (parent != null) { foreach (INode childNode in parent.ChildNodes) { if (childNode == node) return num; num++; } } return -1; } public static bool IsPreceding(this INode before, INode after) { Queue<INode> queue = new Queue<INode>(before.GetInclusiveAncestors()); Queue<INode> queue2 = new Queue<INode>(after.GetInclusiveAncestors()); int num = queue2.Count - queue.Count; if (num != 0) { while (queue.Count > queue2.Count) { queue.Dequeue(); } while (queue2.Count > queue.Count) { queue2.Dequeue(); } if (IsCurrentlySame(queue2, queue)) return num > 0; } while (queue.Count > 0) { before = queue.Dequeue(); after = queue2.Dequeue(); if (IsCurrentlySame(queue2, queue)) return before.Index() < after.Index(); } return false; } public static bool IsFollowing(this INode after, INode before) { return before.IsPreceding(after); } public static INode GetAssociatedHost(this INode node) { if (node is IDocumentFragment) { IDocument owner = node.Owner; if (owner == null) return null; return owner.All.OfType<IHtmlTemplateElement>().FirstOrDefault((IHtmlTemplateElement m) => m.Content == node); } return null; } public static bool IsHostIncludingInclusiveAncestor(this INode parent, INode node) { if (!parent.IsInclusiveAncestorOf(node)) { INode associatedHost = node.GetRoot().GetAssociatedHost(); if (associatedHost != null) return parent.IsInclusiveAncestorOf(associatedHost); return false; } return true; } public static void EnsurePreInsertionValidity(this INode parent, INode node, INode child) { if (parent.IsEndPoint() || node.IsHostIncludingInclusiveAncestor(parent)) throw new DomException(DomError.HierarchyRequest); if (child != null && child.Parent != parent) throw new DomException(DomError.NotFound); if (!(node is IElement) && !(node is ICharacterData) && !(node is IDocumentType) && !(node is IDocumentFragment)) throw new DomException(DomError.HierarchyRequest); IDocument document = parent as IDocument; if (document != null) { bool flag = false; switch (node.NodeType) { case NodeType.Element: flag = (document.DocumentElement != null || child is IDocumentType || child.IsFollowedByDoctype()); break; case NodeType.DocumentFragment: { int elementCount = node.GetElementCount(); flag = (elementCount > 1 || node.HasTextNodes() || (elementCount == 1 && document.DocumentElement != null) || child is IDocumentType || child.IsFollowedByDoctype()); break; } case NodeType.DocumentType: flag = (document.Doctype != null || (child != null && child.IsPrecededByElement()) || (child == null && document.DocumentElement != null)); break; case NodeType.Text: flag = true; break; } if (flag) throw new DomException(DomError.HierarchyRequest); } else if (node is IDocumentType) { throw new DomException(DomError.HierarchyRequest); } } public static INode PreInsert(this INode parent, INode node, INode child) { Node obj = parent as Node; Node node2 = node as Node; if (obj == null) throw new DomException(DomError.NotSupported); parent.EnsurePreInsertionValidity(node, child); Node node3 = child as Node; if (node3 == node) node3 = node2.NextSibling; (parent.Owner ?? (parent as IDocument)).AdoptNode(node); obj.InsertBefore(node2, node3, false); return node; } public static INode PreRemove(this INode parent, INode child) { Node obj = parent as Node; if (obj == null) throw new DomException(DomError.NotSupported); if (child == null || child.Parent != parent) throw new DomException(DomError.NotFound); obj.RemoveChild(child as Node, false); return child; } public static bool HasTextNodes(this INode node) { return node.ChildNodes.OfType<IText>().Any(); } public static bool IsFollowedByDoctype(this INode child) { if (child != null) { bool flag = true; foreach (INode childNode in child.Parent.ChildNodes) { if (flag) flag = (childNode != child); else if (childNode.NodeType == NodeType.DocumentType) { return true; } } } return false; } public static bool IsPrecededByElement(this INode child) { foreach (INode childNode in child.Parent.ChildNodes) { if (childNode == child) break; if (childNode.NodeType == NodeType.Element) return true; } return false; } public static int GetElementCount(this INode parent) { int num = 0; foreach (INode childNode in parent.ChildNodes) { if (childNode.NodeType == NodeType.Element) num++; } return num; } public static TNode FindChild<TNode>(this INode parent) where TNode : class, INode { if (parent != null) { for (int i = 0; i < parent.ChildNodes.Length; i++) { TNode val = parent.ChildNodes[i] as TNode; if (val != null) return val; } } return null; } public static TNode FindDescendant<TNode>(this INode parent) where TNode : class, INode { if (parent != null) { for (int i = 0; i < parent.ChildNodes.Length; i++) { INode node = parent.ChildNodes[i]; TNode val = (node as TNode) ?? node.FindDescendant<TNode>(); if (val != null) return val; } } return null; } public static IElement GetAssignedSlot(this IShadowRoot root, string name) { return root.GetDescendants().OfType<IHtmlSlotElement>().FirstOrDefault((IHtmlSlotElement m) => m.Name.Is(name)); } private static bool IsCurrentlySame(Queue<INode> after, Queue<INode> before) { if (after.Count > 0 && before.Count > 0) return after.Peek() == before.Peek(); return false; } } }