- Dynamic CSS Processor
- Saturday, January 24th, 2009 at 7:57:34pm MST
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using System.Text;
- using System.Text.RegularExpressions;
- using System.Web;
- using System.Web.UI;
- public class StyleSheetHandler : IHttpHandler
- {
- protected Dictionary<StylesheetCacheKey, string> _cache; // Memory cache of processed stylesheets.
- public StyleSheetHandler()
- {
- }
- public bool IsReusable
- {
- get { return true; }
- }
- public void ProcessRequest(HttpContext context)
- {
- var rawFileName = context.Request.PhysicalPath;
- var rawFileLastModified = File.GetLastWriteTimeUtc(rawFileName);
- var browserName = context.Request.Browser.Browser;
- var newCacheKey = new StylesheetCacheKey(rawFileName, rawFileLastModified, browserName, browserVersion);
- // Check for entry in cache of processed contents of stylesheets that is at least as recent as last
- // modified time of raw file.
- var cacheEntry = _cache.SingleOrDefault(entry => entry.Key.Equals(newCacheKey) &&
- entry.Key.RawFileLastModified >= newCacheKey.RawFileLastModified);
- string processedContent;
- if (cacheEntry.Value != null)
- {
- // Found entry in cache.
- processedContent = cacheEntry.Value;
- }
- else
- {
- // Process raw content of stylesheet file.
- var rawContent = File.ReadAllText(rawFileName);
- processedContent = ProcessStylesheet(rawContent, browserName, browserVersion);
- // Add processed stylesheet to cache.
- _cache[newCacheKey] = processedContent;
- }
- // Write process content of stylesheet to response stream.
- context.Response.ContentType = "text/css";
- context.Response.Output.Write(processedContent);
- context.Response.Flush();
- }
- protected string ProcessStylesheet(string content, string browserName, Version browserVersion)
- {
- // Matches blocks (regions) of commented text (of form "/*{comment}*/").
- // Matches browser-conditional tags of form "[[?{browser condition} {true result} | {false result}]]".
- var regexTags = new Regex(@"\[\?(?<browser>.+?) +?(?<trueResult>.*?) ?\| ?(?<falseResult>.*?) *?\]",
- RegexOptions.None);
- // Evaluate tags within each comment block.
- {
- var tagCount = 0;
- {
- tagCount++;
- // Invert condition if preceded by '!'.
- var browser = tagMatch.Groups["browser"].Value;
- bool inverted = false;
- if (browser[0] == '!')
- {
- inverted = true;
- browser = browser.Substring(1);
- }
- return (string.Equals(browser, browserName, StringComparison.InvariantCultureIgnoreCase) ^
- inverted) ? tagMatch.Groups["trueResult"].Value : tagMatch.Groups["falseResult"].Value;
- }));
- return (tagCount > 0) ? evaluatedText.Substring(2, evaluatedText.Length - 4) : blockMatch.Value;
- }));
- return processedContent;
- }
- protected struct StylesheetCacheKey
- {
- public string StylesheetPath; // Path of raw stylesheet file.
- public DateTime RawFileLastModified; // Time at which raw file was last modified.
- public string BrowserName; // Name of browser.
- public Version BrowserVersion; // Version of browser.
- public StylesheetCacheKey(string stylesheetPath, DateTime rawFileLastModified, string browserName,
- Version browserVersion)
- {
- this.StylesheetPath = stylesheetPath;
- this.RawFileLastModified = rawFileLastModified;
- this.BrowserName = browserName;
- this.BrowserVersion = browserVersion;
- }
- public override bool Equals(object obj)
- {
- var objKey = (StylesheetCacheKey)obj;
- return this.StylesheetPath.Equals(objKey.StylesheetPath) &&
- this.BrowserName.Equals(objKey.BrowserName) && this.BrowserVersion.Equals(objKey.BrowserVersion);
- }
- public override int GetHashCode()
- {
- return this.StylesheetPath.GetHashCode() ^ this.BrowserName.GetHashCode() ^
- this.BrowserVersion.GetHashCode();
- }
- public override string ToString()
- {
- return string.Format("{0}, {1} {2}", this.StylesheetPath, this.BrowserName,
- this.BrowserVersion.ToString());
- }
- }
- }
advertising
Update the Post
Either update this post and resubmit it with changes, or make a new post.
You may also comment on this post.
Please note that information posted here will expire by default in one month. If you do not want it to expire, please set the expiry time above. If it is set to expire, web search engines will not be allowed to index it prior to it expiring. Items that are not marked to expire will be indexable by search engines. Be careful with your passwords. All illegal activities will be reported and any information will be handed over to the authorities, so be good.