link_preview 0.3.1 → 0.3.2
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/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
|