rake-pipeline-web-filters-fork 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. data/.gitignore +19 -0
  2. data/.rspec +1 -0
  3. data/.travis.yml +11 -0
  4. data/.yardopts +2 -0
  5. data/Gemfile +6 -0
  6. data/README.markdown +58 -0
  7. data/README.yard +25 -0
  8. data/Rakefile +10 -0
  9. data/lib/rake-pipeline-web-filters.rb +31 -0
  10. data/lib/rake-pipeline-web-filters/cache_buster_filter.rb +42 -0
  11. data/lib/rake-pipeline-web-filters/chained_filter.rb +116 -0
  12. data/lib/rake-pipeline-web-filters/coffee_script_filter.rb +41 -0
  13. data/lib/rake-pipeline-web-filters/filter_with_dependencies.rb +27 -0
  14. data/lib/rake-pipeline-web-filters/gzip_filter.rb +59 -0
  15. data/lib/rake-pipeline-web-filters/handlebars_filter.rb +62 -0
  16. data/lib/rake-pipeline-web-filters/helpers.rb +138 -0
  17. data/lib/rake-pipeline-web-filters/iife_filter.rb +38 -0
  18. data/lib/rake-pipeline-web-filters/jade_filter.rb +61 -0
  19. data/lib/rake-pipeline-web-filters/less_filter.rb +55 -0
  20. data/lib/rake-pipeline-web-filters/markdown_filter.rb +70 -0
  21. data/lib/rake-pipeline-web-filters/minispade_filter.rb +63 -0
  22. data/lib/rake-pipeline-web-filters/neuter_filter.rb +110 -0
  23. data/lib/rake-pipeline-web-filters/sass_filter.rb +87 -0
  24. data/lib/rake-pipeline-web-filters/stylus_filter.rb +59 -0
  25. data/lib/rake-pipeline-web-filters/tilt_filter.rb +70 -0
  26. data/lib/rake-pipeline-web-filters/uglify_filter.rb +82 -0
  27. data/lib/rake-pipeline-web-filters/version.rb +9 -0
  28. data/lib/rake-pipeline-web-filters/yui_css_filter.rb +70 -0
  29. data/lib/rake-pipeline-web-filters/yui_javascript_filter.rb +59 -0
  30. data/rake-pipeline-web-filters.gemspec +33 -0
  31. data/spec/cache_buster_filter_spec.rb +108 -0
  32. data/spec/chained_filter_spec.rb +79 -0
  33. data/spec/coffee_script_filter_spec.rb +113 -0
  34. data/spec/gzip_filter_spec.rb +52 -0
  35. data/spec/handlebars_filter_spec.rb +73 -0
  36. data/spec/helpers_spec.rb +146 -0
  37. data/spec/iife_filter_spec.rb +58 -0
  38. data/spec/jade_filter_spec.rb +92 -0
  39. data/spec/less_filter_spec.rb +62 -0
  40. data/spec/markdown_filter_spec.rb +89 -0
  41. data/spec/minispade_filter_spec.rb +82 -0
  42. data/spec/neuter_filter_spec.rb +216 -0
  43. data/spec/sass_filter_spec.rb +152 -0
  44. data/spec/spec_helper.rb +28 -0
  45. data/spec/stylus_filter_spec.rb +72 -0
  46. data/spec/support/spec_helpers/file_utils.rb +33 -0
  47. data/spec/support/spec_helpers/filters.rb +37 -0
  48. data/spec/support/spec_helpers/input_helpers.rb +23 -0
  49. data/spec/support/spec_helpers/memory_file_wrapper.rb +38 -0
  50. data/spec/support/spec_helpers/memory_manifest.rb +19 -0
  51. data/spec/tilt_filter_spec.rb +82 -0
  52. data/spec/uglify_filter_spec.rb +128 -0
  53. data/spec/yui_css_filter_spec.rb +91 -0
  54. data/spec/yui_javascript_filter_spec.rb +71 -0
  55. metadata +308 -0
@@ -0,0 +1,82 @@
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/*@if (@_jscript) @else @*/\\n//@ sourceURL=/path/to/input/foo.js\\n/*@end@*/");}
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
@@ -0,0 +1,216 @@
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
@@ -0,0 +1,152 @@
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