AngleSharp by AngleSharp

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

.NET API 1,214,976 bytes

 Element

Represents an element node.
using AngleSharp.Dom.Collections; using AngleSharp.Dom.Css; using AngleSharp.Dom.Events; using AngleSharp.Extensions; using AngleSharp.Html; using AngleSharp.Parser.Css; using AngleSharp.Services.Styling; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; namespace AngleSharp.Dom { internal class Element : Node, IElement, INode, IEventTarget, IMarkupFormattable, IParentNode, IChildNode, INonDocumentTypeChildNode, IElementCssInlineStyle { private static readonly ConditionalWeakTable<Element, IShadowRoot> ShadowRoots; private static readonly Dictionary<Type, AttrChangedCallback> RegisteredCallbacks; private readonly NamedNodeMap _attributes; private readonly string _namespace; private readonly string _prefix; private readonly string _localName; private HtmlCollection<IElement> _elements; private ICssStyleDeclaration _style; private TokenList _classList; internal NamedNodeMap Attributes => _attributes; public ICssStyleDeclaration Style => _style ?? (_style = CreateStyle()); public IElement AssignedSlot { get { IElement parentElement = base.ParentElement; if (parentElement.IsShadow()) return parentElement.ShadowRoot.GetAssignedSlot(Slot); return null; } } public string Slot { get { return this.GetOwnAttribute(AttributeNames.Slot); } set { this.SetOwnAttribute(AttributeNames.Slot, value, false); } } public IShadowRoot ShadowRoot { get { IShadowRoot value = null; ShadowRoots.TryGetValue(this, out value); return value; } } public string Prefix => _prefix; public string LocalName => _localName; public string NamespaceUri => _namespace; public override string TextContent { get { StringBuilder stringBuilder = Pool.NewStringBuilder(); foreach (IText item in this.GetDescendants().OfType<IText>()) { stringBuilder.Append(item.Data); } return stringBuilder.ToPool(); } set { TextNode node = (!string.IsNullOrEmpty(value)) ? new TextNode(base.Owner, value) : null; ReplaceAll(node, false); } } public ITokenList ClassList { get { if (_classList == null) { _classList = new TokenList(this.GetOwnAttribute(AttributeNames.Class)); _classList.Changed += delegate(string value) { UpdateAttribute(AttributeNames.Class, value); }; } return _classList; } } public string ClassName { get { return this.GetOwnAttribute(AttributeNames.Class); } set { this.SetOwnAttribute(AttributeNames.Class, value, false); } } public string Id { get { return this.GetOwnAttribute(AttributeNames.Id); } set { this.SetOwnAttribute(AttributeNames.Id, value, false); } } public string TagName => base.NodeName; public IElement PreviousElementSibling { get { Node parent = base.Parent; if (parent != null) { bool flag = false; for (int num = parent.ChildNodes.Length - 1; num >= 0; num--) { if (parent.ChildNodes[num] == this) flag = true; else if (flag && parent.ChildNodes[num] is IElement) { return (IElement)parent.ChildNodes[num]; } } } return null; } } public IElement NextElementSibling { get { Node parent = base.Parent; if (parent != null) { int length = parent.ChildNodes.Length; bool flag = false; for (int i = 0; i < length; i++) { if (parent.ChildNodes[i] == this) flag = true; else if (flag && parent.ChildNodes[i] is IElement) { return (IElement)parent.ChildNodes[i]; } } } return null; } } public int ChildElementCount { get { NodeList childNodes = base.ChildNodes; int length = childNodes.Length; int num = 0; for (int i = 0; i < length; i++) { if (childNodes[i].NodeType == NodeType.Element) num++; } return num; } } public IHtmlCollection<IElement> Children => _elements ?? (_elements = new HtmlCollection<IElement>(this, false, null)); public IElement FirstElementChild { get { NodeList childNodes = base.ChildNodes; int length = childNodes.Length; for (int i = 0; i < length; i++) { IElement element = childNodes[i] as IElement; if (element != null) return element; } return null; } } public IElement LastElementChild { get { NodeList childNodes = base.ChildNodes; for (int num = childNodes.Length - 1; num >= 0; num--) { IElement element = childNodes[num] as IElement; if (element != null) return element; } return null; } } public string InnerHtml { get { return base.ChildNodes.ToHtml(); } set { ReplaceAll(new DocumentFragment(this, value), false); } } public string OuterHtml { get { return this.ToHtml(); } set { Node parent = base.Parent; if (parent == null) throw new DomException(DomError.NotSupported); Document owner = base.Owner; if (owner != null && owner.DocumentElement == this) throw new DomException(DomError.NoModificationAllowed); parent.InsertChild(parent.IndexOf(this), new DocumentFragment(this, value)); parent.RemoveChild(this); } } INamedNodeMap IElement.Attributes { get { return _attributes; } } public bool IsFocused { get { Document owner = base.Owner; if (owner == null) return false; return owner.FocusElement == this; } protected set { Document owner = base.Owner; if (owner != null) { if (value) { owner.SetFocus(this); this.Fire(delegate(FocusEvent m) { m.Init(EventNames.Focus, false, false); }, null); } else { owner.SetFocus(null); this.Fire(delegate(FocusEvent m) { m.Init(EventNames.Blur, false, false); }, null); } } } } static Element() { ShadowRoots = new ConditionalWeakTable<Element, IShadowRoot>(); RegisteredCallbacks = new Dictionary<Type, AttrChangedCallback>(); RegisterCallback(AttributeNames.Class, delegate(Element element, string value) { element._classList?.Update(value); }); } public Element(Document owner, string localName, string prefix, string namespaceUri, NodeFlags flags = NodeFlags.None) : this(owner, (prefix != null) ? (prefix + ":" + localName) : localName, localName, prefix, namespaceUri, flags) { } public Element(Document owner, string name, string localName, string prefix, string namespaceUri, NodeFlags flags = NodeFlags.None) : base(owner, name, NodeType.Element, flags) { _localName = localName; _prefix = prefix; _namespace = namespaceUri; _attributes = new NamedNodeMap(this); } public IShadowRoot AttachShadow(ShadowRootMode mode = ShadowRootMode.Open) { if (TagNames.AllNoShadowRoot.Contains(_localName)) throw new DomException(DomError.NotSupported); if (ShadowRoot != null) throw new DomException(DomError.InvalidState); ShadowRoot shadowRoot = new ShadowRoot(this, mode); ShadowRoots.Add(this, shadowRoot); return shadowRoot; } public IElement QuerySelector(string selectors) { return base.ChildNodes.QuerySelector(selectors); } public IHtmlCollection<IElement> QuerySelectorAll(string selectors) { return base.ChildNodes.QuerySelectorAll(selectors); } public IHtmlCollection<IElement> GetElementsByClassName(string classNames) { return base.ChildNodes.GetElementsByClassName(classNames); } public IHtmlCollection<IElement> GetElementsByTagName(string tagName) { return base.ChildNodes.GetElementsByTagName(tagName); } public IHtmlCollection<IElement> GetElementsByTagNameNS(string namespaceURI, string tagName) { return base.ChildNodes.GetElementsByTagName(namespaceURI, tagName); } public bool Matches(string selectors) { return CssParser.Default.ParseSelector(selectors).Match(this); } public override INode Clone(bool deep = true) { Element element = new Element(base.Owner, LocalName, _prefix, _namespace, base.Flags); CloneElement(element, deep); return element; } public IPseudoElement Pseudo(string pseudoElement) { return PseudoElement.Create(this, pseudoElement); } public bool HasAttribute(string name) { if (_namespace.Is(NamespaceNames.HtmlUri)) name = name.ToLowerInvariant(); return _attributes.GetNamedItem(name) != null; } public bool HasAttribute(string namespaceUri, string localName) { if (string.IsNullOrEmpty(namespaceUri)) namespaceUri = null; return _attributes.GetNamedItem(namespaceUri, localName) != null; } public string GetAttribute(string name) { if (_namespace.Is(NamespaceNames.HtmlUri)) name = name.ToLower(); return _attributes.GetNamedItem(name)?.Value; } public string GetAttribute(string namespaceUri, string localName) { if (string.IsNullOrEmpty(namespaceUri)) namespaceUri = null; return _attributes.GetNamedItem(namespaceUri, localName)?.Value; } public void SetAttribute(string name, string value) { if (value != null) { if (!name.IsXmlName()) throw new DomException(DomError.InvalidCharacter); if (_namespace.Is(NamespaceNames.HtmlUri)) name = name.ToLowerInvariant(); this.SetOwnAttribute(name, value, false); } else RemoveAttribute(name); } public void SetAttribute(string namespaceUri, string name, string value) { if (value != null) { string prefix = null; string localName = null; Node.GetPrefixAndLocalName(name, ref namespaceUri, out prefix, out localName); _attributes.SetNamedItem(new Attr(prefix, localName, value, namespaceUri)); } else RemoveAttribute(namespaceUri, name); } public void RemoveAttribute(string name) { if (_namespace.Is(NamespaceNames.HtmlUri)) name = name.ToLower(); _attributes.RemoveNamedItemOrDefault(name); } public void RemoveAttribute(string namespaceUri, string localName) { if (string.IsNullOrEmpty(namespaceUri)) namespaceUri = null; _attributes.RemoveNamedItemOrDefault(namespaceUri, localName); } public void Prepend(params INode[] nodes) { this.PrependNodes(nodes); } public void Append(params INode[] nodes) { this.AppendNodes(nodes); } public override bool Equals(INode otherNode) { IElement element = otherNode as IElement; if (element != null) { if (NamespaceUri.Is(element.NamespaceUri) && _attributes.AreEqual(element.Attributes)) return base.Equals(otherNode); return false; } return false; } public void Before(params INode[] nodes) { this.InsertBefore(nodes); } public void After(params INode[] nodes) { this.InsertAfter(nodes); } public void Replace(params INode[] nodes) { this.ReplaceWith(nodes); } public void Remove() { this.RemoveFromParent(); } public void Insert(AdjacentPosition position, string html) { DocumentFragment documentFragment = new DocumentFragment((position == AdjacentPosition.BeforeBegin || position == AdjacentPosition.AfterEnd) ? this : (base.Parent as Element), html); switch (position) { case AdjacentPosition.BeforeBegin: base.Parent.InsertBefore(documentFragment, this); break; case AdjacentPosition.AfterEnd: base.Parent.InsertChild(base.Parent.IndexOf(this) + 1, documentFragment); break; case AdjacentPosition.AfterBegin: InsertChild(0, documentFragment); break; case AdjacentPosition.BeforeEnd: AppendChild(documentFragment); break; } } public override void ToHtml(TextWriter writer, IMarkupFormatter formatter) { bool flag = (base.Flags & NodeFlags.SelfClosing) == NodeFlags.SelfClosing; writer.Write(formatter.OpenTag(this, flag)); if (!flag) { if ((base.Flags & NodeFlags.LineTolerance) == NodeFlags.LineTolerance && base.FirstChild is IText && ((IText)base.FirstChild).Data.Has('\n', 0)) writer.Write('\n'); foreach (INode childNode in base.ChildNodes) { childNode.ToHtml(writer, formatter); } } writer.Write(formatter.CloseTag(this, flag)); } internal virtual void SetupElement() { } internal void AttributeChanged(string localName, string namespaceUri, string oldValue, string newValue) { AttrChangedCallback orCreateCallback = GetOrCreateCallback(GetType()); if (namespaceUri == null) orCreateCallback?.Invoke(this, localName, newValue); base.Owner.QueueMutation(MutationRecord.Attributes(this, localName, namespaceUri, oldValue)); } protected ICssStyleDeclaration CreateStyle() { if ((base.Flags & (NodeFlags.HtmlMember | NodeFlags.SvgMember)) != 0) { Document owner = base.Owner; IConfiguration options = owner.Options; IBrowsingContext context = owner.Context; ICssStyleEngine cssStyleEngine = options.GetCssStyleEngine(); if (cssStyleEngine != null) { string ownAttribute = this.GetOwnAttribute(AttributeNames.Style); StyleOptions options2 = new StyleOptions(context) { Element = this }; ICssStyleDeclaration cssStyleDeclaration = cssStyleEngine.ParseDeclaration(ownAttribute, options2); IBindable bindable = cssStyleDeclaration as IBindable; if (bindable != null) bindable.Changed += delegate(string value) { UpdateAttribute(AttributeNames.Style, value); }; return cssStyleDeclaration; } } return null; } protected static void RegisterCallback<TElement>(string name, Action<TElement, string> callback) where TElement : Element { Type typeFromHandle = typeof(TElement); AttrChangedCallback orCreateCallback = GetOrCreateCallback(typeFromHandle); AttrChangedCallback attrChangedCallback = delegate(IElement element, string localName, string newValue) { if (localName.Is(name)) callback((TElement)element, newValue); }; if (orCreateCallback != null) attrChangedCallback = (AttrChangedCallback)Delegate.Combine(orCreateCallback, attrChangedCallback); RegisteredCallbacks[typeFromHandle] = attrChangedCallback; } private static AttrChangedCallback GetOrCreateCallback(Type type) { AttrChangedCallback value = null; if (!RegisteredCallbacks.TryGetValue(type, out value) && (object)type != typeof(Element)) { AttrChangedCallback orCreateCallback = GetOrCreateCallback(type.GetTypeInfo().get_BaseType()); if (orCreateCallback != null) RegisteredCallbacks[type] = orCreateCallback; } return value; } protected void UpdateStyle(string value) { IBindable obj = _style as IBindable; if (string.IsNullOrEmpty(value)) _attributes.RemoveNamedItemOrDefault(AttributeNames.Style, true); obj?.Update(value); } protected void UpdateAttribute(string name, string value) { this.SetOwnAttribute(name, value, true); } protected sealed override string LocateNamespace(string prefix) { return this.LocateNamespaceFor(prefix); } protected sealed override string LocatePrefix(string namespaceUri) { return this.LocatePrefixFor(namespaceUri); } protected void CloneElement(Element element, bool deep) { CloneNode(element, deep); foreach (IAttr attribute in _attributes) { Attr attr = new Attr(attribute.Prefix, attribute.LocalName, attribute.Value, attribute.NamespaceUri); element._attributes.FastAddItem(attr); } element.SetupElement(); } } }