diff --git a/.gitignore b/.gitignore index 76e1c9c..204abb0 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,5 @@ test/tmp test/version_tmp tmp rerun.txt +.tmp/ +template.erb diff --git a/features/process_with_sprockets.feature b/features/process_with_sprockets.feature index 6173abd..d770abb 100644 --- a/features/process_with_sprockets.feature +++ b/features/process_with_sprockets.feature @@ -10,6 +10,7 @@ Feature: Process files with Sprockets another file """ + @fakefs Scenario: Simple Sprockets work When I instantiate a Sprockets handler with the following asset directories: | dir | @@ -18,6 +19,7 @@ Feature: Process files with Sprockets | dir/other.js | | dir/file.js | + @fakefs Scenario: Require the file twice Given I have the file "dir/third.js" with the content: """ @@ -33,3 +35,18 @@ Feature: Process files with Sprockets | dir/file.js | | dir/third.js | + @realfs + Scenario: A CoffeeScript file + Given I have the file "dir/third.js.coffee" with the content: + """ + #= require other + for file in [ 'files' ] + alert(file) + """ + When I instantiate a Sprockets handler with the following asset directories: + | dir | + And I work with the Sprockets asset "third" + Then the handler should have the following files in order: + | dir/other.js | + | <%= temp_path_for("dir/third.js.coffee") %> | + And there should be a temp file for the local path "dir/third.js.coffee" diff --git a/features/step_definitions/given/coffeescript/i_have_coffeescript_template_processor.rb b/features/step_definitions/given/coffeescript/i_have_coffeescript_template_processor.rb new file mode 100644 index 0000000..c912a3d --- /dev/null +++ b/features/step_definitions/given/coffeescript/i_have_coffeescript_template_processor.rb @@ -0,0 +1,3 @@ +Given /^I have a CoffeeScript template processor for the file "([^"]*)"$/ do |file| + @template_processor = Flowerbox::Delivery::Tilt::CoffeeTemplate.new(file) +end diff --git a/features/step_definitions/given/i_have_file.rb b/features/step_definitions/given/i_have_file.rb index 9748479..021ebe3 100644 --- a/features/step_definitions/given/i_have_file.rb +++ b/features/step_definitions/given/i_have_file.rb @@ -3,3 +3,4 @@ Given /^I have the file "([^"]*)" with the content:$/ do |filename, string| File.open(filename, 'wb') { |fh| fh.print(string) } end + diff --git a/features/step_definitions/then/handler_should_have_files_in_order.rb b/features/step_definitions/then/handler_should_have_files_in_order.rb index ec5daf6..1583513 100644 --- a/features/step_definitions/then/handler_should_have_files_in_order.rb +++ b/features/step_definitions/then/handler_should_have_files_in_order.rb @@ -1,5 +1,9 @@ +require 'erb' + Then /^the handler should have the following files in order:$/ do |table| - table.raw.collect(&:first).each_with_index do |path, index| + table.raw.flatten.each_with_index do |path, index| + path = ERB.new(path).result(binding) + @sprockets.files[index].should == Pathname(File.expand_path(path)) end end diff --git a/features/step_definitions/then/temp_file/should_be_temp_file_for_local_path.rb b/features/step_definitions/then/temp_file/should_be_temp_file_for_local_path.rb new file mode 100644 index 0000000..cd6d6fa --- /dev/null +++ b/features/step_definitions/then/temp_file/should_be_temp_file_for_local_path.rb @@ -0,0 +1,7 @@ +Then /^there should be a temp file for the local path "([^"]*)"$/ do |path| + path.gsub!(%r{\.js.*$}, '.js') + + @temp_file_path = Dir[".tmp/**/#{path}"].first + + @temp_file_path.should_not be_nil +end diff --git a/features/step_definitions/then/temp_file/should_contain.rb b/features/step_definitions/then/temp_file/should_contain.rb new file mode 100644 index 0000000..4ab1bf1 --- /dev/null +++ b/features/step_definitions/then/temp_file/should_contain.rb @@ -0,0 +1,7 @@ +Then /^the temp file should contain:$/ do |string| + file_lines = File.read(@temp_file_path).lines.collect(&:strip) + + string.lines.each do |line| + file_lines.should include(line.strip) + end +end diff --git a/features/step_definitions/then/temp_file/should_have_temp_file.rb b/features/step_definitions/then/temp_file/should_have_temp_file.rb new file mode 100644 index 0000000..e69de29 diff --git a/features/step_definitions/then/tilt/result_should_be_path_to_file.rb b/features/step_definitions/then/tilt/result_should_be_path_to_file.rb new file mode 100644 index 0000000..f6512a5 --- /dev/null +++ b/features/step_definitions/then/tilt/result_should_be_path_to_file.rb @@ -0,0 +1,3 @@ +Then /^the evaluated template should be the path to the temp file for "([^"]*)"$/ do |file| + @temp_file_path.should == @result +end diff --git a/features/step_definitions/when/tilt/i_evaluate_template.rb b/features/step_definitions/when/tilt/i_evaluate_template.rb new file mode 100644 index 0000000..5d121e1 --- /dev/null +++ b/features/step_definitions/when/tilt/i_evaluate_template.rb @@ -0,0 +1,3 @@ +When /^I evaluate the template$/ do + @result = @template_processor.render +end diff --git a/features/support/env.rb b/features/support/env.rb index f580d64..4c3258b 100644 --- a/features/support/env.rb +++ b/features/support/env.rb @@ -11,10 +11,14 @@ class FakeFS::File::Stat end end +class FakeFS::File + def self.executable?(file) + false + end +end + Before do mocha_setup - - FakeFS.activate! end After do @@ -24,8 +28,6 @@ After do mocha_teardown end - FakeFS.deactivate! - if @running_server @running_server[:server].shutdown @running_server = nil @@ -35,3 +37,24 @@ After do @server.stop if @server end + +def temp_path_for(file) + File.join('.tmp/sprockets', File.expand_path(file.gsub(%r{\.js.*$}, '.js'))) +end + +Before('@fakefs') do + FakeFS.activate! +end + +After('@fakefs') do + FakeFS::FileSystem.clear + FakeFS.deactivate! +end + +Before('@realfs') do + FileUtils.rm_rf 'dir' +end + +After('@realfs') do + FileUtils.rm_rf 'dir' +end diff --git a/flowerbox-delivery.gemspec b/flowerbox-delivery.gemspec index d895de7..ab2c832 100644 --- a/flowerbox-delivery.gemspec +++ b/flowerbox-delivery.gemspec @@ -21,6 +21,7 @@ Gem::Specification.new do |gem| gem.add_development_dependency 'mocha' gem.add_development_dependency 'fakefs' gem.add_development_dependency 'nokogiri' + gem.add_development_dependency 'therubyracer' gem.add_runtime_dependency 'rack' gem.add_runtime_dependency 'sprockets' diff --git a/lib/flowerbox/delivery.rb b/lib/flowerbox/delivery.rb index 4ece455..2e5076f 100644 --- a/lib/flowerbox/delivery.rb +++ b/lib/flowerbox/delivery.rb @@ -4,6 +4,8 @@ module Flowerbox autoload :TemplateRenderer, 'flowerbox/delivery/template_renderer' autoload :SprocketsHandler, 'flowerbox/delivery/sprockets_handler' autoload :UniqueAssetList, 'flowerbox/delivery/unique_asset_list' + + autoload :Tilt, 'flowerbox/delivery/tilt' end end diff --git a/lib/flowerbox/delivery/sprockets_handler.rb b/lib/flowerbox/delivery/sprockets_handler.rb index d6386a5..3c76634 100644 --- a/lib/flowerbox/delivery/sprockets_handler.rb +++ b/lib/flowerbox/delivery/sprockets_handler.rb @@ -11,7 +11,7 @@ module Flowerbox::Delivery end def add(asset) - @files.add(paths_for(asset)) + paths_for(asset).each { |path| @files.add(path_for_compiled_asset(path)) } end def paths_for(asset) @@ -22,8 +22,19 @@ module Flowerbox::Delivery return @environment if @environment @environment = Sprockets::Environment.new + @environment.unregister_postprocessor('application/javascript', Sprockets::SafetyColons) + @environment.register_engine('.js', Flowerbox::Delivery::Tilt::JSTemplate) + options[:asset_paths].each { |path| @environment.append_path(path) } @environment end + + def asset_for(*args) + environment.find_asset(*args) + end + + def path_for_compiled_asset(path) + Pathname(asset_for(path, :bundle => false).to_s) + end end end diff --git a/lib/flowerbox/delivery/tilt.rb b/lib/flowerbox/delivery/tilt.rb new file mode 100644 index 0000000..71a7d05 --- /dev/null +++ b/lib/flowerbox/delivery/tilt.rb @@ -0,0 +1,6 @@ +require 'sprockets' + +module Flowerbox::Delivery::Tilt + autoload :JSTemplate, 'flowerbox/delivery/tilt/js_template' +end + diff --git a/lib/flowerbox/delivery/tilt/js_template.rb b/lib/flowerbox/delivery/tilt/js_template.rb new file mode 100644 index 0000000..31f6c75 --- /dev/null +++ b/lib/flowerbox/delivery/tilt/js_template.rb @@ -0,0 +1,28 @@ +require 'tilt' + +class Flowerbox::Delivery::Tilt::JSTemplate < Tilt::Template + self.default_mime_type = "application/javascript" + + def prepare ; end + + def evaluate(scope, locals, &block) + case File.extname(file) + when '.js' + file + else + save + end + end + + def save + FileUtils.mkdir_p File.dirname(temp_file) + File.open(temp_file, 'wb') { |fh| fh.print data } + + temp_file + end + + def temp_file + File.join(Dir.pwd, ".tmp/sprockets", file.gsub(%r{(\.js)(.*)$}, '\1')) + end +end + diff --git a/lib/flowerbox/delivery/unique_asset_list.rb b/lib/flowerbox/delivery/unique_asset_list.rb index cfb58e3..c22f1b4 100644 --- a/lib/flowerbox/delivery/unique_asset_list.rb +++ b/lib/flowerbox/delivery/unique_asset_list.rb @@ -1,7 +1,7 @@ module Flowerbox::Delivery class UniqueAssetList < ::Array def add(files) - files.each { |file| self << file if !include?(file) } + [ files ].flatten.each { |file| self << file if !include?(file) } end private diff --git a/spec/flowerbox/delivery/sprockets_handler_spec.rb b/spec/flowerbox/delivery/sprockets_handler_spec.rb index 160ca11..2635a7a 100644 --- a/spec/flowerbox/delivery/sprockets_handler_spec.rb +++ b/spec/flowerbox/delivery/sprockets_handler_spec.rb @@ -7,16 +7,20 @@ describe Flowerbox::Delivery::SprocketsHandler do describe '#add' do let(:asset) { 'asset' } - let(:paths) { [ 'paths' ] } + let(:path) { 'path' } + let(:paths) { [ path ] } + + let(:pathname_path) { 'pathname path' } before do sprockets_handler.expects(:paths_for).with(asset).returns(paths) + sprockets_handler.expects(:path_for_compiled_asset).with(path).returns(pathname_path) end it 'should add the asset to the list of ones to work with' do sprockets_handler.add(asset) - sprockets_handler.files.should == paths + sprockets_handler.files.should == [ pathname_path ] end end diff --git a/spec/flowerbox/delivery/tilt/js_template_spec.rb b/spec/flowerbox/delivery/tilt/js_template_spec.rb new file mode 100644 index 0000000..41a680b --- /dev/null +++ b/spec/flowerbox/delivery/tilt/js_template_spec.rb @@ -0,0 +1,62 @@ +require 'spec_helper' + +describe Flowerbox::Delivery::Tilt::JSTemplate do + let(:js_template) { described_class.new { '' } } + + describe '#evaluate' do + subject { js_template.evaluate(Object.new, {}) } + + before do + js_template.stubs(:file).returns(file) + end + + context '.js' do + let(:file) { 'file.js' } + + it { should == file } + end + + context 'other extension' do + let(:file) { 'file.coffee' } + let(:temp_file) { 'temp file' } + + before do + js_template.expects(:save).returns(temp_file) + end + + it { should == temp_file } + end + end + + describe '#save' do + include FakeFS::SpecHelpers + + let(:temp_file) { 'dir/temp file' } + let(:data) { 'data' } + + before do + js_template.stubs(:temp_file).returns(temp_file) + js_template.stubs(:data).returns(data) + end + + it 'should save the file to disk and return the temp path' do + js_template.save.should == temp_file + + File.read(temp_file).should == data + end + end + + describe '#temp_file' do + subject { js_template.temp_file } + + let(:filename) { "#{root_filename}.ext" } + let(:root_filename) { "dir/file.js" } + + before do + js_template.stubs(:file).returns(filename) + end + + it { should == File.join(Dir.pwd, '.tmp/sprockets', root_filename) } + end +end + diff --git a/spec/flowerbox/delivery/unique_asset_list_spec.rb b/spec/flowerbox/delivery/unique_asset_list_spec.rb index 33fbae5..1def2c1 100644 --- a/spec/flowerbox/delivery/unique_asset_list_spec.rb +++ b/spec/flowerbox/delivery/unique_asset_list_spec.rb @@ -9,7 +9,8 @@ describe Flowerbox::Delivery::UniqueAssetList do let(:third) { Pathname.new('two') } it 'should not add assets already added' do - unique_asset_list.add([ first, second, third ]) + unique_asset_list.add(first) + unique_asset_list.add([ second, third ]) unique_asset_list.should == [ first, third ] end