Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

refactor handlebars pre-compilation support #30

Merged
merged 7 commits into from

2 participants

@tchak
Collaborator
  • expose options for handlebars templates (template_root and template_path)
  • allow .hbs extension for templates
README.md
@@ -10,7 +10,7 @@ You can see an example of how to use the gem [here](https://github.com/keithpitt
Add the gem to your application Gemfile:
- gem "ember-rails"
+ gem "ember_rails"
@dgeb
dgeb added a note

@tchak - why the name change here?

@tchak Collaborator
tchak added a note

because "_" is ruby default. I aliased the name as "ember-rails" so if you like you can still require "ember-rails"
If this is something that shocks people I will revert :)

@dgeb
dgeb added a note

I agree in general about underscores, with the exception that dashes are typically used when gems are variants or extensions of one project. This is explained in this post and discussed here and is followed for gems such as coffee-rails, jquery-rails, rspec-rails, etc.

So, I wouldn't go so far as "shocking", just mildly surprising with no reason to change :)

@tchak Collaborator
tchak added a note

ok my bad, will revert it :)

@tchak Collaborator
tchak added a note

oh and to be clear, I was not trying to change gem name (this was badly reflected by erroneous change to README). I juste wanted to change the default require.

gem 'ember-rails'

require 'ember_rails'

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

Reverted some breaking changes. Now behavior of gem is iso with the old one

@tchak tchak merged commit 736a4d1 into emberjs:master
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Apr 9, 2012
  1. @tchak

    refactor handlebars pre-compilation support

    tchak authored
    * expose options for handlebars templates (template_root and template_path)
    * allow .hbs extension for templates
  2. @tchak

    move precompiller to lib

    tchak authored
  3. @tchak

    revert to ember-rails

    tchak authored
  4. @tchak
  5. @tchak

    remove comment

    tchak authored
  6. @tchak
  7. @tchak

    refactor engine and filters

    tchak authored
