caracal 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +334 -702
  3. data/lib/caracal.rb +1 -0
  4. data/lib/caracal/core/file_name.rb +1 -1
  5. data/lib/caracal/core/fonts.rb +2 -2
  6. data/lib/caracal/core/images.rb +3 -2
  7. data/lib/caracal/core/list_styles.rb +20 -20
  8. data/lib/caracal/core/lists.rb +2 -2
  9. data/lib/caracal/core/models/base_model.rb +1 -1
  10. data/lib/caracal/core/models/border_model.rb +1 -1
  11. data/lib/caracal/core/models/image_model.rb +1 -1
  12. data/lib/caracal/core/models/link_model.rb +11 -0
  13. data/lib/caracal/core/models/list_item_model.rb +2 -2
  14. data/lib/caracal/core/models/list_model.rb +4 -3
  15. data/lib/caracal/core/models/list_style_model.rb +7 -18
  16. data/lib/caracal/core/models/margin_model.rb +1 -1
  17. data/lib/caracal/core/models/page_number_model.rb +1 -1
  18. data/lib/caracal/core/models/page_size_model.rb +1 -1
  19. data/lib/caracal/core/models/paragraph_model.rb +8 -6
  20. data/lib/caracal/core/models/style_model.rb +1 -1
  21. data/lib/caracal/core/models/table_cell_model.rb +3 -3
  22. data/lib/caracal/core/models/table_model.rb +2 -2
  23. data/lib/caracal/core/page_numbers.rb +4 -3
  24. data/lib/caracal/core/page_settings.rb +2 -2
  25. data/lib/caracal/core/relationships.rb +1 -1
  26. data/lib/caracal/core/rules.rb +1 -1
  27. data/lib/caracal/core/styles.rb +1 -1
  28. data/lib/caracal/core/tables.rb +3 -2
  29. data/lib/caracal/core/text.rb +6 -4
  30. data/lib/caracal/document.rb +10 -10
  31. data/lib/caracal/renderers/document_renderer.rb +1 -1
  32. data/lib/caracal/renderers/numbering_renderer.rb +2 -2
  33. data/lib/caracal/utilities.rb +23 -0
  34. data/lib/caracal/version.rb +1 -1
  35. data/spec/lib/caracal/core/models/link_model_spec.rb +6 -0
  36. data/spec/lib/caracal/core/models/list_style_model_spec.rb +15 -29
  37. metadata +3 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 59758b862e0b05d974cf9fc726a87fe910c85763
4
- data.tar.gz: cf29ba4295b3a2e181215eedd77f878f76a1941d
3
+ metadata.gz: 1bb670d6eb597c90b1194c07b2a5e8bc76709d5a
4
+ data.tar.gz: 752f8ffbf3cf9345c643f0cde32828d5c92bd43b
5
5
  SHA512:
6
- metadata.gz: 6666722a221f0e572625787923f9bab053e025e6c6d7b9e25e80dfbdaa09a57a7f1e9eca72e6ea51a76ec56810eb8cc27b8c1c5dd629108082e6cc2c9b16b4e2
7
- data.tar.gz: 7ec8fcde135be9d2b98ae9720bd9cd3f7662a8cb3e1e11ce1bd7b6541e5cc350906b4035d898d877c0d7005543200bbfc346cc892c5a5f97b75ea674e9902f53
6
+ metadata.gz: cfa124deda9e1d77e3a3c81ecefe3f0af759ff2093387e0cbd63ea5dcb4e21ef4dbf0d23b2364708d40c801bdcac25ba78eea444ba016b163c7331ff3bb44b35
7
+ data.tar.gz: 30f6a9a3063b98b433a71f9b8e31a58ee1a0a11f35e2cd6df420e922b8eac04e83886c1d5a72e371bd578a332aad1fecd3803791880d2de4f1bc95077853e231
data/README.md CHANGED
@@ -1,32 +1,89 @@
1
1
  # Caracal
2
+
2
3
  [![Build Status](http://img.shields.io/travis/trade-informatics/caracal.svg?style=flat)](https://travis-ci.org/trade-informatics/caracal)
3
4
  [![Gem Version](http://img.shields.io/gem/v/caracal.svg?style=flat)](https://rubygems.org/gems/caracal)
4
5
 
5
- Caracal is a ruby library for dynamically creating professional-quality Microsoft Word documents (.docx) using an HTML-style syntax.
6
6
 
7
+ ## Overview
7
8
 
8
- ## Installation
9
+ Caracal is a ruby library for dynamically creating professional-quality Microsoft Word documents using an HTML-style syntax.
10
+
11
+ Caracal is not a magical HTML to Word translator. Instead, it is a markup language for generating Office Open XML (OOXML). Programmers create Word documents by issuing a series of simple commands against a document object. When the document is rendered, Caracal takes care of translating those Ruby commands into the requisite OOXML. At its core, the library is essentially a templating engine for the `:docx` format.
12
+
13
+ Or, said differently, if you use [Prawn](https://github.com/prawnpdf/prawn) for PDF generation, you'll probably like Caracal. Only you'll probably like it better. :)
9
14
 
10
- Add this line to your application's Gemfile:
15
+
16
+ ## Teaser
17
+
18
+ How would you like to make a Word document like this?
11
19
 
12
20
  ```ruby
13
- gem 'caracal'
21
+ Caracal::Document.save 'example.docx' do |docx|
22
+ # page 1
23
+ docx.h1 'Page 1 Header'
24
+ docx.hr
25
+ docx.br
26
+ docx.h2 'Section 1'
27
+ docx.p 'Lorem ipsum dolor....'
28
+ docx.br
29
+ docx.table @my_data, border_size: 4 do
30
+ cell_style rows[0], background: 'cccccc', bold: true
31
+ end
32
+
33
+ # page 2
34
+ docx.page
35
+ docx.h1 'Page 2 Header'
36
+ docx.hr
37
+ docx.br
38
+ docx.h2 'Section 2'
39
+ docx.p 'Lorem ipsum dolor....'
40
+ docx.ul do
41
+ li 'Item 1'
42
+ li 'Item 2'
43
+ end
44
+ docx.br
45
+ docx.img image_url('graph.png'), width: 500, height: 300
46
+ end
14
47
  ```
15
48
 
16
- Then execute:
49
+ **You can! Read on.**
17
50
 
18
- ```bash
19
- bundle install
20
- ```
21
51
 
22
- ## Overview
52
+ ## Why is Caracal Needed?
53
+
54
+ We created Caracal to satisfy a genuine business requirement. We were working on a system that produced a periodic PDF report and our clients asked if the report could instead be generated as a Word document, which would allow them to perform edits before passing the report along to their clients.
55
+
56
+ Now, as you may have noticed, the Ruby community has never exactly been known for its enthusiastic support of Microsoft standards. So it might not surprise you to learn that the existing options on Rubygems for Word document generation were limited. Those libraries, by and large, fell into a couple of categories:
57
+
58
+ * **HTML to Word Convertors**
59
+ We understand the motivating idea here (two output streams from one set of instructions), but the reality is the number of possible permutations of nested HTML tags is simply too great for this strategy to ever work for anything other than the simplest kinds of documents. Most of these libraries rely on a number of undocumented assumptions about the structure of your HTML (which undermines the whole value proposition of a convertor) and fail to support basic features of a professional-quality Word document (e.g., images, lists, tables, etc). The remaining libraries simply did not work at all.
60
+
61
+ * **Weekend Projects**
62
+ We also found a number of inactive projects that appeared to be experiments in the space. Obviously, these libraries were out of the question for a commercial product.
63
+
64
+ What we wanted was a Prawn-style library for the `:docx` format. In the absence of an active project organized along those lines, we decided to write one.
65
+
66
+
67
+ ## Design
23
68
 
24
- Many people don't know that .docx files are little more than a zipped collection of XML documents that follow the OfficeOpen XML (OpenXML or OOXML) standard. This means constructing a .docx file from scratch actually requires the creation of several files. Caracal abstracts users from this process by providing a simple set of Ruby commands and HTML-style syntax for generating Word content.
69
+ Caracal is designed to separate the process of parsing and collecting rendering instructions from the process of rendering itself.
70
+
71
+ First, the library consumes all programmer instructions and organizes several collections of data models that capture those instructions. These collections are ordered and nested exactly as the instructions we given. Each model contains all the data required to render it and is responsible for declaring itself valid or invalid.
72
+
73
+ *Note: Some instructions create more than one model. For example, the `img` method both appends an `ImageModel` to the main contents collection and determines whether or not a new `RelationshipModel` should be added to the relationships collection.*
74
+
75
+ Only after all the programmer instructions have been parsed does the document attempt to render the data to XML. This strategy gives the rendering process a tremendous amount of flexibility in the rare cases where renderers combine data from more than one collection.
76
+
77
+
78
+ ## File Structure
79
+
80
+ You may not know that .docx files are simply a zipped collection of XML documents that follow the OOXML standard. (We didn't, in any event.) This means constructing a .docx file from scratch actually requires the creation of several files. Caracal abstracts users from this process entirely.
25
81
 
26
82
  For each Caracal request, the following document structure will be created and zipped into the final output file:
27
83
 
28
84
  example.docx
29
85
  |- _rels
86
+ |- .rels
30
87
  |- docProps
31
88
  |- app.xml
32
89
  |- core.xml
@@ -45,7 +102,8 @@ For each Caracal request, the following document structure will be created and z
45
102
  |- styles.xml
46
103
  |- [Content_Types].xml
47
104
 
48
- ### File Descriptions
105
+
106
+ ## File Descriptions
49
107
 
50
108
  The following provides a brief description for each component of the final document:
51
109
 
@@ -88,7 +146,7 @@ Pairs extensions and XML files with schema content types so Word can parse them
88
146
 
89
147
  ## Units
90
148
 
91
- OpenXML uses a few basic units.
149
+ OpenXML properties are specified in several different units, depending on which attribute is being set.
92
150
 
93
151
  **Points**
94
152
  Most spacing declarations are measured in full points.
@@ -108,8 +166,55 @@ In Word documents, pixels are equivalent to points.
108
166
  **EMUs (English Metric Unit)**
109
167
  EMUs are a virtual unit designed to facilitate the smooth conversion between inches, milliimeters, and pixels for images and vector graphics. 1in == 914400 EMUs == 72dpi x 100 x 254.
110
168
 
169
+ At present, Caracal expects values to be specified in whichever unit OOXML requires. This is admittedly difficult for new Caracal users. Eventually, we'll probably implement a utility object under the hood to convert user-specified units into the format expected by OOXML.
170
+
171
+
172
+ ## Syntax Flexibility
173
+
174
+ Generally speaking, Caracal commands will accept instructions via any combination of a parameters hash and/or a block. For example, all of the folowing commands are equivalent.
175
+
176
+ ```ruby
177
+ docx.style id: 'special', name: 'Special', size: 24, bold: true
178
+
179
+ docx.style id: 'special', size: 24 do
180
+ name 'Special'
181
+ bold true
182
+ end
183
+
184
+ docx.style do
185
+ id 'special'
186
+ name 'Special'
187
+ size 24
188
+ bold true
189
+ end
190
+ ```
191
+
192
+ Parameter options are always evaluated before block options. This means if the same option is provided in the parameter hash and in the block, the value in the block will overwrite the value from the parameter hash. Tread carefully.
193
+
194
+
195
+ ## Validations
111
196
 
112
- ## Syntax
197
+ All Caracal models perform basic validations on their attributes, but this is, without question, the least sophisticated part of the library at present.
198
+
199
+ In forthcoming versions of Caracal, we'll be looking to expand the `InvalidModelError` class to provide broader error reporting abilities across the entire library.
200
+
201
+
202
+ ## Installation
203
+
204
+ Add this line to your application's Gemfile:
205
+
206
+ ```ruby
207
+ gem 'caracal'
208
+ ```
209
+
210
+ Then execute:
211
+
212
+ ```bash
213
+ bundle install
214
+ ```
215
+
216
+
217
+ ## Commands
113
218
 
114
219
  In the following examples, the variable `docx` is assumed to be an instance of Caracal::Document.
115
220
 
@@ -117,6 +222,9 @@ In the following examples, the variable `docx` is assumed to be an instance of C
117
222
  docx = Caracal::Document.new('example_document.docx')
118
223
  ```
119
224
 
225
+ Most code examples show optional values being passed in a block. As noted above, you may also pass these options as a parameter hash or as a combination of a parameter hash and a block.
226
+
227
+
120
228
  ### File Name
121
229
 
122
230
  The final output document's title can be set at initialization or via the `file_name` method.
@@ -124,7 +232,7 @@ The final output document's title can be set at initialization or via the `file_
124
232
  ```ruby
125
233
  docx = Caracal::Document.new('example_document.docx')
126
234
 
127
- docx.file_name 'example_document.docx'
235
+ docx.file_name 'different_name.docx'
128
236
  ```
129
237
 
130
238
  The current document name can be returned by invoking the `name` method:
@@ -135,56 +243,40 @@ docx.name # => 'example_document.docx'
135
243
 
136
244
  *The default file name is caracal.docx.*
137
245
 
246
+
138
247
  ### Page Size
139
248
 
140
249
  Page dimensions can be set using the `page_size` method. The method accepts two parameters for controlling the width and height of the document.
141
250
 
142
- *Pages default to the United States standard A4, portrait dimensions (8.5in x 11in).*
251
+ *Page size defaults to United States standard A4, portrait dimensions (8.5in x 11in).*
143
252
 
144
253
  ```ruby
145
- # options via block
146
254
  docx.page_size do
147
255
  width 12240 # sets the page width. units in twips.
148
256
  height 15840 # sets the page height. units in twips.
149
257
  end
150
-
151
- # options via hash
152
- docx.page_size width: 12240, height: 15840
153
258
  ```
154
259
 
155
- The `page_size` command will produce the following XML in the `document.xml` file:
260
+ Both the `width` and `height` attributes require positive integer values.
156
261
 
157
- ```xml
158
- <w:sectPr>
159
- <w:pgSz w:w="12240" w:h="15840"/>
160
- </w:sectPr>
161
- ```
162
262
 
163
263
  ### Page Margins
164
264
 
165
- Page margins can be set using the `page_margins` method. The method accepts four parameters for controlling the margins of the document.
265
+ Page margins can be set using the `page_margins` method. The method accepts four parameters for controlling the margins of the document.
266
+
166
267
  *Margins default to 1.0in for all sides.*
167
268
 
168
269
  ```ruby
169
- # options via block
170
270
  docx.page_margins do
171
271
  left 720 # sets the left margin. units in twips.
172
272
  right 720 # sets the right margin. units in twips.
173
273
  top 1440 # sets the top margin. units in twips.
174
274
  bottom 1440 # sets the bottom margin. units in twips.
175
275
  end
176
-
177
- # options via hash
178
- docx.page_margins left: 720, right: 720, top: 1440, bottom: 1440
179
276
  ```
180
277
 
181
- The `page_margins` command above will produce the following XML in the `document.xml` file:
278
+ All attributes require positive integer values. Additionally, the combined size of the margins on either axis cannot exceed the page size on that axis (e.g., the sum of the `left` and `right` values must be less than the `page_width`).
182
279
 
183
- ```xml
184
- <w:sectPr>
185
- <w:pgMar w:left="720" w:right="720" w:top="1440" w:bottom="1440"/>
186
- </w:sectPr>
187
- ```
188
280
 
189
281
  ### Page Breaks
190
282
 
@@ -194,15 +286,6 @@ Page breaks can be added via the `page` method. The method accepts no parameter
194
286
  docx.page # starts a new page.
195
287
  ```
196
288
 
197
- The `page` command will produce the following XML in the `document.xml` file:
198
-
199
- ```xml
200
- <w:p w:rsidP="00000000" w:rsidRPr="00000000" w:rsidR="00000000" w:rsidDel="00000000" w:rsidRDefault="00000000">
201
- <w:r w:rsidRPr="00000000" w:rsidR="00000000" w:rsidDel="00000000">
202
- <w:br w:type="page"/>
203
- </w:r>
204
- </w:p>
205
- ```
206
289
 
207
290
  ### Page Numbers
208
291
 
@@ -211,198 +294,99 @@ Page numbers can be added to the footer via the `page_numbers` method. The meth
211
294
  *Page numbers are turned off by default.*
212
295
 
213
296
  ```ruby
214
- # no options
215
- docx.page_numbers true
216
-
217
- # options via block
218
297
  docx.page_numbers true do
219
- align :right # controls text alignment. defaults to :center.
298
+ align :right # sets the alignment. accepts :left, :center, and :right.
220
299
  end
221
-
222
- # options via hash
223
- docx.page_numbers true, align: :right
224
- ```
225
-
226
- The default command will produce the following `footer.xml` file contents.
227
-
228
- ```xml
229
- <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
230
- <w:ftr xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml" xmlns:sl="http://schemas.openxmlformats.org/schemaLibrary/2006/main" xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture" xmlns:c="http://schemas.openxmlformats.org/drawingml/2006/chart" xmlns:lc="http://schemas.openxmlformats.org/drawingml/2006/lockedCanvas" xmlns:dgm="http://schemas.openxmlformats.org/drawingml/2006/diagram">
231
- <w:p w:rsidP="00000000" w:rsidRPr="00000000" w:rsidR="00000000" w:rsidDel="00000000" w:rsidRDefault="00000000">
232
- <w:pPr>
233
- <w:contextualSpacing w:val="0"/>
234
- <w:jc w:val="center"/>
235
- </w:pPr>
236
- <w:fldSimple w:dirty="0" w:instr="PAGE" w:fldLock="0">
237
- <w:r w:rsidRPr="00000000" w:rsidR="00000000" w:rsidDel="00000000">
238
- <w:rPr/>
239
- </w:r>
240
- </w:fldSimple>
241
- <w:r w:rsidRPr="00000000" w:rsidR="00000000" w:rsidDel="00000000">
242
- <w:rPr>
243
- <w:rtl w:val="0"/>
244
- </w:rPr>
245
- </w:r>
246
- </w:p>
247
- </w:ftr>
248
300
  ```
249
301
 
250
- *It will also automatically add the correct notation to the `w:sectPr` node of the `document.xml` file.*
251
-
252
302
 
253
303
  ### Fonts
254
304
 
255
- Fonts are added to the font table file by calling the `font` method and passing the name of the font. At present, Caracal only supports declaring the primary font name.
305
+ Fonts are added to the font table file by calling the `font` method and passing the name of the font.
306
+
307
+ *At present, Caracal only supports declaring the primary font name.
256
308
 
257
309
  ```ruby
258
- docx.font name: 'Arial'
259
310
  docx.font do
260
311
  name 'Droid Serif'
261
312
  end
262
313
  ```
263
314
 
264
- These commands will produce the following `fontTable.xml` file contents:
265
-
266
- ```xml
267
- <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
268
- <w:fonts xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml" xmlns:sl="http://schemas.openxmlformats.org/schemaLibrary/2006/main" xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture" xmlns:c="http://schemas.openxmlformats.org/drawingml/2006/chart" xmlns:lc="http://schemas.openxmlformats.org/drawingml/2006/lockedCanvas" xmlns:dgm="http://schemas.openxmlformats.org/drawingml/2006/diagram">
269
- <w:font w:name="Arial"/>
270
- <w:font w:name="Droid Serif"/>
271
- </w:fonts>
272
- ```
273
315
 
274
316
  ### Styles
275
317
 
276
- Style classes can be added using the `style` method. The method accepts several optional parameters to control the rendering of text using the style.
318
+ Paragraph style classes can be defined using the `style` method. The method accepts several optional parameters to control the rendering of text using the style.
277
319
 
278
320
  ```ruby
279
- # options via block
280
321
  docx.style do
281
- type :paragraph # :paragraph or :table
282
322
  id 'Heading1' # sets the internal identifier for the style.
283
- name 'heading 1' # set the friendly name of the style.
284
- color '333333' # sets the text color. values in hex RGB.
285
- font 'Droid Serif' # sets the font family.
286
- size 28 # set the font size. units in half points.
323
+ name 'heading 1' # sets the friendly name of the style.
324
+ font 'Palantino' # sets the font family.
325
+ color '333333' # sets the text color. accepts hex RGB.
326
+ size 28 # sets the font size. units in half points.
287
327
  bold false # sets the font weight.
288
328
  italic false # sets the font style.
289
- underline false # sets whether or not to underline the text.
329
+ underline false # sets whether or not to underline the text.
290
330
  align :left # sets the alignment. accepts :left, :center, :right, and :both.
331
+ line 360 # sets the line height. units in twips.
291
332
  top 100 # sets the spacing above the paragraph. units in twips.
292
- bottom 0 # sets the spacing below the paragraph. units in twips.
293
- spacing 360 # sets the spacing between lines. units in twips.
294
- end
333
+ bottom 0 # sets the spacing below the paragraph. units in twips.end
295
334
  ```
296
335
 
297
- The `style` command above would produce the following XML:
298
- ```xml
299
- <w:style w:styleId="Heading1" w:type="paragraph">
300
- <w:name w:val="heading 1"/>
301
- <w:basedOn w:val="Normal"/>
302
- <w:next w:val="Normal"/>
303
- <w:pPr>
304
- <w:keepNext w:val="0"/>
305
- <w:keepLines w:val="0"/>
306
- <w:widowControl w:val="0"/>
307
- <w:contextualSpacing w:val="1"/>
308
- </w:pPr>
309
- <w:rPr>
310
- <w:rFonts w:cs="Droid Serif" w:hAnsi="Droid Serif" w:eastAsia="Droid Serif" w:ascii="Droid Serif"/>
311
- <w:sz w:val="28"/>
312
- </w:rPr>
313
- </w:style>
314
- ```
336
+ Caracal establishes a standard set of default styles for every document. Default styles can be overridden by issuing a `style` command referencing an existing id. Default style ids are:
337
+
338
+ * Normal
339
+ * Title
340
+ * Subtitle
341
+ * Heading1
342
+ * Heading2
343
+ * Heading3
344
+ * Heading4
345
+ * Heading5
346
+ * Heading6
347
+
315
348
 
316
349
  ### Paragraphs
317
350
 
318
- Text can be added using the `p` method. The `p` either takes a string and a `class` option or a block of `text`-like commands.
351
+ Paragrpah text can be added using the `p` method. The method accepts several optional parameters for controlling the style and behavior of the paragrpah.
319
352
 
320
- Text within a `p` block can be further defined using the `text` and `link` methods. The `text` method takes a text string and the optional parameters `style`, `color`, `size`, `bold`, `italic`, and `underline`. See below for details on the `link` method.
353
+ In its simple form, a paragraph accepts a text string and formatting options.
321
354
 
322
355
  ```ruby
323
- docx.p 'some text', style: 'my_style'
324
-
325
- docx.p do
326
- text 'Here is a sentence with a ', style: 'my_style'
327
- link 'link', 'https://www.example.com'
328
- text ' to something awesome', color: '555555', size: 16, bold: true, italic: true, underline: true
356
+ docx.p 'Sample text.'
357
+
358
+ docx.p 'Sample text.', style: 'custom_style'
359
+
360
+ docx.p 'Sample text.' do
361
+ style 'custom_style' # sets the paragraph style. generally used at the exclusion of other attributes.
362
+ align :left # sewts the alignment. accepts :left, :center, :right, and :both.
363
+ color '333333' # sets the font color.
364
+ size 32 # sets the font size. units in 1/2 points.
365
+ bold true # sets whether or not to render the text with a bold weight.
366
+ italic false # sets whether or not render the text in italic style.
367
+ underline false # sets whether or not to underline the text.
329
368
  end
330
369
  ```
331
370
 
332
-
333
- A `p` block might yield the following XML:
334
-
335
- ```xml
336
- <w:p w:rsidP="00000000" w:rsidRPr="00000000" w:rsidR="00000000" w:rsidDel="00000000" w:rsidRDefault="00000000">
337
- <w:pPr>
338
- <w:contextualSpacing w:val="0"/>
339
- </w:pPr>
340
- <w:r w:rsidRPr="00000000" w:rsidR="00000000" w:rsidDel="00000000">
341
- <w:rPr>
342
- <w:rtl w:val="0"/>
343
- </w:rPr>
344
- <w:t xml:space="preserve">Here is a sentence with a </w:t>
345
- </w:r>
346
- <w:hyperlink r:id="rId6">
347
- <w:r w:rsidRPr="00000000" w:rsidR="00000000" w:rsidDel="00000000">
348
- <w:rPr>
349
- <w:color w:val="1155cc"/>
350
- <w:u w:val="single"/>
351
- <w:rtl w:val="0"/>
352
- </w:rPr>
353
- <w:t xml:space="preserve">link</w:t>
354
- </w:r>
355
- </w:hyperlink>
356
- <w:r w:rsidRPr="00000000" w:rsidR="00000000" w:rsidDel="00000000">
357
- <w:rPr>
358
- <w:b w:val="1"/>
359
- <w:rtl w:val="0"/>
360
- </w:rPr>
361
- <w:t xml:space="preserve"> to something awesome.</w:t>
362
- </w:r>
363
- </w:p>
364
- ```
365
-
366
- ### Headers
367
-
368
- Headers can be added using the `h1`, `h2`, etc. methods. Text within a header block can be further defined using the `text` method.
369
-
370
- *Ultimately, headers are just paragraphs that use header styles.*
371
+ More complex paragraph runs can be accomplished by using the `text` method instead the paragraph's block.
371
372
 
372
373
  ```ruby
373
- docx.h3 'Heading 3'
374
+ docx.p do
375
+ text 'Here is a sentence with a ', style: 'custom_style'
376
+ link 'link', 'https://www.example.com'
377
+ text ' to something awesome', color: '555555', size: 32, bold: true, italic: true, underline: true
378
+ text '.'
379
+ end
374
380
  ```
375
381
 
376
- The `h3` block above will yield the following XML:
377
-
378
- ```xml
379
- <w:p w:rsidP="00000000" w:rsidRPr="00000000" w:rsidR="00000000" w:rsidDel="00000000" w:rsidRDefault="00000000">
380
- <w:pPr>
381
- <w:pStyle w:val="Heading3"/>
382
- <w:contextualSpacing w:val="0"/>
383
- </w:pPr>
384
- <w:r w:rsidRPr="00000000" w:rsidR="00000000" w:rsidDel="00000000">
385
- <w:rPr>
386
- <w:rtl w:val="0"/>
387
- </w:rPr>
388
- <w:t xml:space="preserve">Heading 3</w:t>
389
- </w:r>
390
- </w:p>
391
- ```
392
382
 
393
383
  ### Links
394
384
 
395
- Links can be added inside paragraphs by using the `link` method. The method accepts several optional parameters for controlling the style and behavior of the rule.
385
+ Links can be added inside paragraphs using the `link` method. The method accepts several optional parameters for controlling the style and behavior of the rule.
396
386
 
397
387
  *At present, all links are assumed to be external.*
398
388
 
399
389
  ```ruby
400
- # no options
401
- docx.p do
402
- link 'Example Text', 'https://wwww.example.com'
403
- end
404
-
405
- # options via block
406
390
  p do
407
391
  link 'Example Text', 'https://wwww.example.com' do
408
392
  style 'my_style' # sets the style class. defaults to nil.
@@ -413,581 +397,229 @@ p do
413
397
  underline true # sets whether or not the text will be underlined. defaults to true.
414
398
  end
415
399
  end
416
-
417
- # options via hash
418
- p do
419
- link 'Example Text', 'https://wwww.example.com', color: '0000ff', underline: false
420
- end
421
- ```
422
-
423
- The `link` command with default properties will produce the following XML output:
424
-
425
- ```xml
426
- <w:hyperlink r:id="rId1">
427
- <w:r w:rsidRPr="00000000" w:rsidR="00000000" w:rsidDel="00000000">
428
- <w:rPr>
429
- <w:color w:val="1155cc"/>
430
- <w:u w:val="single"/>
431
- <w:rtl w:val="0"/>
432
- </w:rPr>
433
- <w:t xml:space="preserve">Example Text</w:t>
434
- </w:r>
435
- </w:hyperlink>
436
400
  ```
437
401
 
438
- *Caracal will automatically generate the relationship entries required by the OpenXML standard.*
439
402
 
440
- ```xml
441
- <Relationship Target="https://www.example.com" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink" TargetMode="External" Id="rId1"/>
442
- ```
443
-
444
- ### Images
403
+ ### Headings
445
404
 
446
- Images can be added by using the `img` method. The method accepts several optional parameters for controlling the style and placement of the asset.
405
+ Headings can be added using the `h1`, `h2`, `h3`, `h4`, `h5`, and `h6` methods. Headings are simply paragraph commands with a specific style set, so anything you can do with a paragraph is available to a heading.
447
406
 
448
407
  ```ruby
449
- # options via block
450
- docx.img image_url('example.png') do
451
- width 396 # sets the image width. units specified in pixels.
452
- height 216 # sets the image height. units specified in pixels.
453
- align :right # controls the justification of the image. default is :left.
454
- top 10 # sets the top margin. units specified in pixels.
455
- bottom 10 # sets the bottom margin. units specified in pixels.
456
- left 10 # sets the left margin. units specified in pixels.
457
- right 10 # sets the right margin. units specified in pixels.
458
- end
459
-
460
- # options via hash
461
- docx.img image_url('example.png'), width: 396, height: 216, align: :right
462
- ```
408
+ docx.h1 'Heading'
463
409
 
464
- The `img` command with default properties will produce the following XML output:
465
-
466
- ```xml
467
- <w:p w:rsidP="00000000" w:rsidRPr="00000000" w:rsidR="00000000" w:rsidDel="00000000" w:rsidRDefault="00000000">
468
- <w:pPr>
469
- <w:spacing w:lineRule="auto" w:line="276"/>
470
- <w:contextualSpacing w:val="0"/>
471
- <w:jc w:val="right"/>
472
- <w:rPr/>
473
- </w:pPr>
474
- <w:r w:rsidRPr="00000000" w:rsidR="00000000" w:rsidDel="00000000">
475
- <w:drawing>
476
- <wp:inline distR="114300" distT="114300" distB="114300" distL="114300">
477
- <wp:extent cy="2743200" cx="5029200"/>
478
- <wp:effectExtent t="0" b="0" r="0" l="0"/>
479
- <wp:docPr id="1" name="image00.png"/>
480
- <a:graphic>
481
- <a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture">
482
- <pic:pic>
483
- <pic:nvPicPr>
484
- <pic:cNvPr id="0" name="image00.png"/>
485
- <pic:cNvPicPr preferRelativeResize="0"/>
486
- </pic:nvPicPr>
487
- <pic:blipFill>
488
- <a:blip r:embed="rId5"/>
489
- <a:srcRect t="0" b="0" r="0" l="0"/>
490
- <a:stretch>
491
- <a:fillRect/>
492
- </a:stretch>
493
- </pic:blipFill>
494
- <pic:spPr>
495
- <a:xfrm>
496
- <a:ext cy="2743200" cx="5029200"/>
497
- </a:xfrm>
498
- <a:prstGeom prst="rect"/>
499
- <a:ln/>
500
- </pic:spPr>
501
- </pic:pic>
502
- </a:graphicData>
503
- </a:graphic>
504
- </wp:inline>
505
- </w:drawing>
506
- </w:r>
507
- <w:r w:rsidRPr="00000000" w:rsidR="00000000" w:rsidDel="00000000">
508
- <w:rPr>
509
- <w:rtl w:val="0"/>
510
- </w:rPr>
511
- </w:r>
512
- </w:p>
410
+ docx.h2 do
411
+ text 'Heading with a '
412
+ link 'Link', 'http://www.google.com'
413
+ text '.'
414
+ end
513
415
  ```
514
416
 
515
- *Caracal will automatically generate the relationship entries required by the OpenXML standard.*
516
-
517
- ```xml
518
- <Relationship Target="media/image00.png" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Id="rId5"/>
519
- ```
520
417
 
521
418
  ### Rules
522
419
 
523
420
  Horizontal rules can be added using the `hr` method. The method accepts several optional parameters for controlling the style of the rule.
524
421
 
525
422
  ```ruby
526
- # no options
527
- docx.hr # defaults to a thin, single line.
528
-
529
- # options via block
530
423
  docx.hr do
531
- color '333333' # controls the color of the line. defaults to auto.
532
- line :double # controls the line style (single or double). defaults to single.
533
- size 8 # controls the thickness of the line. units in 1/8 points. defaults to 4.
534
- spacing 4 # controls the spacing around the line. units in points. defaults to 1.
424
+ color '333333' # sets the color of the line. defaults to auto.
425
+ line :double # sets the line style (single or double). defaults to single.
426
+ size 8 # sets the thickness of the line. units in 1/8 points. defaults to 4.
427
+ spacing 4 # sets the spacing around the line. units in 1/8 points. defaults to 1.
535
428
  end
536
-
537
- # options via hash
538
- docx.hr color: '333333', line: :double, size: 8, spacing: 2
539
429
  ```
540
430
 
541
- The `hr` command with default properties will produce the following XML output:
542
431
 
543
- ```xml
544
- <w:p w:rsidP="00000000" w:rsidRPr="00000000" w:rsidR="00000000" w:rsidDel="00000000" w:rsidRDefault="00000000">
545
- <w:pPr>
546
- <w:pBdr>
547
- <w:top w:color="auto" w:space="1" w:val="single" w:sz="4"/>
548
- </w:pBdr>
549
- </w:pPr>
550
- </w:p>
432
+ ### Line Breaks
433
+
434
+ Line breaks can be added via the `br` method. The method accepts no parameters.
435
+
436
+ ```ruby
437
+ docx.br # adds a blank line using the default paragrpah style.
551
438
  ```
552
439
 
553
- ### Ordered Lists
554
440
 
555
- Ordered lists can be added using the `ol` and `li` methods. The `li` method substantially follows the same rules as the the `p` method; here, simpler examples are demonstrated.
441
+ ### Lists
442
+
443
+ Ordered lists can be added using the `ol` and `li` methods. The `li` method substantially follows the same rules as the the `p` method.
556
444
 
557
445
  ```ruby
558
446
  docx.ol do
559
447
  li 'First item'
560
- li 'Second item'
448
+ li do
449
+ text 'Second item with a '
450
+ link 'link', 'http://www.google.com'
451
+ text '.'
452
+ end
561
453
  end
562
454
  ```
563
455
 
564
- The `ol` and `li` commands with default properties will produce the following XML (assuming the ordered list styles have the abstractNumId=2 in the `numbering.xml` file).
565
-
566
- ```xml
567
- <w:p w:rsidP="00000000" w:rsidRPr="00000000" w:rsidR="00000000" w:rsidDel="00000000" w:rsidRDefault="00000000">
568
- <w:pPr>
569
- <w:numPr>
570
- <w:ilvl w:val="0"/>
571
- <w:numId w:val="2"/>
572
- </w:numPr>
573
- <w:ind w:left="720" w:hanging="359"/>
574
- <w:contextualSpacing w:val="1"/>
575
- <w:rPr>
576
- <w:u w:val="none"/>
577
- </w:rPr>
578
- </w:pPr>
579
- <w:r w:rsidRPr="00000000" w:rsidR="00000000" w:rsidDel="00000000">
580
- <w:rPr>
581
- <w:rtl w:val="0"/>
582
- </w:rPr>
583
- <w:t xml:space="preserve">First item</w:t>
584
- </w:r>
585
- </w:p>
586
- <w:p w:rsidP="00000000" w:rsidRPr="00000000" w:rsidR="00000000" w:rsidDel="00000000" w:rsidRDefault="00000000">
587
- <w:pPr>
588
- <w:numPr>
589
- <w:ilvl w:val="0"/>
590
- <w:numId w:val="2"/>
591
- </w:numPr>
592
- <w:ind w:left="720" w:hanging="359"/>
593
- <w:contextualSpacing w:val="1"/>
594
- <w:rPr>
595
- <w:u w:val="none"/>
596
- </w:rPr>
597
- </w:pPr>
598
- <w:r w:rsidRPr="00000000" w:rsidR="00000000" w:rsidDel="00000000">
599
- <w:rPr>
600
- <w:rtl w:val="0"/>
601
- </w:rPr>
602
- <w:t xml:space="preserve">Second item</w:t>
603
- </w:r>
604
- </w:p>
605
- ```
456
+ Similarly, unordered lists can be added using the `ul` and `li` methods.
606
457
 
607
- ### Unordered Lists
458
+ ```ruby
459
+ docx.ul do
460
+ li 'First item'
461
+ li do
462
+ text 'Second item with a '
463
+ link 'link', 'http://www.google.com'
464
+ text '.'
465
+ end
466
+ end
467
+ ```
608
468
 
609
- Unordered lists can be added using the `ul` and `li` methods. The `li` method substantially follows the same rules as the the `p` method; here, simpler examples are demonstrated.
469
+ Lists can nested as many levels deep as you wish and mixed in any combination.
610
470
 
611
471
  ```ruby
612
472
  docx.ul do
613
473
  li 'First item'
614
- li 'Second item'
474
+ li 'Second item' do
475
+ ol do
476
+ li 'SubItem 1'
477
+ li 'SubItem 2' do
478
+ ol do
479
+ li 'SubSubItem'
480
+ end
481
+ end
482
+ end
483
+ end
615
484
  end
616
485
  ```
617
486
 
618
- The `ul` and `li` commands with default properties will produce the following XML (assuming the ordered list styles have the abstractNumId=1 in the `numbering.xml` file).
619
-
620
- ```xml
621
- <w:p w:rsidP="00000000" w:rsidRPr="00000000" w:rsidR="00000000" w:rsidDel="00000000" w:rsidRDefault="00000000">
622
- <w:pPr>
623
- <w:numPr>
624
- <w:ilvl w:val="0"/>
625
- <w:numId w:val="1"/>
626
- </w:numPr>
627
- <w:ind w:left="720" w:hanging="359"/>
628
- <w:contextualSpacing w:val="1"/>
629
- <w:rPr>
630
- <w:u w:val="none"/>
631
- </w:rPr>
632
- </w:pPr>
633
- <w:r w:rsidRPr="00000000" w:rsidR="00000000" w:rsidDel="00000000">
634
- <w:rPr>
635
- <w:rtl w:val="0"/>
636
- </w:rPr>
637
- <w:t xml:space="preserve">First item</w:t>
638
- </w:r>
639
- </w:p>
640
- <w:p w:rsidP="00000000" w:rsidRPr="00000000" w:rsidR="00000000" w:rsidDel="00000000" w:rsidRDefault="00000000">
641
- <w:pPr>
642
- <w:numPr>
643
- <w:ilvl w:val="0"/>
644
- <w:numId w:val="1"/>
645
- </w:numPr>
646
- <w:ind w:left="720" w:hanging="359"/>
647
- <w:contextualSpacing w:val="1"/>
648
- <w:rPr>
649
- <w:u w:val="none"/>
650
- </w:rPr>
651
- </w:pPr>
652
- <w:r w:rsidRPr="00000000" w:rsidR="00000000" w:rsidDel="00000000">
653
- <w:rPr>
654
- <w:rtl w:val="0"/>
655
- </w:rPr>
656
- <w:t xml:space="preserve">Second item</w:t>
657
- </w:r>
658
- </w:p>
487
+
488
+ ### List Styles
489
+
490
+ List styles can be defined using the `list_style` command. The method accepts several optional parameters to control the rendering of list items using the style.
491
+
492
+ *Caracal will automatically define 9 levels of default styles for both ordered and unordered lists.*
493
+
494
+ ```ruby
495
+ docx.list_style do
496
+ type :ordered # sets the type of list. accepts :ordered or :unordered.
497
+ level 2 # sets the nesting level. 0-based index.
498
+ format 'decimal' # sets the list style. see OOXML docs for details.
499
+ value '%3.' # sets the value of the list item marker. see OOXML docs for details.
500
+ align :left # sets the alignment. accepts :left, :center: and :right. defaults to :left.
501
+ indent 400 # sets the indention of the marker from the margin. units in twips.
502
+ left 800 # sets the indention of the text from the margin. units in twips.
503
+ start 2 # sets the number at which item counts begin. defaults to 1.
504
+ restart 1 # sets the level that triggers a reset of numbers at this level. 1-based index. 0 means numbers never reset. defaults to 1.
505
+ end
506
+ ```
507
+
508
+
509
+ ### Images
510
+
511
+ Images can be added by using the `img` method. The method accepts several optional parameters for controlling the style and placement of the asset.
512
+
513
+ *Caracal will automatically embed the image in the Word document.*
514
+
515
+ ```ruby
516
+ docx.img image_url('example.png') do
517
+ width 396 # sets the image width. units specified in pixels.
518
+ height 216 # sets the image height. units specified in pixels.
519
+ align :right # controls the justification of the image. default is :left.
520
+ top 10 # sets the top margin. units specified in pixels.
521
+ bottom 10 # sets the bottom margin. units specified in pixels.
522
+ left 10 # sets the left margin. units specified in pixels.
523
+ right 10 # sets the right margin. units specified in pixels.
524
+ end
659
525
  ```
660
526
 
527
+
661
528
  ### Tables
662
529
 
663
530
  Tables can be added using the `table` method. The method accepts several optional paramters to control the layout and style of the table cells.
664
531
 
532
+ The `table` command accepts data in the form of a two-dimensional arrays. This corresponds to rows and column cells within those rows. Each array item can be a string, a Hash of options, a Proc (which will be passed as a block), or a `TableCellModel`. The command will normalize all array contents into a two-dimensional array of `TableCellModel` instances.
533
+
665
534
  ```ruby
666
- table data, border: 8 do
667
- cell_style rows(0), background_color: '4a86e8', bold: true
535
+ docx.table [['Header 1','Header 2'],['Cell 1', 'Cell 2']] do
536
+ border_color '666666' # sets the border color. defaults to 'auto'.
537
+ border_line :single # sets the border style. defaults to :single. see OOXML docs for details.
538
+ border_size 4 # sets the border width. defaults to 0. units in twips.
539
+ border_spacing 4 # sets the spacing around the border. deaults to 0. units in twips.
668
540
  end
669
541
  ```
670
542
 
671
- Given the a data structure with two rows and five columns, the `table` method would produce the following XML:
672
-
673
- ```xml
674
- <w:tbl>
675
- <w:tblPr>
676
- <w:tblStyle w:val="KixTable1"/>
677
- <w:bidiVisual w:val="0"/>
678
- <w:tblW w:w="10800.0" w:type="dxa"/>
679
- <w:jc w:val="left"/>
680
- <w:tblBorders>
681
- <w:top w:color="000000" w:space="0" w:val="single" w:sz="8"/>
682
- <w:left w:color="000000" w:space="0" w:val="single" w:sz="8"/>
683
- <w:bottom w:color="000000" w:space="0" w:val="single" w:sz="8"/>
684
- <w:right w:color="000000" w:space="0" w:val="single" w:sz="8"/>
685
- <w:insideH w:color="000000" w:space="0" w:val="single" w:sz="8"/>
686
- <w:insideV w:color="000000" w:space="0" w:val="single" w:sz="8"/>
687
- </w:tblBorders>
688
- <w:tblLayout w:type="fixed"/>
689
- <w:tblLook w:val="0600"/>
690
- </w:tblPr>
691
- <w:tblGrid>
692
- <w:gridCol w:w="2160"/>
693
- <w:gridCol w:w="2160"/>
694
- <w:gridCol w:w="2160"/>
695
- <w:gridCol w:w="2160"/>
696
- <w:gridCol w:w="2160"/>
697
- <w:tblGridChange w:id="0">
698
- <w:tblGrid>
699
- <w:gridCol w:w="2160"/>
700
- <w:gridCol w:w="2160"/>
701
- <w:gridCol w:w="2160"/>
702
- <w:gridCol w:w="2160"/>
703
- <w:gridCol w:w="2160"/>
704
- </w:tblGrid>
705
- </w:tblGridChange>
706
- </w:tblGrid>
707
- <w:tr>
708
- <w:tc>
709
- <w:tcPr>
710
- <w:shd w:fill="4a86e8"/>
711
- <w:tcMar>
712
- <w:top w:w="100.0" w:type="dxa"/>
713
- <w:left w:w="100.0" w:type="dxa"/>
714
- <w:bottom w:w="100.0" w:type="dxa"/>
715
- <w:right w:w="100.0" w:type="dxa"/>
716
- </w:tcMar>
717
- </w:tcPr>
718
- <w:p w:rsidP="00000000" w:rsidRPr="00000000" w:rsidR="00000000" w:rsidDel="00000000" w:rsidRDefault="00000000">
719
- <w:pPr>
720
- <w:spacing w:lineRule="auto" w:after="0" w:line="240" w:before="0"/>
721
- <w:ind w:left="0" w:firstLine="0"/>
722
- <w:contextualSpacing w:val="0"/>
723
- </w:pPr>
724
- <w:r w:rsidRPr="00000000" w:rsidR="00000000" w:rsidDel="00000000">
725
- <w:rPr>
726
- <w:b w:val="1"/>
727
- <w:color w:val="ffffff"/>
728
- <w:rtl w:val="0"/>
729
- </w:rPr>
730
- <w:t xml:space="preserve">Field</w:t>
731
- </w:r>
732
- </w:p>
733
- </w:tc>
734
- <w:tc>
735
- <w:tcPr>
736
- <w:shd w:fill="4a86e8"/>
737
- <w:tcMar>
738
- <w:top w:w="100.0" w:type="dxa"/>
739
- <w:left w:w="100.0" w:type="dxa"/>
740
- <w:bottom w:w="100.0" w:type="dxa"/>
741
- <w:right w:w="100.0" w:type="dxa"/>
742
- </w:tcMar>
743
- </w:tcPr>
744
- <w:p w:rsidP="00000000" w:rsidRPr="00000000" w:rsidR="00000000" w:rsidDel="00000000" w:rsidRDefault="00000000">
745
- <w:pPr>
746
- <w:spacing w:lineRule="auto" w:after="0" w:line="240" w:before="0"/>
747
- <w:ind w:left="0" w:firstLine="0"/>
748
- <w:contextualSpacing w:val="0"/>
749
- </w:pPr>
750
- <w:r w:rsidRPr="00000000" w:rsidR="00000000" w:rsidDel="00000000">
751
- <w:rPr>
752
- <w:b w:val="1"/>
753
- <w:color w:val="ffffff"/>
754
- <w:rtl w:val="0"/>
755
- </w:rPr>
756
- <w:t xml:space="preserve">Response</w:t>
757
- </w:r>
758
- </w:p>
759
- </w:tc>
760
- <w:tc>
761
- <w:tcPr>
762
- <w:shd w:fill="4a86e8"/>
763
- <w:tcMar>
764
- <w:top w:w="100.0" w:type="dxa"/>
765
- <w:left w:w="100.0" w:type="dxa"/>
766
- <w:bottom w:w="100.0" w:type="dxa"/>
767
- <w:right w:w="100.0" w:type="dxa"/>
768
- </w:tcMar>
769
- </w:tcPr>
770
- <w:p w:rsidP="00000000" w:rsidRPr="00000000" w:rsidR="00000000" w:rsidDel="00000000" w:rsidRDefault="00000000">
771
- <w:pPr>
772
- <w:spacing w:lineRule="auto" w:after="0" w:line="240" w:before="0"/>
773
- <w:ind w:left="0" w:firstLine="0"/>
774
- <w:contextualSpacing w:val="0"/>
775
- </w:pPr>
776
- <w:r w:rsidRPr="00000000" w:rsidR="00000000" w:rsidDel="00000000">
777
- <w:rPr>
778
- <w:b w:val="1"/>
779
- <w:color w:val="ffffff"/>
780
- <w:rtl w:val="0"/>
781
- </w:rPr>
782
- <w:t xml:space="preserve">Perf. Quality</w:t>
783
- </w:r>
784
- </w:p>
785
- </w:tc>
786
- <w:tc>
787
- <w:tcPr>
788
- <w:shd w:fill="4a86e8"/>
789
- <w:tcMar>
790
- <w:top w:w="100.0" w:type="dxa"/>
791
- <w:left w:w="100.0" w:type="dxa"/>
792
- <w:bottom w:w="100.0" w:type="dxa"/>
793
- <w:right w:w="100.0" w:type="dxa"/>
794
- </w:tcMar>
795
- </w:tcPr>
796
- <w:p w:rsidP="00000000" w:rsidRPr="00000000" w:rsidR="00000000" w:rsidDel="00000000" w:rsidRDefault="00000000">
797
- <w:pPr>
798
- <w:spacing w:lineRule="auto" w:after="0" w:line="240" w:before="0"/>
799
- <w:ind w:left="0" w:firstLine="0"/>
800
- <w:contextualSpacing w:val="0"/>
801
- </w:pPr>
802
- <w:r w:rsidRPr="00000000" w:rsidR="00000000" w:rsidDel="00000000">
803
- <w:rPr>
804
- <w:b w:val="1"/>
805
- <w:color w:val="ffffff"/>
806
- <w:rtl w:val="0"/>
807
- </w:rPr>
808
- <w:t xml:space="preserve">Data Quality</w:t>
809
- </w:r>
810
- </w:p>
811
- </w:tc>
812
- <w:tc>
813
- <w:tcPr>
814
- <w:shd w:fill="4a86e8"/>
815
- <w:tcMar>
816
- <w:top w:w="100.0" w:type="dxa"/>
817
- <w:left w:w="100.0" w:type="dxa"/>
818
- <w:bottom w:w="100.0" w:type="dxa"/>
819
- <w:right w:w="100.0" w:type="dxa"/>
820
- </w:tcMar>
821
- </w:tcPr>
822
- <w:p w:rsidP="00000000" w:rsidRPr="00000000" w:rsidR="00000000" w:rsidDel="00000000" w:rsidRDefault="00000000">
823
- <w:pPr>
824
- <w:spacing w:lineRule="auto" w:after="0" w:line="240" w:before="0"/>
825
- <w:ind w:left="0" w:firstLine="0"/>
826
- <w:contextualSpacing w:val="0"/>
827
- </w:pPr>
828
- <w:r w:rsidRPr="00000000" w:rsidR="00000000" w:rsidDel="00000000">
829
- <w:rPr>
830
- <w:b w:val="1"/>
831
- <w:color w:val="ffffff"/>
832
- <w:rtl w:val="0"/>
833
- </w:rPr>
834
- <w:t xml:space="preserve">State</w:t>
835
- </w:r>
836
- </w:p>
837
- </w:tc>
838
- </w:tr>
839
- <w:tr>
840
- <w:tc>
841
- <w:tcPr>
842
- <w:tcMar>
843
- <w:top w:w="100.0" w:type="dxa"/>
844
- <w:left w:w="100.0" w:type="dxa"/>
845
- <w:bottom w:w="100.0" w:type="dxa"/>
846
- <w:right w:w="100.0" w:type="dxa"/>
847
- </w:tcMar>
848
- </w:tcPr>
849
- <w:p w:rsidP="00000000" w:rsidRPr="00000000" w:rsidR="00000000" w:rsidDel="00000000" w:rsidRDefault="00000000">
850
- <w:pPr>
851
- <w:spacing w:lineRule="auto" w:after="0" w:line="240" w:before="0"/>
852
- <w:ind w:left="0" w:firstLine="0"/>
853
- <w:contextualSpacing w:val="0"/>
854
- </w:pPr>
855
- <w:r w:rsidRPr="00000000" w:rsidR="00000000" w:rsidDel="00000000">
856
- <w:rPr>
857
- <w:rtl w:val="0"/>
858
- </w:rPr>
859
- <w:t xml:space="preserve">After-Hours trading</w:t>
860
- </w:r>
861
- </w:p>
862
- </w:tc>
863
- <w:tc>
864
- <w:tcPr>
865
- <w:tcMar>
866
- <w:top w:w="100.0" w:type="dxa"/>
867
- <w:left w:w="100.0" w:type="dxa"/>
868
- <w:bottom w:w="100.0" w:type="dxa"/>
869
- <w:right w:w="100.0" w:type="dxa"/>
870
- </w:tcMar>
871
- </w:tcPr>
872
- <w:p w:rsidP="00000000" w:rsidRPr="00000000" w:rsidR="00000000" w:rsidDel="00000000" w:rsidRDefault="00000000">
873
- <w:pPr>
874
- <w:spacing w:lineRule="auto" w:after="0" w:line="240" w:before="0"/>
875
- <w:ind w:left="0" w:firstLine="0"/>
876
- <w:contextualSpacing w:val="0"/>
877
- </w:pPr>
878
- <w:r w:rsidRPr="00000000" w:rsidR="00000000" w:rsidDel="00000000">
879
- <w:rPr>
880
- <w:rtl w:val="0"/>
881
- </w:rPr>
882
- <w:t xml:space="preserve">Yes</w:t>
883
- </w:r>
884
- </w:p>
885
- </w:tc>
886
- <w:tc>
887
- <w:tcPr>
888
- <w:tcMar>
889
- <w:top w:w="100.0" w:type="dxa"/>
890
- <w:left w:w="100.0" w:type="dxa"/>
891
- <w:bottom w:w="100.0" w:type="dxa"/>
892
- <w:right w:w="100.0" w:type="dxa"/>
893
- </w:tcMar>
894
- </w:tcPr>
895
- <w:p w:rsidP="00000000" w:rsidRPr="00000000" w:rsidR="00000000" w:rsidDel="00000000" w:rsidRDefault="00000000">
896
- <w:pPr>
897
- <w:spacing w:lineRule="auto" w:after="0" w:line="240" w:before="0"/>
898
- <w:ind w:left="0" w:firstLine="0"/>
899
- <w:contextualSpacing w:val="0"/>
900
- </w:pPr>
901
- <w:r w:rsidRPr="00000000" w:rsidR="00000000" w:rsidDel="00000000">
902
- <w:rPr>
903
- <w:rtl w:val="0"/>
904
- </w:rPr>
905
- <w:t xml:space="preserve">B</w:t>
906
- </w:r>
907
- </w:p>
908
- </w:tc>
909
- <w:tc>
910
- <w:tcPr>
911
- <w:tcMar>
912
- <w:top w:w="100.0" w:type="dxa"/>
913
- <w:left w:w="100.0" w:type="dxa"/>
914
- <w:bottom w:w="100.0" w:type="dxa"/>
915
- <w:right w:w="100.0" w:type="dxa"/>
916
- </w:tcMar>
917
- </w:tcPr>
918
- <w:p w:rsidP="00000000" w:rsidRPr="00000000" w:rsidR="00000000" w:rsidDel="00000000" w:rsidRDefault="00000000">
919
- <w:pPr>
920
- <w:spacing w:lineRule="auto" w:after="0" w:line="240" w:before="0"/>
921
- <w:ind w:left="0" w:firstLine="0"/>
922
- <w:contextualSpacing w:val="0"/>
923
- </w:pPr>
924
- <w:r w:rsidRPr="00000000" w:rsidR="00000000" w:rsidDel="00000000">
925
- <w:rPr>
926
- <w:rtl w:val="0"/>
927
- </w:rPr>
928
- <w:t xml:space="preserve">B</w:t>
929
- </w:r>
930
- </w:p>
931
- </w:tc>
932
- <w:tc>
933
- <w:tcPr>
934
- <w:tcMar>
935
- <w:top w:w="100.0" w:type="dxa"/>
936
- <w:left w:w="100.0" w:type="dxa"/>
937
- <w:bottom w:w="100.0" w:type="dxa"/>
938
- <w:right w:w="100.0" w:type="dxa"/>
939
- </w:tcMar>
940
- </w:tcPr>
941
- <w:p w:rsidP="00000000" w:rsidRPr="00000000" w:rsidR="00000000" w:rsidDel="00000000" w:rsidRDefault="00000000">
942
- <w:pPr>
943
- <w:spacing w:lineRule="auto" w:after="0" w:line="240" w:before="0"/>
944
- <w:ind w:left="0" w:firstLine="0"/>
945
- <w:contextualSpacing w:val="0"/>
946
- </w:pPr>
947
- <w:r w:rsidRPr="00000000" w:rsidR="00000000" w:rsidDel="00000000">
948
- <w:rPr>
949
- <w:rtl w:val="0"/>
950
- </w:rPr>
951
- <w:t xml:space="preserve">published</w:t>
952
- </w:r>
953
- </w:p>
954
- </w:tc>
955
- </w:tr>
956
- </w:tbl>
543
+ Table borders can be further styled with position-specific options. Caracal supports styling the top, bottom, left, right, inside horizontal, and inside vertical borders with the `border_top`, `border_bottom`, `border_left`, `border_right`, `border_horizontal`, and `border_vertical`, respectively. Options have the same meaning as those set at the table level.
544
+
545
+ ```ruby
546
+ docx.table data, border_size: 4 do
547
+ border_top do
548
+ color '000000'
549
+ line :double
550
+ size 8
551
+ spacing 2
552
+ end
553
+ end
957
554
  ```
958
555
 
959
- ### Line Breaks
556
+ Table cells can be styles using the `cell_style` method inside the table's block. The method will attempt to apply any specified options against the collection of `TableModelCell` instances provided in the first argument. Any improper options will fail silently.
960
557
 
961
- Line breaks can be added via the `br` method. The method accepts no parameters.
558
+ *As a convenience, the table provides the methods `rows`, `cols`, and `cells` to facilitate building the first argument.*
559
+
560
+ The example will style the first row as a header and establish a fixed width for the first column.
962
561
 
963
562
  ```ruby
964
- docx.br # adds a blank line using the default paragrpah style.
563
+ docx.table [['Header 1','Header 2'],['Cell 1', 'Cell 2']], border_size: 4 do
564
+ cell_style rows[0], background: '3366cc', color: 'ffffff', bold: true
565
+ cell_style cols[0], width: 6000
566
+ end
965
567
  ```
966
568
 
967
- The `br` command will produce the folowing XML:
968
-
969
- ```xml
970
- <w:p w:rsidP="00000000" w:rsidRPr="00000000" w:rsidR="00000000" w:rsidDel="00000000" w:rsidRDefault="00000000">
971
- <w:pPr>
972
- <w:contextualSpacing w:val="0"/>
973
- </w:pPr>
974
- <w:r w:rsidRPr="00000000" w:rsidR="00000000" w:rsidDel="00000000">
975
- <w:rPr>
976
- <w:rtl w:val="0"/>
977
- </w:rPr>
978
- </w:r>
979
- </w:p>
569
+
570
+ ### Table Cells
571
+
572
+ If your table contains more complex data (multiple paragraphs, images, lists, etc.), you will probably want to instantiate your `TableCellModel` instances directly. With the exception of page breaks, table cells can contain anything the document can contain, including another table.
573
+
574
+ ```ruby
575
+ c1 = Caracal::Core::Models:TableCellModel.new do
576
+ background 'cccccc' # sets the background color. defaults to 'ffffff'.
577
+ margins do
578
+ top # sets the top margin. defaults to 0. units in twips.
579
+ bottom # sets the bottom margin. defaults to 0. units in twips.
580
+ left # sets the left margin. defaults to 0. units in twips.
581
+ right # sets the right margin. defaults to 0. units in twips.
582
+ end
583
+
584
+ p 'This is a sentence above an image.'
585
+ br
586
+ img image_url('example.png'), width: 200, height: 100
587
+ end
980
588
  ```
981
589
 
982
590
 
983
- ## Template Rendering
591
+ ### Nested Tables
592
+
593
+ Because table cells can contain anything that can be added to the document, **tables can be nested to achieve whatever layout goals you want to achieve**.
984
594
 
985
- Caracal includes [Tilt](https://github.com/rtomayko/tilt) integration to facilitate its inclusion in other frameworks. Rails integration can be added via the [Caracal-Rails](https://github.com/trade-informatics/caracal-rails) gem.
595
+ ```ruby
596
+ row1 = ['Header 1', 'Header 2', 'Header 3']
597
+ row2 = ['Cell 1', 'Cell 2', 'Cell 3']
598
+ row3 = ['Cell 4', 'Cell 5', 'Cell 6']
599
+ row4 = ['Footer 1', 'Footer 2', 'Footer 3']
600
+ c1 = Caracal::Core::Models::TableCellModel.new margins: { top: 0, bottom: 100, left: 0, right: 200 } do
601
+ table [row1, row2, row3, row4], border_size: 4 do
602
+ cell_style rows[0], bold: true, background: '3366cc', color: 'ffffff'
603
+ cell_style rows[-1], bold: true, background: 'dddddd'
604
+ cell_style cells[3], italic: true, color: 'cc0000'
605
+ cell_style cells, size: 18, margins: { top: 100, bottom: 0, left: 100, right: 100 }
606
+ end
607
+ end
608
+ c2 = Caracal::Core::Models::TableCellModel.new margins: { top: 0, bottom: 100, left: 0, right: 200 } do
609
+ p 'This layout uses nested tables (the outer table has no border) to provide a caption to the table data.'
610
+ end
986
611
 
612
+ docx.table [[c1,c2]] do
613
+ cell_style cols[0], width: 6000
614
+ end
615
+ ```
616
+
617
+
618
+ ## Template Rendering
987
619
 
988
- ## Defaults
620
+ Caracal includes [Tilt](https://github.com/rtomayko/tilt) integration to facilitate its inclusion in other frameworks.
989
621
 
990
- [Unsure how best to handle this without code exploration. Not a critical element for the first version.]
622
+ Rails integration can be added via the [Caracal-Rails](https://github.com/trade-informatics/caracal-rails) gem.
991
623
 
992
624
 
993
625
  ## Contributing