Skip to content

Instantly share code, notes, and snippets.

@jkrall
Created July 13, 2016 06:49
Show Gist options
  • Save jkrall/923590957bc0a8aa230d50b9e8647a75 to your computer and use it in GitHub Desktop.
Save jkrall/923590957bc0a8aa230d50b9e8647a75 to your computer and use it in GitHub Desktop.
Handlebars.Net NancyFx View Engine
namespace Nancy.ViewEngines.Handlebars
{
using System;
using System.Collections.Generic;
using System.IO;
using global::HandlebarsDotNet;
using Nancy.Responses;
/// <summary>
/// View engine for rendering nustache views.
/// </summary>
public class HandlebarsViewEngine : IViewEngine
{
/// <summary>
/// Gets the extensions file extensions that are supported by the view engine.
/// </summary>
/// <value>An <see cref="IEnumerable{T}"/> instance containing the extensions.</value>
/// <remarks>The extensions should not have a leading dot in the name.</remarks>
public IEnumerable<string> Extensions
{
get { return new[] { "hbs" }; }
}
/// <summary>
/// Initialise the view engine (if necessary)
/// </summary>
/// <param name="viewEngineStartupContext">Startup context</param>
public void Initialize(ViewEngineStartupContext viewEngineStartupContext)
{
foreach (var view in viewEngineStartupContext.ViewLocator.GetAllCurrentlyDiscoveredViews())
{
if (view.Extension=="hbs" && view.Location.Contains("/partials"))
{
using (var reader = File.OpenText(view.Location+"/"+view.Name+"."+view.Extension))
{
var partialTemplate = Handlebars.Compile(reader);
Handlebars.RegisterTemplate(view.Name, partialTemplate);
}
}
}
}
private Action<TextWriter, object> GetOrCompileTemplate(ViewLocationResult viewLocationResult, IRenderContext renderContext)
{
var viewFactory = renderContext.ViewCache.GetOrAdd(
viewLocationResult,
x =>
{
using (var reader = x.Contents.Invoke())
return this.GetCompiledTemplate<dynamic>(reader);
});
var view = viewFactory.Invoke();
return view;
}
private Func<Action<TextWriter, object>> GetCompiledTemplate<TModel>(TextReader reader)
{
var template = Handlebars.Compile(reader);
return () =>
{
return template;
};
}
/// <summary>
/// Renders the view.
/// </summary>
/// <param name="viewLocationResult">A <see cref="ViewLocationResult"/> instance, containing information on how to get the view template.</param>
/// <param name="model">The model that should be passed into the view</param>
/// <param name="renderContext"></param>
/// <returns>A response</returns>
public Response RenderView(ViewLocationResult viewLocationResult, dynamic model, IRenderContext renderContext)
{
return new HtmlResponse
{
Contents = stream =>
{
var template =
this.GetOrCompileTemplate(viewLocationResult, renderContext);
var writer =
new StreamWriter(stream);
template(writer, model);
writer.Flush();
}
};
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment