protected virtual void ParseName(ItemFactory itemFactory, ITextProvider text, TokenStream tokens)
        {
            if (tokens.CurrentToken.TokenType == CssTokenType.Function &&
                tokens.CurrentToken.Start == Colon.AfterEnd)
            {
                if (TextRange.CompareDecoded(tokens.CurrentToken.Start, tokens.CurrentToken.Length, text, "not(", ignoreCase: true))
                {
                    Function = itemFactory.CreateSpecific <PseudoFunctionNot>(this);
                }
                else if (TextRange.CompareDecoded(tokens.CurrentToken.Start, tokens.CurrentToken.Length, text, "matches(", ignoreCase: true))
                {
                    Function = itemFactory.CreateSpecific <PseudoFunctionMatches>(this);
                }
                else
                {
                    Function = itemFactory.CreateSpecific <Function>(this);
                }

                Function.Parse(itemFactory, text, tokens);

                // Function name should be colorizer as pseudo-class
                Function.Context = CssClassifierContextCache.FromTypeEnum(CssClassifierContextType.PseudoClass);
                Function.FunctionName.Context = Function.Context;

                Children.Add(Function);
            }
            else
            {
                Children.AddParseError(ParseErrorType.PseudoClassNameMissing);
            }
        }
예제 #2
0
        public void CssTextRange_CompareDecoded()
        {
            for (int i = 0; i < 2; i++)
            {
#if !SUPPORT_ENCODED_CSS
                if (i == 0)
                {
                    continue;
                }
#endif
                // Try the same string with and without encoded/escaped chars
                string text = (i == 0)
                    ? @"@na\mes\70 ace \66 \o\o 'www.\'f\6F \o\'.com';"
                    : @"@namespace foo 'www.\'foo\'.com'";

                ITextProvider tp     = new StringTextProvider(text);
                TokenList     tokens = Helpers.MakeTokens(tp);

                Assert.AreEqual("@", TextRange.GetDecodedText(tokens[0].Start, tokens[0].Length, tp, forStringToken: false));
                Assert.AreEqual("namespace", TextRange.GetDecodedText(tokens[1].Start, tokens[1].Length, tp, forStringToken: false));
                Assert.AreEqual("foo", TextRange.GetDecodedText(tokens[2].Start, tokens[2].Length, tp, forStringToken: false));
                Assert.AreEqual(@"'www.'foo'.com'", TextRange.GetDecodedText(tokens[3].Start, tokens[3].Length, tp, forStringToken: false));

                Assert.IsTrue(TextRange.CompareDecoded(tokens[1].Start, tokens[1].Length, tp, "namespace", ignoreCase: false));
                Assert.IsFalse(TextRange.CompareDecoded(tokens[1].Start, tokens[1].Length, tp, "NAMEspace", ignoreCase: false));
                Assert.IsTrue(TextRange.CompareDecoded(tokens[1].Start, tokens[1].Length, tp, "NAMEspace", ignoreCase: true));
                Assert.IsFalse(TextRange.CompareDecoded(tokens[1].Start, tokens[1].Length, tp, "namespace-foobar", ignoreCase: true));
                Assert.IsFalse(TextRange.CompareDecoded(tokens[1].Start, tokens[1].Length, tp, "@namespace", ignoreCase: true));
                Assert.IsTrue(TextRange.CompareDecoded(tokens[2].Start, tokens[2].Length, tp, "foo", ignoreCase: false));

#if SUPPORT_ENCODED_CSS
                Assert.IsTrue(TextRange.CompareDecoded(tokens[3].Start, tokens[3].Length, tp, "'www.'FOO'.com'", ignoreCase: true));
#endif
            }
        }
예제 #3
0
        public override bool Parse(ItemFactory itemFactory, ITextProvider text, TokenStream tokens)
        {
            if (tokens.CurrentToken.TokenType == CssTokenType.Identifier &&
                TextRange.CompareDecoded(tokens.CurrentToken.Start, tokens.CurrentToken.Length, text, "and", true))
            {
                MediaCombineOperator = Children.AddCurrentAndAdvance(tokens, CssClassifierContextType.MediaCombineOperator);
            }

            if (tokens.CurrentToken.TokenType == CssTokenType.OpenFunctionBrace)
            {
                OpenFunctionBrace = Children.AddCurrentAndAdvance(tokens, CssClassifierContextType.FunctionBrace);
                ParseFeatureName(itemFactory, text, tokens);

                if (tokens.CurrentToken.TokenType == CssTokenType.Colon)
                {
                    Colon = Children.AddCurrentAndAdvance(tokens, CssClassifierContextType.Punctuation);
                }

                while (tokens.CurrentToken.TokenType != CssTokenType.CloseFunctionBrace &&
                       tokens.CurrentToken.TokenType != CssTokenType.OpenCurlyBrace &&
                       !tokens.CurrentToken.IsScopeBlocker())
                {
                    ParseNextValue(itemFactory, text, tokens);
                }

                if (tokens.CurrentToken.TokenType == CssTokenType.CloseFunctionBrace)
                {
                    CloseFunctionBrace = Children.AddCurrentAndAdvance(tokens, CssClassifierContextType.FunctionBrace);
                }
                else
                {
                    OpenFunctionBrace.AddParseError(ParseErrorType.CloseFunctionBraceMissing, ParseErrorLocation.AfterItem);
                }

                if ((Colon != null && Children[Children.Count - 1] == Colon) ||
                    (Colon != null && CloseFunctionBrace != null && Children.IndexOf(Colon) + 1 == Children.IndexOf(CloseFunctionBrace)))
                {
                    // There was nothing between the colon and close brace
                    Colon.AddParseError(ParseErrorType.PropertyValueMissing, ParseErrorLocation.AfterItem);
                }
            }

            if (MediaCombineOperator != null && OpenFunctionBrace == null)
            {
                MediaCombineOperator.AddParseError(ParseErrorType.MediaExpressionExpected, ParseErrorLocation.AfterItem);
            }

            return(Children.Count > 0);
        }
예제 #4
0
        public override bool Parse(ItemFactory itemFactory, ITextProvider text, TokenStream tokens)
        {
            if (tokens.CurrentToken.TokenType == CssTokenType.Comma)
            {
                Comma = Children.AddCurrentAndAdvance(tokens, CssClassifierContextType.Default);
            }

            if (tokens.CurrentToken.TokenType == CssTokenType.Identifier)
            {
                if (TextRange.CompareDecoded(tokens.CurrentToken.Start, tokens.CurrentToken.Length, text, "only", ignoreCase: true) ||
                    TextRange.CompareDecoded(tokens.CurrentToken.Start, tokens.CurrentToken.Length, text, "not", ignoreCase: true))
                {
                    Operation = Children.AddCurrentAndAdvance(tokens, CssClassifierContextType.MediaQueryOperation);
                }
            }

            if (tokens.CurrentToken.TokenType == CssTokenType.Identifier &&
                !IsMediaExpressionStart(text, tokens.CurrentToken))
            {
                MediaType = Children.AddCurrentAndAdvance(tokens, CssClassifierContextType.MediaType);
            }
            else if (tokens.CurrentToken.TokenType != CssTokenType.OpenFunctionBrace)
            {
                Children.AddParseError(ParseErrorType.MediaTypeMissing);
            }

            while (!tokens.CurrentToken.IsDirectiveTerminator() && tokens.CurrentToken.TokenType != CssTokenType.Comma)
            {
                if (IsMediaExpressionStart(text, tokens.CurrentToken))
                {
                    MediaExpression mx = itemFactory.CreateSpecific <MediaExpression>(this);
                    if (mx.Parse(itemFactory, text, tokens))
                    {
                        Expressions.Add(mx);
                        Children.Add(mx);
                    }
                    else
                    {
                        Children.AddUnknownAndAdvance(itemFactory, text, tokens, ParseErrorType.MediaExpressionExpected);
                    }
                }
                else
                {
                    Children.AddUnknownAndAdvance(itemFactory, text, tokens, ParseErrorType.UnexpectedMediaQueryToken);
                }
            }

            return(Children.Count > 0);
        }
예제 #5
0
        internal static bool IsMediaExpressionStart(ITextProvider text, CssToken token)
        {
            switch (token.TokenType)
            {
            case CssTokenType.OpenFunctionBrace:
                return(true);

            case CssTokenType.Identifier:
                if (TextRange.CompareDecoded(token.Start, token.Length, text, "and", true))
                {
                    return(true);
                }
                break;
            }

            return(false);
        }
