class Htmltoword::Document

Public Class Methods

create(content, template_name = nil, extras = false) click to toggle source
# File lib/htmltoword/document.rb, line 7
def create(content, template_name = nil, extras = false)
  template_name += extension if template_name && !template_name.end_with?(extension)
  document = new(template_file(template_name))
  document.replace_files(content, extras)
  document.generate
end
create_and_save(content, file_path, template_name = nil, extras = false) click to toggle source
# File lib/htmltoword/document.rb, line 14
def create_and_save(content, file_path, template_name = nil, extras = false)
  File.open(file_path, 'wb') do |out|
    out << create(content, template_name, extras)
  end
end
create_with_content(template, content, extras = false) click to toggle source
# File lib/htmltoword/document.rb, line 20
def create_with_content(template, content, extras = false)
  template += extension unless template.end_with?(extension)
  document = new(template_file(template))
  document.replace_files(content, extras)
  document.generate
end
doc_xml_file() click to toggle source
# File lib/htmltoword/document.rb, line 31
def doc_xml_file
  'word/document.xml'
end
extension() click to toggle source
# File lib/htmltoword/document.rb, line 27
def extension
  '.docx'
end
new(template_path) click to toggle source
# File lib/htmltoword/document.rb, line 44
def initialize(template_path)
  @replaceable_files = {}
  @template_path = template_path
end
numbering_xml_file() click to toggle source
# File lib/htmltoword/document.rb, line 35
def numbering_xml_file
  'word/numbering.xml'
end
relations_xml_file() click to toggle source
# File lib/htmltoword/document.rb, line 39
def relations_xml_file
  'word/_rels/document.xml.rels'
end

Public Instance Methods

generate() click to toggle source

Generate a string representing the contents of a docx file.

# File lib/htmltoword/document.rb, line 52
def generate
  Zip::File.open(@template_path) do |template_zip|
    buffer = Zip::OutputStream.write_buffer do |out|
      template_zip.each do |entry|
        out.put_next_entry entry.name
        if @replaceable_files[entry.name] && entry.name == Document.doc_xml_file
          source = entry.get_input_stream.read
          # Change only the body of document. TODO: Improve this...
          source = source.sub(/(<w:body>)((.|\n)*?)(<w:sectPr)/, "\\1#{@replaceable_files[entry.name]}\\4")
          out.write(source)
        elsif @replaceable_files[entry.name]
          out.write(@replaceable_files[entry.name])
        else
          out.write(template_zip.read(entry.name))
        end
      end
    end
    buffer.string
  end
end
replace_files(html, extras = false) click to toggle source
# File lib/htmltoword/document.rb, line 73
def replace_files(html, extras = false)
  html = '<body></body>' if html.nil? || html.empty?
  source = Nokogiri::HTML(html.gsub(/>\s+</, '><'))
  transform_and_replace(source, xslt_path('numbering'), Document.numbering_xml_file)
  transform_and_replace(source, xslt_path('relations'), Document.relations_xml_file)
  transform_doc_xml(source, extras)
end
transform_doc_xml(source, extras = false) click to toggle source
# File lib/htmltoword/document.rb, line 81
def transform_doc_xml(source, extras = false)
  transformed_source = xslt(stylesheet_name: 'cleanup').transform(source)
  transformed_source = xslt(stylesheet_name: 'inline_elements').transform(transformed_source)
  transform_and_replace(transformed_source, document_xslt(extras), Document.doc_xml_file, extras)
end

Private Instance Methods

transform_and_replace(source, stylesheet_path, file, remove_ns = false) click to toggle source
# File lib/htmltoword/document.rb, line 89
def transform_and_replace(source, stylesheet_path, file, remove_ns = false)
  stylesheet = xslt(stylesheet_path: stylesheet_path)
  content = stylesheet.apply_to(source)
  content.gsub!(/\s*xmlns:(\w+)="(.*?)\s*"/, '') if remove_ns
  @replaceable_files[file] = content
end