예제 #1
0
        public Directive KeyFrameBlock(Parser parser, string name, string identifier, int index)
        {
            if (!parser.Tokenizer.Match('{'))
            {
                return(null);
            }

            NodeList     keyFrames       = new NodeList();
            const string identifierRegEx = "from|to|([0-9]+%)";

            while (true)
            {
                GatherComments(parser);

                string keyFrameIdentifier;
                var    keyFrameIdentifier1 = parser.Tokenizer.Match(identifierRegEx);

                if (!keyFrameIdentifier1)
                {
                    break;
                }

                keyFrameIdentifier = keyFrameIdentifier1.Value;

                if (parser.Tokenizer.Match(","))
                {
                    var keyFrameIdentifier2 = parser.Tokenizer.Match(identifierRegEx);

                    if (!keyFrameIdentifier2)
                    {
                        throw new ParsingException("Comma in @keyframe followed by unknown identifier", parser.Tokenizer.Location.Index);
                    }

                    keyFrameIdentifier += "," + keyFrameIdentifier2;
                }

                var preComments = GatherAndPullComments(parser);

                var block = Block(parser);

                if (block == null)
                {
                    throw new ParsingException("Expected css block after key frame identifier", parser.Tokenizer.Location.Index);
                }

                block.PreComments  = preComments;
                block.PostComments = GatherAndPullComments(parser);

                keyFrames.Add(NodeProvider.KeyFrame(keyFrameIdentifier, block, parser.Tokenizer.Location.Index));
            }

            if (!parser.Tokenizer.Match('}'))
            {
                throw new ParsingException("Expected start, finish, % or '}'", parser.Tokenizer.Location.Index);
            }

            return(NodeProvider.Directive(name, identifier, keyFrames, index));
        }
예제 #2
0
        public Directive Media(Parser parser)
        {
            if (!parser.Tokenizer.Match("@media"))
            {
                return(null);
            }

            var index = parser.Tokenizer.Location.Index;

            var features = MediaFeatures(parser);

            var preRulesComments = GatherAndPullComments(parser);

            var rules = Block(parser);

            if (rules != null)
            {
                rules.PreComments = preRulesComments;
                return(NodeProvider.Directive("@media", rules, features, index));
            }

            throw new ParsingException("@media block with unrecognised format", index);
        }
예제 #3
0
        //
        // A CSS Directive
        //
        //     @charset "utf-8";
        //
        public Directive Directive(Parser parser)
        {
            if (parser.Tokenizer.CurrentChar != '@')
            {
                return(null);
            }

            var import = Import(parser);

            if (import)
            {
                return(import);
            }

            GatherComments(parser);

            var index = parser.Tokenizer.Location.Index;

            var      name = parser.Tokenizer.MatchString(@"@[-a-z]+");
            bool     hasIdentifier = false, hasBlock = false, isKeyFrame = false;
            NodeList rules, preRulesComments = null, preComments = null;
            string   identifierRegEx       = @"[^{]+";
            string   nonVendorSpecificName = name;

            if (name.StartsWith("@-") && name.IndexOf('-', 2) > 0)
            {
                nonVendorSpecificName = "@" + name.Substring(name.IndexOf('-', 2) + 1);
            }

            switch (nonVendorSpecificName)
            {
            case "@font-face":
                hasBlock = true;
                break;

            case "@page":
            case "@document":
            case "@media":
            case "@supports":
                hasBlock      = true;
                hasIdentifier = true;
                break;

            case "@top-left":
            case "@top-left-corner":
            case "@top-center":
            case "@top-right":
            case "@top-right-corner":
            case "@bottom-left":
            case "@bottom-left-corner":
            case "@bottom-center":
            case "@bottom-right":
            case "@bottom-right-corner":
            case "@left-top":
            case "@left-middle":
            case "@left-bottom":
            case "@right-top":
            case "@right-middle":
            case "@right-bottom":
                hasBlock = true;
                break;

            case "@keyframes":
                isKeyFrame    = true;
                hasIdentifier = true;
                break;
            }

            string identifier = "";

            preComments = PullComments();

            if (hasIdentifier)
            {
                GatherComments(parser);

                var identifierRegResult = parser.Tokenizer.MatchAny(identifierRegEx);
                if (identifierRegResult != null)
                {
                    identifier = identifierRegResult.Value.Trim();
                }
            }

            preRulesComments = GatherAndPullComments(parser);

            if (hasBlock)
            {
                rules = Block(parser);

                if (rules != null)
                {
                    rules.PreComments = preRulesComments;
                    return(NodeProvider.Directive(name, identifier, rules, index));
                }
            }
            else if (isKeyFrame)
            {
                var keyframeblock = KeyFrameBlock(parser, name, identifier, index);
                keyframeblock.PreComments = preRulesComments;
                return(keyframeblock);
            }
            else
            {
                Node value;
                if (value = Expression(parser))
                {
                    value.PreComments  = preRulesComments;
                    value.PostComments = GatherAndPullComments(parser);
                    if (parser.Tokenizer.Match(';'))
                    {
                        var directive = NodeProvider.Directive(name, value, index);
                        directive.PreComments = preComments;
                        return(directive);
                    }
                }
            }

            return(null);
        }