whistle 0.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.
Files changed (53) hide show
  1. data/History.txt +3 -0
  2. data/README.txt +38 -0
  3. data/bin/whistle +90 -0
  4. data/lib/config.rb +19 -0
  5. data/lib/phash.rb +16 -0
  6. data/lib/relay.rb +24 -0
  7. data/lib/resource.rb +113 -0
  8. data/lib/ssl_patch.rb +15 -0
  9. data/lib/switchbox.rb +54 -0
  10. data/lib/time_ext.rb +30 -0
  11. data/lib/version.rb +3 -0
  12. data/sample/config.yml +12 -0
  13. data/vendor/rscm-0.5.1-patched-stripped/README +218 -0
  14. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm.rb +14 -0
  15. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/abstract_log_parser.rb +35 -0
  16. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/base.rb +289 -0
  17. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/command_line.rb +146 -0
  18. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/difftool.rb +44 -0
  19. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/line_editor.rb +46 -0
  20. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/mockit.rb +157 -0
  21. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/parser.rb +39 -0
  22. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/path_converter.rb +60 -0
  23. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/platform.rb +26 -0
  24. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/revision.rb +103 -0
  25. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/revision_file.rb +85 -0
  26. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/revision_poller.rb +93 -0
  27. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/revisions.rb +79 -0
  28. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/scm/clearcase.rb +182 -0
  29. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/scm/cvs.rb +374 -0
  30. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/scm/cvs_log_parser.rb +154 -0
  31. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/scm/darcs.rb +120 -0
  32. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/scm/darcs_log_parser.rb +65 -0
  33. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/scm/monotone.rb +338 -0
  34. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/scm/monotone_log_parser.rb +109 -0
  35. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/scm/mooky.rb +6 -0
  36. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/scm/perforce.rb +216 -0
  37. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/scm/star_team.rb +104 -0
  38. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/scm/subversion.rb +397 -0
  39. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/scm/subversion_log_parser.rb +165 -0
  40. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/tempdir.rb +17 -0
  41. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/time_ext.rb +11 -0
  42. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/version.rb +13 -0
  43. data/vendor/ruby-feedparser-0.5-stripped/README +14 -0
  44. data/vendor/ruby-feedparser-0.5-stripped/lib/feedparser.rb +28 -0
  45. data/vendor/ruby-feedparser-0.5-stripped/lib/feedparser/feedparser.rb +300 -0
  46. data/vendor/ruby-feedparser-0.5-stripped/lib/feedparser/filesizes.rb +12 -0
  47. data/vendor/ruby-feedparser-0.5-stripped/lib/feedparser/html-output.rb +126 -0
  48. data/vendor/ruby-feedparser-0.5-stripped/lib/feedparser/html2text-parser.rb +409 -0
  49. data/vendor/ruby-feedparser-0.5-stripped/lib/feedparser/rexml_patch.rb +28 -0
  50. data/vendor/ruby-feedparser-0.5-stripped/lib/feedparser/sgml-parser.rb +332 -0
  51. data/vendor/ruby-feedparser-0.5-stripped/lib/feedparser/text-output.rb +83 -0
  52. data/vendor/ruby-feedparser-0.5-stripped/lib/feedparser/textconverters.rb +120 -0
  53. metadata +132 -0
