dieseltravis (owner)

Revisions

gist: 130913 Download_button fork
public
Description:
A C# ASP.Net handler that concatenates, compresses, and caches CSS/JS files
Public Clone URL: git://gist.github.com/130913.git
Embed All Files: show embed
Readme.txt #
1
2
3
4
5
6
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>
YuiCompressor.ashx #
1
<%@ WebHandler Language="C#" CodeBehind="YuiCompressor.ashx.cs" Class="YuiCompressor" %>
YuiCompressor.ashx.cs #
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
using System;
using System.Collections.Generic;
using System.Web;
using Yahoo.Yui.Compressor;
 
public class YuiCompressor : IHttpHandler
{
public const char DELIMITER = ',';
 
public class ContentTypes
{
public const string CSS = "text/css";
public const string JS = "application/x-javascript";
}
 
public class Extensions
{
public const string CSS = ".css";
public const string JS = ".js";
}
 
public class Folders
{
// customize these to your site's paths
public const string CSS = "~/styles/";
public const string JS = "~/scripts/";
}
 
public void ProcessRequest(HttpContext context)
{
context.Response.ContentEncoding = System.Text.Encoding.Default;
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)
}
}
else
{
// 404?
//Throw New System.IO.FileNotFoundException("A filename hasn't been specified.")
}
}
 
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]);
}
}
}
YuiCompressor.ashx.vb #
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
'<%@ 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 Class ContentTypes
        Public Const Css As String = "text/css"
        Public Const Js As String = "application/x-javascript"
    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
        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)
            End If
        Else
            ' 404?
            'Throw New System.IO.FileNotFoundException("A filename hasn't been specified.")
        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
        If context.Cache(fileName) Is Nothing Then
            Dim filePath As String = HttpContext.Current.Server.MapPath(folder & fileName)
            Dim output As String = String.Empty
            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.Response.Write(output)
                context.Cache.Insert(fileName, output, New CacheDependency(filePath))
            Catch fnf As System.IO.FileNotFoundException
                ' throw 404?
            End Try
        Else
            context.Response.Write(DirectCast(HttpContext.Current.Cache(fileName), String))
        End If
    End Sub
 
End Class