/// <summary>Keeps reading selectors and their properties until a > or the end of the css is reached.</summary> /// <param name="css">The css text to parse.</param> public void ParseCss(string css) { CssLexer lexer = new CssLexer(css, ownerNode); lexer.Sheet = this; while (lexer.Peek() != '\0') { // Read a selector block: Rule[] set; Rule rule = lexer.ReadRules(out set); // Add: Add(rule, set, true); // Skip any junk. // This is done down here too to avoid creating a blank selector. lexer.SkipJunk(); } }
/// <summary>Reads the properties for this style block from the lexer. /// Essentially treats it like a set of properties only. Terminated by }, null or >.</summary> public void LoadProperties(CssLexer lexer, OnReadProperty onPropertyRead) { // Read the properties inside a selectors block. lexer.SkipJunk(); char current = lexer.Peek(); bool readPropertyName = true; bool isVariable = false; int dashCount = 0; StringBuilder propertyName = new StringBuilder(); while (current != '\0' && current != '<' && current != '}') { // Read the property name: if (readPropertyName) { // Hash, open quote or {? If so, the value does not start with a colon. CssUnitHandlers set; if (CssUnits.AllStart.TryGetValue(current, out set)) { // Match on the pretext: Value value = set.Handle(lexer, false); if (value != null) { // Read the value (using the global instance): value = value.ReadStartValue(lexer); // Call ready: value.OnValueReady(lexer); // Get the property name: string pName = propertyName.ToString().ToLower().Trim(); propertyName.Length = 0; // Trigger OPR (note that it's triggered all the time): int status = 0; if (onPropertyRead != null) { status = onPropertyRead(this, pName, value); } if (status == 0) { // Map property to a function: CssProperty property = CssProperties.Get(pName); if (property != null) { // Apply, taking aliases into account: property.OnReadValue(this, value); } } // Read off any junk: lexer.SkipJunk(); // Update current: current = lexer.Peek(); continue; } } if (current == ':') { // Done reading the property: readPropertyName = false; dashCount = 0; // Note that we don't need to skip junk as ReadValue will internally anyway. } else if (current == '-' && propertyName.Length == 0) { dashCount++; if (dashCount == 2) { isVariable = true; propertyName.Length = 0; } else { propertyName.Append(current); } } else { propertyName.Append(current); } // Read it off: lexer.Read(); // And take a look at what's next: current = lexer.Peek(); } else { // Read the value: Value value = lexer.ReadValue(); string pName = propertyName.ToString().ToLower().Trim(); propertyName.Length = 0; if (isVariable) { // CSS variable. isVariable = false; // Add to lexer set: lexer.AddVariable(pName, value); } else { // Trigger OPR (note that it's triggered all the time): int status = 0; if (onPropertyRead != null) { status = onPropertyRead(this, pName, value); } if (status == 0) { // Map property to a function: CssProperty property = CssProperties.Get(pName); if (property != null) { // Apply, taking aliases into account: property.OnReadValue(this, value); } } } // ReadValue might actually read off the } in malformed CSS. // Make sure it didn't just do that: if (lexer.Input[lexer.Position - 1] == '}') { lexer.Position--; } // Read off any junk: lexer.SkipJunk(); // Update current: current = lexer.Peek(); // Go into property reading mode: readPropertyName = true; } } }