caracal_the_curve 1.4.1
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/.github/workflows/main.yml +22 -0
- data/.github/workflows/publish_gem.yml +40 -0
- data/.gitignore +25 -0
- data/.travis.yml +20 -0
- data/CHANGELOG.md +141 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +22 -0
- data/README.md +842 -0
- data/Rakefile +7 -0
- data/caracal.gemspec +28 -0
- data/lib/caracal/core/bookmarks.rb +52 -0
- data/lib/caracal/core/custom_properties.rb +49 -0
- data/lib/caracal/core/file_name.rb +43 -0
- data/lib/caracal/core/fonts.rb +75 -0
- data/lib/caracal/core/iframes.rb +42 -0
- data/lib/caracal/core/ignorables.rb +47 -0
- data/lib/caracal/core/images.rb +37 -0
- data/lib/caracal/core/list_styles.rb +93 -0
- data/lib/caracal/core/lists.rb +57 -0
- data/lib/caracal/core/models/base_model.rb +51 -0
- data/lib/caracal/core/models/bookmark_model.rb +86 -0
- data/lib/caracal/core/models/border_model.rb +120 -0
- data/lib/caracal/core/models/custom_property_model.rb +60 -0
- data/lib/caracal/core/models/font_model.rb +64 -0
- data/lib/caracal/core/models/iframe_model.rb +148 -0
- data/lib/caracal/core/models/image_model.rb +133 -0
- data/lib/caracal/core/models/line_break_model.rb +15 -0
- data/lib/caracal/core/models/link_model.rb +94 -0
- data/lib/caracal/core/models/list_item_model.rb +108 -0
- data/lib/caracal/core/models/list_model.rb +132 -0
- data/lib/caracal/core/models/list_style_model.rb +118 -0
- data/lib/caracal/core/models/margin_model.rb +76 -0
- data/lib/caracal/core/models/namespace_model.rb +65 -0
- data/lib/caracal/core/models/page_break_model.rb +61 -0
- data/lib/caracal/core/models/page_number_model.rb +95 -0
- data/lib/caracal/core/models/page_size_model.rb +79 -0
- data/lib/caracal/core/models/paragraph_model.rb +186 -0
- data/lib/caracal/core/models/relationship_model.rb +114 -0
- data/lib/caracal/core/models/rule_model.rb +27 -0
- data/lib/caracal/core/models/style_model.rb +165 -0
- data/lib/caracal/core/models/table_cell_model.rb +176 -0
- data/lib/caracal/core/models/table_model.rb +206 -0
- data/lib/caracal/core/models/text_model.rb +118 -0
- data/lib/caracal/core/namespaces.rb +89 -0
- data/lib/caracal/core/page_breaks.rb +29 -0
- data/lib/caracal/core/page_numbers.rb +58 -0
- data/lib/caracal/core/page_settings.rb +74 -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 +42 -0
- data/lib/caracal/core/text.rb +75 -0
- data/lib/caracal/document.rb +272 -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 +54 -0
- data/lib/caracal/renderers/core_renderer.rb +44 -0
- data/lib/caracal/renderers/custom_renderer.rb +64 -0
- data/lib/caracal/renderers/document_renderer.rb +427 -0
- data/lib/caracal/renderers/fonts_renderer.rb +56 -0
- data/lib/caracal/renderers/footer_renderer.rb +90 -0
- data/lib/caracal/renderers/numbering_renderer.rb +88 -0
- data/lib/caracal/renderers/package_relationships_renderer.rb +51 -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 +181 -0
- data/lib/caracal/renderers/xml_renderer.rb +83 -0
- data/lib/caracal/utilities.rb +23 -0
- data/lib/caracal/version.rb +3 -0
- data/lib/caracal.rb +40 -0
- data/lib/tilt/caracal.rb +21 -0
- data/spec/lib/caracal/core/bookmarks_spec.rb +35 -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/iframes_spec.rb +29 -0
- data/spec/lib/caracal/core/ignorables_spec.rb +79 -0
- data/spec/lib/caracal/core/images_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/bookmark_model_spec.rb +135 -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/iframe_model_spec.rb +83 -0
- data/spec/lib/caracal/core/models/image_model_spec.rb +225 -0
- data/spec/lib/caracal/core/models/line_break_model_spec.rb +21 -0
- data/spec/lib/caracal/core/models/link_model_spec.rb +179 -0
- data/spec/lib/caracal/core/models/list_item_model_spec.rb +197 -0
- data/spec/lib/caracal/core/models/list_model_spec.rb +178 -0
- data/spec/lib/caracal/core/models/list_style_model_spec.rb +198 -0
- data/spec/lib/caracal/core/models/margin_model_spec.rb +111 -0
- data/spec/lib/caracal/core/models/namespace_model_spec.rb +107 -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 +136 -0
- data/spec/lib/caracal/core/models/page_size_model_spec.rb +101 -0
- data/spec/lib/caracal/core/models/paragraph_model_spec.rb +196 -0
- data/spec/lib/caracal/core/models/relationship_model_spec.rb +193 -0
- data/spec/lib/caracal/core/models/rule_model_spec.rb +108 -0
- data/spec/lib/caracal/core/models/style_model_spec.rb +225 -0
- data/spec/lib/caracal/core/models/table_cell_model_spec.rb +230 -0
- data/spec/lib/caracal/core/models/table_model_spec.rb +222 -0
- data/spec/lib/caracal/core/models/text_model_spec.rb +154 -0
- data/spec/lib/caracal/core/namespaces_spec.rb +116 -0
- data/spec/lib/caracal/core/page_breaks_spec.rb +25 -0
- data/spec/lib/caracal/core/page_numbers_spec.rb +89 -0
- data/spec/lib/caracal/core/page_settings_spec.rb +151 -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
- data/spec/support/_fixtures/snippet.docx +0 -0
- metadata +292 -0
@@ -0,0 +1,176 @@
|
|
1
|
+
require 'caracal/core/models/base_model'
|
2
|
+
require 'caracal/core/models/margin_model'
|
3
|
+
require 'caracal/core/models/paragraph_model'
|
4
|
+
|
5
|
+
|
6
|
+
module Caracal
|
7
|
+
module Core
|
8
|
+
module Models
|
9
|
+
|
10
|
+
# This class handles block options passed to tables via their data
|
11
|
+
# collections.
|
12
|
+
#
|
13
|
+
class TableCellModel < BaseModel
|
14
|
+
|
15
|
+
#-------------------------------------------------------------
|
16
|
+
# Configuration
|
17
|
+
#-------------------------------------------------------------
|
18
|
+
|
19
|
+
# constants
|
20
|
+
const_set(:DEFAULT_CELL_BACKGROUND, 'ffffff')
|
21
|
+
const_set(:DEFAULT_CELL_MARGINS, Caracal::Core::Models::MarginModel.new({ top: 100, bottom: 100, left: 100, right: 100 }))
|
22
|
+
const_set(:DEFAULT_CELL_VERTICAL_ALIGN, :top)
|
23
|
+
|
24
|
+
# accessors
|
25
|
+
attr_reader :cell_background
|
26
|
+
attr_reader :cell_width
|
27
|
+
attr_reader :cell_margins
|
28
|
+
attr_reader :cell_vertical_align
|
29
|
+
attr_reader :cell_rowspan
|
30
|
+
attr_reader :cell_colspan
|
31
|
+
|
32
|
+
# initialization
|
33
|
+
def initialize(options={}, &block)
|
34
|
+
@cell_background = DEFAULT_CELL_BACKGROUND
|
35
|
+
@cell_margins = DEFAULT_CELL_MARGINS
|
36
|
+
@cell_vertical_align = DEFAULT_CELL_VERTICAL_ALIGN
|
37
|
+
|
38
|
+
if content = options.delete(:content)
|
39
|
+
p content, options.dup, &block
|
40
|
+
end
|
41
|
+
|
42
|
+
super options, &block
|
43
|
+
|
44
|
+
p_klass = Caracal::Core::Models::ParagraphModel # the final tag in a table cell
|
45
|
+
unless contents.last.is_a? p_klass # *must* be a paragraph for OOXML
|
46
|
+
contents << p_klass.new(content: '') # to not throw an error.
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
#-------------------------------------------------------------
|
52
|
+
# Public Methods
|
53
|
+
#-------------------------------------------------------------
|
54
|
+
|
55
|
+
#=============== DATA ACCESSORS =======================
|
56
|
+
|
57
|
+
def contents
|
58
|
+
@contents ||= []
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
#=============== STYLES ===============================
|
63
|
+
|
64
|
+
# This method allows styles to be applied to this cell
|
65
|
+
# from the table level. It attempts to add the style
|
66
|
+
# first to the instance, and then to any sub-models that
|
67
|
+
# respond to the method.
|
68
|
+
#
|
69
|
+
# In all cases, invalid options will simply be ignored.
|
70
|
+
#
|
71
|
+
def apply_styles(opts={})
|
72
|
+
# make dup of options so we don't
|
73
|
+
# harm args sent to sibling cells
|
74
|
+
options = opts.dup
|
75
|
+
|
76
|
+
# first, try apply to self
|
77
|
+
options.each do |(k,v)|
|
78
|
+
send(k, v) if respond_to?(k)
|
79
|
+
end
|
80
|
+
|
81
|
+
# prevent top-level attrs from trickling down
|
82
|
+
options.delete_if { |(k,v)| option_keys.include?(k) }
|
83
|
+
|
84
|
+
# then, try apply to contents
|
85
|
+
contents.each do |model|
|
86
|
+
options.each do |k,v|
|
87
|
+
model.send(k, v) if model.respond_to?(k)
|
88
|
+
end
|
89
|
+
|
90
|
+
# finally, apply to runs. options do trickle down
|
91
|
+
# because paragraph-level styles don't seem to
|
92
|
+
# affect runs within tables. weirdsies.
|
93
|
+
if model.respond_to?(:runs)
|
94
|
+
model.runs.each do |run|
|
95
|
+
options.each do |k,v|
|
96
|
+
run.send(k, v) if run.respond_to?(k)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def calculate_width(default_width)
|
104
|
+
width(default_width) unless cell_width.to_i > 0
|
105
|
+
|
106
|
+
container_width = cell_width - cell_margin_left - cell_margin_right
|
107
|
+
|
108
|
+
contents.each do |model|
|
109
|
+
if model.respond_to?(:calculate_width)
|
110
|
+
model.calculate_width(container_width) # will always be a TableModel
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
|
116
|
+
#=============== GETTERS ==============================
|
117
|
+
|
118
|
+
# margin attrs
|
119
|
+
[:top, :bottom, :left, :right].each do |m|
|
120
|
+
define_method "cell_margin_#{ m }" do
|
121
|
+
v = cell_margins ? cell_margins.send("margin_#{ m }") : 0
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
|
126
|
+
#=============== SETTERS ==============================
|
127
|
+
|
128
|
+
# integers
|
129
|
+
[:width, :colspan, :rowspan].each do |m|
|
130
|
+
define_method "#{ m }" do |value|
|
131
|
+
instance_variable_set("@cell_#{ m }", value.to_i)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
# models
|
136
|
+
[:margins].each do |m|
|
137
|
+
define_method "#{ m }" do |options = {}, &block|
|
138
|
+
instance_variable_set("@cell_#{ m }", Caracal::Core::Models::MarginModel.new(options, &block))
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
# strings
|
143
|
+
[:background].each do |m|
|
144
|
+
define_method "#{ m }" do |value|
|
145
|
+
instance_variable_set("@cell_#{ m }", value.to_s)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
#symbols
|
150
|
+
[:vertical_align].each do |m|
|
151
|
+
define_method "#{ m }" do |value|
|
152
|
+
instance_variable_set("@cell_#{ m }", value.to_s.to_sym)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
#=============== VALIDATION ===========================
|
157
|
+
|
158
|
+
def valid?
|
159
|
+
contents.size > 0
|
160
|
+
end
|
161
|
+
|
162
|
+
|
163
|
+
#-------------------------------------------------------------
|
164
|
+
# Private Instance Methods
|
165
|
+
#-------------------------------------------------------------
|
166
|
+
private
|
167
|
+
|
168
|
+
def option_keys
|
169
|
+
[:background, :margins, :width, :vertical_align, :rowspan, :colspan]
|
170
|
+
end
|
171
|
+
|
172
|
+
end
|
173
|
+
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
@@ -0,0 +1,206 @@
|
|
1
|
+
require 'caracal/core/models/base_model'
|
2
|
+
require 'caracal/core/models/border_model'
|
3
|
+
require 'caracal/core/models/table_cell_model'
|
4
|
+
|
5
|
+
|
6
|
+
module Caracal
|
7
|
+
module Core
|
8
|
+
module Models
|
9
|
+
|
10
|
+
# This class handles block options passed to the table
|
11
|
+
# method.
|
12
|
+
#
|
13
|
+
class TableModel < BaseModel
|
14
|
+
|
15
|
+
#-------------------------------------------------------------
|
16
|
+
# Configuration
|
17
|
+
#-------------------------------------------------------------
|
18
|
+
|
19
|
+
# constants
|
20
|
+
const_set(:DEFAULT_TABLE_ALIGN, :center) # weirdly, works better w/ full width
|
21
|
+
const_set(:DEFAULT_TABLE_BORDER_COLOR, 'auto')
|
22
|
+
const_set(:DEFAULT_TABLE_BORDER_LINE, :single)
|
23
|
+
const_set(:DEFAULT_TABLE_BORDER_SIZE, 0) # units in 1/8 points
|
24
|
+
const_set(:DEFAULT_TABLE_BORDER_SPACING, 0)
|
25
|
+
|
26
|
+
# accessors
|
27
|
+
attr_reader :table_align
|
28
|
+
attr_reader :table_width
|
29
|
+
attr_reader :table_border_color
|
30
|
+
attr_reader :table_border_line
|
31
|
+
attr_reader :table_border_size
|
32
|
+
attr_reader :table_border_spacing
|
33
|
+
attr_reader :table_border_top # returns border model
|
34
|
+
attr_reader :table_border_bottom # returns border model
|
35
|
+
attr_reader :table_border_left # returns border model
|
36
|
+
attr_reader :table_border_right # returns border model
|
37
|
+
attr_reader :table_border_horizontal # returns border model
|
38
|
+
attr_reader :table_border_vertical # returns border model
|
39
|
+
|
40
|
+
# initialization
|
41
|
+
def initialize(options={}, &block)
|
42
|
+
@table_align = DEFAULT_TABLE_ALIGN
|
43
|
+
@table_border_color = DEFAULT_TABLE_BORDER_COLOR
|
44
|
+
@table_border_line = DEFAULT_TABLE_BORDER_LINE
|
45
|
+
@table_border_size = DEFAULT_TABLE_BORDER_SIZE
|
46
|
+
@table_border_spacing = DEFAULT_TABLE_BORDER_SPACING
|
47
|
+
|
48
|
+
super options, &block
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
#-------------------------------------------------------------
|
53
|
+
# Public Methods
|
54
|
+
#-------------------------------------------------------------
|
55
|
+
|
56
|
+
#=============== DATA ACCESSORS =======================
|
57
|
+
|
58
|
+
def cells
|
59
|
+
rows.flatten
|
60
|
+
end
|
61
|
+
|
62
|
+
def cols
|
63
|
+
rows.reduce([]) do |array, row|
|
64
|
+
row.each_with_index do |cell, index|
|
65
|
+
array[index] = [] if array[index].nil?
|
66
|
+
array[index] << cell
|
67
|
+
end
|
68
|
+
array
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def rows
|
73
|
+
@table_data || [[]]
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
#=============== STYLES ===============================
|
78
|
+
|
79
|
+
# This method sets explicit widths on all wrapped cells
|
80
|
+
# that do not already have widths asided.
|
81
|
+
#
|
82
|
+
def calculate_width(container_width)
|
83
|
+
width(container_width) unless table_width.to_i > 0
|
84
|
+
|
85
|
+
cells.each { |c| c.calculate_width(default_cell_width) }
|
86
|
+
end
|
87
|
+
|
88
|
+
# This method allows tables to be styled several cells
|
89
|
+
# at a time.
|
90
|
+
#
|
91
|
+
# For example, this would style a header row.
|
92
|
+
#
|
93
|
+
# docx.table data do |t|
|
94
|
+
# t.cell_style t.rows[0], background: '3366cc', color: 'ffffff', bold: true
|
95
|
+
# end
|
96
|
+
#
|
97
|
+
def cell_style(models, options={})
|
98
|
+
[models].flatten.compact.each do |m|
|
99
|
+
m.apply_styles(options)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
|
104
|
+
#=============== GETTERS ==============================
|
105
|
+
|
106
|
+
# border attrs
|
107
|
+
[:top, :bottom, :left, :right, :horizontal, :vertical].each do |m|
|
108
|
+
[:color, :line, :size, :spacing].each do |attr|
|
109
|
+
define_method "table_border_#{ m }_#{ attr }" do
|
110
|
+
model = send("table_border_#{ m }")
|
111
|
+
value = (model) ? model.send("border_#{ attr }") : send("table_border_#{ attr }")
|
112
|
+
end
|
113
|
+
end
|
114
|
+
define_method "table_border_#{ m }_total_size" do
|
115
|
+
model = send("table_border_#{ m }")
|
116
|
+
value = (model) ? model.total_size : table_border_size + (2 * table_border_spacing)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
|
121
|
+
#=============== SETTERS ==============================
|
122
|
+
|
123
|
+
# integers
|
124
|
+
[:border_size, :border_spacing, :width].each do |m|
|
125
|
+
define_method "#{ m }" do |value|
|
126
|
+
instance_variable_set("@table_#{ m }", value.to_i)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
# models
|
131
|
+
[:top, :bottom, :left, :right, :horizontal, :vertical].each do |m|
|
132
|
+
define_method "border_#{ m }" do |options = {}, &block|
|
133
|
+
options.merge!({ type: m })
|
134
|
+
instance_variable_set("@table_border_#{ m }", Caracal::Core::Models::BorderModel.new(options, &block))
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
# strings
|
139
|
+
[:border_color].each do |m|
|
140
|
+
define_method "#{ m }" do |value|
|
141
|
+
instance_variable_set("@table_#{ m }", value.to_s)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
# symbols
|
146
|
+
[:border_line, :align].each do |m|
|
147
|
+
define_method "#{ m }" do |value|
|
148
|
+
instance_variable_set("@table_#{ m }", value.to_s.to_sym)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
# .data
|
153
|
+
def data(value)
|
154
|
+
begin
|
155
|
+
@table_data = value.map do |data_row|
|
156
|
+
data_row.map do |data_cell|
|
157
|
+
case data_cell
|
158
|
+
when Caracal::Core::Models::TableCellModel
|
159
|
+
data_cell
|
160
|
+
when Hash
|
161
|
+
Caracal::Core::Models::TableCellModel.new(data_cell)
|
162
|
+
when Proc
|
163
|
+
Caracal::Core::Models::TableCellModel.new(&data_cell)
|
164
|
+
else
|
165
|
+
Caracal::Core::Models::TableCellModel.new({ content: data_cell.to_s })
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
rescue
|
170
|
+
raise Caracal::Errors::InvalidTableDataError, 'Table data must be a two-dimensional array.'
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
|
175
|
+
#=============== VALIDATION ==============================
|
176
|
+
|
177
|
+
def valid?
|
178
|
+
cells.first.is_a?(Caracal::Core::Models::TableCellModel)
|
179
|
+
end
|
180
|
+
|
181
|
+
|
182
|
+
#-------------------------------------------------------------
|
183
|
+
# Private Instance Methods
|
184
|
+
#-------------------------------------------------------------
|
185
|
+
private
|
186
|
+
|
187
|
+
def default_cell_width
|
188
|
+
cell_widths = rows.first.map { |c| c.cell_width.to_i }
|
189
|
+
remaining_width = table_width - cell_widths.reduce(&:+).to_i
|
190
|
+
remaining_cols = cols.size - cell_widths.reject { |w| w == 0 }.size
|
191
|
+
default_width = (remaining_cols == 0) ? 0 : (remaining_width / remaining_cols)
|
192
|
+
end
|
193
|
+
|
194
|
+
def option_keys
|
195
|
+
k = []
|
196
|
+
k << [:data, :align, :width]
|
197
|
+
k << [:border_color, :border_line, :border_size, :border_spacing]
|
198
|
+
k << [:border_bottom, :border_left, :border_right, :border_top, :border_horizontal, :border_vertical]
|
199
|
+
k.flatten
|
200
|
+
end
|
201
|
+
|
202
|
+
end
|
203
|
+
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
@@ -0,0 +1,118 @@
|
|
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
|
+
# text data.
|
10
|
+
#
|
11
|
+
class TextModel < BaseModel
|
12
|
+
|
13
|
+
#--------------------------------------------------
|
14
|
+
# Configuration
|
15
|
+
#--------------------------------------------------
|
16
|
+
|
17
|
+
# accessors
|
18
|
+
attr_reader :text_content
|
19
|
+
attr_reader :text_style
|
20
|
+
attr_reader :text_font
|
21
|
+
attr_reader :text_color
|
22
|
+
attr_reader :text_size
|
23
|
+
attr_reader :text_bold
|
24
|
+
attr_reader :text_italic
|
25
|
+
attr_reader :text_underline
|
26
|
+
attr_reader :text_bgcolor
|
27
|
+
attr_reader :text_highlight_color
|
28
|
+
attr_reader :text_vertical_align
|
29
|
+
|
30
|
+
|
31
|
+
|
32
|
+
#--------------------------------------------------
|
33
|
+
# Public Methods
|
34
|
+
#--------------------------------------------------
|
35
|
+
|
36
|
+
#========== GETTERS ===============================
|
37
|
+
|
38
|
+
# .run_attributes
|
39
|
+
def run_attributes
|
40
|
+
{
|
41
|
+
style: text_style,
|
42
|
+
font: text_font,
|
43
|
+
color: text_color,
|
44
|
+
size: text_size,
|
45
|
+
bold: text_bold,
|
46
|
+
italic: text_italic,
|
47
|
+
underline: text_underline,
|
48
|
+
bgcolor: text_bgcolor,
|
49
|
+
highlight_color: text_highlight_color,
|
50
|
+
vertical_align: text_vertical_align
|
51
|
+
}
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
#========== SETTERS ===============================
|
56
|
+
|
57
|
+
# booleans
|
58
|
+
[:bold, :italic, :underline].each do |m|
|
59
|
+
define_method "#{ m }" do |value|
|
60
|
+
instance_variable_set("@text_#{ m }", !!value)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# integers
|
65
|
+
[:size].each do |m|
|
66
|
+
define_method "#{ m }" do |value|
|
67
|
+
instance_variable_set("@text_#{ m }", value.to_i)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# strings
|
72
|
+
[:bgcolor, :color, :content, :font, :highlight_color, :style].each do |m|
|
73
|
+
define_method "#{ m }" do |value|
|
74
|
+
instance_variable_set("@text_#{ m }", value.to_s)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# symbols
|
79
|
+
[:vertical_align].each do |m|
|
80
|
+
define_method "#{ m }" do |value|
|
81
|
+
instance_variable_set("@text_#{ m }", value.to_s.to_sym)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
#========== VALIDATION ============================
|
87
|
+
|
88
|
+
def valid?
|
89
|
+
a = [:content]
|
90
|
+
a.map { |m| send("text_#{ m }") }.compact.size == a.size
|
91
|
+
end
|
92
|
+
|
93
|
+
|
94
|
+
#--------------------------------------------------
|
95
|
+
# Private Methods
|
96
|
+
#--------------------------------------------------
|
97
|
+
private
|
98
|
+
|
99
|
+
def option_keys
|
100
|
+
[:content, :style, :font, :color, :size, :bold, :italic, :underline, :bgcolor, :highlight_color, :vertical_align]
|
101
|
+
end
|
102
|
+
|
103
|
+
def method_missing(method, *args, &block)
|
104
|
+
# I'm on the fence with respect to this implementation. We're ignoring
|
105
|
+
# :method_missing errors to allow syntax flexibility for paragraph-type
|
106
|
+
# models. The issue is the syntax format of those models--the way we pass
|
107
|
+
# the content value as a special argument--coupled with the model's
|
108
|
+
# ability to accept nested instructions.
|
109
|
+
#
|
110
|
+
# By ignoring method missing errors here, we can pass the entire paragraph
|
111
|
+
# block in the initial, built-in call to :text.
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'caracal/core/models/namespace_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 namespaces.
|
10
|
+
#
|
11
|
+
module Namespaces
|
12
|
+
def self.included(base)
|
13
|
+
base.class_eval do
|
14
|
+
|
15
|
+
#-------------------------------------------------------------
|
16
|
+
# Class Methods
|
17
|
+
#-------------------------------------------------------------
|
18
|
+
|
19
|
+
def self.default_namespaces
|
20
|
+
[
|
21
|
+
{ prefix: 'xmlns:mc', href: 'http://schemas.openxmlformats.org/markup-compatibility/2006' },
|
22
|
+
{ prefix: 'xmlns:o', href: 'urn:schemas-microsoft-com:office:office' },
|
23
|
+
{ prefix: 'xmlns:r', href: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships' },
|
24
|
+
{ prefix: 'xmlns:m', href: 'http://schemas.openxmlformats.org/officeDocument/2006/math' },
|
25
|
+
{ prefix: 'xmlns:v', href: 'urn:schemas-microsoft-com:vml' },
|
26
|
+
{ prefix: 'xmlns:wp', href: 'http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing' },
|
27
|
+
{ prefix: 'xmlns:w10', href: 'urn:schemas-microsoft-com:office:word' },
|
28
|
+
{ prefix: 'xmlns:w', href: 'http://schemas.openxmlformats.org/wordprocessingml/2006/main' },
|
29
|
+
{ prefix: 'xmlns:wne', href: 'http://schemas.microsoft.com/office/word/2006/wordml' },
|
30
|
+
{ prefix: 'xmlns:sl', href: 'http://schemas.openxmlformats.org/schemaLibrary/2006/main' },
|
31
|
+
{ prefix: 'xmlns:a', href: 'http://schemas.openxmlformats.org/drawingml/2006/main' },
|
32
|
+
{ prefix: 'xmlns:pic', href: 'http://schemas.openxmlformats.org/drawingml/2006/picture' },
|
33
|
+
{ prefix: 'xmlns:c', href: 'http://schemas.openxmlformats.org/drawingml/2006/chart' },
|
34
|
+
{ prefix: 'xmlns:lc', href: 'http://schemas.openxmlformats.org/drawingml/2006/lockedCanvas' },
|
35
|
+
{ prefix: 'xmlns:dgm', href: 'http://schemas.openxmlformats.org/drawingml/2006/diagram' }
|
36
|
+
]
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
#-------------------------------------------------------------
|
41
|
+
# Public Methods
|
42
|
+
#-------------------------------------------------------------
|
43
|
+
|
44
|
+
#============== ATTRIBUTES ==========================
|
45
|
+
|
46
|
+
def namespace(options={}, &block)
|
47
|
+
model = Caracal::Core::Models::NamespaceModel.new(options, &block)
|
48
|
+
if model.valid?
|
49
|
+
ns = register_namespace(model)
|
50
|
+
else
|
51
|
+
raise Caracal::Errors::InvalidModelError, 'namespace must specify the :prefix and :href attributes.'
|
52
|
+
end
|
53
|
+
ns
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
#============== GETTERS =============================
|
58
|
+
|
59
|
+
def namespaces
|
60
|
+
@namespaces ||= []
|
61
|
+
end
|
62
|
+
|
63
|
+
def find_namespace(prefix)
|
64
|
+
namespaces.find { |ns| ns.matches?(prefix) }
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
#============== REGISTRATION ========================
|
69
|
+
|
70
|
+
def register_namespace(model)
|
71
|
+
unless ns = find_namespace(model.namespace_prefix)
|
72
|
+
namespaces << model
|
73
|
+
ns = model
|
74
|
+
end
|
75
|
+
ns
|
76
|
+
end
|
77
|
+
|
78
|
+
def unregister_namespace(prefix)
|
79
|
+
if ns = find_namespace(prefix)
|
80
|
+
namespaces.delete(ns)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'caracal/core/models/page_break_model'
|
2
|
+
|
3
|
+
|
4
|
+
module Caracal
|
5
|
+
module Core
|
6
|
+
|
7
|
+
# This module encapsulates all the functionality related to adding page
|
8
|
+
# breaks to the document.
|
9
|
+
#
|
10
|
+
module PageBreaks
|
11
|
+
def self.included(base)
|
12
|
+
base.class_eval do
|
13
|
+
|
14
|
+
#-------------------------------------------------------------
|
15
|
+
# Public Methods
|
16
|
+
#-------------------------------------------------------------
|
17
|
+
|
18
|
+
def page
|
19
|
+
model = Caracal::Core::Models::PageBreakModel.new()
|
20
|
+
contents << model
|
21
|
+
model
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'caracal/core/models/page_number_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 page number behavior.
|
10
|
+
#
|
11
|
+
module PageNumbers
|
12
|
+
def self.included(base)
|
13
|
+
base.class_eval do
|
14
|
+
|
15
|
+
#-------------------------------------------------------------
|
16
|
+
# Configuration
|
17
|
+
#-------------------------------------------------------------
|
18
|
+
|
19
|
+
# constants
|
20
|
+
const_set(:DEFAULT_PAGE_NUMBER_ALIGN, :center)
|
21
|
+
|
22
|
+
# accessors
|
23
|
+
attr_reader :page_number_align
|
24
|
+
attr_reader :page_number_label
|
25
|
+
attr_reader :page_number_label_size
|
26
|
+
attr_reader :page_number_number_size
|
27
|
+
attr_reader :page_number_show
|
28
|
+
|
29
|
+
|
30
|
+
#-------------------------------------------------------------
|
31
|
+
# Public Methods
|
32
|
+
#-------------------------------------------------------------
|
33
|
+
|
34
|
+
# This method controls whether and how page numbers are displayed
|
35
|
+
# on the document.
|
36
|
+
#
|
37
|
+
def page_numbers(*args, &block)
|
38
|
+
options = Caracal::Utilities.extract_options!(args)
|
39
|
+
options.merge!({ show: !!args.first }) unless args.first.nil? # careful: just `args.first` is falsey
|
40
|
+
|
41
|
+
model = Caracal::Core::Models::PageNumberModel.new(options, &block)
|
42
|
+
if model.valid?
|
43
|
+
@page_number_align = model.page_number_align
|
44
|
+
@page_number_label = model.page_number_label
|
45
|
+
@page_number_label_size = model.page_number_label_size
|
46
|
+
@page_number_number_size = model.page_number_number_size
|
47
|
+
@page_number_show = model.page_number_show
|
48
|
+
else
|
49
|
+
raise Caracal::Errors::InvalidModelError, 'page_numbers :align parameter must be :left, :center, or :right'
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|