octopress-popular-posts 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,7 @@
1
+ Copyright (C) 2012 Wong Liang Zan<zan@liangzan.net>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,105 @@
1
+ # Octopress Popular Posts Plugin
2
+
3
+ Popular posts plugin adds a popular posts asides section to your [Octopress](http://octopress.org) blog. Popularity of the post is calculated by the [Google page rank](http://en.wikipedia.org/wiki/PageRank).
4
+
5
+ ## How it works
6
+
7
+ The popular posts template is generated with the blog. It makes queries to check the page rank for each post. Once generated, the popular posts asides section is a static page. Which means popularity is updated only when the site is generated.
8
+
9
+ Popular posts plugin caches the page rank results of each post. The results are stored in the __.page_ranks__ directory of your blog. When there is a cache, the plugin will read from it. When there is no cache, it will generate one. Caches expires in 1 month. This shortens the time needed to generate your blog.
10
+
11
+ Google page rank is updated every 3 months. A static page is sufficient as page rank don't change every hour.
12
+
13
+ ## Installation
14
+
15
+ The plugin is distributed by Ruby gems.
16
+
17
+ Add this line to your __Gemfile__
18
+
19
+ ```
20
+ gem 'octopress-popular-posts'
21
+ ```
22
+
23
+ Install it using Bundler
24
+
25
+ ```
26
+ bundle install
27
+ ```
28
+
29
+ We have to run installation commands to copy the plugin to your source
30
+
31
+ ```
32
+ bundle exec octopress-popular-posts install
33
+ ```
34
+
35
+ ## Usage
36
+
37
+ Once installed, the popular posts asides section will be generated whenever you run
38
+
39
+ ```
40
+ rake generate
41
+ ```
42
+
43
+ No additional steps are necesary.
44
+
45
+ ## Post install configurations
46
+
47
+ In your blog's __config.yml__, add this line.
48
+
49
+ ```
50
+ popular_posts_count: 5 # Posts in the sidebar Popular Posts section
51
+ ```
52
+
53
+ This sets the number of popular posts to show.
54
+
55
+ Next, we need to add the popular post aside section.
56
+
57
+ ```
58
+ default_asides: [custom/asides/about.html, custom/asides/subscribe.html, custom/asides/popular_posts.html, asides/recent_posts.html, asides/github.html, asides/twitter.html, asides/delicious.html, asides/pinboard.html, asides/googleplus.html]
59
+ ```
60
+
61
+ Note the __custom/asides/popular_posts.html__ that is added on the third entry of the array.
62
+
63
+ Once done, you need to generate the blog.
64
+
65
+ ```
66
+ rake generate
67
+ ```
68
+
69
+ The first run will take some time as the cache for popular plugins is created. You should see the popular posts aside section on your blog.
70
+
71
+ I also suggest that you ignore the cached page rank files by adding this line to your __.gitignore__
72
+
73
+ ```
74
+ .page_ranks
75
+ ```
76
+
77
+ ## Updating the plugin
78
+
79
+ Upon new updates, run the following command
80
+
81
+ ```
82
+ bundle exec octopress-popular-posts install
83
+ ```
84
+
85
+ ## Post remove configurations
86
+
87
+ To remove the plugin, run the following command
88
+
89
+ ```
90
+ bundle exec octopress-popular-posts remove
91
+ ```
92
+
93
+ You will also need to remove the following configurations
94
+
95
+ 1. The octopress-popular-posts gem from your __Gemfile__
96
+ 2. The __popular_posts_count__ variable from your __config.yml__
97
+ 3. The popular posts asides under __defaults_asides__ from your __config.yml__
98
+
99
+ ## Other themes and plugins
100
+
101
+ Shameless plug: more themes and plugins are available on [Octopress themes](http://octopressthemes.com). Feel free to take a look.
102
+
103
+ ## Copyright
104
+
105
+ Copyright &copy 2012 [Wong Liang Zan](http://liangzan.net). MIT License
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env ruby
2
+ require File.expand_path(File.dirname(__FILE__) + '/../lib/popular_posts')
@@ -0,0 +1,15 @@
1
+ require 'fileutils'
2
+ require File.join(File.dirname(__FILE__) + '/popular_posts/utilities')
3
+
4
+ # Handles the command line options
5
+ if ARGV.length == 1 && ARGV[0] == 'install'
6
+ OctopressThemes::PopularPost::Utilities.install
7
+ puts 'Octopress popular posts plugin: installed'
8
+ puts 'Please view the README on https://github.com/octopress-themes/popular-posts for post installation configurations.'
9
+ elsif ARGV.length == 1 && ARGV[0] == 'remove'
10
+ OctopressThemes::PopularPost::Utilities.remove
11
+ puts 'Octopress popular posts plugin: removed'
12
+ puts 'Please view the README on https://github.com/octopress-themes/popular-posts for post removal configurations.'
13
+ else
14
+ puts 'Usage: octopress-popular-posts [install|remove]'
15
+ end
@@ -0,0 +1,86 @@
1
+ # Public: Module for handling the installation and removal of the Octopress popular post
2
+ # plugin
3
+ module OctopressThemes
4
+ module PopularPost
5
+ module Utilities
6
+ PLUGINS_DIR = File.expand_path(File.dirname(__FILE__) + '/../../templates/plugins')
7
+ ASIDES_DIR = File.expand_path(File.dirname(__FILE__) + '/../../templates/asides')
8
+
9
+ # Public: Installs the templates to the designated locations
10
+ #
11
+ # Examples
12
+ #
13
+ # OctopressThemes::PopularPost.install
14
+ # # => nil
15
+ #
16
+ # Returns nothing
17
+ def self.install
18
+ FileUtils.copy_file plugin_path, plugin_destination
19
+ FileUtils.copy_file aside_path, aside_destination
20
+ end
21
+
22
+ # Public: Removes plugin files
23
+ #
24
+ # Examples
25
+ #
26
+ # OctopressThemes::PopularPost.remove
27
+ # # => nil
28
+ #
29
+ # Returns nothing
30
+ def self.remove
31
+ FileUtils.rm plugin_destination
32
+ FileUtils.rm aside_destination
33
+ end
34
+
35
+ protected
36
+
37
+ # Private: Returns the file path to the plugin template
38
+ #
39
+ # Examples
40
+ #
41
+ # plugin_path
42
+ # # => /path/to/plugin.rb
43
+ #
44
+ # Returns a String
45
+ def self.plugin_path
46
+ File.join(PLUGINS_DIR, 'popular_post.rb')
47
+ end
48
+
49
+ # Private: Returns the file path to the plugin destination
50
+ #
51
+ # Examples
52
+ #
53
+ # plugin_destination
54
+ # # => /path/to/destination/plugin.rb
55
+ #
56
+ # Returns a String
57
+ def self.plugin_destination
58
+ File.join(Dir.pwd, 'plugins', 'popular_post.rb')
59
+ end
60
+
61
+ # Private: Returns the file path to the aside template
62
+ #
63
+ # Examples
64
+ #
65
+ # aside_path
66
+ # # => /path/to/aside.html
67
+ #
68
+ # Returns a String
69
+ def self.aside_path
70
+ File.join(ASIDES_DIR, 'popular_posts.html')
71
+ end
72
+
73
+ # Private: Returns the file path to the aside destination
74
+ #
75
+ # Examples
76
+ #
77
+ # aside_destination
78
+ # # => /path/to/destination/aside.html
79
+ #
80
+ # Returns a String
81
+ def self.aside_destination
82
+ File.join(Dir.pwd, 'source', '_includes', 'custom', 'asides', 'popular_posts.html')
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,10 @@
1
+ <section>
2
+ <h1>Popular Posts</h1>
3
+ <ul id="recent_posts">
4
+ {% for post in site.popular_posts limit: site.popular_posts_count %}
5
+ <li class="post">
6
+ <a href="{{ root_url }}{{ post.url }}">{{ post.title }}</a>
7
+ </li>
8
+ {% endfor %}
9
+ </ul>
10
+ </section>
@@ -0,0 +1,194 @@
1
+ require 'page_rankr'
2
+ require 'yaml'
3
+
4
+ # Public: Popular posts plugin for Octopress. This plugin
5
+ # opens up the Jekyll Post and Site classes to allow
6
+ # Jekyll to render the popular posts aside section
7
+ module OctopressThemes
8
+ module PopularPost
9
+ module Post
10
+
11
+ def self.included(base)
12
+ if base.class.instance_methods.include?('page_rank') ||
13
+ base.class.protected_instance_methods.include?(%w(page_rank_expired? cache_page_rank read_page_rank_cache query_page_rank))
14
+ raise 'Octopress Popular Posts: Name clashes'
15
+ else
16
+ base.class_eval do
17
+ include PublicInstanceMethods
18
+ protected
19
+ include ProtectedInstanceMethods
20
+ end
21
+ end
22
+ end
23
+
24
+ module PublicInstanceMethods
25
+
26
+ PAGE_RANK_CACHE = '.page_ranks'
27
+
28
+ # Public: Returns the page rank of the post. It also caches the page rank.
29
+ # If a cached page rank is found, it returns the cached version.
30
+ # Caches expire in a month.
31
+ #
32
+ # host - The String which is the host name of the web site.
33
+ # It is defined in _config.yml. It is needed to form the full url
34
+ # of the post.
35
+ #
36
+ # Examples
37
+ #
38
+ # page_rank('http://foo.com')
39
+ # # => 3
40
+ #
41
+ # Returns the Integer page rank of the post
42
+ def page_rank(host)
43
+ post_name = self.url.split('/').last
44
+ cache_dir_path = File.join(Dir.pwd, PAGE_RANK_CACHE)
45
+ post_path = File.join(Dir.pwd, PAGE_RANK_CACHE, post_name)
46
+
47
+ if !File.directory?(cache_dir_path)
48
+ Dir.mkdir cache_dir_path
49
+ end
50
+
51
+ if File.exists?(post_path) && !page_rank_expired?(post_path)
52
+ read_page_rank_cache(post_path)[:rank]
53
+ else
54
+ post_page_rank = query_page_rank(host)
55
+ page_rank_content = { url: self.url, rank: post_page_rank }
56
+ cache_page_rank(page_rank_content, post_path)
57
+ post_page_rank
58
+ end
59
+ end
60
+ end
61
+
62
+ module ProtectedInstanceMethods
63
+
64
+ DAY_IN_SECS = 86400
65
+
66
+ # Private: Checks if the cached page rank has expired. It is set
67
+ # to expire in 1 month. It assumes the presence of a
68
+ # cached page rank.
69
+ #
70
+ # cache_path - The String which is the file path to the cached
71
+ # page rank.
72
+ #
73
+ # Examples
74
+ #
75
+ # page_rank_expired?('/path/to/cached/page_rank')
76
+ # # => true
77
+ #
78
+ # Returns a Boolean.
79
+ def page_rank_expired?(cache_path)
80
+ file_modified_time = File.mtime(cache_path)
81
+ time_past = Time.now - file_modified_time
82
+
83
+ # if file has not been modified for over a month
84
+ time_past > (30 * DAY_IN_SECS)
85
+ end
86
+
87
+ # Private: Caches the page rank of the post.
88
+ #
89
+ # page_rank_content - The Hash which is contains rank and
90
+ # the full url of the post.
91
+ # cache_path - The String which is the file path
92
+ # to the cache
93
+ #
94
+ # Examples
95
+ #
96
+ # cache_page_rank({url: 'http://foo/blog/bar', rank: 2}, '/path/to/cache')
97
+ # # => nil
98
+ #
99
+ # Returns nothing.
100
+ def cache_page_rank(page_rank_content, cache_path)
101
+ File.open(cache_path, 'w') do |file|
102
+ file.puts YAML.dump(page_rank_content)
103
+ end
104
+ end
105
+
106
+ # Private: Reads the cached page rank
107
+ #
108
+ # cache_path - The String which is the file path to the cache
109
+ #
110
+ # Examples
111
+ #
112
+ # read_page_rank('/path/to/cache')
113
+ # # => {url: 'http://foo', rank: 2}
114
+ #
115
+ # Returns a Hash
116
+ def read_page_rank_cache(cache_path)
117
+ YAML.load_file(cache_path)
118
+ end
119
+
120
+ # Private: Queries Google for the page rank of the post
121
+ #
122
+ # host - The String which is the host name of the web site.
123
+ # It is defined in _config.yml. It is needed to form the full url
124
+ # of the post.
125
+ #
126
+ # Examples
127
+ #
128
+ # query_page_rank('http://foo.com')
129
+ # # => {:google => 3}
130
+ #
131
+ # Returns a Hash
132
+ def query_page_rank(host)
133
+ PageRankr.ranks("#{host}#{self.url}", :google)[:google] || 0
134
+ end
135
+ end
136
+ end # Post
137
+
138
+ module Site
139
+ def self.included(base)
140
+ base.class_eval do
141
+ attr_accessor :popular_posts
142
+ alias_method :old_read, :read
143
+ alias_method :old_site_payload, :site_payload
144
+
145
+ # Public: Making use of the read method to define popular
146
+ # posts. Popular posts are sorted by page rank
147
+ #
148
+ # Examples
149
+ #
150
+ # read
151
+ # # => nil
152
+ #
153
+ # Returns nothing
154
+ def read
155
+ old_read
156
+ host = self.config['url']
157
+ self.popular_posts = self.posts.sort do |post_x, post_y|
158
+ if post_y.page_rank(host) > post_x.page_rank(host) then 1
159
+ elsif post_y.page_rank(host) == post_x.page_rank(host) then 0
160
+ else -1
161
+ end
162
+ end
163
+ end
164
+
165
+ # Public: We need to add popular_posts to site_payload, so that
166
+ # it gets passed to Liquid to be rendered.
167
+ #
168
+ # Examples
169
+ #
170
+ # site_payload
171
+ # # => nil
172
+ #
173
+ # Returns nothing
174
+ def site_payload
175
+ old_site_hash = old_site_payload
176
+ old_site_hash["site"].merge!({"popular_posts" => self.popular_posts})
177
+ old_site_hash
178
+ end
179
+ end
180
+ end # included
181
+ end # Site
182
+
183
+ end # PopularPost
184
+ end # OctopressThemes
185
+
186
+ module Jekyll
187
+ class Post
188
+ include OctopressThemes::PopularPost::Post
189
+ end
190
+
191
+ class Site
192
+ include OctopressThemes::PopularPost::Site
193
+ end
194
+ end
metadata ADDED
@@ -0,0 +1,103 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: octopress-popular-posts
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Wong Liang Zan
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-10-22 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: PageRankr
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 3.2.1
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 3.2.1
30
+ - !ruby/object:Gem::Dependency
31
+ name: rspec
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: 2.11.0
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 2.11.0
46
+ - !ruby/object:Gem::Dependency
47
+ name: jekyll
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: 0.11.2
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 0.11.2
62
+ description: Octopress popular posts adds a popular posts asides section to your Octopress
63
+ blog. It makes use of Google page rank to determine the popularity of the posts.
64
+ email:
65
+ - zan@liangzan.net
66
+ executables:
67
+ - octopress-popular-posts
68
+ extensions: []
69
+ extra_rdoc_files: []
70
+ files:
71
+ - lib/popular_posts/utilities.rb
72
+ - lib/popular_posts.rb
73
+ - bin/octopress-popular-posts
74
+ - templates/asides/popular_posts.html
75
+ - templates/plugins/popular_post.rb
76
+ - LICENSE
77
+ - README.md
78
+ homepage: https://github.com/octopress-themes/popular-posts
79
+ licenses:
80
+ - MIT
81
+ post_install_message:
82
+ rdoc_options: []
83
+ require_paths:
84
+ - lib
85
+ required_ruby_version: !ruby/object:Gem::Requirement
86
+ none: false
87
+ requirements:
88
+ - - ! '>='
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ required_rubygems_version: !ruby/object:Gem::Requirement
92
+ none: false
93
+ requirements:
94
+ - - ! '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ requirements: []
98
+ rubyforge_project:
99
+ rubygems_version: 1.8.24
100
+ signing_key:
101
+ specification_version: 3
102
+ summary: Adds a popular posts asides section to your Octopress blog.
103
+ test_files: []