Skip to content

Instantly share code, notes, and snippets.

@indolent-gnathostome
Last active December 31, 2015 10:38
Show Gist options
  • Save indolent-gnathostome/7974134 to your computer and use it in GitHub Desktop.
Save indolent-gnathostome/7974134 to your computer and use it in GitHub Desktop.
Independent, sortable pagination for ruhoh.rb (plugin)
module SortablePaginator
# provides helpful metrics for the paginator and mustache templates
def paginator_data
per_page = config["paginator"]["per_page"] rescue 5
paginator_sort = config["paginator"]["sort"] rescue 'desc'
current_page = master.page_data['current_page'].to_i
post_count = all.length
page_count = (post_count.to_f/per_page).ceil
if paginator_sort == 'asc'
current_page = current_page.zero? ? page_count : current_page
next_oldest = (current_page == 1) ? false : current_page - 1
next_newest = (current_page == page_count) ? false : current_page + 1
offset = post_count - ((current_page)*per_page)
if offset < 0
per_page = per_page + offset
offset = 0
end
else
# descending pagination (old default)
current_page = current_page.zero? ? 1 : current_page
next_oldest = (current_page == page_count) ? false : current_page + 1
next_newest = (current_page == 1) ? false : current_page - 1
offset = (current_page-1)*per_page
end
# resulting data structure
{
'posts_per_page' => per_page,
'post_count' => post_count,
'page_count' => page_count,
'url' => config['paginator']['url'] || '',
'this_page' => {
'number' => current_page,
'next_oldest_page' => next_oldest,
'next_newest_page' => next_newest,
'post_offset' => offset,
}
}
end
# current_page is set via a compiler or previewer
# in which it can discern what current_page to serve
# current_page is set via a compiler or previewer
# in which it can discern what current_page to serve
def paginator
data = paginator_data
page_batch = all[ data['this_page']['post_offset'], data['posts_per_page'] ]
raise "Page does not exist" unless page_batch
page_batch
end
def paginator_navigation
paginator_config = config["paginator"] || {}
paginator_config_sort = paginator_config['sort'] || 'desc'
page_count = all.length
total_pages = (page_count.to_f/paginator_config["per_page"]).ceil
current_page = master.page_data['current_page'].to_i
current_page = current_page.zero? ? 1 : current_page
pages = total_pages.times.map { |i|
url = if i == (total_pages - 1) and paginator_config['sort'] == 'asc' \
and paginator_config["root_page"]
paginator_config["root_page"]
elsif i.zero? and paginator_config_sort == 'desc' \
and paginator_config["root_page"]
paginator_config["root_page"]
else
"#{paginator_config["url"]}/#{i+1}"
end
{
"url" => ruhoh.to_url(url),
"name" => "#{i+1}",
"is_active_page" => (i+1 == current_page)
}
}
pages
end
end
module Ruhoh::Resources::Pages
class Compiler
# helper method
def pagination_render( view )
resource_name = @collection.resource_name
Ruhoh::Friend.say { cyan "#{resource_name} paginator: page_data: (#{view.page_data} )
" }
FileUtils.mkdir_p File.dirname(view.compiled_path)
File.open(view.compiled_path, 'w:UTF-8') { |p| p.puts view.render_full }
Ruhoh::Friend.say { green " > #{view.page_data['url']}" }
end
def pagination
config = @collection.config["paginator"] || {}
resource_name = @collection.resource_name
Ruhoh::Friend.say { cyan "#{resource_name} paginator: page_data: (#{view.page_data} )
" }
FileUtils.mkdir_p File.dirname(view.compiled_path)
File.open(view.compiled_path, 'w:UTF-8') { |p| p.puts view.render_full }
Ruhoh::Friend.say { green " > #{view.page_data['url']}" }
end
def pagination
config = @collection.config["paginator"] || {}
resource_name = @collection.resource_name
if config["enable"] == false
Ruhoh::Friend.say { yellow "#{resource_name} paginator: disabled - skipping." }
return
end
pages_count = @collection.all.length
total_pages = (pages_count.to_f/config["per_page"]).ceil
Ruhoh::Friend.say { cyan "#{resource_name} paginator: (#{total_pages} pages)" }
total_pages.times.map { |i|
# if a root page is defined we assume it's getting compiled elsewhere.
if not (config.key? 'sort' and config['sort'] == 'asc') and \
(i.zero? && config["root_page"])
next
end
url = "#{config["url"]}/#{i+1}"
view = @ruhoh.master_view({"resource" => resource_name})
view.page_data = {
"layout" => config["layout"],
"current_page" => (i+1),
"total_pages" => total_pages,
"url" => @ruhoh.to_url(url)
}
pagination_render( view )
# in ascending pagination, 'root_page' is a copy of the latest page.
if i == ( total_pages - 1 ) and config["root_page"]
view.page_data['url'] = "/#{ config['root_page'] }"
pagination_render( view )
end
}
end
end
end
Ruhoh::Resources::Pages::CollectionView.send(:include, SortablePaginator)
# TODO: figure out why .send doesn't seem to affect Compiler
#Ruhoh::Resources::Pages::Compiler.send(:include, SortableCompilerPaginator)
# ...in the middle of config.yml:
#
# paginate the 'posts' collection ASC, but keep the collection sorting DESC
posts:
sort: ["date", "desc"]
permalink: "/:categories/:title/"
permalink: "/:year/:month/:day/:title/"
summary_lines: 20
latest: 5
rss:
enable: true
limit: 10
paginator:
enable: true
sort: 'asc'
url: "/posts/page/"
per_page: 10
#
# ...and so on
# I've set up my ruhoh project with its own features/ directory so I can
# test new plugins, etc
Scenario: Paginating asc by date, Collection sorting desc by date.
Given a config file with values:
| essays | { "paginator" : { "per_page" : 2, "sort" : "asc" }, "sort": [ "date", "desc"
] } |
And the file "essays/post-1.md" with body:
"""
---
date: "2010-12-01"
---
<post>1</post>
"""
And the file "essays/post-2.md" with body:
"""
---
date: "2010-12-02"
---
<post>2</post>
"""
And the file "essays/post-3.md" with body:
"""
---
date: "2011-01-01"
---
<post>3</post>
"""
And the file "essays/post-4.md" with body:
"""
---
date: "2011-08-11"
---
<post>4</post>
"""
And the file "essays/post-5.md" with body:
"""
---
date: "2012-01-02"
---
<post>5</post>
"""
When I compile my site
Then my compiled site should have the file "essays/index/1/index.html"
And this file should contain the content node "post|21
Then my compiled site should have the file "essays/index/2/index.html"
And this file should contain the content node "post|43"
Then my compiled site should have the file "essays/index/3/index.html"
And this file should contain the content node "post|5"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment