コード例 #1
0
        private static CSSRule ParseFontFace(AtRule rule, ref string OriginalCss)
        {
            CSSFontFaceRule fontrule = new CSSFontFaceRule();

            int startindex     = 0;
            int endindex       = 0;
            int endselectindex = -1;

            foreach (var item in rule.prelude)
            {
                if (startindex == 0)
                {
                    startindex = item.startindex;
                }

                if (item.endindex > endselectindex)
                {
                    endselectindex = item.endindex;
                }
            }


            CSSStyleDeclaration style = ParseDeclarations(rule.block, ref endindex, ref OriginalCss);

            fontrule.style      = style;
            fontrule.StartIndex = startindex;
            fontrule.EndIndex   = endindex;

            fontrule.EndSelectorIndex = endselectindex - fontrule.StartIndex + 1;

            return(fontrule);
        }
コード例 #2
0
        private static CSSRule ParseAtRule(AtRule rule, CSSStyleSheet parentSheet, string baseurl, bool downloadImportRule, ref string OriginalCss)
        {
            /// the first item in rule is the atkeyword.

            if (rule.prelude[0].Type == CompoenentValueType.preservedToken)
            {
                PreservedToken token = rule.prelude[0] as PreservedToken;
                if (token.token.Type == enumTokenType.at_keyword)
                {
                    at_keyword_token keywordToken = token.token as at_keyword_token;

                    if (keywordToken.value.ToLower() == "import")
                    {
                        return(ParseImportRule(rule, baseurl, downloadImportRule, ref OriginalCss));
                    }
                    else if (keywordToken.value.ToLower() == "media")
                    {
                        return(ParseMediaRule(rule, parentSheet, ref OriginalCss));
                    }
                    else if (keywordToken.value.ToLower() == "font-face")
                    {
                        return(ParseFontFace(rule, ref OriginalCss));
                    }
                }
            }

            return(null);
        }
コード例 #3
0
        private static CSSRule ParseMediaRule(AtRule rule, CSSStyleSheet parentSheet, ref string OriginalCss)
        {
            CSSMediaRule mediarule = new CSSMediaRule();

            mediarule.parentStyleSheet = parentSheet;

            string media = string.Empty;
            string wholeconditiontext = string.Empty;

            int startindex       = -1;
            int endindex         = -1;
            int endindexselector = -1;

            startindex = rule.prelude[0].startindex;

            // the first componentvalue is a preservedtoken and it media.
            rule.prelude.RemoveAt(0);

            wholeconditiontext = ComponentValueExtension.getString(rule.prelude, ref startindex, ref endindexselector, ref OriginalCss);

            foreach (var item in wholeconditiontext.Split(','))
            {
                mediarule.media.appendMedium(item);
            }

            CSSRuleList blockrulelist = ParseMediaRuleList(rule.block, ref endindex, mediarule, ref OriginalCss);

            if (blockrulelist != null)
            {
                mediarule.cssRules = blockrulelist;
            }

            mediarule.conditionText = wholeconditiontext;

            //SelectorText is assigned in a different way now.
            // mediarule.selectorText = wholeconditiontext; /// NON-W3C.

            mediarule.StartIndex = rule.startindex;

            if (rule.endindex > endindex)
            {
                endindex = rule.endindex;
            }

            mediarule.EndIndex         = endindex;
            mediarule.EndSelectorIndex = endindexselector - mediarule.StartIndex + 1;

            return(mediarule);
        }
