goldendocx 0.2.2 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +4 -0
  3. data/CHANGELOG.md +8 -2
  4. data/Gemfile.lock +3 -1
  5. data/README.md +10 -2
  6. data/Rakefile +14 -3
  7. data/demo/templates/generate_codes.rb +10 -0
  8. data/demo/templates/xml_to_class.rb +91 -0
  9. data/demo/texts/append_plain_text.rb +1 -1
  10. data/demo/texts/append_styled_text.rb +1 -2
  11. data/demo/texts/create_text.rb +14 -0
  12. data/lib/extensions/active_support_extensions.rb +16 -0
  13. data/lib/extensions/nokogiri_extensions.rb +41 -0
  14. data/lib/extensions/ox_extensions.rb +35 -0
  15. data/lib/extensions/xml_serialize_extensions.rb +45 -0
  16. data/lib/goldendocx/components/properties/font_property.rb +19 -0
  17. data/lib/goldendocx/components/properties/language_property.rb +18 -0
  18. data/lib/goldendocx/components/properties/run_property.rb +2 -0
  19. data/lib/goldendocx/content_types/default.rb +2 -6
  20. data/lib/goldendocx/content_types/override.rb +2 -6
  21. data/lib/goldendocx/document.rb +9 -28
  22. data/lib/goldendocx/documents/body.rb +20 -11
  23. data/lib/goldendocx/documents/document.rb +2 -4
  24. data/lib/goldendocx/documents/latent_styles.rb +12 -0
  25. data/lib/goldendocx/documents/properties/default_style_property.rb +17 -0
  26. data/lib/goldendocx/documents/properties/page_margin_property.rb +37 -0
  27. data/lib/goldendocx/documents/properties/page_size_property.rb +17 -0
  28. data/lib/goldendocx/documents/properties/paragraph_default_style_property.rb +16 -0
  29. data/lib/goldendocx/documents/properties/run_default_style_property.rb +22 -0
  30. data/lib/goldendocx/documents/properties/section_property.rb +17 -0
  31. data/lib/goldendocx/documents/properties/style_name_property.rb +16 -0
  32. data/lib/goldendocx/documents/properties.rb +12 -0
  33. data/lib/goldendocx/documents/settings.rb +23 -0
  34. data/lib/goldendocx/documents/style.rb +10 -10
  35. data/lib/goldendocx/documents/styles.rb +9 -33
  36. data/lib/goldendocx/docx.rb +55 -12
  37. data/lib/goldendocx/element.rb +33 -140
  38. data/lib/goldendocx/has_associations.rb +52 -0
  39. data/lib/goldendocx/has_attributes.rb +67 -0
  40. data/lib/goldendocx/has_children.rb +116 -0
  41. data/lib/goldendocx/{documents → models}/relationship.rb +1 -1
  42. data/lib/goldendocx/{documents → models}/relationships.rb +4 -12
  43. data/lib/goldendocx/models.rb +10 -0
  44. data/lib/goldendocx/parts/app.rb +46 -0
  45. data/lib/goldendocx/parts/content_types.rb +16 -30
  46. data/lib/goldendocx/parts/core.rb +46 -0
  47. data/lib/goldendocx/parts/documents.rb +26 -13
  48. data/lib/goldendocx/parts/properties/created_at_property.rb +17 -0
  49. data/lib/goldendocx/parts/properties/creator_property.rb +16 -0
  50. data/lib/goldendocx/parts/properties/revision_property.rb +16 -0
  51. data/lib/goldendocx/parts/properties/updated_at_property.rb +17 -0
  52. data/lib/goldendocx/parts/properties/updater_property.rb +16 -0
  53. data/lib/goldendocx/parts/properties.rb +12 -0
  54. data/lib/goldendocx/tables/row.rb +1 -1
  55. data/lib/goldendocx/version.rb +1 -1
  56. data/lib/goldendocx/xml_serializers/nokogiri.rb +30 -22
  57. data/lib/goldendocx/xml_serializers/ox.rb +10 -20
  58. data/lib/goldendocx.rb +14 -2
  59. metadata +51 -7
  60. data/lib/goldendocx/documents/element.rb +0 -23
  61. data/lib/goldendocx/documents/unparsed_style.rb +0 -17
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Goldendocx
4
+ module HasAttributes
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ class_attribute :attributes, instance_accessor: false, default: {}
9
+
10
+ def unparsed_attributes
11
+ @unparsed_attributes ||= {}
12
+ end
13
+ end
14
+
15
+ class_methods do
16
+ # alias_name: nil
17
+ # readonly: false
18
+ # default: nil
19
+ # namespace: nil
20
+ # setter: nil
21
+ def attribute(name, **options)
22
+ named = name.to_s
23
+ attributes[named] = {
24
+ alias_name: options[:alias_name],
25
+ default: options[:default],
26
+ namespace: options[:namespace],
27
+ method: options[:method]
28
+ }.compact
29
+
30
+ readonly = options[:readonly] || false
31
+ if readonly
32
+ attr_reader named
33
+ elsif options[:method]
34
+ attr_writer named
35
+ else
36
+ attr_accessor named
37
+ end
38
+ end
39
+ end
40
+
41
+ def attributes
42
+ self.class.attributes.each_with_object({}) do |(name, options), result|
43
+ value = public_send(options[:method] || name) || options[:default]
44
+ next if value.nil?
45
+
46
+ key = [options[:namespace], options[:alias_name] || name].compact.join(':')
47
+ result[key] = value
48
+ end
49
+ end
50
+
51
+ def read_attributes(node)
52
+ node_attributes = node.attributes_hash
53
+
54
+ attributes = self.class.attributes.each_with_object({}) do |(name, options), result|
55
+ attribute_tag = [options[:namespace], (options[:alias_name] || name)].compact.join(':')
56
+ result[name] = node_attributes.delete(attribute_tag)
57
+ end
58
+ assign_attributes(**attributes)
59
+
60
+ unparsed_attributes.update(node_attributes)
61
+ end
62
+
63
+ def assign_attributes(**attributes)
64
+ attributes.each { |key, value| send("#{key}=", value) if respond_to?("#{key}=") }
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,116 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'goldendocx/has_attributes'
4
+
5
+ module Goldendocx
6
+ module HasChildren
7
+ extend ActiveSupport::Concern
8
+
9
+ included do
10
+ class_attribute :children, instance_accessor: false, default: {}
11
+
12
+ def unparsed_children
13
+ @unparsed_children ||= []
14
+ end
15
+ end
16
+
17
+ module ClassMethods
18
+ def embeds_one(name, class_name:, auto_build: false)
19
+ warning_naming_suggestion(__method__, name, name.to_s.singularize)
20
+
21
+ options = { class_name: class_name, multiple: false, auto_build: auto_build }
22
+ self.children = children.merge(name => options)
23
+
24
+ create_children_getter(name)
25
+ create_children_setter(name)
26
+ create_children_builder(name)
27
+ end
28
+
29
+ def embeds_many(name, class_name:, uniqueness: false)
30
+ warning_naming_suggestion(__method__, name, name.to_s.pluralize)
31
+
32
+ options = { class_name: class_name, multiple: true, uniqueness: uniqueness }
33
+ self.children = children.merge(name => options)
34
+
35
+ create_children_getter(name)
36
+ create_children_setter(name)
37
+ create_children_builder(name)
38
+ end
39
+
40
+ def default_value(name)
41
+ options = children[name]
42
+ return [] if options[:multiple]
43
+
44
+ options[:class_name].constantize.new if options[:auto_build]
45
+ end
46
+
47
+ private
48
+
49
+ def create_children_getter(name)
50
+ define_method name do
51
+ return instance_variable_get("@#{name}") if instance_variable_defined?("@#{name}")
52
+
53
+ instance_variable_set("@#{name}", self.class.default_value(name))
54
+ end
55
+ end
56
+
57
+ def create_children_setter(name)
58
+ define_method("#{name}=") { |value| instance_variable_set("@#{name}", value) }
59
+ end
60
+
61
+ def create_children_appender(name)
62
+ options = children[name]
63
+
64
+ define_method "append_#{name.to_s.singularize}" do |child|
65
+ return instance_variable_set("@#{name}", child) unless options[:multiple]
66
+
67
+ children = send(name)
68
+ children << child unless options[:uniqueness] && children.any?(child)
69
+ child
70
+ end
71
+ end
72
+
73
+ def create_children_builder(name)
74
+ options = children[name]
75
+ create_children_appender(name)
76
+
77
+ define_method "build_#{name.to_s.singularize}" do |**attributes|
78
+ child = options[:class_name].constantize.new
79
+ attributes.each { |key, value| child.send("#{key}=", value) if child.respond_to?("#{key}=") }
80
+ send("append_#{name.to_s.singularize}", child)
81
+ end
82
+ end
83
+
84
+ # :nocov:
85
+ def warning_naming_suggestion(method, name, suggestion_name)
86
+ return if suggestion_name == name.to_s
87
+
88
+ location = caller.find { |c| c.include?('goldendocx/') && !c.include?('goldendocx/element.rb') }
89
+ warn "warning: [#{method}] `#{name}` better be `#{suggestion_name}` at #{location}"
90
+ end
91
+ # :nocov:
92
+ end
93
+
94
+ def children
95
+ self.class.children.keys.flat_map { |name| send(name) }.compact
96
+ end
97
+
98
+ def read_children(xml_node)
99
+ xml_node.children.each do |child_node|
100
+ read_child(child_node)
101
+ end
102
+ end
103
+
104
+ def read_child(child_node)
105
+ name, options = self.class.children.find do |_, opts|
106
+ opts[:class_name].constantize.adapt?(child_node)
107
+ end
108
+ if name.present?
109
+ child = options[:class_name].constantize.read_from(child_node)
110
+ send("append_#{name.to_s.singularize}", child)
111
+ else
112
+ unparsed_children << child_node
113
+ end
114
+ end
115
+ end
116
+ end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Goldendocx
4
- module Documents
4
+ module Models
5
5
  class Relationship
