link_preview 0.3.1 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/link_preview/parser.rb +29 -26
- data/lib/link_preview/version.rb +1 -1
- data/spec/link_preview/parser_spec.rb +99 -15
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d2535acc6627654fb5a535f4d6b93cea2a7761fb
|
4
|
+
data.tar.gz: 39ff7d89c69212bc384ea9c255f587e22da44d13
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f9cd6097b70f642478431d32ea6be8e4015894197256228663614c4771f3e21181c5da94921a19c97b00898085c6bc442cca39f24a6961879c31ed2d32d76cff
|
7
|
+
data.tar.gz: 55ed4eb19b76211c1c1a84a60ff494eb63cd639e6438b9adf1f31db1e7133e250ea649557ae9fd729e3e815a2bf1676890ab779eb0d14a80680f2ca7cbb4658f
|
data/lib/link_preview/parser.rb
CHANGED
@@ -48,27 +48,6 @@ module LinkPreview
|
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
|
-
def parse_image(data)
|
52
|
-
{
|
53
|
-
image: {
|
54
|
-
image_url: data.url,
|
55
|
-
image_data: parse_image_data(data),
|
56
|
-
image_content_type: data.headers[:content_type],
|
57
|
-
image_file_name: parse_image_file_name(data)
|
58
|
-
}
|
59
|
-
}
|
60
|
-
end
|
61
|
-
|
62
|
-
def parse_image_file_name(data)
|
63
|
-
content_disposition_filename = parse_content_disposition_filename(data)
|
64
|
-
if content_disposition_filename.present?
|
65
|
-
content_disposition_filename
|
66
|
-
elsif data.url
|
67
|
-
parsed_uri = LinkPreview::URI.parse(data.url, @options)
|
68
|
-
parsed_uri.path.split('/').last || parsed_uri.hostname.tr('.', '_')
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
51
|
private
|
73
52
|
|
74
53
|
def ignore_opengraph_video_type_html?
|
@@ -102,6 +81,27 @@ module LinkPreview
|
|
102
81
|
}
|
103
82
|
end
|
104
83
|
|
84
|
+
def parse_image(data)
|
85
|
+
{
|
86
|
+
image: {
|
87
|
+
image_url: data.url,
|
88
|
+
image_data: parse_image_data(data),
|
89
|
+
image_content_type: data.headers[:content_type],
|
90
|
+
image_file_name: parse_image_file_name(data)
|
91
|
+
}
|
92
|
+
}
|
93
|
+
end
|
94
|
+
|
95
|
+
def parse_image_file_name(data)
|
96
|
+
content_disposition_filename = parse_content_disposition_filename(data)
|
97
|
+
if content_disposition_filename.present?
|
98
|
+
content_disposition_filename
|
99
|
+
elsif data.url
|
100
|
+
parsed_uri = LinkPreview::URI.parse(data.url, @options)
|
101
|
+
parsed_uri.path.split('/').last || parsed_uri.hostname.tr('.', '_')
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
105
|
def parse_opengraph_common_data(doc)
|
106
106
|
opengraph_image_array_first_elem = find_meta_property_array(doc, 'og:image').first
|
107
107
|
{
|
@@ -145,16 +145,17 @@ module LinkPreview
|
|
145
145
|
)
|
146
146
|
end
|
147
147
|
|
148
|
-
def parse_oembed(data)
|
149
|
-
# TODO: validate oembed response
|
150
|
-
{ oembed: (parse_oembed_data(data) || {}).merge(url: parse_oembed_content_url(data)) }
|
151
|
-
end
|
152
|
-
|
153
148
|
def parse_video_url_content(uri)
|
154
149
|
url = LinkPreview::URI.parse(uri, @options)
|
155
150
|
@config.http_client.get(url.to_s, @options)
|
156
151
|
end
|
157
152
|
|
153
|
+
def parse_oembed(data)
|
154
|
+
oembed_data = parse_oembed_data(data)
|
155
|
+
return {} unless oembed_data.is_a?(Hash) && oembed_data['type']
|
156
|
+
{ oembed: oembed_data.merge(url: parse_oembed_content_url(data)) }
|
157
|
+
end
|
158
|
+
|
158
159
|
def parse_oembed_data(data)
|
159
160
|
case data.headers[:content_type]
|
160
161
|
when /xml/
|
@@ -162,6 +163,8 @@ module LinkPreview
|
|
162
163
|
when /json/
|
163
164
|
MultiJson.load(data.body)
|
164
165
|
end
|
166
|
+
rescue
|
167
|
+
nil
|
165
168
|
end
|
166
169
|
|
167
170
|
def parse_oembed_content_url(data)
|
data/lib/link_preview/version.rb
CHANGED
@@ -23,35 +23,119 @@
|
|
23
23
|
require 'spec_helper'
|
24
24
|
|
25
25
|
describe LinkPreview::Parser do
|
26
|
-
describe '#
|
26
|
+
describe '#parse' do
|
27
27
|
let(:config) { double(LinkPreview::Configuration) }
|
28
28
|
let(:parser) { LinkPreview::Parser.new(config) }
|
29
29
|
let(:response) do
|
30
30
|
Faraday::Response.new.tap do |response|
|
31
|
-
allow(response).to receive(:headers).and_return(
|
31
|
+
allow(response).to receive(:headers).and_return(headers)
|
32
|
+
allow(response).to receive(:url).and_return(url)
|
33
|
+
allow(response).to receive(:body).and_return(body)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
subject(:data) { parser.parse(response) }
|
38
|
+
|
39
|
+
shared_examples 'oembed' do
|
40
|
+
context 'when empty string' do
|
41
|
+
let(:content) { '' }
|
42
|
+
it { expect(data).to be_empty }
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'when empty hash' do
|
46
|
+
let(:content) { {} }
|
47
|
+
it { expect(data).to be_empty }
|
48
|
+
end
|
32
49
|
|
33
|
-
|
50
|
+
context 'when invalid' do
|
51
|
+
let(:content) { { 'version' => '1.0' } }
|
52
|
+
it { expect(data).to be_empty }
|
53
|
+
end
|
54
|
+
|
55
|
+
context 'when valid link' do
|
56
|
+
let(:content) { { 'version' => '1.0', 'type' => 'link' } }
|
57
|
+
it { expect(data[:oembed]).to include(content) }
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'when valid photo' do
|
61
|
+
let(:content) { { 'version' => '1.0', 'type' => 'photo', 'url' => 'http://example.com/image.jpg' } }
|
62
|
+
it { expect(data[:oembed]).to include(content) }
|
63
|
+
end
|
64
|
+
|
65
|
+
context 'when valid video' do
|
66
|
+
let(:content) { { 'version' => '1.0', 'type' => 'video', 'url' => 'http://example.com/videos/1.mp4', 'html' => '<video src="http://example.com/videos/1.mp4"></video>' } }
|
67
|
+
it { expect(data[:oembed]).to include(content) }
|
68
|
+
end
|
69
|
+
|
70
|
+
context 'when valid rich' do
|
71
|
+
let(:content) { { 'version' => '1.0', 'type' => 'rich', 'url' => 'http://example.com/widget/1', 'html' => '<iframe></iframe>' } }
|
72
|
+
it { expect(data[:oembed]).to include(content) }
|
34
73
|
end
|
35
74
|
end
|
36
75
|
|
37
|
-
context '
|
38
|
-
let(:
|
39
|
-
|
40
|
-
|
76
|
+
context 'with json oembed response' do
|
77
|
+
let(:headers) { { content_type: 'application/json' } }
|
78
|
+
let(:url) { 'http://example.com/oembed?url=http%3A%2F%2Fexample.com&format=json' }
|
79
|
+
|
80
|
+
let(:body) do
|
81
|
+
JSON.dump(content)
|
41
82
|
end
|
83
|
+
|
84
|
+
include_examples 'oembed'
|
42
85
|
end
|
43
86
|
|
44
|
-
context '
|
45
|
-
let(:
|
46
|
-
|
47
|
-
|
87
|
+
context 'with xml oembed response' do
|
88
|
+
let(:headers) { { content_type: 'text/xml' } }
|
89
|
+
let(:url) { 'http://example.com/oembed?url=http%3A%2F%2Fexample.com&format=xml' }
|
90
|
+
|
91
|
+
let(:body) do
|
92
|
+
case content
|
93
|
+
when Hash
|
94
|
+
content.to_xml(root: 'oembed')
|
95
|
+
else
|
96
|
+
<<-EOS
|
97
|
+
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
98
|
+
<oembed></oembed>
|
99
|
+
EOS
|
100
|
+
end
|
48
101
|
end
|
102
|
+
|
103
|
+
include_examples 'oembed'
|
49
104
|
end
|
50
105
|
|
51
|
-
context '
|
52
|
-
let(:
|
53
|
-
|
54
|
-
|
106
|
+
context 'with image response' do
|
107
|
+
let(:headers) { { content_type: 'image/jpg', :'content-disposition' => content_disposition } }
|
108
|
+
let(:url) { 'http://example.com/image-url.jpg' }
|
109
|
+
let(:body) { '' }
|
110
|
+
|
111
|
+
context 'when the content-disposition header contains a valid filename' do
|
112
|
+
let(:content_disposition) { 'inline;filename="image-cd.jpg"' }
|
113
|
+
|
114
|
+
it do
|
115
|
+
expect(data[:image][:image_url]).to eq(url)
|
116
|
+
expect(data[:image][:image_content_type]).to eq('image/jpg')
|
117
|
+
expect(data[:image][:image_file_name]).to eq('image-cd.jpg')
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
context 'when the content-disposition header does not contain a filename' do
|
122
|
+
let(:content_disposition) { 'inline;' }
|
123
|
+
|
124
|
+
it do
|
125
|
+
expect(data[:image][:image_url]).to eq(url)
|
126
|
+
expect(data[:image][:image_content_type]).to eq('image/jpg')
|
127
|
+
expect(data[:image][:image_file_name]).to eq('image-url.jpg')
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
context 'when the content-disposition header contains a blank filename' do
|
132
|
+
let(:content_disposition) { 'inline;filename=""' }
|
133
|
+
|
134
|
+
it do
|
135
|
+
expect(data[:image][:image_url]).to eq(url)
|
136
|
+
expect(data[:image][:image_content_type]).to eq('image/jpg')
|
137
|
+
expect(data[:image][:image_file_name]).to eq('image-url.jpg')
|
138
|
+
end
|
55
139
|
end
|
56
140
|
end
|
57
141
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: link_preview
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Andrews
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-04-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ruby-oembed
|
@@ -122,6 +122,20 @@ dependencies:
|
|
122
122
|
- - ">="
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: builder
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
125
139
|
- !ruby/object:Gem::Dependency
|
126
140
|
name: rspec
|
127
141
|
requirement: !ruby/object:Gem::Requirement
|