AngleSharp by Florian Rappl

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

 CssParser

public sealed class 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); } } }