111 lines
2.8 KiB
Ruby
111 lines
2.8 KiB
Ruby
module Microformats2
|
|
class Format
|
|
CLASS_REG_EXP = /^(h-)/
|
|
|
|
attr_reader :method_name
|
|
|
|
def initialize(element, base)
|
|
@element = element
|
|
@base = base
|
|
@method_name = to_method_name(format_types.first)
|
|
@property_names = []
|
|
end
|
|
|
|
def parse
|
|
format_types
|
|
properties
|
|
self
|
|
end
|
|
|
|
def format_types
|
|
@format_types ||= @element.attribute("class").to_s.split.select do |html_class|
|
|
html_class =~ Format::CLASS_REG_EXP
|
|
end
|
|
end
|
|
|
|
def properties
|
|
@properties ||= parse_properties.concat parse_implied_properties
|
|
end
|
|
|
|
def parse_properties
|
|
PropertyParser.parse(@element.children, @base).each do |property|
|
|
assign_property(property)
|
|
end
|
|
end
|
|
|
|
def add_property(property_class, value)
|
|
property = Property.new(nil, property_class, value, @base)
|
|
assign_property(property)
|
|
end
|
|
|
|
def parse_implied_properties
|
|
ip = []
|
|
ip << ImpliedProperty::Name.new(@element).parse unless property_present?(:name)
|
|
ip << ImpliedProperty::Url.new(@element, @base).parse unless property_present?(:url)
|
|
ip << ImpliedProperty::Photo.new(@element).parse unless property_present?(:photo)
|
|
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|
|
|
hash[:properties][method_name.to_sym] = send(method_name.pluralize).map(&:to_hash)
|
|
end
|
|
hash
|
|
end
|
|
|
|
def to_json
|
|
to_hash.to_json
|
|
end
|
|
|
|
private
|
|
|
|
def assign_property(property)
|
|
save_property_name(property.method_name)
|
|
define_method(property.method_name)
|
|
set_value(property.method_name, property)
|
|
end
|
|
|
|
def to_method_name(html_class)
|
|
# p-class-name -> class_name
|
|
mn = html_class.downcase.split("-")[1..-1].join("_")
|
|
# avoid overriding Object#class
|
|
mn = "klass" if mn == "class"
|
|
mn
|
|
end
|
|
|
|
def save_property_name(property_name)
|
|
unless @property_names.include?(property_name)
|
|
@property_names << property_name
|
|
end
|
|
end
|
|
|
|
def define_method(mn)
|
|
unless respond_to?(mn)
|
|
self.singleton_class.class_eval { attr_accessor mn }
|
|
end
|
|
unless respond_to?(mn.pluralize)
|
|
self.singleton_class.class_eval { attr_accessor mn.pluralize }
|
|
end
|
|
end
|
|
|
|
def set_value(mn, value)
|
|
unless current = send(mn)
|
|
send("#{mn}=", value)
|
|
end
|
|
if current = send(mn.pluralize)
|
|
current << value
|
|
else
|
|
send("#{mn.pluralize}=", [value])
|
|
end
|
|
end
|
|
end
|
|
end
|