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.
- 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,90 @@
|
|
|
1
|
+
require 'caracal/core/models/relationship_model'
|
|
2
|
+
require 'caracal/errors'
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
module Caracal
|
|
6
|
+
module Core
|
|
7
|
+
|
|
8
|
+
# This module encapsulates all the functionality related to registering and
|
|
9
|
+
# retrieving relationships.
|
|
10
|
+
#
|
|
11
|
+
module Relationships
|
|
12
|
+
def self.included(base)
|
|
13
|
+
base.class_eval do
|
|
14
|
+
|
|
15
|
+
#-------------------------------------------------------------
|
|
16
|
+
# Configuration
|
|
17
|
+
#-------------------------------------------------------------
|
|
18
|
+
|
|
19
|
+
attr_reader :relationship_counter
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
#-------------------------------------------------------------
|
|
23
|
+
# Class Methods
|
|
24
|
+
#-------------------------------------------------------------
|
|
25
|
+
|
|
26
|
+
def self.default_relationships
|
|
27
|
+
[
|
|
28
|
+
{ target: 'fontTable.xml', type: :font },
|
|
29
|
+
{ target: 'footer1.xml', type: :footer },
|
|
30
|
+
{ target: 'numbering.xml', type: :numbering },
|
|
31
|
+
{ target: 'settings.xml', type: :setting },
|
|
32
|
+
{ target: 'styles.xml', type: :style }
|
|
33
|
+
]
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
#-------------------------------------------------------------
|
|
38
|
+
# Public Methods
|
|
39
|
+
#-------------------------------------------------------------
|
|
40
|
+
|
|
41
|
+
#============== ATTRIBUTES ==========================
|
|
42
|
+
|
|
43
|
+
def relationship(**options, &block)
|
|
44
|
+
id = relationship_counter.to_i + 1
|
|
45
|
+
options.merge!({ id: id })
|
|
46
|
+
|
|
47
|
+
model = Caracal::Core::Models::RelationshipModel.new(options, &block)
|
|
48
|
+
if model.valid?
|
|
49
|
+
@relationship_counter = id
|
|
50
|
+
rel = register_relationship(model)
|
|
51
|
+
else
|
|
52
|
+
raise Caracal::Errors::InvalidModelError, 'relationship must specify the :id, :target, and :type attributes.'
|
|
53
|
+
end
|
|
54
|
+
rel
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
#============== GETTERS =============================
|
|
59
|
+
|
|
60
|
+
def relationships
|
|
61
|
+
@relationships ||= []
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def find_relationship(target)
|
|
65
|
+
relationships.find { |r| r.matches?(target) }
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
#============== REGISTRATION ========================
|
|
70
|
+
|
|
71
|
+
def register_relationship(model)
|
|
72
|
+
unless r = find_relationship(model.relationship_target)
|
|
73
|
+
relationships << model
|
|
74
|
+
r = model
|
|
75
|
+
end
|
|
76
|
+
r
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def unregister_relationship(target)
|
|
80
|
+
if r = find_relationship(target)
|
|
81
|
+
relationships.delete(r)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
end
|
|
90
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
require 'caracal/core/models/rule_model'
|
|
2
|
+
require 'caracal/errors'
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
module Caracal
|
|
6
|
+
module Core
|
|
7
|
+
|
|
8
|
+
# This module encapsulates all the functionality related to adding
|
|
9
|
+
# horizontal rules to the document.
|
|
10
|
+
#
|
|
11
|
+
module Rules
|
|
12
|
+
def self.included(base)
|
|
13
|
+
base.class_eval do
|
|
14
|
+
|
|
15
|
+
#-------------------------------------------------------------
|
|
16
|
+
# Public Methods
|
|
17
|
+
#-------------------------------------------------------------
|
|
18
|
+
|
|
19
|
+
def hr(**options, &block)
|
|
20
|
+
model = Caracal::Core::Models::RuleModel.new(options, &block)
|
|
21
|
+
|
|
22
|
+
if model.valid?
|
|
23
|
+
contents << model
|
|
24
|
+
else
|
|
25
|
+
raise Caracal::Errors::InvalidModelError, 'Horizontal rules require non-zero :size and :spacing values.'
|
|
26
|
+
end
|
|
27
|
+
model
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
require 'caracal/core/models/style_model'
|
|
2
|
+
require 'caracal/errors'
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
module Caracal
|
|
6
|
+
module Core
|
|
7
|
+
|
|
8
|
+
# This module encapsulates all the functionality related to defining
|
|
9
|
+
# paragraph styles.
|
|
10
|
+
#
|
|
11
|
+
module Styles
|
|
12
|
+
def self.included(base)
|
|
13
|
+
base.class_eval do
|
|
14
|
+
|
|
15
|
+
#-------------------------------------------------------------
|
|
16
|
+
# Class Methods
|
|
17
|
+
#-------------------------------------------------------------
|
|
18
|
+
|
|
19
|
+
def self.default_styles
|
|
20
|
+
[
|
|
21
|
+
{ id: 'Normal', name: 'normal', font: 'Arial', size: 20, line: 320, color: '333333' },
|
|
22
|
+
{ id: 'Heading1', name: 'heading 1', font: 'Palatino', size: 36, bottom: 120 },
|
|
23
|
+
{ id: 'Heading2', name: 'heading 2', font: 'Arial', size: 26, top: 120, bottom: 160, bold: true },
|
|
24
|
+
{ id: 'Heading3', name: 'heading 3', font: 'Arial', size: 24, top: 120, bottom: 160, bold: true, italic: true, color: '666666' },
|
|
25
|
+
{ id: 'Heading4', name: 'heading 4', font: 'Palatino', size: 24, top: 120, bottom: 120, bold: true },
|
|
26
|
+
{ id: 'Heading5', name: 'heading 5', font: 'Arial', size: 22, top: 120, bottom: 120, bold: true },
|
|
27
|
+
{ id: 'Heading6', name: 'heading 6', font: 'Arial', size: 22, top: 120, bottom: 120, underline: true, italic: true, color: '666666' },
|
|
28
|
+
{ id: 'Title', name: 'title', font: 'Palatino', size: 60 },
|
|
29
|
+
{ id: 'Subtitle', name: 'subtitle', font: 'Arial', size: 28, top: 60 }
|
|
30
|
+
]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
#-------------------------------------------------------------
|
|
35
|
+
# Public Methods
|
|
36
|
+
#-------------------------------------------------------------
|
|
37
|
+
|
|
38
|
+
#============== ATTRIBUTES ==========================
|
|
39
|
+
|
|
40
|
+
def style(**options, &block)
|
|
41
|
+
model = Caracal::Core::Models::StyleModel.new(options, &block)
|
|
42
|
+
|
|
43
|
+
if model.valid?
|
|
44
|
+
register_style(model)
|
|
45
|
+
else
|
|
46
|
+
raise Caracal::Errors::InvalidModelError, 'style must define an :id and :name.'
|
|
47
|
+
end
|
|
48
|
+
model
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
#============== GETTERS =============================
|
|
53
|
+
|
|
54
|
+
def styles
|
|
55
|
+
@styles ||= []
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def default_style
|
|
59
|
+
styles.find { |s| s.style_default }
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def find_style(id)
|
|
63
|
+
styles.find { |s| s.matches?(id) }
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
#============== REGISTRATION ========================
|
|
68
|
+
|
|
69
|
+
def register_style(model)
|
|
70
|
+
unregister_style(model.style_id)
|
|
71
|
+
styles << model
|
|
72
|
+
model
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def unregister_style(id)
|
|
76
|
+
if s = find_style(id)
|
|
77
|
+
styles.delete(s)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
end
|
|
86
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
require 'caracal/core/models/table_model'
|
|
2
|
+
require 'caracal/errors'
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
module Caracal
|
|
6
|
+
module Core
|
|
7
|
+
|
|
8
|
+
# This module encapsulates all the functionality related to adding tables
|
|
9
|
+
# to the document.
|
|
10
|
+
#
|
|
11
|
+
module Tables
|
|
12
|
+
def self.included(base)
|
|
13
|
+
base.class_eval do
|
|
14
|
+
|
|
15
|
+
#-------------------------------------------------------------
|
|
16
|
+
# Public Methods
|
|
17
|
+
#-------------------------------------------------------------
|
|
18
|
+
|
|
19
|
+
def table(data, **options, &block)
|
|
20
|
+
options.merge!({ data: data })
|
|
21
|
+
|
|
22
|
+
model = Caracal::Core::Models::TableModel.new(options, &block)
|
|
23
|
+
if respond_to?(:page_width)
|
|
24
|
+
container_width = page_width - page_margin_left - page_margin_right
|
|
25
|
+
model.calculate_width(container_width)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
if model.valid?
|
|
29
|
+
contents << model
|
|
30
|
+
else
|
|
31
|
+
raise Caracal::Errors::InvalidModelError, 'Table must be provided data for at least one cell.'
|
|
32
|
+
end
|
|
33
|
+
model
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
require 'caracal/core/models/paragraph_model'
|
|
2
|
+
require 'caracal/errors'
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
module Caracal
|
|
6
|
+
module Core
|
|
7
|
+
|
|
8
|
+
# This module encapsulates all the functionality related to adding text
|
|
9
|
+
# to the document.
|
|
10
|
+
#
|
|
11
|
+
module Text
|
|
12
|
+
def self.included(base)
|
|
13
|
+
base.class_eval do
|
|
14
|
+
|
|
15
|
+
#-------------------------------------------------------------
|
|
16
|
+
# Public Methods
|
|
17
|
+
#-------------------------------------------------------------
|
|
18
|
+
|
|
19
|
+
#============== PARAGRAPHS ==========================
|
|
20
|
+
|
|
21
|
+
def p(*text, **options, &block)
|
|
22
|
+
text.flatten!
|
|
23
|
+
options.merge!( { content: text[0] }) unless text[0].nil?
|
|
24
|
+
|
|
25
|
+
model = Caracal::Core::Models::ParagraphModel.new(options, &block)
|
|
26
|
+
if model.valid?
|
|
27
|
+
contents << model
|
|
28
|
+
else
|
|
29
|
+
raise Caracal::Errors::InvalidModelError, 'Paragraphs and headings, which delegate to the :p command, require at least one text string.'
|
|
30
|
+
end
|
|
31
|
+
model
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
#============== HEADINGS ============================
|
|
36
|
+
|
|
37
|
+
# All heading methods simply delegate to the paragraph
|
|
38
|
+
# model with an explicitly set style class.
|
|
39
|
+
#
|
|
40
|
+
[:h1, :h2, :h3, :h4, :h5, :h6].each do |cmd|
|
|
41
|
+
define_method "#{ cmd }" do |*text, **options, &block|
|
|
42
|
+
options.merge!({ style: style_id_for_header(cmd) })
|
|
43
|
+
p(text, options, &block)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
#-------------------------------------------------------------
|
|
49
|
+
# Private Methods
|
|
50
|
+
#-------------------------------------------------------------
|
|
51
|
+
private
|
|
52
|
+
|
|
53
|
+
# This method translates the html-like command to the
|
|
54
|
+
# corresponding style id.
|
|
55
|
+
#
|
|
56
|
+
def style_id_for_header(command)
|
|
57
|
+
case command.to_s
|
|
58
|
+
when 'h1' then 'Heading1'
|
|
59
|
+
when 'h2' then 'Heading2'
|
|
60
|
+
when 'h3' then 'Heading3'
|
|
61
|
+
when 'h4' then 'Heading4'
|
|
62
|
+
when 'h5' then 'Heading5'
|
|
63
|
+
when 'h6' then 'Heading6'
|
|
64
|
+
else 'Normal'
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
end
|
|
73
|
+
end
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
require 'open-uri'
|
|
2
|
+
require 'zip'
|
|
3
|
+
|
|
4
|
+
require 'caracal/core/file_name'
|
|
5
|
+
require 'caracal/core/fonts'
|
|
6
|
+
require 'caracal/core/images'
|
|
7
|
+
require 'caracal/core/line_breaks'
|
|
8
|
+
require 'caracal/core/list_styles'
|
|
9
|
+
require 'caracal/core/lists'
|
|
10
|
+
require 'caracal/core/page_breaks'
|
|
11
|
+
require 'caracal/core/page_numbers'
|
|
12
|
+
require 'caracal/core/page_settings'
|
|
13
|
+
require 'caracal/core/relationships'
|
|
14
|
+
require 'caracal/core/rules'
|
|
15
|
+
require 'caracal/core/styles'
|
|
16
|
+
require 'caracal/core/tables'
|
|
17
|
+
require 'caracal/core/text'
|
|
18
|
+
|
|
19
|
+
require 'caracal/renderers/app_renderer'
|
|
20
|
+
require 'caracal/renderers/content_types_renderer'
|
|
21
|
+
require 'caracal/renderers/core_renderer'
|
|
22
|
+
require 'caracal/renderers/document_renderer'
|
|
23
|
+
require 'caracal/renderers/fonts_renderer'
|
|
24
|
+
require 'caracal/renderers/footer_renderer'
|
|
25
|
+
require 'caracal/renderers/numbering_renderer'
|
|
26
|
+
require 'caracal/renderers/package_relationships_renderer'
|
|
27
|
+
require 'caracal/renderers/relationships_renderer'
|
|
28
|
+
require 'caracal/renderers/settings_renderer'
|
|
29
|
+
require 'caracal/renderers/styles_renderer'
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
module Caracal
|
|
33
|
+
class Document
|
|
34
|
+
|
|
35
|
+
#-------------------------------------------------------------
|
|
36
|
+
# Configuration
|
|
37
|
+
#-------------------------------------------------------------
|
|
38
|
+
|
|
39
|
+
# mixins (order is important)
|
|
40
|
+
include Caracal::Core::FileName
|
|
41
|
+
|
|
42
|
+
include Caracal::Core::Relationships
|
|
43
|
+
include Caracal::Core::Fonts
|
|
44
|
+
include Caracal::Core::PageSettings
|
|
45
|
+
include Caracal::Core::PageNumbers
|
|
46
|
+
include Caracal::Core::Styles
|
|
47
|
+
include Caracal::Core::ListStyles
|
|
48
|
+
|
|
49
|
+
include Caracal::Core::Images
|
|
50
|
+
include Caracal::Core::LineBreaks
|
|
51
|
+
include Caracal::Core::Lists
|
|
52
|
+
include Caracal::Core::PageBreaks
|
|
53
|
+
include Caracal::Core::Rules
|
|
54
|
+
include Caracal::Core::Tables
|
|
55
|
+
include Caracal::Core::Text
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
#-------------------------------------------------------------
|
|
59
|
+
# Public Class Methods
|
|
60
|
+
#-------------------------------------------------------------
|
|
61
|
+
|
|
62
|
+
#============ GETTERS ===================================
|
|
63
|
+
|
|
64
|
+
# This method returns an array of models which constitute the
|
|
65
|
+
# set of instructions for producing the document content.
|
|
66
|
+
#
|
|
67
|
+
def contents
|
|
68
|
+
@contents ||= []
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
#============ OUTPUT ====================================
|
|
73
|
+
|
|
74
|
+
# This method renders a new Word document and returns it as a
|
|
75
|
+
# a string.
|
|
76
|
+
#
|
|
77
|
+
def self.render(f_name = nil, &block)
|
|
78
|
+
docx = new(f_name, &block)
|
|
79
|
+
buffer = docx.render
|
|
80
|
+
|
|
81
|
+
buffer.rewind
|
|
82
|
+
buffer.sysread
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# This method renders a new Word document and saves it to the
|
|
86
|
+
# file system.
|
|
87
|
+
#
|
|
88
|
+
def self.save(f_name = nil, &block)
|
|
89
|
+
docx = new(f_name, &block)
|
|
90
|
+
buffer = docx.render
|
|
91
|
+
|
|
92
|
+
File.open("./#{ docx.name }", 'w') { |f| f.write(buffer.string) }
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
#-------------------------------------------------------------
|
|
98
|
+
# Public Instance Methods
|
|
99
|
+
#-------------------------------------------------------------
|
|
100
|
+
|
|
101
|
+
# This method instantiates a new word document.
|
|
102
|
+
#
|
|
103
|
+
def initialize(name = nil, &block)
|
|
104
|
+
file_name(name)
|
|
105
|
+
|
|
106
|
+
page_size
|
|
107
|
+
page_margins top: 1440, bottom: 1440, left: 1440, right: 1440
|
|
108
|
+
page_numbers
|
|
109
|
+
|
|
110
|
+
[:relationship, :font, :style, :list_style].each do |method|
|
|
111
|
+
collection = self.class.send("default_#{ method }s")
|
|
112
|
+
collection.each do |item|
|
|
113
|
+
send(method, item)
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
if block_given?
|
|
118
|
+
(block.arity < 1) ? instance_eval(&block) : block[self]
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
#============ RENDERING =================================
|
|
124
|
+
|
|
125
|
+
# This method renders the word document instance into
|
|
126
|
+
# a string buffer. Order is important!
|
|
127
|
+
#
|
|
128
|
+
def render
|
|
129
|
+
buffer = ::Zip::OutputStream.write_buffer do |zip|
|
|
130
|
+
render_package_relationships(zip)
|
|
131
|
+
render_content_types(zip)
|
|
132
|
+
render_app(zip)
|
|
133
|
+
render_core(zip)
|
|
134
|
+
render_fonts(zip)
|
|
135
|
+
render_footer(zip)
|
|
136
|
+
render_settings(zip)
|
|
137
|
+
render_styles(zip)
|
|
138
|
+
render_document(zip)
|
|
139
|
+
render_relationships(zip) # Must go here: Depends on document renderer
|
|
140
|
+
render_media(zip) # Must go here: Depends on document renderer
|
|
141
|
+
render_numbering(zip) # Must go here: Depends on document renderer
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
#-------------------------------------------------------------
|
|
148
|
+
# Private Instance Methods
|
|
149
|
+
#-------------------------------------------------------------
|
|
150
|
+
private
|
|
151
|
+
|
|
152
|
+
#============ RENDERERS =====================================
|
|
153
|
+
|
|
154
|
+
def render_app(zip)
|
|
155
|
+
content = ::Caracal::Renderers::AppRenderer.render(self)
|
|
156
|
+
|
|
157
|
+
zip.put_next_entry('docProps/app.xml')
|
|
158
|
+
zip.write(content)
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def render_content_types(zip)
|
|
162
|
+
content = ::Caracal::Renderers::ContentTypesRenderer.render(self)
|
|
163
|
+
|
|
164
|
+
zip.put_next_entry('[Content_Types].xml')
|
|
165
|
+
zip.write(content)
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def render_core(zip)
|
|
169
|
+
content = ::Caracal::Renderers::CoreRenderer.render(self)
|
|
170
|
+
|
|
171
|
+
zip.put_next_entry('docProps/core.xml')
|
|
172
|
+
zip.write(content)
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def render_document(zip)
|
|
176
|
+
content = ::Caracal::Renderers::DocumentRenderer.render(self)
|
|
177
|
+
|
|
178
|
+
zip.put_next_entry('word/document.xml')
|
|
179
|
+
zip.write(content)
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def render_fonts(zip)
|
|
183
|
+
content = ::Caracal::Renderers::FontsRenderer.render(self)
|
|
184
|
+
|
|
185
|
+
zip.put_next_entry('word/fontTable.xml')
|
|
186
|
+
zip.write(content)
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def render_footer(zip)
|
|
190
|
+
content = ::Caracal::Renderers::FooterRenderer.render(self)
|
|
191
|
+
|
|
192
|
+
zip.put_next_entry('word/footer1.xml')
|
|
193
|
+
zip.write(content)
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
def render_media(zip)
|
|
197
|
+
images = relationships.select { |r| r.relationship_type == :image }
|
|
198
|
+
images.each do |rel|
|
|
199
|
+
content = open(rel.relationship_target).read
|
|
200
|
+
|
|
201
|
+
zip.put_next_entry("word/#{ rel.formatted_target }")
|
|
202
|
+
zip.write(content)
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
def render_numbering(zip)
|
|
207
|
+
content = ::Caracal::Renderers::NumberingRenderer.render(self)
|
|
208
|
+
|
|
209
|
+
zip.put_next_entry('word/numbering.xml')
|
|
210
|
+
zip.write(content)
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def render_package_relationships(zip)
|
|
214
|
+
content = ::Caracal::Renderers::PackageRelationshipsRenderer.render(self)
|
|
215
|
+
|
|
216
|
+
zip.put_next_entry('_rels/.rels')
|
|
217
|
+
zip.write(content)
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
def render_relationships(zip)
|
|
221
|
+
content = ::Caracal::Renderers::RelationshipsRenderer.render(self)
|
|
222
|
+
|
|
223
|
+
zip.put_next_entry('word/_rels/document.xml.rels')
|
|
224
|
+
zip.write(content)
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
def render_settings(zip)
|
|
228
|
+
content = ::Caracal::Renderers::SettingsRenderer.render(self)
|
|
229
|
+
|
|
230
|
+
zip.put_next_entry('word/settings.xml')
|
|
231
|
+
zip.write(content)
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
def render_styles(zip)
|
|
235
|
+
content = ::Caracal::Renderers::StylesRenderer.render(self)
|
|
236
|
+
|
|
237
|
+
zip.put_next_entry('word/styles.xml')
|
|
238
|
+
zip.write(content)
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
end
|
|
242
|
+
end
|