goldendocx 0.2.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -1
  3. data/.ruby-version +1 -0
  4. data/CHANGELOG.md +8 -2
  5. data/Gemfile.lock +3 -1
  6. data/README.md +10 -2
  7. data/Rakefile +14 -3
  8. data/demo/tables/create_embed_image_table.rb +3 -3
  9. data/demo/templates/generate_codes.rb +10 -0
  10. data/demo/templates/xml_to_class.rb +97 -0
  11. data/demo/texts/append_plain_text.rb +1 -1
  12. data/demo/texts/append_styled_text.rb +1 -2
  13. data/demo/texts/create_text.rb +14 -0
  14. data/lib/extensions/active_support_extensions.rb +16 -0
  15. data/lib/extensions/nokogiri_extensions.rb +41 -0
  16. data/lib/extensions/ox_extensions.rb +35 -0
  17. data/lib/extensions/xml_serialize_extensions.rb +45 -0
  18. data/lib/goldendocx/charts/properties.rb +1 -1
  19. data/lib/goldendocx/charts/series.rb +2 -2
  20. data/lib/goldendocx/charts.rb +1 -1
  21. data/lib/goldendocx/components/bar_chart.rb +2 -2
  22. data/lib/goldendocx/components/chart.rb +6 -6
  23. data/lib/goldendocx/components/column_chart.rb +2 -2
  24. data/lib/goldendocx/components/doughnut_chart.rb +2 -2
  25. data/lib/goldendocx/components/line_chart.rb +2 -2
  26. data/lib/goldendocx/components/properties/font_property.rb +19 -0
  27. data/lib/goldendocx/components/properties/language_property.rb +18 -0
  28. data/lib/goldendocx/components/properties/run_property.rb +2 -0
  29. data/lib/goldendocx/components/properties.rb +1 -1
  30. data/lib/goldendocx/components/table.rb +2 -2
  31. data/lib/goldendocx/components.rb +1 -1
  32. data/lib/goldendocx/content_types/default.rb +2 -6
  33. data/lib/goldendocx/content_types/override.rb +2 -6
  34. data/lib/goldendocx/document.rb +9 -28
  35. data/lib/goldendocx/documents/body.rb +23 -14
  36. data/lib/goldendocx/documents/document.rb +2 -4
  37. data/lib/goldendocx/documents/latent_styles.rb +12 -0
  38. data/lib/goldendocx/documents/properties/default_style_property.rb +17 -0
  39. data/lib/goldendocx/documents/properties/page_margin_property.rb +37 -0
  40. data/lib/goldendocx/documents/properties/page_size_property.rb +17 -0
  41. data/lib/goldendocx/documents/properties/paragraph_default_style_property.rb +16 -0
  42. data/lib/goldendocx/documents/properties/run_default_style_property.rb +22 -0
  43. data/lib/goldendocx/documents/properties/section_property.rb +17 -0
  44. data/lib/goldendocx/documents/properties/style_name_property.rb +16 -0
  45. data/lib/goldendocx/documents/properties.rb +12 -0
  46. data/lib/goldendocx/documents/settings.rb +23 -0
  47. data/lib/goldendocx/documents/style.rb +10 -10
  48. data/lib/goldendocx/documents/styles.rb +9 -33
  49. data/lib/goldendocx/documents.rb +1 -1
  50. data/lib/goldendocx/docx.rb +55 -12
  51. data/lib/goldendocx/element.rb +33 -140
  52. data/lib/goldendocx/has_associations.rb +54 -0
  53. data/lib/goldendocx/has_attributes.rb +67 -0
  54. data/lib/goldendocx/has_children.rb +116 -0
  55. data/lib/goldendocx/images/picture.rb +1 -1
  56. data/lib/goldendocx/images/properties.rb +1 -1
  57. data/lib/goldendocx/images.rb +1 -1
  58. data/lib/goldendocx/{documents → models}/relationship.rb +1 -1
  59. data/lib/goldendocx/models/relationships.rb +31 -0
  60. data/lib/goldendocx/models.rb +10 -0
  61. data/lib/goldendocx/parts/app.rb +46 -0
  62. data/lib/goldendocx/parts/content_types.rb +16 -30
  63. data/lib/goldendocx/parts/core.rb +46 -0
  64. data/lib/goldendocx/parts/documents.rb +27 -14
  65. data/lib/goldendocx/parts/media.rb +1 -1
  66. data/lib/goldendocx/parts/properties/created_at_property.rb +17 -0
  67. data/lib/goldendocx/parts/properties/creator_property.rb +16 -0
  68. data/lib/goldendocx/parts/properties/revision_property.rb +16 -0
  69. data/lib/goldendocx/parts/properties/updated_at_property.rb +17 -0
  70. data/lib/goldendocx/parts/properties/updater_property.rb +16 -0
  71. data/lib/goldendocx/parts/properties.rb +12 -0
  72. data/lib/goldendocx/parts.rb +1 -1
  73. data/lib/goldendocx/tables/header_cell.rb +1 -1
  74. data/lib/goldendocx/tables/properties.rb +1 -1
  75. data/lib/goldendocx/tables/row.rb +1 -1
  76. data/lib/goldendocx/tables.rb +1 -1
  77. data/lib/goldendocx/version.rb +1 -1
  78. data/lib/goldendocx/xml_serializers/nokogiri.rb +32 -24
  79. data/lib/goldendocx/xml_serializers/ox.rb +15 -25
  80. data/lib/goldendocx.rb +14 -2
  81. metadata +54 -9
  82. data/lib/goldendocx/documents/element.rb +0 -23
  83. data/lib/goldendocx/documents/relationships.rb +0 -39
  84. data/lib/goldendocx/documents/unparsed_style.rb +0 -17
@@ -6,13 +6,9 @@ module Goldendocx
6
6
  include Goldendocx::Element
7
7
 
8
8
  tag :Override
9
- attribute :part_name, alias_name: :PartName, readonly: true
10
- attribute :content_type, alias_name: :ContentType, readonly: true
11
9
 
12
- def initialize(part_name, content_type)
13
- @part_name = part_name
14
- @content_type = content_type
15
- end
10
+ attribute :part_name, alias_name: :PartName
11
+ attribute :content_type, alias_name: :ContentType
16
12
 
17
13
  def ==(other)
18
14
  part_name == other.part_name && content_type == other.content_type
@@ -3,49 +3,30 @@
3
3
  # Just to mark a element as a root document node
4
4
  module Goldendocx
5
5
  module Document
6
- def self.included(base)
7
- base.include(Goldendocx::Element)
8
- base.extend(ClassMethods)
6
+ extend ActiveSupport::Concern
7
+ include Goldendocx::Element
8
+
9
+ included do
10
+ class_attribute :concerned_namespaces, default: []
11
+ class_attribute :ignorable_namespaces, default: []
9
12
  end
10
13
 
11
- module ClassMethods
14
+ class_methods do
12
15
  def concern_namespaces(*namespaces)
13
16
  namespaces.each do |namespace|
14
17
  concerned_namespaces << namespace unless concerned_namespaces.include?(namespace)
15
18
  end
16
19
  end
17
20
 
18
- def concerned_namespaces
19
- @concerned_namespaces ||= []
20
- end
21
-
22
21
  def ignore_namespaces(*namespaces)
23
22
  namespaces.each do |namespace|
24
23
  ignorable_namespaces << namespace.to_sym unless ignorable_namespaces.include?(namespace)
25
24
  end
26
25
  end
27
-
28
- def ignorable_namespaces
29
- @ignorable_namespaces ||= []
30
- end
31
- end
32
-
33
- def concerned_namespaces
34
- self.class.concerning_ancestors.flat_map(&:concerned_namespaces)
35
- end
36
-
37
- def ignorable_namespaces
38
- self.class.concerning_ancestors.flat_map(&:ignorable_namespaces)
39
26
  end
40
27
 
41
- def to_document_xml
42
- Goldendocx.xml_serializer.build_document_xml(root_tag, concerned_namespaces, ignorable_namespaces) do |xml|
43
- attributes.each { |name, value| xml[name] = value }
44
-
45
- yield(xml) if block_given?
46
-
47
- children.each { |child| xml << child }
48
- end
28
+ def to_document_xml(&)
29
+ Goldendocx.xml_serializer.build_document_xml(tag_name, concerned_namespaces, ignorable_namespaces) { |xml| build_element(xml, &) }
49
30
  end
50
31
  end
51
32
  end
@@ -7,40 +7,49 @@ module Goldendocx
7
7
 
8
8
  XML_PATH = 'word/document.xml'
9
9
 
10
- attr_reader :components, :properties, :charts
10
+ attr_reader :components, :charts
11
11
 
12
12
  namespace :w
