From 4289566552e20ad848f09868fe3a7bb9dc6c12db Mon Sep 17 00:00:00 2001 From: Matthew Kobs Date: Tue, 26 Jan 2016 10:18:58 -0600 Subject: [PATCH 01/17] [skip] Made attributes and properties chainable (5h) --- lib/openxml/docx/attribute_builder.rb | 11 +++++-- lib/openxml/docx/chainable_nested_context.rb | 9 ++++++ lib/openxml/docx/elements/container.rb | 7 +++++ lib/openxml/docx/elements/element.rb | 2 +- lib/openxml/docx/properties/base_property.rb | 2 +- .../docx/properties/container_property.rb | 7 +++++ lib/openxml/docx/property_builder.rb | 31 +++++++++++++++---- lib/openxml/docx/style.rb | 23 +++++++++++++- 8 files changed, 80 insertions(+), 12 deletions(-) create mode 100644 lib/openxml/docx/chainable_nested_context.rb diff --git a/lib/openxml/docx/attribute_builder.rb b/lib/openxml/docx/attribute_builder.rb index d5ba18ed..ede917d6 100644 --- a/lib/openxml/docx/attribute_builder.rb +++ b/lib/openxml/docx/attribute_builder.rb @@ -204,11 +204,9 @@ def self.included(base) module ClassMethods def attribute(name, expects: nil, one_of: nil, displays_as: nil, namespace: nil, matches: nil, deprecated: false) - bad_names = %w(tag name namespace properties_tag) + bad_names = %w(tag name namespace properties_tag class) raise ArgumentError if bad_names.member? name - attr_reader name - define_method "#{name}=" do |value| valid_in?(value, one_of) unless one_of.nil? send(expects, value) unless expects.nil? @@ -216,6 +214,13 @@ def attribute(name, expects: nil, one_of: nil, displays_as: nil, namespace: nil, instance_variable_set "@#{name}", value end + # Attributes will return the element, properties will return property + define_method "#{name}" do |*args| + return instance_variable_get "@#{name}" if args.empty? + public_send(:"#{name}=", args.first) + self + end + camelized_name = name.to_s.gsub(/_([a-z])/i) { $1.upcase }.to_sym attributes[name] = [displays_as || camelized_name, namespace || @attribute_namespace] end diff --git a/lib/openxml/docx/chainable_nested_context.rb b/lib/openxml/docx/chainable_nested_context.rb new file mode 100644 index 00000000..493e7d15 --- /dev/null +++ b/lib/openxml/docx/chainable_nested_context.rb @@ -0,0 +1,9 @@ +module OpenXml + module Docx + module ChainableNestedContext + def end_chain + @self_was + end + end + end +end diff --git a/lib/openxml/docx/elements/container.rb b/lib/openxml/docx/elements/container.rb index 0df92ced..50d1fd6a 100644 --- a/lib/openxml/docx/elements/container.rb +++ b/lib/openxml/docx/elements/container.rb @@ -21,6 +21,13 @@ def to_xml(xml) } end + def method_missing(method, *args, &block) + found_child = children.select { |child| child.name == method.to_s } + return if found_child.empty? + return found_child.first if found_child.count == 1 + found_child + end + private def properties_tag diff --git a/lib/openxml/docx/elements/element.rb b/lib/openxml/docx/elements/element.rb index c943cfa3..ef168949 100644 --- a/lib/openxml/docx/elements/element.rb +++ b/lib/openxml/docx/elements/element.rb @@ -15,7 +15,7 @@ def tag(*args) def name(*args) @property_name = args.first if args.any? - @name + @property_name end def namespace(*args) diff --git a/lib/openxml/docx/properties/base_property.rb b/lib/openxml/docx/properties/base_property.rb index d2d1403d..9bb127a6 100644 --- a/lib/openxml/docx/properties/base_property.rb +++ b/lib/openxml/docx/properties/base_property.rb @@ -20,7 +20,7 @@ def tag(*args) def name(*args) @property_name = args.first if args.any? - @name + @property_name end def namespace(*args) diff --git a/lib/openxml/docx/properties/container_property.rb b/lib/openxml/docx/properties/container_property.rb index 45565466..60f7e03b 100644 --- a/lib/openxml/docx/properties/container_property.rb +++ b/lib/openxml/docx/properties/container_property.rb @@ -42,6 +42,13 @@ def to_xml(xml) } end + def method_missing(method, *args, &block) + found_child = children.select { |child| child.name == method.to_s } + return if found_child.empty? + return found_child.first if found_child.count == 1 + found_child + end + private attr_reader :children diff --git a/lib/openxml/docx/property_builder.rb b/lib/openxml/docx/property_builder.rb index 5aaab536..ec138a7d 100644 --- a/lib/openxml/docx/property_builder.rb +++ b/lib/openxml/docx/property_builder.rb @@ -1,3 +1,5 @@ +require "openxml/docx/chainable_nested_context" + module OpenXml module Docx module PropertyBuilder @@ -13,8 +15,6 @@ def properties_tag(*args) end def value_property(name, as: nil) - attr_reader name - properties[name] = (as || name).to_s class_eval <<-CODE, __FILE__, __LINE__ + 1 @@ -24,6 +24,12 @@ def #{name}=(value) prop_class = OpenXml::Docx::Properties.const_get class_name instance_variable_set "@#{name}", prop_class.new(value) end + + def #{name}(*args) + return instance_variable_get "@#{name}" if args.empty? + public_send :"#{name}=", args.first + self + end CODE end @@ -31,16 +37,30 @@ def property(name, as: nil) properties[name] = (as || name).to_s class_eval <<-CODE, __FILE__, __LINE__ + 1 - def #{name} + def #{name}(*args) property_key = "#{name}".to_sym class_name = properties[property_key].split("_").map(&:capitalize).join prop_class = OpenXml::Docx::Properties.const_get class_name if instance_variable_get("@#{name}").nil? - instance_variable_set "@#{name}", prop_class.new + instance_variable_set "@#{name}", prop_class.new(*args) end - instance_variable_get "@#{name}" + prop_instance = instance_variable_get "@#{name}" + + if block_given? + block = Proc.new + if block.arity == 0 + prop_instance.instance_eval(&block) + else + yield self + end + return self + end + + prop_instance.extend OpenXml::Docx::ChainableNestedContext + prop_instance.instance_variable_set "@self_was", self + prop_instance end CODE end @@ -68,7 +88,6 @@ def properties def properties_tag self.class.properties_tag end - end end end diff --git a/lib/openxml/docx/style.rb b/lib/openxml/docx/style.rb index 85cd393e..11fe349f 100644 --- a/lib/openxml/docx/style.rb +++ b/lib/openxml/docx/style.rb @@ -1,10 +1,12 @@ +require "openxml/docx/chainable_nested_context" + module OpenXml module Docx class Style include AttributeBuilder include PropertyBuilder - attr_reader :paragraph, :character, :table, :type + attr_reader :type attribute :custom, expects: :boolean, displays_as: :customStyle, namespace: :w attribute :default, expects: :boolean, namespace: :w @@ -35,6 +37,21 @@ def type=(value) send "install_#{value}_properties" end + def paragraph + @paragraph.instance_variable_set "@self_was", self + @paragraph + end + + def character + @character.instance_variable_set "@self_was", self + @character + end + + def table + @table.instance_variable_set "@self_was", self + @table + end + def tag :style end @@ -69,18 +86,22 @@ def install_paragraph_properties @table = nil @character = OpenXml::Docx::Elements::Run.new @paragraph = OpenXml::Docx::Elements::Paragraph.new + @character.extend OpenXml::Docx::ChainableNestedContext + @paragraph.extend OpenXml::Docx::ChainableNestedContext end def install_character_properties @paragraph = nil @table = nil @character = OpenXml::Docx::Elements::Run.new + @character.extend OpenXml::Docx::ChainableNestedContext end def install_table_properties @character = nil @paragraph = nil @table = OpenXml::Docx::Elements::Table.new + @table.extend OpenXml::Docx::ChainableNestedContext end def property_xml(xml) From 5e08e58231b1a7e7f58607e0336ff58b71e42ece Mon Sep 17 00:00:00 2001 From: Matthew Kobs Date: Tue, 26 Jan 2016 10:23:36 -0600 Subject: [PATCH 02/17] [skip] Enabled passing options and blocks to element and property initializers (1h) --- lib/openxml/docx/elements/container.rb | 3 ++- lib/openxml/docx/elements/element.rb | 15 +++++++++++++++ lib/openxml/docx/properties/base_property.rb | 8 ++++++++ lib/openxml/docx/properties/container_property.rb | 3 ++- 4 files changed, 27 insertions(+), 2 deletions(-) diff --git a/lib/openxml/docx/elements/container.rb b/lib/openxml/docx/elements/container.rb index 50d1fd6a..4523b7cd 100644 --- a/lib/openxml/docx/elements/container.rb +++ b/lib/openxml/docx/elements/container.rb @@ -6,8 +6,9 @@ class Container < Element attr_reader :children - def initialize + def initialize(options={}) @children = [] + super end def <<(child) diff --git a/lib/openxml/docx/elements/element.rb b/lib/openxml/docx/elements/element.rb index ef168949..258a7a72 100644 --- a/lib/openxml/docx/elements/element.rb +++ b/lib/openxml/docx/elements/element.rb @@ -25,6 +25,21 @@ def namespace(*args) end + def initialize(options={}) + options.each do |(attr_name, value)| + self.public_send("#{attr_name}=", value) if self.respond_to? :"#{attr_name}=" + end + + if block_given? + block = Proc.new + if block.arity == 0 + instance_eval(&block) + else + yield self + end + end + end + def tag self.class.tag || default_tag end diff --git a/lib/openxml/docx/properties/base_property.rb b/lib/openxml/docx/properties/base_property.rb index 9bb127a6..4aaeb283 100644 --- a/lib/openxml/docx/properties/base_property.rb +++ b/lib/openxml/docx/properties/base_property.rb @@ -35,6 +35,14 @@ def initialize(tag=nil, *args) raise ArgumentError, "Invalid tag name for #{name}: #{tag.inspect}. It should be one of #{self.class.allowed_tags.join(", ")}." end @tag = tag + + if block_given? + if block.arity == 0 + instance_eval(&block) + else + yield self + end + end end def render? diff --git a/lib/openxml/docx/properties/container_property.rb b/lib/openxml/docx/properties/container_property.rb index 60f7e03b..a23373b7 100644 --- a/lib/openxml/docx/properties/container_property.rb +++ b/lib/openxml/docx/properties/container_property.rb @@ -17,8 +17,9 @@ def child_class(*args) alias :child_classes :child_class end - def initialize + def initialize(*args) @children = [] + super end def <<(child) From 0104480b25160eab19414e5d5bad7775dcac61a1 Mon Sep 17 00:00:00 2001 From: Matthew Kobs Date: Tue, 26 Jan 2016 10:24:59 -0600 Subject: [PATCH 03/17] [skip] Enabled element scaffolding (20m) --- lib/openxml/docx/elements/element.rb | 7 +++++++ lib/openxml/docx/properties/base_property.rb | 6 +++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/lib/openxml/docx/elements/element.rb b/lib/openxml/docx/elements/element.rb index 258a7a72..bc4b781d 100644 --- a/lib/openxml/docx/elements/element.rb +++ b/lib/openxml/docx/elements/element.rb @@ -26,6 +26,8 @@ def namespace(*args) end def initialize(options={}) + build_scaffold if options.fetch(:scaffold, true) + options.each do |(attr_name, value)| self.public_send("#{attr_name}=", value) if self.respond_to? :"#{attr_name}=" end @@ -58,6 +60,11 @@ def to_xml(xml) private + # Override in subclasses to set up default attributes, properties, and children + # when the `build` class method is used to construct the object + def build_scaffold + end + def default_tag (class_name[0, 1].downcase + class_name[1..-1]).to_sym end diff --git a/lib/openxml/docx/properties/base_property.rb b/lib/openxml/docx/properties/base_property.rb index 4aaeb283..9fbcf40c 100644 --- a/lib/openxml/docx/properties/base_property.rb +++ b/lib/openxml/docx/properties/base_property.rb @@ -29,12 +29,13 @@ def namespace(*args) end end - def initialize(tag=nil, *args) + def initialize(tag=nil, *args, scaffold: true) return unless self.class.allowed_tags unless self.class.allowed_tags.include?(tag) raise ArgumentError, "Invalid tag name for #{name}: #{tag.inspect}. It should be one of #{self.class.allowed_tags.join(", ")}." end @tag = tag + build_scaffold if scaffold if block_given? if block.arity == 0 @@ -75,6 +76,9 @@ def default_namespace private + def build_scaffold + end + def class_name self.class.to_s.split(/::/).last end From cbfdac4250420dfcb62010d93778509dc6a2638d Mon Sep 17 00:00:00 2001 From: Matthew Kobs Date: Tue, 26 Jan 2016 10:25:51 -0600 Subject: [PATCH 04/17] [skip] Added scaffolding for tables (10m) --- lib/openxml/docx/elements/table.rb | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/openxml/docx/elements/table.rb b/lib/openxml/docx/elements/table.rb index 4502860e..274e4f65 100644 --- a/lib/openxml/docx/elements/table.rb +++ b/lib/openxml/docx/elements/table.rb @@ -24,6 +24,15 @@ class Table < Container property :table_p_pr property :table_width + private + + def build_scaffold + table_width.type = :auto + table_width.width = 0 + table_layout.type = :fixed + push OpenXml::Docx::Elements::TableGrid.new + end + end end end From b53634a245b3cce4aee934d1f26b993051263d71 Mon Sep 17 00:00:00 2001 From: Matthew Kobs Date: Tue, 26 Jan 2016 10:27:02 -0600 Subject: [PATCH 05/17] [skip] Added various convenience methods (20m) --- lib/openxml/docx/elements/container.rb | 7 +++++++ lib/openxml/docx/elements/table.rb | 13 +++++++++++++ lib/openxml/docx/properties/container_property.rb | 7 +++++++ lib/openxml/docx/properties/table_borders.rb | 12 ++++++++++++ lib/openxml/docx/properties/table_cell_margins.rb | 12 ++++++++++++ 5 files changed, 51 insertions(+) diff --git a/lib/openxml/docx/elements/container.rb b/lib/openxml/docx/elements/container.rb index 4523b7cd..4b8cd7ca 100644 --- a/lib/openxml/docx/elements/container.rb +++ b/lib/openxml/docx/elements/container.rb @@ -13,6 +13,13 @@ def initialize(options={}) def <<(child) children << child + self + end + alias :push :<< + + def concat(new_children) + Array(new_children).each { |child| self.push child } + self end def to_xml(xml) diff --git a/lib/openxml/docx/elements/table.rb b/lib/openxml/docx/elements/table.rb index 274e4f65..a81f297c 100644 --- a/lib/openxml/docx/elements/table.rb +++ b/lib/openxml/docx/elements/table.rb @@ -24,6 +24,19 @@ class Table < Container property :table_p_pr property :table_width + def width(*args) + return table_width.width if args.empty? + table_width.width = args.first + table_width.type = :dxa if table_width.type == :auto + self + end + + def width_unit(*args) + return table_width.type if args.empty? + table_width.type = args.first + self + end + private def build_scaffold diff --git a/lib/openxml/docx/properties/container_property.rb b/lib/openxml/docx/properties/container_property.rb index a23373b7..4348c9bb 100644 --- a/lib/openxml/docx/properties/container_property.rb +++ b/lib/openxml/docx/properties/container_property.rb @@ -25,6 +25,13 @@ def initialize(*args) def <<(child) raise ArgumentError, invalid_child_message unless valid_child?(child) children << child + self + end + alias :push :<< + + def concat(new_children) + Array(new_children).each { |child| self.push child } + self end def each(*args, &block) diff --git a/lib/openxml/docx/properties/table_borders.rb b/lib/openxml/docx/properties/table_borders.rb index 939bf5c1..e3e5eb95 100644 --- a/lib/openxml/docx/properties/table_borders.rb +++ b/lib/openxml/docx/properties/table_borders.rb @@ -7,6 +7,18 @@ class TableBorders < ContainerProperty tag :tblBorders child_class :table_border + def vertical_tags + %i(left right insideV) + end + + def horizontal_tags + %i(top bottom insideH) + end + + def all_tags + vertical_tags + horizontal_tags + end + end end end diff --git a/lib/openxml/docx/properties/table_cell_margins.rb b/lib/openxml/docx/properties/table_cell_margins.rb index 4222718a..54acd37d 100644 --- a/lib/openxml/docx/properties/table_cell_margins.rb +++ b/lib/openxml/docx/properties/table_cell_margins.rb @@ -7,6 +7,18 @@ class TableCellMargins < ContainerProperty tag :tblCellMar child_class :table_cell_margin + def vertical_tags + %i(top bottom) + end + + def horizontal_tags + %i(left right) + end + + def all_tags + vertical_tags + horizontal_tags + end + end end end From d79c99120f6507aa62f60d4577a49346646711f6 Mon Sep 17 00:00:00 2001 From: Matthew Kobs Date: Tue, 26 Jan 2016 10:27:38 -0600 Subject: [PATCH 06/17] [skip] Added smart initialization for runs (20m) --- lib/openxml/docx/elements/run.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/openxml/docx/elements/run.rb b/lib/openxml/docx/elements/run.rb index bbdafd1a..fed08d23 100644 --- a/lib/openxml/docx/elements/run.rb +++ b/lib/openxml/docx/elements/run.rb @@ -1,3 +1,5 @@ +require "openxml/docx/elements/text" + module OpenXml module Docx module Elements @@ -45,6 +47,12 @@ class Run < Container property :shading property :underline + def initialize(text=nil, options={}) + # More performant than &block: http://mudge.name/2011/01/26/passing-blocks-in-ruby-without-block.html + block_given? ? super(options, &Proc.new) : super(options) + push OpenXml::Docx::Elements::Text.new(text).space(options.fetch(:text_spacing, :preserve)) unless text.nil? + end + end end end From b1642f1367f89ef1c222768f742396d0369ec362 Mon Sep 17 00:00:00 2001 From: Matthew Kobs Date: Tue, 26 Jan 2016 10:28:46 -0600 Subject: [PATCH 07/17] [skip] Added example script using DSL (1h) --- examples/dsl | 134 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100755 examples/dsl diff --git a/examples/dsl b/examples/dsl new file mode 100755 index 00000000..e1960ee5 --- /dev/null +++ b/examples/dsl @@ -0,0 +1,134 @@ +#!/usr/bin/env ruby + +$:.push Dir.pwd + "/lib" +require "ox" +require "openxml/docx" + +ROWS = 8 +COLUMNS = 4 + +def build_docx + docx = OpenXml::Docx::Package.new + + heading = OpenXml::Docx::Elements::Paragraph.new + .paragraph_style("Heading1") + + heading << OpenXml::Docx::Elements::Run.new("A Table of Some Sort") + docx.document << heading + + table = OpenXml::Docx::Elements::Table.new + .width(5000) + .width_unit(:pct) + .table_style("TableGrid") + + ROWS.times do + row = OpenXml::Docx::Elements::TableRow.new + + COLUMNS.times do + cell = OpenXml::Docx::Elements::TableCell.new + + paragraph = OpenXml::Docx::Elements::Paragraph.new + .paragraph_style("CellText") + line_one = OpenXml::Docx::Elements::Run.new("Lorem ipsum dolor sit amet, consectetur adipiscing elit.") + line_one << OpenXml::Docx::Elements::Break.new + line_two = OpenXml::Docx::Elements::Run.new("Donec a diam lectus. Sed sit amet ipsum mauris.") + + paragraph << line_one + paragraph << line_two + cell << paragraph + row << cell + end + + table << row + end + + docx.document << table + docx.document << OpenXml::Docx::Section.new + .page_size + .height(15840) + .width(12240) + .orientation(:portrait) + .end_chain + .page_margins + .bottom(720) + .footer(360) + .gutter(0) + .header(360) + .left(720) + .right(720) + .top(720) + .end_chain + + docx.styles << build_heading_style + docx.styles << build_table_style + docx.styles << build_cell_text_style + + filename = "rocx_test_table.docx" + system "rm -f ~/Desktop/#{filename}" # -f so that we don't have an error if the file doesn't exist + docx.save File.expand_path("~/Desktop/#{filename}") + exec "open ~/Desktop/#{filename}" +end + +def build_table_style + OpenXml::Docx::Style.new(:table) + .id("TableGrid") + .style_name("Table Grid") + .primary_style(true) + .table + .table_borders do + all_tags.each do |tag_name| + push OpenXml::Docx::Properties::TableBorder.new(tag_name, :single) + .color("000000") + .width(8) + end + end + .table_cell_margins do + vertical_tags.each do |tag_name| + push OpenXml::Docx::Properties::TableCellMargin.new(tag_name) + .type(:dxa) + .width(0) + end + horizontal_tags.each do |tag_name| + push OpenXml::Docx::Properties::TableCellMargin.new(tag_name) + .type(:dxa) + .width(108) + end + end + .end_chain +end + +def build_heading_style + OpenXml::Docx::Style.new(:paragraph) + .id("Heading1") + .style_name("Heading 1") + .primary_style(true) + .paragraph + .alignment(:center) + .end_chain + .character + .bold(true) + .font_size(48) + .end_chain +end + +def build_cell_text_style + OpenXml::Docx::Style.new(:paragraph) + .id("CellText") + .style_name("Table Cell") + .primary_style(true) + .paragraph + .alignment(:center) + .text_alignment(:center) + .end_chain + .character + .font + .ascii("Times New Roman") + .high_ansi("Times New Roman") + .end_chain + .font_size(20) + .end_chain +end + +# Do the thing! +build_docx + From 232b57e7ab3bffb3346ee71bf19a795a5b7b1d5d Mon Sep 17 00:00:00 2001 From: Matthew Kobs Date: Tue, 26 Jan 2016 13:50:46 -0600 Subject: [PATCH 08/17] [skip] Toggled scaffolding off by default (2m) --- examples/dsl | 2 +- lib/openxml/docx/elements/element.rb | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/examples/dsl b/examples/dsl index e1960ee5..250712de 100755 --- a/examples/dsl +++ b/examples/dsl @@ -16,7 +16,7 @@ def build_docx heading << OpenXml::Docx::Elements::Run.new("A Table of Some Sort") docx.document << heading - table = OpenXml::Docx::Elements::Table.new + table = OpenXml::Docx::Elements::Table.new(scaffold: true) .width(5000) .width_unit(:pct) .table_style("TableGrid") diff --git a/lib/openxml/docx/elements/element.rb b/lib/openxml/docx/elements/element.rb index bc4b781d..9ff4fb3b 100644 --- a/lib/openxml/docx/elements/element.rb +++ b/lib/openxml/docx/elements/element.rb @@ -26,7 +26,10 @@ def namespace(*args) end def initialize(options={}) - build_scaffold if options.fetch(:scaffold, true) + if options.fetch(:scaffold, false) + @options = options # Make available for scaffolding if needed + build_scaffold + end options.each do |(attr_name, value)| self.public_send("#{attr_name}=", value) if self.respond_to? :"#{attr_name}=" @@ -59,6 +62,7 @@ def to_xml(xml) end private + attr_reader :options # Override in subclasses to set up default attributes, properties, and children # when the `build` class method is used to construct the object From b8e11e948bd795f48a4ada3a6fbb19080e13db2d Mon Sep 17 00:00:00 2001 From: Matthew Kobs Date: Tue, 26 Jan 2016 15:33:03 -0600 Subject: [PATCH 09/17] [skip] Updated wordprocessing drawing position offset to work with DSL (5m) --- .../elements/word_processing_drawing_position_offset.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/openxml/docx/elements/word_processing_drawing_position_offset.rb b/lib/openxml/docx/elements/word_processing_drawing_position_offset.rb index f353a670..3d39291a 100644 --- a/lib/openxml/docx/elements/word_processing_drawing_position_offset.rb +++ b/lib/openxml/docx/elements/word_processing_drawing_position_offset.rb @@ -9,8 +9,10 @@ def <<(text) value << text if text.is_a? String end - def value - @value ||= "" + def value(*args) + return @value ||= "" unless args.any? + @value = args.first.to_s + self end def value=(new_value) From 23c4e15c3bebb88753f26988552d5fe5668ccfc4 Mon Sep 17 00:00:00 2001 From: Matthew Kobs Date: Tue, 26 Jan 2016 15:33:34 -0600 Subject: [PATCH 10/17] [skip] Added scaffolding for Drawing element (1h) --- lib/openxml/docx/elements/drawing.rb | 116 +++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) diff --git a/lib/openxml/docx/elements/drawing.rb b/lib/openxml/docx/elements/drawing.rb index bbf325a7..479e7365 100644 --- a/lib/openxml/docx/elements/drawing.rb +++ b/lib/openxml/docx/elements/drawing.rb @@ -1,8 +1,124 @@ +require "openxml/docx/elements/word_processing_drawing_inline" +require "openxml/docx/elements/word_processing_drawing_anchor" +require "openxml/docx/elements/word_processing_drawing_simple_position" +require "openxml/docx/elements/word_processing_drawing_position_h" +require "openxml/docx/elements/word_processing_drawing_position_v" +require "openxml/docx/elements/word_processing_drawing_position_offset" +require "openxml/docx/elements/word_processing_drawing_extent" +require "openxml/docx/elements/word_processing_drawing_wrap_through" +require "openxml/docx/elements/word_processing_drawing_wrap_tight" +require "openxml/docx/elements/word_processing_drawing_wrap_polygon" +require "openxml/docx/elements/word_processing_drawing_wrap_square" +require "openxml/docx/elements/word_processing_drawing_wrap_top_and_bottom" +require "openxml/docx/elements/word_processing_drawing_wrap_none" +require "openxml/docx/elements/word_processing_drawing_wrap_coordinate" +require "openxml/docx/elements/word_processing_drawing_object_nv_properties" +require "openxml/drawingml/elements/graphic" + module OpenXml module Docx module Elements class Drawing < Container tag :drawing + attr_reader :graphic + + def self.next_index + @index = (@index || 0) + 1 + end + + private + + def build_scaffold + inline = options.fetch(:anchor_type, :floating) == :inline + width = options.fetch(:width, 0) + height = options.fetch(:height, 0) + wrap_type = options.fetch(:wrap_type, :none) + x_pos, y_pos = options.fetch(:position, [0, 0]) + + anchor = if inline + OpenXml::Docx::Elements::WordProcessingDrawingInline.new + .distance_from_bottom(0) + .distance_from_top(0) + .distance_from_left(0) + .distance_from_right(0) + else + OpenXml::Docx::Elements::WordProcessingDrawingAnchor.new + .distance_from_bottom(0) + .distance_from_top(0) + .distance_from_left(0) + .distance_from_right(0) + .allow_overlap(true) + .behind_document(false) + .layout_in_cell(true) + .locked(false) + .z_index(1000) + .simple_position(false) + .push(OpenXml::Docx::Elements::WordProcessingDrawingSimplePosition.new do |sp| + sp.x = x_pos + sp.y = y_pos + end) + .push(OpenXml::Docx::Elements::WordProcessingDrawingPositionH.new do |ph| + ph.relative_from(:column) + ph.push OpenXml::Docx::Elements::WordProcessingDrawingPositionOffset.new + .value(x_pos) + end) + .push(OpenXml::Docx::Elements::WordProcessingDrawingPositionV.new do |ph| + ph.relative_from(:paragraph) + ph.push OpenXml::Docx::Elements::WordProcessingDrawingPositionOffset.new + .value(y_pos) + end) + end + + anchor << OpenXml::Docx::Elements::WordProcessingDrawingExtent.new + .extent_length(width) + .extent_width(height) + + unless inline + case wrap_type + when :polygon + coordinates = options.fetch(:wrap_coordinates, [[0,0], [0,height], [width, height], [width, 0]]) + wrap_margins = options.fetch(:wrap_margins, {}) + behavior_klass = options.fetch(:wrap_behavior, :tight) == :through ? OpenXml::Docx::Elements::WordProcessingDrawingWrapThrough : OpenXml::Docx::Elements::WordProcessingDrawingWrapTight + anchor << behavior_klass.new do + distance_from_left(wrap_margins.fetch(:left, 0)) + distance_from_right(wrap_margins.fetch(:right, 0)) + wrap_text(:bothSides) + push(OpenXml::Docx::Elements::WordProcessingDrawingWrapPolygon.new do + coordinates.each_with_index do |(x, y), index| + coordinate_type = index == 0 ? :start : :lineTo + push OpenXml::Docx::Elements::WordProcessingDrawingWrapCoordinate.new(coordinate_type).x(x).y(y) + end + end) + end + when :square + wrap_margins = options.fetch(:wrap_margins, {}) + anchor << OpenXml::Docx::Elements::WordProcessingDrawingWrapSquare.new + .distance_from_bottom(wrap_margins.fetch(:bottom, 0)) + .distance_from_left(wrap_margins.fetch(:left, 0)) + .distance_from_right(wrap_margins.fetch(:right, 0)) + .distance_from_top(wrap_margins.fetch(:top, 0)) + .wrap_text(:bothSides) + when :top_and_bottom + wrap_margins = options.fetch(:wrap_margins, {}) + anchor << OpenXml::Docx::Elements::WordProcessingDrawingWrapTopAndBottom.new + .distance_from_bottom(wrap_margins.fetch(:bottom, 0)) + .distance_from_top(wrap_margins.fetch(:top, 0)) + else + anchor << OpenXml::Docx::Elements::WordProcessingDrawingWrapNone.new + end + end + + anchor << OpenXml::Docx::Elements::WordProcessingDrawingObjectNvProperties.new + .description(options[:filename] || options.fetch(:name, "Drawing")) + .object_name(options.fetch(:name, "Drawing")) + .id(self.class.next_index) + + @graphic = OpenXml::DrawingML::Elements::Graphic.new + anchor << @graphic + + push(anchor) + end + end end end From 1dcf6b7cfd69ae34fb3e0e5a67cf711792a361f6 Mon Sep 17 00:00:00 2001 From: Matthew Kobs Date: Tue, 26 Jan 2016 15:34:26 -0600 Subject: [PATCH 11/17] [skip] Added list of supported GraphicData types with URIs (5m) --- lib/openxml/drawingml/elements/graphic_data.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/openxml/drawingml/elements/graphic_data.rb b/lib/openxml/drawingml/elements/graphic_data.rb index 5250cb54..3eaf9be8 100644 --- a/lib/openxml/drawingml/elements/graphic_data.rb +++ b/lib/openxml/drawingml/elements/graphic_data.rb @@ -6,6 +6,11 @@ class GraphicData < OpenXml::Docx::Elements::Container attribute :uri, expects: :string + def self.data_types + { picture: "http://schemas.openxmlformats.org/drawingml/2006/picture", + wordprocessing_shape: "http://schemas.microsoft.com/office/word/2010/wordprocessingShape" } + end + end end end From c21a29be5fa8f2f7ab81125f9dbfcd53ed07a666 Mon Sep 17 00:00:00 2001 From: Matthew Kobs Date: Tue, 26 Jan 2016 15:35:05 -0600 Subject: [PATCH 12/17] [skip] Added scaffolding for Picture element (40m) --- lib/openxml/drawingml/elements/picture.rb | 76 +++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/lib/openxml/drawingml/elements/picture.rb b/lib/openxml/drawingml/elements/picture.rb index f8223ba0..55ab0760 100644 --- a/lib/openxml/drawingml/elements/picture.rb +++ b/lib/openxml/drawingml/elements/picture.rb @@ -1,9 +1,85 @@ +require "openxml/drawingml/elements/non_visual_picture_properties" +require "openxml/drawingml/elements/non_visual_drawing_properties" +require "openxml/drawingml/elements/non_visual_picture_drawing_properties" +require "openxml/drawingml/elements/picture_locks" +require "openxml/drawingml/elements/blip_fill" +require "openxml/drawingml/elements/blip" +require "openxml/drawingml/elements/stretch" +require "openxml/drawingml/elements/fill_rectangle" +require "openxml/drawingml/elements/source_rectangle" +require "openxml/drawingml/elements/picture_shape_properties" +require "openxml/drawingml/elements/transform_effect" +require "openxml/drawingml/elements/offset" +require "openxml/drawingml/elements/extents" +require "openxml/drawingml/elements/preset_geometry" +require "openxml/drawingml/elements/adjust_values_list" +require "openxml/drawingml/elements/no_fill" +require "openxml/drawingml/elements/outline" + module OpenXml module DrawingML module Elements class Picture < OpenXml::Docx::Elements::Container namespace :pic tag :pic + + def self.next_index + @index = (@index || 0) + 1 + end + + private + + def build_scaffold + image_rid = options[:image_rid] + return unless image_rid + + picture_desc = options.fetch(:name, "Image") + picture_name = options.fetch(:filename, picture_desc) + width = options.fetch(:width, 0) + height = options.fetch(:height, 0) + + # More non-visual Properties + picture_index = self.class.next_index + push(OpenXml::DrawingML::Elements::NonVisualPictureProperties.new do + push OpenXml::DrawingML::Elements::NonVisualDrawingProperties.new + .id(picture_index) + .picture_name(picture_name) + .description(picture_desc) + push OpenXml::DrawingML::Elements::NonVisualPictureDrawingProperties.new + .push(OpenXml::DrawingML::Elements::PictureLocks.new + .disallow_aspect_ratio_changes(true) + .disallow_arrowhead_changes(true)) + end) + + # The actual image + push(OpenXml::DrawingML::Elements::BlipFill.new do + push OpenXml::DrawingML::Elements::Blip.new + .embed(image_rid) + push OpenXml::DrawingML::Elements::Stretch.new + .push(OpenXml::DrawingML::Elements::FillRectangle.new) + push OpenXml::DrawingML::Elements::SourceRectangle.new + end) + + # Shape Properties + push(OpenXml::DrawingML::Elements::PictureShapeProperties.new do + push(OpenXml::DrawingML::Elements::TransformEffect.new do + push OpenXml::DrawingML::Elements::Offset.new + .x(0) + .y(0) + push OpenXml::DrawingML::Elements::Extents.new + .extent_length(width) + .extent_width(height) + end) + push(OpenXml::DrawingML::Elements::PresetGeometry.new do + preset(:rect) + push OpenXml::DrawingML::Elements::AdjustValuesList.new + end) + push OpenXml::DrawingML::Elements::NoFill.new + push OpenXml::DrawingML::Elements::Outline.new + .push(OpenXml::DrawingML::Elements::NoFill.new) + end) + end + end end end From a599df39e474078eba904e9baa7d39b5c383a315 Mon Sep 17 00:00:00 2001 From: Matthew Kobs Date: Tue, 26 Jan 2016 15:35:56 -0600 Subject: [PATCH 13/17] [skip] Added scaffolding to WPSShape element (20m) --- .../elements/word_processing_shapes_shape.rb | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/lib/openxml/docx/elements/word_processing_shapes_shape.rb b/lib/openxml/docx/elements/word_processing_shapes_shape.rb index 0f869312..2bdf8460 100644 --- a/lib/openxml/docx/elements/word_processing_shapes_shape.rb +++ b/lib/openxml/docx/elements/word_processing_shapes_shape.rb @@ -5,7 +5,61 @@ class WordProcessingShapesShape < Container tag :wsp namespace :wps attribute :normal_east_asian_flow, expects: :boolean, displays_as: :normalEastAsianFlow + + attr_reader :text_content + + private + + def build_scaffold + width = options.fetch(:width, 0) + height = options.fetch(:height, 0) + textbox = options.fetch(:textbox, false) + shape_preset = options.fetch(:shape_preset, :rect) + + push OpenXml::DrawingML::Elements::NonVisualShapeDrawingProperties.new + .textbox(textbox) + push(OpenXml::Docx::Elements::WordProcessingShapesShapeProperties.new do + push(OpenXml::DrawingML::Elements::TransformEffect.new do + push OpenXml::DrawingML::Elements::Offset.new + .x(0) + .y(0) + push OpenXml::DrawingML::Elements::Extents.new + .extent_length(width) + .extent_width(height) + end) + push OpenXml::DrawingML::Elements::PresetGeometry.new + .preset(shape_preset) + .push(OpenXml::DrawingML::Elements::AdjustValuesList.new) + push OpenXml::DrawingML::Elements::NoFill.new + push OpenXml::DrawingML::Elements::Outline.new + .push(OpenXml::DrawingML::Elements::NoFill.new) + end) + + if textbox + @text_content = OpenXml::Docx::Elements::TextboxContent.new + push OpenXml::Docx::Elements::WordProcessingShapesTextualContent.new + .push(@text_content) + end + + push OpenXml::Docx::Elements::WordProcessingShapesBodyProperties.new + .rotation(0) + .paragraph_spacing(false) + .vertical_overflow(:overflow) + .horizontal_overflow(:overflow) + .vertical(:horz) + .wrap(:square) + .number_of_columns(1) + .anchor(:t) + .anchor_center(false) + .force_anti_alias(false) + .compatible_line_spacing(true) + .push(OpenXml::DrawingML::Elements::PresetTextWarp.new + .preset(:textNoShape) + .push(OpenXml::DrawingML::Elements::AdjustValuesList.new)) + end + end end end end + From 107efc104d535ecd91f0030700a8e89ea5d3a300 Mon Sep 17 00:00:00 2001 From: Matthew Kobs Date: Tue, 26 Jan 2016 15:36:26 -0600 Subject: [PATCH 14/17] [skip] Added scaffolded picture and textbox to the dsl example (15m) --- examples/dsl | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/examples/dsl b/examples/dsl index 250712de..825495e6 100755 --- a/examples/dsl +++ b/examples/dsl @@ -3,6 +3,7 @@ $:.push Dir.pwd + "/lib" require "ox" require "openxml/docx" +require "openxml/drawingml" ROWS = 8 COLUMNS = 4 @@ -43,6 +44,42 @@ def build_docx end docx.document << table + + # ochanomizu.jpg + # 96 ppi + # 393px x 599px + image_width = (393 * (96.0 / 300) * 12700).round # Rough conversion to EMU: 1pt = 12700emu + image_height = (599 * (96.0 / 300) * 12700).round + image_rid = docx.embed_image(path: File.join(File.dirname(__FILE__), "ochanomizu.jpg")) + inline_image = OpenXml::Docx::Elements::Paragraph.new do + alignment(:center) + push OpenXml::Docx::Elements::Run.new + .push(OpenXml::Docx::Elements::Drawing.new(scaffold: true, width: image_width, height: image_height, anchor_type: :inline, wrap_type: :top_and_bottom) do + graphic << OpenXml::DrawingML::Elements::GraphicData.new + .uri(OpenXml::DrawingML::Elements::GraphicData.data_types[:picture]) + .push(OpenXml::DrawingML::Elements::Picture.new(scaffold: true, image_rid: image_rid, width: image_width, height: image_height)) + end) + end + docx.document << inline_image + + textbox_width = 6 * 72 * 12700 + textbox_height = 2 * 72 * 12700 + floating_textbox = OpenXml::Docx::Elements::Paragraph.new do + push(OpenXml::Docx::Elements::Run.new do + push(OpenXml::Docx::Elements::Drawing.new(scaffold: true, width: textbox_width, height: textbox_height, wrap_type: :top_and_bottom) do + graphic << OpenXml::DrawingML::Elements::GraphicData.new + .uri(OpenXml::DrawingML::Elements::GraphicData.data_types[:wordprocessing_shape]) + .push(OpenXml::Docx::Elements::WordProcessingShapesShape.new(scaffold: true, width: textbox_width, height: textbox_height, textbox: true) do + text_content << OpenXml::Docx::Elements::Paragraph.new + .alignment(:center) + .paragraph_style("Heading1") + .push(OpenXml::Docx::Elements::Run.new("Hello, Textboxes!")) + end) + end) + end) + end + docx.document << floating_textbox + docx.document << OpenXml::Docx::Section.new .page_size .height(15840) From 1baa14f10d713abdf7dd48dc8aae3d344a458b49 Mon Sep 17 00:00:00 2001 From: Matthew Kobs Date: Wed, 27 Jan 2016 09:49:19 -0600 Subject: [PATCH 15/17] [skip] Removed dependance on Nokogiri from test suite (15m) --- spec/elements/bidi_embed_spec.rb | 2 +- spec/elements/bidi_override_spec.rb | 2 +- spec/elements/ruby_spec.rb | 4 ++-- spec/properties/footer_reference_spec.rb | 2 +- spec/properties/header_reference_spec.rb | 2 +- spec/spec_helper.rb | 1 - spec/support/data/elements/break_element.xml | 2 +- .../support/data/elements/break_with_attributes_element.xml | 2 +- spec/support/data/elements/grid_column_element.xml | 2 +- spec/support/data/elements/paragraph_element.xml | 2 +- spec/support/data/elements/paragraph_with_runs_element.xml | 2 +- .../elements/paragraph_with_section_properties_element.xml | 2 +- spec/support/data/elements/run_element.xml | 2 +- spec/support/data/elements/symbol_element.xml | 2 +- spec/support/data/elements/table_cell_element.xml | 2 +- spec/support/data/elements/table_element.xml | 2 +- spec/support/data/elements/table_grid_element.xml | 2 +- spec/support/data/elements/table_row_element.xml | 2 +- spec/support/data/elements/text_element.xml | 2 +- spec/support/element_test_macros.rb | 6 +++--- spec/support/property_test_macros.rb | 4 ++-- spec/support/style_test_macros.rb | 2 +- spec/support/value_property_test_macros.rb | 4 ++-- 23 files changed, 27 insertions(+), 28 deletions(-) diff --git a/spec/elements/bidi_embed_spec.rb b/spec/elements/bidi_embed_spec.rb index f30a2c9b..4315a733 100644 --- a/spec/elements/bidi_embed_spec.rb +++ b/spec/elements/bidi_embed_spec.rb @@ -30,6 +30,6 @@ instance << run end - it_should_output "\n \n Smucker's Preserves\n \n ", assign: false + it_should_output "\n \n Smucker's Preserves\n \n ", assign: false end end diff --git a/spec/elements/bidi_override_spec.rb b/spec/elements/bidi_override_spec.rb index 1b329eba..eba3a392 100644 --- a/spec/elements/bidi_override_spec.rb +++ b/spec/elements/bidi_override_spec.rb @@ -30,6 +30,6 @@ instance << run end - it_should_output "\n \n Smucker's Preserves\n \n ", assign: false + it_should_output "\n \n Smucker's Preserves\n \n ", assign: false end end diff --git a/spec/elements/ruby_spec.rb b/spec/elements/ruby_spec.rb index 4a3a863c..8d6bad58 100644 --- a/spec/elements/ruby_spec.rb +++ b/spec/elements/ruby_spec.rb @@ -39,7 +39,7 @@ instance.ruby = run end - it_should_output "\n \n \n \n \n \n tō\n \n \n \n \n \n \n \n 東̄\n \n \n ", assign: false + it_should_output "\n \n \n \n \n \n tō\n \n \n \n \n \n \n \n 東̄\n \n \n ", assign: false end context "with base text, ruby text and properties set" do @@ -60,7 +60,7 @@ instance.alignment = :left end - it_should_output "\n \n \n \n \n \n \n \n \n tō\n \n \n \n \n \n \n \n 東̄\n \n \n ", assign: false + it_should_output "\n \n \n \n \n \n \n \n \n tō\n \n \n \n \n \n \n \n 東̄\n \n \n ", assign: false end end diff --git a/spec/properties/footer_reference_spec.rb b/spec/properties/footer_reference_spec.rb index c9dbb45c..29268db2 100644 --- a/spec/properties/footer_reference_spec.rb +++ b/spec/properties/footer_reference_spec.rb @@ -26,7 +26,7 @@ end with_these_attributes_set(id: "rId5", type: :default) do - it_should_output "", assign: false + it_should_output "", assign: false end end diff --git a/spec/properties/header_reference_spec.rb b/spec/properties/header_reference_spec.rb index 51487e51..cb790497 100644 --- a/spec/properties/header_reference_spec.rb +++ b/spec/properties/header_reference_spec.rb @@ -26,7 +26,7 @@ end with_these_attributes_set(id: "rId5", type: :default) do - it_should_output "", assign: false + it_should_output "", assign: false end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index e5b2159d..6a924be8 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -13,4 +13,3 @@ require "openxml/docx" require "openxml/drawingml" require "openxml/vml" -require "nokogiri" diff --git a/spec/support/data/elements/break_element.xml b/spec/support/data/elements/break_element.xml index 253f3d57..19277cf3 100644 --- a/spec/support/data/elements/break_element.xml +++ b/spec/support/data/elements/break_element.xml @@ -1,4 +1,4 @@ - + diff --git a/spec/support/data/elements/break_with_attributes_element.xml b/spec/support/data/elements/break_with_attributes_element.xml index 1ba83f34..a0533b42 100644 --- a/spec/support/data/elements/break_with_attributes_element.xml +++ b/spec/support/data/elements/break_with_attributes_element.xml @@ -1,4 +1,4 @@ - + diff --git a/spec/support/data/elements/grid_column_element.xml b/spec/support/data/elements/grid_column_element.xml index c90d92ee..c97f727f 100644 --- a/spec/support/data/elements/grid_column_element.xml +++ b/spec/support/data/elements/grid_column_element.xml @@ -1,4 +1,4 @@ - + diff --git a/spec/support/data/elements/paragraph_element.xml b/spec/support/data/elements/paragraph_element.xml index 6b608a96..8eab8ab6 100644 --- a/spec/support/data/elements/paragraph_element.xml +++ b/spec/support/data/elements/paragraph_element.xml @@ -1,4 +1,4 @@ - + diff --git a/spec/support/data/elements/paragraph_with_runs_element.xml b/spec/support/data/elements/paragraph_with_runs_element.xml index 5eda86f7..2838704c 100644 --- a/spec/support/data/elements/paragraph_with_runs_element.xml +++ b/spec/support/data/elements/paragraph_with_runs_element.xml @@ -1,4 +1,4 @@ - + diff --git a/spec/support/data/elements/paragraph_with_section_properties_element.xml b/spec/support/data/elements/paragraph_with_section_properties_element.xml index e8754608..533a2b44 100644 --- a/spec/support/data/elements/paragraph_with_section_properties_element.xml +++ b/spec/support/data/elements/paragraph_with_section_properties_element.xml @@ -1,4 +1,4 @@ - + diff --git a/spec/support/data/elements/run_element.xml b/spec/support/data/elements/run_element.xml index 4244d5a5..d2ad94af 100644 --- a/spec/support/data/elements/run_element.xml +++ b/spec/support/data/elements/run_element.xml @@ -1,4 +1,4 @@ - + diff --git a/spec/support/data/elements/symbol_element.xml b/spec/support/data/elements/symbol_element.xml index f6ecb506..4347b90b 100644 --- a/spec/support/data/elements/symbol_element.xml +++ b/spec/support/data/elements/symbol_element.xml @@ -1,4 +1,4 @@ - + diff --git a/spec/support/data/elements/table_cell_element.xml b/spec/support/data/elements/table_cell_element.xml index 4b74d05c..a68e91ef 100644 --- a/spec/support/data/elements/table_cell_element.xml +++ b/spec/support/data/elements/table_cell_element.xml @@ -1,4 +1,4 @@ - + diff --git a/spec/support/data/elements/table_element.xml b/spec/support/data/elements/table_element.xml index 3bdcac72..46d578c7 100644 --- a/spec/support/data/elements/table_element.xml +++ b/spec/support/data/elements/table_element.xml @@ -1,4 +1,4 @@ - + diff --git a/spec/support/data/elements/table_grid_element.xml b/spec/support/data/elements/table_grid_element.xml index 99e5e8a6..23490a50 100644 --- a/spec/support/data/elements/table_grid_element.xml +++ b/spec/support/data/elements/table_grid_element.xml @@ -1,4 +1,4 @@ - + diff --git a/spec/support/data/elements/table_row_element.xml b/spec/support/data/elements/table_row_element.xml index 19339276..911f0c85 100644 --- a/spec/support/data/elements/table_row_element.xml +++ b/spec/support/data/elements/table_row_element.xml @@ -1,4 +1,4 @@ - + diff --git a/spec/support/data/elements/text_element.xml b/spec/support/data/elements/text_element.xml index c926eaef..7f3ca72e 100644 --- a/spec/support/data/elements/text_element.xml +++ b/spec/support/data/elements/text_element.xml @@ -1,4 +1,4 @@ - + Banana diff --git a/spec/support/element_test_macros.rb b/spec/support/element_test_macros.rb index 94b2db11..17134125 100644 --- a/spec/support/element_test_macros.rb +++ b/spec/support/element_test_macros.rb @@ -5,7 +5,7 @@ def element_xml(part) end def xml(obj) - doc = Nokogiri::XML::Builder.new do |xml| + doc = OpenXml::Builder.new do |xml| xml.root(root_namespaces) { obj.to_xml(xml) } @@ -14,7 +14,7 @@ def xml(obj) end def doc_pattern - /<\?xml\sversion="1.0"\?>\n\n\s+([^\s].+)\n<\/root>/m + /<\?xml\sversion="1.0"\sencoding=\"utf-8\"\?>\n\n\s+([^\s].+)\n<\/root>/m end def self.included(base) @@ -55,7 +55,7 @@ def it_should_output_correct_xml(node_xml: nil) node_xml = node_xml.gsub(/(.)([A-Z])/, '\1_\2').downcase end - generated_xml = Nokogiri::XML::Builder.new do |xml| + generated_xml = OpenXml::Builder.new do |xml| xml.root("xmlns:w" => "http://wnamespace.org") { instance.to_xml(xml) } diff --git a/spec/support/property_test_macros.rb b/spec/support/property_test_macros.rb index 8d56223e..cdc53c33 100644 --- a/spec/support/property_test_macros.rb +++ b/spec/support/property_test_macros.rb @@ -1,7 +1,7 @@ module PropertyTestMacros def xml(obj) - doc = Nokogiri::XML::Builder.new do |xml| + doc = OpenXml::Builder.new do |xml| xml.root("xmlns:w" => "http://wnamespace.org") { obj.to_xml(xml) } @@ -10,7 +10,7 @@ def xml(obj) end def doc_pattern - /<\?xml\sversion="1.0"\?>\n\n\s+([^\s].+)\n<\/root>/m + /<\?xml\sversion="1.0"\sencoding=\"utf-8\"\?>\n\n\s+([^\s].+)\n<\/root>/m end def self.included(base) diff --git a/spec/support/style_test_macros.rb b/spec/support/style_test_macros.rb index 7a5e4377..88c3418d 100644 --- a/spec/support/style_test_macros.rb +++ b/spec/support/style_test_macros.rb @@ -18,7 +18,7 @@ def it_should_output_correct_xml(style_xml: nil) style_xml = style_xml.gsub(/(.)([A-Z])/, '\1_\2').downcase end - generated_xml = Nokogiri::XML::Builder.new do |xml| + generated_xml = OpenXml::Builder.new do |xml| xml.styleFoo("xmlns:w" => "http://wnamespace.com") { style.build_xml(xml) } diff --git a/spec/support/value_property_test_macros.rb b/spec/support/value_property_test_macros.rb index ced03760..4cfc1b24 100644 --- a/spec/support/value_property_test_macros.rb +++ b/spec/support/value_property_test_macros.rb @@ -1,7 +1,7 @@ module ValuePropertyTestMacros def xml(obj) - doc = Nokogiri::XML::Builder.new do |xml| + doc = OpenXml::Builder.new do |xml| xml.root("xmlns:w" => "http://wnamespace.org") { obj.to_xml(xml) } @@ -10,7 +10,7 @@ def xml(obj) end def doc_pattern - /<\?xml\sversion="1.0"\?>\n\n\s+([^\s].+)\n<\/root>/m + /<\?xml\sversion="1.0"\sencoding=\"utf-8\"\?>\n\n\s+([^\s].+)\n<\/root>/m end def self.included(base) From cf283774d290bf98f4fee714b53a7886012b023b Mon Sep 17 00:00:00 2001 From: Matthew Kobs Date: Wed, 27 Jan 2016 10:46:49 -0600 Subject: [PATCH 16/17] [skip] Added tests for scaffolded elements (40m) --- spec/elements/drawing_spec.rb | 3 ++ spec/elements/drawingml/picture_spec.rb | 2 ++ spec/elements/table_spec.rb | 1 + .../word_processing_shapes_shape_spec.rb | 2 ++ .../elements/scaffolded_drawing_element.xml | 18 +++++++++++ .../elements/scaffolded_picture_element.xml | 31 +++++++++++++++++++ .../elements/scaffolded_table_element.xml | 10 ++++++ ...d_word_processing_shapes_shape_element.xml | 24 ++++++++++++++ spec/support/element_test_macros.rb | 22 +++++++++++++ 9 files changed, 113 insertions(+) create mode 100644 spec/support/data/elements/scaffolded_drawing_element.xml create mode 100644 spec/support/data/elements/scaffolded_picture_element.xml create mode 100644 spec/support/data/elements/scaffolded_table_element.xml create mode 100644 spec/support/data/elements/scaffolded_word_processing_shapes_shape_element.xml diff --git a/spec/elements/drawing_spec.rb b/spec/elements/drawing_spec.rb index 5a284e59..9f01d982 100644 --- a/spec/elements/drawing_spec.rb +++ b/spec/elements/drawing_spec.rb @@ -8,4 +8,7 @@ with_no_attributes_set do it_should_output "", assign: false end + + it_should_scaffold_itself_correctly + end diff --git a/spec/elements/drawingml/picture_spec.rb b/spec/elements/drawingml/picture_spec.rb index 1621c093..58997a15 100644 --- a/spec/elements/drawingml/picture_spec.rb +++ b/spec/elements/drawingml/picture_spec.rb @@ -5,4 +5,6 @@ it_should_use tag: :pic, name: "picture" + it_should_scaffold_itself_correctly(image_rid: "rId5") + end diff --git a/spec/elements/table_spec.rb b/spec/elements/table_spec.rb index c30bc163..9cd8545e 100644 --- a/spec/elements/table_spec.rb +++ b/spec/elements/table_spec.rb @@ -17,5 +17,6 @@ end it_should_output_correct_xml + it_should_scaffold_itself_correctly end diff --git a/spec/elements/word_processing_shapes_shape_spec.rb b/spec/elements/word_processing_shapes_shape_spec.rb index d1180668..3683d930 100644 --- a/spec/elements/word_processing_shapes_shape_spec.rb +++ b/spec/elements/word_processing_shapes_shape_spec.rb @@ -20,4 +20,6 @@ end end + it_should_scaffold_itself_correctly + end diff --git a/spec/support/data/elements/scaffolded_drawing_element.xml b/spec/support/data/elements/scaffolded_drawing_element.xml new file mode 100644 index 00000000..91c37311 --- /dev/null +++ b/spec/support/data/elements/scaffolded_drawing_element.xml @@ -0,0 +1,18 @@ + + + + + + + 0 + + + 0 + + + + + + + + diff --git a/spec/support/data/elements/scaffolded_picture_element.xml b/spec/support/data/elements/scaffolded_picture_element.xml new file mode 100644 index 00000000..8ea2ca60 --- /dev/null +++ b/spec/support/data/elements/scaffolded_picture_element.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spec/support/data/elements/scaffolded_table_element.xml b/spec/support/data/elements/scaffolded_table_element.xml new file mode 100644 index 00000000..072207eb --- /dev/null +++ b/spec/support/data/elements/scaffolded_table_element.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/spec/support/data/elements/scaffolded_word_processing_shapes_shape_element.xml b/spec/support/data/elements/scaffolded_word_processing_shapes_shape_element.xml new file mode 100644 index 00000000..b5fbaf73 --- /dev/null +++ b/spec/support/data/elements/scaffolded_word_processing_shapes_shape_element.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spec/support/element_test_macros.rb b/spec/support/element_test_macros.rb index 17134125..be6f2175 100644 --- a/spec/support/element_test_macros.rb +++ b/spec/support/element_test_macros.rb @@ -65,6 +65,28 @@ def it_should_output_correct_xml(node_xml: nil) end end + def it_should_scaffold_itself_correctly(options={}) + it "should correctly scaffold itself and its children" do + node_xml = options[:node_xml] + if node_xml.nil? + node_xml = described_class.to_s.split(/::/).last + node_xml = node_xml.gsub(/(.)([A-Z])/, '\1_\2').downcase + end + node_xml = "scaffolded_#{node_xml}" + + options.merge!({scaffold: true}) + @instance = described_class.new(options) + + generated_xml = OpenXml::Builder.new do |xml| + xml.root("xmlns:w" => "http://wnamespace.org") { + instance.to_xml(xml) + } + end.to_xml + + expect(generated_xml).to eq(element_xml(node_xml) + "\n") + end + end + def it_should_use(tag: nil, name: nil, value: nil) context "always" do before(:each) do From 04f22b6884cf6c96beffb4d721d559ecee718937 Mon Sep 17 00:00:00 2001 From: Matthew Kobs Date: Mon, 1 Feb 2016 09:23:02 -0600 Subject: [PATCH 17/17] [skip] Changed example output filename (1m) --- examples/dsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/dsl b/examples/dsl index 825495e6..562b8245 100755 --- a/examples/dsl +++ b/examples/dsl @@ -100,7 +100,7 @@ def build_docx docx.styles << build_table_style docx.styles << build_cell_text_style - filename = "rocx_test_table.docx" + filename = "docx_test_dsl.docx" system "rm -f ~/Desktop/#{filename}" # -f so that we don't have an error if the file doesn't exist docx.save File.expand_path("~/Desktop/#{filename}") exec "open ~/Desktop/#{filename}"