module DocxGenerator module DSL class Document attr_reader :filename def initialize(filename, &block) @filename = filename + ".docx" @objects = [] # It contains all the DSL elements yield self if block end # Could be better def save content_types = generate_content_types rels = generate_rels document = generate_document File.delete(@filename) if File.exists?(@filename) Zip::ZipFile.open(@filename, Zip::ZipFile::CREATE) do |docx| docx.mkdir('_rels') docx.mkdir('word') docx.get_output_stream('[Content_Types].xml') { |f| f.puts content_types } docx.get_output_stream('_rels/.rels') { |f| f.puts rels } docx.get_output_stream('word/document.xml') { |f| f.puts document } end end def paragraph(options = {}, &block) par = DocxGenerator::DSL::Paragraph.new(options) yield par if block @objects << par end def add(*objects) objects.each do |object| @objects << object end self end private def generate_content_types <<EOF <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"> <Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/> <Default Extension="xml" ContentType="application/xml"/> <Override PartName="/word/document.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"/> </Types> EOF end def generate_rels <<EOF <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"> <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="word/document.xml"/> </Relationships> EOF end def generate_document content = [] @objects.each do |object| content << object.generate end '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' + Word::Document.new({ "xmlns:w" => "http://schemas.openxmlformats.org/wordprocessingml/2006/main" }, [ Word::Body.new(content) ]).to_s end end end end