Some important text. It might have a link: http://foo.com/
20 | 21 |Some code
22 |
23 |
24 | That's all.
25 | HTML 26 | 27 | def input_file(name, content) 28 | MemoryFileWrapper.new("/path/to/input", name, "UTF-8", content) 29 | end 30 | 31 | def output_file(name) 32 | MemoryFileWrapper.new("/path/to/output", name, "UTF-8") 33 | end 34 | 35 | def setup_filter(filter) 36 | filter.file_wrapper_class = MemoryFileWrapper 37 | filter.manifest = MemoryManifest.new 38 | filter.last_manifest = MemoryManifest.new 39 | filter.input_files = [input_file("page.md", markdown_input)] 40 | filter.output_root = "/path/to/output" 41 | filter.rake_application = Rake::Application.new 42 | filter 43 | end 44 | 45 | it "generates output" do 46 | filter = setup_filter MarkdownFilter.new 47 | 48 | filter.output_files.should == [output_file("page.html")] 49 | 50 | tasks = filter.generate_rake_tasks 51 | tasks.each(&:invoke) 52 | 53 | file = MemoryFileWrapper.files["/path/to/output/page.html"] 54 | file.body.should == expected_html_output 55 | file.encoding.should == "UTF-8" 56 | end 57 | 58 | describe "naming output files" do 59 | it "translates .md extensions to .html by default" do 60 | filter = setup_filter MarkdownFilter.new 61 | filter.output_files.first.path.should == "page.html" 62 | end 63 | 64 | it "accepts a block to customize output file names" do 65 | filter = setup_filter(MarkdownFilter.new { |input| "octopus" }) 66 | filter.output_files.first.path.should == "octopus" 67 | end 68 | end 69 | 70 | it "passes options to the Markdown compiler" do 71 | filter = setup_filter(MarkdownFilter.new(:autolink => true)) 72 | filter.input_files = [input_file("page.md", markdown_input)] 73 | tasks = filter.generate_rake_tasks 74 | tasks.each(&:invoke) 75 | file = MemoryFileWrapper.files["/path/to/output/page.html"] 76 | file.body.should =~ %r{} 77 | end 78 | 79 | it "accepts a :compiler option" do 80 | filter = setup_filter(MarkdownFilter.new(:compiler => proc { |text, options| text })) 81 | filter.input_files = [input_file("page.md", markdown_input)] 82 | tasks = filter.generate_rake_tasks 83 | tasks.each(&:invoke) 84 | file = MemoryFileWrapper.files["/path/to/output/page.html"] 85 | file.body.should == markdown_input 86 | end 87 | 88 | end 89 | 90 | -------------------------------------------------------------------------------- /spec/minispade_filter_spec.rb: -------------------------------------------------------------------------------- 1 | require "json" 2 | 3 | describe "MinispadeFilter" do 4 | MemoryFileWrapper ||= Rake::Pipeline::SpecHelpers::MemoryFileWrapper 5 | MemoryManifest ||= Rake::Pipeline::SpecHelpers::MemoryManifest 6 | 7 | def input_file(contents="var foo = 'bar'; // last-line comment", path="/path/to/input", name="foo.js") 8 | MemoryFileWrapper.new(path, name, "UTF-8", contents) 9 | end 10 | 11 | let(:output_files) { 12 | [ 13 | MemoryFileWrapper.new("/path/to/output", "foo.js", "UTF-8") 14 | ] 15 | } 16 | 17 | let(:output_file) { 18 | MemoryFileWrapper.files["/path/to/output/foo.js"] 19 | } 20 | 21 | def make_filter(input_file, *args) 22 | filter = Rake::Pipeline::Web::Filters::MinispadeFilter.new(*args) 23 | filter.file_wrapper_class = MemoryFileWrapper 24 | filter.manifest = MemoryManifest.new 25 | filter.last_manifest = MemoryManifest.new 26 | filter.input_files = [input_file] 27 | filter.output_root = "/path/to/output" 28 | filter.rake_application = Rake::Application.new 29 | filter.generate_rake_tasks.each(&:invoke) 30 | filter 31 | end 32 | 33 | it "generates output" do 34 | filter = make_filter(input_file) 35 | filter.output_files.should == output_files 36 | output_file.encoding.should == "UTF-8" 37 | output_file.body.should == 38 | "minispade.register('/path/to/input/foo.js', function() {var foo = 'bar'; // last-line comment\n});" 39 | end 40 | 41 | it "uses strict if asked" do 42 | filter = make_filter(input_file, :use_strict => true) 43 | output_file.body.should == 44 | "minispade.register('/path/to/input/foo.js', function() {\"use strict\";\nvar foo = 'bar'; // last-line comment\n});" 45 | end 46 | 47 | it "compiles a string if asked" do 48 | filter = make_filter(input_file, :string => true) 49 | output_file.body.should == 50 | %{minispade.register('/path/to/input/foo.js', "(function() {var foo = 'bar'; // last-line comment\\n})();\\n//# sourceURL=/path/to/input/foo.js");} 51 | end 52 | 53 | it "takes a proc to name the module" do 54 | filter = make_filter(input_file, :module_id_generator => proc { |input| "octopus" }) 55 | output_file.body.should == 56 | "minispade.register('octopus', function() {var foo = 'bar'; // last-line comment\n});" 57 | end 58 | 59 | it "rewrites requires if asked" do 60 | filter = make_filter(input_file("require('octopus');"), :rewrite_requires => true) 61 | output_file.body.should == 62 | "minispade.register('/path/to/input/foo.js', function() {minispade.require('octopus');\n});" 63 | end 64 | 65 | it "rewrites requires if asked even spaces wrap tokens in the require statement" do 66 | filter = make_filter(input_file("require ( 'octopus');"), :rewrite_requires => true) 67 | output_file.body.should == 68 | "minispade.register('/path/to/input/foo.js', function() {minispade.require('octopus');\n});" 69 | end 70 | 71 | it "rewrites requireAll if asked" do 72 | filter = make_filter(input_file("requireAll('octopus');"), :rewrite_requires => true) 73 | output_file.body.should == 74 | "minispade.register('/path/to/input/foo.js', function() {minispade.requireAll('octopus');\n});" 75 | end 76 | 77 | it "rewrites requireAll if asked even spaces wrap tokens in the require statement" do 78 | filter = make_filter(input_file("requireAll ( 'octopus');"), :rewrite_requires => true) 79 | output_file.body.should == 80 | "minispade.register('/path/to/input/foo.js', function() {minispade.requireAll('octopus');\n});" 81 | end 82 | end 83 | -------------------------------------------------------------------------------- /spec/neuter_filter_spec.rb: -------------------------------------------------------------------------------- 1 | require 'stringio' 2 | 3 | describe "NeuterFilter" do 4 | MemoryFileWrapper ||= Rake::Pipeline::SpecHelpers::MemoryFileWrapper 5 | MemoryManifest ||= Rake::Pipeline::SpecHelpers::MemoryManifest 6 | 7 | def make_input(name, data) 8 | make_data(name, data) 9 | MemoryFileWrapper.new("/path/to/input", name, "UTF-8") 10 | end 11 | 12 | def make_data(name, data) 13 | MemoryFileWrapper.data["/path/to/input/#{name}"] = data 14 | end 15 | 16 | def make_filter(input_files, *args) 17 | opts = args.last.is_a?(Hash) ? args.pop : {} 18 | opts[:additional_dependencies] ||= proc{|input| %w(b c) } 19 | args.push(opts) 20 | 21 | filter = Rake::Pipeline::Web::Filters::NeuterFilter.new(*args) 22 | filter.file_wrapper_class = MemoryFileWrapper 23 | filter.manifest = MemoryManifest.new 24 | filter.last_manifest = MemoryManifest.new 25 | filter.input_files = input_files 26 | filter.output_root = "/path/to/output" 27 | filter.rake_application = Rake::Application.new 28 | 29 | tasks = filter.generate_rake_tasks 30 | 31 | # TODO work around a bug in rakep THIS IS TEMPORARY 32 | filter.rake_application.tasks.each do |task| 33 | task.dynamic_prerequisites.each do |prereq| 34 | filter.send :create_file_task, prereq 35 | end 36 | end 37 | tasks.each(&:invoke) 38 | filter 39 | end 40 | 41 | def make_filter_with_inputs(inputs, options={}) 42 | input_file = make_input(inputs[0][0], inputs[0][1]) 43 | inputs[1..-1].each{|input| make_data(input[0], input[1]) } 44 | make_filter([input_file], "processed", options) 45 | end 46 | 47 | def capture(*streams) 48 | streams.map! { |stream| stream.to_s } 49 | begin 50 | result = StringIO.new 51 | streams.each { |stream| eval "$#{stream} = result" } 52 | yield 53 | ensure 54 | streams.each { |stream| eval("$#{stream} = #{stream.upcase}") } 55 | end 56 | result.string 57 | end 58 | 59 | after(:each) do 60 | MemoryFileWrapper.data.clear 61 | end 62 | 63 | let(:output_files) { 64 | [ 65 | MemoryFileWrapper.new("/path/to/output", "processed", "BINARY") 66 | ] 67 | } 68 | 69 | let(:output_file) { 70 | MemoryFileWrapper.files["/path/to/output/processed"] 71 | } 72 | 73 | it "generates basic output" do 74 | input_file = make_input("contents", "data") 75 | filter = make_filter([input_file], "processed") 76 | 77 | filter.output_files.should == output_files 78 | # ConcatFilter forces Binary, not sure if this is right in this case 79 | output_file.encoding.should == "BINARY" 80 | output_file.body.should == "data" 81 | end 82 | 83 | it "orders required files" do 84 | make_filter_with_inputs([ 85 | ["a", "require('b');\nA"], 86 | ["b", "require('c');\nB"], 87 | ["c", "C"] 88 | ]) 89 | 90 | output_file.body.should == "C\n\nB\n\nA" 91 | end 92 | 93 | it "works with paths" do 94 | make_filter_with_inputs([ 95 | ["lib/a", "require('lib/b');\nA"], 96 | ["lib/b", "require('lib/c');\nB"], 97 | ["lib/c", "C"] 98 | ], :additional_dependencies => proc{ %w(lib/b lib/c) }) 99 | 100 | output_file.body.should == "C\n\nB\n\nA" 101 | end 102 | 103 | it "should handle circular requires" do 104 | make_filter_with_inputs([ 105 | ["a", "require('b');\nA"], 106 | ["b", "require('c');\nB"], 107 | ["c", "require('a');\nC"] 108 | ]) 109 | 110 | output_file.body.should == "C\n\nB\n\nA" 111 | end 112 | 113 | it "should not require the same file twice" do 114 | make_filter_with_inputs([ 115 | ["a", "require('b');\nrequire('c');\nA"], 116 | ["b", "require('c');\nB"], 117 | ["c", "require('a');\nC"] 118 | ]) 119 | 120 | output_file.body.should == "C\n\nB\n\nA" 121 | end 122 | 123 | # Feature not yet supported 124 | it "does not duplicate files both matched and required" 125 | 126 | describe "config" do 127 | describe "require_regexp" do 128 | it "works with minispade format" do 129 | make_filter_with_inputs([ 130 | ["a", "minispade.require('b');\nA"], 131 | ["b", "minispade.require('c');\nB"], 132 | ["c", "C"] 133 | ], :require_regexp => %r{^\s*minispade\.require\(['"]([^'"]*)['"]\);?\s*}) 134 | 135 | output_file.body.should == "C\n\nB\n\nA" 136 | end 137 | 138 | it "works with sprockets format" do 139 | make_filter_with_inputs([ 140 | ["a", "//= require b\nA"], 141 | ["b", "//= require c\nB"], 142 | ["c", "C"] 143 | ], :require_regexp => %r{^//= require (\S+)\s*}) 144 | 145 | output_file.body.should == "C\n\nB\n\nA" 146 | end 147 | end 148 | 149 | describe "path_transform" do 150 | it "converts paths" do 151 | make_filter_with_inputs([ 152 | ["lib/a.js", "require('b');\nA"], 153 | ["lib/b.js", "require('c');\nB"], 154 | ["lib/c.js", "C"] 155 | ], :path_transform => proc{|path| "lib/#{path}.js" }, 156 | :additional_dependencies => proc{ %w(lib/b.js lib/c.js) }) 157 | 158 | output_file.body.should == "C\n\nB\n\nA" 159 | end 160 | end 161 | 162 | describe "closure_wrap" do 163 | it "wraps in a javascript closure" do 164 | make_filter_with_inputs([ 165 | ["a", "require('b');\nA"], 166 | ["b", "require('c');\nB"], 167 | ["c", "C"] 168 | ], :closure_wrap => true) 169 | 170 | output_file.body.should == "(function() {\nC\n})();\n\n\n\n(function() {\nB\n})();\n\n\n\n(function() {\nA\n})();\n\n" 171 | end 172 | 173 | # Not yet supported 174 | it "allows other wrapper types" 175 | end 176 | 177 | describe "filename_comment" do 178 | it "shows a comment with the filename" do 179 | make_filter_with_inputs([ 180 | ["a", "require('b');\nA"], 181 | ["b", "require('c');\nB"], 182 | ["c", "C"], 183 | ], :filename_comment => proc{|input| "/* #{input.fullpath} */" }) 184 | 185 | output_file.body.should == "/* /path/to/input/c */\nC\n\n/* /path/to/input/b */\nB\n\n/* /path/to/input/a */\nA" 186 | end 187 | end 188 | 189 | describe "additional_dependencies" do 190 | it "warns if required file is not contained" do 191 | output = capture(:stderr) do 192 | make_filter_with_inputs([ 193 | ["d", "require('e');\nD"], 194 | ["e", "require('f');\nE"], 195 | ["f", "F"] 196 | ]) 197 | end 198 | 199 | output.should include("Included '/path/to/input/e', which is not listed in :additional_dependencies. The pipeline may not invalidate properly.") 200 | output.should include("Included '/path/to/input/f', which is not listed in :additional_dependencies. The pipeline may not invalidate properly.") 201 | end 202 | 203 | it "does not warn if full paths are provided" do 204 | output = capture(:stderr) do 205 | make_filter_with_inputs([ 206 | ["d", "require('e');\nD"], 207 | ["e", "require('f');\nE"], 208 | ["f", "F"] 209 | ], :additional_dependencies => proc{ %w(/path/to/input/e /path/to/input/f) }) 210 | end 211 | 212 | output.should == "" 213 | end 214 | end 215 | end 216 | end 217 | -------------------------------------------------------------------------------- /spec/sass_filter_spec.rb: -------------------------------------------------------------------------------- 1 | describe "SassFilter" do 2 | SassFilter ||= Rake::Pipeline::Web::Filters::SassFilter 3 | MemoryFileWrapper ||= Rake::Pipeline::SpecHelpers::MemoryFileWrapper 4 | MemoryManifest ||= Rake::Pipeline::SpecHelpers::MemoryManifest 5 | 6 | let(:scss_input) { <<-SCSS } 7 | $blue: #3bbfce; 8 | 9 | .border { 10 | border-color: $blue; 11 | } 12 | SCSS 13 | 14 | let(:sass_input) { <<-SASS } 15 | $blue: #3bbfce 16 | 17 | .border 18 | border-color: $blue 19 | SASS 20 | 21 | def expected_css_output(filename) 22 | <<-CSS 23 | /* line 3, /path/to/input/#{filename} */ 24 | .border { 25 | border-color: #3bbfce; 26 | } 27 | CSS 28 | end 29 | 30 | def input_file(name, content) 31 | MemoryFileWrapper.new("/path/to/input", name, "UTF-8", content) 32 | end 33 | 34 | def output_file(name) 35 | MemoryFileWrapper.new("/path/to/output", name, "UTF-8") 36 | end 37 | 38 | def setup_filter(filter, input_files=nil) 39 | filter.file_wrapper_class = MemoryFileWrapper 40 | filter.manifest = MemoryManifest.new 41 | filter.last_manifest = MemoryManifest.new 42 | filter.input_files = input_files || [input_file("border.scss", scss_input)] 43 | filter.output_root = "/path/to/output" 44 | filter.rake_application = Rake::Application.new 45 | filter 46 | end 47 | 48 | it "generates output" do 49 | filter = setup_filter SassFilter.new 50 | filter.output_files.should == [output_file("border.css")] 51 | 52 | tasks = filter.generate_rake_tasks 53 | tasks.each(&:invoke) 54 | 55 | file = MemoryFileWrapper.files["/path/to/output/border.css"] 56 | file.body.should == expected_css_output("border.scss") 57 | file.encoding.should == "UTF-8" 58 | end 59 | 60 | describe "naming output files" do 61 | it "translates .scss extensions to .css by default" do 62 | filter = setup_filter SassFilter.new 63 | filter.output_files.first.path.should == "border.css" 64 | end 65 | 66 | it "accepts a block to customize output file names" do 67 | filter = setup_filter(SassFilter.new { |input| "octopus" }) 68 | filter.output_files.first.path.should == "octopus" 69 | end 70 | end 71 | 72 | it "accepts options to pass to the Sass compiler" do 73 | input_files = [input_file("border.sass_file", sass_input)] 74 | filter = setup_filter(SassFilter.new(:syntax => :sass), input_files) 75 | tasks = filter.generate_rake_tasks 76 | tasks.each(&:invoke) 77 | file = MemoryFileWrapper.files["/path/to/output/border.sass_file"] 78 | file.body.should == expected_css_output("border.sass_file") 79 | end 80 | 81 | it "compiles files with a .sass extension as sass" do 82 | input_files = [input_file("border.sass", sass_input)] 83 | filter = setup_filter(SassFilter.new, input_files) 84 | tasks = filter.generate_rake_tasks 85 | tasks.each(&:invoke) 86 | file = MemoryFileWrapper.files["/path/to/output/border.css"] 87 | file.body.should == expected_css_output("border.sass") 88 | end 89 | 90 | it "passes Compass's options to the Sass compiler" do 91 | Compass.configuration do |c| 92 | c.preferred_syntax = :sass 93 | end 94 | 95 | input_files = [input_file("border.css", scss_input)] 96 | filter = setup_filter(SassFilter.new, input_files) 97 | tasks = filter.generate_rake_tasks 98 | tasks.each(&:invoke) 99 | file = MemoryFileWrapper.files["/path/to/output/border.css"] 100 | file.body.should == expected_css_output("border.css") 101 | end 102 | 103 | describe "additional load paths" do 104 | it "is empty by default" do 105 | filter = setup_filter(SassFilter.new) 106 | filter.additional_load_paths == [] 107 | end 108 | 109 | it "transforms to array" do 110 | filter = setup_filter(SassFilter.new(:additional_load_paths => "additional")) 111 | filter.additional_load_paths == ["additional"] 112 | end 113 | 114 | it "accepts array" do 115 | filter = setup_filter(SassFilter.new(:additional_load_paths => ["additional", "extra"])) 116 | filter.additional_load_paths == ["additional", "extra"] 117 | end 118 | end 119 | 120 | describe "additional dependencies" do 121 | def write_input_file(filename, contents='', root=tmp) 122 | mkdir_p root 123 | File.open(File.join(root, filename), 'w') { |f| f.puts contents } 124 | Rake::Pipeline::FileWrapper.new(root, filename) 125 | end 126 | 127 | let(:main_scss) { '@import "blue";' } 128 | let(:blue_scss) { '$blue: #3bbfce;' } 129 | let!(:main) { write_input_file('main.scss', main_scss) } 130 | let!(:blue) { write_input_file('blue.scss', blue_scss) } 131 | 132 | before do 133 | File.open(main.fullpath, "w") { |f| f.puts main_scss } 134 | File.open(blue.fullpath, "w") { |f| f.puts blue_scss } 135 | end 136 | 137 | it "includes @imported files" do 138 | filter = SassFilter.new 139 | filter.last_manifest = MemoryManifest.new 140 | filter.manifest = MemoryManifest.new 141 | filter.input_files = [main] 142 | filter.output_root = "#{tmp}/output" 143 | filter.rake_application = Rake::Application.new 144 | 145 | filter.additional_dependencies(main).should include(blue.fullpath) 146 | 147 | tasks = filter.generate_rake_tasks 148 | tasks.each(&:invoke) 149 | end 150 | end 151 | 152 | end 153 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require "rake-pipeline" 2 | require "rake-pipeline-web-filters" 3 | 4 | require "support/spec_helpers/file_utils" 5 | require "support/spec_helpers/filters" 6 | require "support/spec_helpers/input_helpers" 7 | require "support/spec_helpers/memory_file_wrapper" 8 | require "support/spec_helpers/memory_manifest" 9 | 10 | RSpec.configure do |config| 11 | original = Dir.pwd 12 | 13 | config.include Rake::Pipeline::SpecHelpers::FileUtils 14 | 15 | def tmp 16 | File.expand_path("../tmp", __FILE__) 17 | end 18 | 19 | config.before do 20 | rm_rf(tmp) 21 | mkdir_p(tmp) 22 | Dir.chdir(tmp) 23 | end 24 | 25 | config.after do 26 | Dir.chdir(original) 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /spec/stylus_filter_spec.rb: -------------------------------------------------------------------------------- 1 | describe "StylusFilter" do 2 | StylusFilter ||= Rake::Pipeline::Web::Filters::StylusFilter 3 | MemoryFileWrapper ||= Rake::Pipeline::SpecHelpers::MemoryFileWrapper 4 | MemoryManifest ||= Rake::Pipeline::SpecHelpers::MemoryManifest 5 | 6 | let(:styl_input) { <<-STYLUS } 7 | border-radius() 8 | -webkit-border-radius arguments 9 | -moz-border-radius arguments 10 | border-radius arguments 11 | 12 | body 13 | font 12px Helvetica, Arial, sans-serif 14 | 15 | a.button 16 | border-radius 5px 17 | STYLUS 18 | 19 | let(:expected_css_output) { <<-CSS } 20 | body { 21 | font: 12px Helvetica, Arial, sans-serif; 22 | } 23 | a.button { 24 | -webkit-border-radius: 5px; 25 | -moz-border-radius: 5px; 26 | border-radius: 5px; 27 | } 28 | CSS 29 | 30 | def input_file(name, content) 31 | MemoryFileWrapper.new("/path/to/input", name, "UTF-8", content) 32 | end 33 | 34 | def output_file(name) 35 | MemoryFileWrapper.new("/path/to/output", name, "UTF-8") 36 | end 37 | 38 | def setup_filter(filter, input=styl_input) 39 | filter.file_wrapper_class = MemoryFileWrapper 40 | filter.manifest = MemoryManifest.new 41 | filter.last_manifest = MemoryManifest.new 42 | filter.input_files = [input_file("border.styl", input)] 43 | filter.output_root = "/path/to/output" 44 | filter.rake_application = Rake::Application.new 45 | filter 46 | end 47 | 48 | it "generates output" do 49 | filter = setup_filter StylusFilter.new 50 | 51 | filter.output_files.should == [output_file("border.css")] 52 | 53 | tasks = filter.generate_rake_tasks 54 | tasks.each(&:invoke) 55 | 56 | file = MemoryFileWrapper.files["/path/to/output/border.css"] 57 | file.body.should == expected_css_output 58 | file.encoding.should == "UTF-8" 59 | end 60 | 61 | describe "naming output files" do 62 | it "translates .styl extensions to .css by default" do 63 | filter = setup_filter StylusFilter.new 64 | filter.output_files.first.path.should == "border.css" 65 | end 66 | 67 | it "accepts a block to customize output file names" do 68 | filter = setup_filter(StylusFilter.new { |input| "octopus" }) 69 | filter.output_files.first.path.should == "octopus" 70 | end 71 | end 72 | end 73 | -------------------------------------------------------------------------------- /spec/support/spec_helpers/file_utils.rb: -------------------------------------------------------------------------------- 1 | class Rake::Pipeline 2 | module SpecHelpers 3 | 4 | # TODO: OS agnostic modules 5 | module FileUtils 6 | def mkdir_p(dir) 7 | system "mkdir", "-p", dir 8 | end 9 | 10 | def touch(file) 11 | system "touch", file 12 | end 13 | 14 | def rm_rf(dir) 15 | system "rm", "-rf", dir 16 | end 17 | 18 | def touch_p(file) 19 | dir = File.dirname(file) 20 | mkdir_p dir 21 | touch file 22 | end 23 | 24 | def age_existing_files 25 | old_time = Time.now - 10 26 | Dir[File.join(tmp, "**/*.js")].each do |file| 27 | File.utime(old_time, old_time, file) 28 | end 29 | end 30 | end 31 | 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /spec/support/spec_helpers/filters.rb: -------------------------------------------------------------------------------- 1 | class Rake::Pipeline 2 | module SpecHelpers 3 | 4 | module Filters 5 | ConcatFilter = Rake::Pipeline::ConcatFilter 6 | 7 | class StripAssertsFilter < Rake::Pipeline::Filter 8 | def generate_output(inputs, output) 9 | inputs.each do |input| 10 | output.write input.read.gsub(%r{^\s*assert\(.*\)\s*;?\s*$}m, '') 11 | end 12 | end 13 | end 14 | 15 | class DynamicImportFilter < Rake::Pipeline::Filter 16 | def additional_dependencies(input) 17 | includes(input) 18 | end 19 | 20 | def includes(input) 21 | input.read.scan(/^@import\(\"(.*)\"\)$/).map(&:first).map do |inc| 22 | File.join(input.root, "#{inc}.import") 23 | end 24 | end 25 | 26 | def generate_output(inputs, output) 27 | inputs.each do |input| 28 | output.write input.read 29 | includes(input).each do |inc| 30 | output.write File.read(inc) 31 | end 32 | end 33 | end 34 | end 35 | end 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /spec/support/spec_helpers/input_helpers.rb: -------------------------------------------------------------------------------- 1 | class Rake::Pipeline 2 | module SpecHelpers 3 | module InputHelpers 4 | def input_file(path, root=File.join(tmp, "app/assets")) 5 | Rake::Pipeline::FileWrapper.new root, path 6 | end 7 | 8 | def output_file(path, root=File.join(tmp, "public")) 9 | input_file(path, root) 10 | end 11 | 12 | def create_files(files) 13 | Array(files).each do |file| 14 | mkdir_p File.dirname(file.fullpath) 15 | 16 | File.open(file.fullpath, "w") do |file| 17 | file.write "// This is #{file.path}\n" 18 | end 19 | end 20 | end 21 | end 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /spec/support/spec_helpers/memory_file_wrapper.rb: -------------------------------------------------------------------------------- 1 | class Rake::Pipeline 2 | module SpecHelpers 3 | class MemoryFileWrapper < Struct.new(:root, :path, :encoding, :body) 4 | @@files = {} 5 | @@data = {} 6 | 7 | def self.files 8 | @@files 9 | end 10 | 11 | def self.data 12 | @@data 13 | end 14 | 15 | def with_encoding(new_encoding) 16 | self.class.new(root, path, new_encoding, body) 17 | end 18 | 19 | def fullpath 20 | File.join(root, path) 21 | end 22 | 23 | def create 24 | @@files[fullpath] = self 25 | self.body = "" 26 | yield 27 | end 28 | 29 | def read 30 | body || @@data[fullpath] || "" 31 | end 32 | 33 | def write(contents) 34 | self.body << contents 35 | end 36 | end 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /spec/support/spec_helpers/memory_manifest.rb: -------------------------------------------------------------------------------- 1 | class Rake::Pipeline 2 | module SpecHelpers 3 | class MemoryManifest 4 | def initialize 5 | @entries = {} 6 | end 7 | 8 | # Look up an entry by filename. 9 | def [](key) 10 | @entries[key] 11 | end 12 | 13 | # Set an entry 14 | def []=(key, value) 15 | @entries[key] = value 16 | end 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /spec/tilt_filter_spec.rb: -------------------------------------------------------------------------------- 1 | describe "TiltFilter" do 2 | MemoryFileWrapper ||= Rake::Pipeline::SpecHelpers::MemoryFileWrapper 3 | MemoryManifest ||= Rake::Pipeline::SpecHelpers::MemoryManifest 4 | 5 | let(:input_files) { 6 | [ 7 | MemoryFileWrapper.new("/path/to/input", "foo.erb", "UTF-8", "<%= 'foo' %>\n"), 8 | MemoryFileWrapper.new("/path/to/input", "bar.str", "UTF-8", '#{ "bar" }') 9 | ] 10 | } 11 | 12 | let(:output_files) { 13 | [ 14 | MemoryFileWrapper.new("/path/to/output", "foo.txt", "UTF-8"), 15 | MemoryFileWrapper.new("/path/to/output", "bar.txt", "UTF-8") 16 | ] 17 | } 18 | 19 | def make_filter(*args) 20 | filter = Rake::Pipeline::Web::Filters::TiltFilter.new(*args) do |input| 21 | input.sub(/\.(erb|str)$/, '.txt') 22 | end 23 | filter.file_wrapper_class = MemoryFileWrapper 24 | filter.manifest = MemoryManifest.new 25 | filter.last_manifest = MemoryManifest.new 26 | filter.input_files = input_files 27 | filter.output_root = "/path/to/output" 28 | filter.rake_application = Rake::Application.new 29 | filter 30 | end 31 | 32 | it "generates output" do 33 | filter = make_filter 34 | 35 | filter.output_files.should == output_files 36 | 37 | tasks = filter.generate_rake_tasks 38 | tasks.each(&:invoke) 39 | 40 | file = MemoryFileWrapper.files["/path/to/output/foo.txt"] 41 | file.body.should == "foo" 42 | file.encoding.should == "UTF-8" 43 | 44 | file = MemoryFileWrapper.files["/path/to/output/bar.txt"] 45 | file.body.should == "bar" 46 | file.encoding.should == "UTF-8" 47 | end 48 | 49 | it "accepts options to pass to the template class" do 50 | # :trim => '' should tell ERB not to trim newlines 51 | filter = make_filter(:trim => '') 52 | 53 | tasks = filter.generate_rake_tasks 54 | tasks.each(&:invoke) 55 | file = MemoryFileWrapper.files["/path/to/output/foo.txt"] 56 | file.body.should == "foo\n" 57 | end 58 | 59 | describe 'with a rendering context' do 60 | 61 | let(:input_files) do 62 | [ 63 | MemoryFileWrapper.new("/path/to/input", "foo.erb", "UTF-8", "<%= foo %>"), 64 | ] 65 | end 66 | 67 | let(:context) do 68 | context = Class.new do 69 | def foo; 'foo'; end 70 | end.new 71 | end 72 | 73 | it 'uses the context' do 74 | filter = make_filter({}, context) 75 | 76 | tasks = filter.generate_rake_tasks 77 | tasks.each(&:invoke) 78 | file = MemoryFileWrapper.files["/path/to/output/foo.txt"] 79 | file.body.should == "foo" 80 | end 81 | end 82 | end 83 | -------------------------------------------------------------------------------- /spec/uglify_filter_spec.rb: -------------------------------------------------------------------------------- 1 | describe "UglifyFilter" do 2 | UglifyFilter ||= Rake::Pipeline::Web::Filters::UglifyFilter 3 | MemoryFileWrapper ||= Rake::Pipeline::SpecHelpers::MemoryFileWrapper 4 | MemoryManifest ||= Rake::Pipeline::SpecHelpers::MemoryManifest 5 | 6 | let(:js_input) { <<-HERE } 7 | var name = "Truckasaurus Gates"; 8 | console.log(name); 9 | HERE 10 | 11 | let(:expected_js_output) { 12 | 'var name="Truckasaurus Gates";console.log(name);' 13 | } 14 | 15 | let(:expected_beautiful_js_output) { 16 | %[var name = "Truckasaurus Gates";\n\nconsole.log(name);] 17 | } 18 | 19 | let(:filter_args) { [] } 20 | let(:filter_block) { nil } 21 | 22 | let(:filter) { 23 | filter = UglifyFilter.new(*filter_args, &filter_block) 24 | filter.file_wrapper_class = MemoryFileWrapper 25 | filter.manifest = MemoryManifest.new 26 | filter.last_manifest = MemoryManifest.new 27 | filter.input_files = [input_file("name.js", js_input)] 28 | filter.output_root = "/path/to/output" 29 | filter.rake_application = Rake::Application.new 30 | filter 31 | } 32 | 33 | def input_file(name, content) 34 | MemoryFileWrapper.new("/path/to/input", name, "UTF-8", content) 35 | end 36 | 37 | def output_file(name) 38 | MemoryFileWrapper.new("/path/to/output", name, "UTF-8") 39 | end 40 | 41 | it "generates output" do 42 | filter.output_files.should == [output_file("name.min.js")] 43 | 44 | tasks = filter.generate_rake_tasks 45 | tasks.each(&:invoke) 46 | 47 | file = MemoryFileWrapper.files["/path/to/output/name.min.js"] 48 | file.body.should == expected_js_output 49 | file.encoding.should == "UTF-8" 50 | end 51 | 52 | describe "Skipping" do 53 | it "skips files ending in .min.js" do 54 | filter.input_files = [input_file("name.min.js", 'fake-js')] 55 | 56 | filter.output_files.should == [output_file("name.min.js")] 57 | 58 | tasks = filter.generate_rake_tasks 59 | tasks.each(&:invoke) 60 | 61 | file = MemoryFileWrapper.files["/path/to/output/name.min.js"] 62 | file.body.should == 'fake-js' 63 | file.encoding.should == "UTF-8" 64 | end 65 | 66 | it "does not count files ending in min.js as preminified" do 67 | filter.input_files = [input_file("min.js", js_input)] 68 | 69 | filter.output_files.should == [output_file("min.min.js")] 70 | 71 | tasks = filter.generate_rake_tasks 72 | tasks.each(&:invoke) 73 | 74 | file = MemoryFileWrapper.files["/path/to/output/min.min.js"] 75 | file.body.should == expected_js_output 76 | file.encoding.should == "UTF-8" 77 | end 78 | end 79 | 80 | it "translates .js extensions to .min.js by default" do 81 | filter.output_files.first.path.should == "name.min.js" 82 | end 83 | 84 | context "with preserve_input option" do 85 | let(:filter_args) do 86 | [{ :preserve_input => true }] 87 | end 88 | 89 | it "should output both the unminified and the minified files" do 90 | filter.output_files.should == [output_file("name.js"), output_file("name.min.js")] 91 | 92 | tasks = filter.generate_rake_tasks 93 | tasks.each(&:invoke) 94 | 95 | file = MemoryFileWrapper.files["/path/to/output/name.js"] 96 | file.body.should == js_input 97 | file.encoding.should == "UTF-8" 98 | 99 | file = MemoryFileWrapper.files["/path/to/output/name.min.js"] 100 | file.body.should == expected_js_output 101 | file.encoding.should == "UTF-8" 102 | end 103 | end 104 | 105 | context "with output name block" do 106 | let(:filter_block) do 107 | Proc.new { |input| "octopus" } 108 | end 109 | 110 | it "customizes output file names" do 111 | filter.output_files.first.path.should == "octopus" 112 | end 113 | end 114 | 115 | context "with Uglify options" do 116 | let(:filter_args) do 117 | [output: { :beautify => true }] 118 | end 119 | 120 | it "passes options to the Uglify compressor" do 121 | filter.input_files = [input_file("name.js", js_input)] 122 | tasks = filter.generate_rake_tasks 123 | tasks.each(&:invoke) 124 | file = MemoryFileWrapper.files["/path/to/output/name.min.js"] 125 | file.body.should == expected_beautiful_js_output 126 | end 127 | end 128 | end 129 | -------------------------------------------------------------------------------- /spec/yui_css_filter_spec.rb: -------------------------------------------------------------------------------- 1 | describe "YUICssFilter" do 2 | YUICssFilter ||= Rake::Pipeline::Web::Filters::YUICssFilter 3 | MemoryFileWrapper ||= Rake::Pipeline::SpecHelpers::MemoryFileWrapper 4 | MemoryManifest ||= Rake::Pipeline::SpecHelpers::MemoryManifest 5 | 6 | let(:css_input) { <<-HERE } 7 | div.error { 8 | color: red; 9 | } 10 | div.warning { 11 | display: none; 12 | } 13 | HERE 14 | 15 | let(:expected_css_output) { 16 | 'div.error{color:red}div.warning{display:none}' 17 | } 18 | 19 | let(:expected_linebreak_css_output) { 20 | %[div.error{color:red}\ndiv.warning{display:none}] 21 | } 22 | 23 | def input_file(name, content) 24 | MemoryFileWrapper.new("/path/to/input", name, "UTF-8", content) 25 | end 26 | 27 | def output_file(name) 28 | MemoryFileWrapper.new("/path/to/output", name, "UTF-8") 29 | end 30 | 31 | def setup_filter(filter) 32 | filter.file_wrapper_class = MemoryFileWrapper 33 | filter.manifest = MemoryManifest.new 34 | filter.last_manifest = MemoryManifest.new 35 | filter.input_files = [input_file("error.css", css_input)] 36 | filter.output_root = "/path/to/output" 37 | filter.rake_application = Rake::Application.new 38 | filter 39 | end 40 | 41 | it "generates output" do 42 | filter = setup_filter YUICssFilter.new 43 | 44 | filter.output_files.should == [output_file("error.min.css")] 45 | 46 | tasks = filter.generate_rake_tasks 47 | tasks.each(&:invoke) 48 | 49 | file = MemoryFileWrapper.files["/path/to/output/error.min.css"] 50 | file.body.should == expected_css_output 51 | file.encoding.should == "UTF-8" 52 | end 53 | 54 | it "skips files named .min" do 55 | filter = setup_filter YUICssFilter.new 56 | 57 | filter.input_files = [input_file("error.min.css", "fake-css")] 58 | 59 | filter.output_files.should == [output_file("error.min.css")] 60 | 61 | tasks = filter.generate_rake_tasks 62 | tasks.each(&:invoke) 63 | 64 | file = MemoryFileWrapper.files["/path/to/output/error.min.css"] 65 | file.body.should == "fake-css" 66 | file.encoding.should == "UTF-8" 67 | end 68 | 69 | describe "naming output files" do 70 | it "translates .css extensions to .min.css by default" do 71 | filter = setup_filter YUICssFilter.new 72 | filter.output_files.first.path.should == "error.min.css" 73 | end 74 | 75 | it "accepts a block to customize output file names" do 76 | filter = setup_filter(YUICssFilter.new { |input| "octopus" }) 77 | filter.output_files.first.path.should == "octopus" 78 | end 79 | end 80 | 81 | it "accepts options to pass to the YUI compressor" do 82 | filter = setup_filter(YUICssFilter.new(:line_break => 0)) 83 | filter.input_files = [input_file("error.css", css_input)] 84 | tasks = filter.generate_rake_tasks 85 | tasks.each(&:invoke) 86 | file = MemoryFileWrapper.files["/path/to/output/error.min.css"] 87 | file.body.should == expected_linebreak_css_output 88 | end 89 | 90 | end 91 | 92 | -------------------------------------------------------------------------------- /spec/yui_javascript_filter_spec.rb: -------------------------------------------------------------------------------- 1 | describe "YUIJavaScriptFilter" do 2 | YUIFilter ||= Rake::Pipeline::Web::Filters::YUIJavaScriptFilter 3 | MemoryFileWrapper ||= Rake::Pipeline::SpecHelpers::MemoryFileWrapper 4 | MemoryManifest ||= Rake::Pipeline::SpecHelpers::MemoryManifest 5 | 6 | let(:js_input) { <<-HERE } 7 | var name = "Truckasaurus Gates"; 8 | console.log(name); 9 | HERE 10 | 11 | let(:expected_js_output) { 12 | 'var name="Truckasaurus Gates";console.log(name);' 13 | } 14 | 15 | let(:expected_linebreak_js_output) { 16 | %[var name="Truckasaurus Gates";\nconsole.log(name);] 17 | } 18 | 19 | def input_file(name, content) 20 | MemoryFileWrapper.new("/path/to/input", name, "UTF-8", content) 21 | end 22 | 23 | def output_file(name) 24 | MemoryFileWrapper.new("/path/to/output", name, "UTF-8") 25 | end 26 | 27 | def setup_filter(filter) 28 | filter.file_wrapper_class = MemoryFileWrapper 29 | filter.manifest = MemoryManifest.new 30 | filter.last_manifest = MemoryManifest.new 31 | filter.input_files = [input_file("name.js", js_input)] 32 | filter.output_root = "/path/to/output" 33 | filter.rake_application = Rake::Application.new 34 | filter 35 | end 36 | 37 | it "generates output" do 38 | filter = setup_filter YUIFilter.new 39 | 40 | filter.output_files.should == [output_file("name.min.js")] 41 | 42 | tasks = filter.generate_rake_tasks 43 | tasks.each(&:invoke) 44 | 45 | file = MemoryFileWrapper.files["/path/to/output/name.min.js"] 46 | file.body.should == expected_js_output 47 | file.encoding.should == "UTF-8" 48 | end 49 | 50 | describe "naming output files" do 51 | it "translates .js extensions to .min.js by default" do 52 | filter = setup_filter YUIFilter.new 53 | filter.output_files.first.path.should == "name.min.js" 54 | end 55 | 56 | it "accepts a block to customize output file names" do 57 | filter = setup_filter(YUIFilter.new { |input| "octopus" }) 58 | filter.output_files.first.path.should == "octopus" 59 | end 60 | end 61 | 62 | it "accepts options to pass to the YUI compressor" do 63 | filter = setup_filter(YUIFilter.new(:line_break => 0)) 64 | filter.input_files = [input_file("name.js", js_input)] 65 | tasks = filter.generate_rake_tasks 66 | tasks.each(&:invoke) 67 | file = MemoryFileWrapper.files["/path/to/output/name.min.js"] 68 | file.body.should == expected_linebreak_js_output 69 | end 70 | 71 | end 72 | --------------------------------------------------------------------------------