예제 #6
0
        protected virtual void ParseBang(ItemFactory itemFactory, ITextProvider text, TokenStream tokens)
        {
            if (Bang == null)
            {
                Bang = Children.AddCurrentAndAdvance(tokens, CssClassifierContextType.Important);

                if (TextRange.CompareDecoded(tokens.CurrentToken.Start, tokens.CurrentToken.Length, text, "important", ignoreCase: true))
                {
                    Important = Children.AddCurrentAndAdvance(tokens, CssClassifierContextType.Important);
                }
                else
                {
                    Children.AddParseError(ParseErrorType.ImportantMissing);
                }
            }
            else
            {
                Children.AddUnknownAndAdvance(itemFactory, text, tokens, ParseErrorType.UnexpectedBangInProperty);
            }
        }
        public override bool Parse(ItemFactory itemFactory, ITextProvider text, TokenStream tokens)
        {
            switch (tokens.CurrentToken.TokenType)
            {
            case CssTokenType.Identifier:
                if (TextRange.CompareDecoded(tokens.CurrentToken.Start, tokens.CurrentToken.Length, text, "from", true))
                {
                    SelectorType = KeyFrameSelectorType.From;
                    Name         = Children.AddCurrentAndAdvance(tokens, null);
                }
                else if (TextRange.CompareDecoded(tokens.CurrentToken.Start, tokens.CurrentToken.Length, text, "to", true))
                {
                    SelectorType = KeyFrameSelectorType.To;
                    Name         = Children.AddCurrentAndAdvance(tokens, null);
                }
                break;

            case CssTokenType.Number:
                // Must be a percentage:
                if (tokens.Peek(1).TokenType == CssTokenType.Units &&
                    TextRange.Compare(tokens.Peek(1).Start, tokens.Peek(1).Length, text, "%", ignoreCase: false))
                {
                    UnitValue uv = new UnitValue();

                    if (uv.Parse(itemFactory, text, tokens))
                    {
                        SelectorType = KeyFrameSelectorType.Percentage;
                        Children.Add(uv);
                    }
                }
                break;
            }

            if (tokens.CurrentToken.TokenType == CssTokenType.Comma && Children.Count > 0)
            {
                Comma = Children.AddCurrentAndAdvance(tokens, CssClassifierContextType.Punctuation);
            }

            return(Children.Count > 0);
        }
예제 #8
0
        internal static Function ParseFunction(ComplexItem parent, ItemFactory itemFactory, ITextProvider text, TokenStream tokens)
        {
            Function fn;

            if (TextRange.CompareDecoded(tokens.CurrentToken.Start, tokens.CurrentToken.Length, text, "rgb(", ignoreCase: true))
            {
                fn = itemFactory.CreateSpecific <FunctionColor>(parent);
                ((FunctionColor)fn).ColorFunction = ColorFunctionType.Rgb;
            }
            else if (TextRange.CompareDecoded(tokens.CurrentToken.Start, tokens.CurrentToken.Length, text, "rgba(", ignoreCase: true))
            {
                fn = itemFactory.CreateSpecific <FunctionColor>(parent);
                ((FunctionColor)fn).ColorFunction = ColorFunctionType.Rgba;
            }
            else if (TextRange.CompareDecoded(tokens.CurrentToken.Start, tokens.CurrentToken.Length, text, "hsl(", ignoreCase: true))
            {
                fn = itemFactory.CreateSpecific <FunctionColor>(parent);
                ((FunctionColor)fn).ColorFunction = ColorFunctionType.Hsl;
            }
            else if (TextRange.CompareDecoded(tokens.CurrentToken.Start, tokens.CurrentToken.Length, text, "hsla(", ignoreCase: true))
            {
                fn = itemFactory.CreateSpecific <FunctionColor>(parent);
                ((FunctionColor)fn).ColorFunction = ColorFunctionType.Hsla;
            }
            else if (TextRange.CompareDecoded(tokens.CurrentToken.Start, tokens.CurrentToken.Length, text, "attr(", ignoreCase: true))
            {
                fn = itemFactory.CreateSpecific <FunctionAttr>(parent);
            }
            else if (TextRange.CompareDecoded(tokens.CurrentToken.Start, tokens.CurrentToken.Length, text, "calc(", ignoreCase: true))
            {
                fn = itemFactory.CreateSpecific <FunctionCalc>(parent);
            }
            else if (TextRange.CompareDecoded(tokens.CurrentToken.Start, tokens.CurrentToken.Length, text, "counter(", ignoreCase: true))
            {
                fn = itemFactory.CreateSpecific <FunctionCounter>(parent);
            }
            else if (TextRange.CompareDecoded(tokens.CurrentToken.Start, tokens.CurrentToken.Length, text, "expression(", ignoreCase: true))
            {
                fn = itemFactory.CreateSpecific <FunctionExpression>(parent);
            }
            else if (TextRange.CompareDecoded(tokens.CurrentToken.Start, tokens.CurrentToken.Length, text, "format(", ignoreCase: true))
            {
                fn = itemFactory.CreateSpecific <FunctionFormat>(parent);
            }
            else if (TextRange.CompareDecoded(tokens.CurrentToken.Start, tokens.CurrentToken.Length, text, "local(", ignoreCase: true))
            {
                fn = itemFactory.CreateSpecific <FunctionLocal>(parent);
            }
            else if (TextRange.CompareDecoded(tokens.CurrentToken.Start, tokens.CurrentToken.Length, text, "var(", ignoreCase: true))
            {
                fn = itemFactory.CreateSpecific <FunctionVar>(parent);
            }
            else
            {
                fn = itemFactory.CreateSpecific <Function>(parent);
            }

            if (fn != null && !fn.Parse(itemFactory, text, tokens))
            {
                fn = null;
            }

            return(fn);
        }
예제 #9
0
        internal static ParseItem ParseDirective(ComplexItem parent, ItemFactory itemFactory, ITextProvider text, TokenStream tokens)
        {
            Debug.Assert(tokens.CurrentToken.TokenType == CssTokenType.At);

            CssToken  atToken   = tokens.CurrentToken;
            CssToken  nameToken = tokens.Peek(1);
            ParseItem pi        = null;

            if (nameToken.TokenType == CssTokenType.At && AllowDoubleAt(text))
            {
                // Ignore the first @ in @@directive
                atToken   = nameToken;
                nameToken = tokens.Peek(2);
            }

            if (nameToken.TokenType == CssTokenType.Identifier &&
                nameToken.Start == atToken.AfterEnd)
            {
                if ("charset".Length == nameToken.Length && text.CompareTo(nameToken.Start, "charset", ignoreCase: false))
                {
                    // must be lowercase, and not encoded
                    pi = itemFactory.Create <CharsetDirective>(parent);
                }
                else if ("import".Length == nameToken.Length && text.CompareTo(nameToken.Start, "import", ignoreCase: true))
                {
                    pi = itemFactory.Create <ImportDirective>(parent);
                }
                else if ("page".Length == nameToken.Length && text.CompareTo(nameToken.Start, "page", ignoreCase: true))
                {
                    pi = itemFactory.Create <PageDirective>(parent);
                }
                else if ("media".Length == nameToken.Length && text.CompareTo(nameToken.Start, "media", ignoreCase: true))
                {
                    pi = itemFactory.Create <MediaDirective>(parent);
                }
                else if ("namespace".Length == nameToken.Length && text.CompareTo(nameToken.Start, "namespace", ignoreCase: true))
                {
                    // CSS3 Namespaces
                    // http://www.w3.org/TR/css3-namespace/
                    pi = itemFactory.Create <NamespaceDirective>(parent);
                }
                else if (TextRange.CompareDecoded(nameToken.Start, nameToken.Length, text, "keyframes", ignoreCase: true) ||
                         TextRange.CompareDecoded(nameToken.Start, nameToken.Length, text, "-moz-keyframes", ignoreCase: true) ||
                         TextRange.CompareDecoded(nameToken.Start, nameToken.Length, text, "-ms-keyframes", ignoreCase: true) ||
                         TextRange.CompareDecoded(nameToken.Start, nameToken.Length, text, "-o-keyframes", ignoreCase: true) ||
                         TextRange.CompareDecoded(nameToken.Start, nameToken.Length, text, "-webkit-keyframes", ignoreCase: true))
                {
                    // CSS3 Animations
                    // http://www.w3.org/TR/2009/WD-css3-animations-20090320/
                    pi = itemFactory.Create <KeyFramesDirective>(parent);
                }
                else if (TextRange.CompareDecoded(nameToken.Start, nameToken.Length, text, "font-face", ignoreCase: true))
                {
                    // CSS3 Webfonts
                    // http://www.w3.org/TR/2002/WD-css3-webfonts-20020802/#font-descriptions
                    pi = itemFactory.Create <FontFaceDirective>(parent);
                }
                else if (TextRange.CompareDecoded(nameToken.Start, nameToken.Length, text, "counter", ignoreCase: true))
                {
                    pi = itemFactory.Create <CounterDirective>(parent);
                }
                else if (TextRange.CompareDecoded(nameToken.Start, nameToken.Length, text, "viewport", ignoreCase: true))
                {
                    pi = itemFactory.Create <ViewportDirective>(parent);
                }
            }

            if (pi == null)
            {
                // some other stuff, like @top-center/left/top/middle... or @footnoote in CSS3
                pi = itemFactory.Create <UnknownDirective>(parent);
            }

            pi.Parse(itemFactory, text, tokens);

            return(pi);
        }
