lib/hijack/output_drivers/radiant/extensions/nokogiri.rb

Summary

Maintainability
A
0 mins
Test Coverage
require 'nokogiri'
require 'htmlentities'

module Hijack

  module OutputDrivers

    module Radiant

      module Extensions

        module Nokogiri

          HTML_ENCODER = HTMLEntities.new

          def to_radiant
            rdizer = Radiantizer.select(self)
            rdizer.to_radiant
          end

        private

          class RawRadiantizer
            attr_reader :accu, :element

            def initialize(el)
              @element = el
              @accu = []
            end

            def to_radiant
              self.radiantize
              self.accu.join
            end

            def radiantize
              _radiantize
            end

          private

            def _radiantize
            end

          end

          class Radiantizer < RawRadiantizer
            attr_accessor :tag, :orig_key, :special_key, :special_value

            def radiantize
              attrs = delete_special_key
              init_accumulator
              accumulate_other_values(attrs)
              extend_to_children
              close
            end

            def text
              self.element.text || ''
            end

            def children
              self.element.children
            end

            class << self

              def select(el)
                res = case el.name
                  when 'img' then ImageRadiantizer.new(el)
                  when 'a'   then LinkRadiantizer.new(el)
                  when 'text' then TextRadiantizer.new(el)
                  when 'br' then BreakRadiantizer.new(el)
                  when 'h1' then TitleRadiantizer.new(el)
                  else PassThroughRadiantizer.new(el)
                end
                res
              end

            end

          private

            def specialize
               self.special_value = self.element[self.special_key].radiantize
            end

            def delete_special_key
              attrs = self.element.attributes.dup
              attrs.delete(self.special_key)
              attrs
            end

            def init_accumulator
               self.accu << "<#{self.tag} name=\"#{self.special_value}\" "
            end

            def accumulate_other_values(attrs)
              attrs.values.each { |nv| self.accu << "#{nv.name}=\"#{nv.value}\" " }
              self.accu << '>'
            end

            def extend_to_children
              self.children.each { |c| self.accu << c.to_radiant }
            end

            def close
              self.accu << "</#{self.tag}>"
            end

          end

          class ImageRadiantizer < Radiantizer

             def initialize(el)
               super
               self.tag = 'r:asset:image'
               self.orig_key = 'img'
               self.special_key = 'src'
               specialize
             end


          end

          class LinkRadiantizer < Radiantizer

             def initialize(el)
               super
               self.tag = 'r:link'
               self.orig_key = 'a'
               self.special_key = 'href'
               specialize
             end

          end

          class TitleRadiantizer < Radiantizer

             def initialize(el)
               super
               self.tag = 'h1'
             end

          private

            def delete_special_key
              self.element.attributes
            end

            def init_accumulator
               self.accu << "<#{self.tag} "
            end

            def extend_to_children
              # replaces text with radius tag
              self.accu << '<r:title />'
            end

          end

          class TextRadiantizer < RawRadiantizer

          private

            def _radiantize
              self.accu << HTML_ENCODER.encode(self.element.text, :named)
            end

          end

          class BreakRadiantizer < RawRadiantizer

          private

            def _radiantize
              self.accu << '<br />'
            end

          end

          class PassThroughRadiantizer < Radiantizer

             def initialize(el)
               super
               self.tag = el.name
             end

          private

            def delete_special_key
              self.element.attributes
            end

            def init_accumulator
               self.accu << "<#{self.tag} "
            end

          end

        end

      end

    end

  end

end

class Nokogiri::XML::Node

  include Hijack::OutputDrivers::Radiant::Extensions::Nokogiri

end

class Nokogiri::XML::NodeSet

  def to_radiant(*args)
    self.map { |x| x.to_radiant(*args) }.join
  end

end