caracal 1.0.2 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: aa886d1701a3fd3be57df67220f491dc020759ff
4
- data.tar.gz: 0819776425e4c055c74946f6cf9c73622b8964cd
3
+ metadata.gz: c858148d5ae537806007e2e90609ef72cb78aaad
4
+ data.tar.gz: e92af27b1c79d1842ed2aac515aedfe0452bb53c
5
5
  SHA512:
6
- metadata.gz: 01bbb4a1ea7264b9f95363005af6acaa76796a1085a6ef3264645b4cd29f586a79bddcf87d458ae69d63fefd3570908367e7982cdf1705d608d5ab15dd593482
7
- data.tar.gz: 8d116facbd2f0a0c7de17a85cf6694ffca5d8fd88799ccfd20159dbb13402f2e9ef6f57979d6982d2e462682749a93364e0323544602176396a1ce3a3a0c54c1
6
+ metadata.gz: 42047a3d1dc77994ef4bf3f733c5634e6d1dbeec590a7895e9d299a8ae93ac565a6c974b9577f87f4e612936e70ace9fc9c2b7063a42d7b858e8fc10e0724b3b
7
+ data.tar.gz: 795fde5d5a5561e750ccb90953a763b173a48a55a7179197d1eb186203d585c704ba2ed728276a25e2c56dd8d2d67961ee2d81af351655e062110f129abb9f4f
data/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ #### v1.0.3
2
+
3
+ * Enhancements
4
+ * Added custom properties (@davidtolsma).
5
+ * Added page breaks to paragraph model sub-functions (@jdugan).
6
+
7
+
1
8
  #### v1.0.2
2
9
 
3
10
  * Enhancements
@@ -7,7 +14,7 @@
7
14
  #### v0.3.0
8
15
 
9
16
  * Deprecations
10
- * The :style attribute is no longer allowed on text and link commands. Use :font, :size, etc. instead.
17
+ * The :style attribute is no longer allowed on text and link commands. Use :font, :size, etc. instead (@jdugan).
11
18
 
12
19
 
13
20
  #### v0.2.1
@@ -22,15 +29,14 @@
22
29
  * Enhancements
23
30
  * Implemented true line breaks within paragraphs (@Linuus).
24
31
  * Converted paragraph command to accept/allow blank content (@Linuus).
25
- * Allowed :top and :bottom attributes to be set on default paragraph style (@jpdugan).
32
+ * Allowed :top and :bottom attributes to be set on default paragraph style (@jdugan).
26
33
 
27
34
 
28
35
  * Deprecations
29
- * Line breaks are no longer allowed at the document level. Use blank paragraphs instead.
30
-
36
+ * Line breaks are no longer allowed at the document level. Use blank paragraphs instead (@jdugan).
31
37
 
32
38
 
33
39
  #### v0.1.x
34
40
 
35
41
  * Enhancements
36
- * Initial commits. (@jpdugan)
42
+ * Initial commits. (@jdugan)
data/README.md CHANGED
@@ -90,6 +90,7 @@ For each Caracal request, the following document structure will be created and z
90
90
  |- docProps
91
91
  |- app.xml
92
92
  |- core.xml
93
+ |- custom.xml
93
94
  |- word
94
95
  |- _rels
95
96
  |- document.xml.rels
@@ -119,6 +120,9 @@ Specifies the name of the application that generated the document. *This file is
119
120
  **docProps/core.xml**
120
121
  Specifies the title of the document. *This file is generated automatically by the library based on other user directives.*
121
122
 
123
+ **docProps/custom.xml**
124
+ Specifies the custom document properties. *This file is generated automatically by the library based on other user directives.*
125
+
122
126
  **word/_rels/document.xml.rels**
123
127
  Defines an internal identifier and type with all external content items (images, links, etc). *This file is generated automatically by the library based on other user directives.*
124
128
 
@@ -167,14 +171,14 @@ A twip is 1/20 of a point. Word documents are printed at 72dpi. 1in == 72pt ==
167
171
  In Word documents, pixels are equivalent to points.
168
172
 
169
173
  **EMUs (English Metric Unit)**
