docxify 0.0.1 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cca8db68cf66e2ef536b4f78c25cecfe748adb531395d22e858f5e2525be3612
4
- data.tar.gz: 77c9e427bcd6294561654d4b1857f8846c1da4e9bd109aa78de0b42119ecb394
3
+ metadata.gz: 19220bad643ba9281144f2af8122d7c3300befdef7ed3dff796b81ccb493850c
4
+ data.tar.gz: fd960d429aedf127bfdca4eaf1d7a2aeda5a7c18577081a9f280169ccc74c23e
5
5
  SHA512:
6
- metadata.gz: 5ffb8d35049585d33df5e75c178a00be24c0a447f45e0d1ad960a538789f2f996cb74e486d8e1671aced45cb51c3a0eb24fe475377d3eb182ebbbd91ddc835dd
7
- data.tar.gz: 64f8104304ff8ded85f511d598de2d3ef47eb957c85b1d13431882423fdaaf9a6436a4de96710579634a59fd96be11780ce21ec9f94d6f6bc7b0186eadd706b4
6
+ metadata.gz: 7ef5802312027442107a8541ab7e34be20b8309403c12506b2d48ae77eaeaeb3c2a19877a20ac54dbcc88af3a92869dbc4e718a7647b1abecfce677a05ace286
7
+ data.tar.gz: b79ab3fc2a484c4882a0330c8bc25471ecb5304e8efa9260de945cdce57cd2ec2dae71133adaf7a10cf385f72d02c8f4f9255e0025ce47a442ce752f674939ec
data/.rubocop.yml ADDED
@@ -0,0 +1,309 @@
1
+ AllCops:
2
+ SuggestExtensions: false
3
+ NewCops: enable
4
+ Exclude:
5
+ - 'Gemfile'
6
+ - 'Rakefile'
7
+ - 'spec/**/*.rb'
8
+ - 'vendor/**/*'
9
+ Style/FormatStringToken:
10
+ EnforcedStyle: unannotated
11
+ Style/FetchEnvVar:
12
+ Enabled: false
13
+ Style/StringChars:
14
+ Enabled: false
15
+ Naming/BlockForwarding:
16
+ EnforcedStyle: explicit
17
+ Metrics/ClassLength:
18
+ Enabled: false
19
+ Naming/MethodParameterName:
20
+ Enabled: false
21
+ Lint/SuppressedException:
22
+ Enabled: false
23
+ Metrics/ParameterLists:
24
+ Enabled: false
25
+ Metrics/BlockNesting:
26
+ Enabled: false
27
+ Metrics/BlockLength:
28
+ Enabled: false
29
+ Metrics/ModuleLength:
30
+ Enabled: false
31
+ Metrics/CyclomaticComplexity:
32
+ Enabled: false
33
+ Metrics/PerceivedComplexity:
34
+ Enabled: false
35
+ Metrics/MethodLength:
36
+ Enabled: false
37
+ Layout/HashAlignment:
38
+ Enabled: false
39
+ Layout/ArgumentAlignment:
40
+ Enabled: false
41
+ Layout/LineLength:
42
+ Enabled: false
43
+ Layout/SpaceAroundMethodCallOperator:
44
+ Enabled: true
45
+ Lint/RaiseException:
46
+ Enabled: true
47
+ Lint/StructNewOverride:
48
+ Enabled: true
49
+ Style/ExponentialNotation:
50
+ Enabled: true
51
+ Style/HashEachMethods:
52
+ Enabled: true
53
+ Style/Documentation:
54
+ Enabled: false
55
+ Bundler/OrderedGems:
56
+ Enabled: false
57
+ Style/FrozenStringLiteralComment:
58
+ Enabled: false
59
+ Style/TrailingCommaInHashLiteral:
60
+ Enabled: false
61
+ Layout/SpaceBeforeSemicolon:
62
+ Enabled: false
63
+ Style/ClassAndModuleChildren:
64
+ Enabled: false
65
+ Metrics/AbcSize:
66
+ Enabled: false
67
+ Lint/RescueException:
68
+ Enabled: false
69
+ Layout/MultilineMethodCallIndentation:
70
+ Enabled: false
71
+
72
+ # Prefer &&/|| over and/or.
73
+ Style/AndOr:
74
+ Enabled: true
75
+
76
+ Style/FormatString:
77
+ EnforcedStyle: percent
78
+
79
+ # Align `when` with `case`.
80
+ Layout/CaseIndentation:
81
+ Enabled: false
82
+
83
+ Layout/ClosingHeredocIndentation:
84
+ Enabled: true
85
+
86
+ # Align comments with method definitions.
87
+ Layout/CommentIndentation:
88
+ Enabled: true
89
+
90
+ Layout/ElseAlignment:
91
+ Enabled: true
92
+
93
+ Style/RedundantRegexpEscape:
94
+ Enabled: false
95
+
96
+ Style/RaiseArgs:
97
+ EnforcedStyle: compact
98
+
99
+ # Align `end` with the matching keyword or starting expression except for
100
+ # assignments, where it should be aligned with the LHS.
101
+ Layout/EndAlignment:
102
+ Enabled: true
103
+ EnforcedStyleAlignWith: variable
104
+ AutoCorrect: true
105
+
106
+ Layout/EmptyLineAfterMagicComment:
107
+ Enabled: true
108
+
109
+ Layout/EmptyLinesAroundAccessModifier:
110
+ Enabled: false
111
+
112
+ Layout/EmptyLinesAroundBlockBody:
113
+ Enabled: true
114
+
115
+ # In a regular class definition, no empty lines around the body.
116
+ Layout/EmptyLinesAroundClassBody:
117
+ Enabled: true
118
+
119
+ # In a regular method definition, no empty lines around the body.
120
+ Layout/EmptyLinesAroundMethodBody:
121
+ Enabled: true
122
+
123
+ # In a regular module definition, no empty lines around the body.
124
+ Layout/EmptyLinesAroundModuleBody:
125
+ Enabled: true
126
+
127
+ # Use Ruby >= 1.9 syntax for hashes. Prefer { a: :b } over { :a => :b }.
128
+ Style/HashSyntax:
129
+ Enabled: true
130
+ EnforcedShorthandSyntax: never
131
+
132
+ Layout/FirstArgumentIndentation:
133
+ Enabled: true
134
+
135
+ Style/RescueModifier:
136
+ Enabled: false
137
+
138
+ # Method definitions after `private` or `protected` isolated calls need one
139
+ # extra level of indentation.
140
+ Layout/IndentationConsistency:
141
+ Enabled: false
142
+
143
+ # Two spaces, no tabs (for indentation).
144
+ Layout/IndentationWidth:
145
+ Enabled: true
146
+
147
+ Layout/LeadingCommentSpace:
148
+ Enabled: true
149
+
150
+ Layout/SpaceAfterColon:
151
+ Enabled: true
152
+
153
+ Layout/SpaceAfterComma:
154
+ Enabled: true
155
+
156
+ Layout/SpaceAfterSemicolon:
157
+ Enabled: true
158
+
159
+ Layout/SpaceAroundEqualsInParameterDefault:
160
+ Enabled: true
161
+
162
+ Layout/SpaceAroundKeyword:
163
+ Enabled: true
164
+
165
+ Layout/SpaceBeforeComma:
166
+ Enabled: true
167
+
168
+ Layout/SpaceBeforeComment:
169
+ Enabled: true
170
+
171
+ Layout/SpaceBeforeFirstArg:
172
+ Enabled: true
173
+
174
+ Style/DefWithParentheses:
175
+ Enabled: true
176
+
177
+ Style/MethodDefParentheses:
178
+ Enabled: true
179
+
180
+ Style/RedundantFreeze:
181
+ Enabled: true
182
+
183
+ # Use `foo {}` not `foo{}`.
184
+ Layout/SpaceBeforeBlockBraces:
185
+ Enabled: true
186
+
187
+ # Use `foo { bar }` not `foo {bar}`.
188
+ Layout/SpaceInsideBlockBraces:
189
+ Enabled: true
190
+ EnforcedStyleForEmptyBraces: space
191
+
192
+ # Use `{ a: 1 }` not `{a:1}`.
193
+ Layout/SpaceInsideHashLiteralBraces:
194
+ Enabled: true
195
+
196
+ Layout/SpaceInsideParens:
197
+ Enabled: true
198
+
199
+ # Check quotes usage according to lint rule below.
200
+ Style/StringLiterals:
201
+ Enabled: true
202
+ EnforcedStyle: double_quotes
203
+ SupportedStyles:
204
+ - single_quotes
205
+ - double_quotes
206
+
207
+ Style/StringLiteralsInInterpolation:
208
+ Enabled: false
209
+
210
+ Style/HashLikeCase:
211
+ Enabled: false
212
+
213
+ Style/IfUnlessModifier:
214
+ Enabled: false
215
+
216
+ # Detect hard tabs, no hard tabs.
217
+ Layout/IndentationStyle:
218
+ Enabled: true
219
+
220
+ # Empty lines should not have any spaces.
221
+ Layout/TrailingEmptyLines:
222
+ Enabled: true
223
+
224
+ # No trailing whitespace.
225
+ Layout/TrailingWhitespace:
226
+ Enabled: true
227
+
228
+ # Use quotes for string literals when they are enough.
229
+ Style/RedundantPercentQ:
230
+ Enabled: true
231
+
232
+ Lint/AmbiguousOperator:
233
+ Enabled: true
234
+
235
+ Lint/AmbiguousRegexpLiteral:
236
+ Enabled: true
237
+
238
+ Lint/ErbNewArguments:
239
+ Enabled: true
240
+
241
+ Lint/ParenthesesAsGroupedExpression:
242
+ Enabled: false
243
+
244
+ # Use my_method(my_arg) not my_method( my_arg ) or my_method my_arg.
245
+ Lint/RequireParentheses:
246
+ Enabled: true
247
+
248
+ Lint/ShadowingOuterLocalVariable:
249
+ Enabled: true
250
+
251
+ Lint/RedundantStringCoercion:
252
+ Enabled: true
253
+
254
+ Lint/UriEscapeUnescape:
255
+ Enabled: true
256
+
257
+ Lint/UselessAssignment:
258
+ Enabled: true
259
+
260
+ Lint/DeprecatedClassMethods:
261
+ Enabled: true
262
+
263
+ Style/GuardClause:
264
+ Enabled: false
265
+
266
+ Style/ParenthesesAroundCondition:
267
+ Enabled: true
268
+
269
+ Style/HashTransformKeys:
270
+ Enabled: true
271
+
272
+ Style/HashTransformValues:
273
+ Enabled: true
274
+
275
+ Style/RedundantBegin:
276
+ Enabled: true
277
+
278
+ Style/RedundantReturn:
279
+ Enabled: true
280
+ AllowMultipleReturnValues: true
281
+
282
+ Style/Semicolon:
283
+ Enabled: true
284
+ AllowAsExpressionSeparator: true
285
+
286
+ # Prefer Foo.method over Foo::method
287
+ Style/ColonMethodCall:
288
+ Enabled: true
289
+
290
+ Style/TrivialAccessors:
291
+ Enabled: true
292
+
293
+ Style/BarePercentLiterals:
294
+ Enabled: false
295
+
296
+ Style/IfInsideElse:
297
+ Enabled: false
298
+
299
+ Style/RegexpLiteral:
300
+ Enabled: false
301
+
302
+ Style/ParallelAssignment:
303
+ Enabled: false
304
+
305
+ Style/RedundantParentheses:
306
+ Enabled: false
307
+
308
+ Layout/FirstHashElementIndentation:
309
+ Enabled: false
data/CHANGELOG.md CHANGED
@@ -1 +1,33 @@
1
1
  # CHANGELOG
