Skip to content

Instantly share code, notes, and snippets.

@prabirshrestha
Forked from dieseltravis/Readme.txt
Created July 27, 2010 07:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save prabirshrestha/491883 to your computer and use it in GitHub Desktop.
Save prabirshrestha/491883 to your computer and use it in GitHub Desktop.
YUI compressor
Example usage:
...in <head>:
<link rel="stylesheet" type="text/css" href="/YuiCompressor.ashx?css=reset,style" />
...just before the </body>:
<script type="text/javascript" src="/YuiCompressor.ashx?js=main,someotherscript"></script>
Changelog:
2010-02-18: Updated to support HTTP compression
<%@ WebHandler Language="C#" CodeBehind="YuiCompressor.ashx.cs" Class="YuiCompressor" %>
using System;
using System.Collections.Generic;
using System.Web;
using Yahoo.Yui.Compressor;
public class YuiCompressor : IHttpHandler
{
public const char DELIMITER = ',';
public const bool ENABLEHTTPCOMPRESSION = true;
public TimeSpan CacheDuration = TimeSpan.FromDays(1);
public class ContentTypes
{
public const string CSS = "text/css";
public const string JS = "application/x-javascript";
public const string ERROR = "text/plain";
}
public class Folders
{
// customize these to your site's paths
public const string CSS = "~/styles/";
public const string JS = "~/scripts/";
}
public class Extensions
{
public const string CSS = ".css";
public const string JS = ".js";
}
public void ProcessRequest(HttpContext context)
{
context.Response.ContentEncoding = System.Text.Encoding.Default;
context.Response.Cache.SetExpires(DateTime.Now.Add(CacheDuration));
context.Response.Cache.SetMaxAge(CacheDuration);
context.Response.Cache.SetCacheability(HttpCacheability.Private);
string cssFiles = context.Request.QueryString["css"];
string jsFiles = context.Request.QueryString["js"];
string fileName = context.Request.QueryString["f"];
if (! string.IsNullOrEmpty(cssFiles))
{
// A list of CSS files has been passed in, write each file's contents to the response object
context.Response.ContentType = ContentTypes.CSS;
foreach (string cssFile in cssFiles.Split(DELIMITER))
{
WriteCompressedFile(context, cssFile + Extensions.CSS, Folders.CSS);
}
}
else if (! string.IsNullOrEmpty(jsFiles))
{
// A list of JS files has been passed in, write each file's contents to the response object
context.Response.ContentType = ContentTypes.JS;
foreach (string jsFile in jsFiles.Split(DELIMITER))
{
WriteCompressedFile(context, jsFile + Extensions.JS, Folders.JS);
}
}
else if (! string.IsNullOrEmpty(fileName))
{
// A specific file has been passed in, write that file's contents to the response object
if (fileName.EndsWith(Extensions.JS))
{
context.Response.ContentType = ContentTypes.JS;
WriteCompressedFile(context, fileName, Folders.JS);
}
else if (fileName.EndsWith(Extensions.CSS))
{
context.Response.ContentType = ContentTypes.CSS;
WriteCompressedFile(context, fileName, Folders.CSS);
}
else
{
// 500?
//Throw New System.IO.FileNotFoundException("The file specified isn't an allowed type.", fileName)
context.Response.ContentType = ContentTypes.ERROR;
}
}
else
{
// 404?
//Throw New System.IO.FileNotFoundException("A filename hasn't been specified.")
context.Response.ContentType = ContentTypes.ERROR;
context.Response.Write(Environment.NewLine);
}
// compress output if enabled
if (ENABLEHTTPCOMPRESSION)
{
string encodingsAccepted = context.Request.Headers("Accept-Encoding");
if (! string.IsNullOrEmpty(encodingsAccepted))
{
encodingsAccepted = encodingsAccepted.ToLowerInvariant();
if (encodingsAccepted.Contains("deflate"))
{
context.Response.AppendHeader("Content-Encoding", "deflate");
context.Response.Filter = New System.IO.Compression.DeflateStream(context.Response.Filter, System.IO.Compression.CompressionMode.Compress);
}
else if (encodingsAccepted.Contains("gzip"))
{
context.Response.AppendHeader("Content-Encoding", "gzip");
context.Response.Filter = New System.IO.Compression.GZipStream(context.Response.Filter, System.IO.Compression.CompressionMode.Compress);
}
}
}
}
public bool IsReusable
{
get
{
return false;
}
}
public void WriteCompressedFile(HttpContext context, string fileName, string folder)
{
// Add each file's compressed contents to the cache as it is read with a file dependency on itself
if (context.Cache[fileName] == null)
{
string filePath = HttpContext.Current.Server.MapPath(folder + fileName);
string output = string.Empty;
try
{
output = System.IO.File.ReadAllText(filePath);
if (folder == Folders.JS)
{
output = JavaScriptCompressor.Compress(output) + Environment.NewLine;
}
else
{
output = CssCompressor.Compress(output) + Environment.NewLine;
}
context.Response.Write(output);
context.Cache.Insert(fileName, output, new System.Web.Caching.CacheDependency(filePath));
}
catch (System.IO.FileNotFoundException)
{
// throw 404?
}
}
else
{
context.Response.Write((string) context.Cache[fileName]);
}
}
}
'<%@ WebHandler Language="VB" Class="YuiCompressor" %>
Imports System
Imports System.Web
Imports Yahoo.Yui.Compressor
Public Class YuiCompressor : Implements IHttpHandler
Public Const Delimiter As String = ","
Public Const EnableHttpCompression As Boolean = True
Public cacheDuration As TimeSpan = TimeSpan.FromDays(1)
Public Class ContentTypes
Public Const Css As String = "text/css"
Public Const Js As String = "application/x-javascript"
Public Const Err As String = "text/plain"
End Class
Public Class Folders
Public Const Css As String = "~/styles/"
Public Const Js As String = "~/scripts/"
End Class
Public Class Extensions
Public Const Css As String = ".css"
Public Const Js As String = ".js"
End Class
Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
context.Response.ContentEncoding = Encoding.Default
context.Response.Cache.SetExpires(DateTime.Now.Add(cacheDuration))
context.Response.Cache.SetMaxAge(cacheDuration)
context.Response.Cache.SetCacheability(HttpCacheability.Private)
Dim cssFiles As String = context.Request.QueryString("css")
Dim jsFiles As String = context.Request.QueryString("js")
Dim fileName As String = context.Request.QueryString("f")
If Not String.IsNullOrEmpty(cssFiles) Then
' A list of CSS files has been passed in, write each file's contents to the response object
context.Response.ContentType = ContentTypes.Css
For Each cssFile As String In cssFiles.Split(Delimiter)
WriteCompressedFile(context, cssFile & Extensions.Css, Folders.Css)
Next
ElseIf Not String.IsNullOrEmpty(jsFiles) Then
' A list of JS files has been passed in, write each file's contents to the response object
context.Response.ContentType = ContentTypes.Js
For Each jsFile As String In jsFiles.Split(Delimiter)
WriteCompressedFile(context, jsFile & Extensions.Js, Folders.Js)
Next
ElseIf Not String.IsNullOrEmpty(fileName) Then
' A specific file has been passed in, write that file's contents to the response object
If fileName.EndsWith(Extensions.Js) Then
context.Response.ContentType = ContentTypes.Js
WriteCompressedFile(context, fileName, Folders.Js)
ElseIf fileName.EndsWith(Extensions.Css) Then
context.Response.ContentType = ContentTypes.Css
WriteCompressedFile(context, fileName, Folders.Css)
Else
' 500?
'Throw New System.IO.FileNotFoundException("The file specified isn't an allowed type.", fileName)
context.Response.ContentType = ContentTypes.Err
End If
Else
' 404?
'Throw New System.IO.FileNotFoundException("A filename hasn't been specified.")
context.Response.ContentType = ContentTypes.Err
context.Response.Write(Environment.NewLine)
End If
' compress output if enabled
If EnableHttpCompression Then
Dim encodingsAccepted As String = context.Request.Headers("Accept-Encoding")
If Not (String.IsNullOrEmpty(encodingsAccepted)) Then
encodingsAccepted = encodingsAccepted.ToLowerInvariant()
If (encodingsAccepted.Contains("deflate")) Then
context.Response.AppendHeader("Content-Encoding", "deflate")
context.Response.Filter = New System.IO.Compression.DeflateStream(context.Response.Filter, System.IO.Compression.CompressionMode.Compress)
ElseIf (encodingsAccepted.Contains("gzip")) Then
context.Response.AppendHeader("Content-Encoding", "gzip")
context.Response.Filter = New System.IO.Compression.GZipStream(context.Response.Filter, System.IO.Compression.CompressionMode.Compress)
End If
End If
End If
End Sub
Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
Get
Return False
End Get
End Property
Public Sub WriteCompressedFile(ByVal context As HttpContext, ByVal fileName As String, ByVal folder As String)
' Add each file's compressed contents to the cache as it is read with a file dependency on itself
Dim output As String = String.Empty
If context.Cache(fileName) Is Nothing Then
Dim filePath As String = HttpContext.Current.Server.MapPath(folder & fileName)
Try
output = System.IO.File.ReadAllText(filePath)
If folder = Folders.Js Then
output = JavaScriptCompressor.Compress(output) & vbCrLf
Else
output = CssCompressor.Compress(output) & vbCrLf
End If
context.Cache.Insert(fileName, output, New CacheDependency(filePath))
Catch fnf As System.IO.FileNotFoundException
' throw 404?
End Try
Else
output = DirectCast(HttpContext.Current.Cache(fileName), String)
End If
context.Response.Write(output)
End Sub
End Class
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment