SimpleSelector
Represents a simple selector (either a type selector,
universal selector, attribute selector, class selector,
id selector or pseudo-class).
using AngleSharp.Css;
using AngleSharp.Extensions;
using System;
namespace AngleSharp.Dom.Css
{
internal class SimpleSelector : ISelector
{
private static readonly SimpleSelector _all = new SimpleSelector();
private readonly Predicate<IElement> _matches;
private readonly Priority _specifity;
private readonly string _code;
public static ISelector All => _all;
public Priority Specifity => _specifity;
public string Text => _code;
public SimpleSelector()
{
_matches = ((IElement _) => true);
_code = "*";
_specifity = Priority.Zero;
}
public SimpleSelector(string match)
{
_matches = ((IElement _) => _.LocalName.Equals(match, StringComparison.OrdinalIgnoreCase));
_specifity = Priority.OneTag;
_code = match;
}
public SimpleSelector(Predicate<IElement> matches, Priority specifify, string code)
{
_matches = matches;
_specifity = specifify;
_code = code;
}
public static SimpleSelector PseudoElement(Predicate<IElement> action, string pseudoElement)
{
return new SimpleSelector(action, Priority.OneTag, "::" + pseudoElement);
}
public static SimpleSelector PseudoClass(Predicate<IElement> action, string pseudoClass)
{
return new SimpleSelector(action, Priority.OneClass, ":" + pseudoClass);
}
public static SimpleSelector Universal()
{
return _all;
}
public static SimpleSelector Class(string match)
{
return new SimpleSelector((IElement _) => _.ClassList.Contains(match), Priority.OneClass, "." + match);
}
public static SimpleSelector Id(string match)
{
return new SimpleSelector((IElement _) => _.Id == match, Priority.OneId, "#" + match);
}
public static SimpleSelector AttrAvailable(string match, string prefix = null)
{
string str = match;
if (!string.IsNullOrEmpty(prefix)) {
str = prefix + "|" + match;
if (prefix != "*")
match = prefix + ":" + match;
}
return new SimpleSelector((IElement _) => _.HasAttribute(match), Priority.OneClass, "[" + str + "]");
}
public static SimpleSelector AttrMatch(string match, string value, string prefix = null)
{
string text = match;
if (!string.IsNullOrEmpty(prefix)) {
text = prefix + "|" + match;
if (prefix != "*")
match = prefix + ":" + match;
}
string code = string.Format("[{0}={1}]", new object[2] {
text,
GetValueAsString(value)
});
return new SimpleSelector((IElement _) => _.GetAttribute(match) == value, Priority.OneClass, code);
}
public static SimpleSelector AttrNotMatch(string match, string value, string prefix = null)
{
string text = match;
if (!string.IsNullOrEmpty(prefix)) {
text = prefix + "|" + match;
if (prefix != "*")
match = prefix + ":" + match;
}
string code = string.Format("[{0}!={1}]", new object[2] {
text,
GetValueAsString(value)
});
return new SimpleSelector((IElement _) => _.GetAttribute(match) != value, Priority.OneClass, code);
}
public static SimpleSelector AttrList(string match, string value, string prefix = null)
{
string text = match;
if (!string.IsNullOrEmpty(prefix)) {
text = prefix + "|" + match;
if (prefix != "*")
match = prefix + ":" + match;
}
string code = string.Format("[{0}~={1}]", new object[2] {
text,
GetValueAsString(value)
});
if (string.IsNullOrEmpty(value))
return new SimpleSelector((IElement _) => false, Priority.OneClass, code);
return new SimpleSelector((IElement _) => (_.GetAttribute(match) ?? string.Empty).SplitSpaces().Contains(value, StringComparison.Ordinal), Priority.OneClass, code);
}
public static SimpleSelector AttrBegins(string match, string value, string prefix = null)
{
string text = match;
if (!string.IsNullOrEmpty(prefix)) {
text = prefix + "|" + match;
if (prefix != "*")
match = prefix + ":" + match;
}
string code = string.Format("[{0}^={1}]", new object[2] {
text,
GetValueAsString(value)
});
if (string.IsNullOrEmpty(value))
return new SimpleSelector((IElement _) => false, Priority.OneClass, code);
return new SimpleSelector((IElement _) => (_.GetAttribute(match) ?? string.Empty).StartsWith(value), Priority.OneClass, code);
}
public static SimpleSelector AttrEnds(string match, string value, string prefix = null)
{
string text = match;
if (!string.IsNullOrEmpty(prefix)) {
text = prefix + "|" + match;
if (prefix != "*")
match = prefix + ":" + match;
}
string code = string.Format("[{0}$={1}]", new object[2] {
text,
GetValueAsString(value)
});
if (string.IsNullOrEmpty(value))
return new SimpleSelector((IElement _) => false, Priority.OneClass, code);
return new SimpleSelector((IElement _) => (_.GetAttribute(match) ?? string.Empty).EndsWith(value), Priority.OneClass, code);
}
public static SimpleSelector AttrContains(string match, string value, string prefix = null)
{
string text = match;
if (!string.IsNullOrEmpty(prefix)) {
text = prefix + "|" + match;
if (prefix != "*")
match = prefix + ":" + match;
}
string code = string.Format("[{0}*={1}]", new object[2] {
text,
GetValueAsString(value)
});
if (string.IsNullOrEmpty(value))
return new SimpleSelector((IElement _) => false, Priority.OneClass, code);
return new SimpleSelector((IElement _) => (_.GetAttribute(match) ?? string.Empty).Contains(value), Priority.OneClass, code);
}
public static SimpleSelector AttrHyphen(string match, string value, string prefix = null)
{
string text = match;
if (!string.IsNullOrEmpty(prefix)) {
text = prefix + "|" + match;
if (prefix != "*")
match = prefix + ":" + match;
}
string code = string.Format("[{0}|={1}]", new object[2] {
text,
GetValueAsString(value)
});
if (string.IsNullOrEmpty(value))
return new SimpleSelector((IElement _) => false, Priority.OneClass, code);
return new SimpleSelector((IElement _) => (_.GetAttribute(match) ?? string.Empty).HasHyphen(value), Priority.OneClass, code);
}
public static SimpleSelector Type(string match)
{
return new SimpleSelector(match);
}
private static string GetValueAsString(string value)
{
bool flag = false;
for (int i = 0; i < value.Length; i++) {
if (value[i].IsSpaceCharacter()) {
flag = true;
break;
}
}
if (flag) {
if (value.IndexOf('\'') != -1)
return '"' + value + '"';
return "'" + value + "'";
}
return value;
}
public bool Match(IElement element)
{
return _matches(element);
}
}
}