All Projects → Handlebars-Net → Handlebars.net

Handlebars-Net / Handlebars.net

Licence: mit
A real .NET Handlebars engine

Projects that are alternatives of or similar to Handlebars.net

Mikado
Mikado is the webs fastest template library for building user interfaces.
Stars: ✭ 323 (-55.33%)
Mutual labels:  template-engine, handlebars, mustache
velvet
A sweet velvety templating package
Stars: ✭ 72 (-90.04%)
Mutual labels:  template-engine, handlebars
Yarte
Yarte stands for Yet Another Rust Template Engine
Stars: ✭ 189 (-73.86%)
Mutual labels:  template-engine, handlebars
hyperstache
👨‍🦰 Handlebars just got a trim, alternative JS template engine, 2kb gzip
Stars: ✭ 36 (-95.02%)
Mutual labels:  mustache, handlebars
Bbmustache
Binary pattern match Based Mustache template engine for Erlang/OTP.
Stars: ✭ 141 (-80.5%)
Mutual labels:  template-engine, mustache
Aeromock
Lightweight mock web application server
Stars: ✭ 152 (-78.98%)
Mutual labels:  template-engine, handlebars
morestachio
Lightweight, powerful, flavorful, template engine.
Stars: ✭ 45 (-93.78%)
Mutual labels:  template-engine, mustache
Handlebars.java
Logic-less and semantic Mustache templates with Java
Stars: ✭ 1,204 (+66.53%)
Mutual labels:  template-engine, handlebars
moustachu
Mustache templating for Nim
Stars: ✭ 58 (-91.98%)
Mutual labels:  template-engine, mustache
Handlebars
Fullest Handlebars.js templating support for Atom and Sublime Text 2 / 3. Also drives syntax colouring on Github and in Visual Studio Code. Install from: https://atom.io/packages/Handlebars and https://packagecontrol.io/packages/Handlebars.
Stars: ✭ 292 (-59.61%)
Mutual labels:  handlebars, mustache
Lightncandy
An extremely fast PHP implementation of handlebars ( http://handlebarsjs.com/ ) and mustache ( http://mustache.github.io/ ),
Stars: ✭ 565 (-21.85%)
Mutual labels:  handlebars, mustache
Grmustache.swift
Flexible Mustache templates for Swift
Stars: ✭ 538 (-25.59%)
Mutual labels:  template-engine, mustache
Handlebars Iron
Handlebars middleware for Iron web framework
Stars: ✭ 119 (-83.54%)
Mutual labels:  template-engine, handlebars
Spring Boot Email Tools
A set of services and tools for sending emails in a Spring Boot 1.5.x application using a Template Engine
Stars: ✭ 164 (-77.32%)
Mutual labels:  template-engine, mustache
Api2html
Using the data from your API, generate the HTML on the fly! Server-side rendering of the mustache templates
Stars: ✭ 97 (-86.58%)
Mutual labels:  template-engine, mustache
HandlebarsCookbook
A cookbook of handlebars and mustache, focus on handlebars.js , mustache.js and lightncandy usage
Stars: ✭ 20 (-97.23%)
Mutual labels:  mustache, handlebars
Ramhorns
Fast Mustache template engine implementation in pure Rust.
Stars: ✭ 172 (-76.21%)
Mutual labels:  handlebars, mustache
Gluebert
gluebert.js is a tiny helper lazy loading DOM Elements, StyleSheets and JavaScript files using dynamic import and code splitting
Stars: ✭ 194 (-73.17%)
Mutual labels:  handlebars, mustache
django-mustache
Mustache (Pystache) template engine for Django 1.8 and newer, with support for Django context processors. Designed to support offline-capable web apps via progressive enhancement.
Stars: ✭ 20 (-97.23%)
Mutual labels:  template-engine, mustache
Squirrelly
Semi-embedded JS template engine that supports helpers, filters, partials, and template inheritance. 4KB minzipped, written in TypeScript ⛺
Stars: ✭ 359 (-50.35%)
Mutual labels:  template-engine, handlebars

Handlebars.Net

CI Nuget performance


Quality Gate Status Reliability Rating Security Rating

Bugs Code Smells Coverage


Stack Exchange questions GitHub issues questions GitHub issues help wanted


Blistering-fast Handlebars.js templates in your .NET application.

Handlebars.js is an extension to the Mustache templating language created by Chris Wanstrath. Handlebars.js and Mustache are both logicless templating languages that keep the view and the code separated like we all know they should be.

Check out the handlebars.js documentation for how to write Handlebars templates.

Handlebars.Net doesn't use a scripting engine to run a Javascript library - it compiles Handlebars templates directly to IL bytecode. It also mimics the JS library's API as closely as possible.

Install

dotnet add package Handlebars.Net

Usage

string source =
@"<div class=""entry"">
  <h1>{{title}}</h1>
  <div class=""body"">
    {{body}}
  </div>
</div>";

var template = Handlebars.Compile(source);

var data = new {
    title = "My new post",
    body = "This is my first post!"
};

var result = template(data);

/* Would render:
<div class="entry">
  <h1>My New Post</h1>
  <div class="body">
    This is my first post!
  </div>
</div>
*/

Registering Partials

string source =
@"<h2>Names</h2>
{{#names}}
  {{> user}}
{{/names}}";

string partialSource =
@"<strong>{{name}}</strong>";

Handlebars.RegisterTemplate("user", partialSource);

var template = Handlebars.Compile(source);

var data = new {
  names = new [] {
    new {
        name = "Karen"
    },
    new {
        name = "Jon"
    }
  }
};

var result = template(data);

/* Would render:
<h2>Names</h2>
  <strong>Karen</strong>
  <strong>Jon</strong>
*/

Registering Helpers

Handlebars.RegisterHelper("link_to", (writer, context, parameters) => 
{
    writer.WriteSafeString($"<a href='{context["url"]}'>{context["text"]}</a>");
});

string source = @"Click here: {{link_to}}";

var template = Handlebars.Compile(source);

var data = new {
    url = "https://github.com/rexm/handlebars.net",
    text = "Handlebars.Net"
};

var result = template(data);

/* Would render:
Click here: <a href='https://github.com/rexm/handlebars.net'>Handlebars.Net</a>
*/

This will expect your views to be in the /Views folder like so:

Views\layout.hbs                |<--shared as in \Views            
Views\partials\somepartial.hbs   <--shared as in  \Views\partials
Views\{Controller}\{Action}.hbs 
Views\{Controller}\{Action}\partials\somepartial.hbs 

Registering Block Helpers

Handlebars.RegisterHelper("StringEqualityBlockHelper", (output, options, context, arguments) => 
{
    if (arguments.Length != 2)
    {
        throw new HandlebarsException("{{#StringEqualityBlockHelper}} helper must have exactly two arguments");
    }

    var left = arguments.At<string>(0);
    var right = arguments[1] as string;
    if (left == right) options.Template(output, context);
    else options.Inverse(output, context);
});

var animals = new Dictionary<string, string>() 
{
	{"Fluffy", "cat" },
	{"Fido", "dog" },
	{"Chewy", "hamster" }
};

var template = "{{#each this}}The animal, {{@key}}, {{#StringEqualityBlockHelper @value 'dog'}}is a dog{{else}}is not a dog{{/StringEqualityBlockHelper}}.\r\n{{/each}}";
var compiledTemplate = Handlebars.Compile(template);
string templateOutput = compiledTemplate(animals);

/* Would render
The animal, Fluffy, is not a dog.
The animal, Fido, is a dog.
The animal, Chewy, is not a dog.
*/

Register custom value formatter

In case you need to apply custom value formatting (e.g. DateTime) you can use IFormatter and IFormatterProvider interfaces:

public sealed class CustomDateTimeFormatter : IFormatter, IFormatterProvider
{
    private readonly string _format;

    public CustomDateTimeFormatter(string format) => _format = format;

    public void Format<T>(T value, in EncodedTextWriter writer)
    {
        if(!(value is DateTime dateTime)) 
            throw new ArgumentException("supposed to be DateTime");
        
        writer.Write($"{dateTime.ToString(_format)}");
    }

    public bool TryCreateFormatter(Type type, out IFormatter formatter)
    {
        if (type != typeof(DateTime))
        {
            formatter = null;
            return false;
        }

        formatter = this;
        return true;
    }
}

[Fact]
public void DateTimeFormatter(IHandlebars handlebars)
{
    var source = "{{now}}";

    var format = "d";
    var formatter = new CustomDateTimeFormatter(format);
    handlebars.Configuration.FormatterProviders.Add(formatter);

    var template = handlebars.Compile(source);
    var data = new
    {
        now = DateTime.Now
    };
    
    var result = template(data);
    Assert.Equal(data.now.ToString(format), result);
}

Notes

  • Formatters are resolved in reverse order according to registration. If multiple providers can provide formatter for a type the last registered would be used.

Compatibility feature toggles

Compatibility feature toggles defines a set of settings responsible for controlling compilation/rendering behavior. Each of those settings would enable certain feature that would break compatibility with canonical Handlebars. By default all toggles are set to false.

Legend
  • Areas
    • Compile-time: takes affect at the time of template compilation
    • Runtime: takes affect at the time of template rendering

RelaxedHelperNaming

If true enables support for Handlebars.Net helper naming rules. This enables helper names to be not-valid Handlebars identifiers (e.g. {{ one.two }}). Such naming is not supported in Handlebarsjs and would break compatibility.

Areas
  • Compile-time
Example
[Fact]
public void HelperWithDotSeparatedName()
{
    var source = "{{ one.two }}";
    var handlebars = Handlebars.Create();
    handlebars.Configuration.Compatibility.RelaxedHelperNaming = true;
    handlebars.RegisterHelper("one.two", (context, arguments) => 42);

    var template = handlebars.Compile(source);
    var actual = template(null);
    
    Assert.Equal("42", actual);
}

Performance

Compilation

Compared to rendering, compiling is a fairly intensive process. While both are still measured in millseconds, compilation accounts for the most of that time by far. So, it is generally ideal to compile once and cache the resulting function to be re-used for the life of your process.

Rendering

Nearly all time spent in rendering is in the routine that resolves values against the model. Different types of objects have different performance characteristics when used as models.

Model Types

  • The absolute fastest model is a IDictionary<string, object> (microseconds).
  • The next fastest is a POCO (typically a few milliseconds for an average-sized template and model), which uses traditional reflection and is fairly fast.
  • Rendering starts to get slower (into the tens of milliseconds or more) on dynamic objects.
  • The slowest (up to hundreds of milliseconds or worse) tend to be objects with custom type implementations (such as ICustomTypeDescriptor) that are not optimized for heavy reflection.

A frequent performance issue that comes up is JSON.NET's JObject, which for reasons we haven't fully researched, has very slow reflection characteristics when used as a model in Handlebars.Net. A simple fix is to just use JSON.NET's built-in ability to deserialize a JSON string to an ExpandoObject instead of a JObject. This will yield nearly an order of magnitude improvement in render times on average.

Future roadmap

TBD

Contributing

Pull requests are welcome! The guidelines are pretty straightforward:

  • Only add capabilities that are already in the Mustache / Handlebars specs
  • Avoid dependencies outside of the .NET BCL
  • Maintain cross-platform compatibility (.NET/Mono; Windows/OSX/Linux/etc)
  • Follow the established code format
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].