rake-pipeline-web-filters 0.5.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/.gitignore +2 -0
  2. data/Gemfile +1 -0
  3. data/Rakefile +8 -0
  4. data/lib/rake-pipeline-web-filters.rb +17 -3
  5. data/lib/rake-pipeline-web-filters/cache_buster_filter.rb +42 -0
  6. data/lib/rake-pipeline-web-filters/chained_filter.rb +116 -0
  7. data/lib/rake-pipeline-web-filters/coffee_script_filter.rb +41 -0
  8. data/lib/rake-pipeline-web-filters/filter_with_dependencies.rb +27 -0
  9. data/lib/rake-pipeline-web-filters/gzip_filter.rb +59 -0
  10. data/lib/rake-pipeline-web-filters/handlebars_filter.rb +62 -0
  11. data/lib/rake-pipeline-web-filters/helpers.rb +100 -18
  12. data/lib/rake-pipeline-web-filters/iife_filter.rb +38 -0
  13. data/lib/rake-pipeline-web-filters/less_filter.rb +55 -0
  14. data/lib/rake-pipeline-web-filters/markdown_filter.rb +70 -0
  15. data/lib/rake-pipeline-web-filters/minispade_filter.rb +21 -5
  16. data/lib/rake-pipeline-web-filters/neuter_filter.rb +110 -0
  17. data/lib/rake-pipeline-web-filters/sass_filter.rb +87 -0
  18. data/lib/rake-pipeline-web-filters/stylus_filter.rb +59 -0
  19. data/lib/rake-pipeline-web-filters/tilt_filter.rb +16 -3
  20. data/lib/rake-pipeline-web-filters/uglify_filter.rb +66 -0
  21. data/lib/rake-pipeline-web-filters/version.rb +1 -1
  22. data/lib/rake-pipeline-web-filters/yui_css_filter.rb +70 -0
  23. data/lib/rake-pipeline-web-filters/yui_javascript_filter.rb +59 -0
  24. data/rake-pipeline-web-filters.gemspec +10 -1
  25. data/spec/cache_buster_filter_spec.rb +105 -0
  26. data/spec/chained_filter_spec.rb +76 -0
  27. data/spec/coffee_script_filter_spec.rb +110 -0
  28. data/spec/gzip_filter_spec.rb +49 -0
  29. data/spec/handlebars_filter_spec.rb +70 -0
  30. data/spec/helpers_spec.rb +112 -18
  31. data/spec/iife_filter_spec.rb +55 -0
  32. data/spec/less_filter_spec.rb +59 -0
  33. data/spec/markdown_filter_spec.rb +86 -0
  34. data/spec/minispade_filter_spec.rb +47 -15
  35. data/spec/neuter_filter_spec.rb +204 -0
  36. data/spec/sass_filter_spec.rb +147 -0
  37. data/spec/spec_helper.rb +10 -1
  38. data/spec/stylus_filter_spec.rb +69 -0
  39. data/spec/tilt_filter_spec.rb +25 -1
  40. data/spec/uglify_filter_spec.rb +82 -0
  41. data/spec/yui_css_filter_spec.rb +88 -0
  42. data/spec/yui_javascript_filter_spec.rb +68 -0
  43. metadata +225 -19
  44. data/lib/rake-pipeline-web-filters/ordering_concat_filter.rb +0 -38
  45. data/lib/rake-pipeline-web-filters/sass_compiler.rb +0 -53
  46. data/spec/ordering_concat_filter_spec.rb +0 -39
  47. data/spec/sass_compiler_spec.rb +0 -89
@@ -1,4 +1,4 @@
1
- require 'tilt'
1
+ require 'rake-pipeline-web-filters/filter_with_dependencies'
2
2
 
3
3
  module Rake::Pipeline::Web::Filters
4
4
  # A filter that accepts a series of inputs and translates
@@ -6,6 +6,8 @@ module Rake::Pipeline::Web::Filters
6
6
  # to guess which template language to use based on the input
7
7
  # file extension.
8
8
  #
9
+ # Requires {http://rubygems.org/gems/tilt/ tilt}
10
+ #
9
11
  # @example
10
12
  # !!!ruby
11
13
  # Rake::Pipeline.build do
@@ -19,17 +21,24 @@ module Rake::Pipeline::Web::Filters
19
21
  # end
20
22
  # end
21
23
  class TiltFilter < Rake::Pipeline::Filter
