clbustos-rtf 0.3.1 → 0.4.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +16 -1
- data/README.rdoc +13 -1
- data/Rakefile +1 -1
- data/VERSION.yml +2 -2
- data/lib/rtf.rb +2 -1
- data/lib/rtf/list.rb +219 -0
- data/lib/rtf/node.rb +173 -34
- data/test/character_style_test.rb +1 -1
- data/test/colour_table_test.rb +1 -1
- data/test/colour_test.rb +1 -1
- data/test/command_node_test.rb +28 -2
- data/test/container_node_test.rb +1 -1
- data/test/document_style_test.rb +1 -1
- data/test/document_test.rb +1 -1
- data/test/font_table_test.rb +1 -1
- data/test/font_test.rb +1 -1
- data/test/footer_node_test.rb +1 -1
- data/test/header_node_test.rb +1 -1
- data/test/image_node_test.rb +1 -1
- data/test/information_test.rb +2 -2
- data/test/node_test.rb +1 -1
- data/test/paragraph_style_test.rb +1 -1
- data/test/style_test.rb +1 -1
- data/test/table_cell_node_test.rb +1 -1
- data/test/table_node_test.rb +1 -1
- data/test/table_row_node_test.rb +1 -1
- data/test/text_node_test.rb +1 -1
- metadata +33 -27
data/CHANGES
CHANGED
@@ -1,5 +1,20 @@
|
|
1
1
|
== CHANGES
|
2
|
-
|
2
|
+
0.4.2
|
3
|
+
* Fix bug causing TextNode.to_rtf to return nil under 1.8.7[Jason Langenauer]
|
4
|
+
* Tests run under Ruby 1.9.2 and later [clbustos]
|
5
|
+
0.4.1
|
6
|
+
* Links: implemented hyperlinks[Marcello Barnaba]
|
7
|
+
* Lists: add a newline before every new list[Marcello Barnaba]
|
8
|
+
0.4.0
|
9
|
+
* Lists: Decimal: quick&dirty implementation of sequential numbering[Marcello Barnaba]
|
10
|
+
* Lists: Decimal: fixed marker name generation: it must contain the dot[Marcello Barnaba]
|
11
|
+
* Lists: removed last StringIO occurrences in new code[Marcello Barnaba]
|
12
|
+
* Lists: wrote minimal object model test[Marcello Barnaba]
|
13
|
+
* Lists: refactored and cleaned up the API a bit[Marcello Barnaba]
|
14
|
+
* Lists: wrote the API bridge between Nodes and Lists[Marcello Barnaba]
|
15
|
+
* Lists: initial implementation of listtable header generation[Marcello Barnaba]
|
16
|
+
* Node: cleaned up the generic to_rtf, added the .wrap option to the constructor[Marcello Barnaba]
|
17
|
+
* Node: stubbed out paragraph generation into a new ParagraphNode[Marcello Barnaba]
|
3
18
|
0.3.1
|
4
19
|
* Added the #subscript helper to the CommandNode class [vjt]
|
5
20
|
|
data/README.rdoc
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
== Purpose of this fork
|
2
|
+
|
3
|
+
* [DONE] Add support for ordered and unordered lists
|
4
|
+
* [DONE] Add support for hyperlinks
|
5
|
+
* [TODO] Write comprehensive tests for OL and UL
|
6
|
+
* [TODO] Clean up the API
|
7
|
+
* [TODO] DRY the code
|
8
|
+
|
9
|
+
Please, please, please: if you come along this library and would lend me an
|
10
|
+
hand to complete tests, please help. Thank you!
|
11
|
+
|
12
|
+
|
1
13
|
== Ruby Rich Text Format (RTF) Library
|
2
14
|
The RTF library provides a pure Ruby set of functionality that can be used to
|
3
15
|
programmatically create RTF documents. The main aim in developing this library
|
@@ -65,7 +77,7 @@ name space. This is a convenience mechanism that saves on specifically having
|
|
65
77
|
to refer to the module when accessing the RTF library. Next we want to create
|
66
78
|
an RTF document and that is done like this...
|
67
79
|
|
68
|
-
document = RTF::Document.new(RTF::Font::ROMAN)
|
80
|
+
document = RTF::Document.new(RTF::Font.new(RTF::Font::ROMAN, 'Times New Roman'))
|
69
81
|
|
70
82
|
This line of code creates a new Document object, specifying that the default
|
71
83
|
font for the document will the the Times New Roman font. So we have a document,
|
data/Rakefile
CHANGED
data/VERSION.yml
CHANGED
data/lib/rtf.rb
CHANGED
@@ -7,6 +7,7 @@ require 'rtf/style'
|
|
7
7
|
require 'rtf/information'
|
8
8
|
require 'rtf/paper'
|
9
9
|
require 'rtf/node'
|
10
|
+
require 'rtf/list'
|
10
11
|
|
11
12
|
# This module encapsulates all the classes and definitions relating to the RTF
|
12
13
|
# library.
|
@@ -31,4 +32,4 @@ module RTF
|
|
31
32
|
raise RTFError.new(message)
|
32
33
|
end
|
33
34
|
end # End of the RTFError class.
|
34
|
-
end # End of the RTF module.
|
35
|
+
end # End of the RTF module.
|
data/lib/rtf/list.rb
ADDED
@@ -0,0 +1,219 @@
|
|
1
|
+
module RTF
|
2
|
+
class ListTable
|
3
|
+
def initialize
|
4
|
+
@templates = []
|
5
|
+
end
|
6
|
+
|
7
|
+
def new_template
|
8
|
+
@templates.push ListTemplate.new(next_template_id)
|
9
|
+
@templates.last
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_rtf(indent=0)
|
13
|
+
return '' if @templates.empty?
|
14
|
+
|
15
|
+
prefix = indent > 0 ? ' ' * indent : ''
|
16
|
+
|
17
|
+
# List table
|
18
|
+
text = "#{prefix}{\\*\\listtable"
|
19
|
+
@templates.each {|tpl| text << tpl.to_rtf}
|
20
|
+
text << "}"
|
21
|
+
|
22
|
+
# List override table, a Cargo Cult.
|
23
|
+
text << "#{prefix}{\\*\\listoverridetable"
|
24
|
+
@templates.each do |tpl|
|
25
|
+
text << "{\\listoverride\\listid#{tpl.id}\\listoverridecount0\\ls#{tpl.id}}"
|
26
|
+
end
|
27
|
+
text << "}\n"
|
28
|
+
end
|
29
|
+
|
30
|
+
protected
|
31
|
+
def next_template_id
|
32
|
+
@templates.size + 1
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
class ListMarker
|
38
|
+
def initialize(name, codepoint=nil)
|
39
|
+
@name = name
|
40
|
+
@codepoint = codepoint
|
41
|
+
end
|
42
|
+
|
43
|
+
def bullet?
|
44
|
+
!@codepoint.nil?
|
45
|
+
end
|
46
|
+
|
47
|
+
def type
|
48
|
+
bullet? ? :bullet : :decimal
|
49
|
+
end
|
50
|
+
|
51
|
+
def number_type
|
52
|
+
# 23: bullet, 0: arabic
|
53
|
+
# applies to the \levelnfcN macro
|
54
|
+
#
|
55
|
+
bullet? ? 23 : 0
|
56
|
+
end
|
57
|
+
|
58
|
+
def name
|
59
|
+
name = "\\{#@name\\}"
|
60
|
+
name << '.' unless bullet?
|
61
|
+
name
|
62
|
+
end
|
63
|
+
|
64
|
+
def template_format
|
65
|
+
# The first char is the string size, the next ones are
|
66
|
+
# either placeholders (\'0X) or actual characters to
|
67
|
+
# include in the format. In the bullet case, \uc0 is
|
68
|
+
# used to get rid of the multibyte translation: we want
|
69
|
+
# an Unicode character.
|
70
|
+
#
|
71
|
+
# In the decimal case, we have a fixed format, with a
|
72
|
+
# dot following the actual number.
|
73
|
+
#
|
74
|
+
if bullet?
|
75
|
+
"\\'01\\uc0\\u#@codepoint"
|
76
|
+
else
|
77
|
+
"\\'02\\'00. "
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def text_format(n=nil)
|
82
|
+
text =
|
83
|
+
if bullet?
|
84
|
+
"\\uc0\\u#@codepoint"
|
85
|
+
else
|
86
|
+
"#{n}."
|
87
|
+
end
|
88
|
+
|
89
|
+
"\t#{text}\t"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
class ListTemplate
|
94
|
+
attr_reader :id
|
95
|
+
|
96
|
+
Markers = {
|
97
|
+
:disc => ListMarker.new('disc', 0x2022),
|
98
|
+
:hyphen => ListMarker.new('hyphen', 0x2043),
|
99
|
+
:decimal => ListMarker.new('decimal' )
|
100
|
+
}
|
101
|
+
|
102
|
+
def initialize(id)
|
103
|
+
@levels = []
|
104
|
+
@id = id
|
105
|
+
end
|
106
|
+
|
107
|
+
def level_for(level, kind = :bullets)
|
108
|
+
@levels[level-1] ||= begin
|
109
|
+
# Only disc for now: we'll add support
|
110
|
+
# for more customization options later
|
111
|
+
marker = Markers[kind == :bullets ? :disc : :decimal]
|
112
|
+
ListLevel.new(self, marker, level)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def to_rtf(indent=0)
|
117
|
+
prefix = indent > 0 ? ' ' * indent : ''
|
118
|
+
|
119
|
+
text = "#{prefix}{\\list\\listtemplate#{id}\\listhybrid"
|
120
|
+
@levels.each {|lvl| text << lvl.to_rtf}
|
121
|
+
text << "{\\listname;}\\listid#{id}}\n"
|
122
|
+
|
123
|
+
text
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
class ListLevel
|
128
|
+
ValidLevels = (1..9)
|
129
|
+
|
130
|
+
LevelTabs = [
|
131
|
+
220, 720, 1133, 1700, 2267,
|
132
|
+
2834, 3401, 3968, 4535, 5102,
|
133
|
+
5669, 6236, 6803
|
134
|
+
].freeze
|
135
|
+
|
136
|
+
ResetTabs = [560].concat(LevelTabs[2..-1]).freeze
|
137
|
+
|
138
|
+
attr_reader :level, :marker
|
139
|
+
|
140
|
+
def initialize(template, marker, level)
|
141
|
+
unless marker.kind_of? ListMarker
|
142
|
+
RTFError.fire("Invalid marker #{marker.inspect}")
|
143
|
+
end
|
144
|
+
|
145
|
+
unless ValidLevels.include? level
|
146
|
+
RTFError.fire("Invalid list level: #{level}")
|
147
|
+
end
|
148
|
+
|
149
|
+
@template = template
|
150
|
+
@level = level
|
151
|
+
@marker = marker
|
152
|
+
end
|
153
|
+
|
154
|
+
def type
|
155
|
+
@marker.type
|
156
|
+
end
|
157
|
+
|
158
|
+
def reset_tabs
|
159
|
+
ResetTabs
|
160
|
+
end
|
161
|
+
|
162
|
+
def tabs
|
163
|
+
@tabs ||= begin
|
164
|
+
tabs = LevelTabs.dup # Kernel#tap would be prettier here
|
165
|
+
|
166
|
+
(@level - 1).times do
|
167
|
+
# Reverse-engineered while looking at Textedit.app
|
168
|
+
# generated output: they already made sure that it
|
169
|
+
# would look good on every RTF editor :-p
|
170
|
+
#
|
171
|
+
a, = tabs.shift(3)
|
172
|
+
a,b = a + 720, a + 1220
|
173
|
+
tabs.shift while tabs.first < b
|
174
|
+
tabs.unshift a, b
|
175
|
+
end
|
176
|
+
|
177
|
+
tabs
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
def id
|
182
|
+
@id ||= @template.id * 10 + level
|
183
|
+
end
|
184
|
+
|
185
|
+
def indent
|
186
|
+
@indent ||= level * 720
|
187
|
+
end
|
188
|
+
|
189
|
+
def to_rtf(indent=0)
|
190
|
+
prefix = indent > 0 ? ' ' * indent : ''
|
191
|
+
|
192
|
+
text = "#{prefix}{\\listlevel\\levelstartat1"
|
193
|
+
|
194
|
+
# Marker type. The first declaration is for Backward Compatibility (BC).
|
195
|
+
nfc = @marker.number_type
|
196
|
+
text << "\\levelnfc#{nfc}\\levelnfcn#{nfc}"
|
197
|
+
|
198
|
+
# Justification, currently only left justified (0). First decl for BC.
|
199
|
+
text << '\leveljc0\leveljcn0'
|
200
|
+
|
201
|
+
# Character that follows the level text, currently only TAB.
|
202
|
+
text << '\levelfollow0'
|
203
|
+
|
204
|
+
# BC: Minimum distance from the left & right edges.
|
205
|
+
text << '\levelindent0\levelspace360'
|
206
|
+
|
207
|
+
# Marker name
|
208
|
+
text << "{\\*\\levelmarker #{@marker.name}}"
|
209
|
+
|
210
|
+
# Marker text format
|
211
|
+
text << "{\\leveltext\\leveltemplateid#{id}#{@marker.template_format};}"
|
212
|
+
text << '{\levelnumbers;}'
|
213
|
+
|
214
|
+
# The actual spacing
|
215
|
+
text << "\\fi-360\\li#{self.indent}\\lin#{self.indent}}\n"
|
216
|
+
end
|
217
|
+
|
218
|
+
end
|
219
|
+
end
|
data/lib/rtf/node.rb
CHANGED
@@ -120,6 +120,8 @@ module RTF
|
|
120
120
|
rtf.encode("UTF-16LE").each_codepoint.map {|cp|
|
121
121
|
cp < 128 ? cp.chr : "\\u#{cp}\\'3f"
|
122
122
|
}.join("")
|
123
|
+
else
|
124
|
+
rtf
|
123
125
|
end
|
124
126
|
end
|
125
127
|
end # End of the TextNode class.
|
@@ -212,6 +214,9 @@ module RTF
|
|
212
214
|
# be written to separate lines whether the node is converted
|
213
215
|
# to RTF. Defaults to true
|
214
216
|
attr_accessor :split
|
217
|
+
# A boolean to indicate whether the prefix and suffix should
|
218
|
+
# be wrapped in curly braces. Defaults to true.
|
219
|
+
attr_accessor :wrap
|
215
220
|
|
216
221
|
# This is the constructor for the CommandNode class.
|
217
222
|
#
|
@@ -223,11 +228,14 @@ module RTF
|
|
223
228
|
# split:: A boolean to indicate whether the prefix and suffix should
|
224
229
|
# be written to separate lines whether the node is converted
|
225
230
|
# to RTF. Defaults to true.
|
226
|
-
|
231
|
+
# wrap:: A boolean to indicate whether the prefix and suffix should
|
232
|
+
# be wrapped in curly braces. Defaults to true.
|
233
|
+
def initialize(parent, prefix, suffix=nil, split=true, wrap=true)
|
227
234
|
super(parent)
|
228
235
|
@prefix = prefix
|
229
236
|
@suffix = suffix
|
230
237
|
@split = split
|
238
|
+
@wrap = wrap
|
231
239
|
end
|
232
240
|
|
233
241
|
# This method adds text to a command node. If the last child node of the
|
@@ -246,19 +254,20 @@ module RTF
|
|
246
254
|
|
247
255
|
# This method generates the RTF text for a CommandNode object.
|
248
256
|
def to_rtf
|
249
|
-
text
|
250
|
-
|
251
|
-
|
257
|
+
text = StringIO.new
|
258
|
+
|
259
|
+
text << '{' if wrap?
|
260
|
+
text << @prefix if @prefix
|
252
261
|
|
253
|
-
text << "{#{@prefix}"
|
254
|
-
text << separator if self.size > 0
|
255
262
|
self.each do |entry|
|
256
|
-
text << "\n" if
|
257
|
-
|
258
|
-
text << "#{entry.to_rtf}"
|
263
|
+
text << "\n" if split?
|
264
|
+
text << entry.to_rtf
|
259
265
|
end
|
260
|
-
|
261
|
-
text << "
|
266
|
+
|
267
|
+
text << "\n" if split?
|
268
|
+
text << @suffix if @suffix
|
269
|
+
text << '}' if wrap?
|
270
|
+
|
262
271
|
text.string
|
263
272
|
end
|
264
273
|
|
@@ -273,16 +282,43 @@ module RTF
|
|
273
282
|
# for the new paragraph. Defaults to nil to indicate that the
|
274
283
|
# currently applied paragraph styling should be used.
|
275
284
|
def paragraph(style=nil)
|
276
|
-
|
277
|
-
text = StringIO.new
|
278
|
-
text << '\pard'
|
279
|
-
text << style.prefix(nil, nil) if style != nil
|
280
|
-
|
281
|
-
node = CommandNode.new(self, text.string, '\par')
|
285
|
+
node = ParagraphNode.new(self, style)
|
282
286
|
yield node if block_given?
|
283
287
|
self.store(node)
|
284
288
|
end
|
285
289
|
|
290
|
+
# This method provides a short cut means of creating a new ordered or
|
291
|
+
# unordered list. The method requires a block that will be passed a
|
292
|
+
# single parameter that'll be a reference to the first level of the
|
293
|
+
# list. See the +ListLevelNode+ doc for more information.
|
294
|
+
#
|
295
|
+
# Example usage:
|
296
|
+
#
|
297
|
+
# rtf.list do |level1|
|
298
|
+
# level1.item do |li|
|
299
|
+
# li << 'some text'
|
300
|
+
# li.apply(some_style) {|x| x << 'some styled text'}
|
301
|
+
# end
|
302
|
+
#
|
303
|
+
# level1.list(:decimal) do |level2|
|
304
|
+
# level2.item {|li| li << 'some other text in a decimal list'}
|
305
|
+
# level2.item {|li| li << 'and here we go'}
|
306
|
+
# end
|
307
|
+
# end
|
308
|
+
#
|
309
|
+
def list(kind=:bullets)
|
310
|
+
node = ListNode.new(self)
|
311
|
+
yield node.list(kind)
|
312
|
+
self.store(node)
|
313
|
+
end
|
314
|
+
|
315
|
+
def link(url, text=nil)
|
316
|
+
node = LinkNode.new(self, url)
|
317
|
+
node << text if text
|
318
|
+
yield node if block_given?
|
319
|
+
self.store(node)
|
320
|
+
end
|
321
|
+
|
286
322
|
# This method provides a short cut means of creating a line break command
|
287
323
|
# node. This command node does not take a block and may possess no other
|
288
324
|
# content.
|
@@ -541,11 +577,123 @@ module RTF
|
|
541
577
|
node
|
542
578
|
end
|
543
579
|
|
544
|
-
alias :write
|
545
|
-
alias :color
|
580
|
+
alias :write :<<
|
581
|
+
alias :color :colour
|
546
582
|
alias :split? :split
|
583
|
+
alias :wrap? :wrap
|
547
584
|
end # End of the CommandNode class.
|
548
585
|
|
586
|
+
# This class represents a paragraph within an RTF document.
|
587
|
+
class ParagraphNode < CommandNode
|
588
|
+
def initialize(parent, style=nil)
|
589
|
+
prefix = '\pard'
|
590
|
+
prefix << style.prefix(nil, nil) if style
|
591
|
+
|
592
|
+
super(parent, prefix, '\par')
|
593
|
+
end
|
594
|
+
end
|
595
|
+
|
596
|
+
# This class represents an ordered/unordered list within an RTF document.
|
597
|
+
#
|
598
|
+
# Currently list nodes can contain any type of node, but this behaviour
|
599
|
+
# will change in future releases. The class overrides the +list+ method
|
600
|
+
# to return a +ListLevelNode+.
|
601
|
+
#
|
602
|
+
class ListNode < CommandNode
|
603
|
+
def initialize(parent)
|
604
|
+
prefix = "\\"
|
605
|
+
|
606
|
+
suffix = '\pard'
|
607
|
+
suffix << ListLevel::ResetTabs.map {|tw| "\\tx#{tw}"}.join
|
608
|
+
suffix << '\ql\qlnatural\pardirnatural\cf0 \\'
|
609
|
+
|
610
|
+
super(parent, prefix, suffix, true, false)
|
611
|
+
|
612
|
+
@template = root.lists.new_template
|
613
|
+
end
|
614
|
+
|
615
|
+
# This method creates a new +ListLevelNode+ of the given kind and
|
616
|
+
# stores it in the document tree.
|
617
|
+
#
|
618
|
+
# ==== Parameters
|
619
|
+
# kind:: The kind of this list level, may be either :bullets or :decimal
|
620
|
+
def list(kind)
|
621
|
+
self.store ListLevelNode.new(self, @template, kind)
|
622
|
+
end
|
623
|
+
end
|
624
|
+
|
625
|
+
# This class represents a list level, and carries out indenting information
|
626
|
+
# and the bullet or number that is prepended to each +ListTextNode+.
|
627
|
+
#
|
628
|
+
# The class overrides the +list+ method to implement nesting, and provides
|
629
|
+
# the +item+ method to add a new list item, the +ListTextNode+.
|
630
|
+
class ListLevelNode < CommandNode
|
631
|
+
def initialize(parent, template, kind, level=1)
|
632
|
+
@template = template
|
633
|
+
@kind = kind
|
634
|
+
@level = template.level_for(level, kind)
|
635
|
+
|
636
|
+
prefix = '\pard'
|
637
|
+
prefix << @level.tabs.map {|tw| "\\tx#{tw}"}.join
|
638
|
+
prefix << "\\li#{@level.indent}\\fi-#{@level.indent}"
|
639
|
+
prefix << "\\ql\\qlnatural\\pardirnatural\n"
|
640
|
+
prefix << "\\ls#{@template.id}\\ilvl#{@level.level-1}\\cf0"
|
641
|
+
|
642
|
+
super(parent, prefix, nil, true, false)
|
643
|
+
end
|
644
|
+
|
645
|
+
# Returns the kind of this level, either :bullets or :decimal
|
646
|
+
attr_reader :kind
|
647
|
+
|
648
|
+
# Returns the indenting level of this list, from 1 to 9
|
649
|
+
def level
|
650
|
+
@level.level
|
651
|
+
end
|
652
|
+
|
653
|
+
# Creates a new +ListTextNode+ and yields it to the calling block
|
654
|
+
def item
|
655
|
+
node = ListTextNode.new(self, @level)
|
656
|
+
yield node
|
657
|
+
self.store(node)
|
658
|
+
end
|
659
|
+
|
660
|
+
# Creates a new +ListLevelNode+ to implement nested lists
|
661
|
+
def list(kind=@kind)
|
662
|
+
node = ListLevelNode.new(self, @template, kind, @level.level+1)
|
663
|
+
yield node
|
664
|
+
self.store(node)
|
665
|
+
end
|
666
|
+
end
|
667
|
+
|
668
|
+
# This class represents a list item, that can contain text or
|
669
|
+
# other nodes. Currently any type of node is accepted, but after
|
670
|
+
# more extensive testing this behaviour may change.
|
671
|
+
class ListTextNode < CommandNode
|
672
|
+
def initialize(parent, level)
|
673
|
+
@level = level
|
674
|
+
@parent = parent
|
675
|
+
|
676
|
+
number = siblings_count + 1 if parent.kind == :decimal
|
677
|
+
prefix = "{\\listtext#{@level.marker.text_format(number)}}"
|
678
|
+
suffix = '\\'
|
679
|
+
|
680
|
+
super(parent, prefix, suffix, false, false)
|
681
|
+
end
|
682
|
+
|
683
|
+
private
|
684
|
+
def siblings_count
|
685
|
+
parent.children.select {|n| n.kind_of?(self.class)}.size
|
686
|
+
end
|
687
|
+
end
|
688
|
+
|
689
|
+
class LinkNode < CommandNode
|
690
|
+
def initialize(parent, url)
|
691
|
+
prefix = "\\field{\\*\\fldinst HYPERLINK \"#{url}\"}{\\fldrslt "
|
692
|
+
suffix = "}"
|
693
|
+
|
694
|
+
super(parent, prefix, suffix, false)
|
695
|
+
end
|
696
|
+
end
|
549
697
|
|
550
698
|
# This class represents a table node within an RTF document. Table nodes are
|
551
699
|
# specialised container nodes that contain only TableRowNodes and have their
|
@@ -951,19 +1099,8 @@ module RTF
|
|
951
1099
|
# ComamndNode class to forbid the creation of paragraphs.
|
952
1100
|
#
|
953
1101
|
# ==== Parameters
|
954
|
-
#
|
955
|
-
|
956
|
-
# the paragraph. Defaults to nil.
|
957
|
-
# after:: The amount of space, in twips, to be inserted after
|
958
|
-
# the paragraph. Defaults to nil.
|
959
|
-
# left:: The amount of indentation to place on the left of the
|
960
|
-
# paragraph. Defaults to nil.
|
961
|
-
# right:: The amount of indentation to place on the right of the
|
962
|
-
# paragraph. Defaults to nil.
|
963
|
-
# first:: The amount of indentation to place on the left of the
|
964
|
-
# first line in the paragraph. Defaults to nil.
|
965
|
-
def paragraph(justification=CommandNode::LEFT_JUSTIFY, before=nil,
|
966
|
-
after=nil, left=nil, right=nil, first=nil)
|
1102
|
+
# style:: The paragraph style, ignored
|
1103
|
+
def paragraph(style=nil)
|
967
1104
|
RTFError.fire("TableCellNode#paragraph() called. Table cells cannot "\
|
968
1105
|
"contain paragraphs.")
|
969
1106
|
end
|
@@ -1496,8 +1633,8 @@ module RTF
|
|
1496
1633
|
LC_VIETNAMESE = 1066
|
1497
1634
|
|
1498
1635
|
# Attribute accessor.
|
1499
|
-
attr_reader :fonts, :colours, :information, :character_set,
|
1500
|
-
:style
|
1636
|
+
attr_reader :fonts, :lists, :colours, :information, :character_set,
|
1637
|
+
:language, :style
|
1501
1638
|
|
1502
1639
|
# Attribute mutator.
|
1503
1640
|
attr_writer :character_set, :language
|
@@ -1516,6 +1653,7 @@ module RTF
|
|
1516
1653
|
def initialize(font, style=nil, character=CS_ANSI, language=LC_ENGLISH_UK)
|
1517
1654
|
super(nil, '\rtf1')
|
1518
1655
|
@fonts = FontTable.new(font)
|
1656
|
+
@lists = ListTable.new
|
1519
1657
|
@default_font = 0
|
1520
1658
|
@colours = ColourTable.new
|
1521
1659
|
@information = Information.new
|
@@ -1669,6 +1807,7 @@ module RTF
|
|
1669
1807
|
text << "\n#{@fonts.to_rtf}"
|
1670
1808
|
text << "\n#{@colours.to_rtf}" if @colours.size > 0
|
1671
1809
|
text << "\n#{@information.to_rtf}"
|
1810
|
+
text << "\n#{@lists.to_rtf}"
|
1672
1811
|
if @headers.compact != []
|
1673
1812
|
text << "\n#{@headers[3].to_rtf}" if @headers[3] != nil
|
1674
1813
|
text << "\n#{@headers[2].to_rtf}" if @headers[2] != nil
|
data/test/colour_table_test.rb
CHANGED
data/test/colour_test.rb
CHANGED
data/test/command_node_test.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'test_helper'
|
1
|
+
require File.expand_path(File.dirname(__FILE__)+'/test_helper')
|
2
2
|
|
3
3
|
# Information class unit test class.
|
4
4
|
class CommandNodeTest < Test::Unit::TestCase
|
@@ -40,7 +40,7 @@ class CommandNodeTest < Test::Unit::TestCase
|
|
40
40
|
|
41
41
|
assert(root.paragraph(style) != nil)
|
42
42
|
assert(root.size == 1)
|
43
|
-
assert(root[0].class ==
|
43
|
+
assert(root[0].class == ParagraphNode)
|
44
44
|
assert(root[0].prefix == '\pard\ql')
|
45
45
|
assert(root[0].suffix == '\par')
|
46
46
|
assert(root.split == true)
|
@@ -207,6 +207,32 @@ class CommandNodeTest < Test::Unit::TestCase
|
|
207
207
|
assert(table[0][2].width == 200)
|
208
208
|
end
|
209
209
|
|
210
|
+
# List object model test
|
211
|
+
def test_list
|
212
|
+
root = Document.new(Font.new(Font::ROMAN, 'Arial'))
|
213
|
+
root.list do |l1|
|
214
|
+
assert l1.class == ListLevelNode
|
215
|
+
assert l1.level == 1
|
216
|
+
|
217
|
+
l1.item do |li|
|
218
|
+
assert li.class == ListTextNode
|
219
|
+
text = li << 'text'
|
220
|
+
assert text.class == TextNode
|
221
|
+
assert text.text == 'text'
|
222
|
+
end
|
223
|
+
|
224
|
+
l1.list do |l2|
|
225
|
+
assert l2.class == ListLevelNode
|
226
|
+
assert l2.level == 2
|
227
|
+
l2.item do |li|
|
228
|
+
text = li << 'text'
|
229
|
+
assert text.class == TextNode
|
230
|
+
assert text.text == 'text'
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
210
236
|
# This test checks the previous_node and next_node methods that could not be
|
211
237
|
# fully and properly checked in the NodeTest.rb file.
|
212
238
|
def test_peers
|
data/test/container_node_test.rb
CHANGED
data/test/document_style_test.rb
CHANGED
data/test/document_test.rb
CHANGED
data/test/font_table_test.rb
CHANGED
data/test/font_test.rb
CHANGED
data/test/footer_node_test.rb
CHANGED
data/test/header_node_test.rb
CHANGED
data/test/image_node_test.rb
CHANGED
data/test/information_test.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'test_helper'
|
1
|
+
require File.expand_path(File.dirname(__FILE__)+'/test_helper')
|
2
2
|
|
3
3
|
# Information class unit test class.
|
4
4
|
class InformationTest < Test::Unit::TestCase
|
@@ -124,4 +124,4 @@ class InformationTest < Test::Unit::TestCase
|
|
124
124
|
text << "\\hr#{time.hour}\\min#{time.min}}"
|
125
125
|
text.string
|
126
126
|
end
|
127
|
-
end
|
127
|
+
end
|
data/test/node_test.rb
CHANGED
data/test/style_test.rb
CHANGED
data/test/table_node_test.rb
CHANGED
data/test/table_row_node_test.rb
CHANGED
data/test/text_node_test.rb
CHANGED
metadata
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: clbustos-rtf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
+
hash: 11
|
4
5
|
prerelease: false
|
5
6
|
segments:
|
6
7
|
- 0
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: 0.
|
8
|
+
- 4
|
9
|
+
- 2
|
10
|
+
version: 0.4.2
|
10
11
|
platform: ruby
|
11
12
|
authors:
|
12
13
|
- Peter Wood
|
@@ -14,7 +15,7 @@ autorequire:
|
|
14
15
|
bindir: bin
|
15
16
|
cert_chain: []
|
16
17
|
|
17
|
-
date: 2010-
|
18
|
+
date: 2010-11-23 00:00:00 -03:00
|
18
19
|
default_executable:
|
19
20
|
dependencies: []
|
20
21
|
|
@@ -45,6 +46,7 @@ files:
|
|
45
46
|
- lib/rtf/colour.rb
|
46
47
|
- lib/rtf/font.rb
|
47
48
|
- lib/rtf/information.rb
|
49
|
+
- lib/rtf/list.rb
|
48
50
|
- lib/rtf/node.rb
|
49
51
|
- lib/rtf/paper.rb
|
50
52
|
- lib/rtf/style.rb
|
@@ -80,54 +82,58 @@ homepage: http://github.com/clbustos/rtf
|
|
80
82
|
licenses: []
|
81
83
|
|
82
84
|
post_install_message:
|
83
|
-
rdoc_options:
|
84
|
-
|
85
|
+
rdoc_options: []
|
86
|
+
|
85
87
|
require_paths:
|
86
88
|
- lib
|
87
89
|
required_ruby_version: !ruby/object:Gem::Requirement
|
90
|
+
none: false
|
88
91
|
requirements:
|
89
92
|
- - ">="
|
90
93
|
- !ruby/object:Gem::Version
|
94
|
+
hash: 3
|
91
95
|
segments:
|
92
96
|
- 0
|
93
97
|
version: "0"
|
94
98
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
99
|
+
none: false
|
95
100
|
requirements:
|
96
101
|
- - ">="
|
97
102
|
- !ruby/object:Gem::Version
|
103
|
+
hash: 3
|
98
104
|
segments:
|
99
105
|
- 0
|
100
106
|
version: "0"
|
101
107
|
requirements: []
|
102
108
|
|
103
109
|
rubyforge_project: ruby-statsample
|
104
|
-
rubygems_version: 1.3.
|
110
|
+
rubygems_version: 1.3.7
|
105
111
|
signing_key:
|
106
112
|
specification_version: 3
|
107
113
|
summary: Ruby library to create rich text format documents.
|
108
114
|
test_files:
|
109
|
-
-
|
110
|
-
-
|
111
|
-
-
|
112
|
-
-
|
115
|
+
- examples/example01.rb
|
116
|
+
- examples/example02.rb
|
117
|
+
- examples/example03.rb
|
118
|
+
- examples/example04.rb
|
113
119
|
- test/character_style_test.rb
|
114
|
-
- test/paragraph_style_test.rb
|
115
|
-
- test/font_test.rb
|
116
|
-
- test/document_test.rb
|
117
|
-
- test/style_test.rb
|
118
|
-
- test/font_table_test.rb
|
119
|
-
- test/text_node_test.rb
|
120
|
-
- test/table_node_test.rb
|
121
120
|
- test/colour_table_test.rb
|
122
|
-
- test/
|
121
|
+
- test/colour_test.rb
|
122
|
+
- test/command_node_test.rb
|
123
|
+
- test/container_node_test.rb
|
123
124
|
- test/document_style_test.rb
|
124
|
-
- test/
|
125
|
+
- test/document_test.rb
|
126
|
+
- test/font_table_test.rb
|
127
|
+
- test/font_test.rb
|
125
128
|
- test/footer_node_test.rb
|
126
|
-
- test/table_row_node_test.rb
|
127
|
-
- test/colour_test.rb
|
128
129
|
- test/header_node_test.rb
|
129
|
-
- test/
|
130
|
-
-
|
131
|
-
-
|
132
|
-
-
|
133
|
-
-
|
130
|
+
- test/image_node_test.rb
|
131
|
+
- test/information_test.rb
|
132
|
+
- test/node_test.rb
|
133
|
+
- test/paragraph_style_test.rb
|
134
|
+
- test/style_test.rb
|
135
|
+
- test/table_cell_node_test.rb
|
136
|
+
- test/table_node_test.rb
|
137
|
+
- test/table_row_node_test.rb
|
138
|
+
- test/test_helper.rb
|
139
|
+
- test/text_node_test.rb
|