octopress-gauges-popular-posts 0.1.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/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ todo.taskpaper
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in octopress-gauges-popular-posts.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Bastian Bartmann
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,96 @@
1
+ # Octopress Gauges Popular Posts Plugin #
2
+
3
+ Popular posts plugin adds a popular asides section to your [Octopress][1] blog. Popularity of the posts is calculated by page views tracked through [Gaug.es][2].
4
+
5
+ This gem is modelled after the [octopress-popular-posts gem][2].
6
+
7
+ ## Installation ##
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'octopress-gauges-popular-posts'
12
+
13
+ Install it using Bundler:
14
+
15
+ $ bundle
16
+
17
+ And run the installation to copy the plugin to your source:
18
+
19
+ $ bundle exec octopress-gauges-popular-posts install
20
+
21
+ ## Post install configurations ##
22
+
23
+ Add the Gaug.es Tracking ID of your blog and your Gaug.es API token to your **config.yml**:
24
+
25
+ gauges_tracking_id: <your-tracking-id>
26
+
27
+ Also add the following line:
28
+
29
+ popular_posts_count: 5 # Posts in the sidebar Popular Posts section
30
+
31
+ This sets the number of popular posts to show.
32
+
33
+ Next, we need to add the popular post aside section:
34
+
35
+ 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]
36
+
37
+ Note the **custom/asides/popular_posts.html** that is added on the third entry of the array.
38
+
39
+ The installation created the `config` file in the `.page_views` directory. In there you have to add your Gaug.es API token and you can also add the date started tracking your site with Gaug.es.
40
+
41
+ :token: <your-api-token>
42
+ :signup_date: 2013-06-03
43
+
44
+ If a `singup_date` is given, thes gem will fetch the views since then. Depending on the distance, this may take a while.
45
+
46
+ Once done, you need to generate the blog:
47
+
48
+ $ rake generate
49
+
50
+ I also suggest that you ignore the cached page views files and the config file with your Gaug.es API token by adding this line to your **.gitignore**:
51
+
52
+ .page_views
53
+
54
+ ## Usage ##
55
+
56
+ Once installed, the popular posts asides section will be generated whenever you run
57
+
58
+ $ rake generate
59
+
60
+ No additional steps are necesary.
61
+
62
+ ## Updating the plugin ##
63
+
64
+ After updating the gem:
65
+
66
+ $ bundle update octopress-gauges-popular-posts
67
+
68
+ Run the following command:
69
+
70
+ $ bundle exec octopress-gauges-popular-posts install
71
+
72
+ ## Removal ##
73
+
74
+ To remove the plugin, run the following command:
75
+
76
+ $ bundle exec octopress-gauges-popular-posts remove
77
+
78
+ You will also need to remove the following configurations:
79
+
80
+ 1. The octopress-popular-posts gem from your **Gemfile**
81
+ 2. The **gauges_tracking_id** variable from your **config.yml**
82
+ 3. The **popular_posts_count** variable from your **config.yml**
83
+ 4. The popular posts asides under **defaults_asides** from your **config.yml**
84
+ 5. The cache directory **.page_views**
85
+
86
+ ## Contributing ##
87
+
88
+ 1. Fork it
89
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
90
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
91
+ 4. Push to the branch (`git push origin my-new-feature`)
92
+ 5. Create new Pull Request
93
+
94
+ [1]: http://octopress.org
95
+ [2]: http://get.gaug.es
96
+ [2]: https://github.com/octothemes/popular-posts
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env ruby
2
+ require File.expand_path(File.dirname(__FILE__) + '/../lib/octopress-gauges-popular-posts')
@@ -0,0 +1,16 @@
1
+ require 'fileutils'
2
+ require "octopress-gauges-popular-posts/version"
3
+ require 'octopress-gauges-popular-posts/utilities'
4
+
5
+ # Handles the command line options
6
+ if ARGV.length == 1 && ARGV[0] == 'install'
7
+ PopularPost::Utilities.install
8
+ puts 'Octopress Gauges Popular Posts plugin: installed'
9
+ puts 'Please view the README on https://github.com/coding-chimp/octopress-gauges-popular-posts for post installation configurations.'
10
+ elsif ARGV.length == 1 && ARGV[0] == 'remove'
11
+ PopularPost::Utilities.remove
12
+ puts 'Octopress Gauges Popular Posts plugin: removed'
13
+ puts 'Please view the README on https://github.com/coding-chimp/octopress-gauges-popular-posts for post removal configurations.'
14
+ else
15
+ puts 'Usage: octopress-gauges-popular-posts [install|remove]'
16
+ end
@@ -0,0 +1,121 @@
1
+ # Public: Module for handling the installation and removal of the Octopress Gauges Popular Post
2
+ # plugin
3
+ module PopularPost
4
+ module Utilities
5
+ TEMPLATES_DIR = File.expand_path(File.dirname(__FILE__) + '/../../templates')
6
+
7
+ # Public: Installs the templates to the designated locations
8
+ #
9
+ # Examples
10
+ #
11
+ # PopularPost.install
12
+ # # => nil
13
+ #
14
+ # Returns nothing
15
+ def self.install
16
+ FileUtils.copy_file plugin_path, plugin_destination
17
+ FileUtils.copy_file aside_path, aside_destination
18
+ Dir.mkdir cache_path unless File.directory?(cache_path)
19
+ FileUtils.copy_file config_path, config_destination unless File.exists?(config_path)
20
+ end
21
+
22
+ # Public: Removes plugin files
23
+ #
24
+ # Examples
25
+ #
26
+ # 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(TEMPLATES_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(TEMPLATES_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
+
85
+ # Private: Returns the file path to the cache direcetory
86
+ #
87
+ # Examples
88
+ #
89
+ # aside_path
90
+ # # => /path/to/.page_views
91
+ #
92
+ # Returns a String
93
+ def self.cache_path
94
+ File.join(Dir.pwd, '.page_views')
95
+ end
96
+
97
+ # Private: Returns the file path to the config template
98
+ #
99
+ # Examples
100
+ #
101
+ # aside_path
102
+ # # => /path/to/config
103
+ #
104
+ # Returns a String
105
+ def self.config_path
106
+ File.join(TEMPLATES_DIR, 'config')
107
+ end
108
+
109
+ # Private: Returns the file path to the config destination
110
+ #
111
+ # Examples
112
+ #
113
+ # aside_path
114
+ # # => /path/to/destination/config
115
+ #
116
+ # Returns a String
117
+ def self.config_destination
118
+ File.join(Dir.pwd, '.page_views', 'config')
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,3 @@
1
+ module PopularPosts
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'octopress-gauges-popular-posts/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "octopress-gauges-popular-posts"
8
+ gem.version = PopularPosts::VERSION
9
+ gem.authors = ["Bastian Bartmann"]
10
+ gem.email = ["xarfai27@gmail.com"]
11
+ gem.description = "Octopress Gauges Popular Posts adds a popular posts asides section to your Octopress blog. It makes use of GitHub's Gaug.es to determine the popularity of the posts."
12
+ gem.summary = 'Adds a popular posts asides section to your Octopress blog.'
13
+ gem.homepage = "https://github.com/coding-chimp/octopress-gauges-popular-posts"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+ end
data/templates/config ADDED
@@ -0,0 +1,3 @@
1
+ ---
2
+ :token:
3
+ :signup_date:
@@ -0,0 +1,278 @@
1
+ require 'yaml'
2
+ require 'json'
3
+ require 'open-uri'
4
+
5
+ # Public: Popular posts plugin for Octopress. This plugin
6
+ # opens up the Jekyll Post and Site classes to allow
7
+ # Jekyll to render the popular posts aside section
8
+ module PopularPost
9
+ module Post
10
+
11
+ def self.included(base)
12
+ if base.class.instance_methods.include?('page_views') ||
13
+ base.class.protected_instance_methods.include?(%w(cache_page_views read_page_views_cache))
14
+ raise 'Octopress Gauges 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_VIEWS_CACHE = '.page_views'
27
+
28
+ # Public: Returns the page views of the post. It also caches the page views.
29
+ # If a cached page rank is found, it returns the cached version.
30
+ #
31
+ # Examples
32
+ #
33
+ # page_views
34
+ # # => 34
35
+ #
36
+ # Returns the Integer page views of the post
37
+ def page_views
38
+ post_name = self.url.split('/').last
39
+ cache_dir_path = File.join(Dir.pwd, PAGE_VIEWS_CACHE)
40
+ post_path = File.join(Dir.pwd, PAGE_VIEWS_CACHE, post_name)
41
+
42
+ if File.exists?(post_path)
43
+ read_page_views_cache(post_path)[:views]
44
+ else
45
+ post_views = 0
46
+ page_views_content = { path: self.url, views: post_views }
47
+ cache_page_views(page_views_content, post_path)
48
+ post_views
49
+ end
50
+ end
51
+ end
52
+
53
+ module ProtectedInstanceMethods
54
+
55
+ # Private: Caches the page views of the post.
56
+ #
57
+ # page_views_content - The Hash which is contains view and
58
+ # the path of the post.
59
+ # cache_path - The String which is the file path
60
+ # to the cache
61
+ #
62
+ # Examples
63
+ #
64
+ # cache_page_views({path: '/blog/bar', views: 2}, '/path/to/cache')
65
+ # # => nil
66
+ #
67
+ # Returns nothing.
68
+ def cache_page_views(page_views_content, cache_path)
69
+ File.open(cache_path, 'w') do |file|
70
+ file.puts YAML.dump(page_views_content)
71
+ end
72
+ end
73
+
74
+ # Private: Reads the cached page views
75
+ #
76
+ # cache_path - The String which is the file path to the cache
77
+ #
78
+ # Examples
79
+ #
80
+ # read_page_views('/path/to/cache')
81
+ # # => {path: 'http://foo', views: 2}
82
+ #
83
+ # Returns a Hash
84
+ def read_page_views_cache(cache_path)
85
+ YAML.load_file(cache_path)
86
+ end
87
+ end
88
+ end # Post
89
+
90
+ module Site
91
+
92
+ CACHE_DIR_PATH = File.join(Dir.pwd, '.page_views')
93
+
94
+ def self.included(base)
95
+ base.class_eval do
96
+ attr_accessor :popular_posts
97
+ alias_method :old_read, :read
98
+ alias_method :old_site_payload, :site_payload
99
+
100
+ # Public: Making use of the read method to define popular
101
+ # posts. Popular posts are sorted by page views
102
+ #
103
+ # Examples
104
+ #
105
+ # read
106
+ # # => nil
107
+ #
108
+ # Returns nothing
109
+ def read
110
+ old_read
111
+ update_views
112
+ self.popular_posts = self.posts.sort do |post_x, post_y|
113
+ if post_y.page_views > post_x.page_views then 1
114
+ elsif post_y.page_views == post_x.page_views then 0
115
+ else -1
116
+ end
117
+ end
118
+ end
119
+
120
+ # Public: We need to add popular_posts to site_payload, so that
121
+ # it gets passed to Liquid to be rendered.
122
+ #
123
+ # Examples
124
+ #
125
+ # site_payload
126
+ # # => nil
127
+ #
128
+ # Returns nothing
129
+ def site_payload
130
+ old_site_hash = old_site_payload
131
+ old_site_hash["site"].merge!({"popular_posts" => self.popular_posts})
132
+ old_site_hash
133
+ end
134
+
135
+ protected
136
+
137
+ # Private: Checks wether there is a last_run or signup_date and
138
+ # fetches views since then.
139
+ #
140
+ # Examples
141
+ #
142
+ # update_views
143
+ # # => nil
144
+ #
145
+ # Returns nothing
146
+ def update_views
147
+ gauges_config = YAML.load_file("#{CACHE_DIR_PATH}/config")
148
+ views = load_views
149
+ last_run = gauges_config[:last_run] || gauges_config[:signup_date]
150
+ yesterday = Date.today - 1
151
+
152
+ if last_run.nil?
153
+ views = fetch_views(views, yesterday, gauges_config[:token])
154
+ elsif last_run && last_run != Date.today
155
+ for date in last_run..yesterday do
156
+ views = fetch_views(views, date, gauges_config[:token])
157
+ end
158
+ end
159
+
160
+ cache_views(views)
161
+ update_last_run(gauges_config)
162
+ end
163
+
164
+ # Private: Sets the last run date to today and caches it.
165
+ #
166
+ # gauges_config - The path to the gauges config file
167
+ #
168
+ # Examples
169
+ #
170
+ # update_last_run('/path/to/page/gauges/config')
171
+ # # => nil
172
+ #
173
+ # Returns nothing
174
+ def update_last_run(gauges_config)
175
+ gauges_config[:last_run] = Date.today
176
+ File.open("#{CACHE_DIR_PATH}/config", 'w') do |file|
177
+ file.puts YAML.dump(gauges_config)
178
+ end
179
+ end
180
+
181
+ # Private: Caches the views.
182
+ #
183
+ # views - A hash of hashes that contain the page views
184
+ # and path of the post.
185
+ #
186
+ # Examples
187
+ #
188
+ # cache_views({{path: '/blog/bar', views: 2}, ...})
189
+ # # => nil
190
+ #
191
+ # Returns nothing
192
+ def cache_views(views)
193
+ views.each do |k, v|
194
+ content = { path: k, views: v }
195
+ file_path = "#{CACHE_DIR_PATH}#{k.to_s}"
196
+
197
+ File.open(file_path, 'w') do |file|
198
+ file.puts YAML.dump(content)
199
+ end
200
+ end
201
+ end
202
+
203
+ # Private: Loads the view counts from the cache.
204
+ #
205
+ # Examples
206
+ #
207
+ # load_views
208
+ # # => {{path: '/blog/bar', views: 2}, ...}
209
+ #
210
+ # Returns a hash of of hashes that contain the path and
211
+ # views of a post
212
+ def load_views
213
+ posts = {}
214
+ Dir.foreach(CACHE_DIR_PATH) do |file|
215
+ next if file == '.' || file == '..' || file == 'config'
216
+ content = YAML.load_file("#{CACHE_DIR_PATH}/#{file}")
217
+ posts[content[:path]] = content[:views]
218
+ end
219
+ posts
220
+ end
221
+
222
+ # Private: Takes the the current views loaded from cash,
223
+ # calls the Gaug.es API for the views of a specified
224
+ # day, updates the loaded views and returns them.
225
+ #
226
+ # views - An hash of hashes containing the path and views
227
+ # of posts loaded from the cache
228
+ # date - The date for which the API call will be made
229
+ # token - The Gaug.es API token needed for the API call
230
+ #
231
+ # Examples
232
+ #
233
+ # fetch_views({{path: '/blog/bar', views: 2}, ...},
234
+ # 2013-06-03, 188fa4710f08973145c1038af83ba78b)
235
+ # # => {{path: '/blog/bar', views: 11}, ...}
236
+ #
237
+ # Returns a hash of hashed containing the path and updated page
238
+ # updated page views
239
+ def fetch_views(views, date, token)
240
+ puts "Popular posts: fetches views for #{date}"
241
+ gauge_id = config['gauges_tracking_id']
242
+ host = config['url'].gsub "http://", ""
243
+
244
+ content = JSON.parse(open("https://secure.gaug.es/gauges/#{gauge_id}/content?date=#{date}",
245
+ 'X-Gauges-Token' => token).read)['content']
246
+
247
+ content.each do |page|
248
+ unless page['path'] == "/" || page['path'].include?("/categories/") ||
249
+ page['path'] == "/archives/" || page['path'].include?("/page/") ||
250
+ page['path'] == "/about/" || page['host'] != host
251
+ path = page['path'].gsub(/(\/|\/#.*)$/, "")
252
+ current_views = views[path]
253
+ if current_views.nil?
254
+ updated_views = page['views'].to_i
255
+ else
256
+ updated_views = current_views.to_i + page['views'].to_i
257
+ end
258
+ views[path] = updated_views
259
+ end
260
+ end
261
+ views
262
+ end
263
+
264
+ end
265
+ end # included
266
+ end # Site
267
+
268
+ end # PopularPost
269
+
270
+ module Jekyll
271
+ class Post
272
+ include PopularPost::Post
273
+ end
274
+
275
+ class Site
276
+ include PopularPost::Site
277
+ end
278
+ 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>
metadata ADDED
@@ -0,0 +1,62 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: octopress-gauges-popular-posts
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Bastian Bartmann
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-06-03 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Octopress Gauges Popular Posts adds a popular posts asides section to
15
+ your Octopress blog. It makes use of GitHub's Gaug.es to determine the popularity
16
+ of the posts.
17
+ email:
18
+ - xarfai27@gmail.com
19
+ executables:
20
+ - octopress-gauges-popular-posts
21
+ extensions: []
22
+ extra_rdoc_files: []
23
+ files:
24
+ - .gitignore
25
+ - Gemfile
26
+ - LICENSE.txt
27
+ - README.md
28
+ - Rakefile
29
+ - bin/octopress-gauges-popular-posts
30
+ - lib/octopress-gauges-popular-posts.rb
31
+ - lib/octopress-gauges-popular-posts/utilities.rb
32
+ - lib/octopress-gauges-popular-posts/version.rb
33
+ - octopress-gauges-popular-posts.gemspec
34
+ - templates/config
35
+ - templates/popular_post.rb
36
+ - templates/popular_posts.html
37
+ homepage: https://github.com/coding-chimp/octopress-gauges-popular-posts
38
+ licenses: []
39
+ post_install_message:
40
+ rdoc_options: []
41
+ require_paths:
42
+ - lib
43
+ required_ruby_version: !ruby/object:Gem::Requirement
44
+ none: false
45
+ requirements:
46
+ - - ! '>='
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ required_rubygems_version: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ requirements: []
56
+ rubyforge_project:
57
+ rubygems_version: 1.8.24
58
+ signing_key:
59
+ specification_version: 3
60
+ summary: Adds a popular posts asides section to your Octopress blog.
61
+ test_files: []
62
+ has_rdoc: