middleman-webp 0.2.3 → 0.2.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a0b0affadf5badd85debeee5e4c945f5e18dadb9
4
- data.tar.gz: 161c2a8925c82eeda8f84699bade12bb8532b0b7
3
+ metadata.gz: 15324f77a8223f217cce27a1a8b4a568053550d9
4
+ data.tar.gz: 76e7287091230e06db8f9bbcf1bc426893223741
5
5
  SHA512:
6
- metadata.gz: 674cd611524a0617647a575c9e5646f04754774ed4f2df54cab27333e87588b511f2747b8087a158f036f3bcac675c1ab4edff8cd3b4387df3176bbf9eba61b5
7
- data.tar.gz: 6ec3ddc1d381977d35de9dd352c7ef4c5709f26925ecd925b1150e11d91e5aa861954c8b8fe93a9ddefd75ad03f8dbe5ec7bd4307ba98f64a92e56b8f701beb0
6
+ metadata.gz: e1ba54d576791994a6994935ec93cd593351f530cc302c660e871e44eb4e41a13f41202bbc77f968b6277630b947ddce078ff6ba20c22ebf0e60177ad1b3be15
7
+ data.tar.gz: 9813913a33e7073ab880fa64cfb64f801dfbcb871f7a0c856eb4b984a68b3ea2427f0e952b116639ae922c882df97d6f708a6d54f378fb3f686dff01b5dd8e18
data/CHANGELOG.md ADDED
@@ -0,0 +1,4 @@
1
+ ## 0.2.4
2
+
3
+ - Add ```ignore``` option similar to the one in the [asset_hash extension](http://middlemanapp.com/advanced/improving-cacheability/#uniquely-named-assets) 26fb7972c9f7808a222fb03d0a4e11e60f9148d8
4
+ - Allow using Regexp to match files for custom conversion options 985ea2fa62a2eb4c7b37062cd72f300bada62d11
data/README.md CHANGED
@@ -41,20 +41,39 @@ And activate :webp extension in your config.rb:
41
41
  activate :webp
42
42
  ```
43
43
 
44
+ ### Custom conversion options
45
+
44
46
  Options for conversion are defined using
45
47
  [Ruby's glob syntax](http://www.ruby-doc.org/core-2.1.1/Dir.html#method-c-glob)
46
- for matching image files and hashes containing args supported by
47
- cwebp:
48
+ or [Regexp](http://www.ruby-doc.org/core-2.1.1/Regexp.html) for
49
+ matching image files and hashes containing args supported by cwebp:
48
50
 
49
51
  ``` ruby
50
52
  activate :webp do |webp|
51
53
  webp.conversion_options = {
52
54
  "icons/*.png" => {lossless: true},
53
- "photos/**/*.jpg" => {q: 100}
55
+ "photos/**/*.jpg" => {q: 100},
56
+ /[0-9]/.+gif$/ => {lossy: true}
54
57
  }
55
58
  end
56
59
  ```
57
60
 
61
+ ### Ignoring some of the image files at you site
62
+
63
+ If there are some image files that you don't want to convert to the
64
+ webp alternatives, you could ignore them using ```ignore``` option
65
+ matching those paths.
66
+
67
+ ``` ruby
68
+ activate :webp do |webp|
69
+ webp.ignore = '**/*.gif'
70
+ end
71
+ ```
72
+
73
+ Ignore option accepts one or an array of String globs, Regexps or
74
+ Procs.
75
+
76
+
58
77
  ## Configuring your site to provide WebP alternatives
59
78
 
60
79
  Configure web server to serve WebP images if they are available and
@@ -1,7 +1,7 @@
1
- require "middleman-core"
2
- require "middleman-webp/version"
1
+ require 'middleman-core'
2
+ require 'middleman-webp/version'
3
3
 
4
4
  ::Middleman::Extensions.register(:webp) do
5
- require "middleman-webp/extension"
5
+ require 'middleman-webp/extension'
6
6
  ::Middleman::WebPExtension
7
7
  end
@@ -1,11 +1,11 @@
1
- require "middleman-webp/options"
1
+ require 'middleman-webp/options'
2
2
 
3
3
  module Middleman
4
4
  module WebP
5
-
6
5
  class Converter
6
+ SUFFIX_RE = /(jpe?g|png|tiff?|gif)$/i
7
7
 
8
- def initialize(app, options={}, builder)
8
+ def initialize(app, options = {}, builder)
9
9
  @app = app
10
10
  @options = Middleman::WebP::Options.new(options)
11
11
  @builder = builder
@@ -19,10 +19,10 @@ module Middleman
19
19
 
20
20
  @original_size += src.size
21
21
  @converted_size += dst.size
22
- @builder.say_status :webp, "#{dst.path} (#{change_percentage(src.size,dst.size)} smaller)"
22
+ @builder.say_status :webp, "#{dst.path} "\
23
+ "(#{change_percentage(src.size, dst.size)} smaller)"
23
24
  end
24
- savings = @original_size - @converted_size
25
- @builder.say_status(:webp, "Total conversion savings: #{number_to_human_size(savings)} (#{change_percentage(@original_size, @converted_size)})", :blue)
25
+ print_summary
26
26
  end
27
27
 
28
28
  def convert_images(paths, &after_conversion)
@@ -45,7 +45,7 @@ module Middleman
45
45
  #
46
46
  # file - Filename
47
47
  def tool_for(file)
48
- file.to_s =~ /gif$/i ? "gif2webp" : "cwebp"
48
+ file.to_s =~ /gif$/i ? 'gif2webp' : 'cwebp'
49
49
  end
50
50
 
51
51
  def reject_file(file)
@@ -53,10 +53,24 @@ module Middleman
53
53
  File.unlink(file)
54
54
  end
55
55
 
56
+ def print_summary
57
+ savings = @original_size - @converted_size
58
+ @builder.say_status :webp, 'Total conversion savings: '\
59
+ "#{number_to_human_size(savings)} "\
60
+ "(#{change_percentage(@original_size, @converted_size)})", :blue
61
+ end
62
+
56
63
  # Calculate change percentage of converted file size
57
64
  #
58
65
  # src - File instance of the source
59
66
  # dst - File instance of the destination
67
+ #
68
+ # Examples
69
+ #
70
+ # change_percentage(100, 75)
71
+ # # => '25 %'
72
+ #
73
+ # Returns percentage as string.
60
74
  def change_percentage(src_size, dst_size)
61
75
  return '0 %' if src_size == 0
62
76
 
@@ -64,19 +78,35 @@ module Middleman
64
78
  end
65
79
 
66
80
  def destination_path(src_path)
67
- dst_name = src_path.basename.to_s.gsub(/(jpe?g|png|tiff?|gif)$/, "webp")
81
+ dst_name = src_path.basename.to_s.gsub(SUFFIX_RE, 'webp')
68
82
  src_path.parent.join(dst_name)
69
83
  end
70
84
 
71
85
  def image_files
72
86
  all = ::Middleman::Util.all_files_under(@app.inst.build_dir)
73
- all.select {|p| p.to_s =~ /(jpe?g|png|tiff?|gif)$/i }
87
+ images = all.select { |p| p.to_s =~ SUFFIX_RE }
88
+
89
+ # Reject files matching possible ignore patterns
90
+ @options.ignore.reduce(images) do |arr, matcher|
91
+ arr.select { |path| !matcher.matches? path }
92
+ end
74
93
  end
75
94
 
95
+ # Output file size using most human friendly multiple of byte
96
+ # eg. MiB.
97
+ #
98
+ # n - size in bytes
99
+ #
100
+ # Examples
101
+ #
102
+ # number_to_human_size(12345)
103
+ # # => '12.06 KiB'
104
+ #
105
+ # Returns string containing size and unit.
76
106
  def number_to_human_size(n)
77
107
  return '0 B' if n == 0
78
108
 
79
- units = %w{B KiB MiB GiB TiB PiB}
109
+ units = %w(B KiB MiB GiB TiB PiB)
80
110
  exponent = (Math.log(n) / Math.log(1024)).to_i
81
111
  format("%g #{units[exponent]}",
82
112
  format('%.2f', n.to_f / 1024**exponent))
@@ -1,16 +1,16 @@
1
- require "middleman-core"
2
- require "middleman-webp/converter"
1
+ require 'middleman-core'
2
+ require 'middleman-webp/converter'
3
3
 
4
4
  module Middleman
5
5
  class WebPExtension < Extension
6
- option :conversion_options, {}, "Custom conversion options for cwebp/gif2webp"
7
-
8
- def initialize(app, options_hash={}, &block)
6
+ option(:conversion_options, {},
7
+ 'Custom conversion options for cwebp/gif2webp')
8
+ option(:ignore, [], 'Ignores files with matching paths')
9
+ def initialize(app, options_hash = {}, &block)
9
10
  super
10
11
 
11
- args = options.conversion_options
12
12
  app.after_build do |builder|
13
- Middleman::WebP::Converter.new(app, args, builder).convert
13
+ Middleman::WebP::Converter.new(app, options_hash, builder).convert
14
14
  end
15
15
  end
16
16
  end
@@ -1,11 +1,20 @@
1
+ require 'middleman-webp/pathname_matcher'
2
+
1
3
  module Middleman
2
4
  module WebP
3
-
4
5
  class Options
6
+ attr_reader :ignore
7
+
8
+ def initialize(options = {})
9
+ @ignore = options[:ignore] || []
10
+ @ignore = [*@ignore].map do |pattern|
11
+ Middleman::WebP::PathnameMatcher.new(pattern)
12
+ end
5
13
 
6
- def initialize(options={})
7
- @options = options.inject(Hash.new("")) do |h,(k,v)|
8
- h[k] = to_args(v); h
14
+ @conversion = options[:conversion_options] || {}
15
+ @conversion = @conversion.reduce(Hash.new('')) do |h, (k, v)|
16
+ h[Middleman::WebP::PathnameMatcher.new(k)] = to_args(v)
17
+ h
9
18
  end
10
19
  end
11
20
 
@@ -15,26 +24,24 @@ module Middleman
15
24
  # glob pattern matches file path and uses the one with longest
16
25
  # glob, because it's assumed to be the most precise one.
17
26
  def for(file)
18
- matching = @options.select {|g,o| file.fnmatch?(g)}
27
+ matching = @conversion.select { |m, o| m.matches? file }
19
28
 
20
- return "" if matching.empty?
29
+ return '' if matching.empty?
21
30
 
22
- matching.sort {|(ga,oa),(gb,ob)| gb.size <=> ga.size}[0][1]
31
+ matching.sort { |(ga, oa), (gb, ob)| gb.size <=> ga.size }[0][1]
23
32
  end
24
33
 
25
34
  private
26
35
 
27
36
  def to_args(options)
28
- options.map do |k,v|
37
+ options.map do |k, v|
29
38
  if v == true
30
39
  "-#{k}"
31
40
  elsif v != false
32
41
  "-#{k} #{v}"
33
42
  end
34
- end.join(" ").gsub(/ +/, " ")
43
+ end.join(' ').gsub(/ +/, ' ')
35
44
  end
36
-
37
45
  end
38
-
39
46
  end
40
47
  end
@@ -0,0 +1,47 @@
1
+ module Middleman
2
+ module WebP
3
+ class PathnameMatcher
4
+ # Initializes matcher with given pattern.
5
+ #
6
+ # pattern - Pattern to match pathnames against to. May be
7
+ # string, glob, prog or regex.
8
+ def initialize(pattern = '**/*')
9
+ @pattern = pattern
10
+ end
11
+
12
+ # Checks given file against pattern.
13
+ #
14
+ # file - File, Pathname or String
15
+ def matches?(path)
16
+ return false if path.nil?
17
+
18
+ send match_method, path
19
+ end
20
+
21
+ private
22
+
23
+ def match_method
24
+ @match_method ||=
25
+ if @pattern.respond_to? :call
26
+ :matches_proc?
27
+ elsif @pattern.class == Regexp
28
+ :matches_re?
29
+ else
30
+ :matches_glob?
31
+ end
32
+ end
33
+
34
+ def matches_glob?(path)
35
+ Pathname.new(path).fnmatch?(@pattern)
36
+ end
37
+
38
+ def matches_re?(path)
39
+ !@pattern.match(Pathname.new(path).to_s).nil?
40
+ end
41
+
42
+ def matches_proc?(path)
43
+ @pattern.call(Pathname.new(path).to_s)
44
+ end
45
+ end
46
+ end
47
+ end
@@ -1,5 +1,5 @@
1
1
  module Middleman
2
2
  module Webp
3
- VERSION = "0.2.3"
3
+ VERSION = '0.2.4'
4
4
  end
5
5
  end
@@ -1 +1 @@
1
- require "middleman-webp"
1
+ require 'middleman-webp'
File without changes
File without changes
File without changes
File without changes
@@ -1,31 +1,40 @@
1
- require "spec_helper"
2
- require "pathname"
3
- require_relative "../../lib/middleman-webp/converter"
1
+ require 'spec_helper'
2
+ require 'pathname'
3
+ require 'middleman-core'
4
+ require_relative '../../lib/middleman-webp/converter'
4
5
 
5
6
  describe Middleman::WebP::Converter do
6
7
  before do
7
- @converter = Middleman::WebP::Converter.new(nil, {}, nil)
8
+ @app_mock = stub(inst: stub(build_dir: 'spec/fixtures'))
9
+ @converter = Middleman::WebP::Converter.new(@app_mock, {}, nil)
8
10
  end
9
11
 
10
- describe "#change_percentage" do
11
- it "returns how many percents smaller destination file is" do
12
- @converter.change_percentage(10000, 8746).must_equal "12.54 %"
12
+ describe '#destination_path' do
13
+ it 'returns file name with same basename and webp suffix' do
14
+ d = @converter.destination_path(Pathname.new('build/images/sample.jpg'))
15
+ d.to_s.must_equal 'build/images/sample.webp'
16
+ end
17
+ end
18
+
19
+ describe '#change_percentage' do
20
+ it 'returns how many percents smaller destination file is' do
21
+ @converter.change_percentage(10_000, 8746).must_equal '12.54 %'
13
22
  end
14
23
 
15
- it "omits zeroes in the end of decimal part" do
16
- @converter.change_percentage(100, 76).must_equal "24 %"
24
+ it 'omits zeroes in the end of decimal part' do
25
+ @converter.change_percentage(100, 76).must_equal '24 %'
17
26
  end
18
27
 
19
- it "returns 0% when original and new size are both 0" do
20
- @converter.change_percentage(0, 0).must_equal "0 %"
28
+ it 'returns 0% when original and new size are both 0' do
29
+ @converter.change_percentage(0, 0).must_equal '0 %'
21
30
  end
22
31
  end
23
32
 
24
- describe "#number_to_human_size" do
25
- it "uses human readable unit" do
26
- @converter.number_to_human_size(100).must_equal "100 B"
27
- @converter.number_to_human_size(1234).must_equal "1.21 KiB"
28
- @converter.number_to_human_size(2_634_234).must_equal "2.51 MiB"
33
+ describe '#number_to_human_size' do
34
+ it 'uses human readable unit' do
35
+ @converter.number_to_human_size(100).must_equal '100 B'
36
+ @converter.number_to_human_size(1234).must_equal '1.21 KiB'
37
+ @converter.number_to_human_size(2_634_234).must_equal '2.51 MiB'
29
38
  end
30
39
 
31
40
  it 'handles zero size properly' do
@@ -33,19 +42,43 @@ describe Middleman::WebP::Converter do
33
42
  end
34
43
  end
35
44
 
36
- describe "#tool_for" do
37
- it "uses gif2webp for gif files" do
38
- path = Pathname.new("/some/path/image.gif")
39
- @converter.tool_for(path).must_equal "gif2webp"
45
+ describe '#tool_for' do
46
+ it 'uses gif2webp for gif files' do
47
+ path = Pathname.new('/some/path/image.gif')
48
+ @converter.tool_for(path).must_equal 'gif2webp'
49
+ end
50
+
51
+ it 'uses cwebp for jpeg, png and tiff files' do
52
+ path = Pathname.new('/some/path/image.jpg')
53
+ @converter.tool_for(path).must_equal 'cwebp'
54
+ path = Pathname.new('/some/path/image.png')
55
+ @converter.tool_for(path).must_equal 'cwebp'
56
+ path = Pathname.new('/some/path/image.tiff')
57
+ @converter.tool_for(path).must_equal 'cwebp'
58
+ end
59
+ end
60
+
61
+ describe '#image_files' do
62
+ it 'includes all image files in Middleman build dir' do
63
+ @converter.image_files.size.must_equal 3
64
+ end
65
+
66
+ it 'won\'t include ignored files' do
67
+ @converter = Middleman::WebP::Converter.new(@app_mock, {
68
+ ignore: [/jpg$/, '**/*.gif']
69
+ }, nil)
70
+
71
+ files_to_include = [Pathname.new('spec/fixtures/empty.png')]
72
+ @converter.image_files.must_equal files_to_include
40
73
  end
41
74
 
42
- it "uses cwebp for jpeg, png and tiff files" do
43
- path = Pathname.new("/some/path/image.jpg")
44
- @converter.tool_for(path).must_equal "cwebp"
45
- path = Pathname.new("/some/path/image.png")
46
- @converter.tool_for(path).must_equal "cwebp"
47
- path = Pathname.new("/some/path/image.tiff")
48
- @converter.tool_for(path).must_equal "cwebp"
75
+ it 'won\'t include files rejected by given proc' do
76
+ options = {
77
+ ignore: ->(path) { path.end_with? 'jpg' }
78
+ }
79
+ @converter = Middleman::WebP::Converter.new(@app_mock, options, nil)
80
+
81
+ @converter.image_files.size.must_equal 2
49
82
  end
50
83
  end
51
84
  end
@@ -1,23 +1,46 @@
1
- require "spec_helper"
2
- require "pathname"
3
- require_relative "../../lib/middleman-webp/options"
1
+ require 'spec_helper'
2
+ require 'pathname'
3
+ require_relative '../../lib/middleman-webp/options'
4
4
 
5
5
  describe Middleman::WebP::Options do
6
- describe "#for" do
7
- it "returns cwebp args when given file matches option file pattern" do
8
- path = Pathname.new("test_image.jpg")
9
- options = Middleman::WebP::Options.new("*.jpg" => {lossless: true, q: 85})
6
+ describe '#for' do
7
+ it 'returns cwebp args when given file matches option file pattern glob' do
8
+ path = Pathname.new('test_image.jpg')
9
+ options_hash = {
10
+ conversion_options: {
11
+ '*.jpg' => {
12
+ lossless: true,
13
+ q: 85
14
+ }
15
+ }
16
+ }
17
+ options = Middleman::WebP::Options.new options_hash
10
18
 
11
19
  args = options.for(path)
12
20
  args.must_match(/^(-q 85|-lossless) (-q 85|-lossless)$/)
13
21
  end
14
22
 
15
- it "returns empty string when no options are defined" do
16
- path = Pathname.new("test_image.jpg")
23
+ it 'returns empty string when no options are defined' do
24
+ path = Pathname.new('test_image.jpg')
17
25
  options = Middleman::WebP::Options.new
18
26
 
19
27
  args = options.for(path)
20
28
  args.must_be_empty
21
29
  end
30
+
31
+ it 'returns cwebp args when given file matches option pattern regexp' do
32
+ path = Pathname.new('test_image.jpg')
33
+ options_hash = {
34
+ conversion_options: {
35
+ /jpg$/ => {
36
+ q: 85
37
+ }
38
+ }
39
+ }
40
+ options = Middleman::WebP::Options.new options_hash
41
+
42
+ args = options.for(path)
43
+ args.must_match(/^-q 85$/)
44
+ end
22
45
  end
23
46
  end
@@ -0,0 +1,60 @@
1
+ require 'spec_helper'
2
+ require_relative '../../lib/middleman-webp/pathname_matcher'
3
+
4
+ describe Middleman::WebP::PathnameMatcher do
5
+
6
+ describe '#matches?' do
7
+ it 'returns true when given file matches pattern' do
8
+ patterns = ['**/*.jpg', /jpg$/, ->(path) { path.end_with?('jpg') }]
9
+ files = [
10
+ 'images/sample.jpg',
11
+ Pathname.new('images/another.jpg'),
12
+ File.new('spec/fixtures/empty.jpg')
13
+ ]
14
+
15
+ patterns.each do |p|
16
+ matcher = Middleman::WebP::PathnameMatcher.new(p)
17
+ files.each do |f|
18
+ matcher.matches?(f).must_equal true, "Pattern: #{p.inspect}, "\
19
+ "file: #{f.inspect}"
20
+ end
21
+ end
22
+ end
23
+
24
+ it 'returns false when given file won\'t match pattern' do
25
+ patterns = ['**/*.jpg', /jpg$/, ->(path) { path.end_with?('jpg') }]
26
+ files = [
27
+ 'images/sample.png',
28
+ Pathname.new('images/another.png'),
29
+ File.new('spec/fixtures/empty.png')
30
+ ]
31
+
32
+ patterns.each do |p|
33
+ matcher = Middleman::WebP::PathnameMatcher.new(p)
34
+ files.each do |f|
35
+ matcher.matches?(f).must_equal false, "Pattern: #{p.inspect}, "\
36
+ "file: #{f.inspect}"
37
+ end
38
+ end
39
+ end
40
+
41
+ it 'defaults to pattern \'**/*\' and matches all when pattern is nil' do
42
+ paths = [
43
+ 'something/anything.foo',
44
+ Pathname.new('images/another.png'),
45
+ 'a/b/c/d/e/f/g'
46
+ ]
47
+
48
+ matcher = Middleman::WebP::PathnameMatcher.new
49
+ paths.each do |p|
50
+ matcher.matches?(p).must_equal true
51
+ end
52
+ end
53
+
54
+ it 'handles nil path gracefully and returns false' do
55
+ Middleman::WebP::PathnameMatcher.new('*.jpg').matches? nil
56
+ end
57
+
58
+ end
59
+
60
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: middleman-webp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Juhamatti Niemelä
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-04-09 00:00:00.000000000 Z
11
+ date: 2014-04-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: middleman-core
@@ -88,6 +88,7 @@ extensions: []
88
88
  extra_rdoc_files: []
89
89
  files:
90
90
  - .gitignore
91
+ - CHANGELOG.md
91
92
  - Gemfile
92
93
  - LICENSE.txt
93
94
  - README.md
@@ -96,12 +97,18 @@ files:
96
97
  - lib/middleman-webp/converter.rb
97
98
  - lib/middleman-webp/extension.rb
98
99
  - lib/middleman-webp/options.rb
100
+ - lib/middleman-webp/pathname_matcher.rb
99
101
  - lib/middleman-webp/version.rb
100
102
  - lib/middleman_extension.rb
101
103
  - middleman-webp.gemspec
104
+ - spec/fixtures/directory/dummy.html
105
+ - spec/fixtures/directory/empty.gif
106
+ - spec/fixtures/empty.jpg
107
+ - spec/fixtures/empty.png
102
108
  - spec/spec_helper.rb
103
109
  - spec/unit/converter_spec.rb
104
110
  - spec/unit/options_spec.rb
111
+ - spec/unit/pathname_matcher_spec.rb
105
112
  homepage: http://github.com/iiska/middleman-webp
106
113
  licenses:
107
114
  - MIT
@@ -127,7 +134,12 @@ signing_key:
127
134
  specification_version: 4
128
135
  summary: WebP image conversion for Middleman
129
136
  test_files:
137
+ - spec/fixtures/directory/dummy.html
138
+ - spec/fixtures/directory/empty.gif
139
+ - spec/fixtures/empty.jpg
140
+ - spec/fixtures/empty.png
130
141
  - spec/spec_helper.rb
131
142
  - spec/unit/converter_spec.rb
132
143
  - spec/unit/options_spec.rb
144
+ - spec/unit/pathname_matcher_spec.rb
133
145
  has_rdoc: