A long-lived project that still receives updates
Pure Ruby library for Handlebars templates
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

~> 1.63
~> 0.14.0
~> 0.4, >= 0.4.12
~> 13.0
~> 3.10

Runtime

~> 2.0
 Project Readme

ruby-handlebars

Build status

Pure Ruby library for Handlebars template system. This should become an alternative for using the Handlebars javascript library via handlebars.rb.

Installing

Simply run:

gem install mvz-ruby-handlebars

No need for libv8, ruby-racer or any JS related tool.

Using

A very simple case:

require 'ruby-handlebars'

hbs = Handlebars::Handlebars.new
hbs.compile("Hello {{name}}").call({name: 'world'})
# Gives: "Hello world", how original ...

You can also use partials:

hbs.register_partial('full_name', "{{person.first_name}} {{person.last_name}}")
hbs.compile("Hello {{> full_name}}").call({person: {first_name: 'Pinkie', last_name: 'Pie'}})
# Gives: "Hello Pinkie Pie"

Partials support parameters:

hbs.register_partial('full_name', "{{fname}} {{lname}}")
hbs.compile("Hello {{> full_name fname='jon' lname='doe'}}")
# Gives: "Hello jon doe"

You can also register inline helpers:

hbs.register_helper('strip') {|context, value| value.strip}
hbs.compile("Hello {{strip name}}").call({name: '                       world     '})
# Will give (again ....): "Hello world"

or block helpers:

hbs.register_helper('comment') do |context, commenter, block|
  block.fn(context).split("\n").map do |line|
    "#{commenter} #{line}"
  end.join("\n")
end

hbs.compile("{{#comment '//'}}My comment{{/comment}}").call
# Will give: "// My comment"

Note that in any block helper you can use an else block:

hbs.register_helper('markdown') do |context, block, else_block|
  html = md_to_html(block.fn(context))
  html.nil? : else_block.fn(context) : html
end

template = [
  "{{#markdown}}",
  "  {{ description }}",
  "{{else}}",
  "  Description is not valid markdown, no preview available",
  "{{/markdown}}"
].join("\n")

hbs.compile(template).call({description: my_description})
# Output will depend on the validity of the 'my_description' variable

Default helpers:

Three default helpers are provided: each, if and unless.

The each helper let you walk through a list. You can either use the basic notation and referencing the current item as this:

  {{#each items}}
    {{{ this }}}
  {{else}}
    No items
  {{/each}}

or the "as |name|" notation:

  {{#each items as |item| }}
    {{{ item }}}
  {{else}}
    No items
  {{/each}}

The if helper can be used to write conditionnal templates:

  {{#if my_condition}}
    It's ok
  {{else}}
    or maybe not
  {{/if}}

The unless helper works the opposite way to if:

  {{#unless my_condition}}
    It's not ok
  {{else}}
    or maybe it is
  {{/unless}}

Currently, if you call an unknown helper, it will raise an exception. You can override that by registering your own version of the helperMissing helper. Note that only the name of the missing helper will be provided.

For example:

hbs.register_helper('helperMissing') do |context, name|
  puts "No helper found with name #{name}"
end

Limitations and roadmap

This gem does not reuse the real Handlebars code (the JS one) and not everything is handled yet (but it will be someday ;) ):

  • the parser is not fully tested yet, it may complain with spaces ...
  • parsing errors are, well, not helpful at all

Aknowledgements

This is a fork of the ruby-handlebars gem. Eventually I hope to have all my changes accepted upstream so I can abandon this fork.