CssParser
The CSS parser.
See http://dev.w3.org/csswg/css-syntax/#parsing for more details.
using AngleSharp.Css;
using AngleSharp.Dom;
using AngleSharp.Dom.Collections;
using AngleSharp.Dom.Css;
using AngleSharp.Extensions;
using Microsoft.Runtime.CompilerServices;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace AngleSharp.Parser.Css
{
[DebuggerStepThrough]
public sealed class CssParser
{
private readonly CssSelectorConstructor selector;
private readonly CssValueBuilder value;
private readonly CssTokenizer tokenizer;
private readonly object sync;
private readonly CssStyleSheet sheet;
private bool started;
private Task<ICssStyleSheet> task;
public bool IsAsync => task != null;
public ICssStyleSheet Result {
get {
Parse();
return sheet;
}
}
public CssParser(string source, IConfiguration configuration = null)
: this(new CssStyleSheet(configuration, new TextSource(source)))
{
}
public CssParser(Stream stream, IConfiguration configuration = null)
: this(new CssStyleSheet(configuration, new TextSource(stream, configuration.DefaultEncoding())))
{
}
internal CssParser(CssStyleSheet stylesheet)
{
IElement ownerNode = stylesheet.OwnerNode;
selector = new CssSelectorConstructor();
value = new CssValueBuilder();
sync = new object();
tokenizer = new CssTokenizer(stylesheet.Source, stylesheet.Options.Events) {
IgnoreComments = true,
IgnoreWhitespace = true
};
started = false;
sheet = stylesheet;
}
public Task<ICssStyleSheet> ParseAsync()
{
return ParseAsync(CancellationToken.None);
}
public Task<ICssStyleSheet> ParseAsync(CancellationToken cancelToken)
{
lock (sync) {
if (!started) {
started = true;
task = KernelAsync(cancelToken);
}
}
return task;
}
public ICssStyleSheet Parse()
{
if (!started) {
started = true;
Kernel();
}
return sheet;
}
internal static CssMediaRule CreateMediaRule(CssParser parser, IEnumerator<CssToken> tokens)
{
CssMediaRule cssMediaRule = new CssMediaRule(tokens.MoveNext() ? parser.InMediaList(tokens) : new MediaList());
if (tokens.Current.Type != CssTokenType.CurlyBracketOpen)
return null;
parser.FillRules(cssMediaRule, tokens);
return cssMediaRule;
}
internal static CssPageRule CreatePageRule(CssParser parser, IEnumerator<CssToken> tokens)
{
CssPageRule cssPageRule = new CssPageRule();
if (tokens.MoveNext())
cssPageRule.Selector = parser.InSelector(tokens);
if (tokens.Current.Type == CssTokenType.CurlyBracketOpen)
parser.FillDeclarations(cssPageRule.Style, tokens);
return cssPageRule;
}
internal static CssFontFaceRule CreateFontFaceRule(CssParser parser, IEnumerator<CssToken> tokens)
{
CssFontFaceRule cssFontFaceRule = new CssFontFaceRule();
if (tokens.MoveNext() && tokens.Current.Type == CssTokenType.CurlyBracketOpen)
parser.FillDeclarations(cssFontFaceRule.Style, tokens);
return cssFontFaceRule;
}
internal static CssSupportsRule CreateSupportsRule(CssParser parser, IEnumerator<CssToken> tokens)
{
CssSupportsRule cssSupportsRule = new CssSupportsRule();
if (tokens.MoveNext())
cssSupportsRule.Condition = parser.InCondition(tokens);
if (tokens.Current.Type == CssTokenType.CurlyBracketOpen)
parser.FillRules(cssSupportsRule, tokens);
return cssSupportsRule;
}
internal static CssDocumentRule CreateDocumentRule(CssParser parser, IEnumerator<CssToken> tokens)
{
CssDocumentRule cssDocumentRule = new CssDocumentRule();
if (tokens.MoveNext())
cssDocumentRule.Conditions.AddRange(parser.InDocumentFunctions(tokens));
if (tokens.Current.Type == CssTokenType.CurlyBracketOpen)
parser.FillRules(cssDocumentRule, tokens);
return cssDocumentRule;
}
internal static CssKeyframesRule CreateKeyframesRule(CssParser parser, IEnumerator<CssToken> tokens)
{
CssKeyframesRule cssKeyframesRule = new CssKeyframesRule();
if (tokens.MoveNext())
cssKeyframesRule.Name = tokens.InKeyframesName();
if (tokens.Current.Type == CssTokenType.CurlyBracketOpen)
parser.FillRules(cssKeyframesRule, tokens);
return cssKeyframesRule;
}
internal static CssNamespaceRule CreateNamespaceRule(CssParser parser, IEnumerator<CssToken> tokens)
{
CssNamespaceRule cssNamespaceRule = new CssNamespaceRule();
if (tokens.MoveNext()) {
CssToken current = tokens.Current;
if (current.Type == CssTokenType.Ident) {
cssNamespaceRule.Prefix = current.Data;
if (tokens.MoveNext())
current = tokens.Current;
}
if (current.Type == CssTokenType.Url)
cssNamespaceRule.NamespaceUri = current.Data;
tokens.JumpToNextSemicolon();
}
return cssNamespaceRule;
}
internal static CssCharsetRule CreateCharsetRule(CssParser parser, IEnumerator<CssToken> tokens)
{
CssCharsetRule cssCharsetRule = new CssCharsetRule();
if (tokens.MoveNext()) {
CssToken current = tokens.Current;
if (current.Type == CssTokenType.String) {
cssCharsetRule.CharacterSet = ((CssStringToken)current).Data;
tokens.MoveNext();
}
tokens.JumpToNextSemicolon();
}
return cssCharsetRule;
}
internal static CssImportRule CreateImportRule(CssParser parser, IEnumerator<CssToken> tokens)
{
CssImportRule cssImportRule = new CssImportRule();
if (tokens.MoveNext()) {
CssToken current = tokens.Current;
if (current.Type == CssTokenType.String || current.Type == CssTokenType.Url) {
cssImportRule.Href = ((CssStringToken)current).Data;
if (tokens.MoveNext())
cssImportRule.Media = parser.InMediaList(tokens);
}
tokens.JumpToNextSemicolon();
}
return cssImportRule;
}
private static CssUnknownRule CreateUnknownRule(CssParser parser, IEnumerator<CssToken> tokens)
{
CssUnknownRule cssUnknownRule = new CssUnknownRule(tokens.Current.Data);
StringBuilder stringBuilder = Pool.NewStringBuilder();
int num = 0;
int num2 = 0;
parser.tokenizer.IgnoreWhitespace = false;
while (tokens.MoveNext()) {
CssToken current = tokens.Current;
if (num <= 0 && num2 <= 0 && (current.Type == CssTokenType.Semicolon || current.Type == CssTokenType.CurlyBracketOpen))
break;
if (current.Type == CssTokenType.RoundBracketOpen)
num++;
else if (current.Type == CssTokenType.RoundBracketClose) {
num--;
} else if (current.Type == CssTokenType.SquareBracketOpen) {
num2++;
} else if (current.Type == CssTokenType.SquareBracketClose) {
num2--;
}
stringBuilder.Append(current.ToValue());
}
cssUnknownRule.Prelude = stringBuilder.ToPool().Trim();
parser.tokenizer.IgnoreWhitespace = true;
if (tokens.Current.Type == CssTokenType.CurlyBracketOpen)
parser.FillRules(cssUnknownRule, tokens);
return cssUnknownRule;
}
private CssRule CreateRule(IEnumerator<CssToken> tokens)
{
CssToken current = tokens.Current;
switch (current.Type) {
case CssTokenType.AtKeyword: {
CssRule cssRule = this.CreateAtRule(current.Data, tokens);
if (cssRule == null) {
RaiseErrorOccurred(CssParseError.UnknownAtRule);
tokens.SkipUnknownRule();
}
return cssRule;
}
case CssTokenType.CurlyBracketOpen:
RaiseErrorOccurred(CssParseError.InvalidBlockStart);
tokens.SkipUnknownRule();
return null;
case CssTokenType.String:
case CssTokenType.Url:
case CssTokenType.RoundBracketClose:
case CssTokenType.CurlyBracketClose:
case CssTokenType.SquareBracketClose:
RaiseErrorOccurred(CssParseError.InvalidToken);
tokens.SkipUnknownRule();
return null;
default: {
CssStyleRule cssStyleRule = new CssStyleRule();
cssStyleRule.Selector = InSelector(tokens);
FillDeclarations(cssStyleRule.Style, tokens);
if (cssStyleRule.Selector == null)
return null;
return cssStyleRule;
}
}
}
private ISelector InSelector(IEnumerator<CssToken> tokens)
{
tokenizer.IgnoreWhitespace = false;
selector.Reset();
do {
CssToken current = tokens.Current;
if (current.Type == CssTokenType.CurlyBracketOpen || current.Type == CssTokenType.CurlyBracketClose)
break;
selector.Apply(current);
} while (tokens.MoveNext());
if (!selector.IsValid)
RaiseErrorOccurred(CssParseError.InvalidSelector);
tokenizer.IgnoreWhitespace = true;
return selector.Result;
}
private CssProperty Declaration(IEnumerator<CssToken> tokens, CssStyleDeclaration style)
{
CssToken current = tokens.Current;
if (current.Type == CssTokenType.Ident) {
string data = current.Data;
if (!tokens.MoveNext())
RaiseErrorOccurred(CssParseError.ColonMissing);
else if (tokens.Current.Type != CssTokenType.Colon) {
RaiseErrorOccurred(CssParseError.ColonMissing);
tokens.JumpToEndOfDeclaration();
} else {
if (tokens.MoveNext()) {
CssProperty cssProperty = style.CreateProperty(data);
if (cssProperty == null) {
RaiseErrorOccurred(CssParseError.UnknownDeclarationName);
cssProperty = new CssUnknownProperty(data, style);
}
ICssValue cssValue = InValue(tokens);
if (cssValue != null && cssProperty.TrySetValue(cssValue))
style.SetProperty(cssProperty);
if (IsImportant(tokens))
cssProperty.IsImportant = true;
tokens.JumpToEndOfDeclaration();
return cssProperty;
}
RaiseErrorOccurred(CssParseError.ValueMissing);
}
} else
RaiseErrorOccurred(CssParseError.IdentExpected);
return null;
}
private bool IsImportant(IEnumerator<CssToken> tokens)
{
CssToken current = tokens.Current;
if (current.Type == CssTokenType.Ident)
return current.Data == Keywords.Important;
return false;
}
private IEnumerable<Tuple<CssDocumentRule.DocumentFunction, string>> InDocumentFunctions(IEnumerator<CssToken> tokens)
{
do {
Tuple<CssDocumentRule.DocumentFunction, string> tuple = InDocumentFunction(tokens);
if (tuple != null)
yield return tuple;
} while (tokens.MoveNext() && tokens.Current.Type == CssTokenType.Comma);
}
private Tuple<CssDocumentRule.DocumentFunction, string> InDocumentFunction(IEnumerator<CssToken> tokens)
{
CssToken current = tokens.Current;
switch (current.Type) {
case CssTokenType.Url:
return Tuple.Create(CssDocumentRule.DocumentFunction.Url, ((CssStringToken)current).Data);
case CssTokenType.UrlPrefix:
return Tuple.Create(CssDocumentRule.DocumentFunction.UrlPrefix, ((CssStringToken)current).Data);
case CssTokenType.Domain:
return Tuple.Create(CssDocumentRule.DocumentFunction.Domain, ((CssStringToken)current).Data);
case CssTokenType.Function:
if (string.Compare(current.Data, FunctionNames.Regexp, StringComparison.OrdinalIgnoreCase) == 0 && tokens.MoveNext()) {
current = tokens.Current;
if (current.Type == CssTokenType.String)
return Tuple.Create(CssDocumentRule.DocumentFunction.RegExp, ((CssStringToken)current).Data);
tokens.JumpToClosedArguments();
}
break;
}
return null;
}
private CssKeyframeRule CreateKeyframeRule(IEnumerator<CssToken> tokens)
{
CssKeyframeRule cssKeyframeRule = new CssKeyframeRule();
cssKeyframeRule.Key = tokens.InKeyframeText();
FillDeclarations(cssKeyframeRule.Style, tokens);
if (cssKeyframeRule.Key == null)
return null;
return cssKeyframeRule;
}
private MediaList InMediaList(IEnumerator<CssToken> tokens)
{
MediaList mediaList = new MediaList();
do {
CssMedium cssMedium = InMediaValue(tokens);
if (cssMedium == null)
break;
mediaList.Add(cssMedium);
} while (tokens.Current.Type == CssTokenType.Comma && tokens.MoveNext());
if (tokens.Current.Type != CssTokenType.CurlyBracketOpen) {
if (tokens.Current.Type == CssTokenType.RoundBracketClose)
tokens.MoveNext();
if (tokens.Current.Type == CssTokenType.CurlyBracketOpen)
tokens.MoveNext();
tokens.JumpToEndOfDeclaration();
} else if (mediaList.Length == 0 && tokens.MoveNext()) {
tokens.JumpToEndOfDeclaration();
}
return mediaList;
}
private CssMedium InMediaValue(IEnumerator<CssToken> tokens)
{
CssMedium medium = tokens.GetMedium();
CssToken current = tokens.Current;
if (current.Type == CssTokenType.Ident) {
medium.Type = current.Data;
if (!tokens.MoveNext())
return medium;
current = tokens.Current;
if (current.Type != CssTokenType.Ident || string.Compare(current.Data, Keywords.And, StringComparison.OrdinalIgnoreCase) != 0 || !tokens.MoveNext())
return medium;
}
do {
if (tokens.Current.Type != CssTokenType.RoundBracketOpen)
return null;
if (!tokens.MoveNext())
return medium;
Tuple<string, ICssValue> constraint = GetConstraint(tokens);
if (constraint == null || tokens.Current.Type != CssTokenType.RoundBracketClose || !medium.AddConstraint(constraint.Item1, constraint.Item2))
return null;
if (!tokens.MoveNext())
return medium;
current = tokens.Current;
} while (current.Type == CssTokenType.Ident && string.Compare(current.Data, Keywords.And, StringComparison.OrdinalIgnoreCase) == 0 && tokens.MoveNext());
return medium;
}
private Tuple<string, ICssValue> GetConstraint(IEnumerator<CssToken> tokens)
{
CssToken current = tokens.Current;
if (current.Type != CssTokenType.Ident) {
tokens.JumpToClosedArguments();
return null;
}
value.Reset();
string data = current.Data;
tokens.MoveNext();
current = tokens.Current;
if (current.Type == CssTokenType.Colon) {
tokenizer.IgnoreWhitespace = false;
tokens.MoveNext();
while (GetSingleValue(tokens) && tokens.Current.Type != CssTokenType.RoundBracketClose) {
}
tokenizer.IgnoreWhitespace = true;
}
return Tuple.Create(data, value.ToValue());
}
private ICssValue InValue(IEnumerator<CssToken> tokens)
{
tokenizer.IgnoreWhitespace = false;
value.Reset();
while (GetSingleValue(tokens)) {
}
tokenizer.IgnoreWhitespace = true;
return value.ToValue();
}
private bool GetSingleValue(IEnumerator<CssToken> tokens)
{
CssToken current = tokens.Current;
switch (current.Type) {
case CssTokenType.Percentage:
case CssTokenType.Dimension:
return TakeValue(((CssUnitToken)current).ToUnit(), tokens);
case CssTokenType.Hash:
return TakeValue(GetColorFromHexValue(current.Data), tokens);
case CssTokenType.Delim:
return GetValueFromDelim(current.Data[0], tokens);
case CssTokenType.Ident:
value.AddValue(current.ToIdentifier());
return tokens.MoveNext();
case CssTokenType.String:
value.AddValue(new CssString(current.Data));
return tokens.MoveNext();
case CssTokenType.Url:
value.AddValue(new CssUrl(current.Data));
return tokens.MoveNext();
case CssTokenType.Number:
value.AddValue(((CssNumberToken)current).ToNumber());
return tokens.MoveNext();
case CssTokenType.Function:
return GetValueFunction(tokens);
case CssTokenType.Comma:
value.NextArgument();
return tokens.MoveNext();
case CssTokenType.Whitespace:
return tokens.MoveNext();
default:
RaiseErrorOccurred(CssParseError.InputUnexpected);
value.IsFaulted = true;
break;
case CssTokenType.CurlyBracketClose:
case CssTokenType.Semicolon:
break;
}
return false;
}
private bool TakeValue(ICssValue val, IEnumerator<CssToken> tokens)
{
bool result = tokens.MoveNext();
if (val == null) {
value.IsFaulted = true;
return false;
}
value.AddValue(val);
return result;
}
private bool GetValueFromDelim(char delimiter, IEnumerator<CssToken> tokens)
{
if (delimiter == '#' && tokens.MoveNext())
return GetColorFromHexValue(tokens);
switch (delimiter) {
case '/':
value.AddValue(CssValue.Delimiter);
return tokens.MoveNext();
case '!':
if (tokens.MoveNext() && IsImportant(tokens))
break;
goto default;
default:
value.IsFaulted = true;
break;
}
return false;
}
private bool GetValueFunction(IEnumerator<CssToken> tokens)
{
string data = tokens.Current.Data;
value.AddFunction(data);
if (!tokens.MoveNext())
return false;
while (GetSingleValue(tokens) && tokens.Current.Type != CssTokenType.RoundBracketClose) {
}
value.CloseFunction();
return tokens.MoveNext();
}
private bool GetColorFromHexValue(IEnumerator<CssToken> tokens)
{
StringBuilder stringBuilder = Pool.NewStringBuilder();
bool result = true;
do {
CssToken current = tokens.Current;
if (current.Type != CssTokenType.Number && current.Type != CssTokenType.Dimension && current.Type != CssTokenType.Ident)
break;
string text = current.ToValue();
if (stringBuilder.Length + text.Length > 6)
break;
stringBuilder.Append(text);
} while (result = tokens.MoveNext());
Color? colorFromHexValue = GetColorFromHexValue(stringBuilder.ToPool());
if (colorFromHexValue.HasValue)
value.AddValue(colorFromHexValue.Value);
return result;
}
private static Color? GetColorFromHexValue(string hexColor)
{
if (Color.TryFromHex(hexColor, out Color color))
return color;
return null;
}
private CssSupportsRule.ICondition InCondition(IEnumerator<CssToken> tokens)
{
CssSupportsRule.ICondition condition = ExtractConditions(tokens);
if (condition == null) {
while (tokens.Current.Type != CssTokenType.CurlyBracketOpen && tokens.MoveNext()) {
}
}
return condition;
}
private CssSupportsRule.ICondition ExtractConditions(IEnumerator<CssToken> tokens)
{
CssSupportsRule.ICondition condition = ExtractCondition(tokens);
if (condition == null)
return null;
if (tokens.Current.Data.Equals(Keywords.And, StringComparison.OrdinalIgnoreCase))
return new CssSupportsRule.AndCondition(Conditions(tokens, condition, Keywords.And));
if (tokens.Current.Data.Equals(Keywords.Or, StringComparison.OrdinalIgnoreCase))
return new CssSupportsRule.OrCondition(Conditions(tokens, condition, Keywords.Or));
return condition;
}
private CssSupportsRule.ICondition ExtractCondition(IEnumerator<CssToken> tokens)
{
if (tokens.Current.Type == CssTokenType.RoundBracketOpen && tokens.MoveNext()) {
CssSupportsRule.ICondition condition = ExtractConditions(tokens);
if (condition != null)
condition = new CssSupportsRule.GroupCondition(condition);
else if (tokens.Current.Type == CssTokenType.Ident) {
condition = DeclCondition(tokens);
}
if (tokens.Current.Type == CssTokenType.RoundBracketClose && tokens.MoveNext())
return condition;
} else if (tokens.Current.Data.Equals(Keywords.Not, StringComparison.OrdinalIgnoreCase) && tokens.MoveNext()) {
CssSupportsRule.ICondition condition2 = ExtractCondition(tokens);
if (condition2 != null)
return new CssSupportsRule.NotCondition(condition2);
}
return null;
}
private CssSupportsRule.ICondition DeclCondition(IEnumerator<CssToken> tokens)
{
string data = tokens.Current.Data;
CssStyleDeclaration cssStyleDeclaration = new CssStyleDeclaration((string)null);
CssProperty cssProperty = Factory.Properties.Create(data, cssStyleDeclaration);
if (cssProperty == null)
cssProperty = new CssUnknownProperty(data, cssStyleDeclaration);
if (!tokens.MoveNext() || tokens.Current.Type != CssTokenType.Colon || !tokens.MoveNext())
return null;
value.Reset();
while (GetSingleValue(tokens) && tokens.Current.Type != CssTokenType.RoundBracketClose) {
}
ICssValue cssValue = value.ToValue();
if (cssValue == null)
return null;
if (cssProperty.IsImportant = IsImportant(tokens))
tokens.MoveNext();
return new CssSupportsRule.DeclarationCondition(cssProperty, cssValue);
}
private IEnumerable<CssSupportsRule.ICondition> Conditions(IEnumerator<CssToken> tokens, CssSupportsRule.ICondition start, string connector)
{
yield return start;
while (tokens.MoveNext()) {
CssSupportsRule.ICondition condition = ExtractCondition(tokens);
if (condition == null)
break;
yield return condition;
if (!tokens.Current.Data.Equals(connector, StringComparison.OrdinalIgnoreCase))
break;
}
}
private void Kernel()
{
IEnumerator<CssToken> enumerator = tokenizer.Tokens.GetEnumerator();
while (enumerator.MoveNext()) {
CssRule cssRule = CreateRule(enumerator);
if (cssRule != null)
sheet.Rules.Add(cssRule, sheet, null);
}
}
private async Task<ICssStyleSheet> KernelAsync(CancellationToken cancelToken)
{
TextSource source = sheet.Source;
IEnumerator<CssToken> tokens = tokenizer.Tokens.GetEnumerator();
while (true) {
if (source.Length - source.Index < 1024) {
ConfiguredTaskAwaitable val = AwaitExtensions.ConfigureAwait(source.Prefetch(8192, cancelToken), false);
ConfiguredTaskAwaiter val2 = val.GetAwaiter();
if (!val2.get_IsCompleted()) {
await val2;
ConfiguredTaskAwaiter val3 = default(ConfiguredTaskAwaiter);
val2 = val3;
val3 = default(ConfiguredTaskAwaiter);
}
val2.GetResult();
val2 = default(ConfiguredTaskAwaiter);
}
if (!tokens.MoveNext())
break;
CssRule cssRule = CreateRule(tokens);
if (cssRule != null)
sheet.Rules.Add(cssRule, sheet, null);
}
return sheet;
}
private void FillRules(CssGroupingRule parentRule, IEnumerator<CssToken> tokens)
{
while (tokens.MoveNext() && tokens.Current.Type != CssTokenType.CurlyBracketClose) {
CssRule cssRule = CreateRule(tokens);
if (cssRule != null)
parentRule.Rules.Add(cssRule, sheet, parentRule);
}
}
private void FillRules(CssKeyframesRule parentRule, IEnumerator<CssToken> tokens)
{
while (tokens.MoveNext() && tokens.Current.Type != CssTokenType.CurlyBracketClose) {
CssKeyframeRule cssKeyframeRule = CreateKeyframeRule(tokens);
if (cssKeyframeRule != null)
parentRule.Rules.Add(cssKeyframeRule, sheet, parentRule);
}
}
private void FillDeclarations(CssStyleDeclaration style, IEnumerator<CssToken> tokens)
{
while (tokens.MoveNext() && tokens.Current.Type != CssTokenType.CurlyBracketClose) {
Declaration(tokens, style);
if (tokens.Current.Type == CssTokenType.CurlyBracketClose)
break;
}
}
public static ISelector ParseSelector(string selectorText)
{
IEnumerable<CssToken> tokens = new CssTokenizer(new TextSource(selectorText), null) {
IgnoreComments = true
}.Tokens;
CssSelectorConstructor cssSelectorConstructor = Pool.NewSelectorConstructor();
foreach (CssToken item in tokens) {
cssSelectorConstructor.Apply(item);
}
return cssSelectorConstructor.ToPool();
}
public static IKeyframeSelector ParseKeyText(string keyText, IConfiguration configuration = null)
{
IEnumerator<CssToken> enumerator = new CssParser(keyText, configuration ?? Configuration.Default).tokenizer.Tokens.GetEnumerator();
if (!enumerator.MoveNext())
return null;
KeyframeSelector result = enumerator.InKeyframeText();
if (enumerator.MoveNext())
result = null;
return result;
}
public static ICssStyleSheet ParseStyleSheet(string stylesheet, IConfiguration configuration = null)
{
return new CssParser(stylesheet, configuration ?? Configuration.Default).Parse();
}
public static ICssValue ParseValue(string valueText, IConfiguration configuration = null)
{
CssParser cssParser = new CssParser(valueText, configuration ?? Configuration.Default);
IEnumerator<CssToken> enumerator = cssParser.tokenizer.Tokens.GetEnumerator();
if (!enumerator.MoveNext())
return null;
ICssValue result = cssParser.InValue(enumerator);
if (enumerator.MoveNext())
result = null;
return result;
}
internal static CssRule ParseRule(string ruleText, IConfiguration configuration = null)
{
CssParser cssParser = new CssParser(ruleText, configuration ?? Configuration.Default);
IEnumerator<CssToken> enumerator = cssParser.tokenizer.Tokens.GetEnumerator();
if (!enumerator.MoveNext())
return null;
CssRule result = cssParser.CreateRule(enumerator);
if (enumerator.MoveNext())
result = null;
return result;
}
internal static CssStyleDeclaration ParseDeclarations(string declarations, IConfiguration configuration = null)
{
CssStyleDeclaration cssStyleDeclaration = new CssStyleDeclaration((string)null);
AppendDeclarations(cssStyleDeclaration, declarations, configuration);
return cssStyleDeclaration;
}
internal static CssProperty ParseDeclaration(string declarationText, IConfiguration configuration = null)
{
CssParser cssParser = new CssParser(declarationText, configuration ?? Configuration.Default);
IEnumerator<CssToken> enumerator = cssParser.tokenizer.Tokens.GetEnumerator();
if (!enumerator.MoveNext())
return null;
CssProperty result = cssParser.Declaration(enumerator, new CssStyleDeclaration((string)null));
if (enumerator.MoveNext())
result = null;
return result;
}
internal static IEnumerable<CssMedium> ParseMediaList(string mediaText, IConfiguration configuration = null)
{
CssParser parser = new CssParser(mediaText, configuration);
IEnumerator<CssToken> tokens = parser.tokenizer.Tokens.GetEnumerator();
if (tokens.MoveNext()) {
do {
CssMedium cssMedium = parser.InMediaValue(tokens);
if (cssMedium == null)
break;
yield return cssMedium;
} while (tokens.MoveNext());
}
if (tokens.MoveNext())
throw new DomException(DomError.Syntax);
}
internal static CssSupportsRule.ICondition ParseCondition(string conditionText, IConfiguration configuration = null)
{
CssParser cssParser = new CssParser(conditionText, configuration ?? Configuration.Default);
IEnumerator<CssToken> enumerator = cssParser.tokenizer.Tokens.GetEnumerator();
if (!enumerator.MoveNext())
return null;
CssSupportsRule.ICondition result = cssParser.InCondition(enumerator);
if (enumerator.MoveNext())
result = null;
return result;
}
internal static IEnumerable<Tuple<CssDocumentRule.DocumentFunction, string>> ParseDocumentRules(string source, IConfiguration configuration = null)
{
CssParser cssParser = new CssParser(source, configuration);
IEnumerator<CssToken> enumerator = cssParser.tokenizer.Tokens.GetEnumerator();
if (!enumerator.MoveNext())
return Enumerable.Empty<Tuple<CssDocumentRule.DocumentFunction, string>>();
return cssParser.InDocumentFunctions(enumerator);
}
internal static CssValueList ParseValueList(string source, IConfiguration configuration = null)
{
CssParser cssParser = new CssParser(source, configuration);
IEnumerator<CssToken> enumerator = cssParser.tokenizer.Tokens.GetEnumerator();
ICssValue cssValue = enumerator.MoveNext() ? cssParser.InValue(enumerator) : null;
CssValueList cssValueList = cssValue as CssValueList;
if (cssValueList == null) {
cssValueList = new CssValueList();
if (cssValue != null)
cssValueList.Add(cssValue);
}
for (int i = 0; i < cssValueList.Length; i++) {
if (cssValueList[i] == CssValue.Separator) {
for (int num = cssValueList.Length - 1; num >= i; num--) {
cssValueList.RemoveAt(num);
}
break;
}
}
return cssValueList;
}
internal static CssMedium ParseMedium(string source, IConfiguration configuration = null)
{
CssParser cssParser = new CssParser(source, configuration);
IEnumerator<CssToken> enumerator = cssParser.tokenizer.Tokens.GetEnumerator();
if (enumerator.MoveNext()) {
CssMedium result = cssParser.InMediaValue(enumerator);
if (enumerator.MoveNext())
throw new DomException(DomError.Syntax);
return result;
}
return null;
}
internal static List<CssValueList> ParseMultipleValues(string source, IConfiguration configuration = null)
{
CssParser cssParser = new CssParser(source, configuration);
IEnumerator<CssToken> enumerator = cssParser.tokenizer.Tokens.GetEnumerator();
object cssValue2;
if (!enumerator.MoveNext()) {
ICssValue cssValue = new CssValueList();
cssValue2 = cssValue;
} else
cssValue2 = cssParser.InValue(enumerator);
ICssValue cssValue3 = (ICssValue)cssValue2;
CssValueList cssValueList = cssValue3 as CssValueList;
if (cssValueList == null) {
cssValueList = new CssValueList();
if (cssValue3 != null)
cssValueList.Add(cssValue3);
}
return cssValueList.ToList();
}
internal static CssKeyframeRule ParseKeyframeRule(string rule, IConfiguration configuration = null)
{
CssParser cssParser = new CssParser(rule, configuration);
IEnumerator<CssToken> enumerator = cssParser.tokenizer.Tokens.GetEnumerator();
if (!enumerator.MoveNext())
return new CssKeyframeRule();
return cssParser.CreateKeyframeRule(enumerator);
}
internal static void AppendDeclarations(CssStyleDeclaration list, string declarations, IConfiguration configuration = null)
{
CssParser cssParser = new CssParser(declarations, configuration ?? Configuration.Default);
IEnumerator<CssToken> enumerator = cssParser.tokenizer.Tokens.GetEnumerator();
cssParser.FillDeclarations(list, enumerator);
}
private void RaiseErrorOccurred(CssParseError code)
{
tokenizer.RaiseErrorOccurred(code);
}
}
}