openstreetmap-image_optim 0.21.0.1

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.
Files changed (94) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.rubocop.yml +65 -0
  4. data/.travis.yml +42 -0
  5. data/CHANGELOG.markdown +272 -0
  6. data/CONTRIBUTING.markdown +10 -0
  7. data/Gemfile +9 -0
  8. data/LICENSE.txt +20 -0
  9. data/README.markdown +344 -0
  10. data/Vagrantfile +33 -0
  11. data/bin/image_optim +28 -0
  12. data/image_optim.gemspec +29 -0
  13. data/lib/image_optim.rb +228 -0
  14. data/lib/image_optim/bin_resolver.rb +144 -0
  15. data/lib/image_optim/bin_resolver/bin.rb +105 -0
  16. data/lib/image_optim/bin_resolver/comparable_condition.rb +60 -0
  17. data/lib/image_optim/bin_resolver/error.rb +6 -0
  18. data/lib/image_optim/bin_resolver/simple_version.rb +31 -0
  19. data/lib/image_optim/cmd.rb +49 -0
  20. data/lib/image_optim/config.rb +205 -0
  21. data/lib/image_optim/configuration_error.rb +3 -0
  22. data/lib/image_optim/handler.rb +57 -0
  23. data/lib/image_optim/hash_helpers.rb +45 -0
  24. data/lib/image_optim/image_meta.rb +25 -0
  25. data/lib/image_optim/image_path.rb +68 -0
  26. data/lib/image_optim/non_negative_integer_range.rb +11 -0
  27. data/lib/image_optim/option_definition.rb +32 -0
  28. data/lib/image_optim/option_helpers.rb +17 -0
  29. data/lib/image_optim/railtie.rb +38 -0
  30. data/lib/image_optim/runner.rb +139 -0
  31. data/lib/image_optim/runner/glob_helpers.rb +45 -0
  32. data/lib/image_optim/runner/option_parser.rb +227 -0
  33. data/lib/image_optim/space.rb +29 -0
  34. data/lib/image_optim/true_false_nil.rb +16 -0
  35. data/lib/image_optim/worker.rb +159 -0
  36. data/lib/image_optim/worker/advpng.rb +35 -0
  37. data/lib/image_optim/worker/class_methods.rb +91 -0
  38. data/lib/image_optim/worker/gifsicle.rb +63 -0
  39. data/lib/image_optim/worker/jhead.rb +43 -0
  40. data/lib/image_optim/worker/jpegoptim.rb +58 -0
  41. data/lib/image_optim/worker/jpegrecompress.rb +44 -0
  42. data/lib/image_optim/worker/jpegtran.rb +46 -0
  43. data/lib/image_optim/worker/optipng.rb +45 -0
  44. data/lib/image_optim/worker/pngcrush.rb +54 -0
  45. data/lib/image_optim/worker/pngout.rb +38 -0
  46. data/lib/image_optim/worker/pngquant.rb +51 -0
  47. data/lib/image_optim/worker/svgo.rb +32 -0
  48. data/script/template/jquery-2.1.3.min.js +4 -0
  49. data/script/template/sortable-0.6.0.min.js +2 -0
  50. data/script/template/worker_analysis.erb +254 -0
  51. data/script/update_worker_options_in_readme +60 -0
  52. data/script/worker_analysis +599 -0
  53. data/spec/image_optim/bin_resolver/comparable_condition_spec.rb +37 -0
  54. data/spec/image_optim/bin_resolver/simple_version_spec.rb +57 -0
  55. data/spec/image_optim/bin_resolver_spec.rb +272 -0
  56. data/spec/image_optim/cmd_spec.rb +66 -0
  57. data/spec/image_optim/config_spec.rb +217 -0
  58. data/spec/image_optim/handler_spec.rb +95 -0
  59. data/spec/image_optim/hash_helpers_spec.rb +76 -0
  60. data/spec/image_optim/image_path_spec.rb +54 -0
  61. data/spec/image_optim/railtie_spec.rb +121 -0
  62. data/spec/image_optim/runner/glob_helpers_spec.rb +25 -0
  63. data/spec/image_optim/runner/option_parser_spec.rb +99 -0
  64. data/spec/image_optim/space_spec.rb +25 -0
  65. data/spec/image_optim/worker_spec.rb +192 -0
  66. data/spec/image_optim_spec.rb +242 -0
  67. data/spec/images/comparison.png +0 -0
  68. data/spec/images/decompressed.jpeg +0 -0
  69. data/spec/images/icecream.gif +0 -0
  70. data/spec/images/image.jpg +0 -0
  71. data/spec/images/invisiblepixels/generate +24 -0
  72. data/spec/images/invisiblepixels/image.png +0 -0
  73. data/spec/images/lena.jpg +0 -0
  74. data/spec/images/orient/0.jpg +0 -0
  75. data/spec/images/orient/1.jpg +0 -0
  76. data/spec/images/orient/2.jpg +0 -0
  77. data/spec/images/orient/3.jpg +0 -0
  78. data/spec/images/orient/4.jpg +0 -0
  79. data/spec/images/orient/5.jpg +0 -0
  80. data/spec/images/orient/6.jpg +0 -0
  81. data/spec/images/orient/7.jpg +0 -0
  82. data/spec/images/orient/8.jpg +0 -0
  83. data/spec/images/orient/generate +23 -0
  84. data/spec/images/orient/original.jpg +0 -0
  85. data/spec/images/quant/64.png +0 -0
  86. data/spec/images/quant/generate +25 -0
  87. data/spec/images/rails.png +0 -0
  88. data/spec/images/test.svg +3 -0
  89. data/spec/images/transparency1.png +0 -0
  90. data/spec/images/transparency2.png +0 -0
  91. data/spec/images/vergroessert.jpg +0 -0
  92. data/spec/spec_helper.rb +64 -0
  93. data/vendor/jpegrescan +143 -0
  94. metadata +308 -0
