image_optim 0.30.0 → 0.31.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/check.yml +59 -0
- data/CHANGELOG.markdown +5 -0
- data/CONTRIBUTING.markdown +1 -1
- data/Gemfile +1 -7
- data/README.markdown +17 -8
- data/image_optim.gemspec +2 -2
- data/lib/image_optim/bin_resolver/bin.rb +1 -1
- data/lib/image_optim/cmd.rb +1 -1
- data/lib/image_optim/config.rb +1 -1
- data/lib/image_optim/runner/option_parser.rb +18 -18
- data/lib/image_optim/runner.rb +1 -1
- data/lib/image_optim/worker/advpng.rb +5 -5
- data/lib/image_optim/worker/gifsicle.rb +8 -8
- data/lib/image_optim/worker/jpegoptim.rb +9 -9
- data/lib/image_optim/worker/jpegrecompress.rb +4 -4
- data/lib/image_optim/worker/jpegtran.rb +1 -1
- data/lib/image_optim/worker/optipng.rb +5 -5
- data/lib/image_optim/worker/oxipng.rb +53 -0
- data/lib/image_optim/worker/pngcrush.rb +4 -4
- data/lib/image_optim/worker/pngout.rb +5 -5
- data/lib/image_optim/worker/pngquant.rb +7 -7
- data/lib/image_optim/worker.rb +3 -3
- data/lib/image_optim.rb +1 -1
- data/script/update_worker_options_in_readme +1 -1
- data/spec/image_optim/cache_path_spec.rb +4 -3
- data/spec/image_optim/cmd_spec.rb +6 -0
- data/spec/image_optim/handler_spec.rb +1 -1
- data/spec/image_optim/path_spec.rb +4 -3
- data/spec/image_optim/worker/oxipng_spec.rb +89 -0
- data/spec/image_optim_spec.rb +1 -1
- data/spec/images/invisiblepixels/generate +1 -1
- data/spec/spec_helper.rb +2 -2
- metadata +10 -7
- data/.travis.yml +0 -48
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e80e82d67e3434476f0bdf332b14b6369601010aaeef7ab7b901515d0c03565c
|
4
|
+
data.tar.gz: 16f304385c879cf1afc0073d7d037fb548d6c260f57e2b94cdcdd974f3cd4b4e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b0395980a804453e3273f779c1217d5dd5b9b7c522e74964070b43f2b3ac433f9f39d5f997a3e9c6594f22d244752910eea1697ac2e570de34e6b0641555b9e8
|
7
|
+
data.tar.gz: 9de0bebe89071d3aa7bd506b02dc684b53d998dcfccab1debad72bdc244e6fbae6eb0ac2d5871359fe2ffa5cb9e7c5ae8a7dc98829e00e8abef49c017ac3b00c
|
@@ -0,0 +1,59 @@
|
|
1
|
+
name: check
|
2
|
+
on:
|
3
|
+
push:
|
4
|
+
pull_request:
|
5
|
+
schedule:
|
6
|
+
- cron: 45 4 * * 2
|
7
|
+
jobs:
|
8
|
+
check:
|
9
|
+
runs-on: ubuntu-latest
|
10
|
+
strategy:
|
11
|
+
matrix:
|
12
|
+
ruby:
|
13
|
+
- '2.0'
|
14
|
+
- '2.1'
|
15
|
+
- '2.2'
|
16
|
+
- '2.3'
|
17
|
+
- '2.4'
|
18
|
+
- '2.5'
|
19
|
+
- '2.6'
|
20
|
+
- '2.7'
|
21
|
+
- '3.0'
|
22
|
+
- jruby-9.2
|
23
|
+
fail-fast: false
|
24
|
+
steps:
|
25
|
+
- uses: actions/checkout@v2
|
26
|
+
- uses: ruby/setup-ruby@v1
|
27
|
+
with:
|
28
|
+
ruby-version: "${{ matrix.ruby }}"
|
29
|
+
bundler-cache: true
|
30
|
+
- run: sudo npm install -g svgo
|
31
|
+
- run: curl -L "https://www.jonof.id.au/files/kenutils/pngout-20200115-linux.tar.gz" | sudo tar -xz -C /usr/local/bin --strip-components 2 --wildcards '*/amd64/pngout'
|
32
|
+
- run: curl -L "https://github.com/shssoichiro/oxipng/releases/download/v4.0.3/oxipng-4.0.3-x86_64-unknown-linux-musl.tar.gz" | tar -xz -C /usr/local/bin --strip-components 1 --wildcards '*oxipng'
|
33
|
+
- run: bundle exec image_optim --info
|
34
|
+
- run: bundle exec rspec
|
35
|
+
coverage:
|
36
|
+
runs-on: ubuntu-latest
|
37
|
+
env:
|
38
|
+
CC_TEST_REPORTER_ID: b433c6540d220a2da0663670c9b260806bafdb3a43c6f22b2e81bfb1f87b12fe
|
39
|
+
steps:
|
40
|
+
- uses: actions/checkout@v2
|
41
|
+
- uses: ruby/setup-ruby@v1
|
42
|
+
with:
|
43
|
+
ruby-version: '3.0'
|
44
|
+
bundler-cache: true
|
45
|
+
- run: sudo npm install -g svgo
|
46
|
+
- run: curl -L "https://www.jonof.id.au/files/kenutils/pngout-20200115-linux.tar.gz" | sudo tar -xz -C /usr/local/bin --strip-components 2 --wildcards '*/amd64/pngout'
|
47
|
+
- run: curl -L "https://github.com/shssoichiro/oxipng/releases/download/v4.0.3/oxipng-4.0.3-x86_64-unknown-linux-musl.tar.gz" | tar -xz -C /usr/local/bin --strip-components 1 --wildcards '*oxipng'
|
48
|
+
- uses: paambaati/codeclimate-action@v2.7.5
|
49
|
+
with:
|
50
|
+
coverageCommand: bundle exec rspec
|
51
|
+
rubocop:
|
52
|
+
runs-on: ubuntu-latest
|
53
|
+
steps:
|
54
|
+
- uses: actions/checkout@v2
|
55
|
+
- uses: ruby/setup-ruby@v1
|
56
|
+
with:
|
57
|
+
ruby-version: '3.0'
|
58
|
+
bundler-cache: true
|
59
|
+
- run: bundle exec rubocop
|
data/CHANGELOG.markdown
CHANGED
@@ -2,6 +2,11 @@
|
|
2
2
|
|
3
3
|
## unreleased
|
4
4
|
|
5
|
+
## v0.31.0 (2021-10-03)
|
6
|
+
|
7
|
+
* Add support for Oxipng [#167](https://github.com/toy/image_optim/issues/167) [#190](https://github.com/toy/image_optim/pull/190) [@oblakeerickson](https://github.com/oblakeerickson)
|
8
|
+
* Fix `TypeError: can't convert ImageOptim::Timer into Float` with Ruby 3 [#194](https://github.com/toy/image_optim/pull/194) [@yahonda](https://github.com/yahonda)
|
9
|
+
|
5
10
|
## v0.30.0 (2021-05-11)
|
6
11
|
|
7
12
|
* Add `timeout` option to restrict maximum time spent on every image [#21](https://github.com/toy/image_optim/issues/21) [#148](https://github.com/toy/image_optim/pull/148) [#149](https://github.com/toy/image_optim/pull/149) [#162](https://github.com/toy/image_optim/pull/162) [#184](https://github.com/toy/image_optim/pull/184) [#189](https://github.com/toy/image_optim/pull/189) [@tgxworld](https://github.com/tgxworld) [@oblakeerickson](https://github.com/oblakeerickson) [@toy](https://github.com/toy)
|
data/CONTRIBUTING.markdown
CHANGED
@@ -11,4 +11,4 @@
|
|
11
11
|
* Rebase on master and squash commits to logical units
|
12
12
|
* Push your branch: `git push origin awesome-changes`
|
13
13
|
* Create pull request
|
14
|
-
* Check if [
|
14
|
+
* Check if [github actions workflow is happy](https://github.com/toy/image_optim_pack/actions/workflows/check.yml)
|
data/Gemfile
CHANGED
@@ -4,14 +4,8 @@ source 'https://rubygems.org'
|
|
4
4
|
|
5
5
|
gemspec
|
6
6
|
|
7
|
-
if ENV['
|
7
|
+
if ENV['CC_TEST_REPORTER_ID']
|
8
8
|
group :test do
|
9
9
|
gem 'simplecov'
|
10
|
-
|
11
|
-
gem 'codeclimate-test-reporter'
|
12
10
|
end
|
13
11
|
end
|
14
|
-
|
15
|
-
if ENV['CHECK_RUBIES']
|
16
|
-
gem 'travis_check_rubies', '~> 0.2'
|
17
|
-
end
|
data/README.markdown
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
[![Gem Version](https://img.shields.io/gem/v/image_optim
|
2
|
-
[![Build Status](https://img.shields.io/
|
3
|
-
[![AppVeyor Status](https://img.shields.io/appveyor/
|
4
|
-
[![Code Climate](https://img.shields.io/codeclimate/maintainability/toy/image_optim
|
5
|
-
[![Code Climate Coverage](https://img.shields.io/codeclimate/
|
6
|
-
[![Depfu](https://
|
7
|
-
[![Inch CI](https://inch-ci.org/github/toy/image_optim.svg?branch=master
|
1
|
+
[![Gem Version](https://img.shields.io/gem/v/image_optim?logo=rubygems)](https://rubygems.org/gems/image_optim)
|
2
|
+
[![Build Status](https://img.shields.io/github/workflow/status/toy/image_optim/check/master?logo=github)](https://github.com/toy/image_optim/actions/workflows/check.yml)
|
3
|
+
[![AppVeyor Status](https://img.shields.io/appveyor/build/toy/image-optim/master?label=windows&logo=appveyor)](https://ci.appveyor.com/project/toy/image-optim)
|
4
|
+
[![Code Climate](https://img.shields.io/codeclimate/maintainability/toy/image_optim?logo=codeclimate)](https://codeclimate.com/github/toy/image_optim)
|
5
|
+
[![Code Climate Coverage](https://img.shields.io/codeclimate/coverage/toy/image_optim?logo=codeclimate)](https://codeclimate.com/github/toy/image_optim)
|
6
|
+
[![Depfu](https://img.shields.io/depfu/toy/image_optim)](https://depfu.com/github/toy/image_optim)
|
7
|
+
[![Inch CI](https://inch-ci.org/github/toy/image_optim.svg?branch=master)](https://inch-ci.org/github/toy/image_optim)
|
8
8
|
|
9
9
|
# image_optim
|
10
10
|
|
@@ -18,6 +18,7 @@ Command line tool and ruby interface to optimize (lossless compress, optionally
|
|
18
18
|
* [jpeg-recompress](https://github.com/danielgtaylor/jpeg-archive#jpeg-recompress)
|
19
19
|
* jpegtran from [Independent JPEG Group's JPEG library](http://www.ijg.org/)
|
20
20
|
* [optipng](http://optipng.sourceforge.net/)
|
21
|
+
* [oxipng](https://github.com/shssoichiro/oxipng)
|
21
22
|
* [pngcrush](http://pmt.sourceforge.net/pngcrush/)
|
22
23
|
* [pngout](http://www.advsys.net/ken/util/pngout.htm)
|
23
24
|
* [pngquant](http://pngquant.org/)
|
@@ -60,7 +61,7 @@ With version:
|
|
60
61
|
|
61
62
|
<!---<update-version>-->
|
62
63
|
```ruby
|
63
|
-
gem 'image_optim', '~> 0.
|
64
|
+
gem 'image_optim', '~> 0.31'
|
64
65
|
```
|
65
66
|
<!---</update-version>-->
|
66
67
|
|
@@ -166,6 +167,14 @@ sudo port install advancecomp gifsicle jhead jpegoptim jpeg optipng pngcrush png
|
|
166
167
|
brew install advancecomp gifsicle jhead jpegoptim jpeg optipng pngcrush pngquant jonof/kenutils/pngout
|
167
168
|
```
|
168
169
|
|
170
|
+
### oxipng installation (optional)
|
171
|
+
|
172
|
+
Unless it is available in your chosen package manager, can be installed using cargo:
|
173
|
+
|
174
|
+
```bash
|
175
|
+
cargo install oxipng
|
176
|
+
```
|
177
|
+
|
169
178
|
### pngout installation (optional)
|
170
179
|
|
171
180
|
If you installed the dependencies via brew, pngout should be installed already. Otherwise, you can install `pngout` by downloading and installing the [binary versions](http://www.jonof.id.au/kenutils).
|
data/image_optim.gemspec
CHANGED
@@ -2,8 +2,8 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = 'image_optim'
|
5
|
-
s.version = '0.
|
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)}
|
5
|
+
s.version = '0.31.0'
|
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, oxipng, pngcrush, pngout, pngquant, svgo)}
|
7
7
|
s.homepage = "https://github.com/toy/#{s.name}"
|
8
8
|
s.authors = ['Ivan Kuchin']
|
9
9
|
s.license = 'MIT'
|
@@ -109,7 +109,7 @@ class ImageOptim
|
|
109
109
|
case name
|
110
110
|
when :advpng
|
111
111
|
capture("#{escaped_path} --version 2> #{Path::NULL}")[/\bv(\d+(\.\d+)+|none)/, 1]
|
112
|
-
when :gifsicle, :jpegoptim, :optipng
|
112
|
+
when :gifsicle, :jpegoptim, :optipng, :oxipng
|
113
113
|
capture("#{escaped_path} --version 2> #{Path::NULL}")[/\d+(\.\d+)+/]
|
114
114
|
when :svgo, :pngquant
|
115
115
|
capture("#{escaped_path} --version 2>&1")[/\A\d+(\.\d+)+/]
|
data/lib/image_optim/cmd.rb
CHANGED
data/lib/image_optim/config.rb
CHANGED
@@ -38,7 +38,7 @@ class ImageOptim
|
|
38
38
|
columns = terminal_columns - 1
|
39
39
|
# 1 for distance between summary and description
|
40
40
|
# 2 for additional indent
|
41
|
-
wrapped_indent = summary_indent + ' ' * (summary_width + 1 + 2)
|
41
|
+
wrapped_indent = summary_indent + (' ' * (summary_width + 1 + 2))
|
42
42
|
wrapped_width = columns - wrapped_indent.length
|
43
43
|
# don't try to wrap if there is too little space for description
|
44
44
|
return text if wrapped_width < 20
|
@@ -84,7 +84,7 @@ ImageOptim::Runner::OptionParser::DEFINE = proc do |op, options|
|
|
84
84
|
ImageOptim::TrueFalseNil.add_to_option_parser(op)
|
85
85
|
ImageOptim::NonNegativeIntegerRange.add_to_option_parser(op)
|
86
86
|
|
87
|
-
op.banner = <<-TEXT.gsub(/^\s*\|/, '')
|
87
|
+
op.banner = <<-TEXT.gsub(/^\s*\|/, '') # rubocop:disable Layout/DotPosition
|
88
88
|
|#{ImageOptim.full_version}
|
89
89
|
|
|
90
90
|
|Usage:
|
@@ -97,29 +97,29 @@ ImageOptim::Runner::OptionParser::DEFINE = proc do |op, options|
|
|
97
97
|
TEXT
|
98
98
|
|
99
99
|
op.on('--config-paths PATH1,PATH2', Array, 'Config paths to use instead of '\
|
100
|
-
|
100
|
+
'default ones') do |paths|
|
101
101
|
options[:config_paths] = paths
|
102
102
|
end
|
103
103
|
|
104
104
|
op.separator nil
|
105
105
|
|
106
106
|
op.on('-r', '-R', '--recursive', 'Recursively scan directories '\
|
107
|
-
|
107
|
+
'for images') do |recursive|
|
108
108
|
options[:recursive] = recursive
|
109
109
|
end
|
110
110
|
|
111
111
|
op.on("--exclude-dir 'GLOB'", 'Glob for excluding directories '\
|
112
|
-
|
112
|
+
'(defaults to .*)') do |glob|
|
113
113
|
options[:exclude_dir_glob] = glob
|
114
114
|
end
|
115
115
|
|
116
116
|
op.on("--exclude-file 'GLOB'", 'Glob for excluding files '\
|
117
|
-
|
117
|
+
'(defaults to .*)') do |glob|
|
118
118
|
options[:exclude_file_glob] = glob
|
119
119
|
end
|
120
120
|
|
121
121
|
op.on("--exclude 'GLOB'", 'Set glob for excluding both directories and '\
|
122
|
-
|
122
|
+
'files') do |glob|
|
123
123
|
options[:exclude_file_glob] = options[:exclude_dir_glob] = glob
|
124
124
|
end
|
125
125
|
|
@@ -130,19 +130,19 @@ ImageOptim::Runner::OptionParser::DEFINE = proc do |op, options|
|
|
130
130
|
end
|
131
131
|
|
132
132
|
op.on('--[no-]threads N', Integer, 'Number of threads or disable '\
|
133
|
-
|
133
|
+
'(defaults to number of processors)') do |threads|
|
134
134
|
options[:threads] = threads
|
135
135
|
end
|
136
136
|
|
137
137
|
op.on('--[no-]nice N', Integer, 'Nice level, priority of all used tools '\
|
138
|
-
|
139
|
-
|
138
|
+
'with higher value meaning lower priority, in range -20..19, negative '\
|
139
|
+
'values can be set only if run by root user (defaults to 10)') do |nice|
|
140
140
|
options[:nice] = nice
|
141
141
|
end
|
142
142
|
|
143
143
|
op.on('--[no-]pack', 'Require image_optim_pack or disable it, '\
|
144
|
-
|
145
|
-
|
144
|
+
'by default image_optim_pack will be used if available, '\
|
145
|
+
'will turn on skip-missing-workers unless explicitly disabled') do |pack|
|
146
146
|
options[:pack] = pack
|
147
147
|
end
|
148
148
|
|
@@ -150,12 +150,12 @@ ImageOptim::Runner::OptionParser::DEFINE = proc do |op, options|
|
|
150
150
|
op.separator ' Caching:'
|
151
151
|
|
152
152
|
op.on('--cache-dir DIR', 'Cache optimized images '\
|
153
|
-
|
153
|
+
'into the specified directory') do |cache_dir|
|
154
154
|
options[:cache_dir] = cache_dir
|
155
155
|
end
|
156
156
|
|
157
157
|
op.on('--cache-worker-digests', 'Cache worker digests '\
|
158
|
-
|
158
|
+
'(updating workers invalidates cache)') do |cache_worker_digests|
|
159
159
|
options[:cache_worker_digests] = cache_worker_digests
|
160
160
|
end
|
161
161
|
|
@@ -163,7 +163,7 @@ ImageOptim::Runner::OptionParser::DEFINE = proc do |op, options|
|
|
163
163
|
op.separator ' Disabling workers:'
|
164
164
|
|
165
165
|
op.on('--[no-]skip-missing-workers', 'Skip workers with missing or '\
|
166
|
-
|
166
|
+
'problematic binaries') do |skip|
|
167
167
|
options[:skip_missing_workers] = skip
|
168
168
|
end
|
169
169
|
|
@@ -178,7 +178,7 @@ ImageOptim::Runner::OptionParser::DEFINE = proc do |op, options|
|
|
178
178
|
op.separator ' Worker options:'
|
179
179
|
|
180
180
|
op.on('--allow-lossy', 'Allow lossy workers and '\
|
181
|
-
|
181
|
+
'optimizations') do |allow_lossy|
|
182
182
|
options[:allow_lossy] = allow_lossy
|
183
183
|
end
|
184
184
|
|
@@ -230,8 +230,8 @@ ImageOptim::Runner::OptionParser::DEFINE = proc do |op, options|
|
|
230
230
|
op.separator ' Common options:'
|
231
231
|
|
232
232
|
op.on_tail('-v', '--verbose', 'Verbose output (show global and worker '\
|
233
|
-
|
234
|
-
|
233
|
+
'config, binary resolution log, information about each tool invocation, '\
|
234
|
+
'backtrace of exception)') do
|
235
235
|
options[:verbose] = true
|
236
236
|
end
|
237
237
|
|
data/lib/image_optim/runner.rb
CHANGED
@@ -9,11 +9,11 @@ class ImageOptim
|
|
9
9
|
class Advpng < Worker
|
10
10
|
LEVEL_OPTION =
|
11
11
|
option(:level, 4, 'Compression level: '\
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
'`0` - don\'t compress, '\
|
13
|
+
'`1` - fast, '\
|
14
|
+
'`2` - normal, '\
|
15
|
+
'`3` - extra, '\
|
16
|
+
'`4` - extreme') do |v|
|
17
17
|
OptionHelpers.limit_with_range(v.to_i, 0..4)
|
18
18
|
end
|
19
19
|
|
@@ -18,19 +18,19 @@ class ImageOptim
|
|
18
18
|
|
19
19
|
INTERLACE_OPTION =
|
20
20
|
option(:interlace, false, TrueFalseNil, 'Interlace: '\
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
21
|
+
'`true` - interlace on, '\
|
22
|
+
'`false` - interlace off, '\
|
23
|
+
'`nil` - as is in original image '\
|
24
|
+
'(defaults to running two instances, one with interlace off and '\
|
25
|
+
'one with on)') do |v|
|
26
26
|
TrueFalseNil.convert(v)
|
27
27
|
end
|
28
28
|
|
29
29
|
LEVEL_OPTION =
|
30
30
|
option(:level, 3, 'Compression level: '\
|
31
|
-
|
32
|
-
|
33
|
-
|
31
|
+
'`1` - light and fast, '\
|
32
|
+
'`2` - normal, '\
|
33
|
+
'`3` - heavy (slower)') do |v|
|
34
34
|
OptionHelpers.limit_with_range(v.to_i, 1..3)
|
35
35
|
end
|
36
36
|
|
@@ -12,13 +12,13 @@ class ImageOptim
|
|
12
12
|
|
13
13
|
STRIP_OPTION =
|
14
14
|
option(:strip, :all, Array, 'List of markers to strip: '\
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
15
|
+
'`:com`, '\
|
16
|
+
'`:exif`, '\
|
17
|
+
'`:iptc`, '\
|
18
|
+
'`:icc`, '\
|
19
|
+
'`:xmp`, '\
|
20
|
+
'`:none` or '\
|
21
|
+
'`:all`') do |v|
|
22
22
|
values = Array(v).map(&:to_s)
|
23
23
|
known_values = %w[com exif iptc icc xmp none all]
|
24
24
|
unknown_values = values - known_values
|
@@ -30,13 +30,13 @@ class ImageOptim
|
|
30
30
|
|
31
31
|
MAX_QUALITY_OPTION =
|
32
32
|
option(:max_quality, 100, 'Maximum image quality factor '\
|
33
|
-
|
33
|
+
'`0`..`100`, ignored in default/lossless mode') do |v, opt_def|
|
34
34
|
if allow_lossy
|
35
35
|
OptionHelpers.limit_with_range(v.to_i, 0..100)
|
36
36
|
else
|
37
37
|
if v != opt_def.default
|
38
38
|
warn "#{self.class.bin_sym} #{opt_def.name} #{v} ignored " \
|
39
|
-
|
39
|
+
'in lossless mode'
|
40
40
|
end
|
41
41
|
opt_def.default
|
42
42
|
end
|
@@ -28,10 +28,10 @@ class ImageOptim
|
|
28
28
|
|
29
29
|
METHOD_OPTION =
|
30
30
|
option(:method, 'ssim', 'Comparison Metric: '\
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
31
|
+
'`mpe` - Mean pixel error, '\
|
32
|
+
'`ssim` - Structural similarity, '\
|
33
|
+
'`ms-ssim` - Multi-scale structural similarity (slow!), '\
|
34
|
+
'`smallfry` - Linear-weighted BBCQ-like (may be patented)') do |v, opt_def|
|
35
35
|
if %w[mpe ssim ms-ssim smallfry].include? v
|
36
36
|
v
|
37
37
|
else
|
@@ -17,7 +17,7 @@ class ImageOptim
|
|
17
17
|
|
18
18
|
JPEGRESCAN_OPTION =
|
19
19
|
option(:jpegrescan, true, 'Use jpegtran through jpegrescan, '\
|
20
|
-
|
20
|
+
'ignore progressive option'){ |v| !!v }
|
21
21
|
|
22
22
|
def used_bins
|
23
23
|
jpegrescan ? [:jpegtran, :jpegrescan] : [:jpegtran]
|
@@ -10,16 +10,16 @@ class ImageOptim
|
|
10
10
|
class Optipng < Worker
|
11
11
|
LEVEL_OPTION =
|
12
12
|
option(:level, 6, 'Optimization level preset: '\
|
13
|
-
|
14
|
-
|
13
|
+
'`0` is least, '\
|
14
|
+
'`7` is best') do |v|
|
15
15
|
OptionHelpers.limit_with_range(v.to_i, 0..7)
|
16
16
|
end
|
17
17
|
|
18
18
|
INTERLACE_OPTION =
|
19
19
|
option(:interlace, false, TrueFalseNil, 'Interlace: '\
|
20
|
-
|
21
|
-
|
22
|
-
|
20
|
+
'`true` - interlace on, '\
|
21
|
+
'`false` - interlace off, '\
|
22
|
+
'`nil` - as is in original image') do |v|
|
23
23
|
TrueFalseNil.convert(v)
|
24
24
|
end
|
25
25
|
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'image_optim/worker'
|
4
|
+
require 'image_optim/option_helpers'
|
5
|
+
require 'image_optim/true_false_nil'
|
6
|
+
|
7
|
+
class ImageOptim
|
8
|
+
class Worker
|
9
|
+
# https://github.com/shssoichiro/oxipng
|
10
|
+
class Oxipng < Worker
|
11
|
+
LEVEL_OPTION =
|
12
|
+
option(:level, 3, 'Optimization level preset: '\
|
13
|
+
'`0` is least, '\
|
14
|
+
'`6` is best') do |v|
|
15
|
+
OptionHelpers.limit_with_range(v.to_i, 0..6)
|
16
|
+
end
|
17
|
+
|
18
|
+
INTERLACE_OPTION =
|
19
|
+
option(:interlace, false, TrueFalseNil, 'Interlace: '\
|
20
|
+
'`true` - interlace on, '\
|
21
|
+
'`false` - interlace off, '\
|
22
|
+
'`nil` - as is in original image') do |v|
|
23
|
+
TrueFalseNil.convert(v)
|
24
|
+
end
|
25
|
+
|
26
|
+
STRIP_OPTION =
|
27
|
+
option(:strip, true, 'Remove all auxiliary chunks'){ |v| !!v }
|
28
|
+
|
29
|
+
def run_order
|
30
|
+
-4
|
31
|
+
end
|
32
|
+
|
33
|
+
def optimize(src, dst, options = {})
|
34
|
+
src.copy(dst)
|
35
|
+
args = %W[
|
36
|
+
-o #{level}
|
37
|
+
--quiet
|
38
|
+
--
|
39
|
+
#{dst}
|
40
|
+
]
|
41
|
+
args.unshift "-i#{interlace ? 1 : 0}" unless interlace.nil?
|
42
|
+
if strip
|
43
|
+
args.unshift '--strip', 'all'
|
44
|
+
end
|
45
|
+
execute(:oxipng, args, options) && optimized?(src, dst)
|
46
|
+
end
|
47
|
+
|
48
|
+
def optimized?(src, dst)
|
49
|
+
interlace ? dst.size? : super
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -8,18 +8,18 @@ class ImageOptim
|
|
8
8
|
class Pngcrush < Worker
|
9
9
|
CHUNKS_OPTION =
|
10
10
|
option(:chunks, :alla, Array, 'List of chunks to remove or '\
|
11
|
-
|
12
|
-
|
11
|
+
'`:alla` - all except tRNS/transparency or '\
|
12
|
+
'`:allb` - all except tRNS and gAMA/gamma') do |v|
|
13
13
|
Array(v).map(&:to_s)
|
14
14
|
end
|
15
15
|
|
16
16
|
FIX_OPTION =
|
17
17
|
option(:fix, false, 'Fix otherwise fatal conditions '\
|
18
|
-
|
18
|
+
'such as bad CRCs'){ |v| !!v }
|
19
19
|
|
20
20
|
BRUTE_OPTION =
|
21
21
|
option(:brute, false, 'Brute force try all methods, '\
|
22
|
-
|
22
|
+
'very time-consuming and generally not worthwhile'){ |v| !!v }
|
23
23
|
|
24
24
|
BLACKEN_OPTION =
|
25
25
|
option(:blacken, true, 'Blacken fully transparent pixels'){ |v| !!v }
|
@@ -12,11 +12,11 @@ class ImageOptim
|
|
12
12
|
|
13
13
|
STRATEGY_OPTION =
|
14
14
|
option(:strategy, 0, 'Strategy: '\
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
15
|
+
'`0` - xtreme, '\
|
16
|
+
'`1` - intense, '\
|
17
|
+
'`2` - longest Match, '\
|
18
|
+
'`3` - huffman Only, '\
|
19
|
+
'`4` - uncompressed') do |v|
|
20
20
|
OptionHelpers.limit_with_range(v.to_i, 0..4)
|
21
21
|
end
|
22
22
|
|
@@ -19,9 +19,9 @@ class ImageOptim
|
|
19
19
|
QUALITY_OPTION =
|
20
20
|
option(:quality, '`100..100`, `0..100` in lossy mode',
|
21
21
|
NonNegativeIntegerRange, 'min..max - don\'t '\
|
22
|
-
|
23
|
-
|
24
|
-
|
22
|
+
'save below min, use less colors below max (both in range `0..100`; '\
|
23
|
+
'in yaml - `!ruby/range 0..100`), ignored in default/lossless '\
|
24
|
+
'mode') do |v, opt_def|
|
25
25
|
if allow_lossy
|
26
26
|
if v == opt_def.default
|
27
27
|
0..100
|
@@ -32,7 +32,7 @@ class ImageOptim
|
|
32
32
|
else
|
33
33
|
if v != opt_def.default
|
34
34
|
warn "#{self.class.bin_sym} #{opt_def.name} #{v} ignored " \
|
35
|
-
|
35
|
+
'in lossless mode'
|
36
36
|
end
|
37
37
|
100..100
|
38
38
|
end
|
@@ -40,9 +40,9 @@ class ImageOptim
|
|
40
40
|
|
41
41
|
SPEED_OPTION =
|
42
42
|
option(:speed, 3, 'speed/quality trade-off: '\
|
43
|
-
|
44
|
-
|
45
|
-
|
43
|
+
'`1` - slow, '\
|
44
|
+
'`3` - default, '\
|
45
|
+
'`11` - fast & rough') do |v|
|
46
46
|
OptionHelpers.limit_with_range(v.to_i, 1..11)
|
47
47
|
end
|
48
48
|
|
data/lib/image_optim/worker.rb
CHANGED
@@ -105,7 +105,7 @@ class ImageOptim
|
|
105
105
|
return if unknown_options.empty?
|
106
106
|
|
107
107
|
fail ConfigurationError, "unknown options #{unknown_options.inspect} "\
|
108
|
-
|
108
|
+
"for #{self}"
|
109
109
|
end
|
110
110
|
|
111
111
|
# Forward bin resolving to image_optim
|
@@ -118,8 +118,8 @@ class ImageOptim
|
|
118
118
|
def wrap_resolver_error_message(message)
|
119
119
|
name = self.class.bin_sym
|
120
120
|
"#{name} worker: #{message}; please provide proper binary or "\
|
121
|
-
|
122
|
-
|
121
|
+
"disable this worker (--no-#{name} argument or "\
|
122
|
+
"`:#{name} => false` through options)"
|
123
123
|
end
|
124
124
|
|
125
125
|
# Run command setting priority and hiding output
|
data/lib/image_optim.rb
CHANGED
@@ -29,7 +29,7 @@ end
|
|
29
29
|
def write_marked(io)
|
30
30
|
io.puts BEGIN_MARKER
|
31
31
|
io.puts '<!-- markdown for worker options is generated by '\
|
32
|
-
|
32
|
+
"`#{Pathname($PROGRAM_NAME).cleanpath}` -->"
|
33
33
|
io.puts
|
34
34
|
|
35
35
|
ImageOptim::Worker.klasses.sort_by(&:name).each do |klass|
|
@@ -42,13 +42,14 @@ describe ImageOptim::CachePath do
|
|
42
42
|
end
|
43
43
|
|
44
44
|
it 'does not preserve mtime of destination file' do
|
45
|
-
time = src.mtime
|
45
|
+
time = src.mtime - 1000
|
46
|
+
dst.utime(time, time)
|
46
47
|
|
47
|
-
|
48
|
+
time = dst.mtime
|
48
49
|
|
49
50
|
src.replace(dst)
|
50
51
|
|
51
|
-
expect(dst.mtime).
|
52
|
+
expect(dst.mtime).to_not eq(time)
|
52
53
|
end
|
53
54
|
|
54
55
|
it 'changes inode of destination', skip: SkipConditions[:inodes_support] do
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'spec_helper'
|
4
4
|
require 'image_optim/cmd'
|
5
|
+
require 'image_optim/timer'
|
5
6
|
|
6
7
|
describe ImageOptim::Cmd do
|
7
8
|
before do
|
@@ -48,6 +49,11 @@ describe ImageOptim::Cmd do
|
|
48
49
|
expect(Cmd.run('sh -c "exit 66"', timeout: 1)).to eq(false)
|
49
50
|
end
|
50
51
|
|
52
|
+
it 'returns process success status when timeout is instance of ImageOptim::Timer' do
|
53
|
+
timeout = ImageOptim::Timer.new(1.0)
|
54
|
+
expect(Cmd.run('sh -c "exit 0"', timeout: timeout)).to eq(true)
|
55
|
+
end
|
56
|
+
|
51
57
|
it 'raises SignalException if process terminates after signal', skip: SkipConditions[:signals_support] do
|
52
58
|
expect_int_exception do
|
53
59
|
Cmd.run('kill -s INT $$', timeout: 1)
|
@@ -9,7 +9,7 @@ describe ImageOptim::Handler do
|
|
9
9
|
end
|
10
10
|
|
11
11
|
it 'uses original as source for first conversion '\
|
12
|
-
|
12
|
+
'and two temp files for further conversions' do
|
13
13
|
original = double(:original)
|
14
14
|
allow(original).to receive(:respond_to?).with(:temp_path).and_return(true)
|
15
15
|
|
@@ -86,13 +86,14 @@ describe ImageOptim::Path do
|
|
86
86
|
end
|
87
87
|
|
88
88
|
it 'does not preserve mtime of destination file' do
|
89
|
-
time = src.mtime
|
89
|
+
time = src.mtime - 1000
|
90
|
+
dst.utime(time, time)
|
90
91
|
|
91
|
-
|
92
|
+
time = dst.mtime
|
92
93
|
|
93
94
|
src.replace(dst)
|
94
95
|
|
95
|
-
expect(dst.mtime).
|
96
|
+
expect(dst.mtime).to_not eq(time)
|
96
97
|
end
|
97
98
|
|
98
99
|
it 'changes inode of destination', skip: SkipConditions[:inodes_support] do
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require 'image_optim/worker/oxipng'
|
5
|
+
require 'image_optim/path'
|
6
|
+
|
7
|
+
describe ImageOptim::Worker::Oxipng do
|
8
|
+
describe 'strip option' do
|
9
|
+
subject{ described_class.new(ImageOptim.new, options) }
|
10
|
+
|
11
|
+
let(:options){ {} }
|
12
|
+
let(:src){ instance_double(ImageOptim::Path, copy: nil) }
|
13
|
+
let(:dst){ instance_double(ImageOptim::Path) }
|
14
|
+
|
15
|
+
before do
|
16
|
+
oxipng_bin = instance_double(ImageOptim::BinResolver::Bin)
|
17
|
+
allow(subject).to receive(:resolve_bin!).
|
18
|
+
with(:oxipng).and_return(oxipng_bin)
|
19
|
+
|
20
|
+
allow(subject).to receive(:optimized?)
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'by default' do
|
24
|
+
it 'should add --strip all to arguments' do
|
25
|
+
expect(subject).to receive(:execute) do |_bin, *args|
|
26
|
+
expect(args.join(' ')).to match(/(^| )--strip all($| )/)
|
27
|
+
end
|
28
|
+
|
29
|
+
subject.optimize(src, dst)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'when strip is disabled' do
|
34
|
+
let(:options){ {strip: false} }
|
35
|
+
|
36
|
+
it 'should not add --strip all to arguments' do
|
37
|
+
expect(subject).to receive(:execute) do |_bin, *args|
|
38
|
+
expect(args.join(' ')).not_to match(/(^| )--strip all($| )/)
|
39
|
+
end
|
40
|
+
|
41
|
+
subject.optimize(src, dst)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe '#optimized?' do
|
47
|
+
let(:src){ instance_double(ImageOptim::Path, src_options) }
|
48
|
+
let(:dst){ instance_double(ImageOptim::Path, dst_options) }
|
49
|
+
let(:src_options){ {size: 10} }
|
50
|
+
let(:dst_options){ {size?: 9} }
|
51
|
+
let(:instance){ described_class.new(ImageOptim.new, instance_options) }
|
52
|
+
let(:instance_options){ {} }
|
53
|
+
|
54
|
+
subject{ instance.optimized?(src, dst) }
|
55
|
+
|
56
|
+
context 'when interlace option is enabled' do
|
57
|
+
let(:instance_options){ {interlace: true} }
|
58
|
+
|
59
|
+
context 'when dst is empty' do
|
60
|
+
let(:dst_options){ {size?: nil} }
|
61
|
+
it{ is_expected.to be_falsy }
|
62
|
+
end
|
63
|
+
|
64
|
+
context 'when dst is not empty' do
|
65
|
+
let(:dst_options){ {size?: 20} }
|
66
|
+
it{ is_expected.to be_truthy }
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context 'when interlace option is disabled' do
|
71
|
+
let(:instance_options){ {interlace: false} }
|
72
|
+
|
73
|
+
context 'when dst is empty' do
|
74
|
+
let(:dst_options){ {size?: nil} }
|
75
|
+
it{ is_expected.to be_falsy }
|
76
|
+
end
|
77
|
+
|
78
|
+
context 'when dst is greater than or equal to src' do
|
79
|
+
let(:dst_options){ {size?: 10} }
|
80
|
+
it{ is_expected.to be_falsy }
|
81
|
+
end
|
82
|
+
|
83
|
+
context 'when dst is less than src' do
|
84
|
+
let(:dst_options){ {size?: 9} }
|
85
|
+
it{ is_expected.to be_truthy }
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
data/spec/image_optim_spec.rb
CHANGED
@@ -253,7 +253,7 @@ describe ImageOptim do
|
|
253
253
|
|
254
254
|
describe 'given block' do
|
255
255
|
it 'optimizes images, yields path and result for each and '\
|
256
|
-
|
256
|
+
'returns array of yield results' do
|
257
257
|
image_optim = ImageOptim.new
|
258
258
|
results = test_images.map do |src|
|
259
259
|
dst = double
|
@@ -17,7 +17,7 @@ IO.popen(%W[
|
|
17
17
|
].shelljoin, 'w') do |f|
|
18
18
|
side.times do |a|
|
19
19
|
side.times do |b|
|
20
|
-
alpha = [0, 1, 0x7f, 0xff][(a / 8 + b / 8) % 4]
|
20
|
+
alpha = [0, 1, 0x7f, 0xff][((a / 8) + (b / 8)) % 4]
|
21
21
|
f << [rand(256), rand(256), rand(256), alpha].pack('C*')
|
22
22
|
end
|
23
23
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
if ENV['
|
3
|
+
if ENV['CC_TEST_REPORTER_ID']
|
4
4
|
require 'simplecov'
|
5
5
|
SimpleCov.start
|
6
6
|
end
|
@@ -71,7 +71,7 @@ RSpec::Matchers.define :be_similar_to do |expected, max_difference|
|
|
71
71
|
end
|
72
72
|
failure_message do |actual|
|
73
73
|
"expected #{actual} to have at most #{max_difference} difference from "\
|
74
|
-
|
74
|
+
"#{expected}, got normalized root-mean-square error of #{@diff}"
|
75
75
|
end
|
76
76
|
end
|
77
77
|
|
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.31.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: 2021-
|
11
|
+
date: 2021-10-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: fspath
|
@@ -168,10 +168,10 @@ extensions: []
|
|
168
168
|
extra_rdoc_files: []
|
169
169
|
files:
|
170
170
|
- ".appveyor.yml"
|
171
|
+
- ".github/workflows/check.yml"
|
171
172
|
- ".gitignore"
|
172
173
|
- ".pre-commit-hooks.yaml"
|
173
174
|
- ".rubocop.yml"
|
174
|
-
- ".travis.yml"
|
175
175
|
- CHANGELOG.markdown
|
176
176
|
- CONTRIBUTING.markdown
|
177
177
|
- Gemfile
|
@@ -216,6 +216,7 @@ files:
|
|
216
216
|
- lib/image_optim/worker/jpegrecompress.rb
|
217
217
|
- lib/image_optim/worker/jpegtran.rb
|
218
218
|
- lib/image_optim/worker/optipng.rb
|
219
|
+
- lib/image_optim/worker/oxipng.rb
|
219
220
|
- lib/image_optim/worker/pngcrush.rb
|
220
221
|
- lib/image_optim/worker/pngout.rb
|
221
222
|
- lib/image_optim/worker/pngquant.rb
|
@@ -246,6 +247,7 @@ files:
|
|
246
247
|
- spec/image_optim/timer_spec.rb
|
247
248
|
- spec/image_optim/worker/jpegrecompress_spec.rb
|
248
249
|
- spec/image_optim/worker/optipng_spec.rb
|
250
|
+
- spec/image_optim/worker/oxipng_spec.rb
|
249
251
|
- spec/image_optim/worker/pngquant_spec.rb
|
250
252
|
- spec/image_optim/worker_spec.rb
|
251
253
|
- spec/image_optim_spec.rb
|
@@ -284,7 +286,7 @@ licenses:
|
|
284
286
|
metadata:
|
285
287
|
bug_tracker_uri: https://github.com/toy/image_optim/issues
|
286
288
|
changelog_uri: https://github.com/toy/image_optim/blob/master/CHANGELOG.markdown
|
287
|
-
documentation_uri: https://www.rubydoc.info/gems/image_optim/0.
|
289
|
+
documentation_uri: https://www.rubydoc.info/gems/image_optim/0.31.0
|
288
290
|
source_code_uri: https://github.com/toy/image_optim
|
289
291
|
post_install_message: |
|
290
292
|
Rails image assets optimization is extracted into image_optim_rails gem
|
@@ -303,13 +305,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
303
305
|
- !ruby/object:Gem::Version
|
304
306
|
version: '0'
|
305
307
|
requirements: []
|
306
|
-
rubygems_version: 3.2.
|
308
|
+
rubygems_version: 3.2.28
|
307
309
|
signing_key:
|
308
310
|
specification_version: 4
|
309
311
|
summary: Command line tool and ruby interface to optimize (lossless compress, optionally
|
310
312
|
lossy) jpeg, png, gif and svg images using external utilities (advpng, gifsicle,
|
311
|
-
jhead, jpeg-recompress, jpegoptim, jpegrescan, jpegtran, optipng,
|
312
|
-
pngquant, svgo)
|
313
|
+
jhead, jpeg-recompress, jpegoptim, jpegrescan, jpegtran, optipng, oxipng, pngcrush,
|
314
|
+
pngout, pngquant, svgo)
|
313
315
|
test_files:
|
314
316
|
- spec/image_optim/bin_resolver/comparable_condition_spec.rb
|
315
317
|
- spec/image_optim/bin_resolver/simple_version_spec.rb
|
@@ -332,6 +334,7 @@ test_files:
|
|
332
334
|
- spec/image_optim/timer_spec.rb
|
333
335
|
- spec/image_optim/worker/jpegrecompress_spec.rb
|
334
336
|
- spec/image_optim/worker/optipng_spec.rb
|
337
|
+
- spec/image_optim/worker/oxipng_spec.rb
|
335
338
|
- spec/image_optim/worker/pngquant_spec.rb
|
336
339
|
- spec/image_optim/worker_spec.rb
|
337
340
|
- spec/image_optim_spec.rb
|
data/.travis.yml
DELETED
@@ -1,48 +0,0 @@
|
|
1
|
-
dist: xenial
|
2
|
-
language: ruby
|
3
|
-
cache:
|
4
|
-
bundler: true
|
5
|
-
directories:
|
6
|
-
- $(npm root)
|
7
|
-
- ~/bin
|
8
|
-
rvm:
|
9
|
-
- '1.9.3-p551'
|
10
|
-
- '2.0.0-p648'
|
11
|
-
- '2.1.10'
|
12
|
-
- '2.2.10'
|
13
|
-
- '2.3.8'
|
14
|
-
- '2.4.10'
|
15
|
-
- '2.5.9'
|
16
|
-
- '2.6.7'
|
17
|
-
- '2.7.3'
|
18
|
-
- '3.0.1'
|
19
|
-
- 'jruby-9.2.14.0'
|
20
|
-
script:
|
21
|
-
- bundle exec image_optim --info
|
22
|
-
- bundle exec rspec
|
23
|
-
before_install:
|
24
|
-
- 'echo "gem: --no-ri --no-rdoc --no-document" > ~/.gemrc'
|
25
|
-
- gem install rubygems-update || gem install rubygems-update --version '< 3'
|
26
|
-
- update_rubygems
|
27
|
-
- gem install bundler || gem install bundler --version '< 2'
|
28
|
-
- nvm install stable
|
29
|
-
- command -v svgo || npm install -g svgo
|
30
|
-
- mkdir -p ~/bin
|
31
|
-
- command -v pngout || curl -L "https://www.jonof.id.au/files/kenutils/pngout-20200115-linux.tar.gz" | tar -xz -C ~/bin --strip-components 2 --wildcards '*/amd64/pngout'
|
32
|
-
matrix:
|
33
|
-
include:
|
34
|
-
- env: CODECLIMATE=1
|
35
|
-
rvm: '2.4.10'
|
36
|
-
after_success: bundle exec codeclimate-test-reporter
|
37
|
-
- env: RUBOCOP=1
|
38
|
-
rvm: '2.4.10'
|
39
|
-
script: bundle exec rubocop
|
40
|
-
before_install: gem update --system && gem install bundler
|
41
|
-
- env: CHECK_RUBIES=1
|
42
|
-
rvm: '2.4.10'
|
43
|
-
script: bundle exec travis_check_rubies
|
44
|
-
before_install: gem update --system && gem install bundler
|
45
|
-
addons:
|
46
|
-
code_climate:
|
47
|
-
repo_token:
|
48
|
-
secure: FDikT3JnOJHOAFSaKwVPB1VOphU0sSzAnzQ+YjSt9XFE+9uFQHth/j4rFoVoqALhCj+47trv6spwkbcSjGCVzm+87OI80GkLCCzNjDOz2W4sP9JWItVgS1VoWW+ioPxpLgpguTb3wutwKOUMEAf+40EX657ZiHumM7nNHrF+RCU=
|