diff --git a/lib/sablon/processor/document/blocks.rb b/lib/sablon/processor/document/blocks.rb index 2f0f8cd3..a10334bb 100644 --- a/lib/sablon/processor/document/blocks.rb +++ b/lib/sablon/processor/document/blocks.rb @@ -86,7 +86,7 @@ def self.encloses?(start_field, end_field) end end - class ImageBlock < ParagraphBlock + class ImageBlock < Block def self.encloses?(start_field, end_field) start_field.expression.start_with?('@') end @@ -104,8 +104,8 @@ def replace(image) blip.attributes['embed'].value = image.local_rid if blip drawing_size = node.at_xpath('.//wp:extent') - # if image properties are defined, the size of the placeholder image - # should be replaced with the actual values + # if image properties are defined, the size of the placeholder + # image should be replaced with the actual values if image.width && image.height drawing_size.attributes['cx'].value = image.width.to_s if drawing_size drawing_size.attributes['cy'].value = image.height.to_s if drawing_size @@ -126,6 +126,28 @@ def self.encloses?(start_field, end_field) super && parent(start_field) == parent(end_field) end + def process(env) + # Create a mock document structure so xpath queries will work + # correctly on block level content (i.e. searching for the first + # ancestor paragraph) + doc_node = Nokogiri::XML::Node.new('document', start_node.document) + doc_node.namespace = start_node.parent.namespace + p_node = Nokogiri::XML::Node.new('p', doc_node.document) + p_node.namespace = start_node.parent.namespace + p_node.children = Nokogiri::XML::NodeSet.new(p_node.document, + body.map(&:dup)) + doc_node.children = Nokogiri::XML::NodeSet.new(p_node.document, + [p_node]) + Processor::Document.process doc_node, env + + if p_node.parent.nil? + replace_parent_node(doc_node.children) + [] + else + p_node.children + end + end + def remove_control_elements body.each(&:remove) start_field.remove @@ -139,6 +161,16 @@ def start_node def end_node @end_node ||= end_field.start_node end + + private + + # A block level insertion has occurred which must replace the + # parent paragraph of the start node. + def replace_parent_node(content) + node = start_node.ancestors('.//w:p').first + content.each { |n| node.add_next_sibling n } + node.remove + end end end end diff --git a/test/fixtures/conditionals_sample.docx b/test/fixtures/conditionals_sample.docx index 73905b30..d2e4d71e 100644 Binary files a/test/fixtures/conditionals_sample.docx and b/test/fixtures/conditionals_sample.docx differ diff --git a/test/fixtures/conditionals_template.docx b/test/fixtures/conditionals_template.docx index bb7d41e9..369c7ca2 100644 Binary files a/test/fixtures/conditionals_template.docx and b/test/fixtures/conditionals_template.docx differ diff --git a/test/fixtures/images_sample.docx b/test/fixtures/images_sample.docx index aa9b2879..c9803aa2 100644 Binary files a/test/fixtures/images_sample.docx and b/test/fixtures/images_sample.docx differ diff --git a/test/fixtures/images_template.docx b/test/fixtures/images_template.docx index ee7e60a8..b3ca597c 100644 Binary files a/test/fixtures/images_template.docx and b/test/fixtures/images_template.docx differ diff --git a/test/sablon_test.rb b/test/sablon_test.rb index 8478bd8d..4ee34b2b 100644 --- a/test/sablon_test.rb +++ b/test/sablon_test.rb @@ -105,7 +105,8 @@ def test_generate_document_from_template object: OpenStruct.new(true_method: true, false_method: false), success_content: '✓', fail_content: '✗', - content: 'Some Content' + content: 'Some Content', + block_content: Sablon.content(:html, '
HTML paragraph injected
') } # template.render_to_file @output_path, context @@ -155,7 +156,7 @@ def test_generate_document_from_template darth = Sablon.content(:image, @image_fixtures.join('darth_vader.jpg')) # im_data = StringIO.new(IO.binread(@image_fixtures.join('clone.jpg'))) - trooper = Sablon.content(:image, im_data, filename: 'clone.jpg', properties: {height: '8cm', width: '4cm'}) + trooper = Sablon.content(:image, im_data, filename: 'clone.jpg', properties: {height: '1cm', width: '4cm'}) # # with the following context setup all trooper should be reused and # only a single file added to media. R2D2 should get duplicated in the