예제 #10
0
        public override bool Parse(ItemFactory itemFactory, ITextProvider text, TokenStream tokens)
        {
            if (tokens.CurrentToken.TokenType == CssTokenType.At)
            {
                ParseAtAndKeyword(itemFactory, text, tokens);

                // all lowercase per W3C BNF

                if (Keyword == null)
                {
                    Children.AddParseError(ParseErrorType.AtDirectiveNameMissing);
                }
                else if (TextRange.CompareDecoded(Keyword.Start, Keyword.Length, text, "top-left-corner", ignoreCase: false))
                {
                    DirectiveType = MarginDirectiveType.TopLeftCorner;
                }
                else if (TextRange.CompareDecoded(Keyword.Start, Keyword.Length, text, "top-left", ignoreCase: false))
                {
                    DirectiveType = MarginDirectiveType.TopLeft;
                }
                else if (TextRange.CompareDecoded(Keyword.Start, Keyword.Length, text, "top-center", ignoreCase: false))
                {
                    DirectiveType = MarginDirectiveType.TopCenter;
                }
                else if (TextRange.CompareDecoded(Keyword.Start, Keyword.Length, text, "top-right", ignoreCase: false))
                {
                    DirectiveType = MarginDirectiveType.TopRight;
                }
                else if (TextRange.CompareDecoded(Keyword.Start, Keyword.Length, text, "top-right-corner", ignoreCase: false))
                {
                    DirectiveType = MarginDirectiveType.TopRightCorner;
                }
                else if (TextRange.CompareDecoded(Keyword.Start, Keyword.Length, text, "bottom-left-corner", ignoreCase: false))
                {
                    DirectiveType = MarginDirectiveType.BottomLeftCorner;
                }
                else if (TextRange.CompareDecoded(Keyword.Start, Keyword.Length, text, "bottom-left", ignoreCase: false))
                {
                    DirectiveType = MarginDirectiveType.BottomLeft;
                }
                else if (TextRange.CompareDecoded(Keyword.Start, Keyword.Length, text, "bottom-center", ignoreCase: false))
                {
                    DirectiveType = MarginDirectiveType.BottomCenter;
                }
                else if (TextRange.CompareDecoded(Keyword.Start, Keyword.Length, text, "bottom-right", ignoreCase: false))
                {
                    DirectiveType = MarginDirectiveType.BottomRight;
                }
                else if (TextRange.CompareDecoded(Keyword.Start, Keyword.Length, text, "bottom-right-corner", ignoreCase: false))
                {
                    DirectiveType = MarginDirectiveType.BottomRightCorner;
                }
                else if (TextRange.CompareDecoded(Keyword.Start, Keyword.Length, text, "left-top", ignoreCase: false))
                {
                    DirectiveType = MarginDirectiveType.LeftTop;
                }
                else if (TextRange.CompareDecoded(Keyword.Start, Keyword.Length, text, "left-middle", ignoreCase: false))
                {
                    DirectiveType = MarginDirectiveType.LeftMiddle;
                }
                else if (TextRange.CompareDecoded(Keyword.Start, Keyword.Length, text, "left-bottom", ignoreCase: false))
                {
                    DirectiveType = MarginDirectiveType.LeftBottom;
                }
                else if (TextRange.CompareDecoded(Keyword.Start, Keyword.Length, text, "right-top", ignoreCase: false))
                {
                    DirectiveType = MarginDirectiveType.RightTop;
                }
                else if (TextRange.CompareDecoded(Keyword.Start, Keyword.Length, text, "right-middle", ignoreCase: false))
                {
                    DirectiveType = MarginDirectiveType.RightMiddle;
                }
                else if (TextRange.CompareDecoded(Keyword.Start, Keyword.Length, text, "right-bottom", ignoreCase: false))
                {
                    DirectiveType = MarginDirectiveType.RightBottom;
                }
                else
                {
                    DirectiveType = MarginDirectiveType.Unknown;
                }
            }

            RuleBlock = itemFactory.CreateSpecific <RuleBlock>(this);

            if (!ParseBlock(RuleBlock, itemFactory, text, tokens))
            {
                RuleBlock = null;
            }

            return(Children.Count > 0);
        }