rake-pipeline-web-filters-fork 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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