image_optim 0.26.3 → 0.28.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 +4 -4
- data/.appveyor.yml +9 -2
- data/.rubocop.yml +34 -12
- data/.travis.yml +18 -15
- data/CHANGELOG.markdown +23 -0
- data/CONTRIBUTING.markdown +4 -1
- data/Gemfile +3 -1
- data/LICENSE.txt +1 -1
- data/README.markdown +10 -3
- data/Vagrantfile +2 -0
- data/bin/image_optim +1 -0
- data/image_optim.gemspec +5 -7
- data/lib/image_optim.rb +2 -0
- data/lib/image_optim/bin_resolver.rb +2 -0
- data/lib/image_optim/bin_resolver/bin.rb +4 -0
- data/lib/image_optim/bin_resolver/comparable_condition.rb +3 -0
- data/lib/image_optim/bin_resolver/error.rb +2 -0
- data/lib/image_optim/bin_resolver/simple_version.rb +2 -0
- data/lib/image_optim/cache.rb +2 -0
- data/lib/image_optim/cache_path.rb +21 -2
- data/lib/image_optim/cmd.rb +2 -0
- data/lib/image_optim/config.rb +6 -4
- data/lib/image_optim/configuration_error.rb +2 -0
- data/lib/image_optim/handler.rb +2 -0
- data/lib/image_optim/hash_helpers.rb +2 -0
- data/lib/image_optim/image_meta.rb +2 -0
- data/lib/image_optim/non_negative_integer_range.rb +2 -0
- data/lib/image_optim/optimized_path.rb +3 -1
- data/lib/image_optim/option_definition.rb +2 -0
- data/lib/image_optim/option_helpers.rb +2 -0
- data/lib/image_optim/path.rb +30 -5
- data/lib/image_optim/runner.rb +2 -0
- data/lib/image_optim/runner/glob_helpers.rb +3 -1
- data/lib/image_optim/runner/option_parser.rb +5 -2
- data/lib/image_optim/space.rb +3 -1
- data/lib/image_optim/true_false_nil.rb +2 -0
- data/lib/image_optim/worker.rb +1 -0
- data/lib/image_optim/worker/advpng.rb +2 -0
- data/lib/image_optim/worker/class_methods.rb +4 -0
- data/lib/image_optim/worker/gifsicle.rb +2 -0
- data/lib/image_optim/worker/jhead.rb +3 -1
- data/lib/image_optim/worker/jpegoptim.rb +8 -4
- data/lib/image_optim/worker/jpegrecompress.rb +17 -0
- data/lib/image_optim/worker/jpegtran.rb +2 -0
- data/lib/image_optim/worker/optipng.rb +4 -2
- data/lib/image_optim/worker/pngcrush.rb +4 -2
- data/lib/image_optim/worker/pngout.rb +2 -0
- data/lib/image_optim/worker/pngquant.rb +3 -0
- data/lib/image_optim/worker/svgo.rb +2 -0
- data/script/update_worker_options_in_readme +4 -3
- data/script/worker_analysis +7 -3
- data/spec/image_optim/bin_resolver/comparable_condition_spec.rb +2 -0
- data/spec/image_optim/bin_resolver/simple_version_spec.rb +2 -0
- data/spec/image_optim/bin_resolver_spec.rb +2 -0
- data/spec/image_optim/cache_path_spec.rb +71 -26
- data/spec/image_optim/cache_spec.rb +5 -1
- data/spec/image_optim/cmd_spec.rb +2 -0
- data/spec/image_optim/config_spec.rb +2 -0
- data/spec/image_optim/handler_spec.rb +2 -0
- data/spec/image_optim/hash_helpers_spec.rb +2 -0
- data/spec/image_optim/image_meta_spec.rb +2 -0
- data/spec/image_optim/optimized_path_spec.rb +2 -0
- data/spec/image_optim/option_definition_spec.rb +2 -0
- data/spec/image_optim/option_helpers_spec.rb +2 -0
- data/spec/image_optim/path_spec.rb +65 -24
- data/spec/image_optim/runner/glob_helpers_spec.rb +2 -0
- data/spec/image_optim/runner/option_parser_spec.rb +2 -0
- data/spec/image_optim/space_spec.rb +13 -11
- data/spec/image_optim/worker/jpegrecompress_spec.rb +32 -0
- data/spec/image_optim/worker/optipng_spec.rb +2 -0
- data/spec/image_optim/worker/pngquant_spec.rb +2 -0
- data/spec/image_optim/worker_spec.rb +2 -0
- data/spec/image_optim_spec.rb +7 -4
- data/spec/images/invisiblepixels/generate +1 -0
- data/spec/images/quant/generate +3 -2
- data/spec/spec_helper.rb +2 -0
- metadata +14 -13
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
require 'image_optim/cache_path'
|
3
5
|
require 'tempfile'
|
@@ -6,52 +8,95 @@ describe ImageOptim::CachePath do
|
|
6
8
|
include CapabilityCheckHelpers
|
7
9
|
|
8
10
|
before do
|
11
|
+
stub_const('Path', ImageOptim::Path)
|
9
12
|
stub_const('CachePath', ImageOptim::CachePath)
|
10
13
|
end
|
11
14
|
|
12
15
|
describe '#replace' do
|
13
|
-
let(:
|
14
|
-
let(:
|
16
|
+
let(:src_dir){ Path.temp_dir }
|
17
|
+
let(:src){ CachePath.temp_file_path(nil, src_dir) }
|
18
|
+
let(:dst){ Path.temp_file_path }
|
15
19
|
|
16
|
-
|
17
|
-
|
20
|
+
shared_examples 'replaces file' do
|
21
|
+
it 'moves data to destination' do
|
22
|
+
src.write('src')
|
18
23
|
|
19
|
-
|
24
|
+
src.replace(dst)
|
20
25
|
|
21
|
-
|
22
|
-
|
26
|
+
expect(dst.read).to eq('src')
|
27
|
+
end
|
23
28
|
|
24
|
-
|
25
|
-
|
29
|
+
it 'does not remove original file' do
|
30
|
+
src.replace(dst)
|
26
31
|
|
27
|
-
|
28
|
-
|
32
|
+
expect(src).to exist
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'preserves attributes of destination file' do
|
36
|
+
skip 'full file modes are not support' unless any_file_modes_allowed?
|
37
|
+
mode = 0o666
|
38
|
+
|
39
|
+
dst.chmod(mode)
|
40
|
+
|
41
|
+
src.replace(dst)
|
29
42
|
|
30
|
-
|
31
|
-
|
32
|
-
|
43
|
+
got = dst.stat.mode & 0o777
|
44
|
+
expect(got).to eq(mode), format('expected %04o, got %04o', mode, got)
|
45
|
+
end
|
33
46
|
|
34
|
-
|
47
|
+
it 'does not preserve mtime of destination file' do
|
48
|
+
time = src.mtime
|
35
49
|
|
36
|
-
|
50
|
+
dst.utime(time - 1000, time - 1000)
|
37
51
|
|
38
|
-
|
39
|
-
|
52
|
+
src.replace(dst)
|
53
|
+
|
54
|
+
expect(dst.mtime).to be >= time
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'changes inode of destination' do
|
58
|
+
skip 'inodes are not supported' unless inodes_supported?
|
59
|
+
expect{ src.replace(dst) }.to change{ dst.stat.ino }
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'is using temporary file with .tmp extension' do
|
63
|
+
expect(src).to receive(:copy).with(having_attributes(:extname => '.tmp')).at_least(:once)
|
64
|
+
|
65
|
+
src.replace(dst)
|
66
|
+
end
|
40
67
|
end
|
41
68
|
|
42
|
-
|
43
|
-
|
69
|
+
context 'when src and dst are on same device' do
|
70
|
+
before do
|
71
|
+
allow_any_instance_of(File::Stat).to receive(:dev).and_return(0)
|
72
|
+
end
|
44
73
|
|
45
|
-
|
74
|
+
include_examples 'replaces file'
|
75
|
+
end
|
46
76
|
|
47
|
-
|
77
|
+
context 'when src and dst are on different devices' do
|
78
|
+
before do
|
79
|
+
allow_any_instance_of(File::Stat).to receive(:dev, &:__id__)
|
80
|
+
end
|
48
81
|
|
49
|
-
|
82
|
+
include_examples 'replaces file'
|
50
83
|
end
|
51
84
|
|
52
|
-
|
53
|
-
|
54
|
-
|
85
|
+
context 'when src and dst are on same device, but rename causes Errno::EXDEV' do
|
86
|
+
before do
|
87
|
+
allow_any_instance_of(File::Stat).to receive(:dev).and_return(0)
|
88
|
+
allow(described_class).to receive(:temp_file_path).and_call_original
|
89
|
+
expect(described_class).to receive(:temp_file_path).
|
90
|
+
with([dst.basename.to_s, '.tmp'], src.dirname).
|
91
|
+
and_wrap_original do |m, *args, &block|
|
92
|
+
m.call(*args) do |tmp|
|
93
|
+
expect(tmp).to receive(:rename).with(dst.to_s).and_raise(Errno::EXDEV)
|
94
|
+
block.call(tmp)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
include_examples 'replaces file'
|
55
100
|
end
|
56
101
|
end
|
57
102
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
require 'fspath'
|
3
5
|
require 'image_optim/cache'
|
@@ -62,6 +64,7 @@ describe ImageOptim::Cache do
|
|
62
64
|
end
|
63
65
|
end
|
64
66
|
|
67
|
+
# rubocop:disable Style/RedundantFetchBlock
|
65
68
|
shared_examples 'an enabled cache' do
|
66
69
|
context 'when cached file does not exist' do
|
67
70
|
describe :fetch do
|
@@ -99,7 +102,7 @@ describe ImageOptim::Cache do
|
|
99
102
|
expect(FileUtils).not_to receive(:mv)
|
100
103
|
expect(File).not_to receive(:rename)
|
101
104
|
|
102
|
-
expect(cache.fetch(original){}).to eq(cached)
|
105
|
+
expect(cache.fetch(original){ nil }).to eq(cached)
|
103
106
|
end
|
104
107
|
|
105
108
|
it 'returns nil when file is already optimized' do
|
@@ -114,6 +117,7 @@ describe ImageOptim::Cache do
|
|
114
117
|
end
|
115
118
|
end
|
116
119
|
end
|
120
|
+
# rubocop:enable Style/RedundantFetchBlock
|
117
121
|
|
118
122
|
context 'when cache is enabled (without worker digests)' do
|
119
123
|
let(:image_optim) do
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
require 'image_optim/path'
|
3
5
|
require 'tempfile'
|
@@ -59,45 +61,84 @@ describe ImageOptim::Path do
|
|
59
61
|
let(:src){ Path.temp_file_path }
|
60
62
|
let(:dst){ Path.temp_file_path }
|
61
63
|
|
62
|
-
|
63
|
-
|
64
|
+
shared_examples 'replaces file' do
|
65
|
+
it 'moves data to destination' do
|
66
|
+
src.write('src')
|
64
67
|
|
65
|
-
|
68
|
+
src.replace(dst)
|
66
69
|
|
67
|
-
|
68
|
-
|
70
|
+
expect(dst.read).to eq('src')
|
71
|
+
end
|
69
72
|
|
70
|
-
|
71
|
-
|
73
|
+
it 'removes original file' do
|
74
|
+
src.replace(dst)
|
72
75
|
|
73
|
-
|
74
|
-
|
76
|
+
expect(src).to_not exist
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'preserves attributes of destination file' do
|
80
|
+
skip 'full file modes are not support' unless any_file_modes_allowed?
|
81
|
+
mode = 0o666
|
82
|
+
|
83
|
+
dst.chmod(mode)
|
84
|
+
|
85
|
+
src.replace(dst)
|
86
|
+
|
87
|
+
got = dst.stat.mode & 0o777
|
88
|
+
expect(got).to eq(mode), format('expected %04o, got %04o', mode, got)
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'does not preserve mtime of destination file' do
|
92
|
+
time = src.mtime
|
93
|
+
|
94
|
+
dst.utime(time - 1000, time - 1000)
|
75
95
|
|
76
|
-
|
77
|
-
skip 'full file modes are not support' unless any_file_modes_allowed?
|
78
|
-
mode = 0o666
|
96
|
+
src.replace(dst)
|
79
97
|
|
80
|
-
|
98
|
+
expect(dst.mtime).to be >= time
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'changes inode of destination' do
|
102
|
+
skip 'inodes are not supported' unless inodes_supported?
|
103
|
+
expect{ src.replace(dst) }.to change{ dst.stat.ino }
|
104
|
+
end
|
105
|
+
end
|
81
106
|
|
82
|
-
|
107
|
+
context 'when src and dst are on same device' do
|
108
|
+
before do
|
109
|
+
allow_any_instance_of(File::Stat).to receive(:dev).and_return(0)
|
110
|
+
end
|
83
111
|
|
84
|
-
|
85
|
-
expect(got).to eq(mode), format('expected %04o, got %04o', mode, got)
|
112
|
+
include_examples 'replaces file'
|
86
113
|
end
|
87
114
|
|
88
|
-
|
89
|
-
|
115
|
+
context 'when src and dst are on different devices' do
|
116
|
+
before do
|
117
|
+
allow_any_instance_of(File::Stat).to receive(:dev, &:__id__)
|
118
|
+
end
|
90
119
|
|
91
|
-
|
120
|
+
include_examples 'replaces file'
|
92
121
|
|
93
|
-
|
122
|
+
it 'is using temporary file with .tmp extension' do
|
123
|
+
expect(src).to receive(:move).with(having_attributes(:extname => '.tmp'))
|
94
124
|
|
95
|
-
|
125
|
+
src.replace(dst)
|
126
|
+
end
|
96
127
|
end
|
97
128
|
|
98
|
-
|
99
|
-
|
100
|
-
|
129
|
+
context 'when src and dst are on same device, but rename causes Errno::EXDEV' do
|
130
|
+
before do
|
131
|
+
allow_any_instance_of(File::Stat).to receive(:dev).and_return(0)
|
132
|
+
expect(src).to receive(:rename).with(dst.to_s).once.and_raise(Errno::EXDEV)
|
133
|
+
end
|
134
|
+
|
135
|
+
include_examples 'replaces file'
|
136
|
+
|
137
|
+
it 'is using temporary file with .tmp extension' do
|
138
|
+
expect(src).to receive(:move).with(having_attributes(:extname => '.tmp'))
|
139
|
+
|
140
|
+
src.replace(dst)
|
141
|
+
end
|
101
142
|
end
|
102
143
|
end
|
103
144
|
end
|
@@ -1,20 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
require 'image_optim/space'
|
3
5
|
|
4
6
|
describe ImageOptim::Space do
|
5
7
|
describe '.space' do
|
6
8
|
{
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
}.each do |
|
9
|
+
' ' => 0,
|
10
|
+
' 1B' => 1,
|
11
|
+
' 10B' => 10,
|
12
|
+
' 100B' => 100,
|
13
|
+
' 1000B' => 1_000,
|
14
|
+
' 9.8K' => 10_000,
|
15
|
+
' 97.7K' => 100_000,
|
16
|
+
'976.6K' => 1_000_000,
|
17
|
+
' 9.5M' => 10_000_000,
|
18
|
+
' 95.4M' => 100_000_000,
|
19
|
+
}.each do |space, size|
|
18
20
|
it "converts #{size} to #{space}" do
|
19
21
|
expect(described_class.space(size)).to eq(space)
|
20
22
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require 'image_optim/worker/jpegrecompress'
|
5
|
+
|
6
|
+
describe ImageOptim::Worker::Jpegrecompress do
|
7
|
+
describe 'method value' do
|
8
|
+
let(:subject){ described_class.new(ImageOptim.new, method).method }
|
9
|
+
|
10
|
+
context 'default' do
|
11
|
+
let(:method){ {} }
|
12
|
+
|
13
|
+
it{ is_expected.to eq('ssim') }
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'uses default when invalid' do
|
17
|
+
let(:method){ {:method => 'invalid'} }
|
18
|
+
|
19
|
+
it 'warns and keeps default' do
|
20
|
+
expect_any_instance_of(described_class).
|
21
|
+
to receive(:warn).with('Unknown method for jpegrecompress: invalid')
|
22
|
+
is_expected.to eq('ssim')
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'can use a valid option' do
|
27
|
+
let(:method){ {:method => 'smallfry'} }
|
28
|
+
|
29
|
+
it{ is_expected.to eq('smallfry') }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|