diff --git a/lib/microformats2.rb b/lib/microformats2.rb index a7618c5..a9968fc 100644 --- a/lib/microformats2.rb +++ b/lib/microformats2.rb @@ -12,6 +12,10 @@ require "microformats2/property/url" require "microformats2/property/date_time" require "microformats2/property/embedded" require "microformats2/property" +require "microformats2/implied_property/foundation" +require "microformats2/implied_property/name" +require "microformats2/implied_property/photo" +require "microformats2/implied_property/url" module Microformats2 class << self diff --git a/lib/microformats2/format.rb b/lib/microformats2/format.rb index 4bd53f2..6bfbbc3 100644 --- a/lib/microformats2/format.rb +++ b/lib/microformats2/format.rb @@ -23,13 +23,33 @@ module Microformats2 end def properties - @properties ||= PropertyParser.parse(@element.children).each do |property| + @properties ||= parse_properties.concat parse_implied_properties + end + + def parse_properties + PropertyParser.parse(@element.children).each do |property| save_property_name(property.method_name) define_method(property.method_name) set_value(property.method_name, property) end end + def parse_implied_properties + ip = [] + ip << ImpliedProperty::Name.new(@element).parse unless property_present?(:name) + ip << ImpliedProperty::Photo.new(@element).parse unless property_present?(:photo) + ip << ImpliedProperty::Url.new(@element).parse unless property_present?(:url) + ip.compact.each do |property| + save_property_name(property.method_name) + define_method(property.method_name) + set_value(property.method_name, property) + end + end + + def property_present?(property) + !! respond_to?(property) && send(property) + end + def to_hash hash = { type: format_types, properties: {} } @property_names.each do |method_name| diff --git a/lib/microformats2/implied_property/foundation.rb b/lib/microformats2/implied_property/foundation.rb new file mode 100644 index 0000000..d67181a --- /dev/null +++ b/lib/microformats2/implied_property/foundation.rb @@ -0,0 +1,50 @@ +module Microformats2 + module ImpliedProperty + class Foundation + def initialize(element) + @element = element + end + + def parse + self if value + end + + def method_name + "foundation" + end + + def value + @value ||= element_value + end + + def to_hash + value.to_s + end + + def to_json + to_hash.to_json + end + + protected + + def element_value + ev = nil + attr_map.each_pair do |k, v| + selected_elements = @element.css(k) + if selected_elements.first + ev ||= selected_elements.first.attribute(v).to_s + end + end + ev + end + + def attribute + attr_map[@element.name] + end + + def attr_map + {} + end + end + end +end diff --git a/lib/microformats2/implied_property/name.rb b/lib/microformats2/implied_property/name.rb new file mode 100644 index 0000000..4b43bcc --- /dev/null +++ b/lib/microformats2/implied_property/name.rb @@ -0,0 +1,31 @@ +module Microformats2 + module ImpliedProperty + class Name < Foundation + + def method_name + "name" + end + + def value + @value ||= element_value || text_value + end + + protected + + def attr_map + { "img[alt]" => "alt", + "abbr[title]" => "title", + ">img[alt]:only-of-type" => "alt", + ">abbr[title]:only-of-type" => "title", + ">:only-of-type>img[alt]:only-of-type" => "alt", + ">:only-of-type>abbr[title]:only-of-type" => "title" } + end + + private + + def text_value + @element.inner_text.gsub(/\n+/, " ").gsub(/\s+/, " ").strip + end + end + end +end diff --git a/lib/microformats2/implied_property/photo.rb b/lib/microformats2/implied_property/photo.rb new file mode 100644 index 0000000..ebd4d45 --- /dev/null +++ b/lib/microformats2/implied_property/photo.rb @@ -0,0 +1,21 @@ +module Microformats2 + module ImpliedProperty + class Photo < Foundation + + def method_name + "photo" + end + + protected + + def attr_map + { "img[src]" => "src", + "object[data]" => "data", + ">img[src]:only-of-type" => "src", + ">object[data]:only-of-type" => "data", + ">:only-child>img[src]:only-of-type" => "src", + ">:only-child>object[data]:only-of-type" => "data" } + end + end + end +end diff --git a/lib/microformats2/implied_property/url.rb b/lib/microformats2/implied_property/url.rb new file mode 100644 index 0000000..71b218d --- /dev/null +++ b/lib/microformats2/implied_property/url.rb @@ -0,0 +1,17 @@ +module Microformats2 + module ImpliedProperty + class Url < Foundation + + def method_name + "url" + end + + protected + + def attr_map + { "a[href]" => "href", + ">a[href]:only-of-type" => "href" } + end + end + end +end diff --git a/spec/lib/microformats2/collection_spec.rb b/spec/lib/microformats2/collection_spec.rb index 25b70b4..af525be 100644 --- a/spec/lib/microformats2/collection_spec.rb +++ b/spec/lib/microformats2/collection_spec.rb @@ -102,7 +102,7 @@ describe Microformats2::Collection do end end - describe ".h-entry .p-author.h-card nested" do + describe ".h-card .p-name .p-nickname nested" do before do html = "spec/support/hcard-pname-pnickname-nested.html" @collection = Microformats2.parse(html) @@ -132,4 +132,39 @@ describe Microformats2::Collection do end end end + + describe ".h-card implied properties simple" do + before do + html = "spec/support/hcard-implied-simple.html" + @collection = Microformats2.parse(html) + end + + describe "#parse" do + it "assigns .h-card .p-name to HCard#name" do + @collection.first.name.first.value.should == "@jlsuttles" + end + it "assigns .h-card .p-photo to HCard#photo" do + @collection.first.photo.first.value.should == "http://gravatar.com/jlsuttles" + end + it "assigns .h-card .p-url to HCard#url" do + @collection.first.url.first.value.should == "http://twitter.com/jlsuttles" + end + end + + describe "#to_hash" do + it "returns the correct Hash" do + hash = { + :items => [{ + :type => ["h-card"], + :properties => { + :name => ["@jlsuttles"], + :photo => ["http://gravatar.com/jlsuttles"], + :url => ["http://twitter.com/jlsuttles"] + } + }] + } + @collection.to_hash.should == hash + end + end + end end diff --git a/spec/support/hcard-implied-simple.html b/spec/support/hcard-implied-simple.html new file mode 100644 index 0000000..a3fdc8c --- /dev/null +++ b/spec/support/hcard-implied-simple.html @@ -0,0 +1,9 @@ + + +
+