goldendocx 0.2.2
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.
- checksums.yaml +7 -0
- data/.rspec +2 -0
- data/.rubocop.yml +47 -0
- data/CHANGELOG.md +43 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +101 -0
- data/README.md +76 -0
- data/Rakefile +10 -0
- data/coverage/.last_run.json +5 -0
- data/demo/charts/create_bar_chart.rb +30 -0
- data/demo/charts/create_column_chart.rb +29 -0
- data/demo/charts/create_doughnut_chart.rb +28 -0
- data/demo/charts/create_line_chart.rb +41 -0
- data/demo/images/append_image.rb +21 -0
- data/demo/images/append_styled_image.rb +14 -0
- data/demo/tables/create_embed_image_table.rb +42 -0
- data/demo/tables/create_plain_table.rb +22 -0
- data/demo/tables/create_styled_table.rb +36 -0
- data/demo/templates/bg.png +0 -0
- data/demo/templates/blankDocument.docx +0 -0
- data/demo/templates/image_base64 +1 -0
- data/demo/templates/styles/reportLabel +19 -0
- data/demo/templates/styles/reportSubTitle +20 -0
- data/demo/templates/styles/reportTable +27 -0
- data/demo/templates/styles/reportTitle +19 -0
- data/demo/texts/append_plain_text.rb +13 -0
- data/demo/texts/append_styled_text.rb +23 -0
- data/lib/goldendocx/charts/category_axis.rb +20 -0
- data/lib/goldendocx/charts/properties/auto_title_deleted_property.rb +16 -0
- data/lib/goldendocx/charts/properties/axis_property.rb +16 -0
- data/lib/goldendocx/charts/properties/bar_chart_property.rb +28 -0
- data/lib/goldendocx/charts/properties/chart_property.rb +16 -0
- data/lib/goldendocx/charts/properties/column_chart_property.rb +28 -0
- data/lib/goldendocx/charts/properties/cross_axis_property.rb +16 -0
- data/lib/goldendocx/charts/properties/data_lables_property.rb +16 -0
- data/lib/goldendocx/charts/properties/direction_property.rb +16 -0
- data/lib/goldendocx/charts/properties/doughnut_chart_property.rb +17 -0
- data/lib/goldendocx/charts/properties/grouping_property.rb +16 -0
- data/lib/goldendocx/charts/properties/hole_property.rb +16 -0
- data/lib/goldendocx/charts/properties/index_property.rb +16 -0
- data/lib/goldendocx/charts/properties/label_hidden_property.rb +16 -0
- data/lib/goldendocx/charts/properties/layout_property.rb +14 -0
- data/lib/goldendocx/charts/properties/line_chart_property.rb +24 -0
- data/lib/goldendocx/charts/properties/marker_property.rb +16 -0
- data/lib/goldendocx/charts/properties/number_list_property.rb +17 -0
- data/lib/goldendocx/charts/properties/order_property.rb +16 -0
- data/lib/goldendocx/charts/properties/plot_area_property.rb +23 -0
- data/lib/goldendocx/charts/properties/point_count_property.rb +16 -0
- data/lib/goldendocx/charts/properties/point_property.rb +18 -0
- data/lib/goldendocx/charts/properties/rounded_corner_property.rb +16 -0
- data/lib/goldendocx/charts/properties/series_category_property.rb +16 -0
- data/lib/goldendocx/charts/properties/series_text_property.rb +16 -0
- data/lib/goldendocx/charts/properties/series_value_property.rb +16 -0
- data/lib/goldendocx/charts/properties/smooth_property.rb +14 -0
- data/lib/goldendocx/charts/properties/string_list_property.rb +17 -0
- data/lib/goldendocx/charts/properties/symbol_property.rb +16 -0
- data/lib/goldendocx/charts/properties/text_value_property.rb +16 -0
- data/lib/goldendocx/charts/properties.rb +12 -0
- data/lib/goldendocx/charts/reference.rb +16 -0
- data/lib/goldendocx/charts/series.rb +57 -0
- data/lib/goldendocx/charts/value_axis.rb +20 -0
- data/lib/goldendocx/charts.rb +26 -0
- data/lib/goldendocx/components/bar_chart.rb +17 -0
- data/lib/goldendocx/components/chart.rb +55 -0
- data/lib/goldendocx/components/column_chart.rb +17 -0
- data/lib/goldendocx/components/doughnut_chart.rb +17 -0
- data/lib/goldendocx/components/image.rb +77 -0
- data/lib/goldendocx/components/line_chart.rb +17 -0
- data/lib/goldendocx/components/paragraph.rb +23 -0
- data/lib/goldendocx/components/properties/align_property.rb +16 -0
- data/lib/goldendocx/components/properties/bold_property.rb +16 -0
- data/lib/goldendocx/components/properties/color_property.rb +16 -0
- data/lib/goldendocx/components/properties/drawing.rb +16 -0
- data/lib/goldendocx/components/properties/extents_property.rb +17 -0
- data/lib/goldendocx/components/properties/graphic_data_property.rb +17 -0
- data/lib/goldendocx/components/properties/graphic_frame_locks_property.rb +18 -0
- data/lib/goldendocx/components/properties/graphic_frame_property.rb +16 -0
- data/lib/goldendocx/components/properties/graphic_property.rb +16 -0
- data/lib/goldendocx/components/properties/inline.rb +20 -0
- data/lib/goldendocx/components/properties/non_visual_property.rb +17 -0
- data/lib/goldendocx/components/properties/padding_property.rb +19 -0
- data/lib/goldendocx/components/properties/property.rb +17 -0
- data/lib/goldendocx/components/properties/run.rb +20 -0
- data/lib/goldendocx/components/properties/run_property.rb +17 -0
- data/lib/goldendocx/components/properties/style_property.rb +16 -0
- data/lib/goldendocx/components/properties/textual.rb +16 -0
- data/lib/goldendocx/components/properties.rb +12 -0
- data/lib/goldendocx/components/table.rb +44 -0
- data/lib/goldendocx/components/text.rb +35 -0
- data/lib/goldendocx/components.rb +16 -0
- data/lib/goldendocx/configuration.rb +18 -0
- data/lib/goldendocx/content_types/default.rb +22 -0
- data/lib/goldendocx/content_types/override.rb +22 -0
- data/lib/goldendocx/document.rb +51 -0
- data/lib/goldendocx/documents/body.rb +90 -0
- data/lib/goldendocx/documents/document.rb +29 -0
- data/lib/goldendocx/documents/element.rb +23 -0
- data/lib/goldendocx/documents/relationship.rb +17 -0
- data/lib/goldendocx/documents/relationships.rb +39 -0
- data/lib/goldendocx/documents/style.rb +21 -0
- data/lib/goldendocx/documents/styles.rb +74 -0
- data/lib/goldendocx/documents/unparsed_style.rb +17 -0
- data/lib/goldendocx/documents.rb +10 -0
- data/lib/goldendocx/docx.rb +108 -0
- data/lib/goldendocx/element.rb +192 -0
- data/lib/goldendocx/images/picture.rb +41 -0
- data/lib/goldendocx/images/properties/blip_property.rb +16 -0
- data/lib/goldendocx/images/properties/drawing_property.rb +14 -0
- data/lib/goldendocx/images/properties/extents_property.rb +17 -0
- data/lib/goldendocx/images/properties/fill_rectangle_property.rb +14 -0
- data/lib/goldendocx/images/properties/image_data_property.rb +17 -0
- data/lib/goldendocx/images/properties/non_visual_drawing_property.rb +17 -0
- data/lib/goldendocx/images/properties/non_visual_picture_property.rb +17 -0
- data/lib/goldendocx/images/properties/picture_fill_property.rb +17 -0
- data/lib/goldendocx/images/properties/picture_shape_property.rb +16 -0
- data/lib/goldendocx/images/properties/shape_property.rb +30 -0
- data/lib/goldendocx/images/properties/stretch_property.rb +17 -0
- data/lib/goldendocx/images/properties/transform_property.rb +16 -0
- data/lib/goldendocx/images/properties.rb +12 -0
- data/lib/goldendocx/images/shape.rb +32 -0
- data/lib/goldendocx/images.rb +12 -0
- data/lib/goldendocx/parts/content_types.rb +63 -0
- data/lib/goldendocx/parts/documents.rb +103 -0
- data/lib/goldendocx/parts/media.rb +43 -0
- data/lib/goldendocx/parts.rb +10 -0
- data/lib/goldendocx/tables/cell.rb +33 -0
- data/lib/goldendocx/tables/header_cell.rb +16 -0
- data/lib/goldendocx/tables/header_row.rb +14 -0
- data/lib/goldendocx/tables/image_cell.rb +23 -0
- data/lib/goldendocx/tables/properties/cell_property.rb +19 -0
- data/lib/goldendocx/tables/properties/cell_width_property.rb +17 -0
- data/lib/goldendocx/tables/properties/grid_column_property.rb +16 -0
- data/lib/goldendocx/tables/properties/grid_property.rb +16 -0
- data/lib/goldendocx/tables/properties/grid_span_property.rb +16 -0
- data/lib/goldendocx/tables/properties/header_row_property.rb +14 -0
- data/lib/goldendocx/tables/properties/property.rb +17 -0
- data/lib/goldendocx/tables/properties/row_height_property.rb +17 -0
- data/lib/goldendocx/tables/properties/row_property.rb +16 -0
- data/lib/goldendocx/tables/properties/shading_property.rb +18 -0
- data/lib/goldendocx/tables/properties/style_property.rb +16 -0
- data/lib/goldendocx/tables/properties/vertical_align_property.rb +16 -0
- data/lib/goldendocx/tables/properties/width_property.rb +17 -0
- data/lib/goldendocx/tables/properties.rb +12 -0
- data/lib/goldendocx/tables/row.rb +28 -0
- data/lib/goldendocx/tables.rb +19 -0
- data/lib/goldendocx/units.rb +11 -0
- data/lib/goldendocx/version.rb +5 -0
- data/lib/goldendocx/xml_serializers/nokogiri.rb +66 -0
- data/lib/goldendocx/xml_serializers/ox.rb +63 -0
- data/lib/goldendocx.rb +72 -0
- data/sig/goldendocx.rbs +4 -0
- metadata +347 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Goldendocx
|
|
4
|
+
module Documents
|
|
5
|
+
class Relationship
|
|
6
|
+
include Goldendocx::Element
|
|
7
|
+
|
|
8
|
+
attr_reader :id, :type, :target
|
|
9
|
+
|
|
10
|
+
tag :Relationship
|
|
11
|
+
|
|
12
|
+
attribute :id, alias_name: :Id
|
|
13
|
+
attribute :type, alias_name: :Type
|
|
14
|
+
attribute :target, alias_name: :Target
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Goldendocx
|
|
4
|
+
module Documents
|
|
5
|
+
class Relationships
|
|
6
|
+
include Goldendocx::Document
|
|
7
|
+
|
|
8
|
+
XML_PATH = 'word/_rels/document.xml.rels'
|
|
9
|
+
NAMESPACE = 'http://schemas.openxmlformats.org/package/2006/relationships'
|
|
10
|
+
|
|
11
|
+
tag :Relationships
|
|
12
|
+
attribute :xmlns, default: NAMESPACE, readonly: true
|
|
13
|
+
|
|
14
|
+
embeds_many :relationships, class_name: 'Goldendocx::Documents::Relationship'
|
|
15
|
+
|
|
16
|
+
def size
|
|
17
|
+
relationships.size
|
|
18
|
+
end
|
|
19
|
+
|
|
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
|
|
29
|
+
zos.write to_document_xml
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def add_relationship(type, target)
|
|
33
|
+
relationship_id = "rId#{relationships.size + 1}"
|
|
34
|
+
build_relationship(id: relationship_id, type: type, target: target)
|
|
35
|
+
relationship_id
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Goldendocx
|
|
4
|
+
module Documents
|
|
5
|
+
class Style
|
|
6
|
+
attr_reader :node, :id, :type, :name
|
|
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
|
|
15
|
+
|
|
16
|
+
def to_element(**_context)
|
|
17
|
+
@node
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Goldendocx
|
|
4
|
+
module Documents
|
|
5
|
+
class Styles
|
|
6
|
+
include Goldendocx::Document
|
|
7
|
+
|
|
8
|
+
XML_PATH = 'word/styles.xml'
|
|
9
|
+
|
|
10
|
+
tag :styles
|
|
11
|
+
namespace :w
|
|
12
|
+
concern_namespaces :mc, :r, :w, :w14, :w15
|
|
13
|
+
ignore_namespaces :w14, :w15
|
|
14
|
+
|
|
15
|
+
attr_reader :styles, :doc_defaults, :latent_styles
|
|
16
|
+
|
|
17
|
+
def initialize
|
|
18
|
+
@styles = []
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def size
|
|
22
|
+
styles.size
|
|
23
|
+
end
|
|
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
|
+
def write_to(zos)
|
|
46
|
+
zos.put_next_entry XML_PATH
|
|
47
|
+
zos.write to_document_xml
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def find_text_style(style_name)
|
|
51
|
+
return if style_name.nil?
|
|
52
|
+
|
|
53
|
+
styles.find { |s| s.type == 'paragraph' && s.name == style_name }
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def find_table_style(style_name)
|
|
57
|
+
return if style_name.nil?
|
|
58
|
+
|
|
59
|
+
styles.find { |s| s.type == 'table' && s.name == style_name }
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
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
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'goldendocx/units'
|
|
4
|
+
require 'goldendocx/element'
|
|
5
|
+
require 'goldendocx/document'
|
|
6
|
+
|
|
7
|
+
require 'goldendocx/components'
|
|
8
|
+
require 'goldendocx/documents'
|
|
9
|
+
require 'goldendocx/parts'
|
|
10
|
+
|
|
11
|
+
module Goldendocx
|
|
12
|
+
class Docx
|
|
13
|
+
attr_reader :unstructured_entries, :documents, :content_types
|
|
14
|
+
|
|
15
|
+
STRUCTURED_ENTRIES = [
|
|
16
|
+
Goldendocx::Parts::ContentTypes::XML_PATH,
|
|
17
|
+
|
|
18
|
+
Goldendocx::Documents::Body::XML_PATH,
|
|
19
|
+
Goldendocx::Documents::Relationships::XML_PATH,
|
|
20
|
+
Goldendocx::Documents::Styles::XML_PATH
|
|
21
|
+
].freeze
|
|
22
|
+
|
|
23
|
+
def initialize(file_path)
|
|
24
|
+
docx_file = Zip::File.new(file_path)
|
|
25
|
+
@documents = Goldendocx::Parts::Documents.read_from(docx_file)
|
|
26
|
+
@content_types = Goldendocx::Parts::ContentTypes.read_from(docx_file)
|
|
27
|
+
@unstructured_entries = docx_file.entries.filter_map do |entry|
|
|
28
|
+
UnStructuredEntry.new(entry) unless STRUCTURED_ENTRIES.include?(entry.name)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def write_to(new_path)
|
|
33
|
+
File.binwrite(new_path, to_stream.string)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def create_text(text, options = {})
|
|
37
|
+
documents.create_text(text, options)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def create_table(options = {})
|
|
41
|
+
documents.create_table(options)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def create_image(image_data, options = {})
|
|
45
|
+
ensure_image_content_type!(image_data)
|
|
46
|
+
documents.create_image(image_data, options)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def create_embed_image(image_data, options = {})
|
|
50
|
+
ensure_image_content_type!(image_data)
|
|
51
|
+
documents.create_embed_image(image_data, options)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def add_style(style_path)
|
|
55
|
+
documents.add_style(style_path)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def create_chart(chart_type, width: nil, height: nil)
|
|
59
|
+
chart = documents.create_chart(
|
|
60
|
+
chart_type, width || Charts::DEFAULT_WIDTH, height || Charts::DEFAULT_HEIGHT
|
|
61
|
+
)
|
|
62
|
+
ensure_chart_content_type!(chart)
|
|
63
|
+
chart
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
private
|
|
67
|
+
|
|
68
|
+
def ensure_image_content_type!(_image_data)
|
|
69
|
+
extension = 'png'
|
|
70
|
+
content_type = 'image/png'
|
|
71
|
+
content_types.add_default(extension, content_type)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def ensure_chart_content_type!(chart)
|
|
75
|
+
content_types.add_override(
|
|
76
|
+
format(Charts::PART_NAME_PATTERN, id: chart.id), Charts::CONTENT_TYPE
|
|
77
|
+
)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def to_stream
|
|
81
|
+
Zip::OutputStream.write_buffer do |zos|
|
|
82
|
+
zos.put_next_entry Goldendocx::Parts::ContentTypes::XML_PATH
|
|
83
|
+
zos.write content_types.to_document_xml
|
|
84
|
+
|
|
85
|
+
zos.put_next_entry Goldendocx::Parts::Documents::XML_PATH
|
|
86
|
+
documents.write_stream(zos)
|
|
87
|
+
|
|
88
|
+
@unstructured_entries.each { |unstructured_entry| unstructured_entry.write_to(zos) }
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# TODO: Remove this after all structured
|
|
93
|
+
class UnStructuredEntry
|
|
94
|
+
attr_reader :entry
|
|
95
|
+
|
|
96
|
+
def initialize(entry)
|
|
97
|
+
@entry = entry
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def write_to(zos)
|
|
101
|
+
zos.put_next_entry entry.name
|
|
102
|
+
return if entry.directory?
|
|
103
|
+
|
|
104
|
+
zos.write entry.get_input_stream.read
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'active_support/core_ext/string/inflections'
|
|
4
|
+
|
|
5
|
+
ActiveSupport::Inflector.inflections do |inflect|
|
|
6
|
+
inflect.uncountable 'extents', 'image_data', 'data'
|
|
7
|
+
inflect.irregular 'axis', 'axes'
|
|
8
|
+
|
|
9
|
+
inflect.uncountable 'values' # TODO: Find better names
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
module Goldendocx
|
|
13
|
+
module Element
|
|
14
|
+
def self.included(base)
|
|
15
|
+
base.extend(ClassMethods)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
module ClassMethods
|
|
19
|
+
def tag(*args)
|
|
20
|
+
@tag = args.first if args.any?
|
|
21
|
+
@tag
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def namespace(*args)
|
|
25
|
+
@namespace = args.first if args.any?
|
|
26
|
+
@namespace
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# alias_name: nil
|
|
30
|
+
# readonly: false
|
|
31
|
+
# default: nil
|
|
32
|
+
# namespace: nil
|
|
33
|
+
# setter: nil
|
|
34
|
+
def attribute(name, **options)
|
|
35
|
+
named = name.to_s
|
|
36
|
+
attributes[named] = {
|
|
37
|
+
alias_name: options[:alias_name],
|
|
38
|
+
default: options[:default],
|
|
39
|
+
namespace: options[:namespace],
|
|
40
|
+
method: options[:method]
|
|
41
|
+
}.compact
|
|
42
|
+
|
|
43
|
+
readonly = options[:readonly] || false
|
|
44
|
+
if readonly
|
|
45
|
+
attr_reader named
|
|
46
|
+
elsif options[:method]
|
|
47
|
+
attr_writer named
|
|
48
|
+
else
|
|
49
|
+
attr_accessor named
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def attributes
|
|
54
|
+
@attributes ||= {}
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def create_children_getter(name)
|
|
58
|
+
options = children[name]
|
|
59
|
+
class_name = options[:class_name]
|
|
60
|
+
multiple = options[:multiple]
|
|
61
|
+
auto_build = options[:auto_build]
|
|
62
|
+
|
|
63
|
+
define_method name do
|
|
64
|
+
return instance_variable_get("@#{name}") if instance_variable_defined?("@#{name}")
|
|
65
|
+
|
|
66
|
+
default_value = if multiple
|
|
67
|
+
[]
|
|
68
|
+
else
|
|
69
|
+
auto_build ? Kernel.const_get(class_name).new : nil
|
|
70
|
+
end
|
|
71
|
+
instance_variable_set("@#{name}", default_value)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def create_children_setter(name)
|
|
76
|
+
options = children[name]
|
|
77
|
+
class_name = options[:class_name]
|
|
78
|
+
|
|
79
|
+
define_method "#{name}=" do |value|
|
|
80
|
+
value = value.to_s if value && class_name == 'String'
|
|
81
|
+
instance_variable_set("@#{name}", value)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def create_children_builder(name)
|
|
86
|
+
options = children[name]
|
|
87
|
+
class_name = options[:class_name]
|
|
88
|
+
multiple = options[:multiple]
|
|
89
|
+
|
|
90
|
+
define_method "build_#{name.to_s.singularize}" do |**attributes|
|
|
91
|
+
child = Kernel.const_get(class_name).new
|
|
92
|
+
attributes.each { |key, value| child.send("#{key}=", value) if child.respond_to?("#{key}=") }
|
|
93
|
+
multiple ? send(name) << child : instance_variable_set("@#{name}", child)
|
|
94
|
+
child
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def embeds_one(name, class_name:, auto_build: false)
|
|
99
|
+
warning_naming_suggestion(name, name.to_s.singularize)
|
|
100
|
+
|
|
101
|
+
children[name] = { class_name: class_name, multiple: false, auto_build: auto_build }
|
|
102
|
+
create_children_getter(name)
|
|
103
|
+
create_children_setter(name)
|
|
104
|
+
create_children_builder(name)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def embeds_many(name, class_name:)
|
|
108
|
+
warning_naming_suggestion(name, name.to_s.pluralize)
|
|
109
|
+
|
|
110
|
+
children[name] = { class_name: class_name, multiple: true, auto_build: false }
|
|
111
|
+
create_children_getter(name)
|
|
112
|
+
create_children_builder(name)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def children
|
|
116
|
+
@children ||= {}
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def concerning_ancestors
|
|
120
|
+
ancestors.filter { |ancestor| ancestor.include?(Goldendocx::Element) }
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
private
|
|
124
|
+
|
|
125
|
+
# :nocov:
|
|
126
|
+
def warning_naming_suggestion(name, suggestion_name)
|
|
127
|
+
return if suggestion_name == name.to_s
|
|
128
|
+
|
|
129
|
+
location = caller.find { |c| c.include?('goldendocx/') && !c.include?('goldendocx/element.rb') }
|
|
130
|
+
warn "warning: [embeds_one] `#{name}` better be singular `#{suggestion_name}` at #{location}"
|
|
131
|
+
end
|
|
132
|
+
# :nocov:
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def attributes
|
|
136
|
+
self.class.attributes.each_with_object({}) do |(name, options), result|
|
|
137
|
+
value = public_send(options[:method] || name) || options[:default]
|
|
138
|
+
next if value.nil?
|
|
139
|
+
|
|
140
|
+
key = [options[:namespace], options[:alias_name] || name].compact.join(':')
|
|
141
|
+
result[key] = value
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def assign_attributes(**attributes)
|
|
146
|
+
attributes.each { |key, value| send("#{key}=", value) if respond_to?("#{key}=") }
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def tag
|
|
150
|
+
self.class.concerning_ancestors.find { |ancestor| ancestor.tag.present? }&.tag
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def namespace
|
|
154
|
+
self.class.concerning_ancestors.find { |ancestor| ancestor.namespace.present? }&.namespace
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def root_tag
|
|
158
|
+
@root_tag ||= [namespace, tag].compact.join(':')
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def siblings
|
|
162
|
+
return [] unless self.class.superclass.include?(Goldendocx::Element)
|
|
163
|
+
|
|
164
|
+
self.class.superclass.children.keys.flat_map { |name| send(name) }
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def children
|
|
168
|
+
self.class.children.keys.flat_map do |name|
|
|
169
|
+
send(name)
|
|
170
|
+
end.concat(siblings).compact
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def to_element(**context)
|
|
174
|
+
Goldendocx.xml_serializer.build_element(root_tag, **context) do |xml|
|
|
175
|
+
attributes.each { |name, value| xml[name] = value }
|
|
176
|
+
children.each { |child| xml << child }
|
|
177
|
+
|
|
178
|
+
yield(xml) if block_given?
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def to_xml
|
|
183
|
+
Goldendocx.xml_serializer.build_xml(root_tag) do |xml|
|
|
184
|
+
attributes.each { |name, value| xml[name] = value }
|
|
185
|
+
|
|
186
|
+
yield(xml) if block_given?
|
|
187
|
+
|
|
188
|
+
children.each { |child| xml << child }
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Goldendocx
|
|
4
|
+
module Images
|
|
5
|
+
class Picture
|
|
6
|
+
include Goldendocx::Element
|
|
7
|
+
|
|
8
|
+
namespace :pic
|
|
9
|
+
tag :pic
|
|
10
|
+
|
|
11
|
+
embeds_one :non_visual_picture, class_name: 'Goldendocx::Images::Properties::NonVisualPictureProperty', auto_build: true
|
|
12
|
+
embeds_one :drawing, class_name: 'Goldendocx::Images::Properties::DrawingProperty', auto_build: true
|
|
13
|
+
embeds_one :picture_fill, class_name: 'Goldendocx::Images::Properties::PictureFillProperty', auto_build: true
|
|
14
|
+
embeds_one :picture_shape, class_name: 'Goldendocx::Images::Properties::PictureShapeProperty', auto_build: true
|
|
15
|
+
|
|
16
|
+
def initialize(**attributes)
|
|
17
|
+
attributes.each do |name, value|
|
|
18
|
+
send("#{name}=", value) if respond_to?("#{name}=")
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def width=(width)
|
|
23
|
+
picture_shape.transform.extents.width = width if width
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def height=(height)
|
|
27
|
+
picture_shape.transform.extents.height = height if height
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def relationship_id=(relationship_id)
|
|
31
|
+
return unless relationship_id
|
|
32
|
+
|
|
33
|
+
non_visual_picture.non_visual_drawing.assign_attributes(
|
|
34
|
+
relationship_id: relationship_id,
|
|
35
|
+
name: "#{relationship_id}.png"
|
|
36
|
+
)
|
|
37
|
+
picture_fill.blip.relationship_id = relationship_id
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Goldendocx
|
|
4
|
+
module Images
|
|
5
|
+
module Properties
|
|
6
|
+
class BlipProperty
|
|
7
|
+
include Goldendocx::Element
|
|
8
|
+
|
|
9
|
+
namespace :a
|
|
10
|
+
tag :blip
|
|
11
|
+
|
|
12
|
+
attribute :relationship_id, alias_name: :embed, namespace: :r
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Goldendocx
|
|
4
|
+
module Images
|
|
5
|
+
module Properties
|
|
6
|
+
class ExtentsProperty
|
|
7
|
+
include Goldendocx::Element
|
|
8
|
+
|
|
9
|
+
namespace :a
|
|
10
|
+
tag :ext
|
|
11
|
+
|
|
12
|
+
attribute :width, alias_name: :cx
|
|
13
|
+
attribute :height, alias_name: :cy
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Goldendocx
|
|
4
|
+
module Images
|
|
5
|
+
module Properties
|
|
6
|
+
class ImageDataProperty
|
|
7
|
+
include Goldendocx::Element
|
|
8
|
+
|
|
9
|
+
namespace :v
|
|
10
|
+
tag :imagedata
|
|
11
|
+
|
|
12
|
+
attribute :relationship_id, alias_name: :id, namespace: :r
|
|
13
|
+
attribute :title, namespace: :o
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Goldendocx
|
|
4
|
+
module Images
|
|
5
|
+
module Properties
|
|
6
|
+
class NonVisualDrawingProperty
|
|
7
|
+
include Goldendocx::Element
|
|
8
|
+
|
|
9
|
+
namespace :pic
|
|
10
|
+
tag :cNvPr
|
|
11
|
+
|
|
12
|
+
attribute :relationship_id, alias_name: :id
|
|
13
|
+
attribute :name
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Goldendocx
|
|
4
|
+
module Images
|
|
5
|
+
module Properties
|
|
6
|
+
class NonVisualPictureProperty
|
|
7
|
+
include Goldendocx::Element
|
|
8
|
+
|
|
9
|
+
namespace :pic
|
|
10
|
+
tag :nvPicPr
|
|
11
|
+
|
|
12
|
+
embeds_one :non_visual_drawing, class_name: 'Goldendocx::Images::Properties::NonVisualDrawingProperty',
|
|
13
|
+
auto_build: true
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Goldendocx
|
|
4
|
+
module Images
|
|
5
|
+
module Properties
|
|
6
|
+
class PictureFillProperty
|
|
7
|
+
include Goldendocx::Element
|
|
8
|
+
|
|
9
|
+
namespace :pic
|
|
10
|
+
tag :blipFill
|
|
11
|
+
|
|
12
|
+
embeds_one :blip, class_name: 'Goldendocx::Images::Properties::BlipProperty', auto_build: true
|
|
13
|
+
embeds_one :stretch, class_name: 'Goldendocx::Images::Properties::StretchProperty', 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 Images
|
|
5
|
+
module Properties
|
|
6
|
+
class PictureShapeProperty
|
|
7
|
+
include Goldendocx::Element
|
|
8
|
+
|
|
9
|
+
namespace :pic
|
|
10
|
+
tag :spPr
|
|
11
|
+
|
|
12
|
+
embeds_one :transform, class_name: 'Goldendocx::Images::Properties::TransformProperty', auto_build: true
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|