3

次のコードを使用して、css@importステートメントを再帰的に解析し、ネストされたcssファイルをミニファーにロードしています。これは標準のステートメントで完全に機能しますが、メディアクエリを含むステートメントを、条件付きのステートメントを作成せずに@import誤って追加します。@import

私がする必要があるのは:

  1. filenameグループキャプチャをつかむ私の試合をループする
  2. media対応するグループの存在を確認します
  3. その場合、キャプチャされたパラメータを使用して、ロードされたcss全体をメディアクエリ内にラップします
  4. そうでない場合は、ファイル名キャプチャの内容を追加するだけです。

例えば

@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;
    }
4

1 に答える 1

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;
}
于 2013-03-18T13:38:58.933 に答える