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 +4 -4
- data/.rubocop.yml +8 -2
- data/CHANGELOG.markdown +4 -0
- data/README.markdown +1 -1
- data/image_optim.gemspec +2 -2
- data/lib/image_optim.rb +3 -0
- data/lib/image_optim/bin_resolver.rb +3 -0
- data/lib/image_optim/bin_resolver/bin.rb +42 -19
- data/lib/image_optim/cache.rb +1 -0
- data/lib/image_optim/config.rb +4 -0
- data/lib/image_optim/handler.rb +2 -0
- data/lib/image_optim/runner.rb +1 -0
- data/lib/image_optim/runner/option_parser.rb +1 -0
- data/lib/image_optim/worker.rb +4 -0
- data/lib/image_optim/worker/class_methods.rb +1 -0
- data/lib/image_optim/worker/jhead.rb +1 -0
- data/lib/image_optim/worker/pngout.rb +1 -0
- data/script/worker_analysis +6 -0
- data/spec/image_optim/bin_resolver_spec.rb +2 -2
- data/spec/spec_helper.rb +1 -0
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ec91f27b4e53d23a3516908c5714011fb47bbc251e95ef9952acc62948d123af
|
4
|
+
data.tar.gz: 8b5a675e29709e03bf5ca0567ae742f8d4d7f3d7e90f89ac5ef8c1935c594555
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 847ee0b721a90d761ccfa4948c979e532dfd53d52f2e4c82e9df1e3301bcaba6a4217f98ae5cd5be2bcd7407339614710bd95ef381e9d422e778a4674ddeb81b
|
7
|
+
data.tar.gz: 7f5b009a16df3c671ebc9a8c934cb499fd7ac47a0a464d33130ab1197ffa4b9c1f2767467226124dbd78281bcffd7864c058d8f3ff9fe7b58addfd3b6411ace7
|
data/.rubocop.yml
CHANGED
@@ -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:
|
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:
|
69
|
+
Max: 11
|
70
|
+
|
71
|
+
Metrics/LineLength:
|
72
|
+
Max: 120
|
67
73
|
|
68
74
|
Metrics/MethodLength:
|
69
75
|
Max: 25
|
data/CHANGELOG.markdown
CHANGED
@@ -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)
|
data/README.markdown
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
[](https://ci.appveyor.com/project/toy/image-optim)
|
4
4
|
[](https://codeclimate.com/github/toy/image_optim)
|
5
5
|
[](https://codeclimate.com/github/toy/image_optim)
|
6
|
-
[](https://depfu.com/github/toy/image_optim)
|
7
7
|
[](https://inch-ci.org/github/toy/image_optim)
|
8
8
|
|
9
9
|
# image_optim
|
data/image_optim.gemspec
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = 'image_optim'
|
5
|
-
s.version = '0.26.
|
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.
|
39
|
+
s.add_development_dependency 'rubocop', '~> 0.59'
|
40
40
|
end
|
41
41
|
end
|
data/lib/image_optim.rb
CHANGED
@@ -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
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
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
|
-
|
57
|
-
|
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
|
-
|
68
|
-
|
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
|
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+)+/]
|
data/lib/image_optim/cache.rb
CHANGED
@@ -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|
|
data/lib/image_optim/config.rb
CHANGED
@@ -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
|
|
data/lib/image_optim/handler.rb
CHANGED
@@ -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
|
data/lib/image_optim/runner.rb
CHANGED
data/lib/image_optim/worker.rb
CHANGED
@@ -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
|
data/script/worker_analysis
CHANGED
@@ -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('
|
281
|
+
allow(bin).to receive(:version).and_return(SimpleVersion.new('none'))
|
282
282
|
|
283
|
-
expect(bin).to receive(:warn).once.with(match(/
|
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)
|
data/spec/spec_helper.rb
CHANGED
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.
|
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-
|
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.
|
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.
|
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.
|
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
|