image_optim 0.26.2 → 0.26.3

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