13
13
  tag :body
14
14
 
15
+ # TODO: Try to distinguish these paragraphs
15
16
  embeds_many :texts, class_name: 'Goldendocx::Components::Text'
16
17
  embeds_many :images, class_name: 'Goldendocx::Components::Image'
18
+
17
19
  embeds_many :tables, class_name: 'Goldendocx::Components::Table'
18
20
 
21
+ embeds_one :section_property, class_name: 'Goldendocx::Documents::Properties::SectionProperty', auto_build: true
22
+
23
+ class << self
24
+ def read_from(xml_node)
25
+ document = super(xml_node)
26
+
27
+ component_tags = %w[w:p w:tbl]
28
+ xml_node.children.map do |node|
29
+ document.components << node if component_tags.include?(node.tag_name)
30
+ end
31
+
32
+ document
33
+ end
34
+ end
35
+
19
36
  def initialize
20
37
  @components = []
21
38
  @charts = []
22
39
  end
23
40
 
24
- def read_from(docx_file)
25
- Goldendocx.xml_serializer.parse(docx_file.read(XML_PATH), %w[w:document w:body *]).map do |node|
26
- element = Goldendocx::Documents::Element.new(node)
27
- @components << element if element.component?
28
- @properties = element if element.properties?
29
- end
30
- end
31
-
32
41
  # FIXME: Override for children not in correctly order
33
42
  def to_element(**_context)
34
- Goldendocx.xml_serializer.build_element(root_tag) do |xml|
43
+ Goldendocx.xml_serializer.build_element(tag_name) do |xml|
35
44
  components.each { |component| xml << component }
36
- xml << properties if properties
45
+ xml << section_property if section_property
37
46
 
38
47
  yield(xml) if block_given?
39
48
  end
40
49
  end
41
50
 
42
51
  def create_text(text, options = {})
43
- text = build_text(text: text, **options.slice(:align, :color, :bold))
52
+ text = build_text(text:, **options.slice(:align, :color, :bold))
44
53
 
45
54
  components << text
46
55
 
@@ -57,7 +66,7 @@ module Goldendocx
57
66
  end
58
67
 
59
68
  def create_image(relationship_id, options)
60
- image = build_image(relationship_id: relationship_id, width: options[:width], height: options[:height])
69
+ image = build_image(relationship_id:, width: options[:width], height: options[:height])
61
70
 
62
71
  components << image
63
72
 
@@ -65,7 +74,7 @@ module Goldendocx
65
74
  end
66
75
 
67
76
  def create_embed_image(relationship_id, options)
68
- Goldendocx::Components::Image.new(relationship_id: relationship_id, width: options[:width], height: options[:height])
77
+ Goldendocx::Components::Image.new(relationship_id:, width: options[:width], height: options[:height])
69
78
  end
70
79
 
71
80
  def ensure_chart_type(chart_type)
@@ -5,7 +5,9 @@ module Goldendocx
5
5
  class Document
6
6
  include Goldendocx::Document
7
7
 
8
+ TYPE = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument'
8
9
  XML_PATH = 'word/document.xml'
10
+ CONTENT_TYPE = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml'
9
11
 
10
12
  namespace :w
11
13
  tag :document
@@ -16,10 +18,6 @@ module Goldendocx
16
18
 
17
19
  embeds_one :body, class_name: 'Goldendocx::Documents::Body', auto_build: true
18
20
 
19
- def read_from(docx_file)
20
- body.read_from(docx_file)
21
- end
22
-
23
21
  def write_to(zos)
24
22
  zos.put_next_entry XML_PATH
