image_optim 0.15.0 → 0.16.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 +12 -9
- data/.travis.yml +17 -7
- data/CHANGELOG.markdown +209 -0
- data/CONTRIBUTING.markdown +1 -0
- data/Gemfile +1 -1
- data/README.markdown +7 -1
- data/bin/image_optim +16 -1
- data/image_optim.gemspec +8 -8
- data/lib/image_optim.rb +22 -6
- data/lib/image_optim/bin_resolver.rb +22 -4
- data/lib/image_optim/config.rb +14 -8
- data/lib/image_optim/runner.rb +35 -7
- data/lib/image_optim/runner/glob_helpers.rb +45 -0
- data/lib/image_optim/worker.rb +44 -4
- data/lib/image_optim/worker/jhead.rb +4 -0
- data/lib/image_optim/worker/jpegtran.rb +4 -0
- data/spec/image_optim/bin_resolver_spec.rb +22 -8
- data/spec/image_optim/config_spec.rb +51 -32
- data/spec/image_optim/runner/glob_helpers_spec.rb +24 -0
- data/spec/image_optim/worker_spec.rb +3 -4
- data/spec/image_optim_spec.rb +3 -1
- metadata +30 -8
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
MDE1MjA4Yzc2MDkwZWM5YjgwNmJhZDVmMzM5MzI5NTU2ZjY3YWViZA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
NTMxMjc5YTI1ZmEzYzA1YTYwMWYwNWU4YzM3ODA0YTMwNDAyZDc3MQ==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
YWM3ZmNmMzk0NWE4YTI0NTQxNDI1YzEyM2YxNzM3ZjlhMmM3NWIwMTQwYjE5
|
10
|
+
NGIwYzJiZDk3MzhlMGJkOWQ5Y2NkYzc3OWEyMGMyZGQ5YzEyNzJkOGRhODgy
|
11
|
+
NmRkNzBkMTQ0N2M3YTc3YWU2OTI0MzAxM2MyMDZmMzliMjljNDM=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
MjEyYWRhNDA3OTZkMTM2NWNiYTc5MzI2MDEyYzQ4ZDBlYzcyNzU4MjkxODY0
|
14
|
+
MTVjZjdjYjIyMWRhYTIzY2ZiMTA0ZDM3N2U2YzAyZDllM2M5Y2NkNWI5YWQw
|
15
|
+
OGRhYmFmZGU5ZWVlNWIzZjYzMmJkNDI3ODM1NTg0NWY3NDdhODM=
|
data/.rubocop.yml
CHANGED
@@ -5,18 +5,24 @@ AllCops:
|
|
5
5
|
Lint/EndAlignment:
|
6
6
|
AlignWith: variable
|
7
7
|
|
8
|
+
Metrics/ClassLength:
|
9
|
+
Max: 150
|
10
|
+
|
11
|
+
Metrics/CyclomaticComplexity:
|
12
|
+
Max: 10
|
13
|
+
|
14
|
+
Metrics/MethodLength:
|
15
|
+
Max: 20
|
16
|
+
|
17
|
+
Metrics/PerceivedComplexity:
|
18
|
+
Max: 8
|
19
|
+
|
8
20
|
Style/AccessModifierIndentation:
|
9
21
|
EnforcedStyle: outdent
|
10
22
|
|
11
23
|
Style/CaseIndentation:
|
12
24
|
IndentWhenRelativeTo: end
|
13
25
|
|
14
|
-
Style/ClassLength:
|
15
|
-
Max: 120
|
16
|
-
|
17
|
-
Style/CyclomaticComplexity:
|
18
|
-
Max: 8
|
19
|
-
|
20
26
|
Style/DotPosition:
|
21
27
|
EnforcedStyle: trailing
|
22
28
|
|
@@ -35,9 +41,6 @@ Style/IfUnlessModifier:
|
|
35
41
|
Style/IndentHash:
|
36
42
|
EnforcedStyle: consistent
|
37
43
|
|
38
|
-
Style/MethodLength:
|
39
|
-
Max: 20
|
40
|
-
|
41
44
|
Style/PercentLiteralDelimiters:
|
42
45
|
PreferredDelimiters:
|
43
46
|
'%w': '[]'
|
data/.travis.yml
CHANGED
@@ -16,17 +16,27 @@ script:
|
|
16
16
|
- '! bundle show rubocop || bundle exec rubocop' # run rubocop only if it is bundled
|
17
17
|
before_install:
|
18
18
|
- sudo apt-get update -qq
|
19
|
-
- sudo apt-get install -qq
|
19
|
+
- sudo apt-get install -qq gifsicle jhead jpegoptim libjpeg-progs optipng pngcrush
|
20
20
|
- npm install -g svgo
|
21
21
|
- mkdir ~/bin
|
22
|
-
|
22
|
+
|
23
|
+
- echo 'Installing advancecomp(advpng):'
|
24
|
+
- ADVANCECOMP_VERSION=1.19
|
25
|
+
- wget http://downloads.sourceforge.net/project/advancemame/advancecomp/$ADVANCECOMP_VERSION/advancecomp-$ADVANCECOMP_VERSION.tar.gz
|
26
|
+
- tar -xzf advancecomp-$ADVANCECOMP_VERSION.tar.gz
|
27
|
+
- (cd advancecomp-$ADVANCECOMP_VERSION && ./configure && make)
|
28
|
+
- mv advancecomp-$ADVANCECOMP_VERSION/advpng ~/bin
|
29
|
+
|
30
|
+
- echo 'Installing pngquant:'
|
23
31
|
- git clone git://github.com/pornel/pngquant.git
|
24
|
-
-
|
32
|
+
- (cd pngquant && git checkout $(git describe --tags --abbrev=0) && make)
|
25
33
|
- mv pngquant/pngquant ~/bin
|
26
|
-
|
27
|
-
-
|
28
|
-
-
|
29
|
-
-
|
34
|
+
|
35
|
+
- echo 'Installing pngout:'
|
36
|
+
- PNGOUT_VERSION=20130221
|
37
|
+
- wget http://static.jonof.id.au/dl/kenutils/pngout-$PNGOUT_VERSION-linux.tar.gz
|
38
|
+
- tar -xzf pngout-$PNGOUT_VERSION-linux.tar.gz
|
39
|
+
- mv pngout-$PNGOUT_VERSION-linux/x86_64/pngout ~/bin
|
30
40
|
env:
|
31
41
|
- PATH=~/bin:$PATH
|
32
42
|
matrix:
|
data/CHANGELOG.markdown
ADDED
@@ -0,0 +1,209 @@
|
|
1
|
+
# ChangeLog
|
2
|
+
|
3
|
+
## unreleased
|
4
|
+
|
5
|
+
## v0.16.0 (2014-09-12)
|
6
|
+
|
7
|
+
* Wrote this ChangeLog [#62](https://github.com/toy/image_optim/issues/62) [@toy](https://github.com/toy)
|
8
|
+
* Use rubocop ~> 0.26.0 [@toy](https://github.com/toy)
|
9
|
+
* Install advancecomp from source in travis script [#61](https://github.com/toy/image_optim/issues/61) [@toy](https://github.com/toy)
|
10
|
+
* Move expansion of config path to read method and rescue with warning [#58](https://github.com/toy/image_optim/issues/58) [@toy](https://github.com/toy)
|
11
|
+
* Show workers options in verbose mode [#56](https://github.com/toy/image_optim/issues/56) [@toy](https://github.com/toy)
|
12
|
+
* Resolve all bins during initialization [#22](https://github.com/toy/image_optim/issues/22) [@toy](https://github.com/toy)
|
13
|
+
* Add exclusion glob patterns, `.*` by default [#35](https://github.com/toy/image_optim/issues/35) [#48](https://github.com/toy/image_optim/issues/48) [@toy](https://github.com/toy)
|
14
|
+
* Show better warning when running image_optim for a directory without recursive option [@toy](https://github.com/toy)
|
15
|
+
* Use stable sort for workers [@toy](https://github.com/toy)
|
16
|
+
* Check binary version instead of using which to check if binary is present [#59](https://github.com/toy/image_optim/issues/59) [@toy](https://github.com/toy)
|
17
|
+
|
18
|
+
## v0.15.0 (2014-08-19)
|
19
|
+
|
20
|
+
* Use advpng worker before optipng [@toy](https://github.com/toy)
|
21
|
+
* Fix order of results (use progress ~> 3.0.1) [@toy](https://github.com/toy)
|
22
|
+
* Change array returned from `optimize_images`, `optimize_images!` and `optimize_images_data` to contain pairs of item and result instead of just result [@toy](https://github.com/toy)
|
23
|
+
* Fixed `Space` causing exception with negative numbers [@toy](https://github.com/toy)
|
24
|
+
* Added pngquant worker [#14](https://github.com/toy/image_optim/issues/14) [#32](https://github.com/toy/image_optim/issues/32) [#40](https://github.com/toy/image_optim/issues/40) [#52](https://github.com/toy/image_optim/issues/52) [@adammathys](https://github.com/adammathys) [@smasry](https://github.com/smasry) [@toy](https://github.com/toy)
|
25
|
+
* Add instructions to errors from bin resolver [@toy](https://github.com/toy)
|
26
|
+
* Use in_threads ~> 1.2.2 with fix for silent exceptions [@toy](https://github.com/toy)
|
27
|
+
* Fix `LocalJumpError` in railtie initializer block (ruby 2.1.2, rails 4.1.4) [#50](https://github.com/toy/image_optim/issues/50) [@schnittchen](https://github.com/schnittchen)
|
28
|
+
|
29
|
+
## v0.14.0 (2014-07-17)
|
30
|
+
|
31
|
+
* Added Inch CI and Gittip badges to README [@toy](https://github.com/toy)
|
32
|
+
* Assign worker options to constants for documentation [@toy](https://github.com/toy)
|
33
|
+
* Code style, reorganized, comments, added rubocop [@toy](https://github.com/toy)
|
34
|
+
* Switch to rspec 3.0 [@toy](https://github.com/toy)
|
35
|
+
* Don't mention versions in instructions for installing jpegoptim and pngcrush [@toy](https://github.com/toy)
|
36
|
+
|
37
|
+
## v0.13.3 (2014-05-22)
|
38
|
+
|
39
|
+
* Added instruction about libjpeg-turbo-utils [#49](https://github.com/toy/image_optim/issues/49) [@toy](https://github.com/toy)
|
40
|
+
|
41
|
+
## v0.13.2 (2014-04-24)
|
42
|
+
|
43
|
+
* Updated versions of `pngcrush` and `jpegoptim` in installation instructions [#46](https://github.com/toy/image_optim/issues/46) [@toy](https://github.com/toy)
|
44
|
+
* Script for updating instructions in README [@toy](https://github.com/toy)
|
45
|
+
* Typo in README [#45](https://github.com/toy/image_optim/issues/45) [@rawsyntax](https://github.com/rawsyntax)
|
46
|
+
|
47
|
+
## v0.13.1 (2014-04-08)
|
48
|
+
|
49
|
+
* Use image_size ~> 1.3.0 so only `FormatError` exceptions are caught and show warning [#44](https://github.com/toy/image_optim/issues/44) [@lencioni](https://github.com/lencioni)
|
50
|
+
|
51
|
+
## v0.13.0 (2014-04-06)
|
52
|
+
|
53
|
+
* Detect and warn about broken images [#43](https://github.com/toy/image_optim/issues/43) [@toy](https://github.com/toy)
|
54
|
+
* Output image_optim version when running in verbose mode [@toy](https://github.com/toy)
|
55
|
+
* Show resolved version in version exceptions and warnings [@toy](https://github.com/toy)
|
56
|
+
* Warn if advpng version is less than 1.17 as it does not use zopfli [#17](https://github.com/toy/image_optim/issues/17) [#18](https://github.com/toy/image_optim/issues/18) [@toy](https://github.com/toy)
|
57
|
+
|
58
|
+
## v0.12.1 (2014-03-10)
|
59
|
+
|
60
|
+
* Don't try to register preprocessors when sprockets library is not initialized (app.assets is nil) [#41](https://github.com/toy/image_optim/issues/41) [@toy](https://github.com/toy)
|
61
|
+
* Output resolved binaries when verbose [@toy](https://github.com/toy)
|
62
|
+
* Output nice level and number of threads when verbose [@toy](https://github.com/toy)
|
63
|
+
* Output config to stderr when verbose [@toy](https://github.com/toy)
|
64
|
+
* Don't limit number of threads [@toy](https://github.com/toy)
|
65
|
+
|
66
|
+
## v0.12.0 (2014-03-02)
|
67
|
+
|
68
|
+
* Checking bin versions [#33](https://github.com/toy/image_optim/issues/33) [@toy](https://github.com/toy)
|
69
|
+
|
70
|
+
## v0.11.2 (2014-03-01)
|
71
|
+
|
72
|
+
* Fixed building PATH environment variable [@toy](https://github.com/toy)
|
73
|
+
|
74
|
+
## v0.11.1 (2014-02-20)
|
75
|
+
|
76
|
+
* Allow `-v` for version if it is the only argument [@toy](https://github.com/toy)
|
77
|
+
* Fixed initializing railtie [#37](https://github.com/toy/image_optim/issues/37) [@toy](https://github.com/toy)
|
78
|
+
|
79
|
+
## v0.11.0 (2014-02-16)
|
80
|
+
|
81
|
+
* Use image_size ~> 1.2.0 [@toy](https://github.com/toy)
|
82
|
+
* Added `svgo` worker and support for svg files [#27](https://github.com/toy/image_optim/issues/27) [#30](https://github.com/toy/image_optim/issues/30) [@nybblr](https://github.com/nybblr)
|
83
|
+
* Properly unlink temporary files [#29](https://github.com/toy/image_optim/issues/29) [@toy](https://github.com/toy)
|
84
|
+
* Read options from rails app configuration `app.config.assets.image_optim` in railtie [#31](https://github.com/toy/image_optim/issues/31) [@bencrouse](https://github.com/bencrouse)
|
85
|
+
* Updated versions of `pngcrush` and `jpegoptim` in installation instructions [#26](https://github.com/toy/image_optim/issues/26) [@jc00ke](https://github.com/jc00ke)
|
86
|
+
|
87
|
+
## v0.10.2 (2014-01-25)
|
88
|
+
|
89
|
+
* Fixed regression with progress introduced in v0.10.0 [@toy](https://github.com/toy)
|
90
|
+
|
91
|
+
## v0.10.1 (2014-01-23)
|
92
|
+
|
93
|
+
* Ensure binary data (ruby 1.9+) from `optimize_image_data` and `optimize_images_data` [#25](https://github.com/toy/image_optim/issues/25) [@toy](https://github.com/toy)
|
94
|
+
* Mention `optimize_image_data` and `optimize_images_data` in README [#25](https://github.com/toy/image_optim/issues/25) [@toy](https://github.com/toy)
|
95
|
+
|
96
|
+
## v0.10.0 (2013-12-25)
|
97
|
+
|
98
|
+
* Fixed bug with inheritance of `DelegateClass` in jruby 1.9 and 2.0 [@toy](https://github.com/toy)
|
99
|
+
* Return `ImagePath::Optimized` containing also original path and size from `optimize_image` and `optimize_image!` [#12](https://github.com/toy/image_optim/issues/12) [@toy](https://github.com/toy)
|
100
|
+
* Show exception backtrace when verbose [@toy](https://github.com/toy)
|
101
|
+
* Fail if there were warnings with paths to optimize [@toy](https://github.com/toy)
|
102
|
+
* Rails (sprockets) preprocessor [#2](https://github.com/toy/image_optim/issues/2) [@toy](https://github.com/toy)
|
103
|
+
* Use fspath ~> 2.1.0 with fixes for jruby 1.7.8 [@toy](https://github.com/toy)
|
104
|
+
* Add `optimize_image_data` and `optimize_images_data` [@toy](https://github.com/toy)
|
105
|
+
* Read config from `image_optim.yml` at `XDG_CONFIG_HOME` (`~/.config` by default) and from `.image_optim.yml` in current working directory [#13](https://github.com/toy/image_optim/issues/13) [@toy](https://github.com/toy)
|
106
|
+
* Added badges to README [@toy](https://github.com/toy)
|
107
|
+
* Big refactoring [@toy](https://github.com/toy)
|
108
|
+
|
109
|
+
## v0.9.1 (2013-08-20)
|
110
|
+
|
111
|
+
* Use progress ~> 3.0.0 and in_threads ~> 1.2.0 [@toy](https://github.com/toy)
|
112
|
+
|
113
|
+
## v0.9.0 (2013-07-30)
|
114
|
+
|
115
|
+
* Use fspath ~> 2.0.5 with bug fix for jruby in 1.8 mode [@toy](https://github.com/toy)
|
116
|
+
* Overcome wrong implementation of `Process::Status` in jruby [@toy](https://github.com/toy)
|
117
|
+
* Fix for jruby not `File.rename` not accepting non String [@toy](https://github.com/toy)
|
118
|
+
* Fix for jruby `File.rename` not accepting non String [@toy](https://github.com/toy)
|
119
|
+
* Added `.travis.yml` [@toy](https://github.com/toy)
|
120
|
+
* Added `jhead` worker [@toy](https://github.com/toy)
|
121
|
+
|
122
|
+
## v0.8.1 (2013-05-27)
|
123
|
+
|
124
|
+
* Fixed variable name in `jpegoptim` worker [@toy](https://github.com/toy)
|
125
|
+
* Added example of using `PATH` with ImageOptim.app bins [#11](https://github.com/toy/image_optim/issues/11) [@toy](https://github.com/toy)
|
126
|
+
|
127
|
+
## v0.8.0 (2013-03-27)
|
128
|
+
|
129
|
+
* Print options if verbose [@toy](https://github.com/toy)
|
130
|
+
* Added worker options to README using script [#5](https://github.com/toy/image_optim/issues/5) [@toy](https://github.com/toy)
|
131
|
+
* Setting worker options using arguments to image_optim bin [@toy](https://github.com/toy)
|
132
|
+
* Option definitions with description, default value and validation instead of attribute reader in options [@toy](https://github.com/toy)
|
133
|
+
* Don't change PATH for ruby process [@toy](https://github.com/toy)
|
134
|
+
* Vendor `jpegrescan` [@toy](https://github.com/toy)
|
135
|
+
* Option to use `jpegrescan` in `jpegtran` worker, off by default [#6](https://github.com/toy/image_optim/issues/6) [@toy](https://github.com/toy)
|
136
|
+
|
137
|
+
## v0.7.3 (2013-02-24)
|
138
|
+
|
139
|
+
* Use image_size ~> 1.1.2 [@toy](https://github.com/toy)
|
140
|
+
|
141
|
+
## v0.7.2 (2013-01-18)
|
142
|
+
|
143
|
+
* Make `apply_threading` accept enum instead of array [@toy](https://github.com/toy)
|
144
|
+
|
145
|
+
## v0.7.1 (2013-01-17)
|
146
|
+
|
147
|
+
* Use more compatible redirect syntax `>&` [#9](https://github.com/toy/image_optim/issues/9) @"Chris Thompson"
|
148
|
+
|
149
|
+
## v0.7.0 (2013-01-17)
|
150
|
+
|
151
|
+
* Use `system` with `env` and `nice` instead of forking [#8](https://github.com/toy/image_optim/issues/8) [@toy](https://github.com/toy)
|
152
|
+
* Don't use `-s` of `which` as it is nonstandard [#7](https://github.com/toy/image_optim/issues/7) [@toy](https://github.com/toy)
|
153
|
+
* Added bin resolving with ability to specify binary paths using environment variables [@toy](https://github.com/toy)
|
154
|
+
* Reorganized workers [@toy](https://github.com/toy)
|
155
|
+
* Added links to tool projects [@toy](https://github.com/toy)
|
156
|
+
|
157
|
+
## v0.6.0 (2012-11-15)
|
158
|
+
|
159
|
+
* Warn if directly added files are not images or are not optimizable [@toy](https://github.com/toy)
|
160
|
+
* Recursively scan directories for images [#4](https://github.com/toy/image_optim/issues/4) [@toy](https://github.com/toy)
|
161
|
+
* Typo in bin/image_optim [#3](https://github.com/toy/image_optim/issues/3) [@fabiomcosta](https://github.com/fabiomcosta)
|
162
|
+
|
163
|
+
## v0.5.1 (2012-08-07)
|
164
|
+
|
165
|
+
* Nice output for configuration and binary resolving errors [@toy](https://github.com/toy)
|
166
|
+
|
167
|
+
## v0.5.0 (2012-08-05)
|
168
|
+
|
169
|
+
* Verbose output [@toy](https://github.com/toy)
|
170
|
+
|
171
|
+
## v0.4.2 (2012-02-26)
|
172
|
+
|
173
|
+
* Use image_size ~> 1.1 [@toy](https://github.com/toy)
|
174
|
+
|
175
|
+
## v0.4.1 (2012-02-14)
|
176
|
+
|
177
|
+
* Added binary installation instructions to README [#1](https://github.com/toy/image_optim/issues/1) [@jingoro](https://github.com/jingoro)
|
178
|
+
|
179
|
+
## v0.4.0 (2012-01-13)
|
180
|
+
|
181
|
+
* Added usage to README [@toy](https://github.com/toy)
|
182
|
+
* Allow setting nice level, 10 by default [@toy](https://github.com/toy)
|
183
|
+
* Use `fork` instead of `system` [@toy](https://github.com/toy)
|
184
|
+
|
185
|
+
## v0.3.2 (2012-01-12)
|
186
|
+
|
187
|
+
* Fixed setting max thread count [@toy](https://github.com/toy)
|
188
|
+
|
189
|
+
## v0.3.1 (2012-01-12)
|
190
|
+
|
191
|
+
* Fixed parsing thread option [@toy](https://github.com/toy)
|
192
|
+
|
193
|
+
## v0.3.0 (2012-01-12)
|
194
|
+
|
195
|
+
* Output size change per file and total [@toy](https://github.com/toy)
|
196
|
+
* Warn about non files [@toy](https://github.com/toy)
|
197
|
+
|
198
|
+
## v0.2.1 (2012-01-11)
|
199
|
+
|
200
|
+
* Simplified determining presence of bin [@toy](https://github.com/toy)
|
201
|
+
|
202
|
+
## v0.2.0 (2012-01-10)
|
203
|
+
|
204
|
+
* Reduce number of created temp files to minimum [@toy](https://github.com/toy)
|
205
|
+
* Use fspath ~> 2.0.3 [@toy](https://github.com/toy)
|
206
|
+
|
207
|
+
## v0.1.0 (2012-01-09)
|
208
|
+
|
209
|
+
* Initial release [@toy](https://github.com/toy)
|
data/CONTRIBUTING.markdown
CHANGED
data/Gemfile
CHANGED
data/README.markdown
CHANGED
@@ -160,6 +160,8 @@ npm install -g svgo
|
|
160
160
|
```sh
|
161
161
|
image_optim *.{jpg,png,gif,svg}
|
162
162
|
|
163
|
+
image_optim -r .
|
164
|
+
|
163
165
|
image_optim -h
|
164
166
|
```
|
165
167
|
|
@@ -285,7 +287,11 @@ Worker has no options
|
|
285
287
|
|
286
288
|
## Contributing
|
287
289
|
|
288
|
-
If you would like to contribute - that is great and you are very welcome. Please check few notes
|
290
|
+
If you would like to contribute - that is great and you are very welcome. Please check few notes in file [CONTRIBUTING.markdown](CONTRIBUTING.markdown).
|
291
|
+
|
292
|
+
## ChangeLog
|
293
|
+
|
294
|
+
In separate file [CHANGELOG.markdown](CHANGELOG.markdown).
|
289
295
|
|
290
296
|
## Copyright
|
291
297
|
|
data/bin/image_optim
CHANGED
@@ -23,11 +23,26 @@ option_parser = OptionParser.new do |op|
|
|
23
23
|
|
|
24
24
|
TEXT
|
25
25
|
|
26
|
-
op.on('-r', '-R', '--recursive', '
|
26
|
+
op.on('-r', '-R', '--recursive', 'Recursively scan directories '\
|
27
27
|
'for images') do |recursive|
|
28
28
|
options[:recursive] = recursive
|
29
29
|
end
|
30
30
|
|
31
|
+
op.on("--exclude-dir 'GLOB'", 'Glob for excluding directories '\
|
32
|
+
'(defaults to .*)') do |glob|
|
33
|
+
options[:exclude_dir_glob] = glob
|
34
|
+
end
|
35
|
+
|
36
|
+
op.on("--exclude-file 'GLOB'", 'Glob for excluding files '\
|
37
|
+
'(defaults to .*)') do |glob|
|
38
|
+
options[:exclude_file_glob] = glob
|
39
|
+
end
|
40
|
+
|
41
|
+
op.on("--exclude 'GLOB'", 'Set glob for excluding both directories and '\
|
42
|
+
'files') do |glob|
|
43
|
+
options[:exclude_file_glob] = options[:exclude_dir_glob] = glob
|
44
|
+
end
|
45
|
+
|
31
46
|
op.separator nil
|
32
47
|
|
33
48
|
op.on('--[no-]threads N', Integer, 'Number of threads or disable '\
|
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.16.0'
|
6
6
|
s.summary = %q{Optimize (lossless compress) images (jpeg, png, gif, svg) using external utilities (advpng, gifsicle, jpegoptim, jpegtran, optipng, pngcrush, pngout, pngquant, svgo)}
|
7
7
|
s.homepage = "http://github.com/toy/#{s.name}"
|
8
8
|
s.authors = ['Ivan Kuchin']
|
@@ -15,13 +15,13 @@ Gem::Specification.new do |s|
|
|
15
15
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
16
16
|
s.require_paths = %w[lib]
|
17
17
|
|
18
|
-
s.add_dependency 'fspath', '~> 2.1
|
19
|
-
s.add_dependency 'image_size', '~> 1.3
|
20
|
-
s.add_dependency 'exifr', '~> 1.1.3'
|
21
|
-
s.add_dependency 'progress', '~> 3.0.1'
|
22
|
-
s.add_dependency 'in_threads', '~> 1.2.2'
|
18
|
+
s.add_dependency 'fspath', '~> 2.1'
|
19
|
+
s.add_dependency 'image_size', '~> 1.3'
|
20
|
+
s.add_dependency 'exifr', '~> 1.1', '>= 1.1.3'
|
21
|
+
s.add_dependency 'progress', '~> 3.0', '>= 3.0.1'
|
22
|
+
s.add_dependency 'in_threads', '~> 1.2', '>= 1.2.2'
|
23
23
|
s.add_development_dependency 'rspec', '~> 3.0'
|
24
|
-
if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('1.9.
|
25
|
-
s.add_development_dependency 'rubocop', '~> 0.
|
24
|
+
if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('1.9.3')
|
25
|
+
s.add_development_dependency 'rubocop', '~> 0.26.0'
|
26
26
|
end
|
27
27
|
end
|
data/lib/image_optim.rb
CHANGED
@@ -45,8 +45,8 @@ class ImageOptim
|
|
45
45
|
|
46
46
|
if verbose
|
47
47
|
$stderr << config
|
48
|
-
$stderr << "
|
49
|
-
$stderr << "
|
48
|
+
$stderr << "nice: #{nice}\n"
|
49
|
+
$stderr << "threads: #{threads}\n"
|
50
50
|
end
|
51
51
|
|
52
52
|
@bin_resolver = BinResolver.new(self)
|
@@ -55,6 +55,8 @@ class ImageOptim
|
|
55
55
|
config.for_worker(klass)
|
56
56
|
end
|
57
57
|
|
58
|
+
log_workers_by_format if verbose
|
59
|
+
|
58
60
|
config.assert_no_unused_options!
|
59
61
|
end
|
60
62
|
|
@@ -164,18 +166,32 @@ class ImageOptim
|
|
164
166
|
|
165
167
|
private
|
166
168
|
|
169
|
+
def log_workers_by_format
|
170
|
+
$stderr << "Workers by format:\n"
|
171
|
+
@workers_by_format.each do |format, workers|
|
172
|
+
$stderr << "#{format}:\n"
|
173
|
+
workers.each do |worker|
|
174
|
+
$stderr << " #{worker.class.bin_sym}:\n"
|
175
|
+
worker.options.each do |name, value|
|
176
|
+
$stderr << " #{name}: #{value.inspect}\n"
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
167
182
|
# Create hash with format mapped to list of workers sorted by run order
|
168
183
|
def create_workers_by_format(&options_proc)
|
169
184
|
by_format = {}
|
170
|
-
Worker.
|
171
|
-
|
172
|
-
|
185
|
+
workers = Worker.create_all(self, &options_proc)
|
186
|
+
Worker.resolve_all!(workers)
|
187
|
+
sorted = workers.sort_by.with_index{ |worker, i| [worker.run_order, i] }
|
188
|
+
sorted.each do |worker|
|
173
189
|
worker.image_formats.each do |format|
|
174
190
|
by_format[format] ||= []
|
175
191
|
by_format[format] << worker
|
176
192
|
end
|
177
193
|
end
|
178
|
-
by_format
|
194
|
+
by_format
|
179
195
|
end
|
180
196
|
|
181
197
|
# Run method for each item in list
|
@@ -58,6 +58,19 @@ class ImageOptim
|
|
58
58
|
[dir, ENV['PATH'], VENDOR_PATH].compact.join(':')
|
59
59
|
end
|
60
60
|
|
61
|
+
# Collect resolving errors when running block over items of enumerable
|
62
|
+
def self.collect_errors(enumerable)
|
63
|
+
errors = []
|
64
|
+
enumerable.each do |item|
|
65
|
+
begin
|
66
|
+
yield item
|
67
|
+
rescue Error => e
|
68
|
+
errors << e
|
69
|
+
end
|
70
|
+
end
|
71
|
+
errors
|
72
|
+
end
|
73
|
+
|
61
74
|
private
|
62
75
|
|
63
76
|
def resolving(name)
|
@@ -80,17 +93,17 @@ class ImageOptim
|
|
80
93
|
end
|
81
94
|
|
82
95
|
def accessible?(name)
|
83
|
-
|
96
|
+
!!version(name)
|
84
97
|
end
|
85
98
|
|
86
99
|
def version(name)
|
87
100
|
case name.to_sym
|
88
101
|
when :advpng, :gifsicle, :jpegoptim, :optipng, :pngquant
|
89
|
-
capture_output("#{name} --version")[/\d+(\.\d+){1,}/]
|
102
|
+
capture_output("#{name} --version 2> /dev/null")[/\d+(\.\d+){1,}/]
|
90
103
|
when :svgo
|
91
104
|
capture_output("#{name} --version 2>&1")[/\d+(\.\d+){1,}/]
|
92
105
|
when :jhead
|
93
|
-
capture_output("#{name} -V")[/\d+(\.\d+){1,}/]
|
106
|
+
capture_output("#{name} -V 2> /dev/null")[/\d+(\.\d+){1,}/]
|
94
107
|
when :jpegtran
|
95
108
|
capture_output("#{name} -v - 2>&1")[/version (\d+\S*)/, 1]
|
96
109
|
when :pngcrush
|
@@ -98,7 +111,12 @@ class ImageOptim
|
|
98
111
|
when :pngout
|
99
112
|
date_regexp = /[A-Z][a-z]{2} (?: |\d)\d \d{4}/
|
100
113
|
date_str = capture_output("#{name} 2>&1")[date_regexp]
|
101
|
-
Date.parse(date_str).strftime('%Y%m%d')
|
114
|
+
Date.parse(date_str).strftime('%Y%m%d') if date_str
|
115
|
+
when :jpegrescan
|
116
|
+
# jpegrescan has no version so just check presence
|
117
|
+
capture_output("command -v #{name}")['jpegrescan']
|
118
|
+
else
|
119
|
+
fail "getting `#{name}` version is not defined"
|
102
120
|
end
|
103
121
|
end
|
104
122
|
|
data/lib/image_optim/config.rb
CHANGED
@@ -10,7 +10,7 @@ class ImageOptim
|
|
10
10
|
class Config
|
11
11
|
include OptionHelpers
|
12
12
|
|
13
|
-
CONFIG_HOME =
|
13
|
+
CONFIG_HOME = ENV['XDG_CONFIG_HOME'] || '~/.config'
|
14
14
|
GLOBAL_CONFIG_PATH = File.join(CONFIG_HOME, 'image_optim.yml')
|
15
15
|
LOCAL_CONFIG_PATH = './.image_optim.yml'
|
16
16
|
|
@@ -18,25 +18,32 @@ class ImageOptim
|
|
18
18
|
# Read config at GLOBAL_CONFIG_PATH if it exists, warn if anything is
|
19
19
|
# wrong
|
20
20
|
def global
|
21
|
-
|
21
|
+
read(GLOBAL_CONFIG_PATH)
|
22
22
|
end
|
23
23
|
|
24
24
|
# Read config at LOCAL_CONFIG_PATH if it exists, warn if anything is
|
25
25
|
# wrong
|
26
26
|
def local
|
27
|
-
|
27
|
+
read(LOCAL_CONFIG_PATH)
|
28
28
|
end
|
29
29
|
|
30
30
|
private
|
31
31
|
|
32
32
|
def read(path)
|
33
|
-
|
33
|
+
begin
|
34
|
+
full_path = File.expand_path(path)
|
35
|
+
rescue ArgumentError => e
|
36
|
+
warn "Can't expand path #{path}: #{e}"
|
37
|
+
return {}
|
38
|
+
end
|
39
|
+
return {} unless File.file?(full_path)
|
40
|
+
config = YAML.load_file(full_path)
|
34
41
|
unless config.is_a?(Hash)
|
35
|
-
fail "
|
42
|
+
fail "expected hash, got #{config.inspect}"
|
36
43
|
end
|
37
44
|
HashHelpers.deep_symbolise_keys(config)
|
38
45
|
rescue => e
|
39
|
-
warn "exception when reading #{
|
46
|
+
warn "exception when reading #{full_path}: #{e}"
|
40
47
|
{}
|
41
48
|
end
|
42
49
|
end
|
@@ -61,8 +68,7 @@ class ImageOptim
|
|
61
68
|
def assert_no_unused_options!
|
62
69
|
unknown_options = @options.reject{ |key, _value| @used.include?(key) }
|
63
70
|
return if unknown_options.empty?
|
64
|
-
fail ConfigurationError, "unknown options #{unknown_options.inspect}
|
65
|
-
"for #{self}"
|
71
|
+
fail ConfigurationError, "unknown options #{unknown_options.inspect}"
|
66
72
|
end
|
67
73
|
|
68
74
|
def nice
|
data/lib/image_optim/runner.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'image_optim'
|
2
2
|
require 'image_optim/hash_helpers'
|
3
|
+
require 'image_optim/runner/glob_helpers'
|
3
4
|
require 'image_optim/space'
|
4
5
|
require 'progress'
|
5
6
|
require 'optparse'
|
@@ -47,6 +48,10 @@ class ImageOptim
|
|
47
48
|
fail 'specify paths to optimize' if args.empty?
|
48
49
|
options = HashHelpers.deep_symbolise_keys(options)
|
49
50
|
@recursive = options.delete(:recursive)
|
51
|
+
@exclude_dir_globs, @exclude_file_globs = %w[dir file].map do |type|
|
52
|
+
glob = options.delete(:"exclude_#{type}_glob") || '.*'
|
53
|
+
GlobHelpers.expand_braces(glob)
|
54
|
+
end
|
50
55
|
@image_optim = ImageOptim.new(options)
|
51
56
|
@to_optimize = find_to_optimize(args)
|
52
57
|
end
|
@@ -85,14 +90,14 @@ class ImageOptim
|
|
85
90
|
else
|
86
91
|
warning "#{path} is not an image or there is no optimizer for it"
|
87
92
|
end
|
88
|
-
elsif
|
89
|
-
if
|
93
|
+
elsif File.directory?(path)
|
94
|
+
if @recursive
|
90
95
|
to_optimize += find_to_optimize_recursive(path)
|
91
96
|
else
|
92
|
-
warning "#{path} is
|
97
|
+
warning "#{path} is a directory, use --recursive option"
|
93
98
|
end
|
94
99
|
else
|
95
|
-
warning "#{path} is not a file or does not exist"
|
100
|
+
warning "#{path} is not a file or a directory or does not exist"
|
96
101
|
end
|
97
102
|
end
|
98
103
|
to_optimize
|
@@ -101,13 +106,36 @@ class ImageOptim
|
|
101
106
|
def find_to_optimize_recursive(dir)
|
102
107
|
to_optimize = []
|
103
108
|
Find.find(dir) do |path|
|
104
|
-
|
105
|
-
|
106
|
-
|
109
|
+
if File.file?(path)
|
110
|
+
next if exclude_file?(dir, path)
|
111
|
+
next unless @image_optim.optimizable?(path)
|
112
|
+
to_optimize << path
|
113
|
+
elsif File.directory?(path)
|
114
|
+
Find.prune if dir != path && exclude_dir?(dir, path)
|
115
|
+
end
|
107
116
|
end
|
108
117
|
to_optimize
|
109
118
|
end
|
110
119
|
|
120
|
+
def exclude_dir?(dir, path)
|
121
|
+
exclude?(dir, path, @exclude_dir_globs)
|
122
|
+
end
|
123
|
+
|
124
|
+
def exclude_file?(dir, path)
|
125
|
+
exclude?(dir, path, @exclude_file_globs)
|
126
|
+
end
|
127
|
+
|
128
|
+
# Check if any of globs matches either part of path relative from dir or
|
129
|
+
# just basename
|
130
|
+
def exclude?(dir, path, globs)
|
131
|
+
relative_path = Pathname(path).relative_path_from(Pathname(dir)).to_s
|
132
|
+
basename = File.basename(path)
|
133
|
+
globs.any? do |glob|
|
134
|
+
File.fnmatch(glob, relative_path, File::FNM_PATHNAME) ||
|
135
|
+
File.fnmatch(glob, basename, File::FNM_PATHNAME)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
111
139
|
def warning(message)
|
112
140
|
@warnings = true
|
113
141
|
warn message
|
@@ -0,0 +1,45 @@
|
|
1
|
+
class ImageOptim
|
2
|
+
class Runner
|
3
|
+
# Helper methods for glob
|
4
|
+
module GlobHelpers
|
5
|
+
class << self
|
6
|
+
# Match inner curly braces in glob
|
7
|
+
# Negative lookbehind is not used as is not supported by ruby before 1.9
|
8
|
+
BRACE_REGEXP = /
|
9
|
+
\A
|
10
|
+
(
|
11
|
+
(?:.*[^\\]|) # anything ending not with slash or nothing
|
12
|
+
(?:\\\\)* # any number of self escaped slashes
|
13
|
+
)
|
14
|
+
\{ # open brace
|
15
|
+
(
|
16
|
+
(?:|.*?[^\\]) # nothing or non greedy anything ending not with slash
|
17
|
+
(?:\\\\)* # any number of self escaped slashes
|
18
|
+
)
|
19
|
+
\} # close brace
|
20
|
+
(
|
21
|
+
.* # what is left
|
22
|
+
)
|
23
|
+
\z
|
24
|
+
/x
|
25
|
+
|
26
|
+
# Expand curly braces in glob as fnmatch in ruby before 2.0 doesn't
|
27
|
+
# support them
|
28
|
+
def expand_braces(original_glob)
|
29
|
+
expanded = []
|
30
|
+
unexpanded = [original_glob]
|
31
|
+
while (glob = unexpanded.shift)
|
32
|
+
if (m = BRACE_REGEXP.match(glob))
|
33
|
+
m[2].split(',', -1).each do |variant|
|
34
|
+
unexpanded << "#{m[1]}#{variant}#{m[3]}"
|
35
|
+
end
|
36
|
+
else
|
37
|
+
expanded << glob
|
38
|
+
end
|
39
|
+
end
|
40
|
+
expanded.uniq
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/image_optim/worker.rb
CHANGED
@@ -37,6 +37,24 @@ class ImageOptim
|
|
37
37
|
option_definitions <<
|
38
38
|
OptionDefinition.new(name, default, type, description, &proc)
|
39
39
|
end
|
40
|
+
|
41
|
+
# Initialize all workers using options from calling options_proc with
|
42
|
+
# klass
|
43
|
+
def create_all(image_optim, &options_proc)
|
44
|
+
Worker.klasses.map do |klass|
|
45
|
+
next unless (options = options_proc[klass])
|
46
|
+
klass.new(image_optim, options)
|
47
|
+
end.compact
|
48
|
+
end
|
49
|
+
|
50
|
+
# Resolve all bins of all workers failing with one joint exception
|
51
|
+
def resolve_all!(workers)
|
52
|
+
errors = BinResolver.collect_errors(workers) do |worker|
|
53
|
+
worker.resolve_used_bins!
|
54
|
+
end
|
55
|
+
return if errors.empty?
|
56
|
+
fail BinResolver::Error, ['Bin resolving errors:', *errors].join("\n")
|
57
|
+
end
|
40
58
|
end
|
41
59
|
|
42
60
|
# Configure (raises on extra options)
|
@@ -60,6 +78,13 @@ class ImageOptim
|
|
60
78
|
assert_no_unknown_options!(options)
|
61
79
|
end
|
62
80
|
|
81
|
+
# Return hash with worker options
|
82
|
+
def options
|
83
|
+
self.class.option_definitions.each_with_object({}) do |option, h|
|
84
|
+
h[option.name] = send(option.name)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
63
88
|
# Optimize image at src, output at dst, must be overriden in subclass
|
64
89
|
# return true on success
|
65
90
|
def optimize(_src, _dst)
|
@@ -80,8 +105,18 @@ class ImageOptim
|
|
80
105
|
0
|
81
106
|
end
|
82
107
|
|
83
|
-
|
84
|
-
|
108
|
+
# List of bins used by worker
|
109
|
+
def used_bins
|
110
|
+
[self.class.bin_sym]
|
111
|
+
end
|
112
|
+
|
113
|
+
# Resolve used bins, raise exception mergin all messages
|
114
|
+
def resolve_used_bins!
|
115
|
+
errors = BinResolver.collect_errors(used_bins) do |bin|
|
116
|
+
@image_optim.resolve_bin!(bin)
|
117
|
+
end
|
118
|
+
return if errors.empty?
|
119
|
+
fail BinResolver::Error, wrap_resolver_error_message(errors.join(', '))
|
85
120
|
end
|
86
121
|
|
87
122
|
# Check if operation resulted in optimized file
|
@@ -103,9 +138,14 @@ class ImageOptim
|
|
103
138
|
def resolve_bin!(bin)
|
104
139
|
@image_optim.resolve_bin!(bin)
|
105
140
|
rescue BinResolver::Error => e
|
141
|
+
raise e, wrap_resolver_error_message(e.message), e.backtrace
|
142
|
+
end
|
143
|
+
|
144
|
+
def wrap_resolver_error_message(message)
|
106
145
|
name = self.class.bin_sym
|
107
|
-
|
108
|
-
"disable this worker (
|
146
|
+
"#{name} worker: #{message}; please provide proper binary or "\
|
147
|
+
"disable this worker (--no-#{name} argument or "\
|
148
|
+
"`:#{name} => false` through options)"
|
109
149
|
end
|
110
150
|
|
111
151
|
# Run command setting priority and hiding output
|
@@ -17,6 +17,10 @@ class ImageOptim
|
|
17
17
|
option(:jpegrescan, false, 'Use jpegtran through jpegrescan, '\
|
18
18
|
'ignore progressive option'){ |v| !!v }
|
19
19
|
|
20
|
+
def used_bins
|
21
|
+
jpegrescan ? [:jpegtran, :jpegrescan] : [:jpegtran]
|
22
|
+
end
|
23
|
+
|
20
24
|
def optimize(src, dst)
|
21
25
|
if jpegrescan
|
22
26
|
args = %W[#{src} #{dst}]
|
@@ -15,6 +15,7 @@ describe ImageOptim::BinResolver do
|
|
15
15
|
|
16
16
|
it 'should resolve bin in path' do
|
17
17
|
with_env 'LS_BIN', nil do
|
18
|
+
allow(resolver).to receive(:version).with(:ls).and_return('xxx')
|
18
19
|
expect(resolver).to receive(:accessible?).with(:ls).once.and_return(true)
|
19
20
|
expect(FSPath).not_to receive(:temp_dir)
|
20
21
|
|
@@ -28,12 +29,29 @@ describe ImageOptim::BinResolver do
|
|
28
29
|
end
|
29
30
|
end
|
30
31
|
|
32
|
+
it 'should fail to resolve unknown bin' do
|
33
|
+
with_env 'LS_BIN', nil do
|
34
|
+
expect(FSPath).not_to receive(:temp_dir)
|
35
|
+
|
36
|
+
5.times do
|
37
|
+
expect do
|
38
|
+
resolver.resolve!(:ls)
|
39
|
+
end.to raise_error RuntimeError
|
40
|
+
end
|
41
|
+
expect(resolver.env_path).to eq([
|
42
|
+
ENV['PATH'],
|
43
|
+
ImageOptim::BinResolver::VENDOR_PATH,
|
44
|
+
].join(':'))
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
31
48
|
it 'should resolve bin specified in ENV' do
|
32
49
|
path = 'some/path/image_optim2.3.4'
|
33
50
|
with_env 'IMAGE_OPTIM_BIN', path do
|
34
51
|
tmpdir = double(:tmpdir, :to_str => 'tmpdir')
|
35
52
|
symlink = double(:symlink)
|
36
53
|
|
54
|
+
allow(resolver).to receive(:version).with(:image_optim).and_return('xxx')
|
37
55
|
expect(resolver).to receive(:accessible?).
|
38
56
|
with(:image_optim).once.and_return(true)
|
39
57
|
expect(FSPath).to receive(:temp_dir).
|
@@ -63,20 +81,15 @@ describe ImageOptim::BinResolver do
|
|
63
81
|
end
|
64
82
|
|
65
83
|
it 'should raise on failure to resolve bin' do
|
66
|
-
with_env '
|
67
|
-
expect(resolver).to receive(:accessible?).
|
68
|
-
with(:should_not_exist).once.and_return(false)
|
84
|
+
with_env 'PATH', nil do
|
69
85
|
expect(FSPath).not_to receive(:temp_dir)
|
70
86
|
|
71
87
|
5.times do
|
72
88
|
expect do
|
73
|
-
resolver.resolve!(:
|
89
|
+
resolver.resolve!(:jpegtran)
|
74
90
|
end.to raise_error ImageOptim::BinResolver::BinNotFound
|
75
91
|
end
|
76
|
-
expect(resolver.env_path).to eq(
|
77
|
-
ENV['PATH'],
|
78
|
-
ImageOptim::BinResolver::VENDOR_PATH,
|
79
|
-
].join(':'))
|
92
|
+
expect(resolver.env_path).to eq(ImageOptim::BinResolver::VENDOR_PATH)
|
80
93
|
end
|
81
94
|
end
|
82
95
|
|
@@ -118,6 +131,7 @@ describe ImageOptim::BinResolver do
|
|
118
131
|
|
119
132
|
it 'should resolve bin only once' do
|
120
133
|
with_env 'LS_BIN', nil do
|
134
|
+
allow(resolver).to receive(:version).with(:ls).and_return('xxx')
|
121
135
|
expect(resolver).to receive(:resolve?).once.with(:ls){ sleep 0.1; true }
|
122
136
|
|
123
137
|
10.times.map do
|
@@ -60,7 +60,11 @@ describe ImageOptim::Config do
|
|
60
60
|
end
|
61
61
|
|
62
62
|
describe 'for_worker' do
|
63
|
-
Abc = Class.new
|
63
|
+
Abc = Class.new do
|
64
|
+
def self.bin_sym
|
65
|
+
:abc
|
66
|
+
end
|
67
|
+
|
64
68
|
def image_formats
|
65
69
|
[]
|
66
70
|
end
|
@@ -96,17 +100,7 @@ describe ImageOptim::Config do
|
|
96
100
|
end
|
97
101
|
|
98
102
|
describe 'global' do
|
99
|
-
it 'should
|
100
|
-
expect(File).to receive(:file?).
|
101
|
-
with(Config::GLOBAL_CONFIG_PATH).and_return(false)
|
102
|
-
expect(Config).not_to receive(:read)
|
103
|
-
|
104
|
-
expect(Config.global).to eq({})
|
105
|
-
end
|
106
|
-
|
107
|
-
it 'should read global config if it exists' do
|
108
|
-
expect(File).to receive(:file?).
|
109
|
-
with(Config::GLOBAL_CONFIG_PATH).and_return(true)
|
103
|
+
it 'should call read with GLOBAL_CONFIG_PATH' do
|
110
104
|
expect(Config).to receive(:read).
|
111
105
|
with(Config::GLOBAL_CONFIG_PATH).and_return(:config => true)
|
112
106
|
|
@@ -115,17 +109,7 @@ describe ImageOptim::Config do
|
|
115
109
|
end
|
116
110
|
|
117
111
|
describe 'local' do
|
118
|
-
it 'should
|
119
|
-
expect(File).to receive(:file?).
|
120
|
-
with(Config::LOCAL_CONFIG_PATH).and_return(false)
|
121
|
-
expect(Config).not_to receive(:read)
|
122
|
-
|
123
|
-
expect(Config.local).to eq({})
|
124
|
-
end
|
125
|
-
|
126
|
-
it 'should read local config if it exists' do
|
127
|
-
expect(File).to receive(:file?).
|
128
|
-
with(Config::LOCAL_CONFIG_PATH).and_return(true)
|
112
|
+
it 'should call read with LOCAL_CONFIG_PATH' do
|
129
113
|
expect(Config).to receive(:read).
|
130
114
|
with(Config::LOCAL_CONFIG_PATH).and_return(:config => true)
|
131
115
|
|
@@ -134,30 +118,65 @@ describe ImageOptim::Config do
|
|
134
118
|
end
|
135
119
|
|
136
120
|
describe 'read' do
|
121
|
+
let(:path){ double(:path) }
|
122
|
+
let(:full_path){ double(:full_path) }
|
123
|
+
|
124
|
+
it 'should warn if expand path fails' do
|
125
|
+
expect(Config).to receive(:warn)
|
126
|
+
expect(File).to receive(:expand_path).
|
127
|
+
with(path).and_raise(ArgumentError)
|
128
|
+
expect(File).not_to receive(:file?)
|
129
|
+
|
130
|
+
expect(Config.send(:read, path)).to eq({})
|
131
|
+
end
|
132
|
+
|
133
|
+
it 'should return empty hash if path is not a file' do
|
134
|
+
expect(Config).not_to receive(:warn)
|
135
|
+
expect(File).to receive(:expand_path).
|
136
|
+
with(path).and_return(full_path)
|
137
|
+
expect(File).to receive(:file?).
|
138
|
+
with(full_path).and_return(false)
|
139
|
+
|
140
|
+
expect(Config.send(:read, path)).to eq({})
|
141
|
+
end
|
142
|
+
|
137
143
|
it 'should return hash with deep symbolised keys from reader' do
|
138
144
|
stringified = {'config' => {'this' => true}}
|
139
145
|
symbolized = {:config => {:this => true}}
|
140
146
|
|
141
|
-
|
142
|
-
expect(
|
147
|
+
expect(Config).not_to receive(:warn)
|
148
|
+
expect(File).to receive(:expand_path).
|
149
|
+
with(path).and_return(full_path)
|
150
|
+
expect(File).to receive(:file?).
|
151
|
+
with(full_path).and_return(true)
|
152
|
+
expect(YAML).to receive(:load_file).
|
153
|
+
with(full_path).and_return(stringified)
|
143
154
|
|
144
|
-
expect(Config.
|
155
|
+
expect(Config.send(:read, path)).to eq(symbolized)
|
145
156
|
end
|
146
157
|
|
147
158
|
it 'should warn and return an empty hash if reader returns non hash' do
|
148
|
-
path = double(:path)
|
149
|
-
expect(YAML).to receive(:load_file).with(path).and_return([:config])
|
150
159
|
expect(Config).to receive(:warn)
|
160
|
+
expect(File).to receive(:expand_path).
|
161
|
+
with(path).and_return(full_path)
|
162
|
+
expect(File).to receive(:file?).
|
163
|
+
with(full_path).and_return(true)
|
164
|
+
expect(YAML).to receive(:load_file).
|
165
|
+
with(full_path).and_return([:config])
|
151
166
|
|
152
|
-
expect(Config.
|
167
|
+
expect(Config.send(:read, path)).to eq({})
|
153
168
|
end
|
154
169
|
|
155
170
|
it 'should warn and return an empty hash if reader raises exception' do
|
156
|
-
path = double(:path)
|
157
|
-
expect(YAML).to receive(:load_file).with(path).and_raise
|
158
171
|
expect(Config).to receive(:warn)
|
172
|
+
expect(File).to receive(:expand_path).
|
173
|
+
with(path).and_return(full_path)
|
174
|
+
expect(File).to receive(:file?).
|
175
|
+
with(full_path).and_return(true)
|
176
|
+
expect(YAML).to receive(:load_file).
|
177
|
+
with(full_path).and_raise
|
159
178
|
|
160
|
-
expect(Config.
|
179
|
+
expect(Config.send(:read, path)).to eq({})
|
161
180
|
end
|
162
181
|
end
|
163
182
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
$LOAD_PATH.unshift File.expand_path('../../../lib', __FILE__)
|
2
|
+
require 'rspec'
|
3
|
+
require 'image_optim/runner/glob_helpers'
|
4
|
+
|
5
|
+
describe ImageOptim::Runner::GlobHelpers do
|
6
|
+
GH = ImageOptim::Runner::GlobHelpers
|
7
|
+
|
8
|
+
describe :expand_braces do
|
9
|
+
{
|
10
|
+
'hello.world' => %w[hello.world],
|
11
|
+
'{hello,.world}' => %w[hello .world],
|
12
|
+
'hello{.,!}world' => %w[hello.world hello!world],
|
13
|
+
'{a,b},{c,d}' => %w[a,c b,c a,d b,d],
|
14
|
+
'{{a,b},{c,d}}' => %w[a b c d],
|
15
|
+
'{a,b,{c,d}}' => %w[a b c d],
|
16
|
+
'{\{a,b\},\{c,d\}}' => %w[\\{a b\\} \\{c d\\}],
|
17
|
+
'test{ing,}' => %w[testing test],
|
18
|
+
}.each do |glob, expected|
|
19
|
+
it "should expand #{glob}" do
|
20
|
+
expect(GH.expand_braces(glob)).to match_array(expected)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -6,13 +6,12 @@ describe ImageOptim::Worker do
|
|
6
6
|
Worker = ImageOptim::Worker
|
7
7
|
|
8
8
|
describe 'optimize' do
|
9
|
-
it 'should raise NotImplementedError
|
10
|
-
class Abc < ImageOptim::Worker; end
|
11
|
-
|
9
|
+
it 'should raise NotImplementedError' do
|
12
10
|
image_optim = ImageOptim.new
|
11
|
+
worker = Worker.new(image_optim, {})
|
13
12
|
|
14
13
|
expect do
|
15
|
-
|
14
|
+
worker.optimize(double, double)
|
16
15
|
end.to raise_error NotImplementedError
|
17
16
|
end
|
18
17
|
end
|
data/spec/image_optim_spec.rb
CHANGED
@@ -67,7 +67,9 @@ describe ImageOptim do
|
|
67
67
|
expect(path).to receive(:format).and_return(format)
|
68
68
|
|
69
69
|
workers = image_optim.workers_for_image(path)
|
70
|
-
expect(workers).to eq(workers.
|
70
|
+
expect(workers).to eq(workers.sort_by.with_index do |worker, i|
|
71
|
+
[worker.run_order, i]
|
72
|
+
end)
|
71
73
|
end
|
72
74
|
end
|
73
75
|
end
|
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.16.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: 2014-
|
11
|
+
date: 2014-09-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: fspath
|
@@ -16,33 +16,36 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ~>
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 2.1
|
19
|
+
version: '2.1'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ~>
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 2.1
|
26
|
+
version: '2.1'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: image_size
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - ~>
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 1.3
|
33
|
+
version: '1.3'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - ~>
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 1.3
|
40
|
+
version: '1.3'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: exifr
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.1'
|
48
|
+
- - ! '>='
|
46
49
|
- !ruby/object:Gem::Version
|
47
50
|
version: 1.1.3
|
48
51
|
type: :runtime
|
@@ -50,6 +53,9 @@ dependencies:
|
|
50
53
|
version_requirements: !ruby/object:Gem::Requirement
|
51
54
|
requirements:
|
52
55
|
- - ~>
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: '1.1'
|
58
|
+
- - ! '>='
|
53
59
|
- !ruby/object:Gem::Version
|
54
60
|
version: 1.1.3
|
55
61
|
- !ruby/object:Gem::Dependency
|
@@ -57,6 +63,9 @@ dependencies:
|
|
57
63
|
requirement: !ruby/object:Gem::Requirement
|
58
64
|
requirements:
|
59
65
|
- - ~>
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '3.0'
|
68
|
+
- - ! '>='
|
60
69
|
- !ruby/object:Gem::Version
|
61
70
|
version: 3.0.1
|
62
71
|
type: :runtime
|
@@ -64,6 +73,9 @@ dependencies:
|
|
64
73
|
version_requirements: !ruby/object:Gem::Requirement
|
65
74
|
requirements:
|
66
75
|
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '3.0'
|
78
|
+
- - ! '>='
|
67
79
|
- !ruby/object:Gem::Version
|
68
80
|
version: 3.0.1
|
69
81
|
- !ruby/object:Gem::Dependency
|
@@ -71,6 +83,9 @@ dependencies:
|
|
71
83
|
requirement: !ruby/object:Gem::Requirement
|
72
84
|
requirements:
|
73
85
|
- - ~>
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '1.2'
|
88
|
+
- - ! '>='
|
74
89
|
- !ruby/object:Gem::Version
|
75
90
|
version: 1.2.2
|
76
91
|
type: :runtime
|
@@ -78,6 +93,9 @@ dependencies:
|
|
78
93
|
version_requirements: !ruby/object:Gem::Requirement
|
79
94
|
requirements:
|
80
95
|
- - ~>
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '1.2'
|
98
|
+
- - ! '>='
|
81
99
|
- !ruby/object:Gem::Version
|
82
100
|
version: 1.2.2
|
83
101
|
- !ruby/object:Gem::Dependency
|
@@ -100,14 +118,14 @@ dependencies:
|
|
100
118
|
requirements:
|
101
119
|
- - ~>
|
102
120
|
- !ruby/object:Gem::Version
|
103
|
-
version: 0.
|
121
|
+
version: 0.26.0
|
104
122
|
type: :development
|
105
123
|
prerelease: false
|
106
124
|
version_requirements: !ruby/object:Gem::Requirement
|
107
125
|
requirements:
|
108
126
|
- - ~>
|
109
127
|
- !ruby/object:Gem::Version
|
110
|
-
version: 0.
|
128
|
+
version: 0.26.0
|
111
129
|
description:
|
112
130
|
email:
|
113
131
|
executables:
|
@@ -118,6 +136,7 @@ files:
|
|
118
136
|
- .gitignore
|
119
137
|
- .rubocop.yml
|
120
138
|
- .travis.yml
|
139
|
+
- CHANGELOG.markdown
|
121
140
|
- CONTRIBUTING.markdown
|
122
141
|
- Gemfile
|
123
142
|
- LICENSE.txt
|
@@ -139,6 +158,7 @@ files:
|
|
139
158
|
- lib/image_optim/option_helpers.rb
|
140
159
|
- lib/image_optim/railtie.rb
|
141
160
|
- lib/image_optim/runner.rb
|
161
|
+
- lib/image_optim/runner/glob_helpers.rb
|
142
162
|
- lib/image_optim/space.rb
|
143
163
|
- lib/image_optim/true_false_nil.rb
|
144
164
|
- lib/image_optim/worker.rb
|
@@ -160,6 +180,7 @@ files:
|
|
160
180
|
- spec/image_optim/handler_spec.rb
|
161
181
|
- spec/image_optim/hash_helpers_spec.rb
|
162
182
|
- spec/image_optim/image_path_spec.rb
|
183
|
+
- spec/image_optim/runner/glob_helpers_spec.rb
|
163
184
|
- spec/image_optim/space_spec.rb
|
164
185
|
- spec/image_optim/worker_spec.rb
|
165
186
|
- spec/image_optim_spec.rb
|
@@ -220,6 +241,7 @@ test_files:
|
|
220
241
|
- spec/image_optim/handler_spec.rb
|
221
242
|
- spec/image_optim/hash_helpers_spec.rb
|
222
243
|
- spec/image_optim/image_path_spec.rb
|
244
|
+
- spec/image_optim/runner/glob_helpers_spec.rb
|
223
245
|
- spec/image_optim/space_spec.rb
|
224
246
|
- spec/image_optim/worker_spec.rb
|
225
247
|
- spec/image_optim_spec.rb
|