Class: Htmltoword::Document

Inherits:
Object
  • Object
show all
Extended by:
TemplatesHelper
Includes:
XSLTHelper
Defined in:
lib/htmltoword/document.rb

Class Method Summary collapse

Instance Method Summary collapse

Methods included from TemplatesHelper

template_file

Methods included from XSLTHelper

#document_xslt, #xslt, #xslt_path

Constructor Details

#initialize(template_path) ⇒ Document

Returns a new instance of Document.



48
49
50
51
52
# File 'lib/htmltoword/document.rb', line 48

def initialize(template_path)
  @replaceable_files = {}
  @template_path = template_path
  @image_files = []
end

Class Method Details

.content_types_xml_fileObject



43
44
45
# File 'lib/htmltoword/document.rb', line 43

def content_types_xml_file
  '[Content_Types].xml'
end

.create(content, template_name = nil, extras = false) ⇒ Object



7
8
9
10
11
12
# 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) ⇒ Object



14
15
16
17
18
# 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) ⇒ Object



20
21
22
23
24
25
# 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_fileObject



31
32
33
# File 'lib/htmltoword/document.rb', line 31

def doc_xml_file
  'word/document.xml'
end

.extensionObject



27
28
29
# File 'lib/htmltoword/document.rb', line 27

def extension
  '.docx'
end

.numbering_xml_fileObject



35
36
37
# File 'lib/htmltoword/document.rb', line 35

def numbering_xml_file
  'word/numbering.xml'
end

.relations_xml_fileObject



39
40
41
# File 'lib/htmltoword/document.rb', line 39

def relations_xml_file
  'word/_rels/document.xml.rels'
end

Instance Method Details

#generateObject

Generate a string representing the contents of a docx file.



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/htmltoword/document.rb', line 57

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])
        elsif entry.name == Document.content_types_xml_file
          raw_file = entry.get_input_stream.read
          content_types = @image_files.empty? ? raw_file : inject_image_content_types(raw_file)

          out.write(content_types)
        else
          out.write(template_zip.read(entry.name))
        end
      end
      unless @image_files.empty?
      #stream the image files into the media folder using open-uri
        @image_files.each do |hash|
          out.put_next_entry("word/media/#{hash[:filename]}")
          open(hash[:url], 'rb') do |f|
            out.write(f.read)
          end
        end
      end
    end
    buffer.string
  end
end

#replace_files(html, extras = false) ⇒ Object



92
93
94
95
96
97
98
99
100
# File 'lib/htmltoword/document.rb', line 92

def replace_files(html, extras = false)
  html = '<body></body>' if html.nil? || html.empty?
  original_source = Nokogiri::HTML(html.gsub(/>\s+</, '><'))
  source = xslt(stylesheet_name: 'cleanup').transform(original_source)
  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)
  local_images(source)
end

#transform_doc_xml(source, extras = false) ⇒ Object



102
103
104
105
106
# File 'lib/htmltoword/document.rb', line 102

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