25
23
  zos.write to_document_xml
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Goldendocx
4
+ module Documents
5
+ class LatentStyles
6
+ include Goldendocx::Element
7
+
8
+ namespace :w
9
+ tag :latentStyles
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Goldendocx
4
+ module Documents
5
+ module Properties
6
+ class DefaultStyleProperty
7
+ include Goldendocx::Element
8
+
9
+ namespace :w
10
+ tag :docDefaults
11
+
12
+ embeds_one :run_default, class_name: 'Goldendocx::Documents::Properties::RunDefaultStyleProperty', auto_build: true
13
+ embeds_one :paragraph_default, class_name: 'Goldendocx::Documents::Properties::ParagraphDefaultStyleProperty', auto_build: true
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Goldendocx
4
+ module Documents
5
+ module Properties
6
+ class PageMarginProperty
7
+ include Goldendocx::Element
8
+
9
+ namespace :w
10
+ tag :pgMar
11
+
12
+ attribute :top, namespace: :w, default: 1440
13
+ attribute :bottom, namespace: :w, default: 1440
14
+ attribute :left, namespace: :w, default: 1800
15
+ attribute :right, namespace: :w, default: 1800
16
+ attribute :header, namespace: :w, default: 851
17
+ attribute :footer, namespace: :w, default: 992
18
+ attribute :gutter, namespace: :w, default: 0
19
+
20
+ # Follow html margin style setting
21
+ def margin=(*args)
22
+ args = Array(*args)
23
+ raise StandardError("wrong number of arguments (given #{args.length}, expected 1..4)") unless (1..4).cover?(args.length)
24
+
25
+ margins =
26
+ case args.length
27
+ when 1 then [args.first] * 4
28
+ when 2 then [args.first, args.last, args.first, args.last]
29
+ when 3 then [args.first, args.second, args.last, args.second]
30
+ else args
31
+ end
32
+ assign_attributes(**%i[top right bottom left].zip(margins).to_h)
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Goldendocx
4
+ module Documents
5
+ module Properties
6
+ class PageSizeProperty
7
+ include Goldendocx::Element
8
+
9
+ namespace :w
10
+ tag :pgSz
11
+
12
+ attribute :width, alias_name: :w, namespace: :w, default: 11906
13
+ attribute :height, alias_name: :h, namespace: :w, default: 16838
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Goldendocx
4
+ module Documents
5
+ module Properties
6
+ class ParagraphDefaultStyleProperty
7
+ include Goldendocx::Element
8
+
9
+ namespace :w
10
+ tag :pPrDefault
11
+
12
+ embeds_one :property, class_name: 'Goldendocx::Components::Properties::Property'
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Goldendocx
4
+ module Documents
5
+ module Properties
6
+ class RunDefaultStyleProperty
7
+ include Goldendocx::Element
8
+
9
+ namespace :w
10
+ tag :rPrDefault
11
+
12
+ embeds_one :property, class_name: 'Goldendocx::Components::Properties::RunProperty'
13
+
14
+ def initialize
15
+ build_property
16
+ property.build_language
17
+ property.build_font
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Goldendocx
4
+ module Documents
5
+ module Properties
6
+ class SectionProperty
7
+ include Goldendocx::Element
8
+
9
+ namespace :w
10
+ tag :sectPr
11
+
12
+ embeds_one :size, class_name: 'Goldendocx::Documents::Properties::PageSizeProperty', auto_build: true
13
+ embeds_one :margin, class_name: 'Goldendocx::Documents::Properties::PageMarginProperty', auto_build: true
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Goldendocx
4
+ module Documents
5
+ module Properties
6
+ class StyleNameProperty
7
+ include Goldendocx::Element
8
+
9
+ namespace :w
10
+ tag :name
11
+
12
+ attribute :name, alias_name: :val, namespace: :w
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Goldendocx
4
+ module Documents
5
+ module Properties
6
+ end
7
+ end
8
+ end
9
+
10
+ Dir.glob(File.join(File.dirname(__FILE__), 'properties', '*.rb').to_s).each do |file|
11
+ require file
12
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Goldendocx
4
+ module Documents
5
+ class Settings
6
+ include Goldendocx::Document
7
+
8
+ XML_PATH = 'word/settings.xml'
9
+ TYPE = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings'
10
+ CONTENT_TYPE = 'application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml'
11
+
12
+ namespace :w
13
+ tag :settings
14
+ concern_namespaces :mc, :o, :r, :m, :v, :w10, :w, :w14, :w15, :w16cid, :w16se, :sl
15
+ ignore_namespaces :w14, :w15, :w16se, :w16cid
16
+
17
+ def write_to(zos)
18
+ zos.put_next_entry XML_PATH
19
+ zos.write to_document_xml
20
+ end
21
+ end
22
+ end
23
+ end
@@ -3,18 +3,18 @@
3
3
  module Goldendocx
4
4
  module Documents
5
5
  class Style
6
- attr_reader :node, :id, :type, :name
6
+ include Goldendocx::Element
7
7
 
8
- def initialize(node)
9
- @node = node
10
- @id = node['w:styleId']
11
- @type = node['w:type']
12
- @name = node.public_send(:'w:name')['w:val']
13
- @default = node['w:default']
14
- end
8
+ namespace :w
9
+ tag :style
10
+
11
+ attribute :id, alias_name: :styleId, namespace: :w
12
+ attribute :type, namespace: :w
13
+
14
+ embeds_one :style_name, class_name: 'Goldendocx::Documents::Properties::StyleNameProperty', auto_build: true
15
15
 
16
- def to_element(**_context)
17
- @node
16
+ def name
17
+ style_name.name
18
18
  end
19
19
  end
20
20
  end
@@ -6,42 +6,22 @@ module Goldendocx
6
6
  include Goldendocx::Document
7
7
 
8
8
  XML_PATH = 'word/styles.xml'
9
+ TYPE = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles'
10
+ CONTENT_TYPE = 'application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml'
9
11
 
10
12
  tag :styles
11
13
  namespace :w
12
14
  concern_namespaces :mc, :r, :w, :w14, :w15
13
15
  ignore_namespaces :w14, :w15
14
16
 
15
- attr_reader :styles, :doc_defaults, :latent_styles
16
-
17
- def initialize
18
- @styles = []
19
- end
17
+ embeds_one :defaults, class_name: 'Goldendocx::Documents::Properties::DefaultStyleProperty', auto_build: true
18
+ embeds_one :latentStyles, class_name: 'Goldendocx::Documents::LatentStyles'
19
+ embeds_many :styles, class_name: 'Goldendocx::Documents::Style'
20
20
 
21
21
  def size
22
22
  styles.size
23
23
  end
24
24
 
25
- def read_from(docx_file)
26
- @styles = Goldendocx.xml_serializer.parse(docx_file.read(XML_PATH), %w[w:styles w:style]).map do |node|
27
- Goldendocx::Documents::Style.new(node)
28
- end
29
- @doc_defaults = Goldendocx.xml_serializer.parse(docx_file.read(XML_PATH), %w[w:styles w:docDefaults]).map do |node|
30
- Goldendocx::Documents::UnparsedStyle.new(node)
31
- end
32
- @latent_styles = Goldendocx.xml_serializer.parse(docx_file.read(XML_PATH), %w[w:styles w:latentStyles]).map do |node|
33
- Goldendocx::Documents::UnparsedStyle.new(node)
34
- end
35
- end
36
-
37
- def to_document_xml
38
- super do |xml|
39
- @doc_defaults&.each { |element| xml << element }
40
- @latent_styles&.each { |element| xml << element }
41
- styles.each { |style| xml << style }
42
- end
43
- end
44
-
45
25
  def write_to(zos)
46
26
  zos.put_next_entry XML_PATH
47
27
  zos.write to_document_xml
@@ -60,14 +40,10 @@ module Goldendocx
60
40
  end
61
41
 
62
42
  def add_style(fragment)
63
- # FIXME: Not a good implementation for Nokogiri compatibility
64
- raise NotImplementedError unless Goldendocx.config.xml_serializer == :ox
65
-
66
- style_id = (@styles.size + 1).to_s
67
- style = Goldendocx.xml_serializer.parse(fragment)
68
- style['w:styleId'] = style_id if style['w:styleId'].nil? || style['w:styleId'].empty?
69
- @styles << Goldendocx::Documents::Style.new(style)
70
- style_id
43
+ style = Goldendocx::Documents::Style.parse(fragment)
44
+ style.id = (styles.size + 1).to_s # Rearrange id to prevent duplicates
45
+ styles << style
46
+ style.id
71
47
  end
72
48
  end
73
49
  end
@@ -5,6 +5,6 @@ module Goldendocx
5
5
  end
6
6
  end
7
7
 
8
- Dir.glob(File.join(File.dirname(__FILE__), 'documents', '*.rb').to_s).sort.each do |file|
8
+ Dir.glob(File.join(File.dirname(__FILE__), 'documents', '*.rb').to_s).each do |file|
9
9
  require file
10
10
  end
@@ -1,32 +1,54 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'goldendocx/units'
4
- require 'goldendocx/element'
5
- require 'goldendocx/document'
6
-
3
+ require 'goldendocx/models'
7
4
  require 'goldendocx/components'
8
5
  require 'goldendocx/documents'
9
6
  require 'goldendocx/parts'
10
7
 
11
8
  module Goldendocx
12
9
  class Docx
13
- attr_reader :unstructured_entries, :documents, :content_types
10
+ include Goldendocx::HasAssociations
11
+
12
+ attr_reader :unstructured_entries, :documents
13
+
14
+ RELATIONSHIPS_XML_PATH = '_rels/.rels'
14
15
 
