feed_me 0.0.5 → 0.6.0
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/README +2 -2
- data/Rakefile +6 -2
- data/lib/feed_me.rb +5 -22
- data/lib/feed_me/abstract_parser.rb +81 -78
- data/lib/feed_me/feed_parser.rb +56 -31
- data/lib/feed_me/item_parser.rb +17 -17
- data/lib/feed_me/person_parser.rb +23 -0
- data/spec/feed_parser_spec.rb +24 -29
- data/spec/item_parser_spec.rb +4 -14
- data/spec/spec_helper.rb +3 -1
- metadata +3 -7
- data/lib/feed_me/consts.rb +0 -69
- data/lib/feed_me/feed_struct.rb +0 -13
- data/lib/feed_me/merbtasks.rb +0 -6
- data/lib/feed_me/simple_struct.rb +0 -15
- data/spec/simple_struct_spec.rb +0 -14
data/README
CHANGED
@@ -3,7 +3,7 @@ Feed Me
|
|
3
3
|
|
4
4
|
Feed Me is a simple parser for RSS2 and Atom feed, adding other feed formats should be trivial. Feed Me is pretty minimal and basically only does translation/cleanup from different feed formats to a consistent API. It is designed to be minimal.
|
5
5
|
|
6
|
-
Feed Me is built on the excellent
|
6
|
+
Feed Me is built on the excellent Nokogiri parser.
|
7
7
|
|
8
8
|
Use it like this:
|
9
9
|
|
@@ -20,4 +20,4 @@ Use it like this:
|
|
20
20
|
|
21
21
|
Check out the specs or lib/feed_me/consts.rb for the complete API.
|
22
22
|
|
23
|
-
DISCLAIMER: This is very much alpha software, use at your own risk!
|
23
|
+
DISCLAIMER: This is very much alpha software, use at your own risk!
|
data/Rakefile
CHANGED
@@ -23,8 +23,13 @@ namespace :spec do
|
|
23
23
|
|
24
24
|
end
|
25
25
|
|
26
|
+
desc "Run all examples"
|
27
|
+
Spec::Rake::SpecTask.new('spec') do |t|
|
28
|
+
t.spec_files = file_list
|
29
|
+
end
|
30
|
+
|
26
31
|
desc 'Default: run specs.'
|
27
|
-
task :default => 'spec
|
32
|
+
task :default => 'spec'
|
28
33
|
|
29
34
|
PLUGIN = "feed_me"
|
30
35
|
NAME = "feed_me"
|
@@ -53,7 +58,6 @@ begin
|
|
53
58
|
s.add_dependency('hpricot')
|
54
59
|
s.files = %w(LICENSE README Rakefile TODO) + Dir.glob("{lib,specs}/**/*")
|
55
60
|
end
|
56
|
-
Jeweler::GemcutterTasks.new
|
57
61
|
rescue
|
58
62
|
puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install namelessjon-jeweler -s http://gems.github.com"
|
59
63
|
end
|
data/lib/feed_me.rb
CHANGED
@@ -1,23 +1,6 @@
|
|
1
|
-
|
2
|
-
if defined?(Merb::Plugins)
|
3
|
-
dependency 'hpricot'
|
4
|
-
else
|
5
|
-
require 'rubygems'
|
6
|
-
require 'hpricot'
|
7
|
-
end
|
1
|
+
require 'nokogiri'
|
8
2
|
require 'time'
|
9
3
|
|
10
|
-
unless nil.respond_to? :try
|
11
|
-
# the ultimate duck
|
12
|
-
class Object
|
13
|
-
def try(method, *args)
|
14
|
-
self.send(method, *args)
|
15
|
-
rescue NoMethodError
|
16
|
-
nil
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
4
|
module FeedMe
|
22
5
|
class InvalidFeedFormat < StandardError ; end
|
23
6
|
|
@@ -30,7 +13,7 @@ module FeedMe
|
|
30
13
|
end
|
31
14
|
end
|
32
15
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
16
|
+
require 'feed_me/abstract_parser'
|
17
|
+
require 'feed_me/feed_parser'
|
18
|
+
require 'feed_me/item_parser'
|
19
|
+
require 'feed_me/person_parser'
|
@@ -2,118 +2,121 @@ class FeedMe::AbstractParser
|
|
2
2
|
|
3
3
|
class << self
|
4
4
|
|
5
|
-
|
5
|
+
def properties
|
6
|
+
@properties ||= {}
|
7
|
+
end
|
6
8
|
|
7
|
-
def
|
8
|
-
|
9
|
-
|
10
|
-
camelized_format = format.to_s.split('_').map{ |w| w.capitalize }.join('')
|
11
|
-
bare_class = self.to_s.split('::').last
|
9
|
+
def property(name, options={})
|
10
|
+
options[:path] ||= name
|
11
|
+
properties[name.to_sym] = options
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
13
|
+
class_eval <<-RUBY, __FILE__, __LINE__+1
|
14
|
+
def #{name}
|
15
|
+
get_property(:#{name})
|
16
|
+
end
|
17
|
+
RUBY
|
18
|
+
end
|
17
19
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
20
|
+
def has_many(name, options={})
|
21
|
+
raise ArgumentError, "must specify :use option" unless options[:use]
|
22
|
+
options[:path] ||= name
|
23
|
+
options[:association] = :has_many
|
24
|
+
properties[name.to_sym] = options
|
23
25
|
|
26
|
+
class_eval <<-RUBY, __FILE__, __LINE__+1
|
27
|
+
def #{name}
|
28
|
+
get_has_many_association(:#{name})
|
29
|
+
end
|
30
|
+
RUBY
|
24
31
|
end
|
25
32
|
|
26
|
-
|
33
|
+
def has_one(name, options={})
|
34
|
+
raise ArgumentError, "must specify :use option" unless options[:use]
|
35
|
+
options[:path] ||= name
|
36
|
+
options[:association] = :has_one
|
37
|
+
properties[name.to_sym] = options
|
38
|
+
|
39
|
+
class_eval <<-RUBY, __FILE__, __LINE__+1
|
40
|
+
def #{name}
|
41
|
+
get_has_one_association(:#{name})
|
42
|
+
end
|
43
|
+
RUBY
|
44
|
+
end
|
27
45
|
|
28
|
-
|
29
|
-
self.xml = xml
|
30
|
-
self.format = format
|
31
|
-
self.properties = self.class.properties[self.format]
|
46
|
+
end
|
32
47
|
|
33
|
-
|
48
|
+
def initialize(feed, xml)
|
49
|
+
@xml = xml
|
50
|
+
@feed = feed
|
34
51
|
end
|
35
52
|
|
36
53
|
def to_hash
|
37
54
|
hash = {}
|
38
|
-
self.properties.each do |method, p|
|
55
|
+
self.class.properties.each do |method, p|
|
39
56
|
hash[method] = self.send(method)
|
40
57
|
end
|
41
58
|
return hash
|
42
59
|
end
|
43
60
|
|
44
|
-
|
61
|
+
attr_reader :xml, :feed
|
45
62
|
|
46
63
|
alias_method :root_node, :xml
|
47
64
|
|
48
|
-
|
49
|
-
|
50
|
-
def
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
65
|
+
private
|
66
|
+
|
67
|
+
def get_has_many_association(name)
|
68
|
+
return nil unless xml
|
69
|
+
association = self.class.properties[name]
|
70
|
+
|
71
|
+
nodes = xml.xpath("./#{association[:path]}")
|
72
|
+
parser = FeedMe.const_get(association[:use].to_s)
|
73
|
+
|
74
|
+
nodes.map do |node|
|
75
|
+
parser.new(self, node)
|
57
76
|
end
|
58
|
-
FeedMe::SimpleStruct.new(:email => email, :name => name, :uri => nil)
|
59
77
|
end
|
60
78
|
|
61
|
-
def
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
end
|
70
|
-
end
|
79
|
+
def get_has_one_association(name)
|
80
|
+
return nil unless xml
|
81
|
+
association = self.class.properties[name]
|
82
|
+
|
83
|
+
node = xml.xpath("./#{association[:path]}").first
|
84
|
+
parser = FeedMe.const_get(association[:use].to_s)
|
85
|
+
|
86
|
+
parser.new(self, node)
|
71
87
|
end
|
72
88
|
|
73
|
-
def
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
89
|
+
def get_property(name)
|
90
|
+
return nil unless xml
|
91
|
+
property = self.class.properties[name]
|
92
|
+
|
93
|
+
values = xml.xpath("./#{property[:path]}").map do |node|
|
94
|
+
result = extract_result(node, property[:from])
|
95
|
+
cast_result(result, property[:as])
|
96
|
+
end
|
97
|
+
|
98
|
+
case property[:cardinality]
|
99
|
+
when :many
|
100
|
+
return values
|
80
101
|
else
|
81
|
-
return
|
102
|
+
return values.first
|
82
103
|
end
|
83
104
|
end
|
84
105
|
|
85
|
-
def
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
instance_variable_set("@#{name}", result)
|
91
|
-
return result
|
92
|
-
end
|
93
|
-
ivar
|
106
|
+
def extract_result(node, from)
|
107
|
+
if from
|
108
|
+
node[from]
|
109
|
+
else
|
110
|
+
node.inner_html
|
94
111
|
end
|
95
112
|
end
|
96
113
|
|
97
|
-
def
|
98
|
-
|
99
|
-
|
100
|
-
unless method == :array
|
101
|
-
self.try("extract_" + method.to_s, item.first) unless item.empty?
|
114
|
+
def cast_result(result, as)
|
115
|
+
if as == :time
|
116
|
+
Time.parse(result)
|
102
117
|
else
|
103
|
-
|
118
|
+
result
|
104
119
|
end
|
105
120
|
end
|
106
121
|
|
107
|
-
def extract_inner_html(item)
|
108
|
-
item.inner_html
|
109
|
-
end
|
110
|
-
|
111
|
-
def extract_href(item)
|
112
|
-
item[:href]
|
113
|
-
end
|
114
|
-
|
115
|
-
def extract_time(item)
|
116
|
-
Time.parse(item.inner_html).utc
|
117
|
-
end
|
118
|
-
|
119
122
|
end
|
data/lib/feed_me/feed_parser.rb
CHANGED
@@ -2,10 +2,22 @@ module FeedMe
|
|
2
2
|
|
3
3
|
class FeedParser < AbstractParser
|
4
4
|
|
5
|
-
self.properties = FEED_PROPERTIES
|
6
|
-
|
7
5
|
class << self
|
8
6
|
|
7
|
+
def root_node(node=nil)
|
8
|
+
@root_node = node if node
|
9
|
+
@root_node
|
10
|
+
end
|
11
|
+
|
12
|
+
def parsers
|
13
|
+
@parsers ||= []
|
14
|
+
end
|
15
|
+
|
16
|
+
def inherited(subclass)
|
17
|
+
super
|
18
|
+
parsers << subclass
|
19
|
+
end
|
20
|
+
|
9
21
|
def open(file)
|
10
22
|
self.parse(Kernel.open(file).read)
|
11
23
|
end
|
@@ -13,47 +25,60 @@ module FeedMe
|
|
13
25
|
# parses the passed feed and identifeis what kind of feed it is
|
14
26
|
# then returns a parser object
|
15
27
|
def parse(feed)
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
def identify(xml)
|
27
|
-
FeedMe::ROOT_NODES.each do |f, s|
|
28
|
-
item = xml.at(s)
|
29
|
-
return item, f if item
|
28
|
+
document = Nokogiri::XML(feed)
|
29
|
+
if root = document.root
|
30
|
+
root.add_namespace_definition('atom', 'http://www.w3.org/2005/Atom')
|
31
|
+
parsers.each do |parser|
|
32
|
+
node = root.xpath(parser.root_node).first
|
33
|
+
if node
|
34
|
+
return parser.new(node, document.encoding)
|
35
|
+
end
|
36
|
+
end
|
30
37
|
end
|
38
|
+
# if we cannot find a parser, raise an error.
|
39
|
+
raise InvalidFeedFormat
|
31
40
|
end
|
32
41
|
|
42
|
+
end # class << self
|
43
|
+
|
44
|
+
def initialize(xml, encoding)
|
45
|
+
@xml = xml
|
46
|
+
@encoding = encoding
|
33
47
|
end
|
48
|
+
|
49
|
+
attr_reader :encoding
|
50
|
+
|
34
51
|
end
|
35
52
|
|
36
53
|
class AtomFeedParser < FeedParser
|
37
|
-
|
54
|
+
root_node "//atom:feed"
|
38
55
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
56
|
+
property :title, :path => 'atom:title'
|
57
|
+
property :feed_id, :path => 'atom:id'
|
58
|
+
property :description, :path => 'atom:subtitle'
|
59
|
+
property :generator, :path => 'atom:generator'
|
60
|
+
property :updated_at, :path => 'atom:updated', :as => :time
|
61
|
+
property :url, :path => "atom:link[@rel='alternate']", :from => :href
|
62
|
+
property :href, :path => "atom:link[@rel='self']", :from => :href
|
63
|
+
|
64
|
+
has_many :entries, :path => 'atom:entry', :use => :AtomItemParser
|
65
|
+
|
66
|
+
has_one :author, :path => 'atom:author', :use => :AtomPersonParser
|
44
67
|
end
|
45
68
|
|
46
69
|
class Rss2FeedParser < FeedParser
|
47
|
-
|
70
|
+
root_node "//rss[@version='2.0']/channel"
|
48
71
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
72
|
+
property :title
|
73
|
+
property :updated_at, :path => :lastBuildDate, :as => :time
|
74
|
+
property :feed_id, :path => :undefined
|
75
|
+
property :url, :path => :link
|
76
|
+
property :href, :path => :undefined
|
77
|
+
property :description
|
78
|
+
property :generator
|
54
79
|
|
55
|
-
|
56
|
-
|
57
|
-
|
80
|
+
has_many :entries, :path => 'item', :use => :Rss2ItemParser
|
81
|
+
|
82
|
+
has_one :author, :path => 'managingEditor', :use => :Rss2PersonParser
|
58
83
|
end
|
59
84
|
end
|
data/lib/feed_me/item_parser.rb
CHANGED
@@ -1,25 +1,25 @@
|
|
1
1
|
module FeedMe
|
2
2
|
|
3
|
-
class ItemParser < AbstractParser
|
3
|
+
class ItemParser < AbstractParser; end
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
self.feed = feed
|
12
|
-
end
|
5
|
+
class AtomItemParser < ItemParser
|
6
|
+
property :title, :path => 'atom:title'
|
7
|
+
property :updated_at, :path => "atom:updated", :as => :time
|
8
|
+
property :item_id, :path => "atom:id"
|
9
|
+
property :url, :path => "atom:link[@rel='alternate']", :from => :href
|
10
|
+
property :content, :path => 'atom:content'
|
13
11
|
|
12
|
+
has_one :author, :path => 'atom:author', :use => :AtomPersonParser
|
14
13
|
end
|
15
14
|
|
16
15
|
class Rss2ItemParser < ItemParser
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
16
|
+
property :title
|
17
|
+
property :updated_at, :path => :pubDate, :as => :time
|
18
|
+
property :item_id, :path => :guid
|
19
|
+
property :url, :path => :link
|
20
|
+
property :content, :path => :description
|
21
|
+
property :categories, :path => :category, :cardinality => :many
|
22
|
+
|
23
|
+
has_one :author, :use => :Rss2PersonParser
|
24
24
|
end
|
25
|
-
end
|
25
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module FeedMe
|
2
|
+
|
3
|
+
class PersonParser < AbstractParser; end
|
4
|
+
|
5
|
+
class AtomPersonParser < PersonParser
|
6
|
+
property :email, :path => 'atom:email'
|
7
|
+
property :name, :path => 'atom:name'
|
8
|
+
property :uri, :path => 'atom:uri'
|
9
|
+
end
|
10
|
+
|
11
|
+
class Rss2PersonParser < PersonParser
|
12
|
+
attr_reader :uri
|
13
|
+
|
14
|
+
def email
|
15
|
+
xml.inner_html.split(/\s+/, 2)[0] if xml
|
16
|
+
end
|
17
|
+
|
18
|
+
def name
|
19
|
+
xml.inner_html.split(/\s+/, 2)[1].to_s[/\((.*?)\)/, 1] if xml
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
data/spec/feed_parser_spec.rb
CHANGED
@@ -5,24 +5,32 @@ require 'feed_me'
|
|
5
5
|
describe "all parsing methods", :shared => true do
|
6
6
|
it "should identify an atom feed" do
|
7
7
|
@atom.should be_an_instance_of(FeedMe::AtomFeedParser)
|
8
|
-
@atom.format.should == :atom
|
9
8
|
@atom.root_node.xpath == "//feed[@xmlns='http://www.w3.org/2005/Atom']"
|
10
9
|
end
|
11
10
|
|
12
11
|
it "should identify an rss2 feed" do
|
13
12
|
@rss2.should be_an_instance_of(FeedMe::Rss2FeedParser)
|
14
|
-
@rss2.format.should == :rss2
|
15
13
|
@rss2.root_node.xpath == "//rss[@version=2.0]/channel"
|
16
14
|
end
|
15
|
+
|
16
|
+
describe "with bad input" do
|
17
|
+
it "should raise on an empty body" do
|
18
|
+
lambda { FeedMe::FeedParser.parse("") }.should raise_error(FeedMe::InvalidFeedFormat)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should raise on a body with non-recognised xml" do
|
22
|
+
lambda {
|
23
|
+
FeedMe::FeedParser.parse(%Q|<?xml version="1.0" encoding="UTF-8"?>"<foo>bar</foo>|)
|
24
|
+
}.should raise_error(FeedMe::InvalidFeedFormat)
|
25
|
+
end
|
26
|
+
end
|
17
27
|
end
|
18
28
|
|
19
29
|
describe FeedMe::FeedParser do
|
20
30
|
|
21
31
|
before :each do
|
22
|
-
@
|
23
|
-
@
|
24
|
-
@rss2_feed = hpricot_fixture('welformed.rss2') / "//rss[@version=2.0]/channel"
|
25
|
-
@rss2 = FeedMe::FeedParser.build(@rss2_feed, :rss2)
|
32
|
+
@atom = FeedMe::FeedParser.parse(open(fixture('welformed.atom')).read)
|
33
|
+
@rss2 = FeedMe::FeedParser.parse(open(fixture('welformed.rss2')).read)
|
26
34
|
end
|
27
35
|
|
28
36
|
it "should be an atom parser for an atom feed" do
|
@@ -36,19 +44,6 @@ describe FeedMe::FeedParser do
|
|
36
44
|
end
|
37
45
|
|
38
46
|
it_should_behave_like "all parsing methods"
|
39
|
-
|
40
|
-
describe "with bad input" do
|
41
|
-
it "should raise on an empty body" do
|
42
|
-
lambda { FeedMe::FeedParser.parse("") }.should raise_error(FeedMe::InvalidFeedFormat)
|
43
|
-
end
|
44
|
-
|
45
|
-
it "should raise on a body with non-recognised xml" do
|
46
|
-
lambda {
|
47
|
-
FeedMe::FeedParser.parse(%Q|<?xml version="1.0" encoding="UTF-8"?>"<foo>bar</foo>|)
|
48
|
-
}.should raise_error(FeedMe::InvalidFeedFormat)
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
47
|
end
|
53
48
|
|
54
49
|
describe ".open" do
|
@@ -60,6 +55,16 @@ describe FeedMe::FeedParser do
|
|
60
55
|
it_should_behave_like "all parsing methods"
|
61
56
|
end
|
62
57
|
|
58
|
+
describe '#encoding' do
|
59
|
+
it "should return the encoding for an atom feed" do
|
60
|
+
@atom.encoding.should == 'UTF-8'
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should return the encoding for an atom feed" do
|
64
|
+
@rss2.encoding.should == 'iso-8859-1'
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
63
68
|
describe '#title' do
|
64
69
|
it "should be valid for an atom feed" do
|
65
70
|
@atom.title.should == "Test feed"
|
@@ -130,16 +135,6 @@ describe FeedMe::FeedParser do
|
|
130
135
|
end
|
131
136
|
end
|
132
137
|
|
133
|
-
describe '#format' do
|
134
|
-
it "should be :atom for an atom feed" do
|
135
|
-
@atom.format.should == :atom
|
136
|
-
end
|
137
|
-
|
138
|
-
it "should be :rss2 for an rss2 feed" do
|
139
|
-
@rss2.format.should == :rss2
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
138
|
describe '#author.name' do
|
144
139
|
it "should be valid for an atom feed" do
|
145
140
|
@atom.author.name.should == "Frank"
|
data/spec/item_parser_spec.rb
CHANGED
@@ -6,9 +6,9 @@ describe FeedMe::ItemParser do
|
|
6
6
|
|
7
7
|
before :each do
|
8
8
|
@atom_feed = FeedMe::FeedParser.open(fixture('welformed.atom'))
|
9
|
-
@atom =
|
9
|
+
@atom = @atom_feed.entries.first
|
10
10
|
@rss2_feed = FeedMe::FeedParser.open(fixture('welformed.rss2'))
|
11
|
-
@rss2 =
|
11
|
+
@rss2 = @rss2_feed.entries.first
|
12
12
|
end
|
13
13
|
|
14
14
|
describe '#to_hash' do
|
@@ -67,16 +67,6 @@ describe FeedMe::ItemParser do
|
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
70
|
-
describe '#format' do
|
71
|
-
it "should be :atom for an atom feed" do
|
72
|
-
@atom.format.should == :atom
|
73
|
-
end
|
74
|
-
|
75
|
-
it "should be :rss2 for an rss2 feed" do
|
76
|
-
@rss2.format.should == :rss2
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
70
|
describe '#categories' do
|
81
71
|
it "should be correct for an rss2 feed" do
|
82
72
|
@rss2.categories.should == ['news', 'chuck']
|
@@ -170,9 +160,9 @@ describe "Without an author", FeedMe::ItemParser do
|
|
170
160
|
|
171
161
|
before :each do
|
172
162
|
@atom_feed = FeedMe::FeedParser.open(fixture('welformed.atom'))
|
173
|
-
@atom =
|
163
|
+
@atom = @atom_feed.entries[1]
|
174
164
|
@rss2_feed = FeedMe::FeedParser.open(fixture('welformed.rss2'))
|
175
|
-
@rss2 =
|
165
|
+
@rss2 = @rss2_feed.entries[1]
|
176
166
|
end
|
177
167
|
|
178
168
|
describe '#author.name' do
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: feed_me
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jonas Nicklas
|
@@ -10,7 +10,7 @@ autorequire: feed_me
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date:
|
13
|
+
date: 2010-01-18 00:00:00 +01:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -40,12 +40,9 @@ files:
|
|
40
40
|
- TODO
|
41
41
|
- lib/feed_me.rb
|
42
42
|
- lib/feed_me/abstract_parser.rb
|
43
|
-
- lib/feed_me/consts.rb
|
44
43
|
- lib/feed_me/feed_parser.rb
|
45
|
-
- lib/feed_me/feed_struct.rb
|
46
44
|
- lib/feed_me/item_parser.rb
|
47
|
-
- lib/feed_me/
|
48
|
-
- lib/feed_me/simple_struct.rb
|
45
|
+
- lib/feed_me/person_parser.rb
|
49
46
|
has_rdoc: true
|
50
47
|
homepage: http://github.com/jnicklas/feed_me
|
51
48
|
licenses: []
|
@@ -77,5 +74,4 @@ summary: Nice and simple RSS and atom feed parsing built on hpricot
|
|
77
74
|
test_files:
|
78
75
|
- spec/feed_parser_spec.rb
|
79
76
|
- spec/item_parser_spec.rb
|
80
|
-
- spec/simple_struct_spec.rb
|
81
77
|
- spec/spec_helper.rb
|
data/lib/feed_me/consts.rb
DELETED
@@ -1,69 +0,0 @@
|
|
1
|
-
module FeedMe
|
2
|
-
|
3
|
-
ROOT_NODES = {
|
4
|
-
:atom => "//feed[@xmlns='http://www.w3.org/2005/Atom']",
|
5
|
-
:rss2 => "//rss[@version=2.0]/channel"
|
6
|
-
}
|
7
|
-
|
8
|
-
FEED_PROPERTIES = {
|
9
|
-
:atom => {
|
10
|
-
:title => :title,
|
11
|
-
:updated_at => [:updated, :time],
|
12
|
-
:feed_id => :id,
|
13
|
-
:url => ["link[@rel=alternate]", :href],
|
14
|
-
:href => ["link[@rel=self]", :href],
|
15
|
-
:description => :subtitle,
|
16
|
-
:generator => :generator,
|
17
|
-
:author => {
|
18
|
-
:email => 'author/email',
|
19
|
-
:name => 'author/name',
|
20
|
-
:uri => 'author/uri'
|
21
|
-
},
|
22
|
-
:entries => :special
|
23
|
-
},
|
24
|
-
:rss2 => {
|
25
|
-
:title => :title,
|
26
|
-
:updated_at => [:lastBuildDate, :time],
|
27
|
-
:feed_id => :undefined,
|
28
|
-
:url => :link,
|
29
|
-
:href => :undefined,
|
30
|
-
:description => :description,
|
31
|
-
:generator => :generator,
|
32
|
-
:author => :special,
|
33
|
-
:entries => :special
|
34
|
-
}
|
35
|
-
}
|
36
|
-
|
37
|
-
ITEM_PROPERTIES = {
|
38
|
-
:atom => {
|
39
|
-
:title => :title,
|
40
|
-
:updated_at => [:updated, :time],
|
41
|
-
:item_id => :id,
|
42
|
-
:url => ["link[@rel=alternate]", :href],
|
43
|
-
:content => :content,
|
44
|
-
:author => {
|
45
|
-
:email => 'author/email',
|
46
|
-
:name => 'author/name',
|
47
|
-
:uri => 'author/uri'
|
48
|
-
}
|
49
|
-
},
|
50
|
-
:rss2 => {
|
51
|
-
:title => :title,
|
52
|
-
:updated_at => [:pubDate, :time],
|
53
|
-
:item_id => :guid,
|
54
|
-
:url => :link,
|
55
|
-
:content => :description,
|
56
|
-
:author => :special,
|
57
|
-
:categories => [:category, :array]
|
58
|
-
}
|
59
|
-
}
|
60
|
-
|
61
|
-
AUTHOR_PROPERTIES = {
|
62
|
-
:atom => {
|
63
|
-
:name => :name,
|
64
|
-
:uri => :uri,
|
65
|
-
:email => :email
|
66
|
-
}
|
67
|
-
}
|
68
|
-
|
69
|
-
end
|
data/lib/feed_me/feed_struct.rb
DELETED
data/lib/feed_me/merbtasks.rb
DELETED
data/spec/simple_struct_spec.rb
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
require File.join( File.dirname(__FILE__), "spec_helper" )
|
2
|
-
|
3
|
-
require 'feed_me'
|
4
|
-
|
5
|
-
describe FeedMe::SimpleStruct do
|
6
|
-
|
7
|
-
it "should append methods" do
|
8
|
-
struct = FeedMe::SimpleStruct.new(:foo => "blah", :bar => 23)
|
9
|
-
|
10
|
-
struct.foo.should == "blah"
|
11
|
-
struct.bar.should == 23
|
12
|
-
end
|
13
|
-
|
14
|
-
end
|