lib/caracal/renderers/document_renderer.rb in caracal-0.2.1 vs lib/caracal/renderers/document_renderer.rb in caracal-0.3.0

- old
+ new

@@ -5,73 +5,73 @@ module Caracal module Renderers class DocumentRenderer < XmlRenderer - + #------------------------------------------------------------- # Public Methods #------------------------------------------------------------- - - # This method produces the xml required for the `word/document.xml` + + # This method produces the xml required for the `word/document.xml` # sub-document. # def to_xml builder = ::Nokogiri::XML::Builder.with(declaration_xml) do |xml| xml.send 'w:document', root_options do xml.send 'w:background', { 'w:color' => 'FFFFFF' } xml.send 'w:body' do - + #============= CONTENTS =================================== - + document.contents.each do |model| method = render_method_for_model(model) send(method, xml, model) end - + #============= PAGE SETTINGS ============================== - + xml.send 'w:sectPr' do if document.page_number_show if rel = document.find_relationship('footer1.xml') xml.send 'w:footerReference', { 'r:id' => rel.formatted_id, 'w:type' => 'default' } end end xml.send 'w:pgSz', page_size_options xml.send 'w:pgMar', page_margin_options end - + end end end builder.to_xml(save_options) end - - + + #------------------------------------------------------------- # Private Methods - #------------------------------------------------------------- + #------------------------------------------------------------- private - + #============= COMMON RENDERERS ========================== - + # This method converts a model class name to a rendering - # function on this class (e.g., Caracal::Core::Models::ParagraphModel + # function on this class (e.g., Caracal::Core::Models::ParagraphModel # translates to `render_paragraph`). # def render_method_for_model(model) type = model.class.name.split('::').last.downcase.gsub('model', '') "render_#{ type }" end - - # This method renders a standard node of run properties based on the + + # This method renders a standard node of run properties based on the # model's attributes. # def render_run_attributes(xml, model, paragraph_level=false) if model.respond_to? :run_attributes - attrs = model.run_attributes.delete_if { |k, v| v.nil? } - + attrs = model.run_attributes.delete_if { |k, v| v.nil? } + if paragraph_level && attrs.empty? # skip else xml.send 'w:rPr' do unless attrs.empty? @@ -79,29 +79,33 @@ xml.send 'w:color', { 'w:val' => attrs[:color] } unless attrs[:color].nil? xml.send 'w:sz', { 'w:val' => attrs[:size] } unless attrs[:size].nil? xml.send 'w:b', { 'w:val' => (attrs[:bold] ? '1' : '0') } unless attrs[:bold].nil? xml.send 'w:i', { 'w:val' => (attrs[:italic] ? '1' : '0') } unless attrs[:italic].nil? xml.send 'w:u', { 'w:val' => (attrs[:underline] ? 'single' : 'none') } unless attrs[:underline].nil? + unless attrs[:font].nil? + f = attrs[:font] + xml.send 'w:rFonts', { 'w:ascii' => f, 'w:hAnsi' => f, 'w:eastAsia' => f, 'w:cs' => f } + end end xml.send 'w:rtl', { 'w:val' => '0' } end end end end - - + + #============= MODEL RENDERERS =========================== - + def render_image(xml, model) unless ds = document.default_style raise Caracal::Errors::NoDefaultStyleError 'Document must declare a default paragraph style.' end - + rel = document.relationship({ type: :image, target: model.image_url, data: model.image_data }) rel_id = rel.relationship_id rel_name = rel.formatted_target - + xml.send 'w:p', paragraph_options do xml.send 'w:pPr' do xml.send 'w:spacing', { 'w:lineRule' => 'auto', 'w:line' => ds.style_line } xml.send 'w:contextualSpacing', { 'w:val' => '0' } xml.send 'w:jc', { 'w:val' => model.image_align.to_s } @@ -145,43 +149,43 @@ xml.send 'w:rtl', { 'w:val' => '0' } end end end end - + def render_linebreak(xml, model) xml.send 'w:r' do xml.send 'w:br' end end - + def render_link(xml, model) rel = document.relationship({ target: model.link_href, type: :link }) - + xml.send 'w:hyperlink', { 'r:id' => rel.formatted_id } do xml.send 'w:r', run_options do render_run_attributes(xml, model, false) xml.send 'w:t', { 'xml:space' => 'preserve' }, model.link_content end end end - + def render_list(xml, model) if model.list_level == 0 document.toplevel_lists << model list_num = document.toplevel_lists.length # numbering uses 1-based index end - + model.recursive_items.each do |item| render_listitem(xml, item, list_num) end end - + def render_listitem(xml, model, list_num) ls = document.find_list_style(model.list_item_type, model.list_item_level) hanging = ls.style_left.to_i - ls.style_indent.to_i - 1 - + xml.send 'w:p', paragraph_options do xml.send 'w:pPr' do xml.send 'w:numPr' do xml.send 'w:ilvl', { 'w:val' => model.list_item_level } xml.send 'w:numId', { 'w:val' => list_num } @@ -196,22 +200,22 @@ method = render_method_for_model(run) send(method, xml, run) end end end - + def render_pagebreak(xml, model) xml.send 'w:p', paragraph_options do xml.send 'w:r', run_options do xml.send 'w:br', { 'w:type' => 'page' } end end end - + def render_paragraph(xml, model) run_props = [:color, :size, :bold, :italic, :underline].map { |m| model.send("paragraph_#{ m }") }.compact - + xml.send 'w:p', paragraph_options do xml.send 'w:pPr' do xml.send 'w:pStyle', { 'w:val' => model.paragraph_style } unless model.paragraph_style.nil? xml.send 'w:contextualSpacing', { 'w:val' => '0' } xml.send 'w:jc', { 'w:val' => model.paragraph_align } unless model.paragraph_align.nil? @@ -219,37 +223,37 @@ end model.runs.each do |run| method = render_method_for_model(run) send(method, xml, run) end - end + end end - + def render_rule(xml, model) - options = { 'w:color' => model.rule_color, 'w:sz' => model.rule_size, 'w:val' => model.rule_line, 'w:space' => model.rule_spacing } - + options = { 'w:color' => model.rule_color, 'w:sz' => model.rule_size, 'w:val' => model.rule_line, 'w:space' => model.rule_spacing } + xml.send 'w:p', paragraph_options do xml.send 'w:pPr' do xml.send 'w:pBdr' do xml.send 'w:top', options end end end end - + def render_text(xml, model) xml.send 'w:r', run_options do render_run_attributes(xml, model, false) xml.send 'w:t', { 'xml:space' => 'preserve' }, model.text_content end end - + def render_table(xml, model) borders = %w(top left bottom right horizontal vertical).select do |m| model.send("table_border_#{ m }_size") > 0 end - + xml.send 'w:tbl' do xml.send 'w:tblPr' do xml.send 'w:tblStyle', { 'w:val' => 'DefaultTable' } xml.send 'w:bidiVisual', { 'w:val' => '0' } xml.send 'w:tblW', { 'w:w' => model.table_width.to_f, 'w:type' => 'dxa' } @@ -302,19 +306,19 @@ end end end end end - - # don't know why this is needed, but it prevents a + + # don't know why this is needed, but it prevents a # rendering error. render_paragraph(xml, Caracal::Core::Models::ParagraphModel.new) end - + #============= OPTIONS =================================== - + def root_options { 'xmlns:mc' => 'http://schemas.openxmlformats.org/markup-compatibility/2006', 'xmlns:o' => 'urn:schemas-microsoft-com:office:office', 'xmlns:r' => 'http://schemas.openxmlformats.org/officeDocument/2006/relationships', @@ -330,25 +334,25 @@ 'xmlns:c' => 'http://schemas.openxmlformats.org/drawingml/2006/chart', 'xmlns:lc' => 'http://schemas.openxmlformats.org/drawingml/2006/lockedCanvas', 'xmlns:dgm' => 'http://schemas.openxmlformats.org/drawingml/2006/diagram' } end - + def page_margin_options - { - 'w:top' => document.page_margin_top, - 'w:bottom' => document.page_margin_bottom, - 'w:left' => document.page_margin_left, - 'w:right' => document.page_margin_right + { + 'w:top' => document.page_margin_top, + 'w:bottom' => document.page_margin_bottom, + 'w:left' => document.page_margin_left, + 'w:right' => document.page_margin_right } end - + def page_size_options - { - 'w:w' => document.page_width, - 'w:h' => document.page_height + { + 'w:w' => document.page_width, + 'w:h' => document.page_height } end - + end end end