private static bool TryParseSimpleSelector(CssStringStreamReader reader, out CssSimpleSelector selector) { selector = null; reader.SkipWhitespaceAndComments(); switch (reader.CurrentChar) { case '#': reader.Advance(); return (reader.TryReadIdentifier(out var id) && TryParseSimpleSelector(reader, CssSimpleSelectorType.IdSelector, new CssQualifiedName(id), out selector)); case '.': reader.Advance(); return (reader.TryReadIdentifier(out var className) && TryParseSimpleSelector(reader, CssSimpleSelectorType.ClassSelector, new CssQualifiedName(className), out selector)); case '*': reader.Advance(); return(TryParseUniversalSelector(reader, out selector)); case '[': case ':': return(TryParseUniversalSelector(reader, out selector)); default: return (reader.TryReadQualifiedName(out var typeName) && TryParseSimpleSelector(reader, CssSimpleSelectorType.TypeSelector, typeName, out selector)); } }
private static bool TryParseCompoundSelector(CssStringStreamReader reader, out CssCompoundSelector selector) { var simpleSelectors = new List <CssSimpleSelector>(); reader.SkipWhitespaceAndComments(); while (!reader.IsEndOfStream) { if (!TryParseSimpleSelector(reader, out var simpleSelector)) { break; } simpleSelectors.Add(simpleSelector); if (IsCombinatorChar(reader.CurrentChar)) { break; } } if (simpleSelectors.Count == 0) { selector = null; return(false); } selector = new CssCompoundSelector(simpleSelectors.ToArray()); return(true); }
private static CssAttributeSelector[] ParseAttributeSelectors(CssStringStreamReader reader) { var selectors = new List <CssAttributeSelector>(); while (reader.CurrentChar == '[') { reader.Advance(); if (!reader.TryReadIdentifier(out var name) || !reader.TryReadCssAttributeSelectorOperation(out var op)) { return(null); } var value = string.Empty; var wasString = false; if (op != CssAttributeSelectorOperation.Has) { if (!reader.TryReadIdentifierOrString(out value, out wasString)) { return(null); } } reader.SkipWhitespaceAndComments(); var explicitIgnoreCase = reader.CurrentChar == 'i'; if (explicitIgnoreCase) { reader.Advance(); reader.SkipWhitespaceAndComments(); } if (reader.CurrentChar != ']') { return(null); } reader.Advance(); var valueType = wasString ? CssAttributeSelectorValueType.String : CssAttributeSelectorValueType.Identifier; selectors.Add(new CssAttributeSelector(name, value, op, valueType, explicitIgnoreCase)); } return(selectors.ToArray()); }
/// <summary> /// Tries to parse a collection of properties (name value pairs, e.g. 'fill:#000') of a style body /// </summary> public static bool TryParseStyleRuleBodyProperties(CssStringStreamReader reader, out Dictionary <string, CssStylePropertyValue> properties) { properties = new Dictionary <string, CssStylePropertyValue>(); reader.SkipWhitespaceAndComments(); var builder = new StringBuilder(); while (!reader.IsEndOfStream && reader.CurrentChar != '}') { if (!reader.TryReadIdentifier(out var name)) { return(false); } reader.SkipWhitespaceAndComments(); if (!reader.Read(':')) { return(false); } reader.SkipWhitespaceAndComments(); while (reader.CurrentChar != ';' && reader.CurrentChar != '}' && !reader.IsEndOfStream) { builder.Append(reader.CurrentChar); reader.Advance(); } properties[name] = new CssStylePropertyValue(builder.ToString()); builder.Clear(); if (reader.CurrentChar == ';') { reader.Read(';'); } reader.SkipWhitespaceAndComments(); } return(true); }
public static bool TryParseRules(CssStringStreamReader reader, out CssStyleRulesList rules) { rules = new CssStyleRulesList(); reader.SkipWhitespaceAndComments(); while (!reader.IsEndOfStream) { if (!TryParseSelectorList(reader, out var selectors) || !reader.SkipWhitespaceAndComments() || !reader.Read('{') || !TryParseStyleRuleBodyProperties(reader, out var properties) || !reader.SkipWhitespaceAndComments() || !reader.Read('}')) { return(false); } rules.Add(new CssStyleRule(selectors, properties)); reader.SkipWhitespaceAndComments(); } return(true); }
public static bool TryParseSelectorList(CssStringStreamReader reader, out CssSelectorList selectors) { selectors = new CssSelectorList(); while (!reader.IsEndOfStream) { if (!TryParseComplexSelector(reader, out var complex)) { break; } selectors.Add(Flatten(complex)); reader.SkipWhitespaceAndComments(); if (reader.CurrentChar != ',') { break; } reader.Advance(); } return(selectors.Count > 0); }