170
- 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.
174
+ EMUs are a virtual unit designed to facilitate the smooth conversion between inches, millimeters, and pixels for images and vector graphics. 1in == 914400 EMUs == 72dpi x 100 x 254.
171
175
 
172
176
  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.
173
177
 
174
178
 
175
179
  ## Syntax Flexibility
176
180
 
177
- 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.
181
+ Generally speaking, Caracal commands will accept instructions via any combination of a parameters hash and/or a block. For example, all of the following commands are equivalent.
178
182
 
179
183
  ```ruby
180
184
  docx.style id: 'special', name: 'Special', size: 24, bold: true
@@ -351,9 +355,28 @@ Caracal establishes a standard set of default styles for every document. Default
351
355
  * Heading6
352
356
 
353
357
 
358
+
359
+ ### Custom Properties
360
+
361
+ Custom document properties can be defined using the `custom_property` method. The method accepts a few required parameters to control the definition of the custom property.
362
+
363
+ ```ruby
364
+ docx.custom_property do
365
+ name 'property name 1' # sets the name of the custom property.
366
+ value 'test' # sets the value of the custom property.
367
+ type :text # sets the property type. accepts :text, :number, :date, :boolean.
368
+ end
369
+ ```
370
+
371
+ The `name`, `value`, and `height` attributes are required. If any of the attributes are missing, the custom property will not be created.
372
+
373
+ A document may have zero or many custom properties. Each custom property's `name` should be unique with its `type`.
374
+
375
+
376
+
354
377
  ### Paragraphs
355
378
 
356
- Paragraph text can be added using the `p` method. The method accepts several optional parameters for controlling the style and behavior of the paragrpah.
379
+ Paragraph text can be added using the `p` method. The method accepts several optional parameters for controlling the style and behavior of the paragraph.
357
380
 
358
381
  In its simple form, a paragraph accepts a text string and formatting options.
359
382
 
@@ -364,7 +387,7 @@ docx.p 'Sample text.', style: 'custom_style'
364
387
 
365
388
  docx.p 'Sample text.' do
366
389
  style 'custom_style' # sets the paragraph style. generally used at the exclusion of other attributes.
367
- align :left # sewts the alignment. accepts :left, :center, :right, and :both.
390
+ align :left # sets the alignment. accepts :left, :center, :right, and :both.
368
391
  color '333333' # sets the font color.
369
392
  size 32 # sets the font size. units in 1/2 points.
370
393
  bold true # sets whether or not to render the text with a bold weight.
@@ -384,6 +407,7 @@ docx.p do
384
407
  text '.'
385
408
  br
386
409
  text 'This text follows a line break.'
410
+ page
387
411
  end
388
412
  ```
389
413
 
@@ -565,7 +589,7 @@ docx.table [['Header 1','Header 2'],['Cell 1', 'Cell 2']] do
565
589
  border_color '666666' # sets the border color. defaults to 'auto'.
566
590
  border_line :single # sets the border style. defaults to :single. see OOXML docs for details.
567
591
  border_size 4 # sets the border width. defaults to 0. units in twips.
568
- border_spacing 4 # sets the spacing around the border. deaults to 0. units in twips.
592
+ border_spacing 4 # sets the spacing around the border. defaults to 0. units in twips.
569
593
  end
