class RichUrls::XMLHandler

Constants

FALLBACK_ELEMENTS
FINDERS
StopParsingError
WHITELISTED_ATTRS
WHITELISTED_EL_NAMES

Attributes

elements[R]
properties[R]

Public Class Methods

new(filter = []) click to toggle source
# File lib/xml_handler.rb, line 47
def initialize(filter = [])
  @filter = filter
  @elements = []
  @counts = Set.new
  @properties = filtered_properties(filter)
end

Public Instance Methods

attr(key, value) click to toggle source
# File lib/xml_handler.rb, line 80
def attr(key, value)
  return unless WHITELISTED_ATTRS.include?(key)

  el = @elements.last
  el&.add(key, value)
end
end_element(tag) click to toggle source
# File lib/xml_handler.rb, line 68
def end_element(tag)
  return unless WHITELISTED_EL_NAMES.include?(tag)

  el = @elements.reverse_each.detect { |e| e.open && e.tag == tag }
  return unless el

  el.close!
  find_element(el)

  raise StopParsingError if @properties.values.all?
end
find(tag, attrs = {}) click to toggle source
# File lib/xml_handler.rb, line 54
def find(tag, attrs = {})
  @elements.detect do |el|
    matching_attributes = attrs.all? { |k, v| el.attributes[k] == v }

    el.tag == tag && matching_attributes
  end
end
start_element(tag) click to toggle source
# File lib/xml_handler.rb, line 62
def start_element(tag)
  return unless WHITELISTED_EL_NAMES.include?(tag)

  @elements << El.new(tag) if add_element?(tag)
end
text(str) click to toggle source
# File lib/xml_handler.rb, line 87
def text(str)
  el = @elements.detect(&:open)
  el&.append_text(str)
end

Private Instance Methods

add_element?(tag) click to toggle source
# File lib/xml_handler.rb, line 107
def add_element?(tag)
  return true unless FALLBACK_ELEMENTS.keys.include?(tag)
  return false if @counts.include?(tag)

  @counts.add(tag)

  !find(:meta, property: FALLBACK_ELEMENTS.fetch(tag))
end
filtered_properties(filter) click to toggle source

Turns a set of filtered properties into a Hash where the default value is ‘nil`

# File lib/xml_handler.rb, line 118
def filtered_properties(filter)
  keys = FINDERS.values.uniq
  keys &= filter if filter.any?

  Hash[keys.zip([])]
end
find_element(elem) click to toggle source
# File lib/xml_handler.rb, line 94
def find_element(elem)
  FINDERS.each_pair do |finder, attribute|
    next if @properties[attribute]

    content = finder.call(elem)

    if content
      @properties[attribute] = content
      break
    end
  end
end