module Docx::TemplateHandler
Constants
- BUX
- COLON
- EACH
- FINISH
- P
- PARAGRAPH_XPATH
- PR
- START
- TEXT_NODE_XPATH
- W
Public Class Methods
insert(hash, doc)
click to toggle source
Now supported only one-depth cycles and cycle begin/end must be in the separate rows
# File lib/docx/template_handler.rb, line 17 def self.insert(hash, doc) paragraphs = doc.xpath(PARAGRAPH_XPATH) paragraphs.each do |paragraph| text_nodes = paragraph.xpath(TEXT_NODE_XPATH) text_nodes.each do |text_node| value = text_node.content next unless value[0] == BUX && value[-1] == BUX key = value[1..-2] if key.include? COLON if key.start_with? START key.sub! START, FINISH fin_value = value.sub START, FINISH paragraph, repeat = bound_repeatable_piece(text_node, fin_value) elems_for_repeating = key.sub FINISH, '' if hash[elems_for_repeating] && (hash[elems_for_repeating].kind_of? Enumerable) hash[elems_for_repeating].each do |repeated_elem| repeat.each do |repeatable_paragraph| dup_par = repeatable_paragraph.dup handle_paragraph dup_par, repeated_elem paragraph.add_next_sibling dup_par paragraph = dup_par end end end repeat.each do |par| par.remove end break else vars = key.split COLON obj = hash[vars[0]] text_node.content = if obj.is_a? Hash obj[vars[1]] else begin obj.send vars[1] rescue NoMethodError => e value end end end else text_node.content = hash[key] || value end end end end
Private Class Methods
bound_repeatable_piece(node, fin_value)
click to toggle source
# File lib/docx/template_handler.rb, line 82 def self.bound_repeatable_piece(node, fin_value) # Tag name consists from prefix (usually, 'w') and name (i.e. 'r', 'rPr' and so on) temp_key = paragraph_containing node paragraph = temp_key.next_sibling temp_key.remove #next unless paragraph repeat = [] while true result = find_finish paragraph, fin_value #if result.kind_of? Array # new_children = Nokogiri::XML::NodeSet.new paragraph.document # result.each do |node| # new_children.push node # end # paragraph.children = new_children # repeat.push paragraph # break #end unless result # Move 'paragraph' back and remove ending delimiter temp_key = paragraph paragraph = paragraph.previous_sibling temp_key.remove break end #paragraph.xpath('.//w:t') repeat.push result paragraph = paragraph.next_sibling break unless paragraph end return paragraph, repeat end
find_finish(node, finish_str)
click to toggle source
# File lib/docx/template_handler.rb, line 115 def self.find_finish(node, finish_str) # Now think that repeating will be bounded by paragraphs return node if node.name.end_with? PR children = [] node.children.each do |child| ## Be careful, result = nil in the case, when we found finish_str #result = find_finish child, finish_str #unless result # '$FINISH:...$' returns nil # return nil if children.empty? # <w:t>$...$</w:t> returns nil here # return nil if children.size == 1 && node.name+PR == children.first.name # <w:p><w:pPr>...</w:pPr><w:t>...</w:t> returns nil here # return children #else # # If node is returned, then... If array, then... # if result.kind_of? Nokogiri::XML::Node # children.push child # elsif result.kind_of? Array # new_children = Nokogiri::XML::NodeSet.new child.document # result.each do |res_node| # new_children.push res_node # end # child.children = new_children # children.push child # return children # end #end end # WARNING: It seems, situation exists, when finish_str willn't contain in the children but will be in the node if node.content == finish_str return nil else return node end end
handle_paragraph(paragraph, hash)
click to toggle source
# File lib/docx/template_handler.rb, line 68 def self.handle_paragraph(paragraph, hash) paragraph.xpath(TEXT_NODE_XPATH).each do |text_node| value = text_node.content next unless value[0] == BUX && value[-1] == BUX key = value[1..-2] if key.include? COLON if key.start_with? EACH key.sub! EACH, '' text_node.content = hash[key] || value end end end end
paragraph_containing(node)
click to toggle source
# File lib/docx/template_handler.rb, line 153 def self.paragraph_containing node return nil unless node.namespace.prefix == W return node if node.name == P while (node = node.parent).name != P end node end