planet 0.3.11 → 0.3.12

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/bin/planet CHANGED
@@ -50,19 +50,10 @@ command :generate do |c|
50
50
  c.action do |global_options,options,args|
51
51
  conf = YAML.load_file('planet.yml')
52
52
 
53
- @planet = Planet.new(config: conf.fetch('planet', {}))
54
-
55
- conf['blogs'].each do |blog|
56
- @planet.blogs << Planet::Blog.new(
57
- feed: blog['feed'],
58
- url: blog['url'],
59
- author: blog['author'],
60
- image: blog['image'],
61
- posts: [],
62
- planet: @planet,
63
- twitter: blog['twitter']
64
- )
65
- end
53
+ @planet = Planet.new(
54
+ config: conf.fetch('planet', {}),
55
+ blogs: conf.fetch('blogs', [])
56
+ )
66
57
 
67
58
  @planet.aggregate
68
59
 
@@ -1,5 +1,5 @@
1
- require 'feedzirra'
2
- require 'mustache'
1
+ require 'planet/version'
2
+ require 'planet/blog'
3
3
 
4
4
  class Planet
5
5
 
@@ -7,7 +7,17 @@ class Planet
7
7
 
8
8
  def initialize(attributes = {})
9
9
  self.config = attributes[:config]
10
- self.blogs = attributes.fetch(:blogs, [])
10
+ self.blogs = attributes.fetch(:blogs, []).map do |blog|
11
+ Blog.new(
12
+ feed: blog['feed'],
13
+ url: blog['url'],
14
+ author: blog['author'],
15
+ image: blog['image'],
16
+ posts: [],
17
+ planet: self,
18
+ twitter: blog['twitter']
19
+ )
20
+ end
11
21
  end
12
22
 
13
23
  def posts
@@ -32,129 +42,4 @@ class Planet
32
42
  File.open(file_name + '.markdown', "w+") { |f| f.write(post.to_s) }
33
43
  end
34
44
  end
35
-
36
- class Post
37
-
38
- attr_accessor :title, :content, :date, :url, :blog
39
-
40
- def initialize(attributes = {})
41
- self.title = attributes[:title]
42
- self.content = attributes[:content]
43
- self.date = attributes[:date]
44
- self.url = attributes[:url]
45
- self.blog = attributes[:blog]
46
- end
47
-
48
- def to_s
49
- "#{ header }#{ content }#{ footer }"
50
- end
51
-
52
- def to_hash
53
- {
54
- post_content: self.content,
55
- post_title: self.title,
56
- post_date: self.date,
57
- image_url: self.blog.image,
58
- author: self.blog.author,
59
- blog_url: self.blog.url,
60
- blog_name: self.blog.name,
61
- post_url: self.url,
62
- twitter: self.blog.twitter,
63
- twitter_url: "http://twitter.com/#{ self.blog.twitter }"
64
- }
65
- end
66
-
67
- def header
68
- ## TODO: We need categories/tags
69
- file = self.blog.planet.config.fetch('templates_directory', '_layouts/') + 'header.md'
70
- file_contents = File.read(file)
71
-
72
- Mustache.render(file_contents, self.to_hash)
73
- end
74
-
75
- def footer
76
- file = self.blog.planet.config.fetch('templates_directory', '_layouts/') + 'author.html'
77
- file_contents = File.read(file)
78
-
79
- Mustache.render(file_contents, self.to_hash)
80
- end
81
-
82
- def file_name
83
- name_date = date ? date.strftime('%Y-%m-%d') : nil
84
- name_title = title.downcase.scan(/\w+/).join('-')
85
-
86
- [name_date, name_title].join('-')
87
- end
88
-
89
- end
90
-
91
- class Blog
92
-
93
- attr_accessor :url, :feed, :name, :author, :image, :twitter, :posts, :planet
94
-
95
- def initialize(attributes = {})
96
- self.url = attributes[:url]
97
- self.feed = attributes[:feed]
98
- self.name = attributes[:name]
99
- self.author = attributes[:author]
100
- self.image = attributes[:image]
101
- self.twitter = attributes[:twitter]
102
- self.posts = attributes.fetch(:posts, [])
103
- self.planet = attributes[:planet]
104
- end
105
-
106
- def fetch
107
- feed = Feedzirra::Feed.fetch_and_parse(self.feed)
108
-
109
- self.name ||= feed.title || 'the source'
110
- self.url ||= feed.url
111
-
112
- if self.url.nil?
113
- abort "#{ self.author }'s blog does not have a url field on it's feed, you will need to specify it on planet.yml"
114
- end
115
-
116
- feed.entries.each do |entry|
117
- ## TODO: I should probably consider using feed 'adapters' for specific
118
- ## blog engine feeds that don't have their stuff on the standard fields.
119
- ## Example: blogspot has the content on "summary" instead of content ¬¬.
120
- content = if !entry.content.nil?
121
- self.sanitize_images(entry.content.strip)
122
- elsif !entry.summary.nil?
123
- self.sanitize_images(entry.summary.strip)
124
- else
125
- abort "=> No content found on entry"
126
- end
127
-
128
- title = if !entry.title.nil?
129
- entry.title.sanitize
130
- else
131
- self.name
132
- end
133
-
134
- self.posts << @post = Post.new(
135
- title: title,
136
- content: content,
137
- date: entry.published,
138
- url: self.url + entry.url,
139
- blog: self
140
- )
141
-
142
- puts "=> Found post titled #{ @post.title } - by #{ @post.blog.author }"
143
- end
144
- end
145
-
146
- def sanitize_images(html)
147
- ## We take all images with src not matching http refs and append
148
- ## the original blog to them.
149
- html.scan(/<img src="([^h"]+)"/).flatten.each do |img|
150
- if img[0] == '/'
151
- html.gsub!(img, "#{ self.url }#{ img }")
152
- else
153
- html.gsub!(img, "#{ self.url }/#{ img }")
154
- end
155
- end
156
-
157
- html
158
- end
159
- end
160
45
  end
@@ -0,0 +1,79 @@
1
+ require 'planet/post'
2
+ require 'planet/parsers'
3
+
4
+ class Planet
5
+ class Blog
6
+
7
+ attr_accessor :url, :feed, :type, :name, :author, :image, :twitter, :posts, :planet
8
+
9
+ def initialize(attributes = {})
10
+ self.url = attributes[:url]
11
+ self.feed = attributes[:feed]
12
+ self.type = attributes[:type]
13
+ self.name = attributes[:name]
14
+ self.author = attributes[:author]
15
+ self.image = attributes[:image]
16
+ self.twitter = attributes[:twitter]
17
+ self.posts = attributes.fetch(:posts, [])
18
+ self.planet = attributes[:planet]
19
+
20
+ # get parser-manager instance
21
+ @parsers = Parsers.new
22
+ end
23
+
24
+ def fetch
25
+ # given parser can be set arbitrarily with :type or inferred from the domain
26
+ parser = self.type ? @parsers.get_parser(self.type) : @parsers.get_parser_for(self.feed)
27
+
28
+ # parser instances should mimick Feedzirra interface
29
+ feed = parser.fetch_and_parse(self.feed)
30
+
31
+ self.name ||= feed.title || 'the source'
32
+ self.url ||= feed.url
33
+
34
+ if self.url.nil?
35
+ abort "#{ self.author }'s blog does not have a url field on it's feed, you will need to specify it on planet.yml"
36
+ end
37
+
38
+ feed.entries.each do |entry|
39
+ content = if !entry.content.nil?
40
+ self.sanitize_images(entry.content.strip)
41
+ elsif !entry.summary.nil?
42
+ self.sanitize_images(entry.summary.strip)
43
+ else
44
+ abort "=> No content found on entry"
45
+ end
46
+
47
+ title = if !entry.title.nil?
48
+ entry.title.sanitize
49
+ else
50
+ self.name
51
+ end
52
+
53
+ self.posts << @post = Post.new(
54
+ title: title,
55
+ content: content,
56
+ date: entry.published,
57
+ url: self.url + entry.url,
58
+ blog: self
59
+ )
60
+
61
+ puts "=> Found post titled #{ @post.title } - by #{ @post.blog.author }"
62
+ end
63
+ end
64
+
65
+ def sanitize_images(html)
66
+ ## We take all images with src not matching http refs and append
67
+ ## the original blog to them.
68
+ html.scan(/<img src="([^h"]+)"/).flatten.each do |img|
69
+ if img[0] == '/'
70
+ html.gsub!(img, "#{ self.url }#{ img }")
71
+ else
72
+ html.gsub!(img, "#{ self.url }/#{ img }")
73
+ end
74
+ end
75
+
76
+ html
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,64 @@
1
+ require 'feedzirra'
2
+ require 'set'
3
+
4
+ class Planet
5
+ # Parsers class - manager for the feed parsers
6
+ #
7
+ # parser classes inherit from Planet::Parsers::BaseParser
8
+ # and are added automatically to the list of available parsers.
9
+ # files located on planet/parsers are automatically loaded.
10
+ class Parsers
11
+ @@parsers = Set.new
12
+
13
+ def self.add_parser(parser)
14
+ @@parsers << parser
15
+ end
16
+
17
+ # Parser instances keep indexes of the available parsers and
18
+ # check for duplicate definitions (need to use an instance
19
+ # because #inherited gets called as soon as the class is seen
20
+ # but before it is fully defined).
21
+ def initialize
22
+ @types, @domains = {}, {}
23
+
24
+ @@parsers.each do |parser|
25
+ new_type, new_domains = parser.type, parser.domains
26
+
27
+ fail("duplicate type") if new_type and @types.has_key? new_type
28
+ fail("overlapping domains") unless (@domains.keys & new_domains).empty?
29
+
30
+ @types[new_type] = parser if new_type
31
+ new_domains.each do |new_domain|
32
+ @domains[new_domain] = parser
33
+ end
34
+ end
35
+ end
36
+
37
+ # returns the appropiate parser based on the type
38
+ def get_parser(type)
39
+ begin
40
+ return @types.fetch(type)
41
+ rescue KeyError => e
42
+ raise(ArgumentError, "No parser for type '#{ type }'", caller)
43
+ end
44
+ end
45
+
46
+ # returns any parser that can handle this feeds' domain,
47
+ # defaults to Feedzirra if none available.
48
+ def get_parser_for(feed)
49
+ feed_domain = URI(feed).host
50
+
51
+ @domains.each do |domain, parser|
52
+ return parser if feed_domain.end_with? domain
53
+ end
54
+
55
+ return Feedzirra::Feed # default generic parser
56
+ end
57
+ end
58
+ end
59
+
60
+ # load parsers
61
+ dirname = File.join([File.dirname(__FILE__), 'parsers'])
62
+ Dir.open(dirname).each do |filename|
63
+ require "#{dirname}/#{filename}" if filename.end_with? '.rb'
64
+ end
@@ -0,0 +1,24 @@
1
+ class Planet
2
+ class Parsers
3
+ # base class for feed parsers
4
+ # subclasses should declare @type and @domains
5
+ # and also mimick Feedzirra interface.
6
+ class BaseParser
7
+ def self.type
8
+ @type
9
+ end
10
+
11
+ def self.domains
12
+ @domains || []
13
+ end
14
+
15
+ def self.inherited(parser)
16
+ Parsers.add_parser parser
17
+ end
18
+
19
+ def self.fetch_and_parse(feed)
20
+ raise(Exception, "Not implemented", caller)
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,58 @@
1
+ require 'mustache'
2
+
3
+ class Planet
4
+ class Post
5
+
6
+ attr_accessor :title, :content, :date, :url, :blog
7
+
8
+ def initialize(attributes = {})
9
+ self.title = attributes[:title]
10
+ self.content = attributes[:content]
11
+ self.date = attributes[:date]
12
+ self.url = attributes[:url]
13
+ self.blog = attributes[:blog]
14
+ end
15
+
16
+ def to_s
17
+ "#{ header }#{ content }#{ footer }"
18
+ end
19
+
20
+ def to_hash
21
+ {
22
+ post_content: self.content,
23
+ post_title: self.title,
24
+ post_date: self.date,
25
+ image_url: self.blog.image,
26
+ author: self.blog.author,
27
+ blog_url: self.blog.url,
28
+ blog_name: self.blog.name,
29
+ post_url: self.url,
30
+ twitter: self.blog.twitter,
31
+ twitter_url: "http://twitter.com/#{ self.blog.twitter }"
32
+ }
33
+ end
34
+
35
+ def header
36
+ ## TODO: We need categories/tags
37
+ file = self.blog.planet.config.fetch('templates_directory', '_layouts/') + 'header.md'
38
+ file_contents = File.read(file)
39
+
40
+ Mustache.render(file_contents, self.to_hash)
41
+ end
42
+
43
+ def footer
44
+ file = self.blog.planet.config.fetch('templates_directory', '_layouts/') + 'author.html'
45
+ file_contents = File.read(file)
46
+
47
+ Mustache.render(file_contents, self.to_hash)
48
+ end
49
+
50
+ def file_name
51
+ name_date = date ? date.strftime('%Y-%m-%d') : nil
52
+ name_title = title.downcase.scan(/\w+/).join('-')
53
+
54
+ [name_date, name_title].join('-')
55
+ end
56
+
57
+ end
58
+ end
@@ -1,8 +1,8 @@
1
- module Planet
1
+ class Planet
2
2
  module Version
3
3
  MAJOR = 0
4
4
  MINOR = 3
5
- PATCH = 11
5
+ PATCH = 12
6
6
 
7
7
  def self.to_s
8
8
  [MAJOR, MINOR, PATCH].join('.')
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: planet
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.11
4
+ version: 0.3.12
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-05-04 00:00:00.000000000 Z
12
+ date: 2012-05-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -83,6 +83,10 @@ extensions: []
83
83
  extra_rdoc_files: []
84
84
  files:
85
85
  - bin/planet
86
+ - lib/planet/blog.rb
87
+ - lib/planet/parsers/base_parser.rb
88
+ - lib/planet/parsers.rb
89
+ - lib/planet/post.rb
86
90
  - lib/planet/version.rb
87
91
  - lib/planet.rb
88
92
  homepage: http://poteland.com