Jekyll currently does't support natively pagination by categories
or by tags
. So i found a plugin called jekyll-tagging-pagination
.
Source code of this plugin:
tags-pagination.rb
module Jekyll
class TagGenerator < Generator
safe true
def generate(site)
if site.layouts.key? 'tag'
site.tags.keys.each do |tag|
paginate(site, tag)
end
end
end
def paginate(site, tag)
tag_posts = site.posts.find_all {|post| post.tags.include?(tag)}.sort_by {|post| -post.date.to_f}
num_pages = TagPager.calculate_pages(tag_posts, site.config['paginate'].to_i)
(1..num_pages).each do |page|
pager = TagPager.new(site, page, tag_posts, tag, num_pages)
dir = File.join('tags', tag, page > 1 ? "page#{page}" : '')
page = TagPage.new(site, site.source, dir, tag)
page.pager = pager
site.pages << page
end
end
end
class TagPage < Page
def initialize(site, base, dir, tag)
@site = site
@base = base
@dir = dir
@name = 'index.html'
self.process(@name)
self.read_yaml(File.join(base, '_layouts'), 'tag.html')
self.data['tag'] = tag
#self.data['title'] = "Posts Tagged “"+tag+"”"
end
end
class TagPager < Jekyll::Paginate::Pager
attr_reader :tag
def initialize(site, page, all_posts, tag, num_pages = nil)
@tag = tag
super site, page, all_posts, num_pages
end
alias_method :original_to_liquid, :to_liquid
def to_liquid
liquid = original_to_liquid
liquid['tag'] = @tag
liquid
end
end
end
To use this plugin, create a file called tag.html
in the _layout
folder.
Then put the following code snippet as a start.
{% for post in paginator.posts %}
{{ post.title }}
{% endfor %}
When Jekyll generates static website, it will also generate a new folder called tags
which contains all the tags that you put in your post.
For example, in _site
folder, we'll get /tags/cemosis/
, /tags/feelpp/
, and /tags/csmi/
three folders. Each folder contains paginated folders like page2, page3 ...
and one file called index.html
for the first page.
The plugin's Readme said we can use paginate.[tag name]
to access these files described above, but actually it doesn't work.
So instead I put URL to access directly these html files. Just modify the news link to /tags/cemosis/
.
As a result, I must put more HTML and CSS code into tag.html
.
---
layout: default
---
<div class="container">
<div class="row">
<center><h3>Actualités</h3></center>
{% for post in paginator.posts %}
{% include news.html %}
{% endfor %}
<!-- Pagination links -->
{% if paginator.total_pages > 1 %}
{% assign tag = page.tag %}
<center>
{% if paginator.previous_page %}
<a href="/tags/{{ tag }}{{ paginator.previous_page_path | replace: 'news_', '' | replace: '//', '/' }}">« Précédente</a>
{% else %}
<span>« Précédente</span>
{% endif %}
{% for page in (1..paginator.total_pages) %}
{% if page == paginator.page %}
<em>{{ page }}</em>
{% elsif page == 1 %}
<a href="/tags/{{ tag }}">{{ page }}</a>
{% else %}
<a href="/tags/{{ tag }}{{ site.paginate_path | replace: 'news_/', '' | replace: ':num', page }}">{{ page }}</a>
{% endif %}
{% endfor %}
{% if paginator.next_page %}
<a href="/tags/{{ tag }}{{ paginator.next_page_path | replace: 'news_', '' | replace: '//', '/' }}">Suivante »</a>
{% else %}
<span>Suivante »</span>
{% endif %}
</center>
{% endif %}
</div>
</div>
Now the pagination by tag works fine, but there is another issue: it doesn't care if the paginated post are in the same categories.
So i modified some ruby code in the plugin:
def paginate(site, tag)
tag_posts = site.posts.find_all {|post| post.tags.include?(tag) && post.categories.include?(news)}.sort_by {|post| -post.date.to_f}
...
end
end
And now I get only all the post in news
categories with cemosis
tag.
The pagination is for now only used in www.cemosis.fr->Vie de Cemosis->Actualité
correspond to the folder /tags/cemosis/ under _site
.