24
+ include Rake::Pipeline::Web::Filters::FilterWithDependencies
25
+
22
26
  # @return [Hash] a hash of options to pass to Tilt
23
27
  # when rendering.
24
28
  attr_reader :options
25
29
 
30
+ # @return [Object] an object to use as the rendering
31
+ # context.
32
+ attr_reader :context
33
+
26
34
  # @param [Hash] options options to pass to the Tilt
27
35
  # template class constructor.
28
36
  # @param [Proc] block a block to use as the Filter's
29
37
  # {#output_name_generator}.
30
- def initialize(options={}, &block)
38
+ def initialize(options={}, context = nil, &block)
31
39
  super(&block)
32
40
  @options = options
41
+ @context = context || Object.new
33
42
  end
34
43
 
35
44
  # Implement the {#generate_output} method required by
@@ -45,7 +54,7 @@ module Rake::Pipeline::Web::Filters
45
54
  def generate_output(inputs, output)
46
55
  inputs.each do |input|
47
56
  out = if (template_class = Tilt[input.path])
48
- template_class.new(nil, 1, options) { |t| input.read }.render
57
+ template_class.new(nil, 1, options) { |t| input.read }.render(context)
49
58
  else
50
59
  input.read
51
60
  end
@@ -53,5 +62,9 @@ module Rake::Pipeline::Web::Filters
53
62
  output.write out
54
63
  end
55
64
  end
65
+
66
+ def external_dependencies
67
+ [ 'tilt' ]
68
+ end
56
69
  end
57
70
  end
@@ -0,0 +1,66 @@
1
+ require 'rake-pipeline-web-filters/filter_with_dependencies'
2
+
3
+ module Rake::Pipeline::Web::Filters
4
+ # A filter that uses the Uglify JS compressor to compress
5
+ # JavaScript input files.
6
+ #
7
+ # Requires {http://rubygems.org/gems/uglifier uglifier}.
8
+ #
9
+ # @example
10
+ # !!!ruby
11
+ # Rake::Pipeline.build do
12
+ # input "app/assets", "**/*.js"
13
+ # output "public"
14
+ #
15
+ # # Compile each JS file under the app/assets
16
+ # # directory.
17
+ # filter Rake::Pipeline::Web::Filters::UglifyFilter
18
+ # end
19
+ class UglifyFilter < Rake::Pipeline::Filter
20
+ include Rake::Pipeline::Web::Filters::FilterWithDependencies
21
+
22
+ # @return [Hash] a hash of options to pass to Uglify
23
+ # when compiling.
24
+ attr_reader :options
25
+
26
+ # @param [Hash] options options to pass to Uglify
27
+ # @param [Proc] block a block to use as the Filter's
28
+ # {#output_name_generator}.
29
+ def initialize(options={}, &block)
30
+ block ||= proc { |input|
31
+ if input =~ %r{min.js$}
32
+ input
33
+ else
34
+ input.sub(/\.js$/, '.min.js')
35
+ end
36
+ }
37
+
38
+ super(&block)
39
+ @options = options
40
+ end
41
+
42
+ # Implement the {#generate_output} method required by
43
+ # the {Filter} API. Compiles each input file with Uglify.
44
+ #
45
+ # @param [Array<FileWrapper>] inputs an Array of
46
+ # {FileWrapper} objects representing the inputs to
47
+ # this filter.
48
+ # @param [FileWrapper] output a single {FileWrapper}
49
+ # object representing the output.
50
+ def generate_output(inputs, output)
51
+ inputs.each do |input|
52
+ if input.path =~ %r{min.js$}
53
+ output.write input.read
54
+ else
55
+ output.write Uglifier.compile(input.read, options)
56
+ end
57
+ end
58
+ end
59
+
60
+ private
61
+
62
+ def external_dependencies
63
+ [ 'uglifier' ]
64
+ end
65
+ end
66
+ end
@@ -2,7 +2,7 @@ module Rake
2
2
  class Pipeline
3
3
  module Web
4
4
  module Filters
5
- VERSION = "0.5.0"
5
+ VERSION = "0.7.0"
6
6
  end
7
7
  end
8
8
  end
