2012-07-24 80 views
3

我正在使用下面的代碼來遞歸地解析css @import語句來加載嵌套的css文件在minifer中。雖然這與標準的@import聲明完美配合,但它會錯誤地將@import聲明添加到媒體查詢中,而無需在它們周圍創建條件。處理多個正則表達式組

我需要做的是:

  1. 依次通過我的比賽抓住filename組捕獲
  2. 檢查相應的media
  3. 如果是這樣的情況下,包裹裏面的整個加載CSS使用捕獲的參數進行媒體查詢
  4. 如果沒有,只需添加文件名捕獲內容。

e.g

@import url(style.css) screen and (min-width: 768px); 

成爲

@media screen and (min-width: 767px) { 
    /* contents of style.css */ 
} 

我的正則表達式,我使用捕捉到語句是這樣的:

(?:@import\surl\()(?<filename>[^.]+\.css)(?:\)((?<media>[^;]+);|;)) 

這是正確的捕捉。我只是不知道Regex課程全力以赴。

有人比我更聰明嗎?

我的原始代碼。

/// <summary> 
    /// Parses the string for css imports and adds them to the 
    /// file dependency list. 
    /// </summary> 
    /// <param name="css"> 
    /// The css to parse for import statements. 
    /// </param> 
    /// <param name="minify"> 
    /// Whether or not the local script should be minified. 
    /// </param> 
    /// <returns>The css file parsed for imports.</returns> 
    private string ParseImportsAndCache(string css, bool minify) 
    { 
     // Check for imports and parse if necessary. 
     if (!css.Contains("@import", StringComparison.OrdinalIgnoreCase)) 
     { 
      return css; 
     } 

     // Recursivly parse the css for imports. 
     foreach (Match match in ImportsRegex.Matches(css)) 
     { 
      // Recursivly parse the css for imports. 
      GroupCollection groups = match.Groups; 

      // Check and add the @import params to the cache dependancy list. 
      foreach (var groupName in groups["filename"].Captures) 
      { 
       // Get the match 
       List<string> files = new List<string>(); 
       Array.ForEach(
        CSSPaths, 
        cssPath => Array.ForEach(
         Directory.GetFiles(
          HttpContext.Current.Server.MapPath(cssPath), 
          groupName.ToString(), 
          SearchOption.AllDirectories), 
         files.Add)); 

       string file = files.FirstOrDefault(); 
       string thisCSS = string.Empty; 

       // Read the file. 
       if (file != null) 
       { 
        using (StreamReader reader = new StreamReader(file)) 
        { 
         // Recursiveley parse the css. 
         thisCSS = this.ParseImportsAndCache(reader.ReadToEnd(), 
                  minify); 
        } 
       } 

       // Replace the regex match with the full qualified css. 
       css = css.Replace(match.Value, thisCSS); 

       if (minify) 
       { 
        this.cacheDependencies 
         .Add(new CacheDependency(files.FirstOrDefault())); 
       } 
      } 
     } 

     return css; 
    } 
+3

您可以像獲取文件名一樣訪問此結果。你有沒有嘗試過調用'groups [「media」]。捕獲'? – 2012-07-24 20:04:15

+0

我是個白癡。我誤解了我自己的代碼。我實際上並不需要循環組。乾杯! (@ [^。] + \ .css)\)(? [^;] *);' – 2012-07-24 21:35:39

+2

)您是不是歡迎=) – 2012-07-24 21:40:11

回答

0

按照評論中的建議,這裏是最終的工作代碼。

/// <summary> 
/// Parses the string for css imports and adds them to the file dependency 
/// list. 
/// </summary> 
/// <param name="css"> 
/// The css to parse for import statements. 
/// </param> 
/// <param name="minify">Whether or not the local script should be minified. 
////</param> 
/// <returns>The css file parsed for imports.</returns> 
private string ParseImportsAndCache(string css, bool minify) 
{ 
    // Check for imports and parse if necessary. 
    if (!css.Contains("@import", StringComparison.OrdinalIgnoreCase)) 
    { 
     return css; 
    } 

    // Recursivly parse the css for imports. 
    foreach (Match match in ImportsRegex.Matches(css)) 
    { 
     // Recursivly parse the css for imports. 
     GroupCollection groups = match.Groups; 
     Capture fileName = groups["filename"].Captures[0]; 
     CaptureCollection mediaQueries = groups["media"].Captures; 
     Capture mediaQuery = null; 

     if (mediaQueries.Count > 0) 
     { 
      mediaQuery = mediaQueries[0]; 
     } 

     // Check and add the @import params to the cache dependancy list. 
     // Get the match 
     List<string> files = CSSPaths 
      .SelectMany(cssPath => Directory.GetFiles(
       HttpContext.Current.Server.MapPath(cssPath), 
       Path.GetFileName(fileName.ToString()), 
       SearchOption.AllDirectories)) 
      .ToList(); 

     string file = files.FirstOrDefault(); 
     string thisCSS = string.Empty; 

     // Read the file. 
     if (file != null) 
     { 
      using (StreamReader reader = new StreamReader(file)) 
      { 
       thisCSS = mediaQuery != null 
        ? string.Format(CultureInfo.InvariantCulture, 
           "@media {0}{{{1}{2}{1}}}", 
           mediaQuery, 
           Environment.NewLine, 
           this.ParseImportsAndCache(
           this.PreProcessInput(reader.ReadToEnd(), 
           file), 
           minify)) 
        : this.ParseImportsAndCache(this.PreProcessInput(
               reader.ReadToEnd(), 
               file), 
               minify); 
      } 
     } 

     // Replace the regex match with the full qualified css. 
     css = css.Replace(match.Value, thisCSS); 

     if (minify) 
     { 
      this.cacheDependencies.Add(new CacheDependency(
              files.FirstOrDefault())); 
     } 
    } 

    return css; 
}