image_optim 0.26.2 → 0.26.3

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
  SHA256:
3
- metadata.gz: 07b7d1d96cc0bc6f16e0a2b6a512c4ad06015eea55359dcc9c32c2b19714c786
4
- data.tar.gz: be1136efd362c8f13f8a286728fc3c49f62af439cdea90d60c68e4093c1be72a
3
+ metadata.gz: ec91f27b4e53d23a3516908c5714011fb47bbc251e95ef9952acc62948d123af
4
+ data.tar.gz: 8b5a675e29709e03bf5ca0567ae742f8d4d7f3d7e90f89ac5ef8c1935c594555
5
5
  SHA512:
6
- metadata.gz: 82ac7498fa95948f7e6a6380695be2da56436245d4fd595d704b4a8e78d59bb4c483690e8a8ac992ea5bf34fc0f37180ea1e103d76c8ac523975bd8a7690b1e5
7
- data.tar.gz: cb3d17d491ec5accbf9d94caac4725b849e5e42f212b464b1a08b1f0545f0844193154c8c2c141377193a5234e45b70a207fb4a642f2625e0668e08e8821f046
6
+ metadata.gz: 847ee0b721a90d761ccfa4948c979e532dfd53d52f2e4c82e9df1e3301bcaba6a4217f98ae5cd5be2bcd7407339614710bd95ef381e9d422e778a4674ddeb81b
7
+ data.tar.gz: 7f5b009a16df3c671ebc9a8c934cb499fd7ac47a0a464d33130ab1197ffa4b9c1f2767467226124dbd78281bcffd7864c058d8f3ff9fe7b58addfd3b6411ace7
@@ -30,6 +30,9 @@ Layout/IndentHash:
30
30
  Layout/IndentHeredoc:
31
31
  Enabled: false
32
32
 
33
+ Layout/RescueEnsureAlignment:
34
+ Enabled: false
35
+
33
36
  Layout/SpaceBeforeBlockBraces:
34
37
  EnforcedStyle: no_space
35
38
  EnforcedStyleForEmptyBraces: no_space
@@ -51,7 +54,7 @@ Lint/UnneededSplatExpansion:
51
54
  Enabled: false
52
55
 
53
56
  Metrics/AbcSize:
54
- Max: 30
57
+ Max: 33
55
58
 
56
59
  Metrics/BlockLength:
57
60
  Exclude:
@@ -63,7 +66,10 @@ Metrics/ClassLength:
63
66
  Max: 150
64
67
 
65
68
  Metrics/CyclomaticComplexity:
66
- Max: 10
69
+ Max: 11
70
+
71
+ Metrics/LineLength:
72
+ Max: 120
67
73
 
68
74
  Metrics/MethodLength:
69
75
  Max: 25
@@ -2,6 +2,10 @@
2
2
 
3
3
  ## unreleased
4
4
 