15
16
  STRUCTURED_ENTRIES = [
17
+ RELATIONSHIPS_XML_PATH,
18
+
16
19
  Goldendocx::Parts::ContentTypes::XML_PATH,
20
+ Goldendocx::Parts::App::XML_PATH,
21
+ Goldendocx::Parts::Core::XML_PATH,
22
+
23
+ Goldendocx::Parts::Documents::RELATIONSHIPS_XML_PATH,
17
24
 
18
- Goldendocx::Documents::Body::XML_PATH,
19
- Goldendocx::Documents::Relationships::XML_PATH,
25
+ Goldendocx::Documents::Document::XML_PATH,
26
+ Goldendocx::Documents::Settings::XML_PATH,
20
27
  Goldendocx::Documents::Styles::XML_PATH
21
28
  ].freeze
22
29
 
23
- def initialize(file_path)
30
+ relationships_at RELATIONSHIPS_XML_PATH
31
+ associate :app, class_name: 'Goldendocx::Parts::App'
32
+ associate :core, class_name: 'Goldendocx::Parts::Core'
33
+ associate :content_types, class_name: 'Goldendocx::Parts::ContentTypes', isolate: true
34
+
35
+ def initialize(file_path = nil)
36
+ file_path.present? ? read_from(file_path) : build_default
37
+ end
38
+
39
+ def read_from(file_path)
24
40
  docx_file = Zip::File.new(file_path)
41
+
42
+ read_relationships(docx_file)
43
+ read_associations(docx_file)
44
+
25
45
  @documents = Goldendocx::Parts::Documents.read_from(docx_file)
26
- @content_types = Goldendocx::Parts::ContentTypes.read_from(docx_file)
46
+
27
47
  @unstructured_entries = docx_file.entries.filter_map do |entry|
28
48
  UnStructuredEntry.new(entry) unless STRUCTURED_ENTRIES.include?(entry.name)
29
49
  end
50
+
51
+ self
30
52
  end
31
53
 
32
54
  def write_to(new_path)
@@ -65,6 +87,25 @@ module Goldendocx
65
87
 
66
88
  private
67
89
 
90
+ def build_default
91
+ associations.each do |association, options|
92
+ association_class = options.class_name.constantize
93
+ instance_variable_set("@#{association}", association_class.new)
94
+ add_relationship association_class::TYPE, association_class::XML_PATH unless options.isolate
95
+ end
96
+
97
+ content_types.add_override "/#{Goldendocx::Parts::App::XML_PATH}", Goldendocx::Parts::App::CONTENT_TYPE
98
+ content_types.add_override "/#{Goldendocx::Parts::Core::XML_PATH}", Goldendocx::Parts::Core::CONTENT_TYPE
99
+ content_types.add_override "/#{Goldendocx::Documents::Styles::XML_PATH}", Goldendocx::Documents::Styles::CONTENT_TYPE
100
+ content_types.add_override "/#{Goldendocx::Documents::Settings::XML_PATH}", Goldendocx::Documents::Settings::CONTENT_TYPE
101
+
102
+ @documents = Goldendocx::Parts::Documents.new
103
+ add_relationship Goldendocx::Documents::Document::TYPE, Goldendocx::Documents::Document::XML_PATH
104
+ content_types.add_override "/#{Goldendocx::Documents::Document::XML_PATH}", Goldendocx::Documents::Document::CONTENT_TYPE
105
+
106
+ @unstructured_entries = []
107
+ end
108
+
68
109
  def ensure_image_content_type!(_image_data)
69
110
  extension = 'png'
70
111
  content_type = 'image/png'
@@ -79,10 +120,12 @@ module Goldendocx
79
120
 
80
121
  def to_stream
81
122
  Zip::OutputStream.write_buffer do |zos|
82
- zos.put_next_entry Goldendocx::Parts::ContentTypes::XML_PATH
83
- zos.write content_types.to_document_xml
123
+ write_relationships(zos)
124
+
125
+ associations.each_key do |association|
126
+ send(association).write_to(zos)
127
+ end
84
128
 
85
- zos.put_next_entry Goldendocx::Parts::Documents::XML_PATH
86
129
  documents.write_stream(zos)
87
130
 
88
131
  @unstructured_entries.each { |unstructured_entry| unstructured_entry.write_to(zos) }