@@ -0,0 +1,70 @@
1
+ require 'rake-pipeline-web-filters/filter_with_dependencies'
2
+
3
+ module Rake::Pipeline::Web::Filters
4
+ # A filter that compresses CSS input files using
5
+ # the YUI CSS 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 CSS file under the app/assets
16
+ # # directory.
17
+ # filter Rake::Pipeline::Web::Filters::YUICssFilter
18
+ # end
19
+ class YUICssFilter < 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
+ # CSS 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|
32
+ if input =~ %r{min.css$}
33
+ input
34
+ else
35
+ input.sub /\.css$/, '.min.css'
36
+ end
37
+ }
38
+
39
+ super(&block)
40
+ @options = options
41
+ end
42
+
43
+ # Implement the {#generate_output} method required by
44
+ # the {Filter} API. Compresses each input file with
45
+ # the YUI CSS compressor.
46
+ #
47
+ # @param [Array<FileWrapper>] inputs an Array of
48
+ # {FileWrapper} objects representing the inputs to
49
+ # this filter.
50
+ # @param [FileWrapper] output a single {FileWrapper}
51
+ # object representing the output.
52
+ def generate_output(inputs, output)
53
+ compressor = YUI::CssCompressor.new(options)
54
+ inputs.each do |input|
55
+ if input.path !~ /min\.css/
56
+ output.write compressor.compress(input.read)
57
+ else
58
+ output.write input.read
59
+ end
60
+ end
61
+ end
62
+
63
+ private
64
+
65
+ def external_dependencies
66
+ [ 'yui/compressor' ]
67
+ end
68
+ end
69
+ end
70
+
@@ -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
+
@@ -15,10 +15,19 @@ Gem::Specification.new do |gem|
15
15
  gem.require_paths = ["lib"]
16
16
  gem.version = Rake::Pipeline::Web::Filters::VERSION
17
17
 
18
- gem.add_dependency "rake-pipeline"
18
+ gem.add_dependency "rake-pipeline", "~> 0.6"
19
+ gem.add_dependency "rack"
19
20
 
20
21
  gem.add_development_dependency "rspec"
21
22
  gem.add_development_dependency "tilt"
22
23
  gem.add_development_dependency "sass"
23
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"
24
33
  end