6
6
  include Goldendocx::Element
7
7
 
@@ -1,31 +1,23 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Goldendocx
4
- module Documents
4
+ module Models
5
5
  class Relationships
6
6
  include Goldendocx::Document
7
7
 
8
- XML_PATH = 'word/_rels/document.xml.rels'
9
8
  NAMESPACE = 'http://schemas.openxmlformats.org/package/2006/relationships'
10
9
 
11
10
  tag :Relationships
12
11
  attribute :xmlns, default: NAMESPACE, readonly: true
13
12
 
14
- embeds_many :relationships, class_name: 'Goldendocx::Documents::Relationship'
13
+ embeds_many :relationships, class_name: 'Goldendocx::Models::Relationship'
15
14
 
16
15
  def size
17
16
  relationships.size
18
17
  end
19
18
 
20
- def read_from(docx_file)
21
- paths = %w[Relationships Relationship]
22
- Goldendocx.xml_serializer.parse(docx_file.read(XML_PATH), paths).map do |node|
23
- build_relationship(id: node[:Id], type: node[:Type], target: node[:Target])
24
- end
25
- end
26
-
27
- def write_to(zos)
28
- zos.put_next_entry XML_PATH
19
+ def write_to(zos, xml_path)
20
+ zos.put_next_entry xml_path
29
21
  zos.write to_document_xml
