caracal 1.0.4 → 1.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -0
- data/README.md +51 -8
- data/lib/caracal/core/models/table_cell_model.rb +21 -11
- data/lib/caracal/core/models/text_model.rb +17 -8
- data/lib/caracal/renderers/document_renderer.rb +9 -7
- data/lib/caracal/version.rb +1 -1
- data/spec/lib/caracal/core/models/table_cell_model_spec.rb +10 -1
- data/spec/lib/caracal/core/models/text_model_spec.rb +18 -10
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 491450be9349f7528fa95e04b379b72f4807d395
|
4
|
+
data.tar.gz: 823708c706f984673a8f42c64d73e5d4fdc9be87
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 575e505a4c78d7ffc05b87587d12fa94c436ce53c9d466762a84fa9fdeaca974843cec777698ca2cd1bf1ddea1c0727637275f6d3dcc0b3738a7226e29b93f30
|
7
|
+
data.tar.gz: a91c03e2d61d31db942c1c086b462e2528694533055616bb1ff9f30f0f2026c5a4c4b66262c308830c33abb47878dd97f42c9ba0c4994853edded97c1e2fd855
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -84,6 +84,7 @@ You may not know that .docx files are simply a zipped collection of XML document
|
|
84
84
|
|
85
85
|
For each Caracal request, the following document structure will be created and zipped into the final output file:
|
86
86
|
|
87
|
+
```
|
87
88
|
example.docx
|
88
89
|
|- _rels
|
89
90
|
|- .rels
|
@@ -105,6 +106,7 @@ For each Caracal request, the following document structure will be created and z
|
|
105
106
|
|- settings.xml
|
106
107
|
|- styles.xml
|
107
108
|
|- [Content_Types].xml
|
109
|
+
```
|
108
110
|
|
109
111
|
|
110
112
|
## File Descriptions
|
@@ -386,14 +388,15 @@ docx.p 'Sample text.'
|
|
386
388
|
docx.p 'Sample text.', style: 'custom_style'
|
387
389
|
|
388
390
|
docx.p 'Sample text.' do
|
389
|
-
style
|
390
|
-
align
|
391
|
-
color
|
392
|
-
size
|
393
|
-
bold
|
394
|
-
italic
|
395
|
-
underline
|
396
|
-
bgcolor
|
391
|
+
style 'custom_style' # sets the paragraph style. generally used at the exclusion of other attributes.
|
392
|
+
align :left # sets the alignment. accepts :left, :center, :right, and :both.
|
393
|
+
color '333333' # sets the font color.
|
394
|
+
size 32 # sets the font size. units in 1/2 points.
|
395
|
+
bold true # sets whether or not to render the text with a bold weight.
|
396
|
+
italic false # sets whether or not render the text in italic style.
|
397
|
+
underline false # sets whether or not to underline the text.
|
398
|
+
bgcolor 'cccccc' # sets the background color.
|
399
|
+
vertical_align 'superscript' # sets the vertical alignment.
|
397
400
|
end
|
398
401
|
```
|
399
402
|
|
@@ -675,6 +678,46 @@ Caracal includes [Tilt](https://github.com/rtomayko/tilt) integration to facilit
|
|
675
678
|
Rails integration can be added via the [Caracal-Rails](https://github.com/trade-informatics/caracal-rails) gem.
|
676
679
|
|
677
680
|
|
681
|
+
## Filing an Issue
|
682
|
+
|
683
|
+
Caracal was written for and tested against Word 2010, 2013, and Office365. It should also open in LibreOffice
|
684
|
+
with high fidelity.
|
685
|
+
|
686
|
+
### Older Versions
|
687
|
+
If you are using a version of Word that predates 2010, Caracal may or may not work for you. (Probably it won't.)
|
688
|
+
We don't ever plan to support versions before 2010, but if you choose to embark on that endeavor, we'd be
|
689
|
+
happy to answer questions and provide what guidance we can. We just won't write any code in that direction.
|
690
|
+
|
691
|
+
### Newer Versions
|
692
|
+
|
693
|
+
For those using reasonably current versions of Word, please consider the following:
|
694
|
+
|
695
|
+
- Before you file an issue, please run the example Caracal project [caracal-example](https://github.com/trade-informatics/caracal-example) in your development environment and
|
696
|
+
check the output. This project implements nearly every feature Caracal supports and renders the expected output
|
697
|
+
correctly. It can be thought of as a canonical implementation of the library.
|
698
|
+
|
699
|
+
- If you don't see your issue in the example project's implementation of the same feature, chances are you
|
700
|
+
made a mistake in your document's syntax or have an environment-specific, non-caracal problem.
|
701
|
+
|
702
|
+
- If you do see the same behavior in the example project, you've probably uncovered a variance in the way
|
703
|
+
your particular permutation of Windows/Word interprets the OOXML.
|
704
|
+
|
705
|
+
### How to Work on a Problem
|
706
|
+
|
707
|
+
Caracal is essentially an exercise in reverse engineering OOXML output. When developing features, we
|
708
|
+
typically start by building the simplest Word document we can that includes the desired behavior.
|
709
|
+
Then, we change the document extension to .zip, extract the archive, and inspect the resulting OOXML.
|
710
|
+
Finally, we teach the corresponding renderer to output that OOXML.
|
711
|
+
|
712
|
+
It's a tedious process, but it's not nearly as tedious as learning the entire OOXML specification.
|
713
|
+
|
714
|
+
The downside is Word changes its expectations about OOXML format with each version, so it can be a bit
|
715
|
+
of a balancing act to get the OOXML structured for acceptance by all supported versions.
|
716
|
+
|
717
|
+
Ultimately, we'll probably need to implement version-specific renderers (i.e., a set of renderers
|
718
|
+
for 2010/2013, a set for 2016, etc.).
|
719
|
+
|
720
|
+
|
678
721
|
## Contributing
|
679
722
|
|
680
723
|
1. Fork it ( https://github.com/trade-informatics/caracal/fork )
|
@@ -16,19 +16,22 @@ module Caracal
|
|
16
16
|
#-------------------------------------------------------------
|
17
17
|
|
18
18
|
# constants
|
19
|
-
const_set(:DEFAULT_CELL_BACKGROUND,
|
20
|
-
const_set(:DEFAULT_CELL_MARGINS,
|
21
|
-
|
19
|
+
const_set(:DEFAULT_CELL_BACKGROUND, 'ffffff')
|
20
|
+
const_set(:DEFAULT_CELL_MARGINS, Caracal::Core::Models::MarginModel.new({ top: 100, bottom: 100, left: 100, right: 100 }))
|
21
|
+
const_set(:DEFAULT_CELL_VERTICAL_ALIGN, :top)
|
22
|
+
|
22
23
|
# accessors
|
23
24
|
attr_reader :cell_background
|
24
25
|
attr_reader :cell_width
|
25
26
|
attr_reader :cell_margins
|
26
|
-
|
27
|
+
attr_reader :cell_vertical_align
|
28
|
+
|
27
29
|
# initialization
|
28
30
|
def initialize(options={}, &block)
|
29
|
-
@cell_background
|
30
|
-
@cell_margins
|
31
|
-
|
31
|
+
@cell_background = DEFAULT_CELL_BACKGROUND
|
32
|
+
@cell_margins = DEFAULT_CELL_MARGINS
|
33
|
+
@cell_vertical_align = DEFAULT_CELL_VERTICAL_ALIGN
|
34
|
+
|
32
35
|
if content = options.delete(:content)
|
33
36
|
p content, options.dup
|
34
37
|
end
|
@@ -134,8 +137,15 @@ module Caracal
|
|
134
137
|
instance_variable_set("@cell_#{ m }", value.to_s)
|
135
138
|
end
|
136
139
|
end
|
137
|
-
|
138
|
-
|
140
|
+
|
141
|
+
#symbols
|
142
|
+
[:vertical_align].each do |m|
|
143
|
+
define_method "#{ m }" do |value|
|
144
|
+
instance_variable_set("@cell_#{ m }", value.to_s.to_sym)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
|
139
149
|
#=============== VALIDATION ===========================
|
140
150
|
|
141
151
|
def valid?
|
@@ -149,11 +159,11 @@ module Caracal
|
|
149
159
|
private
|
150
160
|
|
151
161
|
def option_keys
|
152
|
-
[:background, :margins, :width]
|
162
|
+
[:background, :margins, :width, :vertical_align]
|
153
163
|
end
|
154
164
|
|
155
165
|
end
|
156
166
|
|
157
167
|
end
|
158
168
|
end
|
159
|
-
end
|
169
|
+
end
|
@@ -23,6 +23,7 @@ module Caracal
|
|
23
23
|
attr_reader :text_italic
|
24
24
|
attr_reader :text_underline
|
25
25
|
attr_reader :text_bgcolor
|
26
|
+
attr_reader :text_vertical_align
|
26
27
|
|
27
28
|
|
28
29
|
|
@@ -35,13 +36,14 @@ module Caracal
|
|
35
36
|
# .run_attributes
|
36
37
|
def run_attributes
|
37
38
|
{
|
38
|
-
font:
|
39
|
-
color:
|
40
|
-
size:
|
41
|
-
bold:
|
42
|
-
italic:
|
43
|
-
underline:
|
44
|
-
bgcolor:
|
39
|
+
font: text_font,
|
40
|
+
color: text_color,
|
41
|
+
size: text_size,
|
42
|
+
bold: text_bold,
|
43
|
+
italic: text_italic,
|
44
|
+
underline: text_underline,
|
45
|
+
bgcolor: text_bgcolor,
|
46
|
+
vertical_align: text_vertical_align
|
45
47
|
}
|
46
48
|
end
|
47
49
|
|
@@ -69,6 +71,13 @@ module Caracal
|
|
69
71
|
end
|
70
72
|
end
|
71
73
|
|
74
|
+
# symbols
|
75
|
+
[:vertical_align].each do |m|
|
76
|
+
define_method "#{ m }" do |value|
|
77
|
+
instance_variable_set("@text_#{ m }", value.to_s.to_sym)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
72
81
|
|
73
82
|
#=============== VALIDATION ===========================
|
74
83
|
|
@@ -84,7 +93,7 @@ module Caracal
|
|
84
93
|
private
|
85
94
|
|
86
95
|
def option_keys
|
87
|
-
[:content, :font, :color, :size, :bold, :italic, :underline, :bgcolor]
|
96
|
+
[:content, :font, :color, :size, :bold, :italic, :underline, :bgcolor, :vertical_align]
|
88
97
|
end
|
89
98
|
|
90
99
|
end
|
@@ -75,13 +75,14 @@ module Caracal
|
|
75
75
|
else
|
76
76
|
xml.send 'w:rPr' do
|
77
77
|
unless attrs.empty?
|
78
|
-
xml.send 'w:rStyle',
|
79
|
-
xml.send 'w:color',
|
80
|
-
xml.send 'w:sz',
|
81
|
-
xml.send 'w:b',
|
82
|
-
xml.send 'w:i',
|
83
|
-
xml.send 'w:u',
|
84
|
-
xml.send 'w:shd',
|
78
|
+
xml.send 'w:rStyle', { 'w:val' => attrs[:style] } unless attrs[:style].nil?
|
79
|
+
xml.send 'w:color', { 'w:val' => attrs[:color] } unless attrs[:color].nil?
|
80
|
+
xml.send 'w:sz', { 'w:val' => attrs[:size] } unless attrs[:size].nil?
|
81
|
+
xml.send 'w:b', { 'w:val' => (attrs[:bold] ? '1' : '0') } unless attrs[:bold].nil?
|
82
|
+
xml.send 'w:i', { 'w:val' => (attrs[:italic] ? '1' : '0') } unless attrs[:italic].nil?
|
83
|
+
xml.send 'w:u', { 'w:val' => (attrs[:underline] ? 'single' : 'none') } unless attrs[:underline].nil?
|
84
|
+
xml.send 'w:shd', { 'w:fill' => attrs[:bgcolor], 'w:val' => 'clear' } unless attrs[:bgcolor].nil?
|
85
|
+
xml.send 'w:vertAlign', { 'w:val' => attrs[:vertical_align] } unless attrs[:vertical_align].nil?
|
85
86
|
unless attrs[:font].nil?
|
86
87
|
f = attrs[:font]
|
87
88
|
xml.send 'w:rFonts', { 'w:ascii' => f, 'w:hAnsi' => f, 'w:eastAsia' => f, 'w:cs' => f }
|
@@ -300,6 +301,7 @@ module Caracal
|
|
300
301
|
xml.send 'w:tc' do
|
301
302
|
xml.send 'tcPr' do
|
302
303
|
xml.send 'w:shd', { 'w:fill' => tc.cell_background }
|
304
|
+
xml.send 'w:vAlign', { 'w:val' => tc.cell_vertical_align }
|
303
305
|
xml.send 'w:tcMar' do
|
304
306
|
%w(top left bottom right).each do |d|
|
305
307
|
xml.send "w:#{ d }", { 'w:w' => tc.send("cell_margin_#{ d }").to_f, 'w:type' => 'dxa' }
|
data/lib/caracal/version.rb
CHANGED
@@ -23,6 +23,7 @@ describe Caracal::Core::Models::TableCellModel do
|
|
23
23
|
# constants
|
24
24
|
describe 'constants' do
|
25
25
|
it { expect(described_class::DEFAULT_CELL_BACKGROUND).to eq 'ffffff' }
|
26
|
+
it { expect(described_class::DEFAULT_CELL_VERTICAL_ALIGN).to eq :top }
|
26
27
|
it { expect(described_class::DEFAULT_CELL_MARGINS).to be_a(Caracal::Core::Models::MarginModel) }
|
27
28
|
it { expect(described_class::DEFAULT_CELL_MARGINS.margin_top).to eq 100 }
|
28
29
|
it { expect(described_class::DEFAULT_CELL_MARGINS.margin_bottom).to eq 100 }
|
@@ -35,6 +36,7 @@ describe Caracal::Core::Models::TableCellModel do
|
|
35
36
|
it { expect(subject.cell_background).to eq 'cccccc' }
|
36
37
|
it { expect(subject.cell_margins).to be_a(Caracal::Core::Models::MarginModel) }
|
37
38
|
it { expect(subject.cell_width).to eq 2000 }
|
39
|
+
it { expect(subject.cell_vertical_align).to eq :top }
|
38
40
|
end
|
39
41
|
|
40
42
|
end
|
@@ -95,6 +97,13 @@ describe Caracal::Core::Models::TableCellModel do
|
|
95
97
|
|
96
98
|
it { expect(subject.cell_width).to eq 7500 }
|
97
99
|
end
|
100
|
+
|
101
|
+
#.vertical_allign
|
102
|
+
describe '.vertical_align' do
|
103
|
+
before { subject.vertical_align(:center) }
|
104
|
+
|
105
|
+
it { expect(subject.cell_vertical_align).to eq :center }
|
106
|
+
end
|
98
107
|
|
99
108
|
|
100
109
|
#=============== CONTENT FNS =======================
|
@@ -211,7 +220,7 @@ describe Caracal::Core::Models::TableCellModel do
|
|
211
220
|
# .option_keys
|
212
221
|
describe '.option_keys' do
|
213
222
|
let(:actual) { subject.send(:option_keys).sort }
|
214
|
-
let(:expected) { [:background, :width, :margins].sort }
|
223
|
+
let(:expected) { [:background, :width, :vertical_align, :margins].sort }
|
215
224
|
|
216
225
|
it { expect(actual).to eq expected }
|
217
226
|
end
|
@@ -3,14 +3,15 @@ require 'spec_helper'
|
|
3
3
|
describe Caracal::Core::Models::TextModel do
|
4
4
|
subject do
|
5
5
|
described_class.new do
|
6
|
-
content
|
7
|
-
font
|
8
|
-
color
|
9
|
-
size
|
10
|
-
bold
|
11
|
-
italic
|
12
|
-
underline
|
13
|
-
bgcolor
|
6
|
+
content 'Lorem ipsum dolor....'
|
7
|
+
font 'Courier New'
|
8
|
+
color '666666'
|
9
|
+
size 20
|
10
|
+
bold false
|
11
|
+
italic false
|
12
|
+
underline true
|
13
|
+
bgcolor 'cccccc'
|
14
|
+
vertical_align :subscript
|
14
15
|
end
|
15
16
|
end
|
16
17
|
|
@@ -30,6 +31,7 @@ describe Caracal::Core::Models::TextModel do
|
|
30
31
|
it { expect(subject.text_italic).to eq false }
|
31
32
|
it { expect(subject.text_underline).to eq true }
|
32
33
|
it { expect(subject.text_bgcolor).to eq 'cccccc' }
|
34
|
+
it { expect(subject.text_vertical_align).to eq :subscript }
|
33
35
|
end
|
34
36
|
|
35
37
|
end
|
@@ -45,7 +47,7 @@ describe Caracal::Core::Models::TextModel do
|
|
45
47
|
|
46
48
|
# .run_attributes
|
47
49
|
describe '.run_attributes' do
|
48
|
-
let(:expected) { { font: 'Courier New', color: '666666', size: 20, bold: false, italic: false, underline: true, bgcolor: 'cccccc' } }
|
50
|
+
let(:expected) { { font: 'Courier New', color: '666666', size: 20, bold: false, italic: false, underline: true, bgcolor: 'cccccc', vertical_align: :subscript } }
|
49
51
|
|
50
52
|
it { expect(subject.run_attributes).to eq expected }
|
51
53
|
end
|
@@ -99,6 +101,12 @@ describe Caracal::Core::Models::TextModel do
|
|
99
101
|
it { expect(subject.text_font).to eq 'Palantino' }
|
100
102
|
end
|
101
103
|
|
104
|
+
#symbols
|
105
|
+
describe '.vertical_align' do
|
106
|
+
before { subject.vertical_align(:superscript) }
|
107
|
+
|
108
|
+
it { expect(subject.text_vertical_align).to eq :superscript }
|
109
|
+
end
|
102
110
|
|
103
111
|
#=============== VALIDATION ===========================
|
104
112
|
|
@@ -129,7 +137,7 @@ describe Caracal::Core::Models::TextModel do
|
|
129
137
|
# .option_keys
|
130
138
|
describe '.option_keys' do
|
131
139
|
let(:actual) { subject.send(:option_keys).sort }
|
132
|
-
let(:expected) { [:bgcolor, :bold, :color, :content, :font, :italic, :size, :underline].sort }
|
140
|
+
let(:expected) { [:bgcolor, :bold, :color, :content, :font, :italic, :size, :underline, :vertical_align].sort }
|
133
141
|
|
134
142
|
it { expect(actual).to eq expected }
|
135
143
|
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.
|
4
|
+
version: 1.0.5
|
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: 2016-
|
12
|
+
date: 2016-05-31 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: nokogiri
|