feedtools 0.2.18 → 0.2.19
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +28 -0
- data/lib/feed_tools.rb +328 -63
- data/lib/feed_tools/feed.rb +767 -764
- data/lib/feed_tools/feed_item.rb +684 -625
- data/lib/feed_tools/helpers/debug_helper.rb +37 -0
- data/lib/feed_tools/helpers/feed_tools_helper.rb +45 -41
- data/lib/feed_tools/helpers/generic_helper.rb +164 -0
- data/lib/feed_tools/helpers/retrieval_helper.rb +36 -0
- data/rakefile +298 -2
- data/test/unit/amp_test.rb +70 -69
- data/test/unit/atom_test.rb +91 -9
- data/test/unit/cache_test.rb +30 -11
- data/test/unit/cdf_test.rb +6 -4
- data/test/unit/encoding_test.rb +99 -0
- data/test/unit/generation_test.rb +3 -40
- data/test/unit/helper_test.rb +66 -6
- data/test/unit/interface_test.rb +34 -0
- data/test/unit/itunes_test.rb +19 -0
- data/test/unit/nonstandard_test.rb +22 -4
- data/test/unit/rdf_test.rb +19 -0
- data/test/unit/rss_test.rb +137 -43
- metadata +18 -8
- data/lib/feed_tools/vendor/builder.rb +0 -15
- data/lib/feed_tools/vendor/builder/blankslate.rb +0 -55
- data/lib/feed_tools/vendor/builder/xmlbase.rb +0 -144
- data/lib/feed_tools/vendor/builder/xmlevents.rb +0 -65
- data/lib/feed_tools/vendor/builder/xmlmarkup.rb +0 -299
@@ -1,144 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# :stopdoc:
|
3
|
-
require 'builder/blankslate'
|
4
|
-
|
5
|
-
module Builder #:nodoc:
|
6
|
-
|
7
|
-
# Generic error for builder
|
8
|
-
class IllegalBlockError < RuntimeError #:nodoc:
|
9
|
-
end
|
10
|
-
|
11
|
-
# XmlBase is a base class for building XML builders. See
|
12
|
-
# Builder::XmlMarkup and Builder::XmlEvents for examples.
|
13
|
-
class XmlBase < BlankSlate #:nodoc:
|
14
|
-
|
15
|
-
# Create an XML markup builder.
|
16
|
-
#
|
17
|
-
# out:: Object receiving the markup.1 +out+ must respond to
|
18
|
-
# <tt><<</tt>.
|
19
|
-
# indent:: Number of spaces used for indentation (0 implies no
|
20
|
-
# indentation and no line breaks).
|
21
|
-
# initial:: Level of initial indentation.
|
22
|
-
#
|
23
|
-
def initialize(indent=0, initial=0)
|
24
|
-
@indent = indent
|
25
|
-
@level = initial
|
26
|
-
end
|
27
|
-
|
28
|
-
# Create a tag named +sym+. Other than the first argument which
|
29
|
-
# is the tag name, the arguements are the same as the tags
|
30
|
-
# implemented via <tt>method_missing</tt>.
|
31
|
-
def tag!(sym, *args, &block)
|
32
|
-
self.__send__(sym, *args, &block)
|
33
|
-
end
|
34
|
-
|
35
|
-
# Create XML markup based on the name of the method. This method
|
36
|
-
# is never invoked directly, but is called for each markup method
|
37
|
-
# in the markup block.
|
38
|
-
def method_missing(sym, *args, &block)
|
39
|
-
text = nil
|
40
|
-
attrs = nil
|
41
|
-
sym = "#{sym}:#{args.shift}" if args.first.kind_of?(Symbol)
|
42
|
-
args.each do |arg|
|
43
|
-
case arg
|
44
|
-
when Hash
|
45
|
-
attrs ||= {}
|
46
|
-
attrs.merge!(arg)
|
47
|
-
else
|
48
|
-
text ||= ''
|
49
|
-
text << arg.to_s
|
50
|
-
end
|
51
|
-
end
|
52
|
-
if block
|
53
|
-
unless text.nil?
|
54
|
-
raise ArgumentError, "XmlMarkup cannot mix a text argument with a block"
|
55
|
-
end
|
56
|
-
_capture_outer_self(block) if @self.nil?
|
57
|
-
_indent
|
58
|
-
_start_tag(sym, attrs)
|
59
|
-
_newline
|
60
|
-
_nested_structures(block)
|
61
|
-
_indent
|
62
|
-
_end_tag(sym)
|
63
|
-
_newline
|
64
|
-
elsif text.nil?
|
65
|
-
_indent
|
66
|
-
_start_tag(sym, attrs, true)
|
67
|
-
_newline
|
68
|
-
else
|
69
|
-
_indent
|
70
|
-
_start_tag(sym, attrs)
|
71
|
-
text! text
|
72
|
-
_end_tag(sym)
|
73
|
-
_newline
|
74
|
-
end
|
75
|
-
@target
|
76
|
-
end
|
77
|
-
|
78
|
-
# Append text to the output target. Escape any markup. May be
|
79
|
-
# used within the markup brackets as:
|
80
|
-
#
|
81
|
-
# builder.p { br; text! "HI" } #=> <p><br/>HI</p>
|
82
|
-
def text!(text)
|
83
|
-
_text(_escape(text))
|
84
|
-
end
|
85
|
-
|
86
|
-
# Append text to the output target without escaping any markup.
|
87
|
-
# May be used within the markup brackets as:
|
88
|
-
#
|
89
|
-
# builder.p { |x| x << "<br/>HI" } #=> <p><br/>HI</p>
|
90
|
-
#
|
91
|
-
# This is useful when using non-builder enabled software that
|
92
|
-
# generates strings. Just insert the string directly into the
|
93
|
-
# builder without changing the inserted markup.
|
94
|
-
#
|
95
|
-
# It is also useful for stacking builder objects. Builders only
|
96
|
-
# use <tt><<</tt> to append to the target, so by supporting this
|
97
|
-
# method/operation builders can use other builders as their
|
98
|
-
# targets.
|
99
|
-
def <<(text)
|
100
|
-
_text(text)
|
101
|
-
end
|
102
|
-
|
103
|
-
# For some reason, nil? is sent to the XmlMarkup object. If nil?
|
104
|
-
# is not defined and method_missing is invoked, some strange kind
|
105
|
-
# of recursion happens. Since nil? won't ever be an XML tag, it
|
106
|
-
# is pretty safe to define it here. (Note: this is an example of
|
107
|
-
# cargo cult programming,
|
108
|
-
# cf. http://fishbowl.pastiche.org/2004/10/13/cargo_cult_programming).
|
109
|
-
def nil?
|
110
|
-
false
|
111
|
-
end
|
112
|
-
|
113
|
-
private
|
114
|
-
|
115
|
-
def _escape(text)
|
116
|
-
text.
|
117
|
-
gsub(%r{&}, '&').
|
118
|
-
gsub(%r{<}, '<').
|
119
|
-
gsub(%r{>}, '>')
|
120
|
-
end
|
121
|
-
|
122
|
-
def _capture_outer_self(block)
|
123
|
-
@self = eval("self", block)
|
124
|
-
end
|
125
|
-
|
126
|
-
def _newline
|
127
|
-
return if @indent == 0
|
128
|
-
text! "\n"
|
129
|
-
end
|
130
|
-
|
131
|
-
def _indent
|
132
|
-
return if @indent == 0 || @level == 0
|
133
|
-
text!(" " * (@level * @indent))
|
134
|
-
end
|
135
|
-
|
136
|
-
def _nested_structures(block)
|
137
|
-
@level += 1
|
138
|
-
block.call(self)
|
139
|
-
ensure
|
140
|
-
@level -= 1
|
141
|
-
end
|
142
|
-
end
|
143
|
-
end
|
144
|
-
# :startdoc:
|
@@ -1,65 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
#--
|
4
|
-
# Copyright 2004 by Jim Weirich (jim@weirichhouse.org).
|
5
|
-
# All rights reserved.
|
6
|
-
|
7
|
-
# Permission is granted for use, copying, modification, distribution,
|
8
|
-
# and distribution of modified versions of this work as long as the
|
9
|
-
# above copyright notice is included.
|
10
|
-
#++
|
11
|
-
|
12
|
-
# :stopdoc:
|
13
|
-
require 'builder/xmlmarkup'
|
14
|
-
|
15
|
-
module Builder
|
16
|
-
|
17
|
-
# Create a series of SAX-like XML events (e.g. start_tag, end_tag)
|
18
|
-
# from the markup code. XmlEvent objects are used in a way similar
|
19
|
-
# to XmlMarkup objects, except that a series of events are generated
|
20
|
-
# and passed to a handler rather than generating character-based
|
21
|
-
# markup.
|
22
|
-
#
|
23
|
-
# Usage:
|
24
|
-
# xe = Builder::XmlEvents.new(hander)
|
25
|
-
# xe.title("HI") # Sends start_tag/end_tag/text messages to the handler.
|
26
|
-
#
|
27
|
-
# Indentation may also be selected by providing value for the
|
28
|
-
# indentation size and initial indentation level.
|
29
|
-
#
|
30
|
-
# xe = Builder::XmlEvents.new(handler, indent_size, initial_indent_level)
|
31
|
-
#
|
32
|
-
# == XML Event Handler
|
33
|
-
#
|
34
|
-
# The handler object must expect the following events.
|
35
|
-
#
|
36
|
-
# [<tt>start_tag(tag, attrs)</tt>]
|
37
|
-
# Announces that a new tag has been found. +tag+ is the name of
|
38
|
-
# the tag and +attrs+ is a hash of attributes for the tag.
|
39
|
-
#
|
40
|
-
# [<tt>end_tag(tag)</tt>]
|
41
|
-
# Announces that an end tag for +tag+ has been found.
|
42
|
-
#
|
43
|
-
# [<tt>text(text)</tt>]
|
44
|
-
# Announces that a string of characters (+text+) has been found.
|
45
|
-
# A series of characters may be broken up into more than one
|
46
|
-
# +text+ call, so the client cannot assume that a single
|
47
|
-
# callback contains all the text data.
|
48
|
-
#
|
49
|
-
class XmlEvents < XmlMarkup #:nodoc:
|
50
|
-
def text!(text)
|
51
|
-
@target.text(text)
|
52
|
-
end
|
53
|
-
|
54
|
-
def _start_tag(sym, attrs, end_too=false)
|
55
|
-
@target.start_tag(sym, attrs)
|
56
|
-
_end_tag(sym) if end_too
|
57
|
-
end
|
58
|
-
|
59
|
-
def _end_tag(sym)
|
60
|
-
@target.end_tag(sym)
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
end
|
65
|
-
# :startdoc:
|
@@ -1,299 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
#--
|
3
|
-
# Copyright 2004 by Jim Weirich (jim@weirichhouse.org).
|
4
|
-
# All rights reserved.
|
5
|
-
|
6
|
-
# Permission is granted for use, copying, modification, distribution,
|
7
|
-
# and distribution of modified versions of this work as long as the
|
8
|
-
# above copyright notice is included.
|
9
|
-
#++
|
10
|
-
|
11
|
-
# Provide a flexible and easy to use Builder for creating XML markup.
|
12
|
-
# See XmlBuilder for usage details.
|
13
|
-
|
14
|
-
# :stopdoc:
|
15
|
-
require 'builder/xmlbase'
|
16
|
-
|
17
|
-
module Builder #:nodoc:
|
18
|
-
|
19
|
-
# Create XML markup easily. All (well, almost all) methods sent to
|
20
|
-
# an XmlMarkup object will be translated to the equivalent XML
|
21
|
-
# markup. Any method with a block will be treated as an XML markup
|
22
|
-
# tag with nested markup in the block.
|
23
|
-
#
|
24
|
-
# Examples will demonstrate this easier than words. In the
|
25
|
-
# following, +xm+ is an +XmlMarkup+ object.
|
26
|
-
#
|
27
|
-
# xm.em("emphasized") # => <em>emphasized</em>
|
28
|
-
# xm.em { xmm.b("emp & bold") } # => <em><b>emph & bold</b></em>
|
29
|
-
# xm.a("A Link", "href"=>"http://onestepback.org")
|
30
|
-
# # => <a href="http://onestepback.org">A Link</a>
|
31
|
-
# xm.div { br } # => <div><br/></div>
|
32
|
-
# xm.target("name"=>"compile", "option"=>"fast")
|
33
|
-
# # => <target option="fast" name="compile"\>
|
34
|
-
# # NOTE: order of attributes is not specified.
|
35
|
-
#
|
36
|
-
# xm.instruct! # <?xml version="1.0" encoding="UTF-8"?>
|
37
|
-
# xm.html { # <html>
|
38
|
-
# xm.head { # <head>
|
39
|
-
# xm.title("History") # <title>History</title>
|
40
|
-
# } # </head>
|
41
|
-
# xm.body { # <body>
|
42
|
-
# xm.comment! "HI" # <!-- HI -->
|
43
|
-
# xm.h1("Header") # <h1>Header</h1>
|
44
|
-
# xm.p("paragraph") # <p>paragraph</p>
|
45
|
-
# } # </body>
|
46
|
-
# } # </html>
|
47
|
-
#
|
48
|
-
# == Notes:
|
49
|
-
#
|
50
|
-
# * The order that attributes are inserted in markup tags is
|
51
|
-
# undefined.
|
52
|
-
#
|
53
|
-
# * Sometimes you wish to insert text without enclosing tags. Use
|
54
|
-
# the <tt>text!</tt> method to accomplish this.
|
55
|
-
#
|
56
|
-
# Example:
|
57
|
-
#
|
58
|
-
# xm.div { # <div>
|
59
|
-
# xm.text! "line"; xm.br # line<br/>
|
60
|
-
# xm.text! "another line"; xmbr # another line<br/>
|
61
|
-
# } # </div>
|
62
|
-
#
|
63
|
-
# * The special XML characters <, >, and & are converted to <,
|
64
|
-
# > and & automatically. Use the <tt><<</tt> operation to
|
65
|
-
# insert text without modification.
|
66
|
-
#
|
67
|
-
# * Sometimes tags use special characters not allowed in ruby
|
68
|
-
# identifiers. Use the <tt>tag!</tt> method to handle these
|
69
|
-
# cases.
|
70
|
-
#
|
71
|
-
# Example:
|
72
|
-
#
|
73
|
-
# xml.tag!("SOAP:Envelope") { ... }
|
74
|
-
#
|
75
|
-
# will produce ...
|
76
|
-
#
|
77
|
-
# <SOAP:Envelope> ... </SOAP:Envelope>"
|
78
|
-
#
|
79
|
-
# <tt>tag!</tt> will also take text and attribute arguments (after
|
80
|
-
# the tag name) like normal markup methods. (But see the next
|
81
|
-
# bullet item for a better way to handle XML namespaces).
|
82
|
-
#
|
83
|
-
# * Direct support for XML namespaces is now available. If the
|
84
|
-
# first argument to a tag call is a symbol, it will be joined to
|
85
|
-
# the tag to produce a namespace:tag combination. It is easier to
|
86
|
-
# show this than describe it.
|
87
|
-
#
|
88
|
-
# xml.SOAP :Envelope do ... end
|
89
|
-
#
|
90
|
-
# Just put a space before the colon in a namespace to produce the
|
91
|
-
# right form for builder (e.g. "<tt>SOAP:Envelope</tt>" =>
|
92
|
-
# "<tt>xml.SOAP :Envelope</tt>")
|
93
|
-
#
|
94
|
-
# * XmlMarkup builds the markup in any object (called a _target_)
|
95
|
-
# that accepts the <tt><<</tt> method. If no target is given,
|
96
|
-
# then XmlMarkup defaults to a string target.
|
97
|
-
#
|
98
|
-
# Examples:
|
99
|
-
#
|
100
|
-
# xm = Builder::XmlMarkup.new
|
101
|
-
# result = xm.title("yada")
|
102
|
-
# # result is a string containing the markup.
|
103
|
-
#
|
104
|
-
# buffer = ""
|
105
|
-
# xm = Builder::XmlMarkup.new(buffer)
|
106
|
-
# # The markup is appended to buffer (using <<)
|
107
|
-
#
|
108
|
-
# xm = Builder::XmlMarkup.new(STDOUT)
|
109
|
-
# # The markup is written to STDOUT (using <<)
|
110
|
-
#
|
111
|
-
# xm = Builder::XmlMarkup.new
|
112
|
-
# x2 = Builder::XmlMarkup.new(:target=>xm)
|
113
|
-
# # Markup written to +x2+ will be send to +xm+.
|
114
|
-
#
|
115
|
-
# * Indentation is enabled by providing the number of spaces to
|
116
|
-
# indent for each level as a second argument to XmlBuilder.new.
|
117
|
-
# Initial indentation may be specified using a third parameter.
|
118
|
-
#
|
119
|
-
# Example:
|
120
|
-
#
|
121
|
-
# xm = Builder.new(:ident=>2)
|
122
|
-
# # xm will produce nicely formatted and indented XML.
|
123
|
-
#
|
124
|
-
# xm = Builder.new(:indent=>2, :margin=>4)
|
125
|
-
# # xm will produce nicely formatted and indented XML with 2
|
126
|
-
# # spaces per indent and an over all indentation level of 4.
|
127
|
-
#
|
128
|
-
# builder = Builder::XmlMarkup.new(:target=>$stdout, :indent=>2)
|
129
|
-
# builder.name { |b| b.first("Jim"); b.last("Weirich) }
|
130
|
-
# # prints:
|
131
|
-
# # <name>
|
132
|
-
# # <first>Jim</first>
|
133
|
-
# # <last>Weirich</last>
|
134
|
-
# # </name>
|
135
|
-
#
|
136
|
-
# * The instance_eval implementation which forces self to refer to
|
137
|
-
# the message receiver as self is now obsolete. We now use normal
|
138
|
-
# block calls to execute the markup block. This means that all
|
139
|
-
# markup methods must now be explicitly send to the xml builder.
|
140
|
-
# For instance, instead of
|
141
|
-
#
|
142
|
-
# xml.div { strong("text") }
|
143
|
-
#
|
144
|
-
# you need to write:
|
145
|
-
#
|
146
|
-
# xml.div { xml.strong("text") }
|
147
|
-
#
|
148
|
-
# Although more verbose, the subtle change in semantics within the
|
149
|
-
# block was found to be prone to error. To make this change a
|
150
|
-
# little less cumbersome, the markup block now gets the markup
|
151
|
-
# object sent as an argument, allowing you to use a shorter alias
|
152
|
-
# within the block.
|
153
|
-
#
|
154
|
-
# For example:
|
155
|
-
#
|
156
|
-
# xml_builder = Builder::XmlMarkup.new
|
157
|
-
# xml_builder.div { |xml|
|
158
|
-
# xml.stong("text")
|
159
|
-
# }
|
160
|
-
#
|
161
|
-
class XmlMarkup < XmlBase #:nodoc:
|
162
|
-
|
163
|
-
# Create an XML markup builder. Parameters are specified by an
|
164
|
-
# option hash.
|
165
|
-
#
|
166
|
-
# :target=><em>target_object</em>::
|
167
|
-
# Object receiving the markup. +out+ must respond to the
|
168
|
-
# <tt><<</tt> operator. The default is a plain string target.
|
169
|
-
# :indent=><em>indentation</em>::
|
170
|
-
# Number of spaces used for indentation. The default is no
|
171
|
-
# indentation and no line breaks.
|
172
|
-
# :margin=><em>initial_indentation_level</em>::
|
173
|
-
# Amount of initial indentation (specified in levels, not
|
174
|
-
# spaces).
|
175
|
-
#
|
176
|
-
def initialize(options={})
|
177
|
-
indent = options[:indent] || 0
|
178
|
-
margin = options[:margin] || 0
|
179
|
-
super(indent, margin)
|
180
|
-
@target = options[:target] || ""
|
181
|
-
end
|
182
|
-
|
183
|
-
# Return the target of the builder.
|
184
|
-
def target!
|
185
|
-
@target
|
186
|
-
end
|
187
|
-
|
188
|
-
def comment!(comment_text)
|
189
|
-
_ensure_no_block block_given?
|
190
|
-
_special("<!-- ", " -->", comment_text, nil)
|
191
|
-
end
|
192
|
-
|
193
|
-
# Insert an XML declaration into the XML markup.
|
194
|
-
#
|
195
|
-
# For example:
|
196
|
-
#
|
197
|
-
# xml.declare! :ELEMENT, :blah, "yada"
|
198
|
-
# # => <!ELEMENT blah "yada">
|
199
|
-
def declare!(inst, *args, &block)
|
200
|
-
_indent
|
201
|
-
@target << "<!#{inst}"
|
202
|
-
args.each do |arg|
|
203
|
-
case arg
|
204
|
-
when String
|
205
|
-
@target << %{ "#{arg}"}
|
206
|
-
when Symbol
|
207
|
-
@target << " #{arg}"
|
208
|
-
end
|
209
|
-
end
|
210
|
-
if block_given?
|
211
|
-
@target << " ["
|
212
|
-
_newline
|
213
|
-
_nested_structures(block)
|
214
|
-
@target << "]"
|
215
|
-
end
|
216
|
-
@target << ">"
|
217
|
-
_newline
|
218
|
-
end
|
219
|
-
|
220
|
-
# Insert a processing instruction into the XML markup. E.g.
|
221
|
-
#
|
222
|
-
# For example:
|
223
|
-
#
|
224
|
-
# xml.instruct!
|
225
|
-
# #=> <?xml version="1.0" encoding="UTF-8"?>
|
226
|
-
# xml.instruct! :aaa, :bbb=>"ccc"
|
227
|
-
# #=> <?aaa bbb="ccc"?>
|
228
|
-
#
|
229
|
-
def instruct!(directive_tag=:xml, attrs={})
|
230
|
-
_ensure_no_block block_given?
|
231
|
-
if directive_tag == :xml
|
232
|
-
a = { :version=>"1.0", :encoding=>"UTF-8" }
|
233
|
-
attrs = a.merge attrs
|
234
|
-
end
|
235
|
-
_special(
|
236
|
-
"<?#{directive_tag}",
|
237
|
-
"?>",
|
238
|
-
nil,
|
239
|
-
attrs,
|
240
|
-
[:version, :encoding, :standalone])
|
241
|
-
end
|
242
|
-
|
243
|
-
private
|
244
|
-
|
245
|
-
# NOTE: All private methods of a builder object are prefixed when
|
246
|
-
# a "_" character to avoid possible conflict with XML tag names.
|
247
|
-
|
248
|
-
# Insert text directly in to the builder's target.
|
249
|
-
def _text(text)
|
250
|
-
@target << text
|
251
|
-
end
|
252
|
-
|
253
|
-
# Insert special instruction.
|
254
|
-
def _special(open, close, data=nil, attrs=nil, order=[])
|
255
|
-
_indent
|
256
|
-
@target << open
|
257
|
-
@target << data if data
|
258
|
-
_insert_attributes(attrs, order) if attrs
|
259
|
-
@target << close
|
260
|
-
_newline
|
261
|
-
end
|
262
|
-
|
263
|
-
# Start an XML tag. If <tt>end_too</tt> is true, then the start
|
264
|
-
# tag is also the end tag (e.g. <br/>
|
265
|
-
def _start_tag(sym, attrs, end_too=false)
|
266
|
-
@target << "<#{sym}"
|
267
|
-
_insert_attributes(attrs)
|
268
|
-
@target << "/" if end_too
|
269
|
-
@target << ">"
|
270
|
-
end
|
271
|
-
|
272
|
-
# Insert an ending tag.
|
273
|
-
def _end_tag(sym)
|
274
|
-
@target << "</#{sym}>"
|
275
|
-
end
|
276
|
-
|
277
|
-
# Insert the attributes (given in the hash).
|
278
|
-
def _insert_attributes(attrs, order=[])
|
279
|
-
return if attrs.nil?
|
280
|
-
order.each do |k|
|
281
|
-
v = attrs[k]
|
282
|
-
@target << %{ #{k}="#{v}"} if v
|
283
|
-
end
|
284
|
-
attrs.each do |k, v|
|
285
|
-
@target << %{ #{k}="#{v}"} unless order.member?(k)
|
286
|
-
end
|
287
|
-
end
|
288
|
-
|
289
|
-
def _ensure_no_block(got_block)
|
290
|
-
if got_block
|
291
|
-
fail IllegalBlockError,
|
292
|
-
"Blocks are not allowed on XML instructions"
|
293
|
-
end
|
294
|
-
end
|
295
|
-
|
296
|
-
end
|
297
|
-
|
298
|
-
end
|
299
|
-
# :startdoc:
|