5
+ ## v0.26.3 (2018-10-13)
6
+
7
+ * Handle `vnone` version of `advpng` that was erroneously produced for `ubuntu` and `homebrew` [#165](https://github.com/toy/image_optim/issues/165) [@toy](https://github.com/toy)
8
+
5
9
  ## v0.26.2 (2018-08-15)
6
10
 
7
11
  * Ignore segmentation fault for `pngout` <= `20150920` [#158](https://github.com/toy/image_optim/issues/158) [@toy](https://github.com/toy)
@@ -3,7 +3,7 @@
3
3
  [![AppVeyor Status](https://img.shields.io/appveyor/ci/toy/image-optim/master.svg?style=flat&label=windows)](https://ci.appveyor.com/project/toy/image-optim)
4
4
  [![Code Climate](https://img.shields.io/codeclimate/maintainability/toy/image_optim.svg?style=flat)](https://codeclimate.com/github/toy/image_optim)
5
5
  [![Code Climate Coverage](https://img.shields.io/codeclimate/c/toy/image_optim.svg?style=flat)](https://codeclimate.com/github/toy/image_optim)
6
- [![Dependency Status](https://img.shields.io/gemnasium/toy/image_optim.svg?style=flat)](https://gemnasium.com/toy/image_optim)
6
+ [![Depfu](https://badges.depfu.com/badges/221b4832fa96f613aa5401f7cb4030ac/overview.svg)](https://depfu.com/github/toy/image_optim)
7
7
  [![Inch CI](https://inch-ci.org/github/toy/image_optim.svg?branch=master&style=flat)](https://inch-ci.org/github/toy/image_optim)
8
8
 
9
9
  # image_optim
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = 'image_optim'
5
- s.version = '0.26.2'
5
+ s.version = '0.26.3'
6
6
  s.summary = %q{Command line tool and ruby interface to optimize (lossless compress, optionally lossy) jpeg, png, gif and svg images using external utilities (advpng, gifsicle, jhead, jpeg-recompress, jpegoptim, jpegrescan, jpegtran, optipng, pngcrush, pngout, pngquant, svgo)}
7
7
  s.homepage = "http://github.com/toy/#{s.name}"
8
8
  s.authors = ['Ivan Kuchin']
@@ -36,6 +36,6 @@ EOF
36
36
  s.add_development_dependency 'image_optim_pack', '~> 0.2', '>= 0.2.2'
37
37
  s.add_development_dependency 'rspec', '~> 3.0'
38
38
  if RUBY_VERSION >= '2.2'
39
- s.add_development_dependency 'rubocop', '~> 0.58'
39
+ s.add_development_dependency 'rubocop', '~> 0.59'
40
40
  end
41
41
  end
@@ -118,6 +118,7 @@ class ImageOptim
118
118
  end
119
119
 
120
120
  return unless optimized
121
+
121
122
  OptimizedPath.new(optimized, original)
122
123
  end
123
124
 
@@ -126,6 +127,7 @@ class ImageOptim
126
127
  def optimize_image!(original)
127
128
  original = Path.convert(original)
128
129
  return unless (result = optimize_image(original))
130
+
129
131
  result.replace(original)
130
132
  OptimizedPath.new(original, result.original_size)
131
133
  end
@@ -134,6 +136,7 @@ class ImageOptim
134
136
  def optimize_image_data(original_data)
135
137
  format = ImageMeta.format_for_data(original_data)
136
138
  return unless format
139
+
137
140
  Path.temp_file %W[image_optim .#{format}] do |temp|
138
141
  temp.binmode
139
142
  temp.write(original_data)
@@ -97,6 +97,7 @@ class ImageOptim
97
97
  # Double-checked locking
98
98
  def resolving(name)
99
99
  return if @bins.include?(name)
100
+
100
101
  @lock.synchronize do
101
102
  yield unless @bins.include?(name)
102
103
  end
@@ -108,11 +109,13 @@ class ImageOptim
108
109
  env_name = "#{name}_bin".upcase
109
110
  path = ENV[env_name]
110
111
  return unless path
112
+
111
113
  path = File.expand_path(path)
112
114
  desc = "`#{path}` specified in #{env_name}"
113
115
  fail "#{desc} doesn\'t exist" unless File.exist?(path)
114
116
  fail "#{desc} is not a file" unless File.file?(path)
115
117
  fail "#{desc} is not executable" unless File.executable?(path)
118
+
116
119
  if @image_optim.verbose
117
120
  $stderr << "Custom path for #{name} specified in #{env_name}: #{path}\n"
118
121
  end
@@ -23,6 +23,7 @@ class ImageOptim
23
23
 
24
24
  def digest
25
25
  return @digest if defined?(@digest)
26
+
26
27
  @digest = File.exist?(@path) && Digest::SHA1.file(@path).hexdigest
27
28
  end
28
29
 
@@ -32,20 +33,34 @@ class ImageOptim
32
33
 
33
34
  is = ComparableCondition.is
34
35
 
35
- FAIL_CHECKS = [
36
- [:pngcrush, is.between?('1.7.60', '1.7.65'), 'is known to produce '\
37
- 'broken pngs'],
38
- [:pngcrush, is == '1.7.80', 'loses one color in indexed images'],
39
- [:pngquant, is < '2.0', 'is not supported'],
40
- ].freeze
41
-
42
- WARN_CHECKS = [
43
- [:advpng, is < '1.17', 'does not use zopfli'],
44
- [:gifsicle, is < '1.85', 'does not support removing extension blocks'],
45
- [:pngcrush, is < '1.7.38', 'does not have blacken flag'],
46
- [:pngquant, is < '2.1', 'may be lossy even with quality `100-`'],
47
- [:optipng, is < '0.7', 'does not support -strip option'],
48
- ].freeze
36
+ FAIL_CHECKS = {
37
+ :pngcrush => [
38
+ [is.between?('1.7.60', '1.7.65'), 'is known to produce broken pngs'],
39
+ [is == '1.7.80', 'loses one color in indexed images'],
40
+ ],
41
+ :pngquant => [
42
+ [is < '2.0', 'is not supported'],
43
+ ],
44
+ }.freeze
45
+
46
+ WARN_CHECKS = {
47
+ :advpng => [
48
+ [is == 'none', 'is of unknown version'],
49
+ [is < '1.17', 'does not use zopfli'],
50
+ ],
51
+ :gifsicle => [
52
+ [is < '1.85', 'does not support removing extension blocks'],
53
+ ],
54
+ :pngcrush => [
55
+ [is < '1.7.38', 'does not have blacken flag'],
56
+ ],
57
+ :pngquant => [
58
+ [is < '2.1', 'may be lossy even with quality `100-`'],
59
+ ],
60
+ :optipng => [
61
+ [is < '0.7', 'does not support -strip option'],
62
+ ],
63
+ }.freeze
49
64
 
50
65
  # Fail if version will not work properly
51
66
  def check_fail!
@@ -53,9 +68,11 @@ class ImageOptim
53
68
  fail UnknownVersion, "could not get version of #{name} at #{path}"
54
69
  end
55
70
 
56
- FAIL_CHECKS.each do |bin_name, matcher, message|
57
- next unless bin_name == name
71
+ return unless FAIL_CHECKS[name]
72
+
73
+ FAIL_CHECKS[name].each do |matcher, message|
58
74
  next unless matcher.match(version)
75
+
59
76
  fail BadVersion, "#{self} (#{matcher}) #{message}"
60
77
  end
61
78
  end
@@ -64,10 +81,14 @@ class ImageOptim
64
81
  def check!
65
82
  check_fail!
66
83
 
67
- WARN_CHECKS.each do |bin_name, matcher, message|
68
- next unless bin_name == name
84
+ return unless WARN_CHECKS[name]
85
+
86
+ WARN_CHECKS[name].each do |matcher, message|
69
87
  next unless matcher.match(version)
88
+
70
89
  warn "WARN: #{self} (#{matcher}) #{message}"
90
+
91
+ break
71
92
  end
72
93
  end
73
94
 
@@ -82,7 +103,9 @@ class ImageOptim
82
103
  # Getting version of bin, will fail for an unknown name
83
104
  def version_string
84
105
  case name
85
- when :advpng, :gifsicle, :jpegoptim, :optipng
106
+ when :advpng
107
+ capture("#{escaped_path} --version 2> #{Path::NULL}")[/\bv(\d+(\.\d+)+|none)/, 1]
108
+ when :gifsicle, :jpegoptim, :optipng
86
109
  capture("#{escaped_path} --version 2> #{Path::NULL}")[/\d+(\.\d+)+/]
87
110
  when :svgo, :pngquant
88
111
  capture("#{escaped_path} --version 2>&1")[/\d+(\.\d+)+/]
@@ -7,6 +7,7 @@ class ImageOptim
7
7
  class Cache
8
8
  def initialize(image_optim, workers_by_format)
9
9
  return unless image_optim.cache_dir
10
+
10
11
  @cache_dir = FSPath.new(image_optim.cache_dir)
11
12
  @cache_worker_digests = image_optim.cache_worker_digests
12
13
  @options_by_format = Hash[workers_by_format.map do |format, workers|
@@ -32,10 +32,12 @@ class ImageOptim
32
32
  return {}
33
33
  end
34
34
  return {} unless File.size?(full_path)
35
+
35
36
  config = YAML.load_file(full_path)
36
37
  unless config.is_a?(Hash)
37
38
  fail "expected hash, got #{config.inspect}"
38
39
  end
40
+
39
41
  HashHelpers.deep_symbolise_keys(config)
40
42
  rescue => e
41
43
  warn "exception when reading #{full_path}: #{e}"
@@ -77,6 +79,7 @@ class ImageOptim
77
79
  def assert_no_unused_options!
78
80
  unknown_options = @options.reject{ |key, _value| @used.include?(key) }
79
81
  return if unknown_options.empty?
82
+
80
83
  fail ConfigurationError, "unknown options #{unknown_options.inspect}"
81
84
  end
82
85
 
@@ -131,6 +134,7 @@ class ImageOptim
131
134
  true
132
135
  rescue LoadError => e
133
136
  raise "Cannot load image_optim_pack: #{e}" if pack
137
+
134
138
  false
135
139
  end
136
140
 
@@ -39,6 +39,7 @@ class ImageOptim
39
39
  @dst ||= @original.temp_path
40
40
 
41
41
  return unless yield @src, @dst
42
+
42
43
  @result = @dst
43
44
  if @src == @original
44
45
  @src, @dst = @dst, nil
@@ -50,6 +51,7 @@ class ImageOptim
50
51
  # Remove extra temp files
51
52
  def cleanup
52
53
  return unless @dst
54
+
53
55
  @dst.unlink
54
56
  @dst = nil
55
57
  end
@@ -104,6 +104,7 @@ class ImageOptim
104
104
  if File.file?(path)
105
105
  next if exclude_file?(dir, path)
106
106
  next unless @image_optim.optimizable?(path)
107
+
107
108
  to_optimize << path
108
109
  elsif File.directory?(path)
109
110
  Find.prune if dir != path && exclude_dir?(dir, path)
@@ -185,6 +185,7 @@ ImageOptim::Runner::OptionParser::DEFINE = proc do |op, options|
185
185
 
186
186
  ImageOptim::Worker.klasses.each_with_index do |klass, i|
187
187
  next if klass.option_definitions.empty?
188
+
188
189
  op.separator nil unless i.zero?
189
190
 
190
191
  bin = klass.bin_sym
@@ -23,6 +23,7 @@ class ImageOptim
23
23
  unless image_optim.is_a?(ImageOptim)
24
24
  fail ArgumentError, 'first parameter should be an ImageOptim instance'
25
25
  end
26
+
26
27
  @image_optim = image_optim
27
28
  parse_options(options)
28
29
  assert_no_unknown_options!(options)
@@ -49,6 +50,7 @@ class ImageOptim
49
50
  unless format_from_name
50
51
  fail "#{self.class}: can't guess applicable format from worker name"
51
52
  end
53
+
52
54
  [format_from_name.to_sym]
53
55
  end
54
56
 
@@ -68,6 +70,7 @@ class ImageOptim
68
70
  @image_optim.resolve_bin!(bin)
69
71
  end
70
72
  return if errors.empty?
73
+
71
74
  fail BinResolver::Error, wrap_resolver_error_message(errors.join(', '))
72
75
  end
73
76
 
@@ -98,6 +101,7 @@ class ImageOptim
98
101
  known_keys = self.class.option_definitions.map(&:name)
99
102
  unknown_options = options.reject{ |key, _value| known_keys.include?(key) }
100
103
  return if unknown_options.empty?
104
+
101
105
  fail ConfigurationError, "unknown options #{unknown_options.inspect} "\
102
106
  "for #{self}"
103
107
  end
@@ -83,6 +83,7 @@ class ImageOptim
83
83
  klasses.map do |klass|
84
84
  options = options_proc[klass]
85
85
  next if options[:disable]
86
+
86
87
  if !options.key?(:allow_lossy) && klass.method_defined?(:allow_lossy)
87
88
  options[:allow_lossy] = image_optim.allow_lossy
88
89
  end
@@ -25,6 +25,7 @@ class ImageOptim
25
25
 
26
26
  def optimize(src, dst)
27
27
  return false unless oriented?(src)
28
+
28
29
  src.copy(dst)
29
30
  args = %W[
30
31
  -autorot
@@ -35,6 +35,7 @@ class ImageOptim
35
35
  rescue SignalException => e
36
36
  raise unless Signal.list.key(e.signo) == 'SEGV'
37
37
  raise unless resolve_bin!(:pngout).version <= '20150920'
38
+
38
39
  warn "pngout caused Segmentation fault for #{src}"
39
40
  end
40
41
  end
@@ -118,8 +118,10 @@ class Analyser
118
118
  def get!(key, etag)
119
119
  raw = DB[Marshal.dump(key)]
120
120
  return unless raw
121
+
121
122
  entry = Marshal.load(raw)
122
123
  return unless entry[1] == etag
124
+
123
125
  entry[0]
124
126
  end
125
127
 
@@ -175,6 +177,7 @@ class Analyser
175
177
 
176
178
  def options_string(options)
177
179
  return '' if options.empty?
180
+
178
181
  "(#{options.sort.map{ |k, v| "#{k}:#{v.inspect}" }.join(', ')})"
179
182
  end
180
183
  end
@@ -284,6 +287,7 @@ class Analyser
284
287
  required_workers = workers.select(&:required)
285
288
  with_progress(workers, last_result) do |worker|
286
289
  next if required_workers.any?{ |w| w.run_order < worker.run_order }
290
+
287
291
  worker_result, result_image = run_worker(src, worker)
288
292
 
289
293
  steps = (last_result ? last_result.steps : []) + [worker_result]
@@ -329,6 +333,7 @@ class Analyser
329
333
  unless $CHILD_STATUS.success?
330
334
  fail "failed comparison of #{@path} with #{other}"
331
335
  end
336
+
332
337
  nrmse
333
338
  end
334
339
  end
@@ -482,6 +487,7 @@ class Analyser
482
487
  ImageOptim::Worker.klasses.each do |klass|
483
488
  worker_config = config.delete(klass.bin_sym)
484
489
  next if worker_config == false
490
+
485
491
  worker_config ||= {}
486
492
 
487
493
  option_variants = worker_config.delete(:variants) || [{}]
@@ -278,9 +278,9 @@ describe ImageOptim::BinResolver do
278
278
  bin = Bin.new(:advpng, '/bin/advpng')
279
279
 
280
280
  expect(Bin).to receive(:new).and_return(bin)
281
- allow(bin).to receive(:version).and_return(SimpleVersion.new('1.15'))
281
+ allow(bin).to receive(:version).and_return(SimpleVersion.new('none'))
282
282
 
283
- expect(bin).to receive(:warn).once.with(match(/does not use zopfli/))
283
+ expect(bin).to receive(:warn).once.with(match(/is of unknown version/))
284
284
 
285
285
  5.times do
286
286
  resolver.resolve!(:pngcrush)
@@ -53,6 +53,7 @@ def mepp(image_a, image_b)
53
53
  unless [0, 1].include?($CHILD_STATUS.exitstatus)
54
54
  fail "compare #{image_a} with #{image_b} failed with `#{output}`"
55
55
  end
56
+
56
57
  num_r = '\d+(?:\.\d+(?:[eE][-+]?\d+)?)?'
57
58
  output[/\((#{num_r}), #{num_r}\)/, 1].to_f
58
59
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: image_optim
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.26.2
4
+ version: 0.26.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ivan Kuchin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-08-15 00:00:00.000000000 Z
11
+ date: 2018-10-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fspath
@@ -138,14 +138,14 @@ dependencies:
138
138
  requirements:
139
139
  - - "~>"
140
140
  - !ruby/object:Gem::Version
141
- version: '0.58'
141
+ version: '0.59'
142
142
  type: :development
143
143
  prerelease: false
144
144
  version_requirements: !ruby/object:Gem::Requirement
145
145
  requirements:
146
146
  - - "~>"
147
147
  - !ruby/object:Gem::Version
148
- version: '0.58'
148
+ version: '0.59'
149
149
  description:
150
150
  email:
151
151
  executables:
@@ -263,7 +263,7 @@ licenses:
263
263
  metadata:
264
264
  bug_tracker_uri: https://github.com/toy/image_optim/issues
265
265
  changelog_uri: https://github.com/toy/image_optim/CHANGELOG.markdown
266
- documentation_uri: https://www.rubydoc.info/gems/image_optim/0.26.2
266
+ documentation_uri: https://www.rubydoc.info/gems/image_optim/0.26.3
267
267
  source_code_uri: https://github.com/toy/image_optim
268
268
  post_install_message: |
269
269
  Rails image assets optimization is extracted into image_optim_rails gem