Haml Coffee Assets compiles Haml CoffeeScript templates in the Rails 3.1 asset pipeline, so you can use them as JavaScript templates in your JavaScript heavy Rails application.
Tested on MRI Ruby 1.8.7, 1.9.2, 1.9.3, REE and the latest version of JRuby.
Haml Coffee allows you to write inline CoffeeScript in your HAML JavaScript templates:
#cart
%h2= I18n.t('js.cart.title')
- if @cart.length == 0
%p.empty= I18n.t('js.cart.empty')
- else
%ul
- for item in @cart
%li
.item
= item.name
%a{ :href => "/cart/item/remove/#{ item.id }" }
= I18n.t('js.cart.item.remove')
The simplest way to install Haml Coffee Assets is to use Bundler.
Add haml_coffee_assets
and execjs
to your Gemfile
:
group :assets do
gem 'haml_coffee_assets'
gem 'execjs'
end
And require the hamlcoffee.js
in your app/assets/javascripts/application.js.coffee
:
#= require hamlcoffee
This provides the default escaping and the global context functions. Read more about it in the configuration section below.
Haml Coffee Assets uses ExecJS to pick the best runtime to evaluate the CoffeeScript and generate the JavaScript template.
- With CRuby you want to use a V8 JavaScript Engine or Mozilla SpiderMonkey.
- With JRuby you want to use the Mozilla Rhino.
- On Mac OS X you want to use Apple JavaScriptCore.
- On Linux or as a node.js developer you want to use Node.js (V8).
- On Windows you want to use Microsoft Windows Script Host.
The following sections gives you a short overview of the available JavaScript runtimes and how to install it.
You can install node.js and use its V8 engine. On OS X you may want to install it with Homebrew, on Linux with your package manager and on Windows you have to download and install the executable.
To use the V8 JavaScript Engine, simple add therubyracer
to your Gemfile
.
The Ruby Racer acts as a bridge between Ruby and the V8 engine, that will be automatically installed by the Ruby Racer.
group :development do
gem 'therubyracer'
end
Another alternative is Mustang, a Ruby proxy library for the awesome Google V8
JavaScript engine. Just add mustang
to your Gemfile
:
group :development do
gem 'mustang'
end
To use Mozilla SpiderMonkey, simple add johnson
to your Gemfile
.
Johnson embeds the Mozilla SpiderMonkey JavaScript runtime as a C extension.
group :development do
gem 'johnson'
end
If you're using JRuby, you can embed the Mozilla Rhino runtime by adding therubyrhino
to your Gemfile
:
group :development do
gem 'therubyrhino'
end
JavaScriptCore is Safari's Nitro JavaScript Engine and only usable on Mac OS X. You don't have to install anything, because JavaScriptCore is already packaged with Mac OS X.
Microsoft Windows Script Host is available on any Microsoft Windows operating systems.
You should place all your Haml Coffee templates in the app/assets/templates
directory and include all templates from
your app/assets/javascripts/application.js.coffee
:
#= require_tree ../templates
Now you can start to add your Haml Coffee templates to your template directory. Make sure all your templates have a
.hamlc
extension to be recognized by Haml Coffee Assets.
Note: Haml Coffee already generates a JavaScript Template, so there is not need to pass it to the JST
Sprocket
processor by using .jst.hamlc
as extension, and if you do, the Haml Coffee templates will not work.
By default all Haml Coffee templates are rendered to a HTML5 document. You can choose between the following output formats:
- html5
- html4
- xhtml
If you prefer another HTML format than HTML5, you can set it in your config/application.rb
:
config.hamlcoffee.format = 'xhtml'
By default all Haml Coffee templates are registered under the JST
namespace.
Example:
A template app/assets/templates/header.hamlc
with the given content:
%header
%h2= title
will be accessible in your browser as JST['header']
. You can now render the precompiled template and pass the data
to be rendered:
JST['header'].render({ title: 'Hello Haml Coffee' })
If you prefer another namespace, you can set it in your config/application.rb
:
config.hamlcoffee.namespace = 'window.HAML'
The name under which the template can be addressed in the namespace depends not only from the filename, but also on the directory name.
The following examples assumes a configured namespace window.JST
and the asset template directory
app/assets/templates
:
app/assets/templates/login.hamlc
will becomeJST['login']
app/assets/templates/users/new.hamlc
will becomeJST['users/new']
app/assets/templates/shared/form/address.hamlc
will becomeJST['shared/form/address']
All generated output by running CoffeeScript in your template is being escaped, but you can disable escaping of either the attributes or the generated Html.
You can toggle attribute escaping in your config/application.rb
:
config.hamlcoffee.escapeAttributes = false
You can toggle HTML escaping in your config/application.rb
:
config.hamlcoffee.escapeHtml = false
By default your code block in your Haml Coffee template will be escaped through the HAML.escape
function that is
provided in the hamlcoffee.js
script.
You can set another escaping function in your config/application.rb
:
config.hamlcoffee.customHtmlEscape = 'App.myEscape'
Your custom escape function must take the unescaped text as parameter and returns the escaped text.
The following default implementation comes with hamlcoffee.js
:
App.myEscape = (text) ->
('' + text)
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
Haml Coffee Assets allows you to configure a global context function that gets merged into the local template context for each template.
There is a example implementation provided in the hamlcoffee.js
that can use the extend
like functions
from the listed frameworks to merge the global and the local conext data:
- jQuery
- Underscore.js
- Prototype
- MooTools
- Zepto.js
If you use one of these, than you can simply override HAML.globals
and return the global context data:
HAML.globals = ->
{
isAuthenticated: App.isAuthenticated()
isAdmin: App.currentUser.hasRole('admin')
}
Now you can use the properties from the global context in every template:
.not-found-error
%h1= I18n.t('js.app.notfound.error', { route: @route })
- if @isAuthenticated
%p= I18n.t('js.app.notfound.homepage')
- else
%p= I18n.t('js.app.notfound.login')
If you like to use your own implementation, simply configure your context function in your config/application.rb
:
config.hamlcoffee.context = 'App.globalTemplateContext'
or disable the global context completely:
config.hamlcoffee.context = false
Your custom context function must take the local context as parameter and returns the merged context data.
The following example uses the _.underscore extend
function to merge the global context data with the
passed local context data:
App.globalTemplateContext = (locals) -> _.extend({}, {
authenticated: App.isAuthenticated()
}, locals)
- Jeremy Ashkenas for CoffeeScript, that little language that compiles into JavaScript.
- The people at 9elements who gave us haml-coffee, an elegant JavaScript template solution.
(The MIT License)
Copyright (c) 2011 Michael Kessler
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.