html-table 1.2.2
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.
- data/CHANGES +72 -0
- data/MANIFEST +41 -0
- data/README +137 -0
- data/doc/attributes.rdoc +143 -0
- data/doc/table.rdoc +157 -0
- data/doc/table_body.rdoc +9 -0
- data/doc/table_caption.rdoc +9 -0
- data/doc/table_colgroup.rdoc +8 -0
- data/doc/table_colgroup_col.rdoc +9 -0
- data/doc/table_foot.rdoc +8 -0
- data/doc/table_head.rdoc +11 -0
- data/doc/table_row.rdoc +105 -0
- data/doc/table_row_data.rdoc +92 -0
- data/doc/table_row_header.rdoc +7 -0
- data/lib/html/attribute_handler.rb +308 -0
- data/lib/html/body.rb +34 -0
- data/lib/html/caption.rb +40 -0
- data/lib/html/col.rb +33 -0
- data/lib/html/colgroup.rb +99 -0
- data/lib/html/data.rb +56 -0
- data/lib/html/foot.rb +43 -0
- data/lib/html/head.rb +42 -0
- data/lib/html/header.rb +56 -0
- data/lib/html/html_handler.rb +94 -0
- data/lib/html/row.rb +129 -0
- data/lib/html/table.rb +227 -0
- data/lib/html/tablesection.rb +42 -0
- data/lib/html/tag_handler.rb +64 -0
- data/test/tc_attribute_handler.rb +259 -0
- data/test/tc_body.rb +97 -0
- data/test/tc_caption.rb +90 -0
- data/test/tc_col.rb +50 -0
- data/test/tc_colgroup.rb +99 -0
- data/test/tc_data.rb +87 -0
- data/test/tc_foot.rb +118 -0
- data/test/tc_head.rb +114 -0
- data/test/tc_header.rb +87 -0
- data/test/tc_html_handler.rb +47 -0
- data/test/tc_row.rb +138 -0
- data/test/tc_table.rb +163 -0
- data/test/tc_tablesection.rb +52 -0
- data/test/ts_all.rb +23 -0
- metadata +96 -0
data/lib/html/row.rb
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
module HTML
|
2
|
+
class Table::Row < Array
|
3
|
+
include AttributeHandler
|
4
|
+
include HtmlHandler
|
5
|
+
@indent_level = 3
|
6
|
+
@end_tags = true
|
7
|
+
|
8
|
+
# Returns a new Table::Row object. Optionally takes a block. If an
|
9
|
+
# argument is provided, it is treated as content.
|
10
|
+
#
|
11
|
+
# Note that, despite the name, Row is a subclass of Array, not Table.
|
12
|
+
def initialize(arg=nil)
|
13
|
+
@html_begin = '<tr'
|
14
|
+
@html_end = '</tr>'
|
15
|
+
yield self if block_given?
|
16
|
+
self.content = arg if arg
|
17
|
+
end
|
18
|
+
|
19
|
+
# Adds content to the Row object.
|
20
|
+
#
|
21
|
+
# Because a Row object doesn't store any of its own content, the
|
22
|
+
# arguments to this method must be a Row::Data object, a Row::Header
|
23
|
+
# object, or a String (or an array of any of these). In the latter case,
|
24
|
+
# a single Row::Data object is created for each string.
|
25
|
+
def content=(arg)
|
26
|
+
if arg.kind_of?(String)
|
27
|
+
td = Table::Row::Data.new(arg)
|
28
|
+
self.push(td)
|
29
|
+
elsif arg.kind_of?(Array)
|
30
|
+
arg.each{ |e|
|
31
|
+
if e.kind_of?(Table::Row::Data) || e.kind_of?(Table::Row::Header)
|
32
|
+
self.push(e)
|
33
|
+
else
|
34
|
+
td = Table::Row::Data.new(e)
|
35
|
+
self.push(td)
|
36
|
+
end
|
37
|
+
}
|
38
|
+
else
|
39
|
+
self.push(arg)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# Returns the number of spaces that tags for this class are indented.
|
44
|
+
# For the Row class, the indention level defaults to 3.
|
45
|
+
def self.indent_level
|
46
|
+
@indent_level
|
47
|
+
end
|
48
|
+
|
49
|
+
# Sets the number of spaces that tags for this class are indented.
|
50
|
+
def self.indent_level=(num)
|
51
|
+
expect(num,Integer)
|
52
|
+
raise ArgumentError if num < 0
|
53
|
+
@indent_level = num
|
54
|
+
end
|
55
|
+
|
56
|
+
# Returns true or false, depending on whether or not the end tags for
|
57
|
+
# this class, </tr>, are included for each row or not. By default, this
|
58
|
+
# is set to true.
|
59
|
+
def self.end_tags?
|
60
|
+
@end_tags
|
61
|
+
end
|
62
|
+
|
63
|
+
# Sets the behavior for whether or not the end tags for this class,
|
64
|
+
# </tr>, are included for each row or not. Only true and false are
|
65
|
+
# valid arguments.
|
66
|
+
def self.end_tags=(bool)
|
67
|
+
expect(bool,[TrueClass,FalseClass])
|
68
|
+
@end_tags = bool
|
69
|
+
end
|
70
|
+
|
71
|
+
# This method has been redefined to only allow certain classes to be
|
72
|
+
# accepted as arguments. Specifically, they are Data and Header. An
|
73
|
+
# Array is also valid, but only if it only includes Data or Header
|
74
|
+
# objects.
|
75
|
+
def []=(index,obj)
|
76
|
+
if obj.kind_of?(Array)
|
77
|
+
obj.each{ |o| expect(o,[Data,Header]) }
|
78
|
+
else
|
79
|
+
expect(obj,[Data,Header])
|
80
|
+
end
|
81
|
+
super
|
82
|
+
end
|
83
|
+
|
84
|
+
# This method has been redefined to only allow certain classes to be
|
85
|
+
# accepted as arguments. Specifically, they are String, Fixnum,
|
86
|
+
# Data and Header.
|
87
|
+
#
|
88
|
+
# A plain string or number pushed onto a Row is automatically
|
89
|
+
# converted to a Data object.
|
90
|
+
def push(*args)
|
91
|
+
args.each do |obj|
|
92
|
+
if obj.kind_of?(String) || obj.kind_of?(Fixnum)
|
93
|
+
td = Table::Row::Data.new(obj.to_s)
|
94
|
+
super(td)
|
95
|
+
next
|
96
|
+
else
|
97
|
+
expect(obj,[Data,Header])
|
98
|
+
end
|
99
|
+
super(obj)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# This method has been redefined to only allow certain classes to be
|
104
|
+
# accepted as arguments. The rules are the same as they are for
|
105
|
+
# Row#push.
|
106
|
+
def <<(obj)
|
107
|
+
if obj.kind_of?(String) || obj.kind_of?(Fixnum)
|
108
|
+
td = Table::Row::Data.new(obj.to_s)
|
109
|
+
super(td)
|
110
|
+
else
|
111
|
+
expect(obj,[Data,Header])
|
112
|
+
end
|
113
|
+
super(obj)
|
114
|
+
end
|
115
|
+
|
116
|
+
# This method has been redefined to only allow certain classes to be
|
117
|
+
# accepted as arguments. The rules are the same as they are for
|
118
|
+
# Row#push.
|
119
|
+
def unshift(obj)
|
120
|
+
if obj.kind_of?(String) || obj.kind_of?(Fixnum)
|
121
|
+
td = Table::Row::Data.new(obj.to_s)
|
122
|
+
super(td)
|
123
|
+
else
|
124
|
+
expect(obj,[Data,Header])
|
125
|
+
end
|
126
|
+
super(obj)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
data/lib/html/table.rb
ADDED
@@ -0,0 +1,227 @@
|
|
1
|
+
require "rbconfig"
|
2
|
+
include Config
|
3
|
+
|
4
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
5
|
+
|
6
|
+
require "attribute_handler"
|
7
|
+
require "html_handler"
|
8
|
+
require "strongtyping"
|
9
|
+
include StrongTyping
|
10
|
+
|
11
|
+
module HTML
|
12
|
+
class Table < Array
|
13
|
+
include AttributeHandler
|
14
|
+
include HtmlHandler
|
15
|
+
VERSION = "1.2.2"
|
16
|
+
@indent_level = 0
|
17
|
+
@html_case = "lower"
|
18
|
+
@@global_end_tags = true
|
19
|
+
|
20
|
+
# Returns a new Table object. Optionally takes a block.
|
21
|
+
# If an argument is provided, it is interpreted as content.
|
22
|
+
def initialize(arg = nil)
|
23
|
+
@html_begin = '<table'
|
24
|
+
@html_body = ''
|
25
|
+
@html_end = '</table>'
|
26
|
+
yield self if block_given?
|
27
|
+
self.content = arg if arg
|
28
|
+
end
|
29
|
+
|
30
|
+
# Adds content to the table. How this method behaves depends on the
|
31
|
+
# type of argument being passed.
|
32
|
+
#
|
33
|
+
# The +arg+ may be a Table::Row object, an Array of Table::Row objects,
|
34
|
+
# an Array of Array's, an Array of Strings, or a single String. In the
|
35
|
+
# last two cases, a single Table::Row with a single Table::Row::Data
|
36
|
+
# object is created, with the string as the content.
|
37
|
+
def content=(arg)
|
38
|
+
if arg.kind_of?(Array)
|
39
|
+
arg.each{ |e|
|
40
|
+
tr = Table::Row.new(e)
|
41
|
+
self.push(tr)
|
42
|
+
}
|
43
|
+
else
|
44
|
+
tr = Table::Row.new(arg)
|
45
|
+
self.push(tr)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Returns true or false, depending on whether or not end tags have been
|
50
|
+
# turned on or off, respectively.
|
51
|
+
def self.global_end_tags?
|
52
|
+
@@global_end_tags
|
53
|
+
end
|
54
|
+
|
55
|
+
# Sets the end tag class variable. This is used to set whether or not
|
56
|
+
# to include optional end tags in the final HTML output. The argument
|
57
|
+
# sent to this method must be true or false. The default value is true.
|
58
|
+
#
|
59
|
+
# Note that mandatory end tags are unaffected by this setting.
|
60
|
+
def self.global_end_tags=(bool)
|
61
|
+
expect(bool,[TrueClass,FalseClass])
|
62
|
+
@@global_end_tags = bool
|
63
|
+
end
|
64
|
+
|
65
|
+
# Returns either "lower" or "upper", indicating the case of all HTML
|
66
|
+
# tags in the final output.
|
67
|
+
def self.html_case
|
68
|
+
@html_case
|
69
|
+
end
|
70
|
+
|
71
|
+
# Sets the case of all HTML tags to either lower or upper. The only
|
72
|
+
# valid arguments to this method are 'upper' or 'lower'.
|
73
|
+
def self.html_case=(arg)
|
74
|
+
expect(arg,String)
|
75
|
+
arg.downcase!
|
76
|
+
unless arg == "upper" || arg == "lower"
|
77
|
+
msg = "Argument to html_case() must be 'upper' or 'lower'"
|
78
|
+
raise ArgumentError, msg
|
79
|
+
end
|
80
|
+
@html_case = arg
|
81
|
+
end
|
82
|
+
|
83
|
+
# Returns the number of spaces that tags for this class are indented.
|
84
|
+
# For the Table class, the indention level defaults to 0.
|
85
|
+
#
|
86
|
+
# Note that each class has its own default indentation level (a multiple
|
87
|
+
# of 3).
|
88
|
+
def self.indent_level
|
89
|
+
@indent_level
|
90
|
+
end
|
91
|
+
|
92
|
+
# Sets the number of spaces that tags for this class are indented.
|
93
|
+
def self.indent_level=(num)
|
94
|
+
expect(num,Integer)
|
95
|
+
raise ArgumentError,"indent level must be >= 0" if num < 0
|
96
|
+
@indent_level = num
|
97
|
+
end
|
98
|
+
|
99
|
+
# This method has been redefined to only allow certain subclasses to
|
100
|
+
# be assigned using a direct index notation. Specifically, only
|
101
|
+
# Caption, ColGroup, Body, Foot, Head and Row objects may be use
|
102
|
+
# assigned using direct index notation.
|
103
|
+
#
|
104
|
+
# In addition, a Caption can only be assigned to index 0. A Head can
|
105
|
+
# only be assigned to index 0, or index 1 if a Caption already exists.
|
106
|
+
# A Foot may only be assigned as the last element.
|
107
|
+
def []=(index,obj)
|
108
|
+
expect(obj,[Caption,ColGroup,Body,Foot,Head,Row])
|
109
|
+
|
110
|
+
# Only allow Caption objects at index 0
|
111
|
+
if index != 0 && obj.kind_of?(HTML::Table::Caption)
|
112
|
+
msg = "CAPTION can only be added at index 0"
|
113
|
+
raise ArgumentError, msg
|
114
|
+
end
|
115
|
+
|
116
|
+
# Only allow Head objects at index 0 or 1
|
117
|
+
if obj.kind_of?(HTML::Table::Head)
|
118
|
+
if self[0].kind_of?(HTML::Table::Caption) && index != 1
|
119
|
+
msg = "THEAD must be at index 1 when Caption is included"
|
120
|
+
raise ArgumentError, msg
|
121
|
+
end
|
122
|
+
if !self[0].kind_of?(HTML::Table::Caption) && index != 0
|
123
|
+
msg = "THEAD must be at index 0 when no Caption is included"
|
124
|
+
raise ArgumentError, msg
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
if obj.kind_of?(HTML::Table::Foot) && index != -1
|
129
|
+
msg = "FOOT must be last element"
|
130
|
+
raise ArgumentError, msg
|
131
|
+
end
|
132
|
+
super
|
133
|
+
end
|
134
|
+
|
135
|
+
# This method has been redefined to only allow certain subclasses to
|
136
|
+
# be accepted as arguments. Specifically, only Caption, ColGroup,
|
137
|
+
# Body, Foot, Head, Row and Row::Data objects may be pushed onto a
|
138
|
+
# Table.
|
139
|
+
#
|
140
|
+
# Pushing a Data or Header object onto a Table object creates its own
|
141
|
+
# row for each. If a Caption object is pushed onto the Table, it will
|
142
|
+
# automatically be bumped to the first element. If a Head object is
|
143
|
+
# pushed onto the Table, it is automatically bumped to the first
|
144
|
+
# element, or the second element if a Caption already exists.
|
145
|
+
def push(*args)
|
146
|
+
args.each{ |obj|
|
147
|
+
expect(obj,[Caption,ColGroup,Body,Foot,Head,Row,Row::Data])
|
148
|
+
|
149
|
+
# Pushing Data or Header objects onto a Table directly gives them
|
150
|
+
# each their own row.
|
151
|
+
if obj.kind_of?(HTML::Table::Row::Data)
|
152
|
+
tr = HTML::Table::Row.new(obj)
|
153
|
+
self.push(tr)
|
154
|
+
# Caption objects are always the first row
|
155
|
+
elsif obj.kind_of?(HTML::Table::Caption)
|
156
|
+
if self[0].kind_of?(HTML::Table::Caption)
|
157
|
+
self[0] = obj
|
158
|
+
else
|
159
|
+
self.unshift(obj)
|
160
|
+
end
|
161
|
+
# Head objects are always at row 0 or 1
|
162
|
+
elsif obj.kind_of?(HTML::Table::Head)
|
163
|
+
if self[0].kind_of?(HTML::Table::Caption)
|
164
|
+
self.unshift(obj)
|
165
|
+
self[0],self[1] = self[1],self[0]
|
166
|
+
else
|
167
|
+
self.unshift(obj)
|
168
|
+
end
|
169
|
+
else
|
170
|
+
super(obj)
|
171
|
+
end
|
172
|
+
}
|
173
|
+
end
|
174
|
+
|
175
|
+
# This method has been redefined to only allow certain subclasses to
|
176
|
+
# be accepted as arguments.
|
177
|
+
#
|
178
|
+
# The restrictions and behavior are identical to the push() method.
|
179
|
+
def <<(obj)
|
180
|
+
expect(obj,[Caption,ColGroup,Body,Foot,Head,Row,Row::Data])
|
181
|
+
|
182
|
+
# Pushing Data or Header objects onto a Table directly gives them
|
183
|
+
# each their own row.
|
184
|
+
if obj.kind_of?(HTML::Table::Row::Data)
|
185
|
+
tr = HTML::Table::Row.new(obj)
|
186
|
+
self.push(tr)
|
187
|
+
# Caption objects are always the first row
|
188
|
+
elsif obj.kind_of?(HTML::Table::Caption)
|
189
|
+
if self[0].kind_of?(HTML::Table::Caption)
|
190
|
+
self[0] = obj
|
191
|
+
else
|
192
|
+
self.unshift(obj)
|
193
|
+
end
|
194
|
+
# Head objects are always at row 0 or 1
|
195
|
+
elsif obj.kind_of?(HTML::Table::Head)
|
196
|
+
if self[0].kind_of?(HTML::Table::Caption)
|
197
|
+
self.unshift(obj)
|
198
|
+
self[0],self[1] = self[1],self[0]
|
199
|
+
else
|
200
|
+
self.unshift(obj)
|
201
|
+
end
|
202
|
+
else
|
203
|
+
super(obj)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
# This method has been redefined to only allow certain subclasses to
|
208
|
+
# be unshifted onto a Table object. Specifically, they are Caption,
|
209
|
+
# ColGroup, Body, Foot, Head and Row.
|
210
|
+
def unshift(obj)
|
211
|
+
expect(obj,[Caption,ColGroup,Body,Foot,Head,Row])
|
212
|
+
super
|
213
|
+
end
|
214
|
+
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
require "caption"
|
219
|
+
require "colgroup"
|
220
|
+
require "col"
|
221
|
+
require "row"
|
222
|
+
require "header"
|
223
|
+
require "data"
|
224
|
+
require "tablesection"
|
225
|
+
require "head"
|
226
|
+
require "foot"
|
227
|
+
require "body"
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module HTML
|
2
|
+
# Superclass for THEAD, TBODY, TFOOT
|
3
|
+
class Table::TableSection < Array
|
4
|
+
include AttributeHandler
|
5
|
+
include HtmlHandler
|
6
|
+
def initialize
|
7
|
+
yield self if block_given?
|
8
|
+
end
|
9
|
+
|
10
|
+
# Adds a Table::Row object as content. The +arg+ is passed as the value
|
11
|
+
# to the Table::Row constructor.
|
12
|
+
def content=(arg)
|
13
|
+
tr = Table::Row.new(arg)
|
14
|
+
self.push(tr)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.indent_level
|
18
|
+
@indent_level
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.indent_level=(num)
|
22
|
+
expect(num,Integer)
|
23
|
+
raise ArgumentError,"indent_level must be >= 0" if num < 0
|
24
|
+
@indent_level = num
|
25
|
+
end
|
26
|
+
|
27
|
+
def []=(index,obj)
|
28
|
+
expect(obj,Table::Row)
|
29
|
+
super
|
30
|
+
end
|
31
|
+
|
32
|
+
def push(*args)
|
33
|
+
args.each{ |obj| expect(obj,Table::Row) }
|
34
|
+
super
|
35
|
+
end
|
36
|
+
|
37
|
+
def unshift(obj)
|
38
|
+
expect(obj,Table::Row)
|
39
|
+
super
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
###################################################################
|
2
|
+
# tag_handler.rb
|
3
|
+
#
|
4
|
+
# Module for handling standard html physical tags (<b>, <i>, etc).
|
5
|
+
# Only used for Table objects that contain text content. That
|
6
|
+
# means Table::Row::Data, Table::Row::Header and Table::Caption.
|
7
|
+
###################################################################
|
8
|
+
module Tag_Handler
|
9
|
+
|
10
|
+
def bold=(bool)
|
11
|
+
handle_physical_tag('b',bool)
|
12
|
+
end
|
13
|
+
|
14
|
+
def big=(bool)
|
15
|
+
handle_physical_tag('big',bool)
|
16
|
+
end
|
17
|
+
|
18
|
+
def blink=(bool)
|
19
|
+
if $VERBOSE
|
20
|
+
STDERR.puts("The 'blink' tag is very annoying. Please reconsider.")
|
21
|
+
end
|
22
|
+
handle_physical_tag('blink',bool)
|
23
|
+
end
|
24
|
+
|
25
|
+
def italic=(bool)
|
26
|
+
handle_physical_tag('i',bool)
|
27
|
+
end
|
28
|
+
|
29
|
+
def strike=(bool)
|
30
|
+
handle_physical_tag('strike',bool)
|
31
|
+
end
|
32
|
+
|
33
|
+
def sub=(bool)
|
34
|
+
handle_physical_tag('sub',bool)
|
35
|
+
end
|
36
|
+
|
37
|
+
def sup=(bool)
|
38
|
+
handle_physical_tag('sup',bool)
|
39
|
+
end
|
40
|
+
|
41
|
+
def tt=(bool)
|
42
|
+
handle_physical_tag('tt',bool)
|
43
|
+
end
|
44
|
+
|
45
|
+
def underline=(bool)
|
46
|
+
handle_physical_tag('u',bool)
|
47
|
+
end
|
48
|
+
|
49
|
+
def handle_physical_tag(tag,bool)
|
50
|
+
begin_tag = "<#{tag}>"
|
51
|
+
end_tag = "</#{tag}>"
|
52
|
+
unless bool == true || bool == false
|
53
|
+
msg = "Invalid tag value: #{bool}"
|
54
|
+
raise ArgumentError, msg
|
55
|
+
end
|
56
|
+
if bool == true
|
57
|
+
@html_body = begin_tag + @html_body + end_tag
|
58
|
+
else
|
59
|
+
@html_body.gsub!(/#{begin_tag}|#{end_tag}/,'')
|
60
|
+
end
|
61
|
+
@html_body
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|