AngleSharp by Florian Rappl

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

.NET API 1,229,312 bytes

 ComplexSelector

sealed class ComplexSelector : ISelector
Represents a complex selector. One or more compound selectors separated by combinators.
using AngleSharp.Css; using AngleSharp.Parser.Css; using System; using System.Collections.Generic; using System.Text; namespace AngleSharp.Dom.Css { internal sealed class ComplexSelector : ISelector { private struct CombinatorSelector { public char Delimiter; public Func<IElement, IEnumerable<IElement>> Transform; public ISelector Selector; } private readonly List<CombinatorSelector> selectors; public Priority Specifity { get { Priority priority = default(Priority); int count = selectors.Count; for (int i = 0; i < count; i++) { priority += selectors[i].Selector.Specifity; } return priority; } } public string Text { get { StringBuilder stringBuilder = Pool.NewStringBuilder(); if (selectors.Count > 0) { int num = selectors.Count - 1; for (int i = 0; i < num; i++) { stringBuilder.Append(selectors[i].Selector.Text).Append(selectors[i].Delimiter); } stringBuilder.Append(selectors[num].Selector.Text); } return stringBuilder.ToPool(); } } public int Length => selectors.Count; public bool IsReady { get; set; } public ComplexSelector() { selectors = new List<CombinatorSelector>(); } public bool Match(IElement element) { int num = selectors.Count - 1; if (selectors[num].Selector.Match(element)) { if (num <= 0) return true; return MatchCascade(num - 1, element); } return false; } public ComplexSelector ConcludeSelector(ISelector selector) { if (!IsReady) { selectors.Add(new CombinatorSelector { Selector = selector, Transform = null, Delimiter = '' }); IsReady = true; } return this; } public ComplexSelector AppendSelector(ISelector selector, CssCombinator combinator) { if (IsReady) return this; selectors.Add(new CombinatorSelector { Selector = combinator.Change(selector), Transform = combinator.Transform, Delimiter = combinator.Delimiter }); return this; } public ComplexSelector ClearSelectors() { IsReady = false; selectors.Clear(); return this; } private bool MatchCascade(int pos, IElement element) { IEnumerable<IElement> enumerable = selectors[pos].Transform(element); foreach (IElement item in enumerable) { if (selectors[pos].Selector.Match(item) && (pos == 0 || MatchCascade(pos - 1, item))) return true; } return false; } } }