Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge pull request #30 from tchak/handlebars

* refactor handlebars pre-compilation support
* move to Ember namespace
  • Loading branch information...
commit 736a4d1c67b4b6516bc9fc00a2868be4e936d993 2 parents 5a4f488 + 4e82f5e
@tchak tchak authored
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  ...r/assets/javascripts/ember-precompiler.js → ...er/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 ...er_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 ...nerators/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 .../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  ...mber_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 ...ils/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
Please sign in to comment.
Something went wrong with that request. Please try again.