caracal 0.1.0

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.
Files changed (95) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +23 -0
  3. data/Gemfile +3 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +941 -0
  6. data/Rakefile +2 -0
  7. data/caracal.gemspec +27 -0
  8. data/lib/caracal.rb +31 -0
  9. data/lib/caracal/core/file_name.rb +39 -0
  10. data/lib/caracal/core/fonts.rb +75 -0
  11. data/lib/caracal/core/images.rb +37 -0
  12. data/lib/caracal/core/line_breaks.rb +29 -0
  13. data/lib/caracal/core/list_styles.rb +92 -0
  14. data/lib/caracal/core/lists.rb +57 -0
  15. data/lib/caracal/core/models/base_model.rb +51 -0
  16. data/lib/caracal/core/models/border_model.rb +120 -0
  17. data/lib/caracal/core/models/font_model.rb +64 -0
  18. data/lib/caracal/core/models/image_model.rb +118 -0
  19. data/lib/caracal/core/models/line_break_model.rb +15 -0
  20. data/lib/caracal/core/models/link_model.rb +65 -0
  21. data/lib/caracal/core/models/list_item_model.rb +105 -0
  22. data/lib/caracal/core/models/list_model.rb +130 -0
  23. data/lib/caracal/core/models/list_style_model.rb +129 -0
  24. data/lib/caracal/core/models/margin_model.rb +76 -0
  25. data/lib/caracal/core/models/page_break_model.rb +15 -0
  26. data/lib/caracal/core/models/page_number_model.rb +69 -0
  27. data/lib/caracal/core/models/page_size_model.rb +70 -0
  28. data/lib/caracal/core/models/paragraph_model.rb +141 -0
  29. data/lib/caracal/core/models/relationship_model.rb +108 -0
  30. data/lib/caracal/core/models/rule_model.rb +27 -0
  31. data/lib/caracal/core/models/style_model.rb +134 -0
  32. data/lib/caracal/core/models/table_cell_model.rb +155 -0
  33. data/lib/caracal/core/models/table_model.rb +206 -0
  34. data/lib/caracal/core/models/text_model.rb +92 -0
  35. data/lib/caracal/core/page_breaks.rb +29 -0
  36. data/lib/caracal/core/page_numbers.rb +51 -0
  37. data/lib/caracal/core/page_settings.rb +72 -0
  38. data/lib/caracal/core/relationships.rb +90 -0
  39. data/lib/caracal/core/rules.rb +35 -0
  40. data/lib/caracal/core/styles.rb +86 -0
  41. data/lib/caracal/core/tables.rb +41 -0
  42. data/lib/caracal/core/text.rb +73 -0
  43. data/lib/caracal/document.rb +242 -0
  44. data/lib/caracal/errors.rb +23 -0
  45. data/lib/caracal/renderers/app_renderer.rb +41 -0
  46. data/lib/caracal/renderers/content_types_renderer.rb +53 -0
  47. data/lib/caracal/renderers/core_renderer.rb +44 -0
  48. data/lib/caracal/renderers/document_renderer.rb +349 -0
  49. data/lib/caracal/renderers/fonts_renderer.rb +56 -0
  50. data/lib/caracal/renderers/footer_renderer.rb +69 -0
  51. data/lib/caracal/renderers/numbering_renderer.rb +87 -0
  52. data/lib/caracal/renderers/package_relationships_renderer.rb +50 -0
  53. data/lib/caracal/renderers/relationships_renderer.rb +48 -0
  54. data/lib/caracal/renderers/settings_renderer.rb +58 -0
  55. data/lib/caracal/renderers/styles_renderer.rb +163 -0
  56. data/lib/caracal/renderers/xml_renderer.rb +83 -0
  57. data/lib/caracal/version.rb +3 -0
  58. data/lib/tilt/caracal.rb +21 -0
  59. data/spec/lib/caracal/core/file_name_spec.rb +54 -0
  60. data/spec/lib/caracal/core/fonts_spec.rb +119 -0
  61. data/spec/lib/caracal/core/images_spec.rb +25 -0
  62. data/spec/lib/caracal/core/line_breaks_spec.rb +25 -0
  63. data/spec/lib/caracal/core/list_styles_spec.rb +121 -0
  64. data/spec/lib/caracal/core/lists_spec.rb +43 -0
  65. data/spec/lib/caracal/core/models/base_model_spec.rb +38 -0
  66. data/spec/lib/caracal/core/models/border_model_spec.rb +159 -0
  67. data/spec/lib/caracal/core/models/font_model_spec.rb +92 -0
  68. data/spec/lib/caracal/core/models/image_model_spec.rb +192 -0
  69. data/spec/lib/caracal/core/models/line_break_model_spec.rb +21 -0
  70. data/spec/lib/caracal/core/models/link_model_spec.rb +139 -0
  71. data/spec/lib/caracal/core/models/list_item_model_spec.rb +190 -0
  72. data/spec/lib/caracal/core/models/list_model_spec.rb +178 -0
  73. data/spec/lib/caracal/core/models/list_style_model_spec.rb +212 -0
  74. data/spec/lib/caracal/core/models/margin_model_spec.rb +111 -0
  75. data/spec/lib/caracal/core/models/page_break_model_spec.rb +21 -0
  76. data/spec/lib/caracal/core/models/page_number_model_spec.rb +101 -0
  77. data/spec/lib/caracal/core/models/page_size_model_spec.rb +91 -0
  78. data/spec/lib/caracal/core/models/paragraph_model_spec.rb +162 -0
  79. data/spec/lib/caracal/core/models/relationship_model_spec.rb +183 -0
  80. data/spec/lib/caracal/core/models/rule_model_spec.rb +108 -0
  81. data/spec/lib/caracal/core/models/style_model_spec.rb +187 -0
  82. data/spec/lib/caracal/core/models/table_cell_model_spec.rb +221 -0
  83. data/spec/lib/caracal/core/models/table_model_spec.rb +222 -0
  84. data/spec/lib/caracal/core/models/text_model_spec.rb +132 -0
  85. data/spec/lib/caracal/core/page_breaks_spec.rb +25 -0
  86. data/spec/lib/caracal/core/page_numbers_spec.rb +80 -0
  87. data/spec/lib/caracal/core/page_settings_spec.rb +143 -0
  88. data/spec/lib/caracal/core/relationships_spec.rb +119 -0
  89. data/spec/lib/caracal/core/rules_spec.rb +25 -0
  90. data/spec/lib/caracal/core/styles_spec.rb +129 -0
  91. data/spec/lib/caracal/core/tables_spec.rb +25 -0
  92. data/spec/lib/caracal/core/text_spec.rb +52 -0
  93. data/spec/lib/caracal/errors_spec.rb +10 -0
  94. data/spec/spec_helper.rb +8 -0
  95. metadata +245 -0
@@ -0,0 +1,23 @@
1
+ module Caracal
2
+ module Errors
3
+ # This error is raised whenever a model is created with
4
+ # invalid options.
5
+ #
6
+ InvalidModelError = Class.new(StandardError)
7
+
8
+ # This error is raised whenever a table model is passed an
9
+ # invalid data structure.
10
+ #
11
+ InvalidTableDataError = Class.new(StandardError)
12
+
13
+ # This error is raised if the document does not have a default
14
+ # style declared.
15
+ #
16
+ NoDefaultStyleError = Class.new(StandardError)
17
+
18
+ # This error is raised when a class lacks a valid reference to a
19
+ # Caracal document object.
20
+ #
21
+ NoDocumentError = Class.new(StandardError)
22
+ end
23
+ end
@@ -0,0 +1,41 @@
1
+ require 'nokogiri'
2
+
3
+ require 'caracal/renderers/xml_renderer'
4
+
5
+
6
+ module Caracal
7
+ module Renderers
8
+ class AppRenderer < XmlRenderer
9
+
10
+ #-------------------------------------------------------------
11
+ # Public Methods
12
+ #-------------------------------------------------------------
13
+
14
+ # This method produces the xml required for the `docProps/app.xml`
15
+ # sub-document.
16
+ #
17
+ def to_xml
18
+ builder = ::Nokogiri::XML::Builder.with(declaration_xml) do |xml|
19
+ xml.send 'Properties', root_options do
20
+ xml.send 'Application', 'Caracal'
21
+ end
22
+ end
23
+ builder.to_xml(save_options)
24
+ end
25
+
26
+
27
+ #-------------------------------------------------------------
28
+ # Private Methods
29
+ #-------------------------------------------------------------
30
+ private
31
+
32
+ def root_options
33
+ {
34
+ 'xmlns' => 'http://schemas.openxmlformats.org/officeDocument/2006/extended-properties',
35
+ 'xmlns:vt' => 'http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes'
36
+ }
37
+ end
38
+
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,53 @@
1
+ require 'nokogiri'
2
+
3
+ require 'caracal/renderers/xml_renderer'
4
+
5
+
6
+ module Caracal
7
+ module Renderers
8
+ class ContentTypesRenderer < XmlRenderer
9
+
10
+ #-------------------------------------------------------------
11
+ # Public Methods
12
+ #-------------------------------------------------------------
13
+
14
+ # This method produces the xml required for the `_[ContentTypes].xml`
15
+ # sub-document.
16
+ #
17
+ def to_xml
18
+ builder = ::Nokogiri::XML::Builder.with(declaration_xml) do |xml|
19
+ xml.send 'Types', root_options do
20
+ xml.send 'Default', { 'Extension' => 'gif', 'ContentType' => 'image/gif' }
21
+ xml.send 'Default', { 'Extension' => 'jpeg', 'ContentType' => 'image/jpeg' }
22
+ xml.send 'Default', { 'Extension' => 'jpg', 'ContentType' => 'image/jpeg' }
23
+ xml.send 'Default', { 'Extension' => 'png', 'ContentType' => 'image/png' }
24
+ xml.send 'Default', { 'Extension' => 'rels', 'ContentType' => 'application/vnd.openxmlformats-package.relationships+xml' }
25
+ xml.send 'Default', { 'Extension' => 'xml', 'ContentType' => 'application/xml' }
26
+ xml.send 'Override', { 'PartName' => '/docProps/app.xml', 'ContentType' => 'application/vnd.openxmlformats-officedocument.extended-properties+xml' }
27
+ xml.send 'Override', { 'PartName' => '/docProps/core.xml', 'ContentType' => 'application/vnd.openxmlformats-package.core-properties+xml' }
28
+ xml.send 'Override', { 'PartName' => '/word/document.xml', 'ContentType' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml' }
29
+ xml.send 'Override', { 'PartName' => '/word/footer1.xml', 'ContentType' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml' }
30
+ xml.send 'Override', { 'PartName' => '/word/fontTable.xml', 'ContentType' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml' }
31
+ xml.send 'Override', { 'PartName' => '/word/numbering.xml', 'ContentType' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml' }
32
+ xml.send 'Override', { 'PartName' => '/word/settings.xml', 'ContentType' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml' }
33
+ xml.send 'Override', { 'PartName' => '/word/styles.xml', 'ContentType' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml' }
34
+ end
35
+ end
36
+ builder.to_xml(save_options)
37
+ end
38
+
39
+
40
+ #-------------------------------------------------------------
41
+ # Private Methods
42
+ #-------------------------------------------------------------
43
+ private
44
+
45
+ def root_options
46
+ {
47
+ 'xmlns' => 'http://schemas.openxmlformats.org/package/2006/content-types'
48
+ }
49
+ end
50
+
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,44 @@
1
+ require 'nokogiri'
2
+
3
+ require 'caracal/renderers/xml_renderer'
4
+
5
+
6
+ module Caracal
7
+ module Renderers
8
+ class CoreRenderer < XmlRenderer
9
+
10
+ #-------------------------------------------------------------
11
+ # Public Methods
12
+ #-------------------------------------------------------------
13
+
14
+ # This method produces the xml required for the `docProps/core.xml`
15
+ # sub-document.
16
+ #
17
+ def to_xml
18
+ builder = ::Nokogiri::XML::Builder.with(declaration_xml) do |xml|
19
+ xml.send 'cp:coreProperties', root_options do
20
+ xml['dc'].title document.name
21
+ end
22
+ end
23
+ builder.to_xml(save_options)
24
+ end
25
+
26
+
27
+ #-------------------------------------------------------------
28
+ # Private Methods
29
+ #-------------------------------------------------------------
30
+ private
31
+
32
+ def root_options
33
+ {
34
+ 'xmlns:cp' => 'http://schemas.openxmlformats.org/package/2006/metadata/core-properties',
35
+ 'xmlns:dc' => 'http://purl.org/dc/elements/1.1/',
36
+ 'xmlns:dcterms' => 'http://purl.org/dc/terms/',
37
+ 'xmlns:dcmitype' => 'http://purl.org/dc/dcmitype/',
38
+ 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance'
39
+ }
40
+ end
41
+
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,349 @@
1
+ require 'nokogiri'
2
+
3
+ require 'caracal/renderers/xml_renderer'
4
+ require 'caracal/errors'
5
+
6
+
7
+ module Caracal
8
+ module Renderers
9
+ class DocumentRenderer < XmlRenderer
10
+
11
+ #-------------------------------------------------------------
12
+ # Public Methods
13
+ #-------------------------------------------------------------
14
+
15
+ # This method produces the xml required for the `word/document.xml`
16
+ # sub-document.
17
+ #
18
+ def to_xml
19
+ builder = ::Nokogiri::XML::Builder.with(declaration_xml) do |xml|
20
+ xml.send 'w:document', root_options do
21
+ xml.send 'w:background', { 'w:color' => 'FFFFFF' }
22
+ xml.send 'w:body' do
23
+
24
+ #============= CONTENTS ===================================
25
+
26
+ document.contents.each do |model|
27
+ method = render_method_for_model(model)
28
+ send(method, xml, model)
29
+ end
30
+
31
+ #============= PAGE SETTINGS ==============================
32
+
33
+ xml.send 'w:sectPr' do
34
+ if document.page_number_show
35
+ if rel = document.find_relationship('footer1.xml')
36
+ xml.send 'w:footerReference', { 'r:id' => rel.formatted_id, 'w:type' => 'default' }
37
+ end
38
+ end
39
+ xml.send 'w:pgSz', page_size_options
40
+ xml.send 'w:pgMar', page_margin_options
41
+ end
42
+
43
+ end
44
+ end
45
+ end
46
+ builder.to_xml(save_options)
47
+ end
48
+
49
+
50
+ #-------------------------------------------------------------
51
+ # Private Methods
52
+ #-------------------------------------------------------------
53
+ private
54
+
55
+ #============= COMMON RENDERERS ==========================
56
+
57
+ # This method converts a model class name to a rendering
58
+ # function on this class (e.g., Caracal::Core::Models::ParagraphModel
59
+ # translates to `render_paragraph`).
60
+ #
61
+ def render_method_for_model(model)
62
+ type = model.class.name.split('::').last.downcase.gsub('model', '')
63
+ "render_#{ type }"
64
+ end
65
+
66
+ # This method renders a standard node of run properties based on the
67
+ # model's attributes.
68
+ #
69
+ def render_run_attributes(xml, model)
70
+ if model.respond_to? :run_attributes
71
+ attrs = model.run_attributes.delete_if { |k, v| v.nil? }
72
+
73
+ xml.send 'w:rPr' do
74
+ unless attrs.empty?
75
+ xml.send 'w:rStyle', { 'w:val' => attrs[:style] } unless attrs[:style].nil?
76
+ xml.send 'w:color', { 'w:val' => attrs[:color] } unless attrs[:color].nil?
77
+ xml.send 'w:sz', { 'w:val' => attrs[:size] } unless attrs[:size].nil?
78
+ xml.send 'w:b', { 'w:val' => (attrs[:bold] ? '1' : '0') } unless attrs[:bold].nil?
79
+ xml.send 'w:i', { 'w:val' => (attrs[:italic] ? '1' : '0') } unless attrs[:italic].nil?
80
+ xml.send 'w:u', { 'w:val' => (attrs[:underline] ? 'single' : 'none') } unless attrs[:underline].nil?
81
+ end
82
+ xml.send 'w:rtl', { 'w:val' => '0' }
83
+ end
84
+ end
85
+ end
86
+
87
+
88
+ #============= MODEL RENDERERS ===========================
89
+
90
+ def render_image(xml, model)
91
+ unless ds = document.default_style
92
+ raise Caracal::Errors::NoDefaultStyleError 'Document must declare a default paragraph style.'
93
+ end
94
+
95
+ rel = document.relationship({ target: model.image_url, type: :image })
96
+ rel_id = rel.relationship_id
97
+ rel_name = rel.formatted_target
98
+
99
+ xml.send 'w:p', paragraph_options do
100
+ xml.send 'w:pPr' do
101
+ xml.send 'w:spacing', { 'w:lineRule' => 'auto', 'w:line' => ds.style_line }
102
+ xml.send 'w:contextualSpacing', { 'w:val' => '0' }
103
+ xml.send 'w:jc', { 'w:val' => model.image_align.to_s }
104
+ xml.send 'w:rPr'
105
+ end
106
+ xml.send 'w:r', run_options do
107
+ xml.send 'w:drawing' do
108
+ xml.send 'wp:inline', { distR: model.formatted_right, distT: model.formatted_top, distB: model.formatted_bottom, distL: model.formatted_left } do
109
+ xml.send 'wp:extent', { cx: model.formatted_width, cy: model.formatted_height }
110
+ xml.send 'wp:effectExtent', { t: 0, b: 0, r: 0, l: 0 }
111
+ xml.send 'wp:docPr', { id: rel_id, name: rel_name }
112
+ xml.send 'a:graphic' do
113
+ xml.send 'a:graphicData', { uri: 'http://schemas.openxmlformats.org/drawingml/2006/picture' } do
114
+ xml.send 'pic:pic' do
115
+ xml.send 'pic:nvPicPr' do
116
+ xml.send 'pic:cNvPr', { id: rel_id, name: rel_name }
117
+ xml.send 'pic:cNvPicPr', { preferRelativeSize: 0 }
118
+ end
119
+ xml.send 'pic:blipFill' do
120
+ xml.send 'a:blip', { 'r:embed' => rel.formatted_id }
121
+ xml.send 'a:srcRect', { t: 0, b: 0, r: 0, l: 0 }
122
+ xml.send 'a:stretch' do
123
+ xml.send 'a:fillRect'
124
+ end
125
+ end
126
+ xml.send 'pic:spPr' do
127
+ xml.send 'a:xfrm' do
128
+ xml.send 'a:ext', { cx: model.formatted_width, cy: model.formatted_height }
129
+ end
130
+ xml.send 'a:prstGeom', { prst: 'rect' }
131
+ xml.send 'a:ln'
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end
137
+ end
138
+ end
139
+ xml.send 'w:r', run_options do
140
+ xml.send 'w:rPr' do
141
+ xml.send 'w:rtl', { 'w:val' => '0' }
142
+ end
143
+ end
144
+ end
145
+ end
146
+
147
+ def render_linebreak(xml, model)
148
+ xml.send 'w:p', paragraph_options do
149
+ xml.send 'w:pPr' do
150
+ xml.send 'w:contextualSpacing', { 'w:val' => '0' }
151
+ end
152
+ xml.send 'w:r', run_options do
153
+ xml.send 'w:rtl', { 'w:val' => '0' }
154
+ end
155
+ end
156
+ end
157
+
158
+ def render_link(xml, model)
159
+ rel = document.relationship({ target: model.link_href, type: :link })
160
+
161
+ xml.send 'w:hyperlink', { 'r:id' => rel.formatted_id } do
162
+ xml.send 'w:r', run_options do
163
+ render_run_attributes(xml, model)
164
+ xml.send 'w:t', { 'xml:space' => 'preserve' }, model.link_content
165
+ end
166
+ end
167
+ end
168
+
169
+ def render_list(xml, model)
170
+ if model.list_level == 0
171
+ document.toplevel_lists << model
172
+ list_num = document.toplevel_lists.length # numbering uses 1-based index
173
+ end
174
+
175
+ model.recursive_items.each do |item|
176
+ render_listitem(xml, item, list_num)
177
+ end
178
+ end
179
+
180
+ def render_listitem(xml, model, list_num)
181
+ ls = document.find_list_style(model.list_item_type, model.list_item_level)
182
+ hanging = ls.style_left.to_i - ls.style_line.to_i - 1
183
+
184
+ xml.send 'w:p', paragraph_options do
185
+ xml.send 'w:pPr' do
186
+ xml.send 'w:numPr' do
187
+ xml.send 'w:ilvl', { 'w:val' => model.list_item_level }
188
+ xml.send 'w:numId', { 'w:val' => list_num }
189
+ end
190
+ xml.send 'w:ind', { 'w:left' => ls.style_left, 'w:hanging' => hanging }
191
+ xml.send 'w:contextualSpacing', { 'w:val' => '1' }
192
+ xml.send 'w:rPr' do
193
+ xml.send 'w:u', { 'w:val' => 'none' }
194
+ end
195
+ end
196
+ model.runs.each do |run|
197
+ method = render_method_for_model(run)
198
+ send(method, xml, run)
199
+ end
200
+ end
201
+ end
202
+
203
+ def render_pagebreak(xml, model)
204
+ xml.send 'w:p', paragraph_options do
205
+ xml.send 'w:r', run_options do
206
+ xml.send 'w:br', { 'w:type' => 'page' }
207
+ end
208
+ end
209
+ end
210
+
211
+ def render_paragraph(xml, model)
212
+ run_props = [:color, :size, :bold, :italic, :underline].map { |m| model.send("paragraph_#{ m }") }.compact
213
+
214
+ xml.send 'w:p', paragraph_options do
215
+ xml.send 'w:pPr' do
216
+ xml.send 'w:pStyle', { 'w:val' => model.paragraph_style } unless model.paragraph_style.nil?
217
+ xml.send 'w:contextualSpacing', { 'w:val' => '0' }
218
+ xml.send 'w:jc', { 'w:val' => model.paragraph_align } unless model.paragraph_align.nil?
219
+ render_run_attributes(xml, model)
220
+ end
221
+ model.runs.each do |run|
222
+ method = render_method_for_model(run)
223
+ send(method, xml, run)
224
+ end
225
+ end
226
+ end
227
+
228
+ def render_rule(xml, model)
229
+ options = { 'w:color' => model.rule_color, 'w:sz' => model.rule_size, 'w:val' => model.rule_line, 'w:space' => model.rule_spacing }
230
+
231
+ xml.send 'w:p', paragraph_options do
232
+ xml.send 'w:pPr' do
233
+ xml.send 'w:pBdr' do
234
+ xml.send 'w:top', options
235
+ end
236
+ end
237
+ end
238
+ end
239
+
240
+ def render_text(xml, model)
241
+ xml.send 'w:r', run_options do
242
+ render_run_attributes(xml, model)
243
+ xml.send 'w:t', { 'xml:space' => 'preserve' }, model.text_content
244
+ end
245
+ end
246
+
247
+ def render_table(xml, model)
248
+ xml.send 'w:tbl' do
249
+ xml.send 'w:tblPr' do
250
+ xml.send 'w:tblStyle', { 'w:val' => 'DefaultTable' }
251
+ xml.send 'w:bidiVisual', { 'w:val' => '0' }
252
+ xml.send 'w:tblW', { 'w:w' => model.table_width.to_f, 'w:type' => 'dxa' }
253
+ xml.send 'w:tblInd', { 'w:w' => '0.0', 'w:type' => 'dxa' }
254
+ xml.send 'w:jc', { 'w:val' => model.table_align }
255
+ xml.send 'w:tblBorders' do
256
+ %w(top left bottom right horizontal vertical).each do |m|
257
+ size = model.send("table_border_#{ m }_size")
258
+ if size > 0
259
+ options = {
260
+ 'w:color' => model.send("table_border_#{ m }_color"),
261
+ 'w:val' => model.send("table_border_#{ m }_line"),
262
+ 'w:sz' => size,
263
+ 'w:space' => model.send("table_border_#{ m }_spacing")
264
+ }
265
+ xml.send "w:#{ Caracal::Core::Models::BorderModel.formatted_type(m) }", options
266
+ end
267
+ end
268
+ end
269
+ xml.send 'w:tblLayout', { 'w:type' => 'fixed' }
270
+ xml.send 'w:tblLook', { 'w:val' => '0600' }
271
+ end
272
+ xml.send 'w:tblGrid' do
273
+ model.rows.first.each do |tc|
274
+ xml.send 'w:gridCol', { 'w:w' => tc.cell_width }
275
+ end
276
+ xml.send 'w:tblGridChange', { 'w:id' => '0' } do
277
+ xml.send 'w:tblGrid' do
278
+ model.rows.first.each do |tc|
279
+ xml.send 'w:gridCol', { 'w:w' => tc.cell_width }
280
+ end
281
+ end
282
+ end
283
+ end
284
+ model.rows.each do |row|
285
+ xml.send 'w:tr' do
286
+ row.each do |tc|
287
+ xml.send 'w:tc' do
288
+ xml.send 'tcPr' do
289
+ xml.send 'w:shd', { 'w:fill' => tc.cell_background }
290
+ xml.send 'w:tcMar' do
291
+ %w(top left bottom right).each do |d|
292
+ xml.send "w:#{ d }", { 'w:w' => tc.send("cell_margin_#{ d }").to_f, 'w:type' => 'dxa' }
293
+ end
294
+ end
295
+ end
296
+ tc.contents.each do |m|
297
+ method = render_method_for_model(m)
298
+ send(method, xml, m)
299
+ end
300
+ end
301
+ end
302
+ end
303
+ end
304
+ end
305
+ end
306
+
307
+
308
+
309
+ #============= OPTIONS ===================================
310
+
311
+ def root_options
312
+ {
313
+ 'xmlns:mc' => 'http://schemas.openxmlformats.org/markup-compatibility/2006',
314
+ 'xmlns:o' => 'urn:schemas-microsoft-com:office:office',
315
+ 'xmlns:r' => 'http://schemas.openxmlformats.org/officeDocument/2006/relationships',
316
+ 'xmlns:m' => 'http://schemas.openxmlformats.org/officeDocument/2006/math',
317
+ 'xmlns:v' => 'urn:schemas-microsoft-com:vml',
318
+ 'xmlns:wp' => 'http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing',
319
+ 'xmlns:w10' => 'urn:schemas-microsoft-com:office:word',
320
+ 'xmlns:w' => 'http://schemas.openxmlformats.org/wordprocessingml/2006/main',
321
+ 'xmlns:wne' => 'http://schemas.microsoft.com/office/word/2006/wordml',
322
+ 'xmlns:sl' => 'http://schemas.openxmlformats.org/schemaLibrary/2006/main',
323
+ 'xmlns:a' => 'http://schemas.openxmlformats.org/drawingml/2006/main',
324
+ 'xmlns:pic' => 'http://schemas.openxmlformats.org/drawingml/2006/picture',
325
+ 'xmlns:c' => 'http://schemas.openxmlformats.org/drawingml/2006/chart',
326
+ 'xmlns:lc' => 'http://schemas.openxmlformats.org/drawingml/2006/lockedCanvas',
327
+ 'xmlns:dgm' => 'http://schemas.openxmlformats.org/drawingml/2006/diagram'
328
+ }
329
+ end
330
+
331
+ def page_margin_options
332
+ {
333
+ 'w:top' => document.page_margin_top,
334
+ 'w:bottom' => document.page_margin_bottom,
335
+ 'w:left' => document.page_margin_left,
336
+ 'w:right' => document.page_margin_right
337
+ }
338
+ end
339
+
340
+ def page_size_options
341
+ {
342
+ 'w:w' => document.page_width,
343
+ 'w:h' => document.page_height
344
+ }
345
+ end
346
+
347
+ end
348
+ end
349
+ end