video_info 2.5.0 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +3 -0
- data/README.md +9 -21
- data/foo.txt +33 -0
- data/lib/video_info.rb +17 -4
- data/lib/video_info/provider.rb +22 -1
- data/lib/video_info/providers/vimeo.rb +13 -103
- data/lib/video_info/providers/vimeo_api.rb +110 -0
- data/lib/video_info/providers/vimeo_scraper.rb +135 -0
- data/lib/video_info/providers/vkontakte.rb +15 -8
- data/lib/video_info/providers/youtube.rb +3 -6
- data/lib/video_info/providers/youtube_api.rb +3 -1
- data/lib/video_info/providers/youtube_scraper.rb +11 -15
- data/lib/video_info/providers/youtubeplaylist.rb +1 -1
- data/lib/video_info/providers/youtubeplaylist_api.rb +12 -0
- data/lib/video_info/version.rb +1 -1
- data/spec/lib/video_info/providers/vimeo_api_spec.rb +242 -0
- data/spec/lib/video_info/providers/vimeo_spec.rb +4 -4
- data/spec/lib/video_info/providers/vkontakte_spec.rb +41 -2
- data/spec/lib/video_info/providers/youtube_api_spec.rb +84 -0
- data/spec/lib/video_info/providers/youtube_playlist_api_spec.rb +15 -1
- data/spec/lib/video_info/providers/youtube_playlist_spec.rb +16 -2
- data/spec/lib/video_info/providers/youtube_spec.rb +146 -0
- data/video_info.gemspec +6 -5
- metadata +42 -26
- data/lib/video_info/providers/vimeoplaylist.rb +0 -63
- data/spec/lib/video_info/providers/vimeo_playlist_spec.rb +0 -157
@@ -2,7 +2,7 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe VideoInfo::Providers::Vimeo do
|
4
4
|
before(:all) do
|
5
|
-
VideoInfo.provider_api_keys = {
|
5
|
+
VideoInfo.provider_api_keys = { }
|
6
6
|
end
|
7
7
|
|
8
8
|
describe '.usable?' do
|
@@ -54,7 +54,7 @@ describe VideoInfo::Providers::Vimeo do
|
|
54
54
|
end
|
55
55
|
|
56
56
|
context "with 'this video does not exist' video", :vcr do
|
57
|
-
subject { VideoInfo.new('http://vimeo.com/
|
57
|
+
subject { VideoInfo.new('http://vimeo.com/593123111') }
|
58
58
|
|
59
59
|
describe '#available?' do
|
60
60
|
it { is_expected.to_not be_available }
|
@@ -120,12 +120,12 @@ describe VideoInfo::Providers::Vimeo do
|
|
120
120
|
|
121
121
|
describe '#width' do
|
122
122
|
subject { super().width }
|
123
|
-
it { is_expected.to eq
|
123
|
+
it { is_expected.to eq 1280 }
|
124
124
|
end
|
125
125
|
|
126
126
|
describe '#height' do
|
127
127
|
subject { super().height }
|
128
|
-
it { is_expected.to eq
|
128
|
+
it { is_expected.to eq 720 }
|
129
129
|
end
|
130
130
|
|
131
131
|
describe '#date' do
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
require 'spec_helper'
|
3
|
+
require 'webmock/rspec'
|
3
4
|
|
4
5
|
describe VideoInfo::Providers::Vkontakte do
|
5
6
|
|
@@ -77,6 +78,17 @@ describe VideoInfo::Providers::Vkontakte do
|
|
77
78
|
|
78
79
|
end
|
79
80
|
|
81
|
+
context "with video https://vk.com/id44052340?z=video61291456_159590018%2F2521d92730a272a9ea", :vcr do
|
82
|
+
subject { VideoInfo.new('https://vk.com/id44052340?z=video61291456_159590018%2F2521d92730a272a9ea') }
|
83
|
+
|
84
|
+
its(:provider) { should eq 'Vkontakte' }
|
85
|
+
its(:video_owner) { should eq '61291456' }
|
86
|
+
its(:video_id) { should eq '159590018' }
|
87
|
+
its(:title) { should eq 'Happy Birthday To You' }
|
88
|
+
its(:embed_url) { should eq '//vk.com/video_ext.php?oid=61291456&id=159590018&hash=68174b2af560c54c' }
|
89
|
+
its(:embed_code) { should eq '<iframe src="//vk.com/video_ext.php?oid=61291456&id=159590018&hash=68174b2af560c54c" frameborder="0" allowfullscreen="allowfullscreen"></iframe>' }
|
90
|
+
end
|
91
|
+
|
80
92
|
context "with video videos43640822#/video43640822_168790809", :vcr do
|
81
93
|
subject { VideoInfo.new('https://vk.com/videos43640822#/video43640822_168790809') }
|
82
94
|
|
@@ -93,8 +105,8 @@ describe VideoInfo::Providers::Vkontakte do
|
|
93
105
|
its(:video_owner) { should eq '2152699' }
|
94
106
|
its(:video_id) { should eq '168591741' }
|
95
107
|
its(:url) { should eq 'https://vk.com/kirill.lyanoi?z=video2152699_168591741%2F56fd229a9dfe2dcdbe' }
|
96
|
-
its(:embed_url) { should eq '//
|
97
|
-
its(:embed_code) { should eq '<iframe src="//
|
108
|
+
its(:embed_url) { should eq '//vk.com/video_ext.php?oid=2152699&id=168591741&hash=' }
|
109
|
+
its(:embed_code) { should eq '<iframe src="//vk.com/video_ext.php?oid=2152699&id=168591741&hash=" frameborder="0" allowfullscreen="allowfullscreen"></iframe>' }
|
98
110
|
its(:title) { should eq 'BEAT SOUL STEP — RDC14 Project818 Russian Dance Championship, May 1-2, Moscow 2014' }
|
99
111
|
its(:description) { should start_with 'BEAT SOUL STEP ★ Project818 Russian Dance Championship ★ 1-2 мая, Москва 2014' }
|
100
112
|
its(:keywords) { should start_with 'BEAT SOUL STEP ★ Project818 Russian Dance Championship ★ 1-2 мая, Москва 2014' }
|
@@ -131,4 +143,31 @@ describe VideoInfo::Providers::Vkontakte do
|
|
131
143
|
its(:title) { should eq 'SpaceGlasses are the future of computing' }
|
132
144
|
end
|
133
145
|
|
146
|
+
context 'with valid video and connection timeout' do
|
147
|
+
subject { VideoInfo.new('http://vk.com/video-54799401_165822734') }
|
148
|
+
|
149
|
+
describe '#title' do
|
150
|
+
before do
|
151
|
+
stub_request(:any, /.*vk.com.*/).to_timeout
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'raises VideoInfo::HttpError exception' do
|
155
|
+
expect { subject.title }.to raise_error VideoInfo::HttpError
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
context 'with valid video and OpenURI::HTTPError exception' do
|
161
|
+
subject { VideoInfo.new('http://vk.com/video-54799401_165822734') }
|
162
|
+
|
163
|
+
describe '#title' do
|
164
|
+
before do
|
165
|
+
stub_request(:any, /.*vk.com.*/).to_raise(OpenURI::HTTPError.new('error', :nop))
|
166
|
+
end
|
167
|
+
|
168
|
+
it 'raises VideoInfo::HttpError exception' do
|
169
|
+
expect { subject.title }.to raise_error VideoInfo::HttpError
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
134
173
|
end
|
@@ -389,4 +389,88 @@ describe VideoInfo::Providers::Youtube do
|
|
389
389
|
it { expect(subject.embed_code(iframe_attributes: { :'data-colorbox' => true })).to match(/data-colorbox="true"/) }
|
390
390
|
end
|
391
391
|
|
392
|
+
context "with full screen video URLs", :vcr do
|
393
|
+
subject { VideoInfo.new('http://www.youtube.com/v/mZqGqE0D0n4') }
|
394
|
+
|
395
|
+
describe '#provider' do
|
396
|
+
subject { super().provider }
|
397
|
+
it { is_expected.to eq 'YouTube' }
|
398
|
+
end
|
399
|
+
|
400
|
+
describe '#video_id' do
|
401
|
+
subject { super().video_id }
|
402
|
+
it { is_expected.to eq 'mZqGqE0D0n4' }
|
403
|
+
end
|
404
|
+
|
405
|
+
describe '#url' do
|
406
|
+
subject { super().url }
|
407
|
+
it { is_expected.to eq 'http://www.youtube.com/v/mZqGqE0D0n4' }
|
408
|
+
end
|
409
|
+
|
410
|
+
describe '#embed_url' do
|
411
|
+
subject { super().embed_url }
|
412
|
+
it { is_expected.to eq '//www.youtube.com/embed/mZqGqE0D0n4' }
|
413
|
+
end
|
414
|
+
|
415
|
+
describe '#embed_code' do
|
416
|
+
subject { super().embed_code }
|
417
|
+
it { is_expected.to eq '<iframe src="//www.youtube.com/embed/mZqGqE0D0n4" frameborder="0" allowfullscreen="allowfullscreen"></iframe>' }
|
418
|
+
end
|
419
|
+
|
420
|
+
describe '#title' do
|
421
|
+
subject { super().title }
|
422
|
+
it { is_expected.to eq 'Cherry Bloom - King Of The Knife' }
|
423
|
+
end
|
424
|
+
|
425
|
+
describe '#description' do
|
426
|
+
subject { super().description }
|
427
|
+
it { is_expected.to eq 'The first video from the upcoming album Secret Sounds, to download in-stores April 14. Checkout http://www.cherrybloom.net' }
|
428
|
+
end
|
429
|
+
|
430
|
+
describe '#keywords' do
|
431
|
+
subject { super().keywords }
|
432
|
+
it { is_expected.to eq %w(cherry bloom king of the knife guitar drum clip rock alternative tremplin Paris-Forum) }
|
433
|
+
end
|
434
|
+
|
435
|
+
describe '#duration' do
|
436
|
+
subject { super().duration }
|
437
|
+
it { is_expected.to eq 176 }
|
438
|
+
end
|
439
|
+
|
440
|
+
describe '#width' do
|
441
|
+
subject { super().width }
|
442
|
+
it { is_expected.to be_nil }
|
443
|
+
end
|
444
|
+
|
445
|
+
describe '#height' do
|
446
|
+
subject { super().height }
|
447
|
+
it { is_expected.to be_nil }
|
448
|
+
end
|
449
|
+
|
450
|
+
describe '#date' do
|
451
|
+
subject { super().date }
|
452
|
+
it { is_expected.to eq Time.parse('Sat Apr 12 22:25:35 UTC 2008', Time.now.utc) }
|
453
|
+
end
|
454
|
+
|
455
|
+
describe '#thumbnail_small' do
|
456
|
+
subject { super().thumbnail_small }
|
457
|
+
it { is_expected.to eq 'https://i.ytimg.com/vi/mZqGqE0D0n4/default.jpg' }
|
458
|
+
end
|
459
|
+
|
460
|
+
describe '#thumbnail_medium' do
|
461
|
+
subject { super().thumbnail_medium }
|
462
|
+
it { is_expected.to eq 'https://i.ytimg.com/vi/mZqGqE0D0n4/mqdefault.jpg' }
|
463
|
+
end
|
464
|
+
|
465
|
+
describe '#thumbnail_large' do
|
466
|
+
subject { super().thumbnail_large }
|
467
|
+
it { is_expected.to eq 'https://i.ytimg.com/vi/mZqGqE0D0n4/hqdefault.jpg' }
|
468
|
+
end
|
469
|
+
|
470
|
+
describe '#view_count' do
|
471
|
+
subject { super().view_count }
|
472
|
+
it { is_expected.to be > 4000 }
|
473
|
+
end
|
474
|
+
end
|
475
|
+
|
392
476
|
end
|
@@ -8,11 +8,16 @@ describe VideoInfo::Providers::YoutubePlaylist do
|
|
8
8
|
describe ".usable?" do
|
9
9
|
subject { VideoInfo::Providers::YoutubePlaylist.usable?(url) }
|
10
10
|
|
11
|
-
context "with youtube.com/playlist url" do
|
11
|
+
context "with youtube.com/playlist?p= url" do
|
12
12
|
let(:url) { 'http://www.youtube.com/playlist?p=PLA575C81A1FBC04CF' }
|
13
13
|
it { is_expected.to be_truthy }
|
14
14
|
end
|
15
15
|
|
16
|
+
context "with youtube.com/playlist?list= url" do
|
17
|
+
let(:url) { 'http://www.youtube.com/playlist?list=PLA575C81A1FBC04CF' }
|
18
|
+
it { is_expected.to be_truthy }
|
19
|
+
end
|
20
|
+
|
16
21
|
context "with youtube.com url" do
|
17
22
|
let(:url) { 'http://www.youtube.com/watch?v=Xp6CXF' }
|
18
23
|
it { is_expected.to be_falsey }
|
@@ -42,6 +47,15 @@ describe VideoInfo::Providers::YoutubePlaylist do
|
|
42
47
|
it { is_expected.to be_falsey }
|
43
48
|
end
|
44
49
|
end
|
50
|
+
|
51
|
+
context "with &list= url", :vcr do
|
52
|
+
subject { VideoInfo.new('http://www.youtube.com/playlist?list=PLA575C81A1FBC04CF') }
|
53
|
+
|
54
|
+
describe '#available?' do
|
55
|
+
subject { super().available? }
|
56
|
+
it { is_expected.to be_truthy }
|
57
|
+
end
|
58
|
+
end
|
45
59
|
end
|
46
60
|
|
47
61
|
context "with playlist PL9hW1uS6HUftLdHI6RIsaf", :vcr do
|
@@ -8,11 +8,16 @@ describe VideoInfo::Providers::YoutubePlaylist do
|
|
8
8
|
describe ".usable?" do
|
9
9
|
subject { VideoInfo::Providers::YoutubePlaylist.usable?(url) }
|
10
10
|
|
11
|
-
context "with youtube.com/playlist url" do
|
11
|
+
context "with youtube.com/playlist?p= url" do
|
12
12
|
let(:url) { 'http://www.youtube.com/playlist?p=PLA575C81A1FBC04CF' }
|
13
13
|
it { is_expected.to be_truthy }
|
14
14
|
end
|
15
15
|
|
16
|
+
context "with youtube.com/playlist?list= url" do
|
17
|
+
let(:url) { 'http://www.youtube.com/playlist?list=PLA575C81A1FBC04CF' }
|
18
|
+
it { is_expected.to be_truthy }
|
19
|
+
end
|
20
|
+
|
16
21
|
context "with youtube.com url" do
|
17
22
|
let(:url) { 'http://www.youtube.com/watch?v=Xp6CXF' }
|
18
23
|
it { is_expected.to be_falsey }
|
@@ -42,6 +47,15 @@ describe VideoInfo::Providers::YoutubePlaylist do
|
|
42
47
|
it { is_expected.to be_falsey }
|
43
48
|
end
|
44
49
|
end
|
50
|
+
|
51
|
+
context "with &list= url", :vcr do
|
52
|
+
subject { VideoInfo.new('http://www.youtube.com/playlist?list=PLA575C81A1FBC04CF') }
|
53
|
+
|
54
|
+
describe '#available?' do
|
55
|
+
subject { super().available? }
|
56
|
+
it { is_expected.to be_truthy }
|
57
|
+
end
|
58
|
+
end
|
45
59
|
end
|
46
60
|
|
47
61
|
context "with playlist PL9hW1uS6HUftLdHI6RIsaf", :vcr do
|
@@ -134,7 +148,7 @@ describe VideoInfo::Providers::YoutubePlaylist do
|
|
134
148
|
|
135
149
|
describe '#videos' do
|
136
150
|
subject { super().videos }
|
137
|
-
it { expect { subject}.to raise_error(NotImplementedError) }
|
151
|
+
it { expect { subject }.to raise_error(NotImplementedError) }
|
138
152
|
end
|
139
153
|
|
140
154
|
describe '#view_count' do
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
+
require 'webmock/rspec'
|
2
3
|
|
3
4
|
describe VideoInfo::Providers::Youtube do
|
4
5
|
describe ".usable?" do
|
@@ -35,6 +36,25 @@ describe VideoInfo::Providers::Youtube do
|
|
35
36
|
end
|
36
37
|
end
|
37
38
|
|
39
|
+
context 'with valid video and invalid API key' do
|
40
|
+
subject { VideoInfo.new('http://www.youtube.com/watch?v=mZqGqE0D0n4') }
|
41
|
+
let(:msg) { 'your API key is probably invalid. Please verify it.' }
|
42
|
+
before do
|
43
|
+
VideoInfo.provider_api_keys[:youtube] = 'invalid_key'
|
44
|
+
end
|
45
|
+
|
46
|
+
after do
|
47
|
+
VideoInfo.provider_api_keys[:youtube] = nil
|
48
|
+
end
|
49
|
+
|
50
|
+
describe '#available?' do
|
51
|
+
it 'logs warning message to alert user about invalid API key' do
|
52
|
+
expect(VideoInfo.logger).to receive(:warn).with(msg)
|
53
|
+
subject.title
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
38
58
|
context "with 'video is unavailable' video", :vcr do
|
39
59
|
subject { VideoInfo.new('http://www.youtube.com/watch?v=SUkXvWn1m7Q') }
|
40
60
|
|
@@ -393,4 +413,130 @@ describe VideoInfo::Providers::Youtube do
|
|
393
413
|
it { is_expected.to eq ('Deafheaven - Sunbather') }
|
394
414
|
end
|
395
415
|
end
|
416
|
+
|
417
|
+
context "with full screen video URLs", :vcr do
|
418
|
+
subject { VideoInfo.new('http://www.youtube.com/v/mZqGqE0D0n4') }
|
419
|
+
|
420
|
+
describe '#provider' do
|
421
|
+
subject { super().provider }
|
422
|
+
it { is_expected.to eq 'YouTube' }
|
423
|
+
end
|
424
|
+
|
425
|
+
describe '#video_id' do
|
426
|
+
subject { super().video_id }
|
427
|
+
it { is_expected.to eq 'mZqGqE0D0n4' }
|
428
|
+
end
|
429
|
+
|
430
|
+
describe '#url' do
|
431
|
+
subject { super().url }
|
432
|
+
it { is_expected.to eq 'http://www.youtube.com/v/mZqGqE0D0n4' }
|
433
|
+
end
|
434
|
+
|
435
|
+
describe '#embed_url' do
|
436
|
+
subject { super().embed_url }
|
437
|
+
it { is_expected.to eq '//www.youtube.com/embed/mZqGqE0D0n4' }
|
438
|
+
end
|
439
|
+
|
440
|
+
describe '#embed_code' do
|
441
|
+
subject { super().embed_code }
|
442
|
+
it { is_expected.to eq '<iframe src="//www.youtube.com/embed/mZqGqE0D0n4" frameborder="0" allowfullscreen="allowfullscreen"></iframe>' }
|
443
|
+
end
|
444
|
+
|
445
|
+
describe '#title' do
|
446
|
+
subject { super().title }
|
447
|
+
it { is_expected.to eq 'Cherry Bloom - King Of The Knife' }
|
448
|
+
end
|
449
|
+
|
450
|
+
describe '#description' do
|
451
|
+
subject { super().description }
|
452
|
+
it { is_expected.to eq 'The first video from the upcoming album Secret Sounds, to download in-stores April 14. Checkout http://www.cherrybloom.net' }
|
453
|
+
end
|
454
|
+
|
455
|
+
describe '#keywords' do
|
456
|
+
subject { super().keywords }
|
457
|
+
it { is_expected.to eq %w(cherry bloom king of the knife guitar drum clip rock alternative tremplin Paris-Forum) }
|
458
|
+
end
|
459
|
+
|
460
|
+
describe '#duration' do
|
461
|
+
subject { super().duration }
|
462
|
+
it { is_expected.to eq 176 }
|
463
|
+
end
|
464
|
+
|
465
|
+
describe '#width' do
|
466
|
+
subject { super().width }
|
467
|
+
it { is_expected.to be_nil }
|
468
|
+
end
|
469
|
+
|
470
|
+
describe '#height' do
|
471
|
+
subject { super().height }
|
472
|
+
it { is_expected.to be_nil }
|
473
|
+
end
|
474
|
+
|
475
|
+
describe '#date' do
|
476
|
+
subject { super().date }
|
477
|
+
it { is_expected.to eq Time.parse('Sat Apr 12 2008', Time.now.utc) }
|
478
|
+
end
|
479
|
+
|
480
|
+
describe '#thumbnail_small' do
|
481
|
+
subject { super().thumbnail_small }
|
482
|
+
it { is_expected.to eq 'https://i.ytimg.com/vi/mZqGqE0D0n4/default.jpg' }
|
483
|
+
end
|
484
|
+
|
485
|
+
describe '#thumbnail_medium' do
|
486
|
+
subject { super().thumbnail_medium }
|
487
|
+
it { is_expected.to eq 'https://i.ytimg.com/vi/mZqGqE0D0n4/mqdefault.jpg' }
|
488
|
+
end
|
489
|
+
|
490
|
+
describe '#thumbnail_large' do
|
491
|
+
subject { super().thumbnail_large }
|
492
|
+
it { is_expected.to eq 'https://i.ytimg.com/vi/mZqGqE0D0n4/hqdefault.jpg' }
|
493
|
+
end
|
494
|
+
|
495
|
+
describe '#view_count' do
|
496
|
+
subject { super().view_count }
|
497
|
+
it { is_expected.to be > 4000 }
|
498
|
+
end
|
499
|
+
end
|
500
|
+
|
501
|
+
|
502
|
+
context "with full screen video URLs with params", :vcr do
|
503
|
+
subject { VideoInfo.new('https://www.youtube.com/v/ylTY9WbMGDc?someParam=foo') }
|
504
|
+
|
505
|
+
describe '#title' do
|
506
|
+
subject { super().title }
|
507
|
+
it { is_expected.to eq 'Deafheaven - Sunbather' }
|
508
|
+
end
|
509
|
+
end
|
510
|
+
|
511
|
+
context 'with valid video and connection timeout' do
|
512
|
+
subject { VideoInfo.new('https://www.youtube.com/watch?v=lExm5LELpP4') }
|
513
|
+
|
514
|
+
describe '#title' do
|
515
|
+
before do
|
516
|
+
@stubbed = stub_request(:get, 'https://www.youtube.com/watch?v=lExm5LELpP4').to_timeout
|
517
|
+
end
|
518
|
+
|
519
|
+
after do
|
520
|
+
remove_request_stub(@stubbed) if @stubbed
|
521
|
+
end
|
522
|
+
|
523
|
+
it 'raises VideoInfo::HttpError exception' do
|
524
|
+
expect { subject.title }.to raise_error VideoInfo::HttpError
|
525
|
+
end
|
526
|
+
end
|
527
|
+
end
|
528
|
+
|
529
|
+
context 'with valid video and OpenURI::HTTPError exception' do
|
530
|
+
subject { VideoInfo.new('https://www.youtube.com/watch?v=lExm5LELpP4') }
|
531
|
+
|
532
|
+
describe '#title' do
|
533
|
+
before do
|
534
|
+
stub_request(:get, 'https://www.youtube.com/watch?v=lExm5LELpP4').to_raise(OpenURI::HTTPError.new('error', :nop))
|
535
|
+
end
|
536
|
+
|
537
|
+
it 'raises VideoInfo::HttpError exception' do
|
538
|
+
expect { subject.title }.to raise_error VideoInfo::HttpError
|
539
|
+
end
|
540
|
+
end
|
541
|
+
end
|
396
542
|
end
|
data/video_info.gemspec
CHANGED
@@ -20,12 +20,13 @@ Gem::Specification.new do |s|
|
|
20
20
|
|
21
21
|
s.required_ruby_version = '>= 1.9.3'
|
22
22
|
|
23
|
-
s.add_dependency 'addressable'
|
23
|
+
s.add_dependency 'addressable', '~> 2.3'
|
24
24
|
s.add_dependency 'multi_json', '~> 1.11'
|
25
|
-
s.add_dependency 'htmlentities'
|
26
|
-
s.add_dependency 'iso8601'
|
27
|
-
s.add_dependency 'oga'
|
28
|
-
s.add_dependency 'open_uri_redirections'
|
25
|
+
s.add_dependency 'htmlentities', '~> 4.3'
|
26
|
+
s.add_dependency 'iso8601', '~> 0.9'
|
27
|
+
s.add_dependency 'oga', '~> 2.2'
|
28
|
+
s.add_dependency 'open_uri_redirections', '~> 0.2'
|
29
|
+
s.add_dependency 'net_http_timeout_errors', '~> 0.3.0'
|
29
30
|
|
30
31
|
s.add_development_dependency 'bundler', '>= 1.3.5'
|
31
32
|
s.add_development_dependency 'rake'
|