aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrandon Mathis <brandon@imathis.com>2011-08-15 23:59:28 -0400
committerBrandon Mathis <brandon@imathis.com>2011-08-16 00:43:22 -0400
commit1c555116be19efe29d19d19286abbb21085a5756 (patch)
treec843bf8683b1c0dcd8a9467663f87a9e2b6f569d
parenta5f87149fec051cbc395bc645de71469361f8c78 (diff)
downloadmy_new_personal_website-1c555116be19efe29d19d19286abbb21085a5756.tar.xz
my_new_personal_website-1c555116be19efe29d19d19286abbb21085a5756.zip
Added support for pagination with a blog index in any directory (helps with landing pages). Added configuration for pagination directory base
-rw-r--r--.themes/classic/source/index.html39
-rw-r--r--_config.yml5
-rw-r--r--plugins/pagination.rb121
3 files changed, 162 insertions, 3 deletions
diff --git a/.themes/classic/source/index.html b/.themes/classic/source/index.html
index fa5310a9..e7e96956 100644
--- a/.themes/classic/source/index.html
+++ b/.themes/classic/source/index.html
@@ -2,4 +2,41 @@
layout: default
---
-{% include blog_index.html %}
+<div class="blog-index">
+{% assign index = true %}
+{% for post in paginator.posts %}
+{% assign content = post.content %}
+ <article>
+ {% include article.html %}
+ </article>
+{% endfor %}
+<nav role="pagination">
+ <div>
+ {% if paginator.next_page %}
+ <a class="prev" href="{{paginator.next_page}}">&larr; Older</a>
+ {% endif %}
+ <a href="/blog/archives">Blog Archives</a>
+ {% if paginator.previous_page %}
+ <a class="next" href="{{paginator.previous_page}}">Newer &rarr;</a>
+ {% endif %}
+ </div>
+</nav>
+{% if site.disqus_short_name %}
+<script type="text/javascript">
+ var disqus_shortname = '{{ site.disqus_short_name }}';
+ (function () {
+ var s = document.createElement('script'); s.async = true;
+ s.type = 'text/javascript';
+ s.src = 'http://' + disqus_shortname + '.disqus.com/count.js';
+ (document.getElementsByTagName('HEAD')[0] || document.getElementsByTagName('BODY')[0]).appendChild(s);
+ }());
+</script>
+{% endif %}
+</div>
+<aside role=sidebar>
+ {% if site.blog_index_asides.size %}
+ {% include_array blog_index_asides %}
+ {% else %}
+ {% include_array default_asides %}
+ {% endif %}
+</aside>
diff --git a/_config.yml b/_config.yml
index 3d6fee89..403f9ba8 100644
--- a/_config.yml
+++ b/_config.yml
@@ -29,8 +29,9 @@ category_dir: blog/categories
markdown: rdiscount
pygments: false # default python pygments have been replaced by pygments.rb
-paginate: 10 # Posts per page on the blog index
-recent_posts: 5 # Posts in the sidebar Recent Posts section
+paginate: 10 # Posts per page on the blog index
+pagination_dir: blog # Directory base for pagination URLs eg. /blog/page/2/
+recent_posts: 5 # Posts in the sidebar Recent Posts section
# list each of the sidebar modules you want to include, in the order you want them to appear.
# To add custom asides, create files in /source/_includes/custom/asides/ and add them to the list like 'custom/asides/custom_aside_name.html'
diff --git a/plugins/pagination.rb b/plugins/pagination.rb
new file mode 100644
index 00000000..001ddd47
--- /dev/null
+++ b/plugins/pagination.rb
@@ -0,0 +1,121 @@
+module Jekyll
+
+ class Pagination < Generator
+ # This generator is safe from arbitrary code execution.
+ safe true
+
+ # Generate paginated pages if necessary.
+ #
+ # site - The Site.
+ #
+ # Returns nothing.
+ def generate(site)
+ site.pages.dup.each do |page|
+ paginate(site, page) if Pager.pagination_enabled?(site.config, page)
+ end
+ end
+
+ # Paginates the blog's posts. Renders the index.html file into paginated
+ # directories, e.g.: page2/index.html, page3/index.html, etc and adds more
+ # site-wide data.
+ #
+ # site - The Site.
+ # page - The index.html Page that requires pagination.
+ #
+ # {"paginator" => { "page" => <Number>,
+ # "per_page" => <Number>,
+ # "posts" => [<Post>],
+ # "total_posts" => <Number>,
+ # "total_pages" => <Number>,
+ # "previous_page" => <Number>,
+ # "next_page" => <Number> }}
+ def paginate(site, page)
+ all_posts = site.site_payload['site']['posts']
+ pages = Pager.calculate_pages(all_posts, site.config['paginate'].to_i)
+ page_dir = page.destination('').sub(/\/[^\/]+$/, '')
+ page_dir_config = site.config['pagination_dir']
+ dir = ((page_dir_config || page_dir) + '/').sub(/^\/+/, '')
+
+ (1..pages).each do |num_page|
+ pager = Pager.new(site.config, num_page, all_posts, pages, page_dir+'/', '/'+dir)
+ if num_page > 1
+ newpage = Page.new(site, site.source, page_dir, page.name)
+ newpage.pager = pager
+ newpage.dir = File.join(page.dir, "#{dir}page/#{num_page}")
+ site.pages << newpage
+ else
+ page.pager = pager
+ end
+ end
+ end
+ end
+
+ class Pager
+ attr_reader :page, :per_page, :posts, :total_posts, :total_pages, :previous_page, :next_page
+
+ # Calculate the number of pages.
+ #
+ # all_posts - The Array of all Posts.
+ # per_page - The Integer of entries per page.
+ #
+ # Returns the Integer number of pages.
+ def self.calculate_pages(all_posts, per_page)
+ (all_posts.size.to_f / per_page.to_i).ceil
+ end
+
+ # Determine if pagination is enabled for a given file.
+ #
+ # config - The configuration Hash.
+ # file - The String filename of the file.
+ #
+ # Returns true if pagination is enabled, false otherwise.
+ def self.pagination_enabled?(config, file)
+ file.name == 'index.html' && !config['paginate'].nil? && file.content =~ /paginator\./
+ end
+
+ # Initialize a new Pager.
+ #
+ # config - The Hash configuration of the site.
+ # page - The Integer page number.
+ # all_posts - The Array of all the site's Posts.
+ # num_pages - The Integer number of pages or nil if you'd like the number
+ # of pages calculated.
+ def initialize(config, page, all_posts, num_pages = nil, index_dir, pagination_dir)
+ @page = page
+ @per_page = config['paginate'].to_i
+ @page_dir = pagination_dir + 'page/'
+ @total_pages = num_pages || Pager.calculate_pages(all_posts, @per_page)
+ @previous_page = nil
+
+ if @page > @total_pages
+ raise RuntimeError, "page number can't be greater than total pages: #{@page} > #{@total_pages}"
+ end
+
+ init = (@page - 1) * @per_page
+ offset = (init + @per_page - 1) >= all_posts.size ? all_posts.size : (init + @per_page - 1)
+
+ @total_posts = all_posts.size
+ @posts = all_posts[init..offset]
+ @previous_page = @page != 1 ? @page_dir + (@page - 1).to_s + '/' : nil
+ @previous_page = index_dir if @page - 1 == 1
+ @next_page = @page != @total_pages ? @page_dir + (@page + 1).to_s + '/' : nil
+ end
+
+ # Convert this Pager's data to a Hash suitable for use by Liquid.
+ #
+ # Returns the Hash representation of this Pager.
+ def to_liquid
+ {
+ 'page' => page,
+ 'per_page' => per_page,
+ 'posts' => posts,
+ 'total_posts' => total_posts,
+ 'total_pages' => total_pages,
+ 'previous_page' => previous_page,
+ 'next_page' => next_page
+ }
+ end
+ end
+
+end
+