コード例 #4
0
        /// <summary>
        /// The @import at-rule is a simple statement. After its name, it takes a single string or url() function to indicate the stylesheet that it should import.
        /// </summary>
        /// <param name="rule"></param>
        /// <returns></returns>
        private static CSSRule ParseImportRule(AtRule rule, string baseurl, bool downloadImportRule, ref string OriginalCss)
        {
            /// the import starts with import atkeyword token.
            /// it should have been checked before calling this method, can be ignored.
            PreservedToken token = rule.prelude[0] as PreservedToken;

            int count = rule.prelude.Count;

            CSSImportRule importrule = new CSSImportRule();
            string        media      = string.Empty;

            int startindex = -1;
            int endindex   = -1;

            for (int i = 0; i < count; i++)
            {
                if (startindex < 0)
                {
                    startindex = rule.prelude[i].startindex;
                }

                if (rule.prelude[i].endindex > endindex)
                {
                    endindex = rule.prelude[i].endindex;
                }

                if (rule.prelude[i].Type == CompoenentValueType.preservedToken)
                {
                    PreservedToken preservedToken = rule.prelude[i] as PreservedToken;

                    /// ignore the whitespace and at-keyword token.
                    if (preservedToken.token.Type == enumTokenType.at_keyword || (string.IsNullOrEmpty(importrule.href) && preservedToken.token.Type == enumTokenType.whitespace))
                    {
                        continue;
                    }

                    if (string.IsNullOrEmpty(importrule.href))
                    {
                        if (preservedToken.token.Type == enumTokenType.String)
                        {
                            string_token stringtoken = preservedToken.token as string_token;
                            string       url         = string.Empty;

                            if (string.IsNullOrEmpty(baseurl))
                            {
                                url = stringtoken.value;
                            }
                            else
                            {
                                url = PathHelper.combine(baseurl, stringtoken.value);
                            }

                            importrule.href = url;
                            if (downloadImportRule && !string.IsNullOrEmpty(url))
                            {
                                importrule.stylesheet = CSSParser.ParseCSSStyleSheetFromUrl(url);
                            }
                        }
                        else if (preservedToken.token.Type == enumTokenType.url)
                        {
                            url_token urltoken = preservedToken.token as url_token;

                            string url = string.Empty;
                            if (string.IsNullOrEmpty(baseurl))
                            {
                                url = urltoken.value;
                            }
                            else
                            {
                                url = PathHelper.combine(baseurl, urltoken.value);
                            }

                            importrule.href = url;
                            if (downloadImportRule && !string.IsNullOrEmpty(url))
                            {
                                importrule.stylesheet = CSSParser.ParseCSSStyleSheetFromUrl(url);
                            }
                        }
                        else
                        {
                            // must start with a string or url token as the next.
                            string error = "this is an error";
                        }
                    }
                    else
                    {
                        // the import rule has href already, next is the media rules.
                        if (preservedToken.token.Type == enumTokenType.comma || preservedToken.token.Type == enumTokenType.semicolon)
                        {
                            if (!string.IsNullOrEmpty(media))
                            {
                                importrule.media.appendMedium(media.Trim());
                                media = string.Empty;
                            }
                        }
                        else
                        {
                            // can be delim token.
                            if (string.IsNullOrEmpty(media) && preservedToken.token.Type == enumTokenType.whitespace)
                            {
                                // the start of whitespace will be ignored.
                            }
                            else
                            {
                                media += preservedToken.token.GetString(ref OriginalCss);
                            }
                        }
                    }
                }

                else if (rule.prelude[i].Type == CompoenentValueType.function)
                {
                    Function urlfunction = rule.prelude[i] as Function;
                    string   href        = string.Empty;
                    if (urlfunction.name == "url")
                    {
                        foreach (var item in urlfunction.value)
                        {
                            if (item.Type == CompoenentValueType.preservedToken)
                            {
                                PreservedToken pretoken = item as PreservedToken;
                                if (pretoken.token.Type == enumTokenType.String)
                                {
                                    string_token stringtoken = pretoken.token as string_token;
                                    href += stringtoken.value;
                                }
                            }
                        }
                    }

                    if (!string.IsNullOrEmpty(href))
                    {
                        importrule.href = href;
                    }
                }

                else if (rule.prelude[i].Type == CompoenentValueType.simpleBlock)
                {
                    // simple block is the block like  screen and (min-width:300);
                    SimpleBlock block = rule.prelude[i] as SimpleBlock;

                    string mediarule = string.Empty;
                    foreach (var item in block.value)
                    {
                        if (item.Type == CompoenentValueType.preservedToken)
                        {
                            PreservedToken pretoken = item as PreservedToken;
                            mediarule += pretoken.token.GetString(ref OriginalCss);

                            if (token.token.endIndex > endindex)
                            {
                                endindex = token.token.endIndex;
                            }
                        }
                    }

                    if (block.token.Type == enumTokenType.round_bracket_left || block.token.Type == enumTokenType.round_bracket_right)
                    {
                        mediarule = "(" + mediarule + ")";
                    }
                    else if (block.token.Type == enumTokenType.square_bracket_left || block.token.Type == enumTokenType.square_bracket_right)
                    {
                        mediarule = "[" + mediarule + "]";
                    }
                    else if (block.token.Type == enumTokenType.curly_bracket_left || block.token.Type == enumTokenType.curly_bracket_right)
                    {
                        mediarule = "{" + mediarule + "}";
                    }

                    media += mediarule;
                }
            }

            if (!string.IsNullOrEmpty(media))
            {
                importrule.media.appendMedium(media.Trim());
                media = string.Empty;
            }

            importrule.StartIndex = startindex;
            if (rule.endindex > endindex)
            {
                endindex = rule.endindex;
            }
            importrule.EndIndex = endindex;

            int endselectorindex = rule.prelude[0].endindex + 1;

            ///import rule does not have one extra char like {
            // importrule.EndSelectorIndex = endselectorindex - importrule.StartIndex + 1;
            importrule.EndSelectorIndex = endselectorindex - importrule.StartIndex;

            return(importrule);
        }
