Created
August 20, 2014 18:27
-
-
Save dotnetchris/3d1e4fe9b0fa77eefc82 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class StyleRelativePathTransform : IBundleTransform | |
{ | |
private const string UrlPattern = @"url\s*\(\s*([""']?)([^:)]+)\1\s*\)"; | |
private static readonly Regex UrlRegex = new Regex(UrlPattern, RegexOptions.IgnoreCase | RegexOptions.Compiled); | |
public void Process(BundleContext context, BundleResponse response) | |
{ | |
var mergedCss = new StringBuilder(); | |
// open each of the files | |
foreach (var cssFileInfo in response.Files) | |
{ | |
if (cssFileInfo.Exists.Equals(false)) continue; | |
string cssFileContents = File.ReadAllText(cssFileInfo.FullName); | |
// apply the RegEx to the file (to change relative paths) | |
var matches = UrlRegex.Matches(cssFileContents); | |
// Ignore the file if no match | |
if (matches.Count > 0) | |
{ | |
string cssDirectoryPath = cssFileInfo.DirectoryName; | |
string cssVirtualPath = context.RelativeUrlFrom(cssDirectoryPath); | |
foreach (Match match in matches) | |
{ | |
string quoteDelimiter = match.Groups[1].Value; //url('') vs url("") | |
string relativePathToCss = match.Groups[2].Value; | |
//prevent querystring from causing error | |
var pathAndQuery = relativePathToCss.Split(new[] {'?'}, 2, StringSplitOptions.RemoveEmptyEntries); | |
var pathOnly = pathAndQuery[0]; | |
var queryOnly = pathAndQuery.Length == 2 ? pathAndQuery[1] : string.Empty; | |
string absolutePath = GetAbsolutePath(cssDirectoryPath, pathOnly); | |
string serverRelativeUrl = context.RelativeUrlFrom(absolutePath, queryOnly); | |
string replace = String.Format("url({0}{1}{0})", quoteDelimiter, serverRelativeUrl); | |
cssFileContents = cssFileContents.Replace(match.Groups[0].Value, replace); | |
} | |
} | |
mergedCss.AppendLine(cssFileContents); | |
} | |
response.Content = mergedCss.ToString(); | |
} | |
private static string GetAbsolutePath(string cssFilePath, string pathOnly) | |
{ | |
return Path.GetFullPath(Path.Combine(cssFilePath, pathOnly)); | |
} | |
} | |
public static class BundleContextExtension | |
{ | |
/// <summary> | |
/// Converts the absolutePath to the server relative URL. | |
/// </summary> | |
/// <param name="bundleContext">The bundle context.</param> | |
/// <param name="absolutePath">The absolute path.</param> | |
/// <param name="queryOnly">[Optional] The query string.</param> | |
/// <returns></returns> | |
public static string RelativeUrlFrom(this BundleContext bundleContext, string absolutePath, string queryOnly = null) | |
{ | |
var request = bundleContext.HttpContext.Request; | |
var applicationPath = request.PhysicalApplicationPath; | |
var virtualDir = request.ApplicationPath.EndsIn('/'); | |
string serverRelativePath = absolutePath.Replace(applicationPath, virtualDir).Replace(@"\", "/"); | |
if (string.IsNullOrEmpty(queryOnly)) return serverRelativePath; | |
string serverRelativeUrl = serverRelativePath + "?" + queryOnly.TrimStart(new[] {'?'}); | |
return serverRelativeUrl; | |
} | |
} | |
public static class StringExtension | |
{ | |
/// <summary> | |
/// Removes all trailing occurrences of a set of characters specified in an array from the current | |
/// <see cref="T:System.String" /> object. | |
/// </summary> | |
/// <param name="str">The string.</param> | |
/// <param name="chars">The chars.</param> | |
/// <returns></returns> | |
public static string TrimEndSafe(this string str, params char[] chars) | |
{ | |
if (string.IsNullOrEmpty(str)) return str; | |
return str.TrimEnd(chars); | |
} | |
/// <summary> | |
/// Forces the string to end with the specified char. Will not allow duplicated end characters | |
/// </summary> | |
/// <param name="str">The string. If null will return @char</param> | |
/// <param name="char">The character.</param> | |
/// <returns></returns> | |
public static string EndsIn(this string str, char @char) | |
{ | |
return str.TrimEndSafe(@char) + @char; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment