diff --git a/features/pagination.feature b/features/pagination.feature new file mode 100644 index 00000000..6901ef92 --- /dev/null +++ b/features/pagination.feature @@ -0,0 +1,22 @@ +Feature: Site pagination + In order to paginate my blog + As a blog's user + I want divide the posts in several pages + + Scenario: Create pages + Given I have a configuration file with "paginate" set to "1" + And I have a _layouts directory + And I have an "index.html" file that contains "Basic Site" + And I have a _posts directory + And I have the following post: + | title | date | layout | content | + | Wargames | 3/27/2009 | default | The only winning move is not to play. | + | Wargames2 | 4/27/2009 | default | The only winning move is not to play2. | + When I run jekyll + Then the _site/page2 directory should exist + And the _site/page2/index.html file should exist + + + + + diff --git a/lib/jekyll/pager.rb b/lib/jekyll/pager.rb new file mode 100644 index 00000000..d20683a8 --- /dev/null +++ b/lib/jekyll/pager.rb @@ -0,0 +1,45 @@ +module Jekyll + class Pager + attr_reader :page, :per_page, :posts, :total_posts, :total_pages, :previous_page, :next_page + + def self.calculate_pages(all_posts, per_page) + num_pages = all_posts.size / per_page.to_i + num_pages.abs + 1 if all_posts.size % per_page.to_i != 0 + num_pages + end + + def self.pagination_enabled?(config, file) + File.basename(file) == 'index.html' && !config['paginate'].nil? + end + + def initialize(config, page, all_posts, num_pages = nil) + @page = page + @per_page = config['paginate'].to_i + @total_pages = num_pages || Pager.calculate_pages(all_posts, @per_page) + + if @page > @total_pages + raise RuntimeError, "page number can't be grater 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 - 1 : nil + @next_page = @page != @total_pages ? @page + 1 : nil + end + + def to_hash + { + '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 \ No newline at end of file diff --git a/test/test_pager.rb b/test/test_pager.rb new file mode 100644 index 00000000..dc0b66e8 --- /dev/null +++ b/test/test_pager.rb @@ -0,0 +1,47 @@ +require File.dirname(__FILE__) + '/helper' + +class TestPager < Test::Unit::TestCase + + def setup + stub(Jekyll).configuration do + Jekyll::DEFAULTS.merge({'source' => source_dir, 'destination' => dest_dir, + 'paginate' => 2}) + end + + @config = Jekyll.configuration + @site = Site.new(@config) + @posts = @site.read_posts('') + end + + def teardown + @config = Jekyll.configuration('paginate' => nil) + end + + def test_calculate_pages + assert_equal(2, Pager.calculate_pages(@posts, @config['paginate'])) + end + + def test_create_first_pager + pager = Pager.new(@config, 1, @posts) + assert_equal(@config['paginate'].to_i, pager.posts.size) + assert_equal(2, pager.total_pages) + assert_nil(pager.previous_page) + assert_equal(2, pager.next_page) + end + + def test_create_second_pager + pager = Pager.new(@config, 2, @posts) + assert_equal(@posts.size - @config['paginate'].to_i, pager.posts.size) + assert_equal(2, pager.total_pages) + assert_equal(1, pager.previous_page) + assert_nil(pager.next_page) + end + + def test_create_third_pager + assert_raise(RuntimeError) { Pager.new(@config, 3, @posts) } + end + + def test_pagination_enabled_with_command_option + assert_equal(true, Pager.pagination_enabled?(@config, 'index.html')) + end +end \ No newline at end of file