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); }
public static List <UrlInfo> GetUrlInfos(string CssText) { List <UrlInfo> urllist = new List <UrlInfo>(); if (string.IsNullOrEmpty(CssText)) { return(urllist); } Kooboo.Dom.CSS.Tokenizer toknizer = new Kooboo.Dom.CSS.Tokenizer(CssText); while (true) { cssToken token = toknizer.ConsumeNextToken(); if (token == null || token.Type == enumTokenType.EOF) { break; } else { if (token.Type == enumTokenType.url) { url_token urltoken = token as url_token; string resourceurl = urltoken.value; if (!string.IsNullOrEmpty(resourceurl)) { urllist.Add(new UrlInfo() { StartIndex = urltoken.startIndex, EndIndex = urltoken.endIndex, RawUrl = resourceurl, isUrlToken = true }); } } else if (token.Type == enumTokenType.at_keyword) { at_keyword_token keywordtoken = token as at_keyword_token; if (keywordtoken.value.ToLower() == "import") { cssToken nexttoken = toknizer.ConsumeNextToken(); while (nexttoken.Type == enumTokenType.whitespace) { nexttoken = toknizer.ConsumeNextToken(); } if (nexttoken.Type == enumTokenType.String) { string_token stringtoken = nexttoken as string_token; if (!string.IsNullOrEmpty(stringtoken.value)) { urllist.Add(new UrlInfo() { StartIndex = stringtoken.startIndex, EndIndex = stringtoken.endIndex, RawUrl = stringtoken.value, isImportRule = true }); } } else if (nexttoken.Type == enumTokenType.url) { url_token urltoken = nexttoken as url_token; string resourceurl = urltoken.value; if (!string.IsNullOrEmpty(resourceurl)) { urllist.Add(new UrlInfo() { StartIndex = urltoken.startIndex, EndIndex = urltoken.endIndex, RawUrl = resourceurl, isUrlToken = true, isImportRule = true }); } } else if (nexttoken.Type == enumTokenType.function) { function_token functoken = nexttoken as function_token; string functionvalue = functoken.Value; if (functionvalue.ToLower() == "url") { nexttoken = toknizer.ConsumeNextToken(); while (nexttoken.Type == enumTokenType.whitespace) { nexttoken = toknizer.ConsumeNextToken(); } if (nexttoken == null || nexttoken.Type == enumTokenType.EOF) { break; } if (nexttoken.Type == enumTokenType.String) { string_token stringtoken = nexttoken as string_token; if (!string.IsNullOrEmpty(stringtoken.value)) { urllist.Add(new UrlInfo() { StartIndex = stringtoken.startIndex, EndIndex = stringtoken.endIndex, RawUrl = stringtoken.value, isImportRule = true }); } } else if (nexttoken.Type == enumTokenType.url) { url_token urltoken = nexttoken as url_token; string resourceurl = urltoken.value; if (!string.IsNullOrEmpty(resourceurl)) { urllist.Add(new UrlInfo() { StartIndex = urltoken.startIndex, EndIndex = urltoken.endIndex, RawUrl = resourceurl, isUrlToken = true, isImportRule = true }); } } } } } } else if (token.Type == enumTokenType.function) { function_token functoken = token as function_token; string functionvalue = functoken.Value; if (functionvalue.ToLower() == "url") { cssToken nexttoken = toknizer.ConsumeNextToken(); while (nexttoken.Type == enumTokenType.whitespace) { nexttoken = toknizer.ConsumeNextToken(); } if (nexttoken == null || nexttoken.Type == enumTokenType.EOF) { break; } if (nexttoken.Type == enumTokenType.String) { string_token stringtoken = nexttoken as string_token; if (!string.IsNullOrEmpty(stringtoken.value)) { urllist.Add(new UrlInfo() { StartIndex = stringtoken.startIndex, EndIndex = stringtoken.endIndex, RawUrl = stringtoken.value }); } } } } } } return(cleanSpecialMark(urllist)); }
/// <summary> /// consume a list of cssrule from simpleblock, /// Recursive. /// </summary> /// <param name="block"></param> /// <returns></returns> private static CSSRuleList ParseMediaRuleList(SimpleBlock block, ref int endindex, CSSMediaRule parentmediarule, ref string OriginalCss) { int count = block.value.Count; CSSRuleList rulelist = new CSSRuleList(); MediaRuleParseState state = MediaRuleParseState.init; CSSStyleRule stylerule = null; CSSMediaRule mediarule = null; string media = string.Empty; string wholeconditiontext = string.Empty; int startindex = -1; for (int i = 0; i < count; i++) { if (block.value[i].endindex > endindex) { endindex = block.value[i].endindex; } if (startindex < 0) { startindex = block.value[i].startindex; } switch (state) { case MediaRuleParseState.init: { if (block.value[i].Type == CompoenentValueType.preservedToken) { PreservedToken pretoken = block.value[i] as PreservedToken; if (pretoken.token.Type == enumTokenType.whitespace) { // ignored whitespace at the beginning. } else if (pretoken.token.Type == enumTokenType.at_keyword) { // at keyword token, only handle media now. // others to be added. at_keyword_token token = pretoken.token as at_keyword_token; if (token.value.ToLower() == "media") { state = MediaRuleParseState.mediarule; i = i - 1; // reconsume to have correct startindex. } else { // other at rules. state = MediaRuleParseState.OtherAtRule; i = i - 1; } } /// else treat as regular style rule. else { state = MediaRuleParseState.stylerule; i = i - 1; // reconsume. } } break; } case MediaRuleParseState.stylerule: { if (stylerule == null) { stylerule = new CSSStyleRule(); startindex = block.value[i].startindex; } if (block.value[i].Type == CompoenentValueType.preservedToken) { PreservedToken pretoken = block.value[i] as PreservedToken; // not a defined way to parse the selector, assembly them back and give it to selector module. // in the new way of getting selectorText, we have not need to assign it any more. //stylerule.selectorText += pretoken.token.getString(); } else if (block.value[i].Type == CompoenentValueType.simpleBlock) { int endselectorindex = block.value[i].startindex; stylerule.style = ParseDeclarations(block.value[i] as SimpleBlock, ref endindex, ref OriginalCss); stylerule.StartIndex = startindex; stylerule.EndIndex = endindex; stylerule.EndSelectorIndex = endselectorindex - stylerule.StartIndex; stylerule.parentRule = parentmediarule; stylerule.parentStyleSheet = parentmediarule.parentStyleSheet; rulelist.appendRule(stylerule); stylerule = null; state = MediaRuleParseState.init; startindex = -1; } break; } case MediaRuleParseState.mediarule: { if (mediarule == null) { mediarule = new CSSMediaRule(); media = string.Empty; wholeconditiontext = string.Empty; startindex = block.value[i].startindex; mediarule.parentStyleSheet = parentmediarule.parentStyleSheet; mediarule.parentRule = parentmediarule; } if (block.value[i].Type == CompoenentValueType.preservedToken) { PreservedToken pretoken = block.value[i] as PreservedToken; if (pretoken.token.Type == enumTokenType.comma) { if (!string.IsNullOrEmpty(media)) { mediarule.media.appendMedium(media.Trim()); media = string.Empty; } wholeconditiontext += ","; } else { // can be delim token. if (string.IsNullOrEmpty(media) && pretoken.token.Type == enumTokenType.whitespace) { // the start of whitespace will be ignored. } else { media += pretoken.token.GetString(ref OriginalCss); wholeconditiontext += pretoken.token.GetString(ref OriginalCss); } } } else if (block.value[i].Type == CompoenentValueType.simpleBlock) { CSSRuleList mediarulelist = ParseMediaRuleList(block.value[i] as SimpleBlock, ref endindex, mediarule, ref OriginalCss); mediarule.cssRules = mediarulelist; if (!string.IsNullOrEmpty(media)) { mediarule.media.appendMedium(media.Trim()); wholeconditiontext += media; } mediarule.conditionText = wholeconditiontext; mediarule.selectorText = wholeconditiontext; /// NON-W3C. mediarule.StartIndex = startindex; mediarule.EndIndex = endindex; rulelist.appendRule(mediarule); state = 0; mediarule = null; media = string.Empty; wholeconditiontext = string.Empty; startindex = -1; } break; } case MediaRuleParseState.OtherAtRule: { //if (mediarule == null) //{ // mediarule = new CSSMediaRule(); // media = string.Empty; // wholeconditiontext = string.Empty; // startindex = block.value[i].startindex; // mediarule.parentStyleSheet = parentmediarule.parentStyleSheet; // mediarule.parentRule = parentmediarule; //} if (block.value[i].Type == CompoenentValueType.preservedToken) { //PreservedToken pretoken = block.value[i] as PreservedToken; //if (pretoken.token.Type == enumTokenType.comma) //{ // if (!string.IsNullOrEmpty(media)) // { // mediarule.media.appendMedium(media.Trim()); // media = string.Empty; // } // wholeconditiontext += ","; //} //else //{ // // can be delim token. // if (string.IsNullOrEmpty(media) && pretoken.token.Type == enumTokenType.whitespace) // { // // the start of whitespace will be ignored. // } // else // { // media += pretoken.token.GetString(ref OriginalCss); // wholeconditiontext += pretoken.token.GetString(ref OriginalCss); // } //} } else if (block.value[i].Type == CompoenentValueType.simpleBlock) { // not implemented now. //CSSRuleList mediarulelist = ParseMediaRuleList(block.value[i] as SimpleBlock, ref endindex, mediarule, ref OriginalCss); //mediarule.cssRules = mediarulelist; //if (!string.IsNullOrEmpty(media)) //{ // mediarule.media.appendMedium(media.Trim()); // wholeconditiontext += media; //} //mediarule.conditionText = wholeconditiontext; //mediarule.selectorText = wholeconditiontext; /// NON-W3C. //mediarule.StartIndex = startindex; //mediarule.EndIndex = endindex; //rulelist.appendRule(mediarule); state = MediaRuleParseState.init; startindex = -1; } break; } default: break; } } if (stylerule != null) { if (stylerule.EndIndex > stylerule.StartIndex) { rulelist.appendRule(stylerule); } stylerule = null; } if (mediarule != null) { rulelist.appendRule(mediarule); mediarule = null; } return(rulelist); }