Skip to content

Instantly share code, notes, and snippets.

@aiwilliams
Created May 2, 2011 21:31
Show Gist options
  • Save aiwilliams/952416 to your computer and use it in GitHub Desktop.
Save aiwilliams/952416 to your computer and use it in GitHub Desktop.
Sprockets producing Handlebars templates from Haml
http_path = "/"
css_dir = "public/stylesheets"
sass_dir = "sass"
images_dir = "public/images"
http_images_dir = "images"
javascripts_dir = "public/javascripts"
fonts_dir = "public/fonts"
http_fonts_dir = "fonts"
line_comments = false
$LOAD_PATH << File.expand_path('.')
require 'rubygems'
require 'bundler/setup'
require 'haml'
require 'sass'
require 'sass/plugin/rack'
require 'compass'
require 'tilt'
require 'sprockets'
require 'hamlbars'
Compass.add_configuration(File.expand_path('config.rb'))
Compass.configure_sass_plugin!
use Sass::Plugin::Rack
map '/javascripts' do
sprockets = Sprockets::Environment.new
sprockets.engines.register 'hamlbars', Tilt::HamlbarsTemplate
sprockets.paths << 'apps'
sprockets.paths << 'vendor/javascripts'
sprockets.static_root = 'public/javascripts'
run sprockets
end
map '/' do
run Rack::Directory.new('public')
end
require 'tilt/template'
module Tilt
class HamlbarsTemplate < Template
JS_ESCAPE_MAP = {
"\r\n" => '\n',
"\n" => '\n',
"\r" => '\n',
'"' => '\\"',
"'" => "\\'" }
self.default_mime_type = 'application/javascript'
def self.engine_initialized?
defined? ::Haml::Engine
end
def initialize_engine
require_template_library 'haml'
end
def prepare
options = @options.merge(:filename => eval_file, :line => line)
@engine = ::Haml::Engine.new(data, options)
end
def evaluate(scope, locals, &block)
template = if @engine.respond_to?(:precompiled_method_return_value, true)
super
else
@engine.render(scope, locals, &block)
end
if basename =~ /^_/
"Handlebars.registerPartial('#{name}', '#{template.strip.gsub(/(\r\n|[\n\r"'])/) { JS_ESCAPE_MAP[$1] }}');\n"
else
"App.registerTemplate('#{name}', '#{template.strip.gsub(/(\r\n|[\n\r"'])/) { JS_ESCAPE_MAP[$1] }}');\n"
end
end
# Precompiled Haml source. Taken from the precompiled_with_ambles
# method in Haml::Precompiler:
# http://github.com/nex3/haml/blob/master/lib/haml/precompiler.rb#L111-126
def precompiled_template(locals)
@engine.precompiled
end
def precompiled_preamble(locals)
local_assigns = super
@engine.instance_eval do
<<-RUBY
begin
extend Haml::Helpers
_hamlout = @haml_buffer = Haml::Buffer.new(@haml_buffer, #{options_for_buffer.inspect})
_erbout = _hamlout.buffer
__in_erb_template = true
_haml_locals = locals
#{local_assigns}
RUBY
end
end
def precompiled_postamble(locals)
@engine.instance_eval do
<<-RUBY
#{precompiled_method_return_value}
ensure
@haml_buffer = @haml_buffer.upper
end
RUBY
end
end
end
end
module Haml
module Helpers
module HamlbarsExtensions
def iterate(name, &block)
content = capture_haml(&block)
"{{##{name}}}#{content.strip}{{/#{name}}}"
end
end
include HamlbarsExtensions
end
end
@aiwilliams
Copy link
Author

We are using backbone.js and wanted to have handlebars.js as our client-side template language. This means that you must compile the templates and register the partials with Handlebars so that they can be rendered from backbone view instances, but we never want to write that registration code. We have index.js.hamlbars files written in Haml, and concatenated by Sprockets as "Handlebars.compile('<p>haml to html</p>')" and "Handlebars.registerPartial" if the filename starts with an underscore. There are helpers for the Haml that allow us to use Haml within Handlebars lists.

The reason we load config.rb is that @imathis uses Guard and LiveReload to continuously compile his scss, so Sprockets isn't the only thing that cares about how Sass is configured. We plan to precompile all our assets for a non-Ruby server environment.

@chriseppstein
Copy link

I just started working on making sprockets support sass better. It should land in the next few days: sstephenson/sprockets#23

@aiwilliams
Copy link
Author

That's great news. Thanks for the heads up and all your excellent work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment