caracal 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +23 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +22 -0
- data/README.md +941 -0
- data/Rakefile +2 -0
- data/caracal.gemspec +27 -0
- data/lib/caracal.rb +31 -0
- data/lib/caracal/core/file_name.rb +39 -0
- data/lib/caracal/core/fonts.rb +75 -0
- data/lib/caracal/core/images.rb +37 -0
- data/lib/caracal/core/line_breaks.rb +29 -0
- data/lib/caracal/core/list_styles.rb +92 -0
- data/lib/caracal/core/lists.rb +57 -0
- data/lib/caracal/core/models/base_model.rb +51 -0
- data/lib/caracal/core/models/border_model.rb +120 -0
- data/lib/caracal/core/models/font_model.rb +64 -0
- data/lib/caracal/core/models/image_model.rb +118 -0
- data/lib/caracal/core/models/line_break_model.rb +15 -0
- data/lib/caracal/core/models/link_model.rb +65 -0
- data/lib/caracal/core/models/list_item_model.rb +105 -0
- data/lib/caracal/core/models/list_model.rb +130 -0
- data/lib/caracal/core/models/list_style_model.rb +129 -0
- data/lib/caracal/core/models/margin_model.rb +76 -0
- data/lib/caracal/core/models/page_break_model.rb +15 -0
- data/lib/caracal/core/models/page_number_model.rb +69 -0
- data/lib/caracal/core/models/page_size_model.rb +70 -0
- data/lib/caracal/core/models/paragraph_model.rb +141 -0
- data/lib/caracal/core/models/relationship_model.rb +108 -0
- data/lib/caracal/core/models/rule_model.rb +27 -0
- data/lib/caracal/core/models/style_model.rb +134 -0
- data/lib/caracal/core/models/table_cell_model.rb +155 -0
- data/lib/caracal/core/models/table_model.rb +206 -0
- data/lib/caracal/core/models/text_model.rb +92 -0
- data/lib/caracal/core/page_breaks.rb +29 -0
- data/lib/caracal/core/page_numbers.rb +51 -0
- data/lib/caracal/core/page_settings.rb +72 -0
- data/lib/caracal/core/relationships.rb +90 -0
- data/lib/caracal/core/rules.rb +35 -0
- data/lib/caracal/core/styles.rb +86 -0
- data/lib/caracal/core/tables.rb +41 -0
- data/lib/caracal/core/text.rb +73 -0
- data/lib/caracal/document.rb +242 -0
- data/lib/caracal/errors.rb +23 -0
- data/lib/caracal/renderers/app_renderer.rb +41 -0
- data/lib/caracal/renderers/content_types_renderer.rb +53 -0
- data/lib/caracal/renderers/core_renderer.rb +44 -0
- data/lib/caracal/renderers/document_renderer.rb +349 -0
- data/lib/caracal/renderers/fonts_renderer.rb +56 -0
- data/lib/caracal/renderers/footer_renderer.rb +69 -0
- data/lib/caracal/renderers/numbering_renderer.rb +87 -0
- data/lib/caracal/renderers/package_relationships_renderer.rb +50 -0
- data/lib/caracal/renderers/relationships_renderer.rb +48 -0
- data/lib/caracal/renderers/settings_renderer.rb +58 -0
- data/lib/caracal/renderers/styles_renderer.rb +163 -0
- data/lib/caracal/renderers/xml_renderer.rb +83 -0
- data/lib/caracal/version.rb +3 -0
- data/lib/tilt/caracal.rb +21 -0
- data/spec/lib/caracal/core/file_name_spec.rb +54 -0
- data/spec/lib/caracal/core/fonts_spec.rb +119 -0
- data/spec/lib/caracal/core/images_spec.rb +25 -0
- data/spec/lib/caracal/core/line_breaks_spec.rb +25 -0
- data/spec/lib/caracal/core/list_styles_spec.rb +121 -0
- data/spec/lib/caracal/core/lists_spec.rb +43 -0
- data/spec/lib/caracal/core/models/base_model_spec.rb +38 -0
- data/spec/lib/caracal/core/models/border_model_spec.rb +159 -0
- data/spec/lib/caracal/core/models/font_model_spec.rb +92 -0
- data/spec/lib/caracal/core/models/image_model_spec.rb +192 -0
- data/spec/lib/caracal/core/models/line_break_model_spec.rb +21 -0
- data/spec/lib/caracal/core/models/link_model_spec.rb +139 -0
- data/spec/lib/caracal/core/models/list_item_model_spec.rb +190 -0
- data/spec/lib/caracal/core/models/list_model_spec.rb +178 -0
- data/spec/lib/caracal/core/models/list_style_model_spec.rb +212 -0
- data/spec/lib/caracal/core/models/margin_model_spec.rb +111 -0
- data/spec/lib/caracal/core/models/page_break_model_spec.rb +21 -0
- data/spec/lib/caracal/core/models/page_number_model_spec.rb +101 -0
- data/spec/lib/caracal/core/models/page_size_model_spec.rb +91 -0
- data/spec/lib/caracal/core/models/paragraph_model_spec.rb +162 -0
- data/spec/lib/caracal/core/models/relationship_model_spec.rb +183 -0
- data/spec/lib/caracal/core/models/rule_model_spec.rb +108 -0
- data/spec/lib/caracal/core/models/style_model_spec.rb +187 -0
- data/spec/lib/caracal/core/models/table_cell_model_spec.rb +221 -0
- data/spec/lib/caracal/core/models/table_model_spec.rb +222 -0
- data/spec/lib/caracal/core/models/text_model_spec.rb +132 -0
- data/spec/lib/caracal/core/page_breaks_spec.rb +25 -0
- data/spec/lib/caracal/core/page_numbers_spec.rb +80 -0
- data/spec/lib/caracal/core/page_settings_spec.rb +143 -0
- data/spec/lib/caracal/core/relationships_spec.rb +119 -0
- data/spec/lib/caracal/core/rules_spec.rb +25 -0
- data/spec/lib/caracal/core/styles_spec.rb +129 -0
- data/spec/lib/caracal/core/tables_spec.rb +25 -0
- data/spec/lib/caracal/core/text_spec.rb +52 -0
- data/spec/lib/caracal/errors_spec.rb +10 -0
- data/spec/spec_helper.rb +8 -0
- 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
|