This uses mini_racer to bind to the actual JavaScript implementation of Handlebars.js so that you can use it from ruby. This is a fork of handlebars.rb to change out the deprecated therubyracer JS integration. 99% the same idea as the better-named minibars.
Please be mindful of how this library works: it brings in the full libv8 JS VM to your ruby environment. Each
Context
is a full blown JS machine (memory management, JIT, etc). This fork does not support attaching ruby
functions to the JS VM.
Note on security: do not compile untrusted Handlebars templates. We compile Handlebars template by building ad-hoc javascript statements, a bad actor could perform an SQL-injection like attack using the v8 environment for bad things.
require 'smolbars'
smolbars = Smolbars::Context.new
template = smolbars.compile("{{say}} {{what}}")
template.call(:say => "Hey", :what => "Yuh!") #=> "Hey Yuh!"
You must write helpers with JavaScript. The JavaScript code should include calls to the Handlebars class registration function.
require 'smolbars'
helper = %Q{
Handlebars.registerHelper("nthTimes", function(n, options){
var buffer = "";
for(var i = 0; i < n; i++) {
buffer += options.fn();
}
return buffer;
});
}
smolbars = Smolbars::Context.new
smolbars.eval(helper)
template = smolbars.compile('{{#nthTimes 2}}yep {{/nthTimes}}hurrah!')
template.call # 'yep yep hurrah!'
You must write partials with JavaScript. The JavaScript code should include calls to the Handlebars class registration function.
require 'smolbars'
partial = %Q{
Handlebars.registerPartial("legend", "I am {{ who }}");
}
smolbars = Smolbars::Context.new
smolbars.eval(partial)
template = smolbars.compile('{{> legend}}')
template.call # 'I am Legend!'
In general, you should not trust user-provided templates: a template can call any method
(with no arguments) or access any property on any object in the Smolbars::Context
.
If you'd like to render user-provided templates, you'd want to make sure you do so in a sanitized Context, e.g. no filesystem access, read-only or no database access, etc.
You can try setting the timeout on a Smolbars::Context through kwargs that are passed to the underlying JS instance
Smolbars::Context.new(timeout: 500)
rspec spec/
Building an image:
docker compose run --rm app bundle install
Running tests:
docker compose run --rm app bundle exec rspec spec/