image_optim 0.21.0 → 0.22.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/.rubocop.yml +3 -3
- data/.travis.yml +3 -1
- data/CHANGELOG.markdown +8 -0
- data/README.markdown +14 -13
- data/Vagrantfile +10 -3
- data/image_optim.gemspec +2 -2
- data/lib/image_optim.rb +3 -1
- data/lib/image_optim/bin_resolver/bin.rb +1 -0
- data/lib/image_optim/option_definition.rb +6 -0
- data/lib/image_optim/railtie.rb +10 -0
- data/lib/image_optim/runner/option_parser.rb +2 -2
- data/lib/image_optim/worker/optipng.rb +3 -1
- data/lib/image_optim/worker/pngquant.rb +12 -7
- data/lib/image_optim/worker/svgo.rb +16 -0
- data/script/update_worker_options_in_readme +2 -2
- data/spec/image_optim/handler_spec.rb +1 -3
- data/spec/image_optim/hash_helpers_spec.rb +1 -3
- data/spec/image_optim/option_definition_spec.rb +110 -0
- data/spec/image_optim/railtie_spec.rb +29 -3
- data/spec/image_optim/worker/optipng_spec.rb +58 -0
- data/spec/image_optim/worker/pngquant_spec.rb +27 -0
- data/spec/image_optim_spec.rb +1 -1
- data/spec/images/test.svg +1 -1
- data/spec/spec_helper.rb +9 -8
- metadata +10 -10
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
NGEwM2UzY2VlZmU0OWJmNzg2YTAyMDZlNWM1MzM5ZWVhNDAyOTg3Mw==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
YTE0YzA1YjQ2NzU3NDIxZjFjNzA4ZGVjOGFmNGY4YTgxMjhiODlhZA==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
YjI3M2JhYmExNTg2OTg2OGI1NWU5YWEwM2Y4MjNmOWRhNjcwM2EwZmFjOTQz
|
10
|
+
ZjI2MzBiZjcwZWIwMjQ0ZWUwOTFlODNjZjU0NThmMDhjYWUzMTE2ZTVmOGFm
|
11
|
+
NGM1ZWMzMjYyODZmZTUzZjk2NzljMTY1MDg1M2Y4NmZmNTMwZTY=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
NTQxYjc1MWI2OTgzNzNhOTliMGRjMjgwMTBlMDBjZDdjYmRlN2RjOTVhNTk0
|
14
|
+
YjE0NzczOWE0NzZjMWMzOGM4NWFlZTg0ZjAzZWQ3NTNjZGRhYTVkNjc2ZjUx
|
15
|
+
OWQ3ODZmZGE2MmMxMWM1YmU1NjI0NzljNDE4MjE4MDdjYzliOTU=
|
data/.rubocop.yml
CHANGED
@@ -20,9 +20,6 @@ Metrics/MethodLength:
|
|
20
20
|
Metrics/PerceivedComplexity:
|
21
21
|
Max: 8
|
22
22
|
|
23
|
-
Performance/ParallelAssignment:
|
24
|
-
Enabled: false
|
25
|
-
|
26
23
|
Style/AccessModifierIndentation:
|
27
24
|
EnforcedStyle: outdent
|
28
25
|
|
@@ -47,6 +44,9 @@ Style/IfUnlessModifier:
|
|
47
44
|
Style/IndentHash:
|
48
45
|
EnforcedStyle: consistent
|
49
46
|
|
47
|
+
Style/ParallelAssignment:
|
48
|
+
Enabled: false
|
49
|
+
|
50
50
|
Style/PercentLiteralDelimiters:
|
51
51
|
PreferredDelimiters:
|
52
52
|
'%w': '[]'
|
data/.travis.yml
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
sudo: false
|
1
2
|
language: ruby
|
2
3
|
rvm:
|
3
4
|
- 1.8.7
|
@@ -6,7 +7,6 @@ rvm:
|
|
6
7
|
- '2.0'
|
7
8
|
- '2.1'
|
8
9
|
- '2.2'
|
9
|
-
- jruby-18mode
|
10
10
|
- jruby-19mode
|
11
11
|
- ree
|
12
12
|
script:
|
@@ -36,6 +36,8 @@ matrix:
|
|
36
36
|
rvm: default
|
37
37
|
- env: RUBOCOP=true
|
38
38
|
rvm: default
|
39
|
+
allow_failures:
|
40
|
+
- rvm: jruby-19mode
|
39
41
|
addons:
|
40
42
|
code_climate:
|
41
43
|
repo_token:
|
data/CHANGELOG.markdown
CHANGED
@@ -2,6 +2,14 @@
|
|
2
2
|
|
3
3
|
## unreleased
|
4
4
|
|
5
|
+
## v0.22.0 (2015-11-21)
|
6
|
+
|
7
|
+
* Unify getting description of option default value using `default_description` [@toy](https://github.com/toy)
|
8
|
+
* Don't use `-strip` option for optipng when the bin version is less than 0.7 [#106](https://github.com/toy/image_optim/issues/106) [@toy](https://github.com/toy)
|
9
|
+
* Use quality `0..100` by default in lossy mode of pngquant worker [#77](https://github.com/toy/image_optim/issues/77) [@toy](https://github.com/toy)
|
10
|
+
* Add `:disable_plugins` and `:enable_plugins` options to `svgo` worker [#110](https://github.com/toy/image_optim/pull/110) [@tomhughes](https://github.com/tomhughes)
|
11
|
+
* Allow setting config in rails like `config.assets.image_optim.name = value` [#111](https://github.com/toy/image_optim/pull/111) [@toy](https://github.com/toy)
|
12
|
+
|
5
13
|
## v0.21.0 (2015-05-30)
|
6
14
|
|
7
15
|
* Use exifr 1.2.2 with fix for a bug [#85](https://github.com/toy/image_optim/issues/85) [@toy](https://github.com/toy)
|
data/README.markdown
CHANGED
@@ -277,50 +277,51 @@ Worker can be disabled by passing `false` instead of options hash or by setting
|
|
277
277
|
<!---<worker-options>-->
|
278
278
|
<!-- markdown for worker options is generated by `script/update_worker_options_in_readme` -->
|
279
279
|
|
280
|
-
### :
|
280
|
+
### advpng:
|
281
281
|
* `:level` — Compression level: `0` - don't compress, `1` - fast, `2` - normal, `3` - extra, `4` - extreme *(defaults to `4`)*
|
282
282
|
|
283
|
-
### :
|
283
|
+
### gifsicle:
|
284
284
|
* `:interlace` — Interlace: `true` - interlace on, `false` - interlace off, `nil` - as is in original image (defaults to running two instances, one with interlace off and one with on)
|
285
285
|
* `:level` — Compression level: `1` - light and fast, `2` - normal, `3` - heavy (slower) *(defaults to `3`)*
|
286
286
|
* `:careful` — Avoid bugs with some software *(defaults to `false`)*
|
287
287
|
|
288
|
-
### :
|
288
|
+
### jhead:
|
289
289
|
Worker has no options
|
290
290
|
|
291
|
-
### :
|
291
|
+
### jpegoptim:
|
292
292
|
* `:strip` — List of extra markers to strip: `:comments`, `:exif`, `:iptc`, `:icc` or `:all` *(defaults to `:all`)*
|
293
293
|
* `:max_quality` — Maximum image quality factor `0`..`100`, ignored in default/lossless mode *(defaults to `100`)*
|
294
294
|
|
295
|
-
### :
|
295
|
+
### jpegrecompress:
|
296
296
|
* `:quality` — JPEG quality preset: `0` - low, `1` - medium, `2` - high, `3` - veryhigh *(defaults to `3`)*
|
297
297
|
|
298
|
-
### :
|
298
|
+
### jpegtran:
|
299
299
|
* `:copy_chunks` — Copy all chunks *(defaults to `false`)*
|
300
300
|
* `:progressive` — Create progressive JPEG file *(defaults to `true`)*
|
301
301
|
* `:jpegrescan` — Use jpegtran through jpegrescan, ignore progressive option *(defaults to `false`)*
|
302
302
|
|
303
|
-
### :
|
303
|
+
### optipng:
|
304
304
|
* `:level` — Optimization level preset: `0` is least, `7` is best *(defaults to `6`)*
|
305
305
|
* `:interlace` — Interlace: `true` - interlace on, `false` - interlace off, `nil` - as is in original image *(defaults to `false`)*
|
306
306
|
* `:strip` — Remove all auxiliary chunks *(defaults to `true`)*
|
307
307
|
|
308
|
-
### :
|
308
|
+
### pngcrush:
|
309
309
|
* `:chunks` — List of chunks to remove or `:alla` - all except tRNS/transparency or `:allb` - all except tRNS and gAMA/gamma *(defaults to `:alla`)*
|
310
310
|
* `:fix` — Fix otherwise fatal conditions such as bad CRCs *(defaults to `false`)*
|
311
311
|
* `:brute` — Brute force try all methods, very time-consuming and generally not worthwhile *(defaults to `false`)*
|
312
312
|
* `:blacken` — Blacken fully transparent pixels *(defaults to `true`)*
|
313
313
|
|
314
|
-
### :
|
314
|
+
### pngout:
|
315
315
|
* `:copy_chunks` — Copy optional chunks *(defaults to `false`)*
|
316
316
|
* `:strategy` — Strategy: `0` - xtreme, `1` - intense, `2` - longest Match, `3` - huffman Only, `4` - uncompressed *(defaults to `0`)*
|
317
317
|
|
318
|
-
### :
|
319
|
-
* `:quality` — min..max - don't save below min, use less colors below max (both in range `0..100`; in yaml - `!ruby/range 0..100`), ignored in default/lossless mode *(defaults to `100..100`)*
|
318
|
+
### pngquant:
|
319
|
+
* `:quality` — min..max - don't save below min, use less colors below max (both in range `0..100`; in yaml - `!ruby/range 0..100`), ignored in default/lossless mode *(defaults to `100..100`, `0..100` in lossy mode)*
|
320
320
|
* `:speed` — speed/quality trade-off: `1` - slow, `3` - default, `11` - fast & rough *(defaults to `3`)*
|
321
321
|
|
322
|
-
### :
|
323
|
-
|
322
|
+
### svgo:
|
323
|
+
* `:disable_plugins` — List of plugins to disable *(defaults to `[]`)*
|
324
|
+
* `:enable_plugins` — List of plugins to enable *(defaults to `[]`)*
|
324
325
|
|
325
326
|
<!---</worker-options>-->
|
326
327
|
|
data/Vagrantfile
CHANGED
@@ -1,15 +1,22 @@
|
|
1
1
|
VAGRANTFILE_API_VERSION = '2'
|
2
2
|
|
3
3
|
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
4
|
-
config.vm.box = 'ubuntu/
|
4
|
+
config.vm.box = 'ubuntu/precise64'
|
5
5
|
|
6
6
|
config.vm.provision 'shell', :inline => <<-SH
|
7
7
|
set -e
|
8
8
|
|
9
9
|
cd /vagrant
|
10
10
|
|
11
|
-
echo '
|
12
|
-
apt-get
|
11
|
+
echo 'apt-get update...'
|
12
|
+
apt-get update > /dev/null
|
13
|
+
|
14
|
+
echo 'Install git, imagemagick, ruby1.9.1-dev...'
|
15
|
+
apt-get install -y git npm imagemagick ruby1.9.1-dev > /dev/null
|
16
|
+
|
17
|
+
echo 'Install node, npm...'
|
18
|
+
curl -sL https://deb.nodesource.com/setup | sudo bash - > /dev/null
|
19
|
+
sudo apt-get install -y nodejs > /dev/null
|
13
20
|
|
14
21
|
echo 'Update rubygems...'
|
15
22
|
REALLY_GEM_UPDATE_SYSTEM=x gem update --system > /dev/null
|
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.
|
5
|
+
s.version = '0.22.0'
|
6
6
|
s.summary = %q{Optimize (lossless compress, optionally lossy) images (jpeg, png, gif, svg) 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']
|
@@ -24,6 +24,6 @@ Gem::Specification.new do |s|
|
|
24
24
|
s.add_development_dependency 'image_optim_pack', '~> 0.2'
|
25
25
|
s.add_development_dependency 'rspec', '~> 3.0'
|
26
26
|
if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('1.9.3')
|
27
|
-
s.add_development_dependency 'rubocop', '~> 0.
|
27
|
+
s.add_development_dependency 'rubocop', '~> 0.35'
|
28
28
|
end
|
29
29
|
end
|
data/lib/image_optim.rb
CHANGED
@@ -163,7 +163,9 @@ class ImageOptim
|
|
163
163
|
|
164
164
|
# Version of image_optim gem spec loaded
|
165
165
|
def self.version
|
166
|
-
Gem.loaded_specs['image_optim'].version.to_s
|
166
|
+
Gem.loaded_specs['image_optim'].version.to_s
|
167
|
+
rescue
|
168
|
+
'DEV'
|
167
169
|
end
|
168
170
|
|
169
171
|
# Full version of image_optim
|
@@ -36,6 +36,7 @@ class ImageOptim
|
|
36
36
|
[:gifsicle, is < '1.85', 'does not support removing extension blocks'],
|
37
37
|
[:pngcrush, is < '1.7.38', 'does not have blacken flag'],
|
38
38
|
[:pngquant, is < '2.1', 'may be lossy even with quality `100-`'],
|
39
|
+
[:optipng, is < '0.7', 'does not support -strip option'],
|
39
40
|
]
|
40
41
|
|
41
42
|
# Fail if version will not work properly
|
@@ -28,5 +28,11 @@ class ImageOptim
|
|
28
28
|
value
|
29
29
|
end
|
30
30
|
end
|
31
|
+
|
32
|
+
# Describe default value, returns string as is otherwise surrounds
|
33
|
+
# inspected value with backticks
|
34
|
+
def default_description
|
35
|
+
default.is_a?(String) ? default : "`#{default.inspect}`"
|
36
|
+
end
|
31
37
|
end
|
32
38
|
end
|
data/lib/image_optim/railtie.rb
CHANGED
@@ -3,6 +3,16 @@ require 'image_optim'
|
|
3
3
|
class ImageOptim
|
4
4
|
# Adds image_optim as preprocessor for gif, jpeg, png and svg images
|
5
5
|
class Railtie < Rails::Railtie
|
6
|
+
config.before_configuration do |app|
|
7
|
+
worker_names = ImageOptim::Worker.klasses.map(&:bin_sym)
|
8
|
+
app.config.assets.image_optim =
|
9
|
+
ActiveSupport::OrderedOptions.new do |hash, key|
|
10
|
+
if worker_names.include?(key.to_sym)
|
11
|
+
hash[key] = ActiveSupport::OrderedOptions.new
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
6
16
|
initializer 'image_optim.initializer' do |app|
|
7
17
|
register_preprocessor(app) if register_preprocessor?(app)
|
8
18
|
end
|
@@ -174,8 +174,8 @@ ImageOptim::Runner::OptionParser::DEFINE = proc do |op, options|
|
|
174
174
|
|
175
175
|
bin = klass.bin_sym
|
176
176
|
klass.option_definitions.each do |option_definition|
|
177
|
-
name = option_definition.name.to_s.
|
178
|
-
default = option_definition.
|
177
|
+
name = option_definition.name.to_s.tr('_', '-')
|
178
|
+
default = option_definition.default_description
|
179
179
|
type = option_definition.type
|
180
180
|
|
181
181
|
type, marking = case
|
@@ -37,7 +37,9 @@ class ImageOptim
|
|
37
37
|
#{dst}
|
38
38
|
]
|
39
39
|
args.unshift "-i#{interlace ? 1 : 0}" unless interlace.nil?
|
40
|
-
|
40
|
+
if resolve_bin!(:optipng).version >= '0.7'
|
41
|
+
args.unshift '-strip', 'all' if strip
|
42
|
+
end
|
41
43
|
execute(:optipng, *args) && optimized?(src, dst)
|
42
44
|
end
|
43
45
|
end
|
@@ -7,19 +7,24 @@ class ImageOptim
|
|
7
7
|
# http://pngquant.org/
|
8
8
|
class Pngquant < Worker
|
9
9
|
QUALITY_OPTION =
|
10
|
-
option(:quality, 100..100
|
11
|
-
|
12
|
-
|
13
|
-
|
10
|
+
option(:quality, '`100..100`, `0..100` in lossy mode',
|
11
|
+
NonNegativeIntegerRange, 'min..max - don\'t '\
|
12
|
+
'save below min, use less colors below max (both in range `0..100`; '\
|
13
|
+
'in yaml - `!ruby/range 0..100`), ignored in default/lossless '\
|
14
|
+
'mode') do |v, opt_def|
|
14
15
|
if allow_lossy
|
15
|
-
|
16
|
-
|
16
|
+
if v == opt_def.default
|
17
|
+
0..100
|
18
|
+
else
|
19
|
+
min = OptionHelpers.limit_with_range(v.begin, 0..100)
|
20
|
+
min..OptionHelpers.limit_with_range(v.end, min..100)
|
21
|
+
end
|
17
22
|
else
|
18
23
|
if v != opt_def.default
|
19
24
|
warn "#{self.class.bin_sym} #{opt_def.name} #{v} ignored " \
|
20
25
|
'in lossless mode'
|
21
26
|
end
|
22
|
-
|
27
|
+
100..100
|
23
28
|
end
|
24
29
|
end
|
25
30
|
|
@@ -4,11 +4,27 @@ class ImageOptim
|
|
4
4
|
class Worker
|
5
5
|
# https://github.com/svg/svgo
|
6
6
|
class Svgo < Worker
|
7
|
+
DISABLE_PLUGINS_OPTION =
|
8
|
+
option(:disable_plugins, [], 'List of plugins to disable') do |v|
|
9
|
+
Array(v).map(&:to_s)
|
10
|
+
end
|
11
|
+
|
12
|
+
ENABLE_PLUGINS_OPTION =
|
13
|
+
option(:enable_plugins, [], 'List of plugins to enable') do |v|
|
14
|
+
Array(v).map(&:to_s)
|
15
|
+
end
|
16
|
+
|
7
17
|
def optimize(src, dst)
|
8
18
|
args = %W[
|
9
19
|
--input #{src}
|
10
20
|
--output #{dst}
|
11
21
|
]
|
22
|
+
disable_plugins.each do |plugin_name|
|
23
|
+
args.unshift "--disable=#{plugin_name}"
|
24
|
+
end
|
25
|
+
enable_plugins.each do |plugin_name|
|
26
|
+
args.unshift "--enable=#{plugin_name}"
|
27
|
+
end
|
12
28
|
execute(:svgo, *args) && optimized?(src, dst)
|
13
29
|
end
|
14
30
|
end
|
@@ -12,14 +12,14 @@ GENERATED_NOTE = '<!-- markdown for worker options is generated by '\
|
|
12
12
|
"`#{Pathname($PROGRAM_NAME).cleanpath}` -->"
|
13
13
|
|
14
14
|
def write_worker_options(io, klass)
|
15
|
-
io.puts "###
|
15
|
+
io.puts "### #{klass.bin_sym}:"
|
16
16
|
if klass.option_definitions.empty?
|
17
17
|
io.puts 'Worker has no options'
|
18
18
|
else
|
19
19
|
klass.option_definitions.each do |option_definition|
|
20
20
|
line = "* `:#{option_definition.name}` — #{option_definition.description}"
|
21
21
|
unless line['(defaults']
|
22
|
-
line << " *(defaults to
|
22
|
+
line << " *(defaults to #{option_definition.default_description})*"
|
23
23
|
end
|
24
24
|
io.puts line
|
25
25
|
end
|
@@ -72,9 +72,7 @@ describe ImageOptim::Handler do
|
|
72
72
|
expect(handler).to receive(:cleanup)
|
73
73
|
expect(handler).to receive(:result).and_return(result)
|
74
74
|
|
75
|
-
expect(Handler.for(original)
|
76
|
-
h.process
|
77
|
-
end).to eq(result)
|
75
|
+
expect(Handler.for(original, &:process)).to eq(result)
|
78
76
|
end
|
79
77
|
|
80
78
|
it 'cleans up if exception is raised' do
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'image_optim/option_definition'
|
3
|
+
|
4
|
+
describe ImageOptim::OptionDefinition do
|
5
|
+
describe 'initialization' do
|
6
|
+
context 'when type is not specified explicitly' do
|
7
|
+
subject{ described_class.new('abc', :def, 'desc') }
|
8
|
+
|
9
|
+
describe '#name' do
|
10
|
+
it{ expect(subject.name).to eq(:abc) }
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#default' do
|
14
|
+
it{ expect(subject.default).to eq(:def) }
|
15
|
+
end
|
16
|
+
|
17
|
+
describe '#type' do
|
18
|
+
it{ expect(subject.type).to eq(Symbol) }
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '#description' do
|
22
|
+
it{ expect(subject.description).to eq('desc') }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'when type is specified explicitly' do
|
27
|
+
subject{ described_class.new('abc', :def, Hash, 'desc') }
|
28
|
+
|
29
|
+
describe '#name' do
|
30
|
+
it{ expect(subject.name).to eq(:abc) }
|
31
|
+
end
|
32
|
+
|
33
|
+
describe '#default' do
|
34
|
+
it{ expect(subject.default).to eq(:def) }
|
35
|
+
end
|
36
|
+
|
37
|
+
describe '#type' do
|
38
|
+
it{ expect(subject.type).to eq(Hash) }
|
39
|
+
end
|
40
|
+
|
41
|
+
describe '#description' do
|
42
|
+
it{ expect(subject.description).to eq('desc') }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe '#value' do
|
48
|
+
context 'when proc not given' do
|
49
|
+
subject{ described_class.new('abc', :def, 'desc') }
|
50
|
+
|
51
|
+
context 'when option not provided' do
|
52
|
+
it 'returns default' do
|
53
|
+
expect(subject.value(nil, {})).to eq(:def)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context 'when option is nil' do
|
58
|
+
it 'returns nil' do
|
59
|
+
expect(subject.value(nil, :abc => nil)).to eq(nil)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context 'when option is set' do
|
64
|
+
it 'returns value' do
|
65
|
+
expect(subject.value(nil, :abc => 123)).to eq(123)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context 'when proc given' do
|
71
|
+
subject{ described_class.new('abc', :def, 'desc', &:inspect) }
|
72
|
+
|
73
|
+
context 'when option not provided' do
|
74
|
+
it 'returns default passed through proc' do
|
75
|
+
expect(subject.value(nil, {})).to eq(':def')
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context 'when option is nil' do
|
80
|
+
it 'returns nil passed through proc' do
|
81
|
+
expect(subject.value(nil, :abc => nil)).to eq('nil')
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context 'when option is set' do
|
86
|
+
it 'returns value passed through proc' do
|
87
|
+
expect(subject.value(nil, :abc => 123)).to eq('123')
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe '#default_description' do
|
94
|
+
context 'when default is not a string' do
|
95
|
+
subject{ described_class.new('abc', :def, 'desc') }
|
96
|
+
|
97
|
+
it 'returns inspected value in backticks' do
|
98
|
+
expect(subject.default_description).to eq('`:def`')
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
context 'when default is a string' do
|
103
|
+
subject{ described_class.new('abc', '`1`', 'desc') }
|
104
|
+
|
105
|
+
it 'returns it as is' do
|
106
|
+
expect(subject.default_description).to eq('`1`')
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -23,7 +23,6 @@ describe 'ImageOptim::Railtie' do
|
|
23
23
|
assets.paths = %w[spec/images]
|
24
24
|
|
25
25
|
assets.delete(:compress)
|
26
|
-
assets.delete(:image_optim)
|
27
26
|
end
|
28
27
|
|
29
28
|
yield config if block_given?
|
@@ -68,14 +67,14 @@ describe 'ImageOptim::Railtie' do
|
|
68
67
|
end
|
69
68
|
|
70
69
|
it 'initializes with empty hash if config.assets.image_optim is true' do
|
71
|
-
expect(ImageOptim).to receive(:new).with({})
|
70
|
+
expect(ImageOptim).to receive(:new).with({})
|
72
71
|
init_rails_app do |config|
|
73
72
|
config.assets.image_optim = true
|
74
73
|
end
|
75
74
|
end
|
76
75
|
|
77
76
|
it 'initializes with empty hash if config.assets.image_optim is nil' do
|
78
|
-
expect(ImageOptim).to receive(:new).with({})
|
77
|
+
expect(ImageOptim).to receive(:new).with({})
|
79
78
|
init_rails_app do |config|
|
80
79
|
config.assets.image_optim = nil
|
81
80
|
end
|
@@ -88,6 +87,33 @@ describe 'ImageOptim::Railtie' do
|
|
88
87
|
config.assets.image_optim = hash
|
89
88
|
end
|
90
89
|
end
|
90
|
+
|
91
|
+
it 'is possible to set individual options' do
|
92
|
+
hash = {:config_paths => 'config/image_optim.yml'}
|
93
|
+
expect(ImageOptim).to receive(:new).with(hash)
|
94
|
+
init_rails_app do |config|
|
95
|
+
config.assets.image_optim.config_paths = 'config/image_optim.yml'
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'is possible to set individual worker options' do
|
100
|
+
hash = {:advpng => {:level => 3}}
|
101
|
+
expect(ImageOptim).to receive(:new).with(hash)
|
102
|
+
init_rails_app do |config|
|
103
|
+
expect(config.assets.image_optim.advpng).to eq({})
|
104
|
+
config.assets.image_optim.advpng.level = 3
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'is not possible to set unknown worker options' do
|
109
|
+
expect(ImageOptim).to receive(:new).with({})
|
110
|
+
init_rails_app do |config|
|
111
|
+
expect(config.assets.image_optim.unknown).to eq(nil)
|
112
|
+
expect do
|
113
|
+
config.assets.image_optim.unknown.level = 3
|
114
|
+
end.to raise_error(NoMethodError)
|
115
|
+
end
|
116
|
+
end
|
91
117
|
end
|
92
118
|
end
|
93
119
|
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'image_optim/worker/optipng'
|
3
|
+
require 'image_optim/image_path'
|
4
|
+
|
5
|
+
describe ImageOptim::Worker::Optipng do
|
6
|
+
describe 'strip option' do
|
7
|
+
subject{ described_class.new(ImageOptim.new, options) }
|
8
|
+
|
9
|
+
let(:options){ {} }
|
10
|
+
let(:optipng_version){ '0.7' }
|
11
|
+
let(:src){ instance_double(ImageOptim::ImagePath, :copy => nil) }
|
12
|
+
let(:dst){ instance_double(ImageOptim::ImagePath) }
|
13
|
+
|
14
|
+
before do
|
15
|
+
optipng_bin = instance_double(ImageOptim::BinResolver::Bin)
|
16
|
+
allow(subject).to receive(:resolve_bin!).
|
17
|
+
with(:optipng).and_return(optipng_bin)
|
18
|
+
allow(optipng_bin).to receive(:version).
|
19
|
+
and_return(ImageOptim::BinResolver::SimpleVersion.new(optipng_version))
|
20
|
+
|
21
|
+
allow(subject).to receive(:optimized?)
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'by default' do
|
25
|
+
it 'should add -strip all to arguments' do
|
26
|
+
expect(subject).to receive(:execute) do |_bin, *args|
|
27
|
+
expect(args.join(' ')).to match(/(^| )-strip all($| )/)
|
28
|
+
end
|
29
|
+
|
30
|
+
subject.optimize(src, dst)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'when strip is disabled' do
|
35
|
+
let(:options){ {:strip => false} }
|
36
|
+
|
37
|
+
it 'should not add -strip all to arguments' do
|
38
|
+
expect(subject).to receive(:execute) do |_bin, *args|
|
39
|
+
expect(args.join(' ')).not_to match(/(^| )-strip all($| )/)
|
40
|
+
end
|
41
|
+
|
42
|
+
subject.optimize(src, dst)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context 'when optipng version is < 0.7' do
|
47
|
+
let(:optipng_version){ '0.6.999' }
|
48
|
+
|
49
|
+
it 'should not add -strip all to arguments' do
|
50
|
+
expect(subject).to receive(:execute) do |_bin, *args|
|
51
|
+
expect(args.join(' ')).not_to match(/(^| )-strip all($| )/)
|
52
|
+
end
|
53
|
+
|
54
|
+
subject.optimize(src, dst)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'image_optim/worker/pngquant'
|
3
|
+
|
4
|
+
describe ImageOptim::Worker::Pngquant do
|
5
|
+
describe 'quality option' do
|
6
|
+
describe 'default' do
|
7
|
+
subject{ described_class::QUALITY_OPTION.default }
|
8
|
+
|
9
|
+
it{ is_expected.to match(/100\.\.100.*0\.\.100/) }
|
10
|
+
end
|
11
|
+
|
12
|
+
describe 'value' do
|
13
|
+
let(:options){ {} }
|
14
|
+
subject{ described_class.new(ImageOptim.new, options).quality }
|
15
|
+
|
16
|
+
context 'by default' do
|
17
|
+
it{ is_expected.to eq(100..100) }
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'when lossy allowed by default' do
|
21
|
+
let(:options){ {:allow_lossy => true} }
|
22
|
+
|
23
|
+
it{ is_expected.to eq(0..100) }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/spec/image_optim_spec.rb
CHANGED
@@ -67,7 +67,7 @@ describe ImageOptim do
|
|
67
67
|
base_options = {:skip_missing_workers => false}
|
68
68
|
[
|
69
69
|
['lossless', base_options, 0],
|
70
|
-
['lossy', base_options.merge(:allow_lossy => true), 0.
|
70
|
+
['lossy', base_options.merge(:allow_lossy => true), 0.001],
|
71
71
|
].each do |type, options, max_difference|
|
72
72
|
image_optim = ImageOptim.new(options)
|
73
73
|
describe type do
|
data/spec/images/test.svg
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -14,35 +14,36 @@ end
|
|
14
14
|
def flatten_animation(image)
|
15
15
|
if image.format == :gif
|
16
16
|
flattened = image.temp_path
|
17
|
-
|
17
|
+
command = %W[
|
18
18
|
convert
|
19
19
|
#{image.to_s.shellescape}
|
20
20
|
-coalesce
|
21
21
|
-append
|
22
22
|
#{flattened.to_s.shellescape}
|
23
23
|
].join(' ')
|
24
|
-
expect(ImageOptim::Cmd.run(
|
24
|
+
expect(ImageOptim::Cmd.run(command)).to be_truthy
|
25
25
|
flattened
|
26
26
|
else
|
27
27
|
image
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
-
def
|
31
|
+
def mepp(image_a, image_b)
|
32
32
|
coalesce_a = flatten_animation(image_a)
|
33
33
|
coalesce_b = flatten_animation(image_b)
|
34
|
-
|
34
|
+
command = %W[
|
35
35
|
compare
|
36
|
-
-metric
|
36
|
+
-metric MEPP
|
37
37
|
-alpha Background
|
38
38
|
#{coalesce_a.to_s.shellescape}
|
39
39
|
#{coalesce_b.to_s.shellescape}
|
40
40
|
/dev/null
|
41
41
|
2>&1
|
42
42
|
].join(' ')
|
43
|
-
output = ImageOptim::Cmd.capture(
|
43
|
+
output = ImageOptim::Cmd.capture(command)
|
44
44
|
if [0, 1].include?($CHILD_STATUS.exitstatus)
|
45
|
-
|
45
|
+
num_r = '\d+(?:\.\d+(?:[eE][-+]?\d+)?)?'
|
46
|
+
output[/\((#{num_r}), #{num_r}\)/, 1].to_f
|
46
47
|
else
|
47
48
|
fail "compare #{image_a} with #{image_b} failed with `#{output}`"
|
48
49
|
end
|
@@ -54,7 +55,7 @@ end
|
|
54
55
|
|
55
56
|
RSpec::Matchers.define :be_similar_to do |expected, max_difference|
|
56
57
|
match do |actual|
|
57
|
-
@diff =
|
58
|
+
@diff = mepp(actual, expected)
|
58
59
|
@diff <= max_difference
|
59
60
|
end
|
60
61
|
failure_message do |actual|
|
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.
|
4
|
+
version: 0.22.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ivan Kuchin
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-11-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: fspath
|
@@ -126,20 +126,14 @@ dependencies:
|
|
126
126
|
requirements:
|
127
127
|
- - ~>
|
128
128
|
- !ruby/object:Gem::Version
|
129
|
-
version: '0.
|
130
|
-
- - ! '!='
|
131
|
-
- !ruby/object:Gem::Version
|
132
|
-
version: 0.30.1
|
129
|
+
version: '0.35'
|
133
130
|
type: :development
|
134
131
|
prerelease: false
|
135
132
|
version_requirements: !ruby/object:Gem::Requirement
|
136
133
|
requirements:
|
137
134
|
- - ~>
|
138
135
|
- !ruby/object:Gem::Version
|
139
|
-
version: '0.
|
140
|
-
- - ! '!='
|
141
|
-
- !ruby/object:Gem::Version
|
142
|
-
version: 0.30.1
|
136
|
+
version: '0.35'
|
143
137
|
description:
|
144
138
|
email:
|
145
139
|
executables:
|
@@ -206,10 +200,13 @@ files:
|
|
206
200
|
- spec/image_optim/handler_spec.rb
|
207
201
|
- spec/image_optim/hash_helpers_spec.rb
|
208
202
|
- spec/image_optim/image_path_spec.rb
|
203
|
+
- spec/image_optim/option_definition_spec.rb
|
209
204
|
- spec/image_optim/railtie_spec.rb
|
210
205
|
- spec/image_optim/runner/glob_helpers_spec.rb
|
211
206
|
- spec/image_optim/runner/option_parser_spec.rb
|
212
207
|
- spec/image_optim/space_spec.rb
|
208
|
+
- spec/image_optim/worker/optipng_spec.rb
|
209
|
+
- spec/image_optim/worker/pngquant_spec.rb
|
213
210
|
- spec/image_optim/worker_spec.rb
|
214
211
|
- spec/image_optim_spec.rb
|
215
212
|
- spec/images/comparison.png
|
@@ -274,10 +271,13 @@ test_files:
|
|
274
271
|
- spec/image_optim/handler_spec.rb
|
275
272
|
- spec/image_optim/hash_helpers_spec.rb
|
276
273
|
- spec/image_optim/image_path_spec.rb
|
274
|
+
- spec/image_optim/option_definition_spec.rb
|
277
275
|
- spec/image_optim/railtie_spec.rb
|
278
276
|
- spec/image_optim/runner/glob_helpers_spec.rb
|
279
277
|
- spec/image_optim/runner/option_parser_spec.rb
|
280
278
|
- spec/image_optim/space_spec.rb
|
279
|
+
- spec/image_optim/worker/optipng_spec.rb
|
280
|
+
- spec/image_optim/worker/pngquant_spec.rb
|
281
281
|
- spec/image_optim/worker_spec.rb
|
282
282
|
- spec/image_optim_spec.rb
|
283
283
|
- spec/images/comparison.png
|