link-preview 0.0.3

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 ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ OGRiMDRjOTI2ODE4MTQzZDBlNDdlNjBjZjMzN2Q3NmU4Mjk4N2YxMA==
5
+ data.tar.gz: !binary |-
6
+ NzdhYTkyMmYwNGQwMDAzYzE3NTNjZDdhY2U1ZmRjNTJlZmEzZDU5Mg==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ NGI4ODQyMjU3MzhhMGQ0MThmYjE3ODk1NjBiNjg3ZTNhMTMwOGUyMDQ2MDgx
10
+ ZTU3NTlmY2E3MDlmYmY5NTk1NTgxNDdjNjliMWM1Mzc4YjEwYTEyOGM3OWYy
11
+ ZjljM2Y0ODUzMTU4Y2U1NTIxNmM0OTNmYWE0OWUwN2ZjZGE2YmI=
12
+ data.tar.gz: !binary |-
13
+ M2UyYjI2ZWM2ODIyYzU1MzMwOTk0NjgyMTA4Y2MxN2ViOTcxNzM0ODI1NGMw
14
+ Zjg1OTgxNmVmMDE4MjE3MWY0OTBiZTFiM2UzNjNiMTk3ZTZhMzJlMWI4N2M4
15
+ MTY4NDJmMzhiYjE5NDdjMmJkOGFkNjI2YTlmMzA5ZWVlYTBkMDc=
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in link_preview.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Tomas D'Stefano
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,53 @@
1
+ # LinkPreview
2
+
3
+ Link preview feature find open graph or normal meta tags.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'link-preview'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install link-preview
18
+
19
+ ## Usage
20
+
21
+ ```ruby
22
+ page = LinkPreview::Page.new('http://globoesporte.globo.com/futebol/times/corinthians/noticia/2013/06/sheik-cobra-responsabilidade-dos-companheiros-durante-folga.html')
23
+
24
+ # Return the title of the page
25
+ #
26
+ page.title
27
+
28
+ # Return the description of the page.
29
+ #
30
+ page.description
31
+
32
+ # Return all images from page
33
+ #
34
+ page.images
35
+
36
+ # Return the favicon link
37
+ #
38
+ page.favicon
39
+
40
+ # Return the uri
41
+ #
42
+ page.uri
43
+ ```
44
+
45
+ Obs.: The Page class is compatible with Active Model Serializers, :).
46
+
47
+ ## Contributing
48
+
49
+ 1. Fork it
50
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
51
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
52
+ 4. Push to the branch (`git push origin my-new-feature`)
53
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,14 @@
1
+ require 'link_preview/version'
2
+ require 'httparty'
3
+ require 'nokogiri'
4
+ require 'active_support/core_ext/object'
5
+
6
+ module LinkPreview
7
+ autoload :ExternalDescription, 'link_preview/external_description'
8
+ autoload :ExternalFavicon, 'link_preview/external_favicon'
9
+ autoload :ExternalImage, 'link_preview/external_image'
10
+ autoload :ExternalResource, 'link_preview/external_resource'
11
+ autoload :ExternalTitle, 'link_preview/external_title'
12
+ autoload :Parser, 'link_preview/parser'
13
+ autoload :Page, 'link_preview/page'
14
+ end
@@ -0,0 +1,23 @@
1
+ module LinkPreview
2
+ class ExternalDescription < ExternalResource
3
+ attr_reader :document
4
+
5
+ def initialize(document)
6
+ @document = document
7
+
8
+ super(text.to_s)
9
+ end
10
+
11
+ def text
12
+ open_graph_description || meta_description
13
+ end
14
+
15
+ def open_graph_description
16
+ find_value(document.css("*[property~='og:description']").first)
17
+ end
18
+
19
+ def meta_description
20
+ find_value(document.css("*[name~='description']").first)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,28 @@
1
+ module LinkPreview
2
+ class ExternalFavicon < ExternalImage
3
+ attr_reader :uri, :document, :favicon_element, :itemprop_element, :open_graph_element
4
+
5
+ def initialize(uri, document)
6
+ @uri = uri
7
+ @document = document
8
+
9
+ super(uri, favicon_path.to_s)
10
+ end
11
+
12
+ def favicon_path
13
+ find_value(open_graph_element) || favicon_element['href'] || find_value(itemprop_element)
14
+ end
15
+
16
+ def open_graph_element
17
+ @open_graph_element ||= document.css("*[property~='og:image']").first
18
+ end
19
+
20
+ def favicon_element
21
+ @favicon_element ||= document.css("*[rel~='icon']").first || {}
22
+ end
23
+
24
+ def itemprop_element
25
+ @itemprop_element ||= document.css("*[itemprop~='image']").first
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,28 @@
1
+ module LinkPreview
2
+ class ExternalImage < ExternalResource
3
+ attr_reader :image_path
4
+
5
+ def self.parse(uri, document)
6
+ document.css("img").collect { |image|
7
+ self.new(uri, image.attributes['src'].value) if image.attributes['src'].present?
8
+ }
9
+ end
10
+
11
+ def initialize(uri, image_path)
12
+ @uri = uri
13
+ @image_path = image_path
14
+
15
+ super(path)
16
+ end
17
+
18
+ def path
19
+ return '' if image_path.blank?
20
+
21
+ if URI.regexp !~ image_path
22
+ "#{File.join(@uri, image_path)}"
23
+ else
24
+ image_path
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,7 @@
1
+ module LinkPreview
2
+ class ExternalResource < String
3
+ def find_value(element)
4
+ element.attributes['content'] if element.present?
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,13 @@
1
+ module LinkPreview
2
+ class ExternalTitle < ExternalResource
3
+ def initialize(document)
4
+ @document = document
5
+
6
+ super(text)
7
+ end
8
+
9
+ def text
10
+ find_value(@document.css("*[property~='og:title']").first) || @document.css('title').text
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,4 @@
1
+ module LinkPreview
2
+ class Page < Parser
3
+ end
4
+ end
@@ -0,0 +1,76 @@
1
+ module LinkPreview
2
+ class Parser < Hash
3
+ attr_reader :document, :title, :images, :uri
4
+
5
+ def initialize(uri)
6
+ @uri = uri
7
+
8
+ super()
9
+ end
10
+
11
+ # Parse title, favicon and images from an external page.
12
+ #
13
+ def parse!
14
+ merge!(link: @uri, title: title, favicon: favicon, images: images, type: type, description: description)
15
+ rescue StandardError => exception
16
+ merge!(error: exception.message)
17
+ end
18
+
19
+ # @return [True, False] return false if self contain error node. True otherwise.
20
+ #
21
+ def valid?
22
+ self[:error].blank?
23
+ end
24
+
25
+ # Return the title from HTML document.
26
+ #
27
+ # @return [String]
28
+ #
29
+ def title
30
+ LinkPreview::ExternalTitle.new(document)
31
+ end
32
+
33
+ # Return the description from HTML document.
34
+ #
35
+ # @return [String]
36
+ #
37
+ def description
38
+ LinkPreview::ExternalDescription.new(document)
39
+ end
40
+
41
+ # For now all links are considering external.
42
+ # In the future this could be: external, youtube, images.
43
+ #
44
+ def type
45
+ 'external'
46
+ end
47
+
48
+ # Return the absolute path from a favicon element.
49
+ #
50
+ # @return [String]
51
+ #
52
+ def favicon
53
+ @favicon ||= LinkPreview::ExternalFavicon.new(uri, document)
54
+ end
55
+
56
+ # Return all images from the page.
57
+ #
58
+ # @return [Array]
59
+ #
60
+ def images
61
+ @images ||= LinkPreview::ExternalImage.parse(uri, document).unshift(favicon).reject(&:blank?)
62
+ end
63
+
64
+ # Convenience method to be used in the active model serializers.
65
+ #
66
+ def read_attribute_for_serialization(attribute)
67
+ self[attribute.to_sym]
68
+ end
69
+
70
+ private
71
+
72
+ def document
73
+ @document ||= Nokogiri::HTML(HTTParty.get(@uri))
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,3 @@
1
+ module LinkPreview
2
+ VERSION = "0.0.3"
3
+ end
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'link_preview/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "link-preview"
8
+ spec.version = LinkPreview::VERSION
9
+ spec.authors = ["Tomas D'Stefano"]
10
+ spec.email = ["tomas_stefano@successoft.com"]
11
+ spec.description = %q{Link Preview parser feature.}
12
+ spec.summary = %q{Link Preview parser feature.}
13
+ spec.homepage = "https://github.com/tomas-stefano/link_preview"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency 'httparty'
22
+ spec.add_dependency 'nokogiri'
23
+ spec.add_dependency 'activesupport'
24
+
25
+ spec.add_development_dependency "bundler", "~> 1.3"
26
+ spec.add_development_dependency "rake"
27
+
28
+ spec.add_development_dependency 'rspec'
29
+ end
@@ -0,0 +1,229 @@
1
+ require 'spec_helper'
2
+
3
+ module LinkPreview
4
+ describe Parser do
5
+ let(:html) do
6
+ %{<html>
7
+ <head>
8
+ <title>Foobar</title>
9
+ <link rel='icon' href='/favicon.ico'>
10
+ </head>
11
+ <body>
12
+ <p>Hello World</p>
13
+ <a href='/foo' rel='nofollow'>Foo</a>
14
+ </body>
15
+ </html>
16
+ }
17
+ end
18
+ let(:link_preview_parser) { Parser.new('http://foobar.com') }
19
+
20
+ before { HTTParty.stub(:get).and_return(html) }
21
+
22
+ describe '#title' do
23
+ context 'when title is nil' do
24
+ let(:html) { '<html><head></head><body><p>Hello World</p></body></html>' }
25
+ subject { link_preview_parser.title }
26
+
27
+ it { should eq '' }
28
+ end
29
+
30
+ context 'when the page had title' do
31
+ subject { link_preview_parser.title }
32
+
33
+ it { should eq 'Foobar' }
34
+ end
35
+ end
36
+
37
+ describe '#favicon' do
38
+ context 'when had favicon' do
39
+ subject { link_preview_parser.favicon }
40
+
41
+ it { should eq 'http://foobar.com/favicon.ico' }
42
+ end
43
+
44
+ context 'when had other implementation of favicon' do
45
+ let(:html) do
46
+ %{<html>
47
+ <head>
48
+ <title>Google</title>
49
+ <meta itemprop="image" content="/images/google_favicon_128.png">
50
+ </head>
51
+ <body>
52
+ <p>Google Search</p>
53
+ </body>
54
+ </html>
55
+ }
56
+ end
57
+ subject { Parser.new('http://google.com').favicon }
58
+
59
+ it { should eq 'http://google.com/images/google_favicon_128.png' }
60
+ end
61
+
62
+ context 'when favicon is a link to other domain' do
63
+ let(:html) do
64
+ %{<html>
65
+ <head>
66
+ <title>Globo</title>
67
+ <link rel="icon" href="http://s.glbimg.com/es/ge/static/globoesporte/img/favicon.png">
68
+ </head>
69
+ <body>
70
+ <p>Google Search</p>
71
+ </body>
72
+ </html>
73
+ }
74
+ end
75
+ subject { Parser.new('http://globoesporte.com').favicon }
76
+
77
+ it { should eq 'http://s.glbimg.com/es/ge/static/globoesporte/img/favicon.png' }
78
+ end
79
+
80
+ context 'when do not had favicon' do
81
+ let(:html) { '<html><head></head><body><p>Hello World</p></body></html>' }
82
+ subject { link_preview_parser.favicon }
83
+
84
+ it { should eq '' }
85
+ end
86
+ end
87
+
88
+ describe '#images' do
89
+ subject { link_preview_parser.images }
90
+
91
+ context 'when contain images from domain' do
92
+ let(:html) do
93
+ %{<html>
94
+ <head>
95
+ <title>Foobar</title>
96
+ </head>
97
+ <body>
98
+ <p>Hello World</p>
99
+ <img src='/foo.png' />
100
+ </body>
101
+ </html>
102
+ }
103
+ end
104
+
105
+ it { should eq ['http://foobar.com/foo.png'] }
106
+ end
107
+
108
+ context 'when contain images from the request domain' do
109
+ subject { Parser.new('trello.com').images }
110
+
111
+ let(:html) do
112
+ %{<html>
113
+ <head>
114
+ <title>Foobar</title>
115
+ </head>
116
+ <body>
117
+ <p>Hello World</p>
118
+ <img src='/foo.png' />
119
+ </body>
120
+ </html>
121
+ }
122
+ end
123
+
124
+ it { should eq ['trello.com/foo.png'] }
125
+ end
126
+
127
+ context 'when contain images from other domain' do
128
+ let(:html) do
129
+ %{<html>
130
+ <head>
131
+ <title>Foobar</title>
132
+ </head>
133
+ <body>
134
+ <p>Hello World</p>
135
+ <img src='http://youtube.com/foo.png' />
136
+ </body>
137
+ </html>
138
+ }
139
+ end
140
+
141
+ it { should eq ['http://youtube.com/foo.png'] }
142
+ end
143
+
144
+ context 'when contain images without src attribute' do
145
+ let(:html) do
146
+ %{<html>
147
+ <head>
148
+ <title>Foobar</title>
149
+ </head>
150
+ <body>
151
+ <p>Hello World</p>
152
+ <img />
153
+ </body>
154
+ </html>
155
+ }
156
+ end
157
+
158
+ it { should eq [] }
159
+ end
160
+ end
161
+
162
+ describe '#parse!' do
163
+ context 'merge the properties' do
164
+ let(:html) do
165
+ %{<html>
166
+ <head>
167
+ <title>GitHub - Build software better, together.</title>
168
+ <link rel='icon' href='/favicon.ico'>
169
+ </head>
170
+ <body>
171
+ <p>Hello World</p>
172
+ <img src="https://a248.e.akamai.net/assets.github.com/images/network.png?1355422571" />
173
+ </body>
174
+ </html>
175
+ }
176
+ end
177
+ subject { Parser.new('github.com').parse! }
178
+
179
+ it { should eq({ link: 'github.com', type: 'external', title: 'GitHub - Build software better, together.', favicon: 'github.com/favicon.ico', images: ['github.com/favicon.ico', 'https://a248.e.akamai.net/assets.github.com/images/network.png?1355422571'], description: ''}) }
180
+ end
181
+
182
+ context 'when raises exception trying to access the page' do
183
+ subject { link_preview_parser.parse! }
184
+ before { HTTParty.should_receive(:get).and_raise(Errno::ECONNREFUSED) }
185
+
186
+ it { should eq({ error: 'Connection refused' }) }
187
+ end
188
+
189
+ context 'with open graph content' do
190
+ let(:html) do
191
+ %{
192
+ <html>
193
+ <head>
194
+ <meta property="og:title" content="globoesporte.com">
195
+ <meta property="og:type" content="website">
196
+ <meta property="og:url" content="globoesporte.globo.com">
197
+ <meta property="og:image" content="http://s.glbimg.com/es/ge/static/globoesporte/img/logo-globoesporte-facebook.jpg">
198
+ <meta property="og:site_name" content="globoesporte.com">
199
+ <meta property="og:description" content="globoesporte.com a melhor cobertura sobre o Futebol.">
200
+ </head>
201
+ </html>
202
+ }
203
+ end
204
+ subject { Parser.new('globoesporte.com') }
205
+ before { subject.parse! }
206
+
207
+ its([:title]) { should eq 'globoesporte.com' }
208
+ its([:description]) { should eq 'globoesporte.com a melhor cobertura sobre o Futebol.' }
209
+ its([:images]) { should eq ['http://s.glbimg.com/es/ge/static/globoesporte/img/logo-globoesporte-facebook.jpg'] }
210
+ end
211
+ end
212
+
213
+ describe '#valid?' do
214
+ subject { Parser.new('http://github.com') }
215
+
216
+ context 'when parse page' do
217
+ before { subject[:link] = 'foo' }
218
+
219
+ it { should be_valid }
220
+ end
221
+
222
+ context 'when raises error parsing page' do
223
+ before { subject[:error] = 'SSL_connect state=SSLv3 bad ecpoint' }
224
+
225
+ it { should_not be_valid }
226
+ end
227
+ end
228
+ end
229
+ end
@@ -0,0 +1 @@
1
+ require 'link_preview'
metadata ADDED
@@ -0,0 +1,147 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: link-preview
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ platform: ruby
6
+ authors:
7
+ - Tomas D'Stefano
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-06-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: httparty
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ! '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ! '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: nokogiri
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: activesupport
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '1.3'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '1.3'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ! '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ! '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ! '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ! '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: Link Preview parser feature.
98
+ email:
99
+ - tomas_stefano@successoft.com
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - .gitignore
105
+ - Gemfile
106
+ - LICENSE.txt
107
+ - README.md
108
+ - Rakefile
109
+ - lib/link_preview.rb
110
+ - lib/link_preview/external_description.rb
111
+ - lib/link_preview/external_favicon.rb
112
+ - lib/link_preview/external_image.rb
113
+ - lib/link_preview/external_resource.rb
114
+ - lib/link_preview/external_title.rb
115
+ - lib/link_preview/page.rb
116
+ - lib/link_preview/parser.rb
117
+ - lib/link_preview/version.rb
118
+ - link_preview.gemspec
119
+ - spec/link_preview/parser_spec.rb
120
+ - spec/spec_helper.rb
121
+ homepage: https://github.com/tomas-stefano/link_preview
122
+ licenses:
123
+ - MIT
124
+ metadata: {}
125
+ post_install_message:
126
+ rdoc_options: []
127
+ require_paths:
128
+ - lib
129
+ required_ruby_version: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - ! '>='
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ required_rubygems_version: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ! '>='
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ requirements: []
140
+ rubyforge_project:
141
+ rubygems_version: 2.0.3
142
+ signing_key:
143
+ specification_version: 4
144
+ summary: Link Preview parser feature.
145
+ test_files:
146
+ - spec/link_preview/parser_spec.rb
147
+ - spec/spec_helper.rb