Skip to content

Instantly share code, notes, and snippets.

@chrisortman
Created March 8, 2012 19:48
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save chrisortman/2002958 to your computer and use it in GitHub Desktop.
Save chrisortman/2002958 to your computer and use it in GitHub Desktop.
ASP.NET Optimization Minifiers
public class ImportedFilePathResolver : IPathResolver
{
private string currentFileDirectory;
private string currentFilePath;
/// <summary>
/// Initializes a new instance of the <see cref="ImportedFilePathResolver"/> class.
/// </summary>
/// <param name="currentFilePath">The path to the currently processed file.</param>
public ImportedFilePathResolver(string 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)
{
filePath = filePath.Replace('\\', '/').Trim();
if(filePath.StartsWith("~"))
{
filePath = VirtualPathUtility.ToAbsolute(filePath);
}
if(filePath.StartsWith("/"))
{
filePath = HostingEnvironment.MapPath(filePath);
}
else if(!Path.IsPathRooted(filePath))
{
filePath = Path.Combine(currentFileDirectory, filePath);
}
return filePath;
}
}
public class LessMinify : IBundleTransform
{
/// <summary>
/// Processes the specified bundle of LESS files.
/// </summary>
/// <param name="bundle">The LESS bundle.</param>
public void Process(BundleContext context, BundleResponse bundle)
{
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);
foreach(FileInfo file in bundle.Files)
{
SetCurrentFilePath(lessParser, file.FullName);
string source = File.ReadAllText(file.FullName);
content.Append(lessEngine.TransformToCss(source, file.FullName));
content.AppendLine();
AddFileDependencies(lessParser);
}
bundle.Content = content.ToString();
bundle.ContentType = "text/css";
//base.Process(context, bundle);
}
/// <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, false);
}
/// <summary>
/// Adds imported files to the collection of files on which the current response is dependent.
/// </summary>
/// <param name="lessParser">The LESS parser.</param>
private void AddFileDependencies(Parser lessParser)
{
IPathResolver pathResolver = GetPathResolver(lessParser);
foreach(string importedFilePath in lessParser.Importer.Imports)
{
string fullPath = pathResolver.GetFullPath(importedFilePath);
HttpContext.Current.Response.AddFileDependency(fullPath);
}
lessParser.Importer.Imports.Clear();
}
/// <summary>
/// Returns an <see cref="IPathResolver"/> instance used by the specified LESS lessParser.
/// </summary>
/// <param name="lessParser">The LESS prser.</param>
private IPathResolver GetPathResolver(Parser lessParser)
{
var importer = lessParser.Importer as Importer;
if(importer != null)
{
var fileReader = importer.FileReader as FileReader;
if(fileReader != null)
{
return fileReader.PathResolver;
}
}
return null;
}
/// <summary>
/// Informs the LESS parser about the path to the currently processed file.
/// This is done by using 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)
{
var fileReader = importer.FileReader as FileReader;
if(fileReader == null)
{
importer.FileReader = fileReader = new FileReader();
}
var pathResolver = fileReader.PathResolver as ImportedFilePathResolver;
if(pathResolver != null)
{
pathResolver.CurrentFilePath = currentFilePath;
}
else
{
fileReader.PathResolver = new ImportedFilePathResolver(currentFilePath);
}
}
else
{
throw new InvalidOperationException("Unexpected importer type on dotless parser");
}
}
}
// <copyright>
// Copyright (c) 2011+ Dusan Janosik, MIT License
// </copyright>
using System;
using Microsoft.Web.Optimization;
using Yahoo.Yui.Compressor;
namespace MoonCode.Web.Optimization
{
/// <summary>
/// The bundle transform used to minify CSS files by using YUI Compressor for .Net.
/// </summary>
public class YuiCssMinify : IBundleTransform
{
/// <summary>
/// Processes the specified bundle of CSS files.
/// </summary>
/// <param name="bundle">The CSS bundle.</param>
public virtual void Process(BundleResponse bundle)
{
if (bundle == null)
{
throw new ArgumentNullException("bundle");
}
bundle.Content = CssCompressor.Compress(bundle.Content, 0, CssCompressionType.Hybrid, true);
bundle.ContentType = "text/css";
}
}
}
// <copyright>
// Copyright (c) 2011+ Dusan Janosik, MIT License
// </copyright>
using System;
using Microsoft.Web.Optimization;
using Yahoo.Yui.Compressor;
namespace MoonCode.Web.Optimization
{
/// <summary>
/// The bundle transform used to minify JS files by using YUI Compressor for .Net.
/// </summary>
public class YuiJsMinify : IBundleTransform
{
/// <summary>
/// Processes the specified bundle of JS files.
/// </summary>
/// <param name="bundle">The JS bundle.</param>
public virtual void Process(BundleResponse bundle)
{
if (bundle == null)
{
throw new ArgumentNullException("bundle");
}
bundle.Content = JavaScriptCompressor.Compress(bundle.Content);
bundle.ContentType = "text/javascript";
}
}
}
@chrisortman
Copy link
Author

Updated for dotless 1.2.4

@LaleWolf
Copy link

needed to change it for mvc 4

using System;
using System.Web.Optimization;
using Yahoo.Yui.Compressor;

namespace Mvc4_BundlingAndMinifaction.Optimization
{
    /// <summary>
    /// The bundle transform used to minify CSS files by using YUI Compressor for .Net.
    /// </summary>
    public class YuiCssMinify : IBundleTransform
    {
        /// <summary>
        /// Processes the specified bundle of CSS files.
        /// </summary>
        /// <param name="bundle">The CSS bundle.</param>
        public void Process(BundleContext context, BundleResponse bundle)
        {
            if (bundle == null)
            {
                throw new ArgumentNullException("bundle");
            }


            bundle.Content = new CssCompressor().Compress(bundle.Content);
            bundle.ContentType = "text/css";
        }
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment