lib/consolidate/docx/merge.rb in standard-procedure-consolidate-0.1.0 vs lib/consolidate/docx/merge.rb in standard-procedure-consolidate-0.1.1

- old
+ new

@@ -8,77 +8,105 @@ class Merge def self.open(path, force_settings: true, &block) new(path, force_settings: force_settings, &block) end + def examine + extract_field_names + end + def data fields = {} fields = fields.transform_keys(&:to_s) - xml = @zip.read("word/document.xml") - doc = Nokogiri::XML(xml) { |x| x.noent } + result = doc.dup + result = substitute_style_one_with result, fields + result = substitute_style_two_with result, fields - doc = substitute_style_one_with xml, doc, fields - doc = substitute_style_two_with xml, doc, fields - - @output["word/document.xml"] = doc.serialize save_with: 0 + @output["word/document.xml"] = result.serialize save_with: 0 end def write_to path Zip::File.open(path, Zip::File::CREATE) do |out| - @zip.each do |entry| + zip.each do |entry| out.get_output_stream(entry.name) do |o| - o.write(@output[entry.name] || @zip.read(entry.name)) + o.write(output[entry.name] || zip.read(entry.name)) end end end end protected + attr_reader :zip + attr_reader :xml + attr_reader :doc + attr_accessor :output + def initialize(path, force_settings: true, &block) raise "No block given" unless block @output = {} set_standard_settings if force_settings begin @zip = Zip::File.open(path) + @xml = @zip.read("word/document.xml") + @doc = Nokogiri::XML(xml) { |x| x.noent } + yield self ensure @zip.close end end - def substitute_style_one_with xml, doc, fields + def extract_field_names + (extract_style_one + extract_style_two).uniq + end + + def extract_style_one + (doc / "//w:fldSimple").collect do |field| + value = field.attributes["instr"].value.strip + value.include?("MERGEFIELD") ? value.gsub("MERGEFIELD", "").strip : nil + end.compact + end + + def extract_style_two + (doc / "//w:instrText").collect do |instr| + value = instr.inner_text + value.include?("MERGEFIELD") ? value.gsub("MERGEFIELD", "").strip : nil + end.compact + end + + def substitute_style_one_with document, fields # Word's first way of doing things - (doc / "//w:fldSimple").each do |field| + (document / "//w:fldSimple").each do |field| if field.attributes["instr"].value =~ /MERGEFIELD (\S+)/ text_node = (field / ".//w:t").first next unless text_node text_node.inner_html = fields[$1].to_s end end - doc + document end - def substitute_style_two_with xml, doc, fields + def substitute_style_two_with document, fields # Word's second way of doing things - (doc / "//w:instrText").each do |instr| + (document / "//w:instrText").each do |instr| if instr.inner_text =~ /MERGEFIELD (\S+)/ text_node = instr.parent.next_sibling.next_sibling.xpath(".//w:t").first text_node ||= instr.parent.next_sibling.next_sibling.next_sibling.xpath(".//w:t").first next unless text_node text_node.inner_html = fields[$1].to_s end end - doc + document end def set_standard_settings - @output["word/settings.xml"] = %(<?xml version="1.0" encoding="UTF-8" standalone="yes"?> + output["word/settings.xml"] = %(<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <w:settings xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:sl="http://schemas.openxmlformats.org/schemaLibrary/2006/main"><w:zoom w:percent="100"/></w:settings>) end def close - @zip.close + zip.close end end end end