@@ -0,0 +1,95 @@
1
+ require 'spec_helper'
2
+ require 'image_optim/handler'
3
+
4
+ describe ImageOptim::Handler do
5
+ before do
6
+ stub_const('Handler', ImageOptim::Handler)
7
+ end
8
+
9
+ it 'uses original as source for first conversion '\
10
+ 'and two temp files for further conversions' do
11
+ original = double(:original)
12
+ allow(original).to receive(:temp_path) do
13
+ fail 'temp_path called unexpectedly'
14
+ end
15
+
16
+ handler = Handler.new(original)
17
+ temp_a = double(:temp_a)
18
+ temp_b = double(:temp_b)
19
+ expect(original).to receive(:temp_path).once.and_return(temp_a)
20
+ expect(original).to receive(:temp_path).once.and_return(temp_b)
21
+
22
+ # first unsuccessful run
23
+ handler.process do |src, dst|
24
+ expect([src, dst]).to eq([original, temp_a]); false
25
+ end
26
+ expect(handler.result).to be_nil
27
+
28
+ # first successful run
29
+ handler.process do |src, dst|
30
+ expect([src, dst]).to eq([original, temp_a]); true
31
+ end
32
+ expect(handler.result).to eq(temp_a)
33
+
34
+ # second unsuccessful run
35
+ handler.process do |src, dst|
36
+ expect([src, dst]).to eq([temp_a, temp_b]); false
37
+ end
38
+ expect(handler.result).to eq(temp_a)
39
+
40
+ # second successful run
41
+ handler.process do |src, dst|
42
+ expect([src, dst]).to eq([temp_a, temp_b]); true
43
+ end
44
+ expect(handler.result).to eq(temp_b)
45
+
46
+ # third successful run
47
+ handler.process do |src, dst|
48
+ expect([src, dst]).to eq([temp_b, temp_a]); true
49
+ end
50
+ expect(handler.result).to eq(temp_a)
51
+
52
+ # forth successful run
53
+ handler.process do |src, dst|
54
+ expect([src, dst]).to eq([temp_a, temp_b]); true
55
+ end
56
+ expect(handler.result).to eq(temp_b)
57
+
58
+ expect(temp_a).to receive(:unlink).once
59
+ handler.cleanup
60
+ handler.cleanup
61
+ end
62
+
63
+ describe :open do
64
+ it 'yields instance, runs cleanup and returns result' do
65
+ original = double
66
+ handler = double
67
+ result = double
68
+
69
+ expect(Handler).to receive(:new).
70
+ with(original).and_return(handler)
71
+ expect(handler).to receive(:process)
72
+ expect(handler).to receive(:cleanup)
73
+ expect(handler).to receive(:result).and_return(result)
74
+
75
+ expect(Handler.for(original) do |h|
76
+ h.process
77
+ end).to eq(result)
78
+ end
79
+
80
+ it 'cleans up if exception is raised' do
81
+ original = double
82
+ handler = double
83
+
84
+ expect(Handler).to receive(:new).
85
+ with(original).and_return(handler)
86
+ expect(handler).to receive(:cleanup)
87
+
88
+ expect do
89
+ Handler.for(original) do
90
+ fail 'hello'
91
+ end
92
+ end.to raise_error 'hello'
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,76 @@
1
+ require 'spec_helper'
2
+ require 'image_optim/hash_helpers'
3
+
4
+ describe ImageOptim::HashHelpers do
5
+ before do
6
+ stub_const('HashHelpers', ImageOptim::HashHelpers)
7
+ end
8
+
9
+ context 'stringify/simbolyze' do
10
+ symbol_keys = {
11
+ :a => 1,
12
+ :b => {
13
+ :c => [:a, 'a'],
14
+ :d => {},
15
+ },
16
+ }
17
+
18
+ string_keys = {
19
+ 'a' => 1,
20
+ 'b' => {
21
+ 'c' => [:a, 'a'],
22
+ 'd' => {},
23
+ },
24
+ }
25
+
26
+ it 'deep stringifies hash keys' do
27
+ expect(HashHelpers.deep_stringify_keys(symbol_keys)).to eq(string_keys)
28
+ expect(HashHelpers.deep_stringify_keys(string_keys)).to eq(string_keys)
29
+ end
30
+
31
+ it 'deep symbolises hash keys' do
32
+ expect(HashHelpers.deep_symbolise_keys(string_keys)).to eq(symbol_keys)
33
+ expect(HashHelpers.deep_symbolise_keys(symbol_keys)).to eq(symbol_keys)
34
+ end
35
+ end
36
+
37
+ it 'deep merges hashes' do
38
+ merge_a = {
39
+ :a => {
40
+ :b => 1,
41
+ :c => {
42
+ :d => 2,
43
+ :e => {
44
+ :f => true,
45
+ },
46
+ },
47
+ },
48
+ :y => 10,
49
+ }
50
+
51
+ merge_b = {
52
+ :a => {
53
+ :b => 2,
54
+ :c => {
55
+ :d => 3,
56
+ :e => false,
57
+ },
58
+ },
59
+ 'z' => 20,
60
+ }
61
+
62
+ merge_result = {
63
+ :a => {
64
+ :b => 2,
65
+ :c => {
66
+ :d => 3,
67
+ :e => false,
68
+ },
69
+ },
70
+ :y => 10,
71
+ 'z' => 20,
72
+ }
73
+
74
+ expect(HashHelpers.deep_merge(merge_a, merge_b)).to eq(merge_result)
75
+ end
76
+ end
@@ -0,0 +1,54 @@
1
+ require 'spec_helper'
2
+ require 'image_optim/image_path'
3
+
4
+ describe ImageOptim::ImagePath do
5
+ before do
6
+ stub_const('ImagePath', ImageOptim::ImagePath)
7
+ end
8
+
9
+ describe :convert do
10
+ it 'returns ImagePath for string' do
11
+ path = 'a'
12
+
13
+ expect(ImagePath.convert(path)).to be_a(ImagePath)
14
+ expect(ImagePath.convert(path)).to eq(ImagePath.new(path))
15
+
16
+ expect(ImagePath.convert(path)).not_to eq(path)
17
+ expect(ImagePath.convert(path)).not_to be(path)
18
+ end
19
+
20
+ it 'returns ImagePath for Pathname' do
21
+ pathname = Pathname.new('a')
22
+
23
+ expect(ImagePath.convert(pathname)).to be_a(ImagePath)
24
+ expect(ImagePath.convert(pathname)).to eq(ImagePath.new(pathname))
25
+
26
+ expect(ImagePath.convert(pathname)).to eq(pathname)
27
+ expect(ImagePath.convert(pathname)).not_to be(pathname)
28
+ end
29
+
30
+ it 'returns same instance for ImagePath' do
31
+ image_path = ImagePath.new('a')
32
+
33
+ expect(ImagePath.convert(image_path)).to be_a(ImagePath)
34
+ expect(ImagePath.convert(image_path)).to eq(ImagePath.new(image_path))
35
+
36
+ expect(ImagePath.convert(image_path)).to eq(image_path)
37
+ expect(ImagePath.convert(image_path)).to be(image_path)
38
+ end
39
+ end
40
+
41
+ describe :binread do
42
+ it 'reads binary data' do
43
+ data = (0..255).to_a.pack('c*')
44
+
45
+ path = ImagePath.temp_file_path
46
+ path.write(data)
47
+
48
+ expect(path.binread).to eq(data)
49
+ if ''.respond_to?(:encoding)
50
+ expect(path.binread.encoding).to eq(Encoding.find('ASCII-8BIT'))
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,121 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'ImageOptim::Railtie' do
4
+ require 'rails/all'
5
+ require 'image_optim/railtie'
6
+
7
+ def init_rails_app
8
+ Class.new(Rails::Application) do
9
+ # Rails 4 requires application class to have name
10
+ def self.name
11
+ 'Dummy'
12
+ end
13
+
14
+ config.active_support.deprecation = :stderr
15
+ config.eager_load = false
16
+
17
+ config.logger = Logger.new('/dev/null')
18
+
19
+ config.assets.tap do |assets|
20
+ assets.enabled = true
21
+ assets.version = '1.0'
22
+ assets.cache_store = :null_store
23
+ assets.paths = %w[spec/images]
24
+
25
+ assets.delete(:compress)
26
+ assets.delete(:image_optim)
27
+ end
28
+
29
+ yield config if block_given?
30
+ end.initialize!
31
+ end
32
+
33
+ after do
34
+ Rails.application = nil
35
+ end
36
+
37
+ describe :initialization do
38
+ it 'initializes by default' do
39
+ expect(ImageOptim).to receive(:new)
40
+ init_rails_app
41
+ end
42
+
43
+ it 'initializes if config.assets.image_optim is nil' do
44
+ expect(ImageOptim).to receive(:new)
45
+ init_rails_app do |config|
46
+ config.assets.image_optim = nil
47
+ end
48
+ end
49
+
50
+ it 'does not initialize if config.assets.image_optim is false' do
51
+ expect(ImageOptim).not_to receive(:new)
52
+ init_rails_app do |config|
53
+ config.assets.image_optim = false
54
+ end
55
+ end
56
+
57
+ it 'does not initialize if config.assets.compress is false' do
58
+ expect(ImageOptim).not_to receive(:new)
59
+ init_rails_app do |config|
60
+ config.assets.compress = false
61
+ end
62
+ end
63
+
64
+ describe 'options' do
65
+ it 'initializes with empty hash by default' do
66
+ expect(ImageOptim).to receive(:new).with({})
67
+ init_rails_app
68
+ end
69
+
70
+ it 'initializes with empty hash if config.assets.image_optim is true' do
71
+ expect(ImageOptim).to receive(:new).with({}).and_call_original
72
+ init_rails_app do |config|
73
+ config.assets.image_optim = true
74
+ end
75
+ end
76
+
77
+ it 'initializes with empty hash if config.assets.image_optim is nil' do
78
+ expect(ImageOptim).to receive(:new).with({}).and_call_original
79
+ init_rails_app do |config|
80
+ config.assets.image_optim = nil
81
+ end
82
+ end
83
+
84
+ it 'initializes with hash assigned to config.assets.image_optim' do
85
+ hash = double
86
+ expect(ImageOptim).to receive(:new).with(hash)
87
+ init_rails_app do |config|
88
+ config.assets.image_optim = hash
89
+ end
90
+ end
91
+ end
92
+ end
93
+
94
+ describe :assets do
95
+ before do
96
+ stub_const('ImagePath', ImageOptim::ImagePath)
97
+ end
98
+
99
+ %w[
100
+ icecream.gif
101
+ lena.jpg
102
+ rails.png
103
+ test.svg
104
+ ].each do |asset_name|
105
+ it "optimizes #{asset_name}" do
106
+ asset = init_rails_app.assets.find_asset(asset_name)
107
+
108
+ asset_data = asset.source
109
+ original = ImagePath.convert(asset.pathname)
110
+
111
+ expect(asset_data).to be_smaller_than(original)
112
+
113
+ ImagePath.temp_file_path %W[spec .#{original.format}] do |temp|
114
+ temp.write(asset_data)
115
+
116
+ expect(temp).to be_similar_to(original, 0)
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end if ENV['RAILS_VERSION']
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+ require 'image_optim/runner/glob_helpers'
3
+
4
+ describe ImageOptim::Runner::GlobHelpers do
5
+ before do
6
+ stub_const('GlobHelpers', ImageOptim::Runner::GlobHelpers)
7
+ end
8
+
9
+ describe :expand_braces do
10
+ {
11
+ 'hello.world' => %w[hello.world],
12
+ '{hello,.world}' => %w[hello .world],
13
+ 'hello{.,!}world' => %w[hello.world hello!world],
14
+ '{a,b},{c,d}' => %w[a,c b,c a,d b,d],
15
+ '{{a,b},{c,d}}' => %w[a b c d],
16
+ '{a,b,{c,d}}' => %w[a b c d],
17
+ '{\{a,b\},\{c,d\}}' => %w[\\{a b\\} \\{c d\\}],
18
+ 'test{ing,}' => %w[testing test],
19
+ }.each do |glob, expected|
20
+ it "expands #{glob}" do
21
+ expect(GlobHelpers.expand_braces(glob)).to match_array(expected)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,99 @@
1
+ require 'spec_helper'
2
+ require 'image_optim/runner/option_parser'
3
+
4
+ describe ImageOptim::Runner::OptionParser do
5
+ before do
6
+ stub_const('OptionParser', ImageOptim::Runner::OptionParser)
7
+ end
8
+
9
+ describe :parse! do
10
+ it 'returns empty hash for arguments without options' do
11
+ args = %w[foo bar]
12
+ expect(OptionParser.parse!(args)).to eq({})
13
+ expect(args).to eq(%w[foo bar])
14
+ end
15
+
16
+ it 'removes options from arguments' do
17
+ args = %w[-r foo bar]
18
+ OptionParser.parse!(args)
19
+ expect(args).to eq(%w[foo bar])
20
+ end
21
+
22
+ it 'stops parsing optiosn after --' do
23
+ args = %w[-- -r foo bar]
24
+ OptionParser.parse!(args)
25
+ expect(args).to eq(%w[-r foo bar])
26
+ end
27
+
28
+ describe 'boolean option recursive' do
29
+ %w[-r -R --recursive].each do |flag|
30
+ it "is parsed from #{flag}" do
31
+ args = %W[#{flag} foo bar]
32
+ expect(OptionParser.parse!(args)).to eq(:recursive => true)
33
+ expect(args).to eq(%w[foo bar])
34
+ end
35
+ end
36
+ end
37
+
38
+ describe 'numeric option threads' do
39
+ it 'is parsed with space separator' do
40
+ args = %w[--threads 616 foo bar]
41
+ expect(OptionParser.parse!(args)).to eq(:threads => 616)
42
+ expect(args).to eq(%w[foo bar])
43
+ end
44
+
45
+ it 'is parsed with equal separator' do
46
+ args = %w[--threads=616 foo bar]
47
+ expect(OptionParser.parse!(args)).to eq(:threads => 616)
48
+ expect(args).to eq(%w[foo bar])
49
+ end
50
+
51
+ it 'is parsed with no- prefix' do
52
+ args = %w[--no-threads 616 foo bar]
53
+ expect(OptionParser.parse!(args)).to eq(:threads => false)
54
+ expect(args).to eq(%w[616 foo bar])
55
+ end
56
+ end
57
+
58
+ describe 'help option' do
59
+ it 'prints help text to stdout and exits' do
60
+ parser = OptionParser.new({})
61
+ expect(OptionParser).to receive(:new).and_return(parser)
62
+
63
+ help = double
64
+ expect(parser).to receive(:help).and_return(help)
65
+
66
+ expect do
67
+ OptionParser.parse!(%w[--help])
68
+ end.to output("#{help}\n").to_stdout &
69
+ raise_error(SystemExit){ |e| expect(e.status).to eq(0) }
70
+ end
71
+ end
72
+
73
+ describe 'wrong option' do
74
+ it 'prints help text to stdout and exits' do
75
+ parser = OptionParser.new({})
76
+ expect(OptionParser).to receive(:new).and_return(parser)
77
+
78
+ help = double
79
+ expect(parser).to receive(:help).and_return(help)
80
+
81
+ expect do
82
+ OptionParser.parse!(%w[--unknown-option])
83
+ end.to output("invalid option: --unknown-option\n\n#{help}\n").
84
+ to_stderr & raise_error(SystemExit){ |e| expect(e.status).to eq(1) }
85
+ end
86
+ end
87
+ end
88
+
89
+ describe :help do
90
+ it 'returns wrapped text' do
91
+ parser = OptionParser.new({})
92
+
93
+ allow(parser).to receive(:terminal_columns).and_return(80)
94
+
95
+ expect(parser.help.split("\n")).
96
+ to all(satisfy{ |line| line.length <= 80 })
97
+ end
98
+ end
99
+ end