30
22
  end
31
23
 
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Goldendocx
4
+ module Models
5
+ end
6
+ end
7
+
8
+ Dir.glob(File.join(File.dirname(__FILE__), 'models', '*.rb').to_s).sort.each do |file|
9
+ require file
10
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Goldendocx
4
+ module Parts
5
+ class App
6
+ include Goldendocx::Document
7
+
8
+ TYPE = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties'
9
+ XML_PATH = 'docProps/app.xml'
10
+ NAMESPACE = 'http://schemas.openxmlformats.org/officeDocument/2006/extended-properties'
11
+ CONTENT_TYPE = 'application/vnd.openxmlformats-officedocument.extended-properties+xml'
12
+
13
+ tag :Properties
14
+ attribute :xmlns, default: NAMESPACE, readonly: true
15
+
16
+ class << self
17
+ def read_from(app_document)
18
+ new_instance = new
19
+
20
+ app_document.children.map do |node|
21
+ new_instance.properties[node.name.to_sym] = node.text
22
+ end
23
+
24
+ new_instance
25
+ end
26
+ end
27
+
28
+ def write_to(zos)
29
+ zos.put_next_entry XML_PATH
30
+ zos.write to_document_xml
31
+ end
32
+
33
+ def to_document_xml
34
+ super do |xml|
35
+ properties.each do |name, value|
36
+ xml << Goldendocx.xml_serializer.build_element(name).tap { |app| app << value }
37
+ end
38
+ end
39
+ end
40
+
41
+ def properties
42
+ @properties ||= { Application: "Goldendocx_#{Goldendocx::VERSION}" }
43
+ end
44
+ end
45
+ end
46
+ end
@@ -11,52 +11,38 @@ module Goldendocx
11
11
  XML_PATH = '[Content_Types].xml'
12
12
  NAMESPACE = 'http://schemas.openxmlformats.org/package/2006/content-types'
13
13
 
14
- attr_reader :defaults, :overrides
14
+ REQUIRED_DEFAULTS = {
15
+ rels: 'application/vnd.openxmlformats-package.relationships+xml',
16
+ xml: 'application/xml'
17
+ }.with_indifferent_access.freeze
15
18
 
16
19
  tag :Types
17
20
  attribute :xmlns, default: NAMESPACE, readonly: true
18
21
 
19
- class << self
20
- def read_from(docx_file)
21
- content_types = Goldendocx::Parts::ContentTypes.new
22
- content_types.read_defaults(docx_file)
23
- content_types.read_overrides(docx_file)
24
- content_types
25
- end
26
- end
22
+ embeds_many :defaults, class_name: 'Goldendocx::ContentTypes::Default', uniqueness: true
23
+ embeds_many :overrides, class_name: 'Goldendocx::ContentTypes::Override', uniqueness: true
27
24
 
28
25
  def initialize
29
- @defaults = []
30
- @overrides = []
31
- end
32
-
33
- def read_defaults(docx_file)
34
- @defaults = Goldendocx.xml_serializer.parse(docx_file.read(XML_PATH), %w[Types Default]).map do |node|
35
- Goldendocx::ContentTypes::Default.new(node[:Extension], node[:ContentType])
26
+ REQUIRED_DEFAULTS.map do |extension, content_type|
27
+ build_defaults(extension: extension, content_type: content_type)
36
28
  end
37
29
  end
38
30
 
39
- def read_overrides(docx_file)
40
- @overrides = Goldendocx.xml_serializer.parse(docx_file.read(XML_PATH), %w[Types Override]).map do |node|
41
- Goldendocx::ContentTypes::Override.new(node[:PartName], node[:ContentType])
42
- end
31
+ def write_to(zos)
32
+ zos.put_next_entry XML_PATH
33
+ zos.write to_document_xml
43
34
  end
44
35
 
45
36
  def add_default(extension, content_type)
46
- new_default = Goldendocx::ContentTypes::Default.new(extension, content_type)
47
- defaults << new_default if defaults.none?(new_default)
37
+ return if defaults.any? { |default| extension == default.extension && content_type == default.content_type }
38
+
39
+ build_defaults(extension: extension, content_type: content_type)
48
40
  end
49
41
 
50
42
  def add_override(part_name, content_type)
51
- new_override = Goldendocx::ContentTypes::Override.new(part_name, content_type)
52
- overrides << new_override if overrides.none?(new_override)
53
- end
43
+ return if overrides.any? { |override| part_name == override.part_name && content_type == override.content_type }
54
44
 
55
- def to_document_xml
56
- super do |xml|
57
- defaults.each { |default| xml << default }
58
- overrides.each { |override| xml << override }
59
- end
45
+ build_override(part_name: part_name, content_type: content_type)
60
46
  end
61
47
  end
62
48
  end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Goldendocx
4
+ module Parts
5
+ class Core
6
+ include Goldendocx::Document
7
+
8
+ TYPE = 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties'
9
+ XML_PATH = 'docProps/core.xml'
10
+ NAMESPACE = 'http://schemas.openxmlformats.org/officeDocument/2006/extended-properties'
11
+ CONTENT_TYPE = 'application/vnd.openxmlformats-package.core-properties+xml'
12
+
13
+ concern_namespaces :cp, :dc, :dcterms, :dcmitype, :xsi
14
+
15
+ namespace :cp
16
+ tag :coreProperties
17
+
18
+ embeds_one :creator, class_name: 'Goldendocx::Parts::Properties::CreatorProperty'
19
+ embeds_one :created_at, class_name: 'Goldendocx::Parts::Properties::CreatedAtProperty'
20
+ embeds_one :revision, class_name: 'Goldendocx::Parts::Properties::RevisionProperty'
21
+ embeds_one :updater, class_name: 'Goldendocx::Parts::Properties::UpdaterProperty'
22
+ embeds_one :updated_at, class_name: 'Goldendocx::Parts::Properties::UpdatedAtProperty'
23
+
24
+ class << self
25
+ def read_from(xml_node)
26
+ core = super(xml_node)
27
+ revision = (core.revision || core.build_revision)
28
+ revision.value = revision.value.to_i + 1
29
+ core.build_updater(name: "Goldendocx_#{Goldendocx::VERSION}")
30
+ core.build_updated_at(timestamp: Time.now)
31
+ core
32
+ end
33
+ end
34
+
35
+ def initialize
36
+ build_creator(name: "Goldendocx_#{Goldendocx::VERSION}")
37
+ build_created_at(timestamp: Time.now)
38
+ end
39
+
40
+ def write_to(zos)
41
+ zos.put_next_entry XML_PATH
42
+ zos.write to_document_xml
43
+ end
44
+ end
45
+ end
46
+ end
@@ -4,37 +4,50 @@
4
4
  module Goldendocx
5
5
  module Parts
6
6
  class Documents
7
+ include Goldendocx::HasAssociations
8
+
7
9
  XML_PATH = 'word/'
10
+ RELATIONSHIPS_XML_PATH = 'word/_rels/document.xml.rels'
8
11
 
9
12
  attr_reader :document, # document.xml
10
- :styles, # styles.xml
11
- :relationships, # _rels/document.xml.rels
12
13
  :charts, # charts/
13
14
  :medias # New Medias to media/
14
15
 
15
16
  attr_accessor :media_amount # Entries amount in directory media/ for generating relationship id
16
17
 
18
+ relationships_at RELATIONSHIPS_XML_PATH
19
+ associate :styles, class_name: 'Goldendocx::Documents::Styles'
20
+ associate :settings, class_name: 'Goldendocx::Documents::Settings'
21
+ associate :document, class_name: 'Goldendocx::Documents::Document', isolate: true
22
+
17
23
  class << self
18
24
  def read_from(docx_file)
19
25
  parts = Goldendocx::Parts::Documents.new
20
- parts.document.read_from(docx_file)
21
- parts.styles.read_from(docx_file)
22
- parts.relationships.read_from(docx_file)
26
+ parts.read_relationships(docx_file)
27
+ parts.read_associations(docx_file)
23
28
  parts.media_amount = docx_file.entries.count { |entry| entry.name.start_with?('word/media/') }
24
29
  parts
25
30
  end
26
31
  end
27
32
 
28
33
  def initialize
29
- @document = Goldendocx::Documents::Document.new
30
- @styles = Goldendocx::Documents::Styles.new
31
- @relationships = Goldendocx::Documents::Relationships.new
34
+ associations.each do |association, options|
35
+ association_class = options[:class_name].constantize
36
+ instance_variable_set("@#{association}", association_class.new)
37
+ add_relationship association_class::TYPE, association_class::XML_PATH.gsub(XML_PATH, '') unless options[:isolate]
38
+ end
39
+
32
40
  @medias = []
41
+ @media_amount = 0
33
42
  end
34
43
 
35
44
  def write_stream(zos)
36
- styles.write_to(zos)
37
- relationships.write_to(zos)
45
+ write_relationships(zos)
46
+
47
+ associations.each_key do |association|
48
+ send(association).write_to(zos)
49
+ end
50
+
38
51
  document.write_to(zos)
39
52
  medias.each { |media| media.write_to(zos) }
40
53
  document.body.charts.each { |chart| chart.write_to(zos) }
@@ -60,14 +73,14 @@ module Goldendocx
60
73
 
61
74
  def create_image(image_data, options = {})
62
75
  image_media = add_image_media(image_data, options)
63
- relationship_id = relationships.add_relationship(image_media.type, image_media.target)
76
+ relationship_id = add_relationship(image_media.type, image_media.target)
64
77
 
65
78
  document.body.create_image(relationship_id, options)
66
79
  end
67
80
 
68
81
  def create_embed_image(image_data, options = {})
69
82
  image_media = add_image_media(image_data, options)
70
- relationship_id = relationships.add_relationship(image_media.type, image_media.target)
83
+ relationship_id = add_relationship(image_media.type, image_media.target)
71
84
 
72
85
  document.body.create_embed_image(relationship_id, options)
73
86
  end
@@ -87,7 +100,7 @@ module Goldendocx
87
100
 
88
101
  chart_id = document.body.charts.size + 1
89
102
 
90
- relationship_id = relationships.add_relationship(
103
+ relationship_id = add_relationship(
91
104
  Goldendocx::Charts::RELATIONSHIP_TYPE,
92
105
  format(Goldendocx::Charts::RELATIONSHIP_NAME_PATTERN, id: chart_id)
93
106
  )
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Goldendocx
4
+ module Parts
5
+ module Properties
6
+ class CreatedAtProperty
7
+ include Goldendocx::Element
8
+
9
+ namespace :dcterms
10
+ tag :created
11
+
12
+ attribute :type, namespace: :xsi, default: 'dcterms:W3CDTF'
13
+ embeds_one :timestamp, class_name: 'Time'
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Goldendocx
4
+ module Parts
5
+ module Properties
6
+ class CreatorProperty
7
+ include Goldendocx::Element
8
+
9
+ namespace :dc
10
+ tag :creator
11
+
12
+ embeds_one :name, class_name: 'String'
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Goldendocx
4
+ module Parts
5
+ module Properties
6
+ class RevisionProperty
7
+ include Goldendocx::Element
8
+
9
+ namespace :cp
10
+ tag :revision
11
+
12
+ embeds_one :value, class_name: 'Integer'
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Goldendocx
4
+ module Parts
5
+ module Properties
6
+ class UpdatedAtProperty
7
+ include Goldendocx::Element
8
+
9
+ namespace :dcterms
10
+ tag :modified
11
+
12
+ attribute :type, namespace: :xsi, default: 'dcterms:W3CDTF'
13
+ embeds_one :timestamp, class_name: 'Time'
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Goldendocx
4
+ module Parts
5
+ module Properties
6
+ class UpdaterProperty
7
+ include Goldendocx::Element
8
+
9
+ namespace :cp
10
+ tag :lastModifiedBy
11
+
12
+ embeds_one :name, class_name: 'String'
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Goldendocx
4
+ module Parts
5
+ module Properties
6
+ end
7
+ end
8
+ end
9
+
10
+ Dir.glob(File.join(File.dirname(__FILE__), 'properties', '*.rb').to_s).sort.each do |file|
11
+ require file
12
+ end
@@ -18,7 +18,7 @@ module Goldendocx
18
18
  def add_cell(data)
19
19
  cell = case data
20
20
  when Goldendocx::Tables::Cell then data
21
- when Hash then Goldendocx::Tables::Cell.new(data)
21
+ when Hash then Goldendocx::Tables::Cell.new(**data)
22
22
  else Goldendocx::Tables::Cell.new(content: data.to_s)
23
23
  end
24
24
  cells << cell
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Goldendocx
4
- VERSION = '0.2.2'
4
+ VERSION = '0.2.3'
5
5
  end