This page is out of date. Refresh to see the latest.
View
8 CHANGELOG.md
@@ -1,3 +1,11 @@
+## 0.3.0 (Avr 6, 2012)
+
+Improvements:
+
+ - Updated Ember.js to version 0.9.6
+ - Use precompilation only in production environment
+ - Expose some options related to templates paths
+
## 0.2.4 (Jan 27, 2012)
Improvements:
View
2  README.md
@@ -60,7 +60,7 @@ If you want to avoid `.gitkeep` files, use the `skip git` option like
this: `rails g ember_rails:bootstrap -g`.
Ask Rails to serve HandlebarsJS and pre-compile templates to Ember
-by putting each template in a dedicated ".js.hjs" or ".handlebars" file
+by putting each template in a dedicated ".js.hjs", ".hbs" or ".handlebars" file
(e.g. `app/assets/javascripts/templates/admin_panel.handlebars`)
and including the assets in your layout:
View
6 ember-rails.gemspec
@@ -1,12 +1,12 @@
# -*- encoding: utf-8 -*-
$:.push File.expand_path("../lib", __FILE__)
-require "ember-rails/version"
+require "ember/rails/version"
Gem::Specification.new do |s|
s.name = "ember-rails"
- s.version = EmberRails::VERSION
+ s.version = Ember::Rails::VERSION
s.platform = Gem::Platform::RUBY
- s.authors = ["Keith Pitt", "Rob Monie", "Joao Carlos"]
+ s.authors = ["Keith Pitt", "Rob Monie", "Joao Carlos", "Paul Chavard"]
s.email = ["me@keithpitt.com"]
s.homepage = "https://github.com/emberjs/ember-rails"
s.summary = "Ember for Rails 3.x"
View
18 lib/ember-rails.rb
@@ -1,17 +1 @@
-require 'sprockets'
-require 'sprockets/engines'
-require 'ember-rails/hjs_template'
-
-require "ember-rails/slim" if defined? Slim
-require "ember-rails/haml" if defined? Haml
-
-module EmberRails
- class Engine < Rails::Engine
- end
-
- # Registers the HandlebarsJS template engine so that
- # an asset file having the extension ".hjs" is processed
- # by the asset pipeline and converted to javascript code.
- Sprockets.register_engine '.hjs', HjsTemplate
- Sprockets.register_engine '.handlebars', HjsTemplate
-end
+require 'ember_rails'
View
48 lib/ember-rails/hjs_template.rb
@@ -1,48 +0,0 @@
-require 'tilt/template'
-require "execjs"
-
-module EmberRails
-
- # = Sprockets engine for HandlebarsJS templates
- class HjsTemplate < Tilt::Template
-
- def self.default_mime_type
- 'application/javascript'
- end
-
- def initialize_engine
- end
-
- def prepare
- end
-
- # Generates Javascript code from a HandlebarsJS template.
- # The Ember template name is derived from the lowercase logical asset path
- # by replacing non-alphanumeric characters by underscores.
- def evaluate(scope, locals, &block)
- t = data
- if scope.pathname.to_s =~ /\.mustache\.(handlebars|hjs)/
- t = t.gsub(/\{\{(\w[^\}\}]+)\}\}/){ |x| "{{unbound #{$1}}}" }
- end
- "Ember.TEMPLATES[\"#{scope.logical_path}\"] = Handlebars.template(#{precompile t});\n"
- end
-
- private
-
- def precompile(template)
- runtime.call("EmberRails.precompile", template)
- end
-
- def runtime
- Thread.current[:hjs_runtime] ||= ExecJS.compile(ember)
- end
-
- def ember
- [ "ember-precompiler.js", "ember.js" ].map do |name|
- File.read(File.expand_path(File.join(__FILE__, "..", "..", "..", "vendor/assets/javascripts/#{name}")))
- end.join("\n")
- end
-
- end
-
-end
View
4 lib/ember-rails/version.rb
@@ -1,4 +0,0 @@
-module EmberRails
- VERSION = "0.2.4"
- EMBER_VERSION = "0.9.6"
-end
View
0  lib/ember-rails/haml.rb → lib/ember/filters/haml.rb
File renamed without changes
View
0  lib/ember-rails/slim.rb → lib/ember/filters/slim.rb
File renamed without changes
View
0  vendor/assets/javascripts/ember-precompiler.js → lib/ember/handlebars/assets/ember-precompiler.js
File renamed without changes
View
49 lib/ember/handlebars/source.rb
@@ -0,0 +1,49 @@
+require "execjs"
+
+module Ember
+ module Handlebars
+ class Source
+ class << self
+ def precompiler_path
+ File.expand_path(File.join(__FILE__, "../assets/ember-precompiler.js"))
+ end
+
+ def bundled_path
+ File.expand_path(File.join(__FILE__, "../../../../vendor/assets/javascripts/ember.js"))
+ end
+
+ def path
+ @path ||= ENV["EMBER_SOURCE_PATH"] || bundled_path
+ end
+
+ def path=(path)
+ @contents = @version = @context = nil
+ @path = path
+ end
+
+ def contents
+ @contents ||= [File.read(precompiler_path), File.read(path)].join("\n")
+ end
+
+ def version
+ @version ||= contents[/^Handlebars.VERSION = "([^"]*)"/, 1]
+ end
+
+ def context
+ @context ||= ExecJS.compile(contents)
+ end
+ end
+ end
+
+ class << self
+ def version
+ Source.version
+ end
+
+ def compile(template)
+ template = template.read if template.respond_to?(:read)
+ Source.context.call("EmberRails.precompile", template)
+ end
+ end
+ end
+end
View
51 lib/ember/handlebars/template.rb
@@ -0,0 +1,51 @@
+require "ember/handlebars/source"
+
+module Ember
+ module Handlebars
+ class Template < Tilt::Template
+ def self.default_mime_type
+ 'application/javascript'
+ end
+
+ def prepare; end
+
+ def evaluate(scope, locals, &block)
+ template = mustache_to_handlebars(scope, data)
+
+ if configuration.precompile
+ func = Ember::Handlebars.compile(template)
+ "Ember.TEMPLATES[#{template_path(scope.logical_path).inspect}] = Ember.Handlebars.template(#{func});\n"
+ else
+ "Ember.TEMPLATES[#{template_path(scope.logical_path).inspect}] = Ember.Handlebars.compile(#{indent(template).inspect});\n"
+ end
+ end
+
+ private
+
+ def mustache_to_handlebars(scope, template)
+ if scope.pathname.to_s =~ /\.mustache\.(handlebars|hjs)/
+ template.gsub(/\{\{(\w[^\}\}]+)\}\}/){ |x| "{{unbound #{$1}}}" }
+ else
+ template
+ end
+ end
+
+ def template_path(path)
+ path = path.split('/')
+ root = configuration.template_root
+
+ path.delete(root) unless root.blank?
+
+ path.join(configuration.template_path_separator)
+ end
+
+ def configuration
+ ::Rails.configuration.handlebars
+ end
+
+ def indent(string)
+ string.gsub(/$(.)/m, "\\1 ").strip
+ end
+ end
+ end
+end
View
5 lib/ember/handlebars/version.rb
@@ -0,0 +1,5 @@
+module Ember
+ module Handlebars
+ VERSION = '1.0.beta.2'
+ end
+end
View
18 lib/ember/rails/engine.rb
@@ -0,0 +1,18 @@
+require "ember/handlebars/template"
+
+module Ember
+ module Rails
+ class Engine < ::Rails::Engine
+ config.handlebars = ActiveSupport::OrderedOptions.new
+ config.handlebars.precompile = ::Rails.env.production?
+ config.handlebars.template_root = nil
+ config.handlebars.template_path_separator = '/'
+
+ initializer :setup_ember_rails, :group => :all do |app|
+ app.assets.register_engine '.handlebars', Ember::Handlebars::Template
+ app.assets.register_engine '.hbs', Ember::Handlebars::Template
+ app.assets.register_engine '.hjs', Ember::Handlebars::Template
+ end
+ end
+ end
+end
View
5 lib/ember/rails/version.rb
@@ -0,0 +1,5 @@
+module Ember
+ module Rails
+ VERSION = "0.3.0"
+ end
+end
View
3  lib/ember/version.rb
@@ -0,0 +1,3 @@
+module Ember
+ VERSION = "0.9.6"
+end
View
7 lib/ember_rails.rb
@@ -0,0 +1,7 @@
+require 'sprockets'
+require 'sprockets/engines'
+
+require "ember/rails/engine"
+
+require "ember/filters/slim" if defined? Slim
+require "ember/filters/haml" if defined? Haml
View
12 ...tors/ember_rails/bootstrap/bootstrap_generator.rb → lib/generators/ember/bootstrap_generator.rb
@@ -1,11 +1,11 @@
-require 'generators/ember_rails/generator_helpers'
+require 'generators/ember/generator_helpers'
-module EmberRails
+module Ember
module Generators
- class BootstrapGenerator < Rails::Generators::Base
- include EmberRails::Generators::GeneratorHelpers
+ class BootstrapGenerator < ::Rails::Generators::Base
+ include Ember::Generators::GeneratorHelpers
- source_root File.expand_path("../templates", __FILE__)
+ source_root File.expand_path("../../templates", __FILE__)
desc "Creates a default Ember.js folder layout in app/assets/javascripts/ember"
@@ -34,8 +34,6 @@ def create_dir_layout
def create_app_file
template "app.coffee", "#{ember_path}/#{application_name.underscore}.js.coffee"
end
-
end
-
end
end
View
10 lib/generators/ember_rails/generator_helpers.rb → lib/generators/ember/generator_helpers.rb
@@ -1,14 +1,14 @@
-module EmberRails
+module Ember
module Generators
module GeneratorHelpers
-
+
def ember_path
"app/assets/javascripts/ember"
end
def application_name
- if defined?(Rails) && Rails.application
- Rails.application.class.name.split('::').first
+ if defined?(::Rails) && ::Rails.application
+ ::Rails.application.class.name.split('::').first
else
"app"
end
@@ -16,4 +16,4 @@ def application_name
end
end
-end
+end
View
27 ...nerators/ember_rails/install/install_generator.rb → lib/generators/ember/install_generator.rb
@@ -1,4 +1,4 @@
-module EmberRails
+module Ember
module Generators
class InstallGenerator < Rails::Generators::Base
@@ -50,9 +50,9 @@ def copy_ember
ember_files.each do |name|
source_file = if name.match /-dev/
- name.gsub /-dev/, ''
+ name.gsub /-dev/, '.debug'
else
- name.gsub /.js/, '.min.js'
+ name.gsub /.js/, '.prod.js'
end
copy_file source_file, "vendor/assets/javascripts/#{name}"
@@ -61,7 +61,7 @@ def copy_ember
else
self.class.source_root File.expand_path('../../../../../vendor/assets/javascripts', __FILE__)
- say_status("copying", "Ember.js (#{EmberRails::EMBER_VERSION})", :green)
+ say_status("copying", "Ember.js (#{Ember::VERSION})", :green)
ember_files.each do |name|
copy_file name, "vendor/assets/javascripts/#{name}"
@@ -72,20 +72,19 @@ def copy_ember
private
- def ember_files
- options.runtime? ? RUNTIME_FILES : EMBER_FILES
- end
+ def ember_files
+ options.runtime? ? RUNTIME_FILES : EMBER_FILES
+ end
- def cmd(command)
- out = `#{command}`
+ def cmd(command)
+ out = `#{command}`
- if $?.exitstatus != 0
- raise "Command error: command `#{command}` in directory #{Dir.pwd} has failed."
- end
- out
+ if $?.exitstatus != 0
+ raise "Command error: command `#{command}` in directory #{Dir.pwd} has failed."
end
+ out
+ end
end
-
end
end
View
0  ...rators/ember_rails/bootstrap/templates/app.coffee → lib/generators/templates/app.coffee
File renamed without changes
View
2  test/dummy/config/application.rb
@@ -39,6 +39,8 @@ class Application < Rails::Application
# Enable the asset pipeline
config.assets.enabled = true
+
+ config.handlebars.precompile = true
end
end
View
4 ...ember_rails/bootstrap/bootstrap_generator_test.rb → test/generators/bootstrap_generator_test.rb
@@ -1,8 +1,8 @@
require 'test_helper'
-require 'generators/ember_rails/bootstrap/bootstrap_generator'
+require 'generators/ember/bootstrap_generator'
class BootstrapGeneratorTest < Rails::Generators::TestCase
- tests EmberRails::Generators::BootstrapGenerator
+ tests Ember::Generators::BootstrapGenerator
destination File.join(Rails.root, "tmp")
setup :prepare_destination
View
4 test/hjstemplate_test.rb
@@ -15,13 +15,13 @@ class HjsTemplateTest < ActionController::IntegrationTest
test "asset pipeline should serve template" do
get "/assets/templates/test.js"
assert_response :success
- assert @response.body == "Ember.TEMPLATES[\"templates/test\"] = Handlebars.template(function anonymous(Handlebars,depth0,helpers,partials,data) {\nhelpers = helpers || Ember.Handlebars.helpers;\n var buffer = '', stack1, stack2, stack3, stack4, tmp1, self=this, functionType=\"function\", helperMissing=helpers.helperMissing, undef=void 0, escapeExpression=this.escapeExpression;\n\n\n stack1 = depth0;\n stack2 = \"test\";\n stack3 = {};\n stack4 = \"true\";\n stack3['escaped'] = stack4;\n stack4 = helpers._triageMustache || depth0._triageMustache;\n tmp1 = {};\n tmp1.hash = stack3;\n tmp1.contexts = [];\n tmp1.contexts.push(stack1);\n tmp1.data = data;\n if(typeof stack4 === functionType) { stack1 = stack4.call(depth0, stack2, tmp1); }\n else if(stack4=== undef) { stack1 = helperMissing.call(depth0, \"_triageMustache\", stack2, tmp1); }\n else { stack1 = stack4; }\n data.buffer.push(escapeExpression(stack1) + \"\\n\");\n return buffer;\n});\n", @response.body.inspect
+ assert @response.body == "Ember.TEMPLATES[\"templates/test\"] = Ember.Handlebars.template(function anonymous(Handlebars,depth0,helpers,partials,data) {\nhelpers = helpers || Ember.Handlebars.helpers;\n var buffer = '', stack1, stack2, stack3, stack4, tmp1, self=this, functionType=\"function\", helperMissing=helpers.helperMissing, undef=void 0, escapeExpression=this.escapeExpression;\n\n\n stack1 = depth0;\n stack2 = \"test\";\n stack3 = {};\n stack4 = \"true\";\n stack3['escaped'] = stack4;\n stack4 = helpers._triageMustache || depth0._triageMustache;\n tmp1 = {};\n tmp1.hash = stack3;\n tmp1.contexts = [];\n tmp1.contexts.push(stack1);\n tmp1.data = data;\n if(typeof stack4 === functionType) { stack1 = stack4.call(depth0, stack2, tmp1); }\n else if(stack4=== undef) { stack1 = helperMissing.call(depth0, \"_triageMustache\", stack2, tmp1); }\n else { stack1 = stack4; }\n data.buffer.push(escapeExpression(stack1) + \"\\n\");\n return buffer;\n});\n", @response.body.inspect
end
test "should unbind mustache templates" do
get "/assets/templates/hairy.mustache"
assert_response :success
- assert @response.body == "Ember.TEMPLATES[\"templates/hairy\"] = Handlebars.template(function anonymous(Handlebars,depth0,helpers,partials,data) {\nhelpers = helpers || Ember.Handlebars.helpers;\n var buffer = '', stack1, stack2, stack3, tmp1, self=this, functionType=\"function\", helperMissing=helpers.helperMissing, undef=void 0, escapeExpression=this.escapeExpression;\n\n\n data.buffer.push(\"This is a great <img src=\\\"\");\n stack1 = depth0;\n stack2 = \"image\";\n stack3 = helpers.unbound || depth0.unbound;\n tmp1 = {};\n tmp1.hash = {};\n tmp1.contexts = [];\n tmp1.contexts.push(stack1);\n tmp1.data = data;\n if(typeof stack3 === functionType) { stack1 = stack3.call(depth0, stack2, tmp1); }\n else if(stack3=== undef) { stack1 = helperMissing.call(depth0, \"unbound\", stack2, tmp1); }\n else { stack1 = stack3; }\n data.buffer.push(escapeExpression(stack1) + \"\\\" />\\n\");\n return buffer;\n});\n", @response.body.inspect
+ assert @response.body == "Ember.TEMPLATES[\"templates/hairy\"] = Ember.Handlebars.template(function anonymous(Handlebars,depth0,helpers,partials,data) {\nhelpers = helpers || Ember.Handlebars.helpers;\n var buffer = '', stack1, stack2, stack3, tmp1, self=this, functionType=\"function\", helperMissing=helpers.helperMissing, undef=void 0, escapeExpression=this.escapeExpression;\n\n\n data.buffer.push(\"This is a great <img src=\\\"\");\n stack1 = depth0;\n stack2 = \"image\";\n stack3 = helpers.unbound || depth0.unbound;\n tmp1 = {};\n tmp1.hash = {};\n tmp1.contexts = [];\n tmp1.contexts.push(stack1);\n tmp1.data = data;\n if(typeof stack3 === functionType) { stack1 = stack3.call(depth0, stack2, tmp1); }\n else if(stack3=== undef) { stack1 = helperMissing.call(depth0, \"unbound\", stack2, tmp1); }\n else { stack1 = stack3; }\n data.buffer.push(escapeExpression(stack1) + \"\\\" />\\n\");\n return buffer;\n});\n", @response.body.inspect
end
test "ensure new lines inside the anon function are persisted" do
Something went wrong with that request. Please try again.