image_optim 0.15.0 → 0.16.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 +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
|