570
594
  ```
571
595
 
@@ -0,0 +1,47 @@
1
+ require 'caracal/core/models/custom_property_model'
2
+ require 'caracal/errors'
3
+
4
+
5
+ module Caracal
6
+ module Core
7
+
8
+ # This module encapsulates all the functionality related to setting the
9
+ # document's custom properties.
10
+ #
11
+ module CustomProperties
12
+ def self.included(base)
13
+ base.class_eval do
14
+
15
+ #-------------------------------------------------------------
16
+ # Public Methods
17
+ #-------------------------------------------------------------
18
+
19
+ # This method controls the custom properties.
20
+ #
21
+ def custom_property(options={}, &block)
22
+ model = Caracal::Core::Models::CustomPropertyModel.new(options, &block)
23
+ if model.valid?
24
+ register_property(model)
25
+ end
26
+ model
27
+ end
28
+
29
+ #============== GETTERS =============================
30
+
31
+ def custom_props
32
+ @custom_props ||= []
33
+ end
34
+
35
+ #============== REGISTRATION ========================
36
+
37
+ def register_property(model)
38
+ custom_props << model
39
+ model
40
+ end
41
+
42
+ end
43
+ end
44
+ end
45
+
46
+ end
47
+ end
@@ -0,0 +1,60 @@
1
+ require 'caracal/core/models/base_model'
2
+
3
+
4
+ module Caracal
5
+ module Core
6
+ module Models
7
+
8
+ # This class encapsulates the logic needed to store and manipulate
9
+ # custom properties
10
+ #
11
+ class CustomPropertyModel < BaseModel
12
+
13
+ # accessors
14
+ attr_reader :custom_property_name
15
+ attr_reader :custom_property_value
16
+ attr_reader :custom_property_type
17
+
18
+
19
+ #-------------------------------------------------------------
20
+ # Public Instance Methods
21
+ #-------------------------------------------------------------
22
+
23
+
24
+ #=================== SETTERS =============================
25
+
26
+ def name(value)
27
+ @custom_property_name = value.to_s
28
+ end
29
+
30
+ def value(value)
31
+ @custom_property_value = value.to_s
32
+ end
33
+
34
+ def type(value)
35
+ @custom_property_type = value.to_s
36
+ end
37
+
38
+
39
+ #=============== VALIDATION ===========================
40
+
41
+ def valid?
42
+ required = option_keys
43
+ required.all? { |m| !send("custom_property_#{ m }").nil? }
44
+ end
45
+
46
+
47
+ #-------------------------------------------------------------
48
+ # Private Instance Methods
49
+ #-------------------------------------------------------------
50
+ private
51
+
52
+ def option_keys
53
+ [:name, :value, :type]
54
+ end
55
+
56
+ end
57
+
58
+ end
59
+ end
60
+ end
@@ -4,12 +4,58 @@ require 'caracal/core/models/base_model'
4
4
  module Caracal
5
5
  module Core
6
6
  module Models
7
-
7
+
8
8
  # This class encapsulates the logic needed to store and manipulate
9
9
  # page break data.
10
10
  #
11
- class PageBreakModel < BaseModel; end
12
-
11
+ # The :wrap option is not described in the project's README because
12
+ # it exists purely as an internal Caracal concern. Page breaks
13
+ # at the document level must be wrapped in a paragraph node; page breaks
14
+ # within paragraph-like container simply add a run. There's no need to
15
+ # trouble end users with this issue.
16
+ #
17
+ class PageBreakModel < BaseModel
18
+
19
+ #-------------------------------------------------------------
20
+ # Configuration
21
+ #-------------------------------------------------------------
22
+
23
+ # constants
24
+ const_set(:DEFAULT_PAGE_BREAK_WRAP, true)
25
+
26
+ # accessors
27
+ attr_reader :page_break_wrap
28
+
29
+ # initialization
30
+ def initialize(options={}, &block)
31
+ @page_break_wrap = DEFAULT_PAGE_BREAK_WRAP
32
+
33
+ super options, &block
34
+ end
35
+
36
+
37
+ #-------------------------------------------------------------
38
+ # Public Methods
39
+ #-------------------------------------------------------------
40
+
41
+ #=============== SETTERS ==============================
42
+
43
+ def wrap(value)
44
+ @page_break_wrap = !!value
45
+ end
46
+
47
+
48
+ #-------------------------------------------------------------
49
+ # Private Instance Methods
50
+ #-------------------------------------------------------------
51
+ private
52
+
53
+ def option_keys
54
+ [:wrap]
55
+ end
56
+
57
+ end
58
+
13
59
  end
14
60
  end
15
- end
61
+ end
@@ -92,6 +92,13 @@ module Caracal
92
92
 
93
93
  #=============== SUB-METHODS ===========================
94
94
 
95
+ # .br
96
+ def br
97
+ model = Caracal::Core::Models::LineBreakModel.new()
98
+ runs << model
99
+ model
100
+ end
101
+
95
102
  # .link
96
103
  def link(*args, &block)
97
104
  options = Caracal::Utilities.extract_options!(args)
@@ -107,9 +114,9 @@ module Caracal
107
114
  model
108
115
  end
109
116
 
110
- # .br
111
- def br
112
- model = Caracal::Core::Models::LineBreakModel.new()
117
+ # .page
118
+ def page
119
+ model = Caracal::Core::Models::PageBreakModel.new({ wrap: false })
113
120
  runs << model
114
121
  model
115
122
  end
@@ -9,6 +9,7 @@ require 'caracal/core/lists'
9
9
  require 'caracal/core/page_breaks'
10
10
  require 'caracal/core/page_numbers'
11
11
  require 'caracal/core/page_settings'
12
+ require 'caracal/core/custom_properties'
12
13
  require 'caracal/core/relationships'
13
14
  require 'caracal/core/rules'
14
15
  require 'caracal/core/styles'
@@ -18,6 +19,7 @@ require 'caracal/core/text'
18
19
  require 'caracal/renderers/app_renderer'
19
20
  require 'caracal/renderers/content_types_renderer'
20
21
  require 'caracal/renderers/core_renderer'
22
+ require 'caracal/renderers/custom_renderer'
21
23
  require 'caracal/renderers/document_renderer'
22
24
  require 'caracal/renderers/fonts_renderer'
23
25
  require 'caracal/renderers/footer_renderer'
@@ -30,97 +32,98 @@ require 'caracal/renderers/styles_renderer'
30
32
 
31
33
  module Caracal
32
34
  class Document
33
-
35
+
34
36
  #-------------------------------------------------------------
35
37
  # Configuration
36
38
  #-------------------------------------------------------------
37
-
39
+
38
40
  # mixins (order is important)
39
41
  include Caracal::Core::FileName
40
-
42
+ include Caracal::Core::CustomProperties
43
+
41
44
  include Caracal::Core::Relationships
42
45
  include Caracal::Core::Fonts
43
46
  include Caracal::Core::PageSettings
44
47
  include Caracal::Core::PageNumbers
45
48
  include Caracal::Core::Styles
46
49
  include Caracal::Core::ListStyles
47
-
50
+
48
51
  include Caracal::Core::Images
49
52
  include Caracal::Core::Lists
50
53
  include Caracal::Core::PageBreaks
51
54
  include Caracal::Core::Rules
52
55
  include Caracal::Core::Tables
53
56
  include Caracal::Core::Text
54
-
55
-
57
+
58
+
56
59
  #-------------------------------------------------------------
57
60
  # Public Class Methods
58
61
  #-------------------------------------------------------------
59
-
62
+
60
63
  #============ OUTPUT ====================================
61
-
64
+
62
65
  # This method renders a new Word document and returns it as a
63
66
  # a string.
64
67
  #
65
68
  def self.render(f_name = nil, &block)
66
69
  docx = new(f_name, &block)
67
70
  buffer = docx.render
68
-
71
+
69
72
  buffer.rewind
70
73
  buffer.sysread
71
74
  end
72
-
75
+
73
76
  # This method renders a new Word document and saves it to the
74
77
  # file system.
75
78
  #
76
79
  def self.save(f_name = nil, &block)
77
80
  docx = new(f_name, &block)
78
81
  buffer = docx.render
79
-
82
+
80
83
  File.open("./#{ docx.name }", 'w') { |f| f.write(buffer.string) }
81
84
  end
82
-
83
-
84
-
85
+
86
+
87
+
85
88
  #-------------------------------------------------------------
86
89
  # Public Instance Methods
87
90
  #-------------------------------------------------------------
88
-
91
+
89
92
  # This method instantiates a new word document.
90
93
  #
91
94
  def initialize(name = nil, &block)
92
95
  file_name(name)
93
-
94
- page_size
96
+
97
+ page_size
95
98
  page_margins top: 1440, bottom: 1440, left: 1440, right: 1440
96
99
  page_numbers
97
-
100
+
98
101
  [:relationship, :font, :style, :list_style].each do |method|
99
102
  collection = self.class.send("default_#{ method }s")
100
103
  collection.each do |item|
101
104
  send(method, item)
102
105
  end
103
106
  end
104
-
107
+
105
108
  if block_given?
106
109
  (block.arity < 1) ? instance_eval(&block) : block[self]
107
110
  end
108
111
  end
109
-
110
-
112
+
113
+
111
114
  #============ GETTERS ===================================
112
-
113
- # This method returns an array of models which constitute the
115
+
116
+ # This method returns an array of models which constitute the
114
117
  # set of instructions for producing the document content.
115
118
  #
116
119
  def contents
117
120
  @contents ||= []
118
121
  end
119
-
120
-
122
+
123
+
121
124
  #============ RENDERING =================================
122
-
123
- # This method renders the word document instance into
125
+
126
+ # This method renders the word document instance into
124
127
  # a string buffer. Order is important!
125
128
  #
126
129
  def render
@@ -129,6 +132,7 @@ module Caracal
129
132
  render_content_types(zip)
130
133
  render_app(zip)
131
134
  render_core(zip)
135
+ render_custom(zip)
132
136
  render_fonts(zip)
133
137
  render_footer(zip)
134
138
  render_settings(zip)
@@ -139,58 +143,65 @@ module Caracal
139
143
  render_numbering(zip) # Must go here: Depends on document renderer
140
144
  end
141
145
  end
142
-
143
-
144
-
146
+
147
+
148
+
145
149
  #-------------------------------------------------------------
146
150
  # Private Instance Methods
147
151
  #-------------------------------------------------------------
148
152
  private
149
-
153
+
150
154
  #============ RENDERERS =====================================
151
-
155
+
152
156
  def render_app(zip)
153
157
  content = ::Caracal::Renderers::AppRenderer.render(self)
154
-
158
+
155
159
  zip.put_next_entry('docProps/app.xml')
156
160
  zip.write(content)
157
161
  end
158
-
162
+
159
163
  def render_content_types(zip)
160
164
  content = ::Caracal::Renderers::ContentTypesRenderer.render(self)
161
-
165
+
162
166
  zip.put_next_entry('[Content_Types].xml')
163
167
  zip.write(content)
164
168
  end
165
-
169
+
166
170
  def render_core(zip)
167
171
  content = ::Caracal::Renderers::CoreRenderer.render(self)
168
-
172
+
169
173
  zip.put_next_entry('docProps/core.xml')
170
174
  zip.write(content)
171
175
  end
172
-
176
+
177
+ def render_custom(zip)
178
+ content = ::Caracal::Renderers::CustomRenderer.render(self)
179
+
180
+ zip.put_next_entry('docProps/custom.xml')
181
+ zip.write(content)
182
+ end
183
+
173
184
  def render_document(zip)
174
185
  content = ::Caracal::Renderers::DocumentRenderer.render(self)
175
-
186
+
176
187
  zip.put_next_entry('word/document.xml')
177
188
  zip.write(content)
178
189
  end
179
-
190
+
180
191
  def render_fonts(zip)
181
192
  content = ::Caracal::Renderers::FontsRenderer.render(self)
182
-
193
+
183
194
  zip.put_next_entry('word/fontTable.xml')
184
195
  zip.write(content)
185
196
  end
186
-
197
+
187
198
  def render_footer(zip)
188
199
  content = ::Caracal::Renderers::FooterRenderer.render(self)
189
-
200
+
190
201
  zip.put_next_entry('word/footer1.xml')
191
202
  zip.write(content)
192
203
  end
193
-
204
+
194
205
  def render_media(zip)
195
206
  images = relationships.select { |r| r.relationship_type == :image }
196
207
  images.each do |rel|
@@ -199,46 +210,46 @@ module Caracal
199
210
  else
200
211
  content = open(rel.relationship_target).read
201
212
  end
202
-
213
+
203
214
  zip.put_next_entry("word/#{ rel.formatted_target }")
204
215
  zip.write(content)
205
216
  end
206
217
  end
207
-
218
+
208
219
  def render_numbering(zip)
209
220
  content = ::Caracal::Renderers::NumberingRenderer.render(self)
210
-
221
+
211
222
  zip.put_next_entry('word/numbering.xml')
212
223
  zip.write(content)
213
224
  end
214
-
225
+
215
226
  def render_package_relationships(zip)
216
227
  content = ::Caracal::Renderers::PackageRelationshipsRenderer.render(self)
217
-
228
+
218
229
  zip.put_next_entry('_rels/.rels')
219
230
  zip.write(content)
220
231
  end
221
-
232
+
222
233
  def render_relationships(zip)
223
234
  content = ::Caracal::Renderers::RelationshipsRenderer.render(self)
224
-
235
+
225
236
  zip.put_next_entry('word/_rels/document.xml.rels')
226
237
  zip.write(content)
227
238
  end
228
-
239
+
229
240
  def render_settings(zip)
230
241
  content = ::Caracal::Renderers::SettingsRenderer.render(self)
231
-
242
+
232
243
  zip.put_next_entry('word/settings.xml')
233
244
  zip.write(content)
234
245
  end
235
-
246
+
236
247
  def render_styles(zip)
237
248
  content = ::Caracal::Renderers::StylesRenderer.render(self)
238
-
249
+
239
250
  zip.put_next_entry('word/styles.xml')
240
251
  zip.write(content)
241
252
  end
242
-
253
+
243
254
  end
244
255
  end
@@ -6,12 +6,12 @@ require 'caracal/renderers/xml_renderer'
6
6
  module Caracal
7
7
  module Renderers
8
8
  class ContentTypesRenderer < XmlRenderer
9
-
9
+
10
10
  #-------------------------------------------------------------
11
11
  # Public Methods
12
12
  #-------------------------------------------------------------
13
-
14
- # This method produces the xml required for the `_[ContentTypes].xml`
13
+
14
+ # This method produces the xml required for the `_[ContentTypes].xml`
15
15
  # sub-document.
16
16
  #
17
17
  def to_xml
@@ -23,31 +23,32 @@ module Caracal
23
23
  xml.send 'Default', { 'Extension' => 'png', 'ContentType' => 'image/png' }
24
24
  xml.send 'Default', { 'Extension' => 'rels', 'ContentType' => 'application/vnd.openxmlformats-package.relationships+xml' }
25
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' }
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' => '/docProps/custom.xml', 'ContentType' => 'application/vnd.openxmlformats-officedocument.custom-properties+xml' }
29
+ xml.send 'Override', { 'PartName' => '/word/document.xml', 'ContentType' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml' }
30
+ xml.send 'Override', { 'PartName' => '/word/footer1.xml', 'ContentType' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml' }
31
+ xml.send 'Override', { 'PartName' => '/word/fontTable.xml', 'ContentType' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml' }
32
+ xml.send 'Override', { 'PartName' => '/word/numbering.xml', 'ContentType' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml' }
33
+ xml.send 'Override', { 'PartName' => '/word/settings.xml', 'ContentType' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml' }
34
+ xml.send 'Override', { 'PartName' => '/word/styles.xml', 'ContentType' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml' }
34
35
  end
35
36
  end
36
37
  builder.to_xml(save_options)
37
38
  end
38
-
39
-
39
+
40
+
40
41
  #-------------------------------------------------------------
41
42
  # Private Methods
42
- #-------------------------------------------------------------
43
+ #-------------------------------------------------------------
43
44
  private
44
-
45
+
45
46
  def root_options
46
47
  {
47
48
  'xmlns' => 'http://schemas.openxmlformats.org/package/2006/content-types'
48
49
  }
49
50
  end
50
-
51
+
51
52
  end
52
53
  end
53
- end
54
+ end
@@ -0,0 +1,64 @@
1
+ require 'nokogiri'
2
+ require 'date'
3
+
4
+ require 'caracal/renderers/xml_renderer'
5
+
6
+
7
+ module Caracal
8
+ module Renderers
9
+ class CustomRenderer < XmlRenderer
10
+
11
+ #-------------------------------------------------------------
12
+ # Public Methods
13
+ #-------------------------------------------------------------
14
+
15
+ # This method produces the xml required for the `docProps/custom.xml`
16
+ # sub-document.
17
+ #
18
+ def to_xml
19
+ builder = ::Nokogiri::XML::Builder.with(declaration_xml) do |xml|
20
+ xml.send 'Properties', root_options do
21
+ document.custom_props.each_with_index do |property, index|
22
+ xml.send 'property',
23
+ { fmtid: '{D5CDD505-2E9C-101B-9397-08002B2CF9AE}', pid: index + 2, name: property.custom_property_name } do
24
+ case property.custom_property_type.downcase
25
+ when 'text'
26
+ xml['vt'].lpwstr property.custom_property_value
27
+ when 'date'
28
+ xml['vt'].filetime property.custom_property_value.to_date
29
+ when 'number'
30
+ xml['vt'].i4 property.custom_property_value.to_f
31
+ when 'boolean'
32
+ if property.custom_property_value == 'true' || property.custom_property_value == 'false'
33
+ xml['vt'].bool property.custom_property_value
34
+ else
35
+ # Not a boolean sent, so reverting to string so docx will open
36
+ xml['vt'].lpwstr property.custom_property_value
37
+ end
38
+ else
39
+ # Fail to string type
40
+ xml['vt'].lpwstr property.custom_property_value
41
+ end
42
+ end
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
+ def root_options
56
+ {
57
+ 'xmlns' => "http://schemas.openxmlformats.org/officeDocument/2006/custom-properties",
58
+ 'xmlns:vt' => "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"
59
+ }
60
+ end
61
+
62
+ end
63
+ end
64
+ end
@@ -205,7 +205,13 @@ module Caracal
205
205
  end
206
206
 
207
207
  def render_pagebreak(xml, model)
208
- xml.send 'w:p', paragraph_options do
208
+ if model.page_break_wrap
209
+ xml.send 'w:p', paragraph_options do
210
+ xml.send 'w:r', run_options do
211
+ xml.send 'w:br', { 'w:type' => 'page' }
212
+ end
213
+ end
214
+ else
209
215
  xml.send 'w:r', run_options do
210
216
  xml.send 'w:br', { 'w:type' => 'page' }
211
217
  end
@@ -6,12 +6,12 @@ require 'caracal/renderers/xml_renderer'
6
6
  module Caracal
7
7
  module Renderers
8
8
  class PackageRelationshipsRenderer < XmlRenderer
9
-
9
+
10
10
  #-------------------------------------------------------------
11
11
  # Public Methods
12
12
  #-------------------------------------------------------------
13
-
14
- # This method produces the xml required for the `word/settings.xml`
13
+
14
+ # This method produces the xml required for the `word/settings.xml`
15
15
  # sub-document.
16
16
  #
17
17
  def to_xml
@@ -24,27 +24,28 @@ module Caracal
24
24
  end
25
25
  builder.to_xml(save_options)
26
26
  end
27
-
28
-
27
+
28
+
29
29
  #-------------------------------------------------------------
30
30
  # Private Methods
31
- #-------------------------------------------------------------
31
+ #-------------------------------------------------------------
32
32
  private
33
-
33
+
34
34
  def relationship_data
35
35
  [
36
- ['docProps/app.xml', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties'],
37
- ['docProps/core.xml', 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties'],
38
- ['word/document.xml', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument']
36
+ ['docProps/app.xml', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties'],
37
+ ['docProps/core.xml', 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties'],
38
+ ['docProps/custom.xml', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties'],
39
+ ['word/document.xml', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument']
39
40
  ]
40
41
  end
41
-
42
+
42
43
  def root_options
43
44
  {
44
45
  'xmlns' => 'http://schemas.openxmlformats.org/package/2006/relationships'
45
46
  }
46
47
  end
47
-
48
+
48
49
  end
49
50
  end
50
- end
51
+ end
@@ -4,80 +4,80 @@ require 'nokogiri'
4
4
  module Caracal
5
5
  module Renderers
6
6
  class XmlRenderer
7
-
7
+
8
8
  #-------------------------------------------------------------
9
9
  # Configuration
10
10
  #-------------------------------------------------------------
11
-
11
+
12
12
  attr_reader :document
13
-
14
-
13
+
14
+
15
15
  #-------------------------------------------------------------
16
16
  # Class Methods
17
17
  #-------------------------------------------------------------
18
-
19
- # This method produces xml output for the given document
18
+
19
+ # This method produces xml output for the given document
20
20
  # according to the rules of this renderer object.
21
21
  #
22
22
  def self.render(doc)
23
23
  renderer = new(doc)
24
24
  renderer.to_xml
25
25
  end
26
-
27
-
26
+
27
+
28
28
  #-------------------------------------------------------------
29
29
  # Public Methods
30
30
  #-------------------------------------------------------------
31
-
31
+
32
32
  # This method instantiates a new verison of this renderer.
33
33
  #
34
34
  def initialize(doc)
35
35
  unless doc.is_a?(Caracal::Document)
36
36
  raise NoDocumentError, 'renderers must receive a reference to a valid Caracal document object.'
37
37
  end
38
-
38
+
39
39
  @document = doc
40
40
  end
41
-
41
+
42
42
  # This method converts data in the specified document to XML.
43
43
  # A concrete implementation must be provided by the subclass.
44
44
  #
45
45
  def to_xml
46
46
  raise NotImplementedError, 'renderers must implement the method :to_xml.'
47
47
  end
48
-
49
-
48
+
49
+
50
50
  #-------------------------------------------------------------
51
51
  # Private Methods
52
52
  #-------------------------------------------------------------
53
53
  private
54
-
55
- # This method returns a Nokogiri::XML object that contains the
54
+
55
+ # This method returns a Nokogiri::XML object that contains the
56
56
  # specific declaration we want.
57
57
  #
58
58
  def declaration_xml
59
59
  ::Nokogiri::XML('<?xml version = "1.0" encoding = "UTF-8" standalone ="yes"?>')
60
60
  end
61
-
61
+
62
62
  # This method returns a commonly used set of attributes for paragraph nodes.
63
63
  #
64
64
  def paragraph_options
65
65
  { 'w:rsidP' => '00000000', 'w:rsidRDefault' => '00000000' }.merge(run_options)
66
66
  end
67
-
67
+
68
68
  # This method returns a commonly used set of attributes for text run nodes.
69
69
  #
70
70
  def run_options
71
71
  { 'w:rsidR' => '00000000', 'w:rsidRPr' => '00000000', 'w:rsidDel' => '00000000' }
72
72
  end
73
-
73
+
74
74
  # These save options force Nokogiri to remove indentation and
75
75
  # line feeds from the output.
76
76
  #
77
77
  def save_options
78
78
  { save_with: Nokogiri::XML::Node::SaveOptions::AS_XML }
79
79
  end
80
-
80
+
81
81
  end
82
82
  end
83
- end
83
+ end
@@ -1,3 +1,3 @@
1
1
  module Caracal
2
- VERSION = '1.0.2'
2
+ VERSION = '1.0.3'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: caracal
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Trade Infomatics
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-12-09 00:00:00.000000000 Z
12
+ date: 2016-01-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: nokogiri
@@ -112,6 +112,7 @@ files:
112
112
  - Rakefile
113
113
  - caracal.gemspec
114
114
  - lib/caracal.rb
115
+ - lib/caracal/core/custom_properties.rb
115
116
  - lib/caracal/core/file_name.rb
116
117
  - lib/caracal/core/fonts.rb
117
118
  - lib/caracal/core/images.rb
@@ -119,6 +120,7 @@ files:
119
120
  - lib/caracal/core/lists.rb
120
121
  - lib/caracal/core/models/base_model.rb
121
122
  - lib/caracal/core/models/border_model.rb
123
+ - lib/caracal/core/models/custom_property_model.rb
122
124
  - lib/caracal/core/models/font_model.rb
123
125
  - lib/caracal/core/models/image_model.rb
124
126
  - lib/caracal/core/models/line_break_model.rb
@@ -150,6 +152,7 @@ files:
150
152
  - lib/caracal/renderers/app_renderer.rb
151
153
  - lib/caracal/renderers/content_types_renderer.rb
152
154
  - lib/caracal/renderers/core_renderer.rb
155
+ - lib/caracal/renderers/custom_renderer.rb
153
156
  - lib/caracal/renderers/document_renderer.rb
154
157
  - lib/caracal/renderers/fonts_renderer.rb
155
158
  - lib/caracal/renderers/footer_renderer.rb