open_graph_reader 0.7.2 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 47077321ba2e81ce2661a44db8908de870d1d2722a2669133bb35be087fd1004
4
- data.tar.gz: db84da7bdf562ac50597da8222ed2109643db75ec47e6e3d8204f7bafb5e2872
3
+ metadata.gz: 0e7c1f4b9ce43af3f0ba0a120f14bdd14bf5f91aacac242e3c9d8f000d06b861
4
+ data.tar.gz: f8300efb032e1f687f5c99d8b53b2a553c7b6de9cd45f6c323ac86b8b9761646
5
5
  SHA512:
6
- metadata.gz: 76806aa4f7106ae2767f3c457b0a095a92d36c5647b4d36a6edb341d7d908dd53d66662d364a2803b8e7e1ffd41673729edad049dde7b2988b4da90584d94146
7
- data.tar.gz: 37dc4ecd1ba0ed18a48105820342c516d622a62bcb6857784f4c3fec880d43d6add6ab24eee1868137eb90e269e2c99fc4a746ca0ea8fa49570366de15d5fafe
6
+ metadata.gz: da884cc904c76766f0fa5e6cce33e224511be0c489c7ae99cc589a639efdfdb8c48aa90b4c51ad312f86a8133012c96efbb11f001b4a9d134c913884b697d277
7
+ data.tar.gz: '028e2821d6a628a266d8c365254518d3e3758f2ea94ab612addae5a875dd280eecc287e7c087aef3d957288581cdd4839bf6177ec21c2c576d17a07c798aa44c'
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # OpenGraphReader [![Gem Version](https://badge.fury.io/rb/open_graph_reader.svg)](http://badge.fury.io/rb/open_graph_reader) [![Build Status](https://travis-ci.org/jhass/open_graph_reader.svg?branch=master)](https://travis-ci.org/jhass/open_graph_reader)
1
+ # OpenGraphReader [![Gem Version](https://badge.fury.io/rb/open_graph_reader.svg)](http://badge.fury.io/rb/open_graph_reader)
2
2
 
3
3
  A library to fetch and parse OpenGraph properties from an URL or a given string.
4
4
 
@@ -17,14 +17,14 @@ A library to fetch and parse OpenGraph properties from an URL or a given string.
17
17
  * Objects and their properties are defined in code, not by parsing the response at the namespace identifier.
18
18
 
19
19
 
20
- Ruby 2.0 and later are supported.
20
+ Ruby 3.1 and later are supported. Compatibility with earlier versions might exist but is not verified.
21
21
 
22
22
  ## Installation
23
23
 
24
24
  Add this line to your application's Gemfile:
25
25
 
26
26
  ```ruby
27
- gem 'open_graph_reader'
27
+ gem "open_graph_reader"
28
28
  ```
29
29
 
30
30
  And then execute:
@@ -38,13 +38,13 @@ Or install it yourself as:
38
38
 
39
39
  Install the following gems the same way for a higher success rate at fetching websites:
40
40
 
