ValueExtensions
A bunch of useful extension methods.
using AngleSharp.Css.Values;
using AngleSharp.Dom.Css;
using AngleSharp.Parser.Css;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace AngleSharp.Extensions
{
[DebuggerStepThrough]
internal static class ValueExtensions
{
public static CssToken OnlyOrDefault(this IEnumerable<CssToken> value)
{
CssToken cssToken = null;
foreach (CssToken item in value) {
if (cssToken != null)
return null;
cssToken = item;
}
return cssToken;
}
public static bool Is(this IEnumerable<CssToken> value, string expected)
{
return value.ToIdentifier()?.Equals(expected, StringComparison.OrdinalIgnoreCase) ?? false;
}
public static string ToUri(this IEnumerable<CssToken> value)
{
CssToken cssToken = value.OnlyOrDefault();
if (cssToken != null && cssToken.Type == CssTokenType.Url)
return cssToken.Data;
return null;
}
public static Length? ToDistance(this IEnumerable<CssToken> value)
{
Percent? nullable = value.ToPercent();
if (nullable.HasValue)
return new Length(nullable.Value.Value, Length.Unit.Percent);
return value.ToLength();
}
public static Length ToLength(this FontSize fontSize)
{
switch (fontSize) {
case FontSize.Big:
return new Length(1.5, Length.Unit.Em);
case FontSize.Huge:
return new Length(2, Length.Unit.Em);
case FontSize.Large:
return new Length(1.2, Length.Unit.Em);
case FontSize.Larger:
return new Length(120, Length.Unit.Percent);
case FontSize.Little:
return new Length(0.75, Length.Unit.Em);
case FontSize.Small:
return new Length(0.8888889, Length.Unit.Em);
case FontSize.Smaller:
return new Length(80, Length.Unit.Percent);
case FontSize.Tiny:
return new Length(0.6, Length.Unit.Em);
default:
return new Length(1, Length.Unit.Em);
}
}
public static Percent? ToPercent(this IEnumerable<CssToken> value)
{
CssToken cssToken = value.OnlyOrDefault();
if (cssToken != null && cssToken.Type == CssTokenType.Percentage)
return new Percent(((CssUnitToken)cssToken).Value);
return null;
}
public static string ToCssString(this IEnumerable<CssToken> value)
{
CssToken cssToken = value.OnlyOrDefault();
if (cssToken != null && cssToken.Type == CssTokenType.String)
return cssToken.Data;
return null;
}
public static string ToLiterals(this IEnumerable<CssToken> value)
{
List<string> list = new List<string>();
IEnumerator<CssToken> enumerator = value.GetEnumerator();
if (enumerator.MoveNext()) {
do {
if (enumerator.Current.Type != CssTokenType.Ident)
return null;
list.Add(enumerator.Current.Data);
if (enumerator.MoveNext() && enumerator.Current.Type != CssTokenType.Whitespace)
return null;
} while (enumerator.MoveNext());
return string.Join(" ", list);
}
return null;
}
public static string ToIdentifier(this IEnumerable<CssToken> value)
{
CssToken cssToken = value.OnlyOrDefault();
if (cssToken != null && cssToken.Type == CssTokenType.Ident)
return cssToken.Data.ToLowerInvariant();
return null;
}
public static string ToAnimatableIdentifier(this IEnumerable<CssToken> value)
{
string text = value.ToIdentifier();
if (text != null && (text.Equals(Keywords.All, StringComparison.OrdinalIgnoreCase) || Factory.Properties.IsAnimatable(text)))
return text;
return null;
}
public static float? ToSingle(this IEnumerable<CssToken> value)
{
CssToken cssToken = value.OnlyOrDefault();
if (cssToken != null && cssToken.Type == CssTokenType.Number)
return ((CssNumberToken)cssToken).Value;
return null;
}
public static float? ToNaturalSingle(this IEnumerable<CssToken> value)
{
float? result = value.ToSingle();
if (!result.HasValue || !(result.Value >= 0))
return null;
return result;
}
public static int? ToInteger(this IEnumerable<CssToken> value)
{
CssToken cssToken = value.OnlyOrDefault();
if (cssToken != null && cssToken.Type == CssTokenType.Number && ((CssNumberToken)cssToken).IsInteger)
return ((CssNumberToken)cssToken).IntegerValue;
return null;
}
public static int? ToNaturalInteger(this IEnumerable<CssToken> value)
{
int? result = value.ToInteger();
if (!result.HasValue || result.Value < 0)
return null;
return result;
}
public static int? ToPositiveInteger(this IEnumerable<CssToken> value)
{
int? result = value.ToInteger();
if (!result.HasValue || result.Value <= 0)
return null;
return result;
}
public static int? ToWeightInteger(this IEnumerable<CssToken> value)
{
int? result = value.ToPositiveInteger();
if (!result.HasValue || !IsWeight(result.Value))
return null;
return result;
}
public static int? ToBinary(this IEnumerable<CssToken> value)
{
int? result = value.ToInteger();
if (!result.HasValue || (result.Value != 0 && result.Value != 1))
return null;
return result;
}
public static byte? ToByte(this IEnumerable<CssToken> value)
{
int? nullable = value.ToNaturalInteger();
if (!nullable.HasValue)
return null;
return (byte)Math.Min(nullable.Value, 255);
}
public static Angle? ToAngle(this IEnumerable<CssToken> value)
{
CssToken cssToken = value.OnlyOrDefault();
if (cssToken != null && cssToken.Type == CssTokenType.Dimension) {
CssUnitToken cssUnitToken = (CssUnitToken)cssToken;
switch (cssUnitToken.Unit) {
case "deg":
return new Angle(cssUnitToken.Value, Angle.Unit.Deg);
case "grad":
return new Angle(cssUnitToken.Value, Angle.Unit.Grad);
case "turn":
return new Angle(cssUnitToken.Value, Angle.Unit.Turn);
case "rad":
return new Angle(cssUnitToken.Value, Angle.Unit.Rad);
}
}
return null;
}
public static Frequency? ToFrequency(this IEnumerable<CssToken> value)
{
CssToken cssToken = value.OnlyOrDefault();
if (cssToken != null && cssToken.Type == CssTokenType.Dimension) {
CssUnitToken cssUnitToken = (CssUnitToken)cssToken;
switch (cssUnitToken.Unit) {
case "hz":
return new Frequency(cssUnitToken.Value, Frequency.Unit.Hz);
case "khz":
return new Frequency(cssUnitToken.Value, Frequency.Unit.Khz);
}
}
return null;
}
public static Length? ToLength(this IEnumerable<CssToken> value)
{
CssToken cssToken = value.OnlyOrDefault();
if (cssToken != null) {
if (cssToken.Type == CssTokenType.Dimension) {
CssUnitToken cssUnitToken = (CssUnitToken)cssToken;
switch (cssUnitToken.Unit) {
case "ch":
return new Length(cssUnitToken.Value, Length.Unit.Ch);
case "cm":
return new Length(cssUnitToken.Value, Length.Unit.Cm);
case "em":
return new Length(cssUnitToken.Value, Length.Unit.Em);
case "ex":
return new Length(cssUnitToken.Value, Length.Unit.Ex);
case "in":
return new Length(cssUnitToken.Value, Length.Unit.In);
case "mm":
return new Length(cssUnitToken.Value, Length.Unit.Mm);
case "pc":
return new Length(cssUnitToken.Value, Length.Unit.Pc);
case "pt":
return new Length(cssUnitToken.Value, Length.Unit.Pt);
case "px":
return new Length(cssUnitToken.Value, Length.Unit.Px);
case "rem":
return new Length(cssUnitToken.Value, Length.Unit.Rem);
case "vh":
return new Length(cssUnitToken.Value, Length.Unit.Vh);
case "vmax":
return new Length(cssUnitToken.Value, Length.Unit.Vmax);
case "vmin":
return new Length(cssUnitToken.Value, Length.Unit.Vmin);
case "vw":
return new Length(cssUnitToken.Value, Length.Unit.Vw);
}
} else if (cssToken.Type == CssTokenType.Number && ((CssNumberToken)cssToken).Value == 0) {
return Length.Zero;
}
}
return null;
}
public static Resolution? ToResolution(this IEnumerable<CssToken> value)
{
CssToken cssToken = value.OnlyOrDefault();
if (cssToken != null && cssToken.Type == CssTokenType.Dimension) {
CssUnitToken cssUnitToken = (CssUnitToken)cssToken;
switch (cssUnitToken.Unit) {
case "dpcm":
return new Resolution(cssUnitToken.Value, Resolution.Unit.Dpcm);
case "dpi":
return new Resolution(cssUnitToken.Value, Resolution.Unit.Dpi);
case "dppx":
return new Resolution(cssUnitToken.Value, Resolution.Unit.Dppx);
}
}
return null;
}
public static Time? ToTime(this IEnumerable<CssToken> value)
{
CssToken cssToken = value.OnlyOrDefault();
if (cssToken != null && cssToken.Type == CssTokenType.Dimension) {
CssUnitToken cssUnitToken = (CssUnitToken)cssToken;
switch (cssUnitToken.Unit) {
case "s":
return new Time(cssUnitToken.Value, Time.Unit.S);
case "ms":
return new Time(cssUnitToken.Value, Time.Unit.Ms);
}
}
return null;
}
public static Length? ToBorderWidth(this IEnumerable<CssToken> value)
{
Length? result = value.ToLength();
if (result.HasValue)
return result;
if (value.Is(Keywords.Thin))
return Length.Thin;
if (value.Is(Keywords.Medium))
return Length.Medium;
if (value.Is(Keywords.Thick))
return Length.Thick;
return result;
}
public static List<List<CssToken>> ToItems(this IEnumerable<CssToken> value)
{
List<List<CssToken>> list = new List<List<CssToken>>();
List<CssToken> list2 = new List<CssToken>();
int num = 0;
list.Add(list2);
foreach (CssToken item in value) {
bool flag = item.Type == CssTokenType.Whitespace;
bool flag2 = item.Type == CssTokenType.String || item.Type == CssTokenType.Url || item.Type == CssTokenType.Function;
if (num == 0 && (flag || flag2)) {
if (list2.Count != 0) {
list2 = new List<CssToken>();
list.Add(list2);
}
if (flag)
continue;
} else if (item.Type == CssTokenType.RoundBracketOpen) {
num++;
} else if (item.Type == CssTokenType.RoundBracketClose) {
num--;
}
list2.Add(item);
}
return list;
}
public static void Trim(this List<CssToken> value)
{
int num = 0;
int num2 = value.Count - 1;
while (num < num2) {
if (value[num].Type == CssTokenType.Whitespace)
num++;
else {
if (value[num2].Type != CssTokenType.Whitespace)
break;
num2--;
}
}
value.RemoveRange(++num2, value.Count - num2);
value.RemoveRange(0, num);
}
public static List<List<CssToken>> ToList(this IEnumerable<CssToken> value)
{
List<List<CssToken>> list = new List<List<CssToken>>();
List<CssToken> list2 = new List<CssToken>();
int num = 0;
list.Add(list2);
foreach (CssToken item in value) {
if (num == 0 && item.Type == CssTokenType.Comma) {
list2 = new List<CssToken>();
list.Add(list2);
} else {
if (item.Type == CssTokenType.RoundBracketOpen)
num++;
else if (item.Type == CssTokenType.RoundBracketClose) {
num--;
} else if (item.Type == CssTokenType.Whitespace && list2.Count == 0) {
continue;
}
list2.Add(item);
}
}
for (int i = 0; i < list.Count; i++) {
list[i].Trim();
}
return list;
}
public static string ToText(this IEnumerable<CssToken> value)
{
return string.Join(string.Empty, from m in value
select m.ToValue());
}
public static Color? ToColor(this IEnumerable<CssToken> value)
{
CssToken cssToken = value.OnlyOrDefault();
if (cssToken != null && cssToken.Type == CssTokenType.Ident)
return Color.FromName(cssToken.Data);
if (cssToken != null && cssToken.Type == CssTokenType.Color && !((CssStringToken)cssToken).IsBad)
return Color.FromHex(cssToken.Data);
return null;
}
private static bool IsWeight(int value)
{
if (value != 100 && value != 200 && value != 300 && value != 400 && value != 500 && value != 600 && value != 700 && value != 800)
return value == 900;
return true;
}
}
}