AngleSharp by Florian Rappl

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

 CssSelectorConstructor

sealed class CssSelectorConstructor
Class for construction for CSS selectors as specified in http://www.w3.org/html/wg/drafts/html/master/selectors.html.
using AngleSharp.DOM; using AngleSharp.DOM.Css; using AngleSharp.DOM.Html; using System; using System.Diagnostics; namespace AngleSharp.Parser.Css { [DebuggerStepThrough] internal sealed class CssSelectorConstructor { private enum State { Data, Attribute, AttributeOperator, AttributeValue, AttributeEnd, Class, PseudoClass, PseudoClassFunction, PseudoClassFunctionEnd, PseudoElement } private abstract class NthChildSelector : SimpleSelector { public int step; public int offset; public override int Specifity => 10; } private sealed class NthFirstChildSelector : NthChildSelector { public override bool Match(Element element) { Node parentNode = element.ParentNode; if (parentNode == null) return false; int num = 1; for (int i = 0; i < parentNode.ChildNodes.Length; i++) { if (parentNode.ChildNodes[i] == element) { if (step != 0) return (num - offset) % step == 0; return num == offset; } if (parentNode.ChildNodes[i] is Element) num++; } return true; } public override string ToCss() { return string.Format(":{0}({1}n+{2})", new object[3] { "nth-child", step, offset }); } } private sealed class NthLastChildSelector : NthChildSelector { public override bool Match(Element element) { Element parentElement = element.ParentElement; if (parentElement == null) return false; int num = 1; for (int num2 = parentElement.ChildNodes.Length - 1; num2 >= 0; num2--) { if (parentElement.ChildNodes[num2] == element) { if (step != 0) return (num - offset) % step == 0; return num == offset; } if (parentElement.ChildNodes[num2] is Element) num++; } return true; } public override string ToCss() { return string.Format(":{0}({1}n+{2})", new object[3] { "nth-last-child", step, offset }); } } private sealed class FirstChildSelector : SimpleSelector { private static FirstChildSelector instance; public static FirstChildSelector Instance => instance ?? (instance = new FirstChildSelector()); public override int Specifity => 10; private FirstChildSelector() { } public override bool Match(Element element) { Node parentNode = element.ParentNode; if (parentNode == null) return false; for (int i = 0; i <= parentNode.ChildNodes.Length; i++) { if (parentNode.ChildNodes[i] == element) return true; if (parentNode.ChildNodes[i] is Element) return false; } return false; } public override string ToCss() { return ":first-child"; } } private sealed class LastChildSelector : SimpleSelector { private static LastChildSelector instance; public static LastChildSelector Instance => instance ?? (instance = new LastChildSelector()); public override int Specifity => 10; private LastChildSelector() { } public override bool Match(Element element) { Element parentElement = element.ParentElement; if (parentElement == null) return false; for (int num = parentElement.ChildNodes.Length - 1; num >= 0; num--) { if (parentElement.ChildNodes[num] == element) return true; if (parentElement.ChildNodes[num] is Element) return false; } return false; } public override string ToCss() { return ":last-child"; } } private const string pseudoclass_root = "root"; private const string pseudoclass_firstoftype = "first-of-type"; private const string pseudoclass_lastoftype = "last-of-type"; private const string pseudoclass_onlychild = "only-child"; private const string pseudoclass_firstchild = "first-child"; private const string pseudoclass_lastchild = "last-child"; private const string pseudoclass_empty = "empty"; private const string pseudoclass_link = "link"; private const string pseudoclass_visited = "visited"; private const string pseudoclass_active = "active"; private const string pseudoclass_hover = "hover"; private const string pseudoclass_focus = "focus"; private const string pseudoclass_target = "target"; private const string pseudoclass_enabled = "enabled"; private const string pseudoclass_disabled = "disabled"; private const string pseudoclass_checked = "checked"; private const string pseudoclass_unchecked = "unchecked"; private const string pseudoclass_indeterminate = "indeterminate"; private const string pseudoclass_default = "default"; private const string pseudoclass_valid = "valid"; private const string pseudoclass_invalid = "invalid"; private const string pseudoclass_required = "required"; private const string pseudoclass_inrange = "in-range"; private const string pseudoclass_outofrange = "out-of-range"; private const string pseudoclass_optional = "optional"; private const string pseudoclass_readonly = "read-only"; private const string pseudoclass_readwrite = "read-write"; private const string pseudoclassfunction_dir = "dir"; private const string pseudoclassfunction_nthchild = "nth-child"; private const string pseudoclassfunction_nthlastchild = "nth-last-child"; private const string pseudoclassfunction_not = "not"; private const string pseudoclassfunction_lang = "lang"; private const string pseudoclassfunction_contains = "contains"; private const string pseudoelement_before = "before"; private const string pseudoelement_after = "after"; private const string pseudoelement_selection = "selection"; private const string pseudoelement_firstline = "first-line"; private const string pseudoelement_firstletter = "first-letter"; private static readonly string nth_child_odd = "odd"; private static readonly string nth_child_even = "even"; private static readonly string nth_child_n = "n"; private State state; private Selector temp; private ListSelector group; private ComplexSelector complex; private bool hasCombinator; private bool ignoreErrors; private CssCombinator combinator; private CssSelectorConstructor nested; private string attrName; private string attrValue; private string attrOp; public bool IgnoreErrors { get { return ignoreErrors; } set { ignoreErrors = value; } } public Selector Result { get { if (complex != null) { complex.ConcludeSelector(temp); temp = complex; } if (group == null || group.Length == 0) return temp ?? SimpleSelector.All; if (temp == null && group.Length == 1) return group[0]; if (temp != null) { group.AppendSelector(temp); temp = null; } return group; } } public CssSelectorConstructor() { Reset(); } public void Apply(CssToken token) { switch (state) { case State.Data: OnData(token); break; case State.Class: OnClass(token); break; case State.Attribute: OnAttribute(token); break; case State.AttributeOperator: OnAttributeOperator(token); break; case State.AttributeValue: OnAttributeValue(token); break; case State.AttributeEnd: OnAttributeEnd(token); break; case State.PseudoClass: OnPseudoClass(token); break; case State.PseudoClassFunction: OnPseudoClassFunction(token); break; case State.PseudoClassFunctionEnd: OnPseudoClassFunctionEnd(token); break; case State.PseudoElement: OnPseudoElement(token); break; } } public CssSelectorConstructor Reset() { attrName = null; attrValue = null; attrOp = string.Empty; state = State.Data; combinator = CssCombinator.Descendent; hasCombinator = false; ignoreErrors = false; temp = null; group = null; complex = null; return this; } private void OnData(CssToken token) { switch (token.Type) { case CssTokenType.SquareBracketOpen: attrName = null; attrValue = null; attrOp = string.Empty; state = State.Attribute; break; case CssTokenType.Colon: state = State.PseudoClass; break; case CssTokenType.Hash: Insert(SimpleSelector.Id(((CssKeywordToken)token).Data)); break; case CssTokenType.Ident: Insert(SimpleSelector.Type(((CssKeywordToken)token).Data)); break; case CssTokenType.Whitespace: Insert(CssCombinator.Descendent); break; case CssTokenType.Delim: OnDelim(token); break; case CssTokenType.Comma: InsertOr(); break; default: if (!ignoreErrors) throw new DOMException(ErrorCode.SyntaxError); break; } } private void OnAttribute(CssToken token) { if (token.Type != CssTokenType.Whitespace) { state = State.AttributeOperator; if (token.Type == CssTokenType.Ident) attrName = ((CssKeywordToken)token).Data; else if (token.Type == CssTokenType.String) { attrName = ((CssStringToken)token).Data; } else { if (!ignoreErrors) throw new DOMException(ErrorCode.SyntaxError); state = State.Data; } } } private void OnAttributeOperator(CssToken token) { if (token.Type != CssTokenType.Whitespace) { state = State.AttributeValue; if (token.Type == CssTokenType.SquareBracketClose) OnAttributeEnd(token); else if (token is CssMatchToken || token.Type == CssTokenType.Delim) { attrOp = token.ToValue(); } else { if (!ignoreErrors) throw new DOMException(ErrorCode.SyntaxError); state = State.AttributeEnd; } } } private void OnAttributeValue(CssToken token) { if (token.Type != CssTokenType.Whitespace) { state = State.AttributeEnd; if (token.Type == CssTokenType.Ident) attrValue = ((CssKeywordToken)token).Data; else if (token.Type == CssTokenType.String) { attrValue = ((CssStringToken)token).Data; } else if (token.Type == CssTokenType.Number) { attrValue = ((CssNumberToken)token).Data.ToString(); } else { if (!ignoreErrors) throw new DOMException(ErrorCode.SyntaxError); state = State.Data; } } } private void OnAttributeEnd(CssToken token) { if (token.Type != CssTokenType.Whitespace) { state = State.Data; if (token.Type == CssTokenType.SquareBracketClose) { switch (attrOp) { case "=": Insert(SimpleSelector.AttrMatch(attrName, attrValue)); break; case "~=": Insert(SimpleSelector.AttrList(attrName, attrValue)); break; case "|=": Insert(SimpleSelector.AttrHyphen(attrName, attrValue)); break; case "^=": Insert(SimpleSelector.AttrBegins(attrName, attrValue)); break; case "$=": Insert(SimpleSelector.AttrEnds(attrName, attrValue)); break; case "*=": Insert(SimpleSelector.AttrContains(attrName, attrValue)); break; case "!=": Insert(SimpleSelector.AttrNotMatch(attrName, attrValue)); break; default: Insert(SimpleSelector.AttrAvailable(attrName)); break; } } else if (!ignoreErrors) { throw new DOMException(ErrorCode.SyntaxError); } } } private void OnPseudoClass(CssToken token) { state = State.Data; if (token.Type == CssTokenType.Colon) state = State.PseudoElement; else if (token.Type == CssTokenType.Function) { attrName = ((CssKeywordToken)token).Data; attrValue = string.Empty; state = State.PseudoClassFunction; if (nested != null) nested.Reset(); } else if (token.Type == CssTokenType.Ident) { SimpleSelector pseudoSelector = GetPseudoSelector(token); if (pseudoSelector != null) Insert(pseudoSelector); else if (!ignoreErrors) { throw new DOMException(ErrorCode.SyntaxError); } } else if (!ignoreErrors) { throw new DOMException(ErrorCode.SyntaxError); } } private void OnPseudoElement(CssToken token) { if (token.Type == CssTokenType.Ident) { string data = ((CssKeywordToken)token).Data; switch (data) { case "before": Insert(SimpleSelector.PseudoElement(MatchBefore, "before")); break; case "after": Insert(SimpleSelector.PseudoElement(MatchAfter, "after")); break; case "selection": Insert(SimpleSelector.PseudoElement((Element el) => true, "selection")); break; case "first-line": Insert(SimpleSelector.PseudoElement(MatchFirstLine, "first-line")); break; case "first-letter": Insert(SimpleSelector.PseudoElement(MatchFirstLetter, "first-letter")); break; default: if (!ignoreErrors) throw new DOMException(ErrorCode.SyntaxError); Insert(SimpleSelector.PseudoElement((Element el) => false, data)); break; } } else if (!ignoreErrors) { throw new DOMException(ErrorCode.SyntaxError); } } private void OnClass(CssToken token) { state = State.Data; if (token.Type == CssTokenType.Ident) Insert(SimpleSelector.Class(((CssKeywordToken)token).Data)); else if (!ignoreErrors) { throw new DOMException(ErrorCode.SyntaxError); } } private void OnPseudoClassFunction(CssToken token) { if (token.Type != CssTokenType.Whitespace) { switch (attrName) { case "nth-child": case "nth-last-child": switch (token.Type) { case CssTokenType.Ident: case CssTokenType.Number: case CssTokenType.Dimension: attrValue += token.ToValue(); return; case CssTokenType.Delim: { char data = ((CssDelimToken)token).Data; if (data == '+' || data == '-') { attrValue += data; return; } break; } } break; case "not": if (nested == null) nested = new CssSelectorConstructor(); if (token.Type != CssTokenType.RoundBracketClose || nested.state != 0) { nested.Apply(token); return; } break; case "dir": if (token.Type == CssTokenType.Ident) attrValue = ((CssKeywordToken)token).Data; state = State.PseudoClassFunctionEnd; return; case "lang": if (token.Type == CssTokenType.Ident) attrValue = ((CssKeywordToken)token).Data; state = State.PseudoClassFunctionEnd; return; case "contains": if (token.Type == CssTokenType.String) attrValue = ((CssStringToken)token).Data; else if (token.Type == CssTokenType.Ident) { attrValue = ((CssKeywordToken)token).Data; } state = State.PseudoClassFunctionEnd; return; } OnPseudoClassFunctionEnd(token); } } private void OnPseudoClassFunctionEnd(CssToken token) { state = State.Data; if (token.Type == CssTokenType.RoundBracketClose) { string a; if ((a = attrName) != null) { if (!(a == "nth-child")) { if (!(a == "nth-last-child")) { if (!(a == "not")) { if (!(a == "dir")) { if (!(a == "lang")) { if (a == "contains") { string pseudoClass = string.Format("{0}({1})", new object[2] { "contains", attrValue }); Insert(SimpleSelector.PseudoClass((Element el) => el.TextContent.Contains(attrValue), pseudoClass)); } } else { string pseudoClass2 = string.Format("{0}({1})", new object[2] { "lang", attrValue }); Insert(SimpleSelector.PseudoClass((Element el) => el.Lang.StartsWith(attrValue, StringComparison.OrdinalIgnoreCase), pseudoClass2)); } } else { string pseudoClass3 = string.Format("{0}({1})", new object[2] { "dir", attrValue }); DirectionMode dirCode = (!(attrValue == "ltr")) ? DirectionMode.Rtl : DirectionMode.Ltr; Insert(SimpleSelector.PseudoClass((Element el) => el.Dir == dirCode, pseudoClass3)); } } else { Selector sel = nested.Result; string pseudoClass4 = string.Format("{0}({1})", new object[2] { "not", sel.ToCss() }); Insert(SimpleSelector.PseudoClass((Element el) => !sel.Match(el), pseudoClass4)); } } else Insert(GetChildSelector<NthLastChildSelector>()); } else Insert(GetChildSelector<NthFirstChildSelector>()); } } else if (!ignoreErrors) { throw new DOMException(ErrorCode.SyntaxError); } } private void InsertOr() { if (temp != null) { if (group == null) group = new ListSelector(); if (complex != null) { complex.ConcludeSelector(temp); group.AppendSelector(complex); complex = null; } else group.AppendSelector(temp); temp = null; } } private void Insert(Selector selector) { if (temp != null) { if (!hasCombinator) { CompoundSelector compoundSelector = temp as CompoundSelector; if (compoundSelector == null) { compoundSelector = new CompoundSelector(); compoundSelector.AppendSelector(temp); } compoundSelector.AppendSelector(selector); temp = compoundSelector; } else { if (complex == null) complex = new ComplexSelector(); complex.AppendSelector(temp, combinator); combinator = CssCombinator.Descendent; hasCombinator = false; temp = selector; } } else { combinator = CssCombinator.Descendent; hasCombinator = false; temp = selector; } } private void Insert(CssCombinator cssCombinator) { hasCombinator = true; if (cssCombinator != CssCombinator.Descendent) combinator = cssCombinator; } private void OnDelim(CssToken token) { switch (((CssDelimToken)token).Data) { case ',': InsertOr(); break; case '>': Insert(CssCombinator.Child); break; case '+': Insert(CssCombinator.AdjacentSibling); break; case '~': Insert(CssCombinator.Sibling); break; case '*': Insert(SimpleSelector.All); break; case '.': state = State.Class; break; default: if (!ignoreErrors) throw new DOMException(ErrorCode.SyntaxError); break; } } private SimpleSelector GetChildSelector<T>() where T : NthChildSelector, new { new NthFirstChildSelector(); T val = new T(); if (attrValue.Equals(nth_child_odd, StringComparison.OrdinalIgnoreCase)) { val.step = 2; val.offset = 1; } else if (attrValue.Equals(nth_child_even, StringComparison.OrdinalIgnoreCase)) { val.step = 2; val.offset = 0; } else if (!int.TryParse(attrValue, out val.offset)) { int num = attrValue.IndexOf(nth_child_n, StringComparison.OrdinalIgnoreCase); if (attrValue.Length > 0 && num != -1) { string text = attrValue.Substring(0, num).Replace(" ", ""); string text2 = attrValue.Substring(num + 1).Replace(" ", ""); if (text == string.Empty || (text.Length == 1 && text[0] == '+')) val.step = 1; else if (text.Length == 1 && text[0] == '-') { val.step = -1; } else if (!int.TryParse(text, out val.step)) { throw new DOMException(ErrorCode.SyntaxError); } if (text2 == string.Empty) val.offset = 0; else if (!int.TryParse(text2, out val.offset) && !ignoreErrors) { throw new DOMException(ErrorCode.SyntaxError); } } else if (!ignoreErrors) { throw new DOMException(ErrorCode.SyntaxError); } } return val; } private SimpleSelector GetPseudoSelector(CssToken token) { switch (((CssKeywordToken)token).Data) { case "root": return SimpleSelector.PseudoClass((Element el) => el.OwnerDocument.DocumentElement == el, "root"); case "first-of-type": return SimpleSelector.PseudoClass(delegate(Element el) { Element parentElement3 = el.ParentElement; if (parentElement3 == null) return true; for (int j = 0; j < parentElement3.ChildNodes.Length; j++) { if (parentElement3.ChildNodes[j].NodeName == el.NodeName) return parentElement3.ChildNodes[j] == el; } return false; }, "first-of-type"); case "last-of-type": return SimpleSelector.PseudoClass(delegate(Element el) { Element parentElement = el.ParentElement; if (parentElement == null) return true; for (int num = parentElement.ChildNodes.Length - 1; num >= 0; num--) { if (parentElement.ChildNodes[num].NodeName == el.NodeName) return parentElement.ChildNodes[num] == el; } return false; }, "last-of-type"); case "only-child": return SimpleSelector.PseudoClass(delegate(Element el) { Element parentElement2 = el.ParentElement; if (parentElement2 == null) return false; int num2 = 0; for (int i = 0; i < parentElement2.ChildNodes.Length; i++) { if (parentElement2.ChildNodes[i] is Element && ++num2 == 2) return false; } return true; }, "only-child"); case "first-child": return FirstChildSelector.Instance; case "last-child": return LastChildSelector.Instance; case "empty": return SimpleSelector.PseudoClass((Element el) => el.ChildNodes.Length == 0, "empty"); case "link": return SimpleSelector.PseudoClass(delegate(Element el) { if (el is HTMLAnchorElement) { if (!string.IsNullOrEmpty(el.GetAttribute(AttributeNames.Href))) return !((HTMLAnchorElement)el).IsVisited; return false; } if (el is HTMLAreaElement) { if (!string.IsNullOrEmpty(el.GetAttribute(AttributeNames.Href))) return !((HTMLAreaElement)el).IsVisited; return false; } if (el is HTMLLinkElement) { if (!string.IsNullOrEmpty(el.GetAttribute(AttributeNames.Href))) return !((HTMLLinkElement)el).IsVisited; return false; } return false; }, "link"); case "visited": return SimpleSelector.PseudoClass(delegate(Element el) { if (el is HTMLAnchorElement) { if (!string.IsNullOrEmpty(el.GetAttribute(AttributeNames.Href))) return ((HTMLAnchorElement)el).IsVisited; return false; } if (el is HTMLAreaElement) { if (!string.IsNullOrEmpty(el.GetAttribute(AttributeNames.Href))) return ((HTMLAreaElement)el).IsVisited; return false; } if (el is HTMLLinkElement) { if (!string.IsNullOrEmpty(el.GetAttribute(AttributeNames.Href))) return ((HTMLLinkElement)el).IsVisited; return false; } return false; }, "visited"); case "active": return SimpleSelector.PseudoClass(delegate(Element el) { if (el is HTMLAnchorElement) { if (!string.IsNullOrEmpty(el.GetAttribute(AttributeNames.Href))) return ((HTMLAnchorElement)el).IsActive; return false; } if (el is HTMLAreaElement) { if (!string.IsNullOrEmpty(el.GetAttribute(AttributeNames.Href))) return ((HTMLAreaElement)el).IsActive; return false; } if (el is HTMLLinkElement) { if (!string.IsNullOrEmpty(el.GetAttribute(AttributeNames.Href))) return ((HTMLLinkElement)el).IsActive; return false; } if (el is HTMLButtonElement) { if (!((HTMLButtonElement)el).Disabled) return ((HTMLButtonElement)el).IsActive; return false; } if (el is HTMLInputElement) { HTMLInputElement hTMLInputElement2 = (HTMLInputElement)el; if (hTMLInputElement2.Type == HTMLInputElement.InputType.Submit || hTMLInputElement2.Type == HTMLInputElement.InputType.Image || hTMLInputElement2.Type == HTMLInputElement.InputType.Reset || hTMLInputElement2.Type == HTMLInputElement.InputType.Button) return hTMLInputElement2.IsActive; return false; } if (el is HTMLMenuItemElement) { if (string.IsNullOrEmpty(el.GetAttribute(AttributeNames.Disabled))) return ((HTMLMenuItemElement)el).IsActive; return false; } return false; }, "active"); case "hover": return SimpleSelector.PseudoClass((Element el) => el.IsHovered, "hover"); case "focus": return SimpleSelector.PseudoClass((Element el) => el.IsFocused, "focus"); case "target": return SimpleSelector.PseudoClass(delegate(Element el) { if (el.OwnerDocument != null) return el.Id == el.OwnerDocument.Location.Hash; return false; }, "target"); case "enabled": return SimpleSelector.PseudoClass(delegate(Element el) { if (el is HTMLAnchorElement || el is HTMLAreaElement || el is HTMLLinkElement) return !string.IsNullOrEmpty(el.GetAttribute(AttributeNames.Href)); if (el is HTMLButtonElement) return !((HTMLButtonElement)el).Disabled; if (el is HTMLInputElement) return !((HTMLInputElement)el).Disabled; if (el is HTMLSelectElement) return !((HTMLSelectElement)el).Disabled; if (el is HTMLTextAreaElement) return !((HTMLTextAreaElement)el).Disabled; if (el is HTMLOptionElement) return !((HTMLOptionElement)el).Disabled; if (el is HTMLOptGroupElement || el is HTMLMenuItemElement || el is HTMLFieldSetElement) return string.IsNullOrEmpty(el.GetAttribute(AttributeNames.Disabled)); return false; }, "enabled"); case "disabled": return SimpleSelector.PseudoClass(delegate(Element el) { if (el is HTMLButtonElement) return ((HTMLButtonElement)el).Disabled; if (el is HTMLInputElement) return ((HTMLInputElement)el).Disabled; if (el is HTMLSelectElement) return ((HTMLSelectElement)el).Disabled; if (el is HTMLTextAreaElement) return ((HTMLTextAreaElement)el).Disabled; if (el is HTMLOptionElement) return ((HTMLOptionElement)el).Disabled; if (el is HTMLOptGroupElement || el is HTMLMenuItemElement || el is HTMLFieldSetElement) return !string.IsNullOrEmpty(el.GetAttribute(AttributeNames.Disabled)); return false; }, "disabled"); case "default": return SimpleSelector.PseudoClass(delegate(Element el) { if (el is HTMLButtonElement) { HTMLButtonElement hTMLButtonElement = (HTMLButtonElement)el; HTMLFormElement form = hTMLButtonElement.Form; if (form != null) return true; } else if (el is HTMLInputElement) { HTMLInputElement hTMLInputElement3 = (HTMLInputElement)el; if (hTMLInputElement3.Type == HTMLInputElement.InputType.Submit || hTMLInputElement3.Type == HTMLInputElement.InputType.Image) { HTMLFormElement form2 = hTMLInputElement3.Form; if (form2 != null) return true; } } else if (el is HTMLOptionElement) { return !string.IsNullOrEmpty(el.GetAttribute(AttributeNames.Selected)); } return false; }, "default"); case "checked": return SimpleSelector.PseudoClass(delegate(Element el) { if (el is HTMLInputElement) { HTMLInputElement hTMLInputElement4 = (HTMLInputElement)el; if (hTMLInputElement4.Type == HTMLInputElement.InputType.Checkbox || hTMLInputElement4.Type == HTMLInputElement.InputType.Radio) return hTMLInputElement4.Checked; return false; } if (el is HTMLMenuItemElement) { HTMLMenuItemElement hTMLMenuItemElement2 = (HTMLMenuItemElement)el; if (hTMLMenuItemElement2.Type == HTMLMenuItemElement.ItemType.Checkbox || hTMLMenuItemElement2.Type == HTMLMenuItemElement.ItemType.Radio) return hTMLMenuItemElement2.Checked; return false; } if (el is HTMLOptionElement) return ((HTMLOptionElement)el).Selected; return false; }, "checked"); case "indeterminate": return SimpleSelector.PseudoClass(delegate(Element el) { if (el is HTMLInputElement) { HTMLInputElement hTMLInputElement5 = (HTMLInputElement)el; if (hTMLInputElement5.Type == HTMLInputElement.InputType.Checkbox) return hTMLInputElement5.Indeterminate; return false; } if (el is HTMLProgressElement) return string.IsNullOrEmpty(el.GetAttribute(AttributeNames.Value)); return false; }, "indeterminate"); case "unchecked": return SimpleSelector.PseudoClass(delegate(Element el) { if (el is HTMLInputElement) { HTMLInputElement hTMLInputElement = (HTMLInputElement)el; if (hTMLInputElement.Type == HTMLInputElement.InputType.Checkbox || hTMLInputElement.Type == HTMLInputElement.InputType.Radio) return !hTMLInputElement.Checked; return false; } if (el is HTMLMenuItemElement) { HTMLMenuItemElement hTMLMenuItemElement = (HTMLMenuItemElement)el; if (hTMLMenuItemElement.Type == HTMLMenuItemElement.ItemType.Checkbox || hTMLMenuItemElement.Type == HTMLMenuItemElement.ItemType.Radio) return !hTMLMenuItemElement.Checked; return false; } if (el is HTMLOptionElement) return !((HTMLOptionElement)el).Selected; return false; }, "unchecked"); case "valid": return SimpleSelector.PseudoClass(delegate(Element el) { if (el is IValidation) return ((IValidation)el).CheckValidity(); if (el is HTMLFormElement) return ((HTMLFormElement)el).CheckValidity(); return false; }, "valid"); case "invalid": return SimpleSelector.PseudoClass(delegate(Element el) { if (el is IValidation) return !((IValidation)el).CheckValidity(); if (el is HTMLFormElement) return !((HTMLFormElement)el).CheckValidity(); return false; }, "invalid"); case "required": return SimpleSelector.PseudoClass(delegate(Element el) { if (el is HTMLInputElement) return ((HTMLInputElement)el).Required; if (el is HTMLSelectElement) return ((HTMLSelectElement)el).Required; if (el is HTMLTextAreaElement) return ((HTMLTextAreaElement)el).Required; return false; }, "required"); case "read-only": return SimpleSelector.PseudoClass(delegate(Element el) { if (el is HTMLInputElement) return !((HTMLInputElement)el).IsMutable; if (el is HTMLTextAreaElement) return !((HTMLTextAreaElement)el).IsMutable; return !el.IsContentEditable; }, "read-only"); case "read-write": return SimpleSelector.PseudoClass(delegate(Element el) { if (el is HTMLInputElement) return ((HTMLInputElement)el).IsMutable; if (el is HTMLTextAreaElement) return ((HTMLTextAreaElement)el).IsMutable; return el.IsContentEditable; }, "read-write"); case "in-range": return SimpleSelector.PseudoClass(delegate(Element el) { if (el is IValidation) { ValidityState validity = ((IValidation)el).Validity; if (!validity.RangeOverflow) return !validity.RangeUnderflow; return false; } return false; }, "in-range"); case "out-of-range": return SimpleSelector.PseudoClass(delegate(Element el) { if (el is IValidation) { ValidityState validity2 = ((IValidation)el).Validity; if (!validity2.RangeOverflow) return validity2.RangeUnderflow; return true; } return false; }, "out-of-range"); case "optional": return SimpleSelector.PseudoClass(delegate(Element el) { if (el is HTMLInputElement) return !((HTMLInputElement)el).Required; if (el is HTMLSelectElement) return !((HTMLSelectElement)el).Required; if (el is HTMLTextAreaElement) return !((HTMLTextAreaElement)el).Required; return false; }, "optional"); case "before": return SimpleSelector.PseudoClass(MatchBefore, "before"); case "after": return SimpleSelector.PseudoClass(MatchAfter, "after"); case "first-line": return SimpleSelector.PseudoClass(MatchFirstLine, "first-line"); case "first-letter": return SimpleSelector.PseudoClass(MatchFirstLetter, "first-letter"); default: return null; } } private static bool MatchBefore(Element element) { return true; } private static bool MatchAfter(Element element) { return true; } private static bool MatchFirstLine(Element element) { return true; } private static bool MatchFirstLetter(Element element) { return true; } } }