-
-
Save tugberkugurlu/3924324 to your computer and use it in GitHub Desktop.
LESS CSS Support in System.Web.Optimization
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 LessTransform : IBundleTransform | |
{ | |
public void Process(BundleContext context, BundleResponse bundle) | |
{ | |
if (context == null) | |
{ | |
throw new ArgumentNullException("context"); | |
} | |
if (bundle == null) | |
{ | |
throw new ArgumentNullException("bundle"); | |
} | |
context.HttpContext.Response.Cache.SetLastModifiedFromFileDependencies(); | |
var lessParser = new Parser(); | |
ILessEngine lessEngine = CreateLessEngine(lessParser); | |
var content = new StringBuilder(bundle.Content.Length); | |
var bundleFiles = new List<FileInfo>(); | |
foreach (var bundleFile in bundle.Files) | |
{ | |
bundleFiles.Add(bundleFile); | |
SetCurrentFilePath(lessParser, bundleFile.FullName); | |
string source = File.ReadAllText(bundleFile.FullName); | |
content.Append(lessEngine.TransformToCss(source, bundleFile.FullName)); | |
content.AppendLine(); | |
bundleFiles.AddRange(GetFileDependencies(lessParser)); | |
} | |
if (BundleTable.EnableOptimizations) | |
{ | |
// include imports in bundle files to register cache dependencies | |
bundle.Files = bundleFiles.Distinct(); | |
} | |
bundle.ContentType = "text/css"; | |
bundle.Content = content.ToString(); | |
} | |
/// <summary> | |
/// Creates an instance of LESS engine. | |
/// </summary> | |
/// <param name="lessParser">The LESS parser.</param> | |
private ILessEngine CreateLessEngine(Parser lessParser) | |
{ | |
var logger = new AspNetTraceLogger(LogLevel.Debug, new Http()); | |
return new LessEngine(lessParser, logger, true, false); | |
} | |
/// <summary> | |
/// Gets the file dependencies (@imports) of the LESS file being parsed. | |
/// </summary> | |
/// <param name="lessParser">The LESS parser.</param> | |
/// <returns>An array of file references to the dependent file references.</returns> | |
private IEnumerable<FileInfo> GetFileDependencies(Parser lessParser) | |
{ | |
IPathResolver pathResolver = GetPathResolver(lessParser); | |
foreach (var importPath in lessParser.Importer.Imports) | |
{ | |
yield return new FileInfo(pathResolver.GetFullPath(importPath)); | |
} | |
lessParser.Importer.Imports.Clear(); | |
} | |
/// <summary> | |
/// Returns an <see cref="IPathResolver"/> instance used by the specified LESS lessParser. | |
/// </summary> | |
/// <param name="lessParser">The LESS parser.</param> | |
private IPathResolver GetPathResolver(Parser lessParser) | |
{ | |
var importer = lessParser.Importer as Importer; | |
var fileReader = importer.FileReader as FileReader; | |
return fileReader.PathResolver; | |
} | |
/// <summary> | |
/// Informs the LESS parser about the path to the currently processed file. | |
/// This is done by using a custom <see cref="IPathResolver"/> implementation. | |
/// </summary> | |
/// <param name="lessParser">The LESS parser.</param> | |
/// <param name="currentFilePath">The path to the currently processed file.</param> | |
private void SetCurrentFilePath(Parser lessParser, string currentFilePath) | |
{ | |
var importer = lessParser.Importer as Importer; | |
if (importer == null) | |
throw new InvalidOperationException("Unexpected dotless importer type."); | |
var fileReader = importer.FileReader as FileReader; | |
if (fileReader == null || !(fileReader.PathResolver is ImportedFilePathResolver)) | |
{ | |
fileReader = new FileReader(new ImportedFilePathResolver(currentFilePath)); | |
importer.FileReader = fileReader; | |
} | |
} | |
} | |
public class ImportedFilePathResolver : IPathResolver | |
{ | |
private string currentFileDirectory; | |
private string currentFilePath; | |
public ImportedFilePathResolver(string currentFilePath) | |
{ | |
if (string.IsNullOrEmpty(currentFilePath)) | |
{ | |
throw new ArgumentNullException("currentFilePath"); | |
} | |
CurrentFilePath = currentFilePath; | |
} | |
/// <summary> | |
/// Gets or sets the path to the currently processed file. | |
/// </summary> | |
public string CurrentFilePath | |
{ | |
get { return currentFilePath; } | |
set | |
{ | |
currentFilePath = value; | |
currentFileDirectory = Path.GetDirectoryName(value); | |
} | |
} | |
/// <summary> | |
/// Returns the absolute path for the specified improted file path. | |
/// </summary> | |
/// <param name="filePath">The imported file path.</param> | |
public string GetFullPath(string filePath) | |
{ | |
if (filePath.StartsWith("~")) | |
{ | |
filePath = VirtualPathUtility.ToAbsolute(filePath); | |
} | |
if (filePath.StartsWith("/")) | |
{ | |
filePath = HostingEnvironment.MapPath(filePath); | |
} | |
else if (!Path.IsPathRooted(filePath)) | |
{ | |
filePath = Path.GetFullPath(Path.Combine(currentFileDirectory, filePath)); | |
} | |
return filePath; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment