goldendocx 0.2.2 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
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