diff --git a/README.md b/README.md index efd88dd..8faa137 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,10 @@ open_graph.title # => "Open Graph protocol" open_graph.type # => "website" open_graph.image.url # => "http://ogp.me/logo.png" open_graph.url # => "http://ogp.me/" + +# All open graph tags are additionally stored in a `data` hash so that custom +# open graph tags can still be accessed. +open_graph.data["title"] # => "Open Graph protocol" ``` ## Contributing diff --git a/lib/ogp/open_graph.rb b/lib/ogp/open_graph.rb index 903358a..a163c4d 100644 --- a/lib/ogp/open_graph.rb +++ b/lib/ogp/open_graph.rb @@ -5,6 +5,9 @@ module OGP class OpenGraph + # Accessor for storing all open graph data + attr_accessor :data + # Required Accessors attr_accessor :title, :type, :url attr_accessor :images @@ -24,6 +27,7 @@ def initialize(source) source.force_encoding('UTF-8') if source.encoding != 'UTF-8' + self.data = {} self.images = [] self.audios = [] self.locales = [] @@ -51,6 +55,21 @@ def check_required_attributes(document) def parse_attributes(document) document.xpath('//head/meta[starts-with(@property, \'og:\')]').each do |attribute| attribute_name = attribute.get('property').downcase.gsub('og:', '') + + if data.has_key?(attribute_name) + # There can be multiple entries for the same og tag, see + # https://open.spotify.com/album/3NkIlQR6wZwPCQiP1vPjF8 for an example + # where there are multiple `restrictions:country:allowed` og tags. + # + # In this case store the content values as an array. + if !data[attribute_name].kind_of?(Array) + data[attribute_name] = [ data[attribute_name] ] + end + data[attribute_name] << attribute.get('content') + else + data[attribute_name] = attribute.get('content') + end + case attribute_name when /^image$/i images << OpenStruct.new(url: attribute.get('content').to_s) @@ -70,7 +89,15 @@ def parse_attributes(document) videos << OpenStruct.new unless videos.last videos.last[Regexp.last_match[1].gsub('-', '_')] = attribute.get('content').to_s else - instance_variable_set("@#{attribute_name}", attribute.get('content')) + begin + instance_variable_set("@#{attribute_name}", attribute.get('content')) + rescue NameError + warn("Some og tag names include colons `:`, such as Spotify song + pages (`restrictions:country:allowed`), which will result in a + NameError. Please rely on data[attribute_name] instead. Setting + top-level instance variables is deprecated and will be removed in + the next major version.") + end end end end diff --git a/lib/ogp/version.rb b/lib/ogp/version.rb index 58c77fe..a4b9716 100644 --- a/lib/ogp/version.rb +++ b/lib/ogp/version.rb @@ -1,3 +1,3 @@ module OGP - VERSION = '0.3.0'.freeze + VERSION = '0.4.0'.freeze end diff --git a/ogp.gemspec b/ogp.gemspec index d462a4d..f215cca 100644 --- a/ogp.gemspec +++ b/ogp.gemspec @@ -22,7 +22,7 @@ Gem::Specification.new do |spec| spec.add_dependency 'oga', '~> 2.15' - spec.add_development_dependency 'bundler', '~> 1.13' + spec.add_development_dependency 'bundler', '>= 1.13' spec.add_development_dependency 'rake', '~> 10.0' spec.add_development_dependency 'rspec', '~> 3.6' spec.add_development_dependency 'rubocop', '~> 0.49.1' diff --git a/spec/fixtures/custom_attributes.html b/spec/fixtures/custom_attributes.html new file mode 100644 index 0000000..90421ff --- /dev/null +++ b/spec/fixtures/custom_attributes.html @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/spec/ogp/open_graph_spec.rb b/spec/ogp/open_graph_spec.rb index 87d9c25..466923c 100644 --- a/spec/ogp/open_graph_spec.rb +++ b/spec/ogp/open_graph_spec.rb @@ -141,5 +141,17 @@ expect(open_graph.image.url).to eql('https://www.example.com/image.jpg') end end + + context 'with custom attributes' do + it 'should include them to the data hash' do + content = File.read("#{File.dirname(__FILE__)}/../fixtures/custom_attributes.html", encoding: 'ASCII-8BIT') + open_graph = OGP::OpenGraph.new(content) + + expect(open_graph.title).to eql('Way Out') + expect(open_graph.data['title']).to eql(open_graph.title) + expect(open_graph.data['restrictions:country:allowed'].size).to eql(3) + expect(open_graph.data['restrictions:country:allowed'][0]).to eql('AR') + end + end end end