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,59 @@
1
+ require 'rake-pipeline-web-filters/filter_with_dependencies'
2
+
3
+ module Rake::Pipeline::Web::Filters
4
+ # A filter that compresses JavaScript input files using
5
+ # the YUI JavaScript compressor.
6
+ #
7
+ # Requires {https://rubygems.org/gems/yui-compressor yui-compressor}
8
+ #
9
+ # @example
10
+ # !!!ruby
11
+ # Rake::Pipeline.build do
12
+ # input "app/assets", "**/*.js"
13
+ # output "public"
14
+ #
15
+ # # Compress each JS file under the app/assets
16
+ # # directory.
17
+ # filter Rake::Pipeline::Web::Filters::YUIJavaScriptFilter
18
+ # end
19
+ class YUIJavaScriptFilter < Rake::Pipeline::Filter
20
+ include Rake::Pipeline::Web::Filters::FilterWithDependencies
21
+
22
+ # @return [Hash] a hash of options to pass to the
23
+ # YUI compressor when compressing.
24
+ attr_reader :options
25
+
26
+ # @param [Hash] options options to pass to the YUI
27
+ # JavaScript compressor.
28
+ # @param [Proc] block a block to use as the Filter's
29
+ # {#output_name_generator}.
30
+ def initialize(options={}, &block)
31
+ block ||= proc { |input| input.sub(/\.js$/, '.min.js') }
32
+ super(&block)
33
+ @options = options
34
+ end
35
+
36
+ # Implement the {#generate_output} method required by
37
+ # the {Filter} API. Compresses each input file with
38
+ # the YUI JavaScript compressor.
39
+ #
40
+ # @param [Array<FileWrapper>] inputs an Array of
41
+ # {FileWrapper} objects representing the inputs to
42
+ # this filter.
43
+ # @param [FileWrapper] output a single {FileWrapper}
44
+ # object representing the output.
45
+ def generate_output(inputs, output)
46
+ compressor = YUI::JavaScriptCompressor.new(options)
47
+ inputs.each do |input|
48
+ output.write compressor.compress(input.read)
49
+ end
50
+ end
51
+
52
+ private
53
+
54
+ def external_dependencies
55
+ [ 'yui/compressor' ]
56
+ end
57
+ end
58
+ end
59
+
@@ -0,0 +1,33 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/rake-pipeline-web-filters/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Yehuda Katz"]
6
+ gem.email = ["wycats@gmail.com"]
7
+ gem.description = %q{A collection of web filters for rake-pipeline}
8
+ gem.summary = %q{Contributed filters for use in rake-pipeline that are useful for web projects, like asset management}
9
+ gem.homepage = "http://github.com/wycats/rake-pipeline-web-filters"
10
+
11
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
12
+ gem.files = `git ls-files`.split("\n")
13
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
14
+ gem.name = "rake-pipeline-web-filters-fork"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Rake::Pipeline::Web::Filters::VERSION
17
+
18
+ gem.add_dependency "rake-pipeline", "~> 0.6"
19
+ gem.add_dependency "rack"
20
+
21
+ gem.add_development_dependency "rspec"
22
+ gem.add_development_dependency "tilt"
23
+ gem.add_development_dependency "sass"
24
+ gem.add_development_dependency "compass"
25
+ gem.add_development_dependency "coffee-script"
26
+ gem.add_development_dependency "redcarpet", '~> 2.0'
27
+ gem.add_development_dependency "yui-compressor"
28
+ gem.add_development_dependency "uglifier"
29
+ gem.add_development_dependency "less"
30
+ gem.add_development_dependency "json"
31
+ gem.add_development_dependency "therubyracer"
32
+ gem.add_development_dependency "stylus"
33
+ end
@@ -0,0 +1,108 @@
1
+ describe "CacheBusterFilter" do
2
+ MemoryFileWrapper ||= Rake::Pipeline::SpecHelpers::MemoryFileWrapper
3
+ MemoryManifest ||= Rake::Pipeline::SpecHelpers::MemoryManifest
4
+ CacheBusterFilter ||= Rake::Pipeline::Web::Filters::CacheBusterFilter
5
+
6
+ let(:content) { "it doesn't matter" }
7
+
8
+ let(:input_file) {
9
+ MemoryFileWrapper.new '/path/to/input', 'file.txt', 'UTF-8', content
10
+ }
11
+
12
+ let(:output_root) {
13
+ '/path/to/output'
14
+ }
15
+
16
+ def setup_filter(filter)
17
+ filter.file_wrapper_class = MemoryFileWrapper
18
+ filter.manifest = MemoryManifest.new
19
+ filter.last_manifest = MemoryManifest.new
20
+ filter.input_files = [ input_file ]
21
+ filter.output_root = output_root
22
+ filter.rake_application = Rake::Application.new
23
+ filter
24
+ end
25
+
26
+ describe 'DEFAULT_KEY_GENERATOR' do
27
+
28
+ subject { CacheBusterFilter::DEFAULT_KEY_GENERATOR }
29
+
30
+ it "returns the MD5 hash of the input's file name and contents" do
31
+ expected = Digest::MD5.new << input_file.path << content
32
+ subject.call(input_file).should == expected
33
+ end
34
+
35
+ end
36
+
37
+ describe 'with the default cache key strategy' do
38
+
39
+ let(:output_file) {
40
+ key = CacheBusterFilter::DEFAULT_KEY_GENERATOR.call(input_file)
41
+ MemoryFileWrapper.new output_root, "file-#{key}.txt", 'UTF-8'
42
+ }
43
+
44
+ subject { setup_filter CacheBusterFilter.new }
45
+
46
+ it 'outputs to the MD5 hash of the file name and contents' do
47
+ subject.output_files.should == [ output_file ]
48
+ end
49
+
50
+ it 'passes file contents through unchanged' do
51
+ tasks = subject.generate_rake_tasks
52
+ tasks.each(&:invoke)
53
+ file = MemoryFileWrapper.files[ output_file.fullpath ]
54
+ file.body.should == content
55
+ file.encoding.should == 'UTF-8'
56
+ end
57
+
58
+ end
59
+
60
+ describe 'with a custom key strategy' do
61
+
62
+ let(:output_file) {
63
+ MemoryFileWrapper.new output_root, 'file-foo.txt', 'UTF-8'
64
+ }
65
+
66
+ subject do
67
+ setup_filter(CacheBusterFilter.new() { 'foo' })
68
+ end
69
+
70
+ it 'uses the custom key strategy' do
71
+ subject.output_files.should == [ output_file ]
72
+ end
73
+
74
+ end
75
+
76
+ describe 'for an input file with multiple dots' do
77
+ let(:input_file) {
78
+ MemoryFileWrapper.new '/path/to/input', 'my.text.file.txt', 'UTF-8', content
79
+ }
80
+
81
+ let(:output_file) {
82
+ MemoryFileWrapper.new output_root, "my.text.file-foo.txt", 'UTF-8'
83
+ }
84
+
85
+ subject { setup_filter(CacheBusterFilter.new() { 'foo' }) }
86
+
87
+ it 'appends the busting key to the penultimate part' do
88
+ subject.output_files.should == [ output_file ]
89
+ end
90
+ end
91
+
92
+ describe 'for an input file with no dots' do
93
+ let(:input_file) {
94
+ MemoryFileWrapper.new '/path/to/input', 'my_text_file', 'UTF-8', content
95
+ }
96
+
97
+ let(:output_file) {
98
+ MemoryFileWrapper.new output_root, "my_text_file-foo", 'UTF-8'
99
+ }
100
+
101
+ subject { setup_filter(CacheBusterFilter.new() { 'foo' }) }
102
+
103
+ it 'appends the busting key to the end of the filename' do
104
+ subject.output_files.should == [ output_file ]
105
+ end
106
+ end
107
+
108
+ end
@@ -0,0 +1,79 @@
1
+ describe "ChainedFilter" do
2
+ MemoryFileWrapper ||= Rake::Pipeline::SpecHelpers::MemoryFileWrapper
3
+ MemoryManifest ||= Rake::Pipeline::SpecHelpers::MemoryManifest
4
+ ChainedFilter ||= Rake::Pipeline::Web::Filters::ChainedFilter
5
+
6
+ input_file1 = MemoryFileWrapper.new("/path", "input.js.strip_asserts.erb", "UTF-8", <<-CONTENT)
7
+ assert("must be true", true);
8
+ Input = {};
9
+ <%= $chained_filter_title %> = {};
10
+ CONTENT
11
+
12
+ input_file2 = MemoryFileWrapper.new("/path", "input.js.erb.strip_asserts", "UTF-8", <<-CONTENT)
13
+ assert("must be true", true);
14
+ Input = {};
15
+ <%= $chained_filter_title %> = {};
16
+ CONTENT
17
+
18
+ EXPECTED_OUTPUT = <<-EXPECTED
19
+
20
+ Input = {};
21
+ Chained = {};
22
+ EXPECTED
23
+
24
+ let(:erb_filter) do
25
+ Class.new(Rake::Pipeline::Filter) do
26
+ def generate_output(inputs, output)
27
+ inputs.each do |input|
28
+ output.write ERB.new(input.read).result
29
+ end
30
+ end
31
+ end
32
+ end
33
+
34
+ let(:strip_asserts_filter) do
35
+ Class.new(Rake::Pipeline::Filter) do
36
+ def generate_output(inputs, output)
37
+ inputs.each do |input|
38
+ output.write input.read.gsub(/^assert.*$/, '')
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ before do
45
+ $chained_filter_title = "Chained"
46
+ end
47
+
48
+ after do
49
+ $chained_filter_title = nil
50
+ end
51
+
52
+ [ input_file1, input_file2 ].each do |file_wrapper|
53
+ it "should run through the filters in order" do
54
+ filter = ChainedFilter.new(
55
+ :types => {
56
+ :erb => erb_filter,
57
+ :strip_asserts => strip_asserts_filter
58
+ }
59
+ )
60
+
61
+ filter.file_wrapper_class = MemoryFileWrapper
62
+ filter.manifest = MemoryManifest.new
63
+ filter.last_manifest = MemoryManifest.new
64
+ filter.input_files = [ file_wrapper ]
65
+ filter.output_root = "/output"
66
+ filter.rake_application = Rake::Application.new
67
+
68
+ filter.output_files.should == [ MemoryFileWrapper.new("/output", "input.js", "UTF-8") ]
69
+
70
+ tasks = filter.generate_rake_tasks
71
+ tasks.each(&:invoke)
72
+
73
+ file = MemoryFileWrapper.files["/output/input.js"]
74
+ file.body.should == EXPECTED_OUTPUT
75
+ file.encoding.should == "UTF-8"
76
+ end
77
+ end
78
+
79
+ end
@@ -0,0 +1,113 @@
1
+ describe "CoffeeScriptFilter" do
2
+ CoffeeScriptFilter ||= Rake::Pipeline::Web::Filters::CoffeeScriptFilter
3
+ MemoryFileWrapper ||= Rake::Pipeline::SpecHelpers::MemoryFileWrapper
4
+ MemoryManifest ||= Rake::Pipeline::SpecHelpers::MemoryManifest
5
+
6
+ let(:coffee_input) { <<-COFFEE }
7
+ x = 1;
8
+
9
+ y = ->
10
+ x += 1
11
+ COFFEE
12
+
13
+ let(:expected_coffee_output) { <<-HTML }
14
+ (function() {
15
+ var x, y;
16
+
17
+ x = 1;
18
+
19
+ y = function() {
20
+ return x += 1;
21
+ };
22
+
23
+ }).call(this);
24
+ HTML
25
+
26
+ let(:expected_unwrapped_coffee_output) { <<-HTML }
27
+ var x, y;
28
+
29
+ x = 1;
30
+
31
+ y = function() {
32
+ return x += 1;
33
+ };
34
+ HTML
35
+
36
+ def input_file(name, content)
37
+ MemoryFileWrapper.new("/path/to/input", name, "UTF-8", content)
38
+ end
39
+
40
+ def output_file(name)
41
+ MemoryFileWrapper.new("/path/to/output", name, "UTF-8")
42
+ end
43
+
44
+ def should_match(expected, output)
45
+ "#{expected}\n".gsub(/\n+/, "\n").should == "#{output}\n".gsub(/\n+/, "\n")
46
+ end
47
+
48
+ def setup_filter(filter)
49
+ filter.file_wrapper_class = MemoryFileWrapper
50
+ filter.manifest = MemoryManifest.new
51
+ filter.last_manifest = MemoryManifest.new
52
+ filter.input_files = [input_file("input.coffee", coffee_input)]
53
+ filter.output_root = "/path/to/output"
54
+ filter.rake_application = Rake::Application.new
55
+ filter
56
+ end
57
+
58
+ it "generates output" do
59
+ filter = setup_filter CoffeeScriptFilter.new
60
+
61
+ filter.output_files.should == [output_file("input.js")]
62
+
63
+ tasks = filter.generate_rake_tasks
64
+ tasks.each(&:invoke)
65
+
66
+ file = MemoryFileWrapper.files["/path/to/output/input.js"]
67
+ should_match file.body, expected_coffee_output
68
+ file.encoding.should == "UTF-8"
69
+ end
70
+
71
+ it "generates unwrapped output" do
72
+ filter = setup_filter CoffeeScriptFilter.new(:no_wrap => true)
73
+
74
+ filter.output_files.should == [output_file("input.js")]
75
+
76
+ tasks = filter.generate_rake_tasks
77
+ tasks.each(&:invoke)
78
+
79
+ file = MemoryFileWrapper.files["/path/to/output/input.js"]
80
+ should_match file.body, expected_unwrapped_coffee_output
81
+ file.encoding.should == "UTF-8"
82
+ end
83
+
84
+ describe "naming output files" do
85
+ it "translates .coffee extensions to .js by default" do
86
+ filter = setup_filter CoffeeScriptFilter.new
87
+ filter.output_files.first.path.should == "input.js"
88
+ end
89
+
90
+ it "accepts a block to customize output file names" do
91
+ filter = setup_filter(CoffeeScriptFilter.new { |input| "octopus" })
92
+ filter.output_files.first.path.should == "octopus"
93
+ end
94
+ end
95
+
96
+ describe "invalid input" do
97
+ let(:coffee_input) { <<-COFFEE }
98
+ y = function(){
99
+ return "whoops there javascript in here!"
100
+ }
101
+ COFFEE
102
+
103
+ it "has a useful error message including the input file name" do
104
+ filter = setup_filter CoffeeScriptFilter.new
105
+ tasks = filter.generate_rake_tasks
106
+ lambda {
107
+ tasks.each(&:invoke)
108
+ }.should raise_error(ExecJS::RuntimeError, /Error compiling input.coffee.+line 1/i)
109
+ end
110
+ end
111
+
112
+ end
113
+
@@ -0,0 +1,52 @@
1
+ require 'base64'
2
+ require 'stringio'
3
+ require 'zlib'
4
+
5
+ describe "GzipFilter" do
6
+ GzipFilter ||= Rake::Pipeline::Web::Filters::GzipFilter
7
+ MemoryFileWrapper ||= Rake::Pipeline::SpecHelpers::MemoryFileWrapper
8
+ MemoryManifest ||= Rake::Pipeline::SpecHelpers::MemoryManifest
9
+
10
+ let(:input) { "(function(){console.log('gzip me')})();" }
11
+
12
+ def input_file(name, content)
13
+ MemoryFileWrapper.new("/path/to/input", name, "UTF-8", content)
14
+ end
15
+
16
+ def output_file(name)
17
+ MemoryFileWrapper.new("/path/to/output", name, "BINARY")
18
+ end
19
+
20
+ def setup_filter(filter)
21
+ filter.file_wrapper_class = MemoryFileWrapper
22
+ filter.manifest = MemoryManifest.new
23
+ filter.last_manifest = MemoryManifest.new
24
+ filter.input_files = [input_file("test.js", input)]
25
+ filter.output_root = "/path/to/output"
26
+ filter.rake_application = Rake::Application.new
27
+ filter
28
+ end
29
+
30
+ it "generates output" do
31
+ filter = setup_filter GzipFilter.new
32
+ filter.output_files.should == [output_file("test.js.gz")]
33
+ tasks = filter.generate_rake_tasks
34
+ tasks.each(&:invoke)
35
+ file = MemoryFileWrapper.files["/path/to/output/test.js.gz"]
36
+ Zlib::GzipReader.new(StringIO.new(file.body)).read.should == input
37
+ end
38
+
39
+ describe "naming output files" do
40
+ it "translates extensions to .*.gz by default" do
41
+ filter = setup_filter GzipFilter.new
42
+ filter.output_files.first.path.should == "test.js.gz"
43
+ end
44
+
45
+ it "accepts a block to customize output file names" do
46
+ filter = setup_filter(GzipFilter.new { |input| "octopus" })
47
+ filter.output_files.first.path.should == "octopus"
48
+ end
49
+ end
50
+
51
+ end
52
+