2
+
3
+ ## 0.0.5
4
+
5
+ Features:
6
+
7
+ - Paragraph font name, size, colour and yellow highlight done
8
+ - Document level default font name, size and colour done
9
+
10
+ ## 0.0.4
11
+
12
+ Features:
13
+
14
+ - Image insertion is working
15
+
16
+ ## 0.0.3
17
+
18
+ Features:
19
+
20
+ - Dividers and page breaks implemented
21
+ - Simple HTML parsing (for paragraphs) implemented
22
+
23
+ ## 0.0.2
24
+
25
+ Features:
26
+
27
+ - Able to generate a valid docx file, with no styling or anything useful yet
28
+
29
+ ## 0.0.1
30
+
31
+ Features:
32
+
33
+ - Brand new code/gem generated
data/LICENSE.md ADDED
@@ -0,0 +1,9 @@
1
+ # MIT License
2
+
3
+ Copyright ©️2024 FounderCatalyst IP Ltd
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -1,24 +1,71 @@
1
- # Docxify
1
+ # DocXify
2
2
 
3
- TODO: Delete this and the text below, and describe your gem
4
-
5
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/docxify`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ If you've ever wanted to generate a Word Document containing a letter or a contract (not a full page layout advert or advanced formatting like that), DocXify is the gem you need in your life.
6
4
 
7
5
  ## Installation
8
6
 
9
- TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
10
-
11
7
  Install the gem and add to the application's Gemfile by executing:
12
8
 
13
- $ bundle add UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
9
+ ```sh
10
+ bundle add docxify
11
+ ```
14
12
 
15
13
  If bundler is not being used to manage dependencies, install the gem by executing:
16
14
 
17
- $ gem install UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
15
+ ```sh
16
+ gem install docxify
17
+ ```
18
18
 
19
19
  ## Usage
20
20
 
21
- TODO: Write usage instructions here
21
+ ```ruby
22
+ @docx = DocXify::Document.new(page_width: DocXify::A4_PORTRAIT_WIDTH, page_height: DocXify::A4_PORTRAIT_HEIGHT)
23
+
24
+ @docx.default_styling font: "Serif font here", size: 14, color: "#040404"
25
+
26
+ @docx.add_paragraph "Title", font: "Something", size: 18, color: "#00000"
27
+ @docx.add_paragraph "Body copy"
28
+ @docx.add_paragraph "This is <b>bold</b>, <i>Italic</i> and <u>Underlined</u>."
29
+ @docx.add_paragraph "Text can also contain <a href='foo'>Links</a>."
30
+ @docx.add_paragraph "Centred text", align: :center
31
+ @docx.add_paragraph "Highlighted text", background: "#FFFF99"
32
+ @docx.add_paragraph "This won't show as <b>bold</b>", inline_styling: false
33
+
34
+ @docx.add_paragraph "\t1.1.1\tBody copy", tab_stops_cm: [1, 2]
35
+ @docx.add_paragraph "{CHECKBOX_EMPTY}\tEmpty checkbox", tab_stops_cm: [2]
36
+ @docx.add_paragraph "{CHECKBOX_CHECKED}\tChecked checkbox", tab_stops_cm: [2]
37
+
38
+ @docx.add_page_break
39
+ @docx.add_divider
40
+
41
+ @docx.add_image "file_path or data", align: :right, height_cm: 2, width_cm: 4
42
+
43
+ headers = [
44
+ DocXify::Element::TableCell.new("<b>Header 1</b>"),
45
+ DocXify::Element::TableCell.new("<b>Header 2</b>")
46
+ ]
47
+ row = [
48
+ DocXify::Element::TableCell.new("Content <b>here</b>", valign: :center, align: :left, nowrap: true, colspan: 3),
49
+ DocXify::Element::TableCell.new("Content <b>here</b>")
50
+ ]
51
+ rows = [row]
52
+ @docx.add_table headers, rows, expand: :full
53
+
54
+ docx_binary_data = @docx.render
55
+ # or
56
+ @docx.render "file_path"
57
+
58
+ # All of the above add_* are also available as objects for more dynamic control
59
+
60
+ para = DocXify::Element::Paragraph.new()
61
+ para.content = "This is <b>bold</b>, <i>Italic</i> and <u>Underlined</u>. It can also contain <a href='foo'>Links</a>."
62
+ para.font = "Something"
63
+ para.size = 18
64
+ para.color = "#040404"
65
+ para.background = "#FFFF99"
66
+ para.align = :center
67
+ @docx.add para
68
+ ```
22
69
 
23
70
  ## Development
24
71
 
@@ -26,6 +73,12 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
26
73
 
27
74
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
28
75
 
76
+ ### Overall architecture
77
+
78
+ The main object created by users is a `DocXify::Document`. This builds up a `@content` instance variable containing an array of all of the elements. Each element has a `to_s` method that will convert it's current state to a string, ready for insertion in to a complete document.
79
+
80
+ The `render` method on a `DocXify::Document` will generate a complete `document.xml` (Word terminology not a Ruby method) by creating a template and iterating each `@content` item. It will then create a `DocXify::Container` with that `document.xml` to generate a complete Zipped DocX file, and call it's `render` method to generate an in-memory file. This is then either returned to the `render` caller, or if a file path was passed as the first attribute, then it writes it out.
81
+
29
82
  ## Contributing
30
83
 
31
- Bug reports and pull requests are welcome on GitHub at https://github.com/andyjeffries/docxify.
84
+ Bug reports and pull requests are welcome on GitHub at <https://github.com/andyjeffries/docxify>.
data/Rakefile CHANGED
@@ -1,10 +1,8 @@
1
- # frozen_string_literal: true
2
-
3
1
  require "bundler/gem_tasks"
4
2
  require "rspec/core/rake_task"
3
+ require 'rubocop/rake_task'
5
4
 
6
5
  RSpec::Core::RakeTask.new(:spec)
6
+ RuboCop::RakeTask.new
7
7
 
8
- require "standard/rake"
9
-
10
- task default: %i[spec standard]
8
+ task default: %i[spec rubocop]
@@ -0,0 +1,75 @@
1
+ require "zip"
2
+
3
+ module DocXify
4
+ class Container
5
+ attr_accessor :document
6
+
7
+ def initialize(document)
8
+ @document = document
9
+ end
10
+
11
+ def render
12
+ temp_file = Tempfile.new("docxify.zip")
13
+
14
+ Zip::OutputStream.open(temp_file) do |zip|
15
+ zip.put_next_entry "_rels/.rels"
16
+ zip.write DocXify::Template.top_level_rels
17
+
18
+ zip.put_next_entry "[Content_Types].xml"
19
+ zip.write DocXify::Template.content_types
20
+
21
+ zip.put_next_entry "word/theme/theme1.xml"
22
+ zip.write DocXify::Template.theme
23
+
24
+ zip.put_next_entry "word/fontTable.xml"
25
+ zip.write DocXify::Template.font_table
26
+
27
+ zip.put_next_entry "word/settings.xml"
28
+ zip.write DocXify::Template.settings
29
+
30
+ zip.put_next_entry "word/styles.xml"
31
+ zip.write DocXify::Template.styles
32
+
33
+ zip.put_next_entry "word/webSettings.xml"
34
+ zip.write DocXify::Template.web_settings
35
+
36
+ zip.put_next_entry "word/document.xml"
37
+ zip.write document.build_xml(self)
38
+
39
+ zip.put_next_entry "word/_rels/document.xml.rels"
40
+ zip.write document_xml_rels
41
+
42
+ @document.images.each do |image|
43
+ zip.put_next_entry "word/media/#{image.filename}"
44
+ zip.write image.data
45
+ end
46
+ end
47
+
48
+ temp_file.flush
49
+ temp_file.rewind
50
+ temp_file.read
51
+ ensure
52
+ temp_file.close
53
+ temp_file.unlink
54
+ end
55
+
56
+ def document_xml_rels
57
+ xml = <<~XML
58
+ <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
59
+ <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
60
+ <Relationship Id="rId3" Target="webSettings.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings"/>
61
+ <Relationship Id="rId2" Target="settings.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings"/>
62
+ <Relationship Id="rId1" Target="styles.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles"/>
63
+ <Relationship Id="rId5" Target="theme/theme1.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme"/>
64
+ <Relationship Id="rId4" Target="fontTable.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable"/>
65
+ XML
66
+
67
+ @document.images.each do |image|
68
+ xml << "<Relationship Id=\"#{image.reference}\" Target=\"media/#{image.filename}\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image\"/>"
69
+ end
70
+
71
+ xml << "</Relationships>"
72
+ xml
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,98 @@
1
+ module DocXify
2
+ class Document
3
+ attr_accessor :font, :size, :color, :background
4
+ attr_reader :content, :images
5
+
6
+ def initialize(options = {})
7
+ @content = []
8
+ @images = []
9
+ @width = options[:width] || A4_PORTRAIT_WIDTH
10
+ @height = options[:height] || A4_PORTRAIT_HEIGHT
11
+ @font = options[:font] || "Times New Roman"
12
+ @size = options[:size] || 12
13
+ @color = options[:color] || 12
14
+ @background = options[:background] if options[:background]
15
+ @margins = { top: 2, bottom: 2, left: 2, right: 2 }
16
+ end
17
+
18
+ def default_styling(options = {})
19
+ @font = options[:font] if options[:font]
20
+ @size = options[:size] if options[:size]
21
+ @color = options[:color] if options[:color]
22
+ @background = options[:background] if options[:background]
23
+ end
24
+
25
+ # MARK: Rendering
26
+
27
+ def render(path = nil)
28
+ container = DocXify::Container.new(self)
29
+
30
+ if path
31
+ File.write(path, container.render)
32
+ else
33
+ container.render
34
+ end
35
+ end
36
+
37
+ def build_xml(container)
38
+ xml = <<~XML
39
+ <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
40
+ <w:document mc:Ignorable="w14 w15 w16se w16cid w16 w16cex w16sdtdh wp14" xmlns:aink="http://schemas.microsoft.com/office/drawing/2016/ink" xmlns:am3d="http://schemas.microsoft.com/office/drawing/2017/model3d" xmlns:cx="http://schemas.microsoft.com/office/drawing/2014/chartex" xmlns:cx1="http://schemas.microsoft.com/office/drawing/2015/9/8/chartex" xmlns:cx2="http://schemas.microsoft.com/office/drawing/2015/10/21/chartex" xmlns:cx3="http://schemas.microsoft.com/office/drawing/2016/5/9/chartex" xmlns:cx4="http://schemas.microsoft.com/office/drawing/2016/5/10/chartex" xmlns:cx5="http://schemas.microsoft.com/office/drawing/2016/5/11/chartex" xmlns:cx6="http://schemas.microsoft.com/office/drawing/2016/5/12/chartex" xmlns:cx7="http://schemas.microsoft.com/office/drawing/2016/5/13/chartex" xmlns:cx8="http://schemas.microsoft.com/office/drawing/2016/5/14/chartex" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:oel="http://schemas.microsoft.com/office/2019/extlst" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml" xmlns:w16="http://schemas.microsoft.com/office/word/2018/wordml" xmlns:w16cex="http://schemas.microsoft.com/office/word/2018/wordml/cex" xmlns:w16cid="http://schemas.microsoft.com/office/word/2016/wordml/cid" xmlns:w16sdtdh="http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash" xmlns:w16se="http://schemas.microsoft.com/office/word/2015/wordml/symex" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing" xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup" xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk" xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape">
41
+ <w:body>
42
+ XML
43
+
44
+ @content.each do |element|
45
+ xml << element.to_s(container)
46
+ end
47
+
48
+ xml << <<~XML
49
+ <w:sectPr >
50
+ <w:pgSz w:h="#{@height}" w:w="#{@width}"/>
51
+ <w:pgMar w:bottom="#{DocXify.cm2dxa @margins[:bottom]}" w:footer="708" w:gutter="0" w:header="708" w:left="#{DocXify.cm2dxa @margins[:left]}" w:right="#{DocXify.cm2dxa @margins[:right]}" w:top="#{DocXify.cm2dxa @margins[:top]}"/>
52
+ <w:cols w:space="708"/>
53
+ <w:docGrid w:linePitch="360"/>
54
+ </w:sectPr>
55
+ </w:body>
56
+ </w:document>
57
+ XML
58
+ end
59
+
60
+ # MARK: Elements
61
+
62
+ def add(element)
63
+ @content << element
64
+ end
65
+
66
+ def add_image(file_path_or_data, options = {})
67
+ file = if file_path_or_data.is_a?(DocXify::Element::File)
68
+ file_path_or_data
69
+ else
70
+ add_file(file_path_or_data)
71
+ end
72
+ add DocXify::Element::Image.new(file, options)
73
+ end
74
+
75
+ def add_file(file_path_or_data)
76
+ file = DocXify::Element::File.new(file_path_or_data)
77
+ @images << file
78
+ file
79
+ end
80
+
81
+ def add_page_break
82
+ add DocXify::Element::PageBreak.new
83
+ end
84
+
85
+ def add_divider
86
+ add DocXify::Element::Divider.new
87
+ end
88
+
89
+ def add_paragraph(text, options = {})
90
+ options[:document] = self
91
+ add DocXify::Element::Paragraph.new(text, options)
92
+ end
93
+
94
+ def add_table(headers, rows, options = {})
95
+ add DocXify::Element::Table.new(headers, rows, options)
96
+ end
97
+ end
98
+ end