middleman-webp 0.2.3 → 0.2.4

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.
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: