module Sablon module Content class << self def wrap(value) case value when Sablon::Content value else if type = type_wrapping(value) type.new(value) else raise ArgumentError, "Could not find Sablon content type to wrap #{value.inspect}" end end end def make(type_id, *args) if types.key?(type_id) types[type_id].new(*args) else raise ArgumentError, "Could not find Sablon content type with id '#{type_id}'" end end def register(content_type) types[content_type.id] = content_type end def remove(content_type_or_id) types.delete_if {|k,v| k == content_type_or_id || v == content_type_or_id } end private def type_wrapping(value) types.values.reverse.detect { |type| type.wraps?(value) } end def types @types ||= {} end end class String < Struct.new(:string) include Sablon::Content def self.id; :string end def self.wraps?(value) value.respond_to?(:to_s) end def initialize(value) super value.to_s end def append_to(paragraph, display_node) string.scan(/[^\n]+|\n/).reverse.each do |part| if part == "\n" display_node.add_next_sibling Nokogiri::XML::Node.new "w:br", display_node.document else text_part = display_node.dup text_part.content = part display_node.add_next_sibling text_part end end end end class WordML < Struct.new(:xml) include Sablon::Content def self.id; :word_ml end def self.wraps?(value) false end def append_to(paragraph, display_node) Nokogiri::XML.fragment(xml).children.reverse.each do |child| paragraph.add_next_sibling child end paragraph.remove end end class Markdown < Struct.new(:word_ml) include Sablon::Content def self.id; :markdown end def self.wraps?(value) false end def initialize(markdown) warn "[DEPRECATION] `Sablon::Content::Markdown` is deprecated. Please use `Sablon::Content::HTML` instead." redcarpet = ::Redcarpet::Markdown.new(::Redcarpet::Render::HTML.new) word_ml = Sablon.content(:html, redcarpet.render(markdown)) super word_ml end def append_to(*args) word_ml.append_to(*args) end end class HTML < Struct.new(:word_ml) include Sablon::Content def self.id; :html end def self.wraps?(value) false end def initialize(html) converter = HTMLConverter.new word_ml = Sablon.content(:word_ml, converter.process(html)) super word_ml end def append_to(*args) word_ml.append_to(*args) end end register Sablon::Content::String register Sablon::Content::WordML register Sablon::Content::Markdown register Sablon::Content::HTML end end