@@ -0,0 +1,165 @@
1
+ require 'rscm/parser'
2
+ require 'rscm/revision'
3
+ require 'rscm/revisions'
4
+ require 'rscm/revision_file'
5
+ require 'time'
6
+
7
+ module RSCM
8
+
9
+ class SubversionLogParser
10
+ def initialize(io, url, exclude_below_and_including=nil, exclude_above_and_including=nil, path=nil)
11
+ @io = io
12
+ @revision_parser = SubversionLogEntryParser.new(url, path)
13
+ @exclude_below_and_including = exclude_below_and_including
14
+ @exclude_above_and_including = exclude_above_and_including
15
+ end
16
+
17
+ def parse_revisions(&line_proc)
18
+ # skip over the first ------
19
+ @revision_parser.parse(@io, true, &line_proc)
20
+ revisions = Revisions.new
21
+ while(!@io.eof?)
22
+ revision = @revision_parser.parse(@io, &line_proc)
23
+ unless(revision.nil?)
24
+ # Filter out the lower bound to avoid inclusiveness of the lower bound (see contract)
25
+ # We're doing this instead of increasing the from_identifer with 1, since that causes an error.
26
+ too_low = false
27
+ too_high = false
28
+ next if revision.time.nil?
29
+ if(@exclude_below_and_including.is_a? Time)
30
+ too_low = revision.time <= @exclude_below_and_including
31
+ elsif(@exclude_below_and_including.is_a? Numeric)
32
+ too_low = revision.identifier <= @exclude_below_and_including
33
+ end
34
+
35
+ if(@exclude_above_and_including.is_a? Time)
36
+ too_high = revision.time >= @exclude_above_and_including
37
+ elsif(@exclude_above_and_including.is_a? Numeric)
38
+ too_high = revision.identifier >= @exclude_above_and_including
39
+ end
40
+ revisions.add(revision) unless too_low || too_high
41
+ end
42
+ end
43
+ revisions
44
+ end
45
+ end
46
+
47
+ class SubversionLogEntryParser < Parser
48
+
49
+ def initialize(url, path=nil)
50
+ super(/^------------------------------------------------------------------------/)
51
+ @url = url
52
+ @path = path
53
+ end
54
+
55
+ def parse(io, skip_line_parsing=false, &line_proc)
56
+ # We have to trim off the last newline - it's not meant to be part of the message
57
+ revision = super
58
+ revision.message = revision.message[0..-2] if revision
59
+ revision
60
+ end
61
+
62
+ def relative_path(url, path_from_root)
63
+ path_from_root = path_from_root.chomp
64
+ url_tokens = url.split('/')
65
+ path_from_root_tokens = path_from_root.split('/')
66
+
67
+ max_similar = path_from_root_tokens.length
68
+ while(max_similar > 0)
69
+ url = url_tokens[-max_similar..-1]
70
+ path = path_from_root_tokens[0..max_similar-1]
71
+ if(url == path)
72
+ break
73
+ end
74
+ max_similar -= 1
75
+ end
76
+
77
+ if(max_similar == 0)
78
+ if(@path.nil? || @path == "")
79
+ path_from_root
80
+ else
81
+ nil
82
+ end
83
+ else
84
+ path_from_root_tokens[max_similar..-1].join("/")
85
+ end
86
+ end
87
+
88
+ protected
89
+
90
+ def parse_line(line)
91
+ if(@revision.nil?)
92
+ parse_header(line)
93
+ elsif(line.strip == "")
94
+ @parse_state = :parse_message
95
+ elsif(line =~ /Changed paths/)
96
+ @parse_state = :parse_files
97
+ elsif(@parse_state == :parse_files)
98
+ file = parse_file(line)
99
+ if(file && file.path)
100
+ previously_added_file = @revision[-1]
101
+ if(previously_added_file)
102
+ # remove previous revision_file if it's a dir
103
+ previous_tokens = previously_added_file.path.split("/")
104
+ current_tokens = file.path.split("/")
105
+ current_tokens.pop
106
+ if(previous_tokens == current_tokens)
107
+ @revision.pop
108
+ end
109
+ end
110
+ @revision.add file
111
+ end
112
+ elsif(@parse_state == :parse_message)
113
+ @revision.message << line.chomp << "\n"
114
+ end
115
+ end
116
+
117
+ def next_result
118
+ result = @revision
119
+ @revision = nil
120
+ result
121
+ end
122
+
123
+ private
124
+
125
+ STATES = {"M" => RevisionFile::MODIFIED, "A" => RevisionFile::ADDED, "D" => RevisionFile::DELETED} unless defined? STATES
126
+
127
+ def parse_header(line)
128
+ @revision = Revision.new
129
+ @revision.message = ""
130
+ revision, developer, time, the_rest = line.split("|")
131
+ @revision.identifier = revision.strip[1..-1].to_i unless revision.nil?
132
+ developer.strip!
133
+ @revision.developer = developer unless developer.nil? || developer == "(no author)"
134
+ time.strip!
135
+ @revision.time = Time.parse(time).utc unless time.nil? || time == "(no date)"
136
+ end
137
+
138
+ def parse_file(line)
139
+ file = RevisionFile.new
140
+ path_from_root = nil
141
+ if(line =~ /^ [M|A|D|R] ([^\s]+) \(from (.*)\)/)
142
+ path_from_root = $1
143
+ file.status = RevisionFile::MOVED
144
+ elsif(line =~ /^ ([M|A|D|R]) (.+)$/)
145
+ status = $1
146
+ path_from_root = $2
147
+ file.status = STATES[status]
148
+ else
149
+ raise "could not parse file line: '#{line}'"
150
+ end
151
+
152
+ path_from_root.gsub!(/\\/, "/")
153
+ path_from_root = path_from_root[1..-1]
154
+ rp = relative_path(@url, path_from_root)
155
+ return if rp.nil?
156
+
157
+ file.path = rp
158
+ file.native_revision_identifier = @revision.identifier
159
+ # http://jira.codehaus.org/browse/DC-204
160
+ file.previous_native_revision_identifier = file.native_revision_identifier.to_i - 1;
161
+ file
162
+ end
163
+ end
164
+
165
+ end
@@ -0,0 +1,17 @@
1
+ require 'fileutils'
2
+
3
+ module RSCM
4
+
5
+ def method_name
6
+ /\`([^\']+)\'/.match(caller.first)[1]
7
+ end
8
+
9
+ def new_temp_dir(suffix="", basedir=File.dirname(__FILE__) + "/../../target")
10
+ identifier = identifier.to_s
11
+ identifier.gsub!(/\(|:|\)/, '_')
12
+ dir = "#{basedir}/temp_#{identifier}_#{Time.new.to_i}#{suffix}"
13
+ FileUtils.mkdir_p(dir)
14
+ dir
15
+ end
16
+ module_function :new_temp_dir
17
+ end
@@ -0,0 +1,11 @@
1
+ class Time
2
+ class << self
3
+ def epoch
4
+ Time.utc(1972)
5
+ end
6
+
7
+ def infinity
8
+ Time.utc(2036)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,13 @@
1
+ module RSCM
2
+ module VERSION
3
+ MAJOR = 0
4
+ MINOR = 5
5
+ TINY = 1
6
+
7
+ STRING = [MAJOR, MINOR, TINY].join('.')
8
+
9
+ NAME = "RSCM"
10
+ FULLNAME = "Ruby Source Control Management"
11
+ URL = "http://rscm.rubyforge.org/"
12
+ end
13
+ end
@@ -0,0 +1,14 @@
1
+ Ruby-Feedparser
2
+ -----------------
3
+ by Lucas Nussbaum <lucas@lucas-nussbaum.net>
4
+
5
+ Currently, all the information is provided on
6
+
7
+ http://home.gna.org/ruby-feedparser/
8
+
9
+ If you need to ask questions, feel free to ask them on the
10
+ ruby-feedparser-devel@gna.org mailing list.
11
+
12
+ Ruby-Feedparser is released under the Ruby license (see the LICENSE file),
13
+ which is compatible with the GNU GPL (see the COPYING file) via an explicit
14
+ dual-licensing clause.
@@ -0,0 +1,28 @@
1
+ # =Ruby-feedparser - ATOM/RSS feed parser for Ruby
2
+ # License:: Ruby's license (see the LICENSE file) or GNU GPL, at your option.
3
+ # Website::http://home.gna.org/ruby-feedparser/
4
+ #
5
+ # ==Introduction
6
+ #
7
+ # Ruby-Feedparser is an RSS and Atom parser for Ruby.
8
+ # Ruby-feedparser is :
9
+ # * based on REXML
10
+ # * built for robustness : most feeds are not valid, a parser can't ignore that
11
+ # * fully unit-tested
12
+ # * easy to use (it can output text or HTML easily)
13
+ #
14
+ # ==Example
15
+ # require 'net/http'
16
+ # require 'feedparser'
17
+ # require 'uri'
18
+ # s = Net::HTTP::get URI::parse('http://rss.slashdot.org/Slashdot/slashdot')
19
+ # f = FeedParser::Feed::new(s)
20
+ # f.title
21
+ # => "Slashdot"
22
+ # f.items.each { |i| puts i.title }
23
+ # [...]
24
+ # require 'feedparser/html-output'
25
+ # f.items.each { |i| puts i.to_html }
26
+ #
27
+
28
+ require 'feedparser/feedparser'
@@ -0,0 +1,300 @@
1
+ require 'rexml/document'
2
+ require 'time'
3
+ require 'feedparser/textconverters'
4
+ require 'feedparser/rexml_patch'
5
+ require 'feedparser/text-output'
6
+ require 'base64'
7
+
8
+ module FeedParser
9
+
10
+ VERSION = "0.5"
11
+
12
+ class UnknownFeedTypeException < RuntimeError
13
+ end
14
+
15
+ # an RSS/Atom feed
16
+ class Feed
17
+ attr_reader :type, :title, :link, :description, :creator, :encoding, :items
18
+
19
+ # REXML::Element for this feed.
20
+ attr_reader :xml
21
+
22
+ # parse str to build a Feed
23
+ def initialize(str = nil)
24
+ parse(str) if str
25
+ end
26
+
27
+ # Determines all the fields using a string containing an
28
+ # XML document
29
+ def parse(str)
30
+ # Dirty hack: some feeds contain the & char. It must be changed to &amp;
31
+ str.gsub!(/&(\s+)/, '&amp;\1')
32
+ doc = REXML::Document.new(str)
33
+ @xml = doc.root
34
+ # get feed info
35
+ @encoding = doc.encoding
36
+ @title,@link,@description,@creator = nil
37
+ @items = []
38
+ if doc.root.elements['channel'] || doc.root.elements['rss:channel']
39
+ @type = "rss"
40
+ # We have a RSS feed!
41
+ # Title
42
+ if (e = doc.root.elements['channel/title'] ||
43
+ doc.root.elements['rss:channel/rss:title']) && e.text
44
+ @title = e.text.unescape_html.toUTF8(@encoding).rmWhiteSpace!
45
+ end
46
+ # Link
47
+ if (e = doc.root.elements['channel/link'] ||
48
+ doc.root.elements['rss:channel/rss:link']) && e.text
49
+ @link = e.text.rmWhiteSpace!
50
+ end
51
+ # Description
52
+ if (e = doc.root.elements['channel/description'] ||
53
+ doc.root.elements['rss:channel/rss:description']) && e.text
54
+ @description = e.text.toUTF8(@encoding).rmWhiteSpace!
55
+ end
56
+ # Creator
57
+ if ((e = doc.root.elements['channel/dc:creator']) && e.text) ||
58
+ ((e = doc.root.elements['channel/author'] ||
59
+ doc.root.elements['rss:channel/rss:author']) && e.text)
60
+ @creator = e.text.unescape_html.toUTF8(@encoding).rmWhiteSpace!
61
+ end
62
+ # Items
63
+ if doc.root.elements['channel/item']
64
+ query = 'channel/item'
65
+ elsif doc.root.elements['item']
66
+ query = 'item'
67
+ elsif doc.root.elements['rss:channel/rss:item']
68
+ query = 'rss:channel/rss:item'
69
+ else
70
+ query = 'rss:item'
71
+ end
72
+ doc.root.each_element(query) { |e| @items << RSSItem::new(e, self) }
73
+
74
+ elsif doc.root.elements['/feed']
75
+ # We have an ATOM feed!
76
+ @type = "atom"
77
+ # Title
78
+ if (e = doc.root.elements['/feed/title']) && e.text
79
+ @title = e.text.unescape_html.toUTF8(@encoding).rmWhiteSpace!
80
+ end
81
+ # Link
82
+ doc.root.each_element('/feed/link') do |e|
83
+ if e.attribute('type') and (
84
+ e.attribute('type').value == 'text/html' or
85
+ e.attribute('type').value == 'application/xhtml' or
86
+ e.attribute('type').value == 'application/xhtml+xml')
87
+ if (h = e.attribute('href')) && h
88
+ @link = h.value.rmWhiteSpace!
89
+ end
90
+ end
91
+ end
92
+ # Description
93
+ if e = doc.root.elements['/feed/info']
94
+ e = e.elements['div'] || e
95
+ @description = e.to_s.toUTF8(@encoding).rmWhiteSpace!
96
+ end
97
+ # Items
98
+ doc.root.each_element('/feed/entry') do |e|
99
+ @items << AtomItem::new(e, self)
100
+ end
101
+ else
102
+ raise UnknownFeedTypeException::new
103
+ end
104
+ end
105
+
106
+ def to_s(localtime = true)
107
+ s = ''
108
+ s += "Type: #{@type}\n"
109
+ s += "Encoding: #{@encoding}\n"
110
+ s += "Title: #{@title}\n"
111
+ s += "Link: #{@link}\n"
112
+ s += "Description: #{@description}\n"
113
+ s += "Creator: #{@creator}\n"
114
+ s += "\n"
115
+ @items.each { |i| s += i.to_s(localtime) }
116
+ s
117
+ end
118
+ end
119
+
120
+ # an Item from a feed
121
+ class FeedItem
122
+ attr_accessor :title, :link, :content, :date, :creator, :subject,
123
+ :category, :cacheditem
124
+
125
+ # The item's enclosures childs. An array of (url, length, type) triplets.
126
+ attr_accessor :enclosures
127
+
128
+ attr_reader :feed
129
+
130
+ # REXML::Element for this item
131
+ attr_reader :xml
132
+
133
+ def initialize(item = nil, feed = nil)
134
+ @xml = item
135
+ @feed = feed
136
+ @title, @link, @content, @date, @creator, @subject, @category = nil
137
+ @enclosures = []
138
+ parse(item) if item
139
+ end
140
+
141
+ def parse(item)
142
+ raise "parse() should be implemented by subclasses!"
143
+ end
144
+
145
+ def to_s(localtime = true)
146
+ s = "--------------------------------\n" +
147
+ "Title: #{@title}\nLink: #{@link}\n"
148
+ if localtime or @date.nil?
149
+ s += "Date: #{@date.to_s}\n"
150
+ else
151
+ s += "Date: #{@date.getutc.to_s}\n"
152
+ end
153
+ s += "Creator: #{@creator}\n" +
154
+ "Subject: #{@subject}\nCategory: #{@category}\nContent:\n#{content}\n"
155
+ if defined?(@enclosures) and @enclosures.length > 0
156
+ s2 = "Enclosures:\n"
157
+ @enclosures.each do |e|
158
+ s2 += e.join(' ') + "\n"
159
+ end
160
+ s += s2
161
+ end
162
+ return s
163
+ end
164
+ end
165
+
166
+ class RSSItem < FeedItem
167
+
168
+
169
+ def parse(item)
170
+ # Title. If no title, use the pubDate as fallback.
171
+ if ((e = item.elements['title'] || item.elements['rss:title']) &&
172
+ e.text) ||
173
+ ((e = item.elements['pubDate'] || item.elements['rss:pubDate']) &&
174
+ e.text)
175
+ @title = e.text.unescape_html.toUTF8(@feed.encoding).html2text.rmWhiteSpace!
176
+ end
177
+ # Link
178
+ if ((e = item.elements['link'] || item.elements['rss:link']) && e.text)||
179
+ (e = item.elements['guid'] || item.elements['rss:guid'] and
180
+ not (e.attribute('isPermaLink') and
181
+ e.attribute('isPermaLink').value == 'false'))
182
+ @link = e.text.rmWhiteSpace!
183
+ end
184
+ # Content
185
+ if (e = item.elements['content:encoded']) ||
186
+ (e = item.elements['description'] || item.elements['rss:description'])
187
+ @content = FeedParser::getcontent(e, @feed)
188
+ end
189
+ # Date
190
+ if e = item.elements['dc:date'] || item.elements['pubDate'] ||
191
+ item.elements['rss:pubDate']
192
+ begin
193
+ @date = Time::xmlschema(e.text)
194
+ rescue
195
+ begin
196
+ @date = Time::rfc2822(e.text)
197
+ rescue
198
+ begin
199
+ @date = Time::parse(e.text)
200
+ rescue
201
+ @date = nil
202
+ end
203
+ end
204
+ end
205
+ end
206
+ # Creator
207
+ @creator = @feed.creator
208
+ if (e = item.elements['dc:creator'] || item.elements['author'] ||
209
+ item.elements['rss:author']) && e.text
210
+ @creator = e.text.unescape_html.toUTF8(@feed.encoding).rmWhiteSpace!
211
+ end
212
+ # Subject
213
+ if (e = item.elements['dc:subject']) && e.text
214
+ @subject = e.text.unescape_html.toUTF8(@feed.encoding).rmWhiteSpace!
215
+ end
216
+ # Category
217
+ if (e = item.elements['dc:category'] || item.elements['category'] ||
218
+ item.elements['rss:category']) && e.text
219
+ @category = e.text.unescape_html.toUTF8(@feed.encoding).rmWhiteSpace!
220
+ end
221
+ # Enclosures
222
+ item.each_element('enclosure') do |e|
223
+ url = e.attribute('url').value if e.attribute('url')
224
+ length = e.attribute('length').value if e.attribute('length')
225
+ type = e.attribute('type').value if e.attribute('type')
226
+ @enclosures << [ url, length, type ] if url
227
+ end
228
+ end
229
+ end
230
+
231
+ class AtomItem < FeedItem
232
+ def parse(item)
233
+ # Title
234
+ if (e = item.elements['title']) && e.text
235
+ @title = e.text.unescape_html.toUTF8(@feed.encoding).html2text.rmWhiteSpace!
236
+ end
237
+ # Link
238
+ item.each_element('link') do |e|
239
+ if (h = e.attribute('href')) && h.value
240
+ @link = h.value
241
+ end
242
+ end
243
+ # Content
244
+ if e = item.elements['content'] || item.elements['summary']
245
+ if (e.attribute('mode') and e.attribute('mode').value == 'escaped') &&
246
+ e.text
247
+ @content = e.text.toUTF8(@feed.encoding).rmWhiteSpace!
248
+ else
249
+ @content = FeedParser::getcontent(e, @feed)
250
+ end
251
+ end
252
+ # Date
253
+ if (e = item.elements['issued'] || e = item.elements['created'] || e = item.elements['updated'] || e = item.elements['published']) && e.text
254
+ begin
255
+ @date = Time::xmlschema(e.text)
256
+ rescue
257
+ begin
258
+ @date = Time::rfc2822(e.text)
259
+ rescue
260
+ begin
261
+ @date = Time::parse(e.text)
262
+ rescue
263
+ @date = nil
264
+ end
265
+ end
266
+ end
267
+ end
268
+ # Creator
269
+ @creator = @feed.creator
270
+ if (e = item.elements['author/name']) && e.text
271
+ @creator = e.text.unescape_html.toUTF8(@feed.encoding).rmWhiteSpace!
272
+ end
273
+ end
274
+ end
275
+
276
+ def FeedParser::getcontent(e, feed = nil)
277
+ encoding = feed ? feed.encoding : 'utf-8'
278
+ children = e.children.reject do |i|
279
+ i.class == REXML::Text and i.to_s.chomp == ''
280
+ end
281
+ if children.length > 1
282
+ s = ''
283
+ children.each do |c|
284
+ s += c.to_s if c.class != REXML::Comment
285
+ end
286
+ return s.toUTF8(encoding).rmWhiteSpace!.text2html(feed)
287
+ elsif children.length == 1
288
+ c = children[0]
289
+ if c.class == REXML::Text
290
+ return e.text.toUTF8(encoding).rmWhiteSpace!.text2html(feed)
291
+ else
292
+ if c.class == REXML::CData
293
+ return c.to_s.toUTF8(encoding).rmWhiteSpace!.text2html(feed)
294
+ elsif c.text
295
+ return c.text.toUTF8(encoding).text2html(feed)
296
+ end
297
+ end
298
+ end
299
+ end
300
+ end