Skip to content

Instantly share code, notes, and snippets.

@garth
Created November 8, 2012 14:40
Show Gist options
  • Save garth/4039168 to your computer and use it in GitHub Desktop.
Save garth/4039168 to your computer and use it in GitHub Desktop.
Pre-compile emberjs handlebars templates with ASP.NET MVC Bundles
// use NuGet to add BundleTransformer to your project
// add ember.js and handlebars.js to the /Scripts folder
// in bundle config add something like this
bundles.Add(new ScriptBundle("~/bundles/templates").IncludeDirectory(
"~/templates", "*.handlebars"));
// or like this
bundles.Add(new ScriptBundle("~/bundles/teamplates").Include(
"~/templates/application.handlebars",
"~/templates/header.handlebars",
"~/templates/footer.handlebars")));
public class HandlebarsAssetHandler : AssetHandlerBase {
public override string ContentType {
get { return BundleTransformer.Core.Constants.ContentType.Js; }
}
/// <summary>Constructs instance of TypeScript asset handler</summary>
public HandlebarsAssetHandler()
: this(HttpContext.Current.Cache,
BundleTransformerContext.Current.GetFileSystemWrapper(),
BundleTransformerContext.Current.GetCoreConfiguration().AssetHandler,
BundleTransformerContext.Current.GetApplicationInfo()) { }
/// <summary>Constructs instance of Handlebars asset handler</summary>
/// <param name="cache">Server cache</param>
/// <param name="fileSystemWrapper">File system wrapper</param>
/// <param name="assetHandlerConfig">Configuration settings of HTTP-handler that responsible
/// for text output of processed asset</param>
/// <param name="applicationInfo">Information about web application</param>
public HandlebarsAssetHandler(Cache cache, IFileSystemWrapper fileSystemWrapper,
AssetHandlerSettings assetHandlerConfig, IHttpApplicationInfo applicationInfo)
: base(cache, fileSystemWrapper, assetHandlerConfig, applicationInfo) { }
/// <summary>Translates handlebars templates to JS-code</summary>
/// <param name="asset">Handlebars template</param>
/// <returns>Asset with translated code</returns>
protected override IAsset ProcessAsset(IAsset asset) {
ITranslator handlebarsTranslator = BundleTransformerContext.Current.GetJsTranslatorInstance("HandlebarsTranslator");
handlebarsTranslator.IsDebugMode = _applicationInfo.IsDebugMode;
return handlebarsTranslator.Translate(asset);
}
}
public class HandlebarsTranslator : TranslatorWithNativeMinificationBase {
private readonly MsieJsEngine jsEngine = new MsieJsEngine();
public HandlebarsTranslator() {
//setup a dummy browser environment with jquery
jsEngine.Execute(@"
var window = this
//dummy jQuery
var $ = jQuery = function () { return jQuery }
jQuery.ready = function () { return jQuery }
jQuery.inArray = function () { return jQuery }
jQuery.jquery = '1.8.2'
jQuery.event = { fixHooks: {} }
//dummy DOM element
var element = {
firstChild: function () { return element },
innerHTML: function () { return element }
}
// DOM
var document = {
createRange: false,
createElement: function () { return element }
}
// Console
var console = {
log: function () {}
}
");
//load handlebars and ember
var server = new AspServerPathResolver();
jsEngine.ExecuteFile(server.GetFullPath("~/Scripts/handlebars.js"));
jsEngine.ExecuteFile(server.GetFullPath("~/Scripts/ember.js"));
}
public override IAsset Translate(IAsset asset) {
// inject the template
jsEngine.SetVariableValue("template", asset.Content);
// compile
string templateJs = jsEngine.Evaluate<string>("Ember.Handlebars.precompile(template).toString()");
// add the template to the collection
var templateName = Path.GetFileNameWithoutExtension(asset.Path);
asset.Content = "Ember.TEMPLATES['" + templateName + "'] = Ember.Handlebars.template(" + templateJs + ");";
return asset;
}
public override IList<IAsset> Translate(IList<IAsset> assets) {
foreach (IAsset asset in assets) {
Translate(asset);
}
return assets;
}
}
<!-- Add relevant bits to your web config and fix namespaces/assembly names -->
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.web>
<httpHandlers>
<add path="*.handlebars" verb="GET" type="yournamespace.HandlebarsAssetHandler, yourassembly" />
</httpHandlers>
</system.web>
<system.webServer>
<handlers>
<add name="HandlebarsAssetHandler" path="*.handlebars" verb="GET" type="yournamespace.HandlebarsAssetHandler, yourassembly" resourceType="File" preCondition="" />
</handlers>
</system.webServer>
<bundleTransformer xmlns="http://tempuri.org/BundleTransformer.Configuration.xsd">
<core>
<js>
<translators>
<add name="HandlebarsTranslator" type="yournamespace.HandlebarsTranslator, yourassembly" enabled="true" />
</translators>
</js>
</core>
</bundleTransformer>
</configuration>
@garth
Copy link
Author

garth commented Nov 12, 2012

This example turns out to be buggy for production use, but can be used as a starting point.

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