41
- * [faraday_middleware](https://github.com/lostisland/faraday_middleware)
41
+ * [faraday-follow_redirects](https://github.com/tisba/faraday-follow-redirects)
42
42
  * [faraday-cookie_jar](https://github.com/miyagawa/faraday-cookie_jar)
43
43
 
44
44
  ## Usage
45
45
 
46
46
  ```ruby
47
- require 'open_graph_reader'
47
+ require "open_graph_reader"
48
48
 
49
49
  # Returns nil if anything on the object is invalid
50
50
  object = OpenGraphReader.fetch("http://examples.opengraphprotocol.us/article.html")
@@ -52,18 +52,18 @@ module OpenGraphReader
52
52
  end
53
53
 
54
54
  # @private
55
- def respond_to_missing?(method, _include_private=false)
55
+ def respond_to_missing?(method, _include_private = false)
56
56
  @bases.has_key? method.to_s
57
57
  end
58
58
 
59
59
  # Makes the found root objects available.
60
60
  # @return [Object]
61
- def method_missing(method, *args, &block)
61
+ def method_missing(method, ...)
62
62
  name = method.to_s
63
63
  if respond_to_missing? name
64
64
  @bases[name]
65
65
  else
66
- super(method, *args, &block)
66
+ super
67
67
  end
68
68
  end
69
69
  end
@@ -7,7 +7,7 @@ module OpenGraphReader
7
7
  # Well-known types from
8
8
  #
9
9
  # @see http://ogp.me
10
- KNOWN_TYPES = %w(website article book profile).freeze
10
+ KNOWN_TYPES = %w[website article book profile].freeze
11
11
 
12
12
  # Create a new builder.
13
13
  #
@@ -188,7 +188,7 @@ module OpenGraphReader
188
188
 
189
189
  def extra_properties object, type, verticals
190
190
  valid_properties = verticals[type]
191
- set_properties = object.class.available_properties.select {|property| object[property] }
191
+ set_properties = object.class.available_properties.select { |property| object[property] }
192
192
 
193
193
  set_properties - valid_properties
194
194
  end
@@ -98,15 +98,15 @@ module OpenGraphReader
98
98
 
99
99
  # Reset configuration to their defaults
100
100
  def reset_to_defaults!
101
- @strict = false
102
- @validate_required = true
103
- @validate_references = true
101
+ @strict = false
102
+ @validate_required = true
103
+ @validate_references = true
104
104
  @discard_invalid_optional_properties = false
105
- @synthesize_title = false
106
- @synthesize_url = false
107
- @synthesize_full_url = false
108
- @synthesize_image_url = false
109
- @guess_datetime_format = false
105
+ @synthesize_title = false
106
+ @synthesize_url = false
107
+ @synthesize_full_url = false
108
+ @synthesize_image_url = false
109
+ @guess_datetime_format = false
110
110
  end
111
111
  end
112
112
  end
@@ -9,7 +9,7 @@ module OpenGraphReader
9
9
 
10
10
  # @!macro property
11
11
  # @return [String]
12
- string :type, required: true, downcase: true, default: "website"
12
+ string :type, required: true, downcase: true, default: "website"
13
13
 
14
14
  # @!macro property
15
15
  # @return [String]
@@ -74,6 +74,10 @@ module OpenGraphReader
74
74
  # @return [Integer, nil]
75
75
  integer :height
76
76
 
77
+ # @!macro property
78
+ # @return [String, nil]
79
+ string :alt
80
+
77
81
  # @return [String, nil]
78
82
  def url
79
83
  secure_url || properties[:url] || content
@@ -169,7 +173,7 @@ module OpenGraphReader
169
173
 
170
174
  # @!macro property
171
175
  # @return [String, nil]
172
- enum :gender, %w(male female)
176
+ enum :gender, %w[male female]
173
177
 
174
178
  # @!macro property
175
179
  # @return [String, nil]
@@ -224,38 +228,38 @@ module OpenGraphReader
224
228
  # @return [Array<Profile>]
225
229
  # @!macro property
226
230
  # @return [Profile, nil]
227
- url :actor, to: Profile, verticals: %w(movie episode tv_show other), collection: true
231
+ url :actor, to: Profile, verticals: %w[movie episode tv_show other], collection: true
228
232
 
229
233
  # @!attribute [r] directors
230
234
  # @return [Array<Profile>]
231
235
  # @!macro property
232
236
  # @return [Profile, nil]
233
- url :director, to: Profile, verticals: %w(movie episode tv_show other), collection: true
237
+ url :director, to: Profile, verticals: %w[movie episode tv_show other], collection: true
234
238
 
235
239
  # @!attribute [r] writers
236
240
  # @return [Array<Profile>]
237
241
  # @!macro property
238
242
  # @return [Profile, nil]
239
- url :writer, to: Profile, verticals: %w(movie episode tv_show other), collection: true
243
+ url :writer, to: Profile, verticals: %w[movie episode tv_show other], collection: true
240
244
 
241
245
  # @!macro property
242
246
  # @return [Integer, nil]
243
- integer :duration, verticals: %w(movie episode tv_show other)
247
+ integer :duration, verticals: %w[movie episode tv_show other]
244
248
 
245
249
  # @!macro property
246
250
  # @return [DateTime, nil]
247
- datetime :release_date, verticals: %w(movie episode tv_show other)
251
+ datetime :release_date, verticals: %w[movie episode tv_show other]
248
252
 
249
253
  # @!attribute [r] tags
250
254
  # @return [Array<String>]
251
255
  # @!macro property
252
256
  # @return [String, nil]
253
- string :tag, verticals: %w(movie episode tv_show other), collection: true
257
+ string :tag, verticals: %w[movie episode tv_show other], collection: true
254
258
 
255
259
  # @todo validate that target vertical is video.tv_show ?
256
260
  # @!macro property
257
261
  # @return [Sring, nil]
258
- url :series, to: Video, verticals: %w(episode)
262
+ url :series, to: Video, verticals: %w[episode]
259
263
  end
260
264
 
261
265
  # @see http://ogp.me/#type_book
@@ -294,39 +298,39 @@ module OpenGraphReader
294
298
 
295
299
  # @!macro property
296
300
  # @return [Integer, nil]
297
- integer :duration, verticals: %w(song)
301
+ integer :duration, verticals: %w[song]
298
302
 
299
303
  # @todo validate that target vertical is music.album/music.song ?
300
304
  # @!attribute [r] albums
301
305
  # @return [Array<Music>]
302
306
  # @macro property
303
307
  # @return [Music, nil]
304
- url :album, to: Music, verticals: %w(song), collection: true
308
+ url :album, to: Music, verticals: %w[song], collection: true
305
309
 
306
310
  # @macro property
307
311
  # @return [Integer, nil]
308
- integer :disc, verticals: %w(song album playlist)
312
+ integer :disc, verticals: %w[song album playlist]
309
313
 
310
314
  # @macro property
311
315
  # @return [Integer, nil]
312
- integer :track, verticals: %w(song album playlist)
316
+ integer :track, verticals: %w[song album playlist]
313
317
 
314
318
  # @!attribute [r] musicians
315
319
  # @return [Array<Profile>]
316
320
  # @!macro property
317
321
  # @return [Profile, nil]
318
- url :musician, to: Profile, verticals: %w(song album), collection: true
322
+ url :musician, to: Profile, verticals: %w[song album], collection: true
319
323
 
320
324
  # @macro property
321
325
  # @return [Music, nil]
322
- url :song, to: Music, verticals: %w(album playlist)
326
+ url :song, to: Music, verticals: %w[album playlist]
323
327
 
324
328
  # @macro property
325
329
  # @return [DateTime, nil]
326
- datetime :release_date, verticals: %w(album)
330
+ datetime :release_date, verticals: %w[album]
327
331
 
328
332
  # @macro property
329
333
  # @return [Profile, nil]
330
- url :creator, to: Profile, verticals: %w(playlist radio_station)
334
+ url :creator, to: Profile, verticals: %w[playlist radio_station]
331
335
  end
332
336
  end
@@ -1,7 +1,7 @@
1
1
  require "faraday"
2
2
 
3
3
  begin
4
- require "faraday_middleware/response/follow_redirects"
4
+ require "faraday/follow_redirects"
5
5
  rescue LoadError; end
6
6
 
7
7
  begin
@@ -16,7 +16,7 @@ module OpenGraphReader
16
16
  # @api private
17
17
  class Fetcher
18
18
  HEADERS = {
19
- "Accept" => "text/html",
19
+ "Accept" => "text/html",
20
20
  "User-Agent" => "OpenGraphReader/#{OpenGraphReader::VERSION} (+https://github.com/jhass/open_graph_reader)"
21
21
  }.freeze
22
22
 
@@ -25,6 +25,7 @@ module OpenGraphReader
25
25
  # @param [URI] uri the URI to fetch.
26
26
  def initialize uri
27
27
  raise ArgumentError, "url needs to be an instance of URI" unless uri.is_a? URI
28
+
28
29
  @uri = uri
29
30
  @fetch_failed = false
30
31
  @connection = Faraday.default_connection.dup
@@ -33,7 +34,7 @@ module OpenGraphReader
33
34
  @get_response = nil
34
35
 
35
36
  prepend_middleware Faraday::CookieJar if defined? Faraday::CookieJar
36
- prepend_middleware FaradayMiddleware::FollowRedirects if defined? FaradayMiddleware
37
+ prepend_middleware Faraday::FollowRedirects::Middleware if defined? Faraday::FollowRedirects
37
38
  end
38
39
 
39
40
  # The URL to fetch
@@ -71,6 +72,7 @@ module OpenGraphReader
71
72
  fetch_body unless fetched?
72
73
  raise NoOpenGraphDataError, "No response body received for #{@uri}" if fetch_failed?
73
74
  raise NoOpenGraphDataError, "Did not receive a HTML site at #{@uri}" unless html?
75
+
74
76
  @get_response.body
75
77
  end
76
78
 
@@ -84,6 +86,7 @@ module OpenGraphReader
84
86
  return false unless response
85
87
  return false unless response.success?
86
88
  return false unless response["content-type"]
89
+
87
90
  response["content-type"].include? "text/html"
88
91
  end
89
92
 
@@ -40,8 +40,8 @@ module OpenGraphReader
40
40
  rescue
41
41
  next unless options[:required] || !OpenGraphReader.config.discard_invalid_optional_properties
42
42
  raise InvalidObjectError,
43
- "URL #{value.inspect} does not start with http:// or https:// and failed to "\
44
- "synthesize a full URL"
43
+ "URL #{value.inspect} does not start with http:// or https:// and failed to " \
44
+ "synthesize a full URL"
45
45
  end
46
46
  elsif options.has_key?(:to) && OpenGraphReader.config.validate_references
47
47
  next unless options[:required] || !OpenGraphReader.config.discard_invalid_optional_properties
@@ -67,32 +67,28 @@ module OpenGraphReader
67
67
  end
68
68
 
69
69
  # @see http://ogp.me/#integer
70
- define_type :integer do |value, options|
71
- begin
72
- Integer(value)
73
- rescue ArgumentError
74
- next unless options[:required] || !OpenGraphReader.config.discard_invalid_optional_properties
75
- raise InvalidObjectError, "Integer expected, but was #{value.inspect}"
76
- end
70
+ define_type :integer do |value, options|
71
+ Integer(value)
72
+ rescue ArgumentError
73
+ next unless options[:required] || !OpenGraphReader.config.discard_invalid_optional_properties
74
+ raise InvalidObjectError, "Integer expected, but was #{value.inspect}"
77
75
  end
78
76
 
79
77
  # @see http://ogp.me/#datetime
80
78
  define_type :datetime do |value, options|
81
- begin
82
- if OpenGraphReader.config.guess_datetime_format
83
- DateTime.parse value
84
- else
85
- DateTime.iso8601 value
86
- end
87
- rescue ArgumentError
88
- next unless options[:required] || !OpenGraphReader.config.discard_invalid_optional_properties
89
- raise InvalidObjectError, "ISO8601 datetime expected, but was #{value.inspect}"
79
+ if OpenGraphReader.config.guess_datetime_format
80
+ DateTime.parse value
81
+ else
82
+ DateTime.iso8601 value
90
83
  end
84
+ rescue ArgumentError
85
+ next unless options[:required] || !OpenGraphReader.config.discard_invalid_optional_properties
86
+ raise InvalidObjectError, "ISO8601 datetime expected, but was #{value.inspect}"
91
87
  end
92
88
 
93
89
  # @see http://ogp.me/#bool
94
90
  define_type :boolean do |value, options|
95
- {"true" => true, "false" => false, "1" => true, "0" => false}[value].tap {|bool|
91
+ {"true" => true, "false" => false, "1" => true, "0" => false}[value].tap { |bool|
96
92
  if bool.nil?
97
93
  next unless options[:required] || !OpenGraphReader.config.discard_invalid_optional_properties
98
94
  raise InvalidObjectError, "Boolean expected, but was #{value.inspect}"
@@ -102,12 +98,10 @@ module OpenGraphReader
102
98
 
103
99
  # @see http://ogp.me/#float
104
100
  define_type :float do |value, options|
105
- begin
106
- Float(value)
107
- rescue ArgumentError
108
- next unless options[:required] || !OpenGraphReader.config.discard_invalid_optional_properties
109
- raise InvalidObjectError, "Float expected, but was #{value.inspect}"
110
- end
101
+ Float(value)
102
+ rescue ArgumentError
103
+ next unless options[:required] || !OpenGraphReader.config.discard_invalid_optional_properties
104
+ raise InvalidObjectError, "Float expected, but was #{value.inspect}"
111
105
  end
112
106
  end
113
107
  end
@@ -72,7 +72,7 @@ module OpenGraphReader
72
72
  define_method(name) do
73
73
  value = children[name.to_s].first
74
74
  # @todo figure out a sane way to distinguish subobject properties
75
- value.content if value && value.is_a?(Object)
75
+ value.content if value&.is_a?(Object)
76
76
  value || options[:default]
77
77
  end
78
78
  end
@@ -130,7 +130,7 @@ module OpenGraphReader
130
130
  options = args.pop if args.last.is_a? Hash
131
131
  options ||= {}
132
132
 
133
- @content_processor = proc {|value|
133
+ @content_processor = proc { |value|
134
134
  value.downcase! if options[:downcase]
135
135
  options[:to] ||= self
136
136
  DSL.processors[type].call(value, *args, options)
@@ -164,7 +164,7 @@ module OpenGraphReader
164
164
  # @api private
165
165
  # @return [{String => Array<Strin>}]
166
166
  def verticals
167
- @verticals ||= Hash.new {|h, k| h[k] = [] }
167
+ @verticals ||= Hash.new { |h, k| h[k] = [] }
168
168
  end
169
169
  end
170
170
  end
@@ -1,6 +1,5 @@
1
1
  require "singleton"
2
2
  require "forwardable"
3
- require "set"
4
3
 
5
4
  module OpenGraphReader
6
5
  module Object
@@ -44,7 +43,7 @@ module OpenGraphReader
44
43
 
45
44
  def_delegators :@namespaces, :[]=, :has_key?
46
45
  alias_method :register, :[]=
47
- alias_method :registered?, :has_key?
46
+ alias_method :registered?, :has_key?
48
47
 
49
48
  # @see Registry.verticals
50
49
  attr_reader :verticals
@@ -39,7 +39,7 @@ module OpenGraphReader
39
39
  # Create a new object. If your class overrides this don't forget to call <tt>super</tt>.
40
40
  def initialize
41
41
  @properties = {}
42
- @children = Hash.new {|h, k| h[k] = [] }
42
+ @children = Hash.new { |h, k| h[k] = [] }
43
43
  end
44
44
 
45
45
  # Whether this object has the given property
@@ -48,7 +48,7 @@ module OpenGraphReader
48
48
  #
49
49
  # @return [String]
50
50
  def namespace
51
- parent.fullname if parent
51
+ parent&.fullname
52
52
  end
53
53
 
54
54
  # Get node's namespace as array.
@@ -69,7 +69,7 @@ module OpenGraphReader
69
69
  def inspect
70
70
  "#{super.chop} children=#{children.inspect}>"
71
71
  end
72
- alias to_s inspect
72
+ alias_method :to_s, :inspect
73
73
  end
74
74
 
75
75
  extend Forwardable
@@ -109,8 +109,8 @@ module OpenGraphReader
109
109
  # @return [Bool] Whether the given property exists in the graph.
110
110
  def exist? property
111
111
  path = property.split(":")
112
- child = path.inject(root) {|node, name|
113
- node.children.find {|child| child.name == name } || break
112
+ child = path.inject(root) { |node, name|
113
+ node.children.find { |child| child.name == name } || break
114
114
  }
115
115
  !child.nil? && !child.empty?
116
116
  end
@@ -121,7 +121,7 @@ module OpenGraphReader
121
121
  # @param [String] default The default in case the a value is not found.
122
122
  # @yield Return a default in case the value is not found. Supersedes the default parameter.
123
123
  # @return [String, Bool, Integer, Float, DateTime, nil]
124
- def fetch property, default=nil
124
+ def fetch property, default = nil
125
125
  node = find_by(property)
126
126
  return yield if node.nil? && block_given?
127
127
  return default if node.nil?
@@ -134,7 +134,7 @@ module OpenGraphReader
134
134
  # @return [Node, nil]
135
135
  def find_by property
136
136
  property = normalize_property property
137
- find {|node| node.fullname == property }
137
+ find { |node| node.fullname == property }
138
138
  end
139
139
 
140
140
  # Fetch all nodes
@@ -143,12 +143,12 @@ module OpenGraphReader
143
143
  # @return [Array<Node>]
144
144
  def select_by property
145
145
  property = normalize_property property
146
- select {|node| node.fullname == property }
146
+ select { |node| node.fullname == property }
147
147
  end
148
148
 
149
149
  def find_or_create_path path
150
- path.inject(root) {|node, name|
151
- child = node.children.reverse.find {|child| child.name == name }
150
+ path.inject(root) { |node, name|
151
+ child = node.children.reverse.find { |child| child.name == name }
152
152
 
153
153
  unless child
154
154
  child = Node.new name
@@ -11,7 +11,7 @@ module OpenGraphReader
11
11
  module XPathHelpers
12
12
  # Helper to lowercase all given properties
13
13
  def self.ci_starts_with node_set, string
14
- node_set.select {|node|
14
+ node_set.select { |node|
15
15
  node.to_s.downcase.start_with? string.downcase
16
16
  }
17
17
  end
@@ -56,7 +56,7 @@ module OpenGraphReader
56
56
  def build_graph
57
57
  graph = Graph.new
58
58
 
59
- meta_tags.each do |tag|
59
+ sorted_meta_tags.each do |tag|
60
60
  *path, leaf = tag["property"].downcase.split(":")
61
61
  node = graph.find_or_create_path path
62
62
 
@@ -67,6 +67,11 @@ module OpenGraphReader
67
67
  graph
68
68
  end
69
69
 
70
+ # Ensure the tags are sorted by their hierarchy, that is sort a:b before a:b:c.
71
+ def sorted_meta_tags
72
+ meta_tags.sort_by { |tag| tag["property"] }
73
+ end
74
+
70
75
  def meta_tags
71
76
  head = @doc.xpath("/html/head").first
72
77
 
@@ -80,7 +85,7 @@ module OpenGraphReader
80
85
 
81
86
  if head["prefix"]
82
87
  @additional_namespaces = head["prefix"].scan(/(\w+):\s*([^ ]+)/)
83
- @additional_namespaces.map! {|prefix, _| prefix.downcase }
88
+ @additional_namespaces.map! { |prefix, _| prefix.downcase }
84
89
  @additional_namespaces.each do |additional_namespace|
85
90
  next if additional_namespace == "og"
86
91
  condition << " or ci_starts_with(@property, '#{additional_namespace}')"
@@ -1,4 +1,4 @@
1
1
  module OpenGraphReader
2
- # Tbe library version
3
- VERSION = "0.7.2"
2
+ # The library version
3
+ VERSION = "0.8.0".freeze
4
4
  end
@@ -37,11 +37,11 @@ module OpenGraphReader
37
37
  # @return [Base] The base object from which you can obtain the root objects.
38
38
  # @raise [NoOpenGraphDataError] {include:NoOpenGraphDataError}
39
39
  # @raise [InvalidObjectError] {include:InvalidObjectError}
40
- def self.parse! html, origin=nil
40
+ def self.parse! html, origin = nil
41
41
  self.current_origin = origin
42
42
  parser = Parser.new html
43
43
  raise NoOpenGraphDataError, "#{origin || html} does not contain any OpenGraph tags" unless parser.any_tags?
44
- Builder.new(parser).base.tap {|base|
44
+ Builder.new(parser).base.tap { |base|
45
45
  base.origin = origin.to_s if origin
46
46
  self.current_origin = nil
47
47
  }
@@ -65,7 +65,7 @@ module OpenGraphReader
65
65
  # @param [#to_s] origin The source from where the given document was fetched.
66
66
  # @return [Base, nil] The base object from which you can obtain the root objects.
67
67
  # @see OpenGraphReader.parse!
68
- def self.parse html, origin=nil
68
+ def self.parse html, origin = nil
69
69
  parse! html, origin
70
70
  rescue NoOpenGraphDataError, InvalidObjectError
71
71
  end
@@ -0,0 +1,13 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta property="og:title" content="title">
6
+ <meta property="og:description" content="desc">
7
+ <meta property="og:url" content="https://example.com">
8
+
9
+ <meta property="og:image:alt" content="image:alt">
10
+ <meta property="og:image" content="https://example.com/example.png">
11
+ </head>
12
+ <body></body>
13
+ </html>