@@ -0,0 +1,105 @@
1
+ describe "CacheBusterFilter" do
2
+ MemoryFileWrapper ||= Rake::Pipeline::SpecHelpers::MemoryFileWrapper
3
+ CacheBusterFilter ||= Rake::Pipeline::Web::Filters::CacheBusterFilter
4
+
5
+ let(:content) { "it doesn't matter" }
6
+
7
+ let(:input_file) {
8
+ MemoryFileWrapper.new '/path/to/input', 'file.txt', 'UTF-8', content
9
+ }
10
+
11
+ let(:output_root) {
12
+ '/path/to/output'
13
+ }
14
+
15
+ def setup_filter(filter)
16
+ filter.file_wrapper_class = MemoryFileWrapper
17
+ filter.input_files = [ input_file ]
18
+ filter.output_root = output_root
19
+ filter.rake_application = Rake::Application.new
20
+ filter
21
+ end
22
+
23
+ describe 'DEFAULT_KEY_GENERATOR' do
24
+
25
+ subject { CacheBusterFilter::DEFAULT_KEY_GENERATOR }
26
+
27
+ it "returns the MD5 hash of the input's file name and contents" do
28
+ expected = Digest::MD5.new << input_file.path << content
29
+ subject.call(input_file).should == expected
30
+ end
31
+
32
+ end
33
+
34
+ describe 'with the default cache key strategy' do
35
+
36
+ let(:output_file) {
37
+ key = CacheBusterFilter::DEFAULT_KEY_GENERATOR.call(input_file)
38
+ MemoryFileWrapper.new output_root, "file-#{key}.txt", 'UTF-8'
39
+ }
40
+
41
+ subject { setup_filter CacheBusterFilter.new }
42
+
43
+ it 'outputs to the MD5 hash of the file name and contents' do
44
+ subject.output_files.should == [ output_file ]
45
+ end
46
+
47
+ it 'passes file contents through unchanged' do
48
+ tasks = subject.generate_rake_tasks
49
+ tasks.each(&:invoke)
50
+ file = MemoryFileWrapper.files[ output_file.fullpath ]
51
+ file.body.should == content
52
+ file.encoding.should == 'UTF-8'
53
+ end
54
+
55
+ end
56
+
57
+ describe 'with a custom key strategy' do
58
+
59
+ let(:output_file) {
60
+ MemoryFileWrapper.new output_root, 'file-foo.txt', 'UTF-8'
61
+ }
62
+
63
+ subject do
64
+ setup_filter(CacheBusterFilter.new() { 'foo' })
65
+ end
66
+
67
+ it 'uses the custom key strategy' do
68
+ subject.output_files.should == [ output_file ]
69
+ end
70
+
71
+ end
72
+
73
+ describe 'for an input file with multiple dots' do
74
+ let(:input_file) {
75
+ MemoryFileWrapper.new '/path/to/input', 'my.text.file.txt', 'UTF-8', content
76
+ }
77
+
78
+ let(:output_file) {
79
+ MemoryFileWrapper.new output_root, "my.text.file-foo.txt", 'UTF-8'
80
+ }
81
+
82
+ subject { setup_filter(CacheBusterFilter.new() { 'foo' }) }
83
+
84
+ it 'appends the busting key to the penultimate part' do
85
+ subject.output_files.should == [ output_file ]
86
+ end
87
+ end
88
+
89
+ describe 'for an input file with no dots' do
90
+ let(:input_file) {
91
+ MemoryFileWrapper.new '/path/to/input', 'my_text_file', 'UTF-8', content
92
+ }
93
+
94
+ let(:output_file) {
95
+ MemoryFileWrapper.new output_root, "my_text_file-foo", 'UTF-8'
96
+ }
97
+
98
+ subject { setup_filter(CacheBusterFilter.new() { 'foo' }) }
99
+
100
+ it 'appends the busting key to the end of the filename' do
101
+ subject.output_files.should == [ output_file ]
102
+ end
103
+ end
104
+
105
+ end
@@ -0,0 +1,76 @@
1
+ describe "ChainedFilter" do
2
+ MemoryFileWrapper ||= Rake::Pipeline::SpecHelpers::MemoryFileWrapper
3
+ ChainedFilter ||= Rake::Pipeline::Web::Filters::ChainedFilter
4
+
5
+ input_file1 = MemoryFileWrapper.new("/path", "input.js.strip_asserts.erb", "UTF-8", <<-CONTENT)
6
+ assert("must be true", true);
7
+ Input = {};
8
+ <%= $chained_filter_title %> = {};
9
+ CONTENT
10
+
11
+ input_file2 = MemoryFileWrapper.new("/path", "input.js.erb.strip_asserts", "UTF-8", <<-CONTENT)
12
+ assert("must be true", true);
13
+ Input = {};
14
+ <%= $chained_filter_title %> = {};
15
+ CONTENT
16
+
17
+ EXPECTED_OUTPUT = <<-EXPECTED
18
+
19
+ Input = {};
20
+ Chained = {};
21
+ EXPECTED
22
+
23
+ let(:erb_filter) do
24
+ Class.new(Rake::Pipeline::Filter) do
25
+ def generate_output(inputs, output)
26
+ inputs.each do |input|
27
+ output.write ERB.new(input.read).result
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ let(:strip_asserts_filter) do
34
+ Class.new(Rake::Pipeline::Filter) do
35
+ def generate_output(inputs, output)
36
+ inputs.each do |input|
37
+ output.write input.read.gsub(/^assert.*$/, '')
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ before do
44
+ $chained_filter_title = "Chained"
45
+ end
46
+
47
+ after do
48
+ $chained_filter_title = nil
49
+ end
50
+
51
+ [ input_file1, input_file2 ].each do |file_wrapper|
52
+ it "should run through the filters in order" do
53
+ filter = ChainedFilter.new(
54
+ :types => {
55
+ :erb => erb_filter,
56
+ :strip_asserts => strip_asserts_filter
57
+ }
58
+ )
59
+
60
+ filter.file_wrapper_class = MemoryFileWrapper
61
+ filter.input_files = [ file_wrapper ]
62
+ filter.output_root = "/output"
63
+ filter.rake_application = Rake::Application.new
64
+
65
+ filter.output_files.should == [ MemoryFileWrapper.new("/output", "input.js", "UTF-8") ]
66
+
67
+ tasks = filter.generate_rake_tasks
68
+ tasks.each(&:invoke)
69
+
70
+ file = MemoryFileWrapper.files["/output/input.js"]
71
+ file.body.should == EXPECTED_OUTPUT
72
+ file.encoding.should == "UTF-8"
73
+ end
74
+ end
75
+
76
+ end