コード例 #5
0
ファイル: CssParser.cs プロジェクト: carbon/Css
        public CssNode ReadAtRule()
        {
            // ATKEYWORD S* any* [ block | ';' S* ];
            // @{keyword} ...

            // @import "subs.css";
            // @media print {

            Read(TokenKind.AtSymbol, LexicalMode.Rule); // Read @

            var ruleType = RuleType.Unknown;

            var atName = Read();                        // read name

            ReadTrivia();

            switch (atName.Text)
            {
                case "charset"   : ruleType = RuleType.Charset; break;
                case "import"    : return ReadImportRule();
                case "font-face" : return ReadFontFaceRule();
                case "media"     : return ReadMediaRule();
                case "page"      : ruleType = RuleType.Page; break;
                case "keyframes" : return ReadKeyframesRule();
                case "mixin"     : return ReadMixinBody();
                case "if"        : return ReadIfRule();
            }

            string selectorText = null;

            if (current.Kind == TokenKind.Name)
            {
                selectorText = ReadSpan().ToString();
            }

            var rule = new AtRule(atName.Text, ruleType, selectorText ?? "");

            switch (current.Kind)
            {
                case TokenKind.BlockStart: ReadBlock(rule); break; // {
                case TokenKind.Semicolon: tokenizer.Read(); break; // ;
            }

            return rule;
        }
コード例 #6
0
        /// <summary>
        /// 5.4.1. Consume a list of rules
        /// </summary>
        /// <param name="tokenizer"></param>
        /// <param name="top_level_flag"></param>
        /// <returns></returns>
        private List <Rule> ConsumeListOfRules(bool top_level_flag)
        {
            //To consume a list of rules:

            //Create an initially empty list of rules.
            List <Rule> rulelist = new List <Rule>();

            cssToken token;

            while (true)
            {
                //Repeatedly consume the next input token:
                token = ConsumeNextToken();

                //<whitespace-token>
                if (token.Type == enumTokenType.whitespace)
                {
                    //Do nothing.
                }
                //<EOF-token>
                else if (token.Type == enumTokenType.EOF)
                {
                    //Return the list of rules.
                    return(rulelist);
                }
                //<CDO-token>
                //<CDC-token>
                else if (token.Type == enumTokenType.CDC || token.Type == enumTokenType.CDO)
                {
                    //If the top-level flag is set, do nothing.
                    if (!top_level_flag)
                    {
                        //Otherwise, reconsume the current input token. Consume a qualified rule. If anything is returned, append it to the list of rules.
                        ReconsumeToken();
                        QualifiedRule rule = ConsumeQualifiedRule();
                        if (rule != null)
                        {
                            rulelist.Add(rule);
                        }
                    }
                }
                //<at-keyword-token>
                else if (token.Type == enumTokenType.at_keyword)
                {
                    //Reconsume the current input token. Consume an at-rule. If anything is returned, append it to the list of rules.
                    ReconsumeToken();
                    AtRule rule = ConsumeAtRule();

                    if (rule != null)
                    {
                        rulelist.Add(rule);
                    }
                }
                //anything else
                else
                {
                    //Reconsume the current input token. Consume a qualified rule. If anything is returned, append it to the list of rules.
                    ReconsumeToken();
                    QualifiedRule rule = ConsumeQualifiedRule();
                    if (rule != null)
                    {
                        rulelist.Add(rule);
                    }
                }
            }
        }
コード例 #7
0
        /// <summary>
        /// 5.4.2. Consume an at-rule
        /// </summary>
        /// <returns></returns>
        private AtRule ConsumeAtRule()
        {
            //To consume an at-rule:
            //Create a new at-rule with its name set to the value of the current input token, its prelude initially set to an empty list, and its value initially set to nothing.
            AtRule rule = new AtRule();

            int startindex = -1;

            cssToken token = null;

            while (true)
            {
                //Repeatedly consume the next input token:
                token = ConsumeNextToken();
                if (startindex == -1)
                {
                    startindex = token.startIndex;
                }

                //<semicolon-token>
                //<EOF-token>
                if (token.Type == enumTokenType.semicolon || token.Type == enumTokenType.EOF)
                {
                    //Return the at-rule.
                    rule.startindex = startindex;
                    rule.endindex   = token.endIndex;

                    if (token.Type == enumTokenType.EOF)
                    {
                        rule.endindex = rule.endindex - 1;
                    }
                    return(rule);
                }
                //<{-token>
                else if (token.Type == enumTokenType.curly_bracket_left)
                {
                    //Consume a simple block and assign it to the at-rule’s block. Return the at-rule.
                    SimpleBlock simpleblock = ConsumeSimpleBlock();
                    simpleblock.startindex = token.startIndex;
                    rule.block             = simpleblock;

                    rule.startindex = startindex;
                    rule.endindex   = simpleblock.endindex;

                    return(rule);
                }
                //simple block with an associated token of <{-token>
                //Assign the block to the at-rule’s block. Return the at-rule.

                ///TODO: ???? check what does this means???

                //anything else
                else
                {
                    //Reconsume the current input token. Consume a component value. Append the returned value to the at-rule’s prelude.
                    ReconsumeToken();
                    ComponentValue value = ConsumeComponentValue();
                    rule.prelude.Add(value);
                }
            }
        }