image_optim 0.21.0 → 0.22.0

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,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- MzU4OTIxMDYxM2E3MjAyOTk3NGEzOTg1MjY0NzY0OGE2YTVkZGNiMA==
4
+ NGEwM2UzY2VlZmU0OWJmNzg2YTAyMDZlNWM1MzM5ZWVhNDAyOTg3Mw==
5
5
  data.tar.gz: !binary |-
6
- M2E0MzhmYWQ2MGJjMDIzOWJkMDg3ODNhZDg5NmVjMTNhODRiMDMxMg==
6
+ YTE0YzA1YjQ2NzU3NDIxZjFjNzA4ZGVjOGFmNGY4YTgxMjhiODlhZA==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- NWI2M2EyYzdjOTVmYjVlNmY3YjQ5ZTc4ZTg1NGFmNTBmODQ2NzI5MDBjZjEy
10
- MDlkMDI4NTNmNWYyMDAyOTcyN2ZhMWY4ZDA3ZjZlNGQwMmQ5MGY2ODdjMWRh
11
- ODM1MWVlMTkyM2EyMWQ2NjEzMGMwOWZhNWIwNDZjNDg1MjZjMmM=
9
+ YjI3M2JhYmExNTg2OTg2OGI1NWU5YWEwM2Y4MjNmOWRhNjcwM2EwZmFjOTQz
10
+ ZjI2MzBiZjcwZWIwMjQ0ZWUwOTFlODNjZjU0NThmMDhjYWUzMTE2ZTVmOGFm
11
+ NGM1ZWMzMjYyODZmZTUzZjk2NzljMTY1MDg1M2Y4NmZmNTMwZTY=
12
12
  data.tar.gz: !binary |-
13
- MmExY2E0YzJlODkwM2EwOTdiODI3ZTU4ZjU4ODNmNmQ4ZDQ1ZWQwZDczMDc3
14
- YThiMTdlNGI5ODc3M2NiODkzMDRkMDU0MGUyOWUzZWRiZDcwMDYyM2U5NTQ3
15
- NzZmNzc0NzhiOGE0ZTFhMmFlMGU1ODA4YjUzYzQxYzc0YTViYTg=
13
+ NTQxYjc1MWI2OTgzNzNhOTliMGRjMjgwMTBlMDBjZDdjYmRlN2RjOTVhNTk0
14
+ YjE0NzczOWE0NzZjMWMzOGM4NWFlZTg0ZjAzZWQ3NTNjZGRhYTVkNjc2ZjUx
15
+ OWQ3ODZmZGE2MmMxMWM1YmU1NjI0NzljNDE4MjE4MDdjYzliOTU=
@@ -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': '[]'
@@ -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:
@@ -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)
@@ -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
- ### :advpng =>
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
- ### :gifsicle =>
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
- ### :jhead =>
288
+ ### jhead:
289
289
  Worker has no options
290
290
 
291
- ### :jpegoptim =>
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
- ### :jpegrecompress =>
295
+ ### jpegrecompress:
296
296
  * `:quality` — JPEG quality preset: `0` - low, `1` - medium, `2` - high, `3` - veryhigh *(defaults to `3`)*
297
297
 
298
- ### :jpegtran =>
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
- ### :optipng =>
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
- ### :pngcrush =>
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
- ### :pngout =>
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
- ### :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`)*
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
- ### :svgo =>
323
- Worker has no options
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
 
@@ -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/trusty64'
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 'Install git, node, npm, imagemagick...'
12
- apt-get install -y git npm nodejs-legacy imagemagick > /dev/null
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
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = 'image_optim'
5
- s.version = '0.21.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', '!= 0.30.1'
27
+ s.add_development_dependency 'rubocop', '~> 0.35'
28
28
  end
29
29
  end
@@ -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 rescue 'DEV'
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
@@ -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.gsub('_', '-')
178
- default = option_definition.default
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
- args.unshift '-strip', 'all' if strip
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, NonNegativeIntegerRange, 'min..max - don\'t '\
11
- 'save below min, use less colors below max (both in range `0..100`; '\
12
- 'in yaml - `!ruby/range 0..100`), ignored in default/lossless '\
13
- 'mode') do |v, opt_def|
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
- min = OptionHelpers.limit_with_range(v.begin, 0..100)
16
- min..OptionHelpers.limit_with_range(v.end, min..100)
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
- opt_def.default
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 "### :#{klass.bin_sym} =>"
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 `#{option_definition.default.inspect}`)*"
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) do |h|
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
@@ -40,9 +40,7 @@ describe ImageOptim::HashHelpers do
40
40
  :b => 1,
41
41
  :c => {
42
42
  :d => 2,
43
- :e => {
44
- :f => true,
45
- },
43
+ :e => {:f => true},
46
44
  },
47
45
  },
48
46
  :y => 10,
@@ -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({}).and_call_original
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({}).and_call_original
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
@@ -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.01],
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
@@ -1,3 +1,3 @@
1
- <svg width="1in" height="100" xmlns="http://www.w3.org/2000/svg">
1
+ <svg width="90.000" height="100.000" xmlns="http://www.w3.org/2000/svg">
2
2
  <circle cx="36" cy="50" r="30" stroke="black" stroke-width="10" fill="red" />
3
3
  </svg>
@@ -14,35 +14,36 @@ end
14
14
  def flatten_animation(image)
15
15
  if image.format == :gif
16
16
  flattened = image.temp_path
17
- flatten_command = %W[
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(flatten_command)).to be_truthy
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 nrmse(image_a, image_b)
31
+ def mepp(image_a, image_b)
32
32
  coalesce_a = flatten_animation(image_a)
33
33
  coalesce_b = flatten_animation(image_b)
34
- nrmse_command = %W[
34
+ command = %W[
35
35
  compare
36
- -metric RMSE
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(nrmse_command)
43
+ output = ImageOptim::Cmd.capture(command)
44
44
  if [0, 1].include?($CHILD_STATUS.exitstatus)
45
- output[/\((\d+(\.\d+)?)\)/, 1].to_f
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 = nrmse(actual, expected)
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.21.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-05-30 00:00:00.000000000 Z
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.27'
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.27'
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