module DocxGenerator class Document attr_reader :filename def initialize(filename) @filename = filename @content = [] end def save content_types = generate_content_types rels = generate_rels document = generate_document Zip::Archive.open(@filename + ".docx", Zip::CREATE | Zip::TRUNC) do |docx| docx.add_dir('_rels') docx.add_dir('word') docx.add_buffer('[Content_Types].xml', content_types) docx.add_buffer('_rels/.rels', rels) docx.add_buffer('word/document.xml', document) end end # text_fragments : Word::Text or String # Later: Paragraph Object, with Text Object def add_paragraph(*text_fragments) arguments = {} content = [] text_fragments.each do |text_fragment| if text_fragment.respond_to?(:keys) arguments = text_fragment else content.push(text_fragment.respond_to?(:generate) ? text_fragment : text(text_fragment)) content.push Word::Extensions.space end end content.pop if arguments.length != 0 options = [] arguments.each do |option, value| options.push parse_paragraph_option(option, value) end content.unshift Word::ParagraphProperties.new({}, options) end @content.push Word::Paragraph.new({}, content) self end def text(text_fragment, arguments = {}) content = [] if arguments.length != 0 options = [] arguments.each do |option, value| options.push parse_text_option(option, value) end content.push Word::RunProperties.new({}, options) end content.push Word::Text.new({}, [text_fragment]) Word::Run.new({}, content) end private def generate_content_types < EOF end def generate_rels < EOF end def generate_document '' + Word::Document.new({ "xmlns:w" => "http://schemas.openxmlformats.org/wordprocessingml/2006/main" }, [ Word::Body.new({}, @content) ]).to_s end def parse_text_option(option, value) case option when :bold then Word::Bold.new(value) when :italics then Word::Italics.new(value) when :underline then Word::Underline.new(value) when :size then Word::Size.new(value) end end def parse_paragraph_option(option, value) case option when :alignment then Word::Alignment.new(value) end end end end