我正在使用以下代码递归解析css @import
语句以在minifer中加载嵌套的css文件。虽然这与标准@import
语句完美匹配,但它会错误地将@import
语句添加到媒体查询中,而不会围绕它们创建条件。
我需要做的是:
filename
群组抓取media
组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;
}
答案 0 :(得分: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;
}