예제 #1
0
        /// <summary>Reads the properties for this style block from the lexer.
        /// Essentially treats it like a set of properties only. Terminated by }, null or &gt;.</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;
                }
            }
        }
예제 #2
0
        /// <summary>Attempts to handle the given lexer with this units set.</summary>
        public Css.Value Handle(CssLexer lexer, bool removeAll)
        {
            // By peeking, get as far as we can until a delim of any kind is reached, or we can't go any further.
            // e.g. 41px*50% - the first will terminate successfully at the x.

            // Note that we know the current peek matches character.
            CssUnitHandlers handler = this;

            int currentIndex = 1;

            while (true)
            {
                // Get the char:
                char letter = lexer.Peek(currentIndex);
                currentIndex++;

                // Got a handler for it?
                if (handler.Handlers == null)
                {
                    // Nope! handler.Value, if there is one, is the furthest we can go.

                    break;
                }

                int handlerSetCount = handler.Handlers.Count;

                // Linear scan is faster than a hashtable here.
                for (int i = 0; i < handlerSetCount; i++)
                {
                    if (handler.Handlers[i].Character == letter)
                    {
                        // Got it! Keep going.
                        handler = handler.Handlers[i];
                        goto NextLetter;
                    }
                }

                // No letter matches. Stop there.
                break;

NextLetter:
                continue;
            }

            if (handler.Value != null)
            {
                // Read off the amount we read now.

                int start = 2;

                if (removeAll)
                {
                    start = 1;
                }

                for (int i = start; i < currentIndex; i++)
                {
                    lexer.Read();
                }
            }

            return(handler.Value);
        }