Jekyll 添加翻页部分(包含分类页,标签页)

100
TaoAlpha
2015-06-027360 words22 minutes to read

缘起

随着博文数量正式达到15篇以上, 我寻思着也是时候给blog增加一个翻页的部分了. 首先当然是研究jekyll的官方文档, 然后再结合我们自己的需求进行修改. 因为考虑到blog的通常结构都会有category和tag, 而且昨天刚刚增加了 tag专属页, 所以就希望能够在category和tag页下都增加一个翻页的模块. 而目前jekyll的默认paginator尚无法支持这样的需求, 我们只能自己动手喽~

jekyll paginator

开启翻页模块

jekyll有默认的paginator, 可以非常简单的开启. 只需要在_config.yml中加入下面这行行即可:

1
2
3
{% raw %}
paginate: 2
{% endraw %}

这里的paginate表示是单页显示的博文条数. 这里设置2也是为了方便测试, 具体数值大家根据需要自行调整即可.

通过设定paginate后, 就可以重新build一下jekyll, 你就会发现在_site/blog路径下多出了一些pageX的文件夹了~ 这些就是生成的分页了.

添加翻页导航模块

开启翻页后, 就需要我们自行在页面上添加上翻页导航组件了. 这里需要借助paginator这个对象, 其包含了当前页面下分页的一些基本属性. 具体参照下面的代码即可.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
{% raw %}
{% if paginator.total_pages > 1 %}
<div class="pagination">
{% if paginator.previous_page %}
<a href="{{ paginator.previous_page_path | prepend: site.baseurl | replace: '//', '/' }}">&laquo; Prev</a>
{% else %}
<span>&laquo; Prev</span>
{% endif %}

{% for page in (1..paginator.total_pages) %}
{% if page == paginator.page %}
<em>{{ page }}</em>
{% elsif page == 1 %}
<a href="{{ '/' | replace: '//', '/' }}">{{ page }}</a>
{% else %}
<a href="{{ site.paginate_path | prepend: site.baseurl | replace: '//', '/' | replace: ':num', page }}">{{ page }}</a>
{% endif %}
{% endfor %}

{% if paginator.next_page %}
<a href="{{ paginator.next_page_path | prepend: site.baseurl | replace: '//', '/' }}">Next &raquo;</a>
{% else %}
<span>Next &raquo;</span>
{% endif %}
</div>
{% endif %}
{% endraw %}

当然, 对应的页码显示样式就要看大家自己设定喽~

定制翻页插件

插件部分

如果只需要在首页开启翻页的话, 如此倒也是足够了. 但是如果想要在category以及tag分页上都加上翻页导航的话, 就需要在上述基础上自行定制了.

首先我们可以学习以下默认的pagination是如何做的, 这一点我们可以在github上jekyll-paginate的主页查看其源码.

可以看到基本方法是完全可以通用的, 只是默认情况下的pager这个包含了翻页信息的对象只包含在了首页的创建上. 我们完全可以在生成tag页和category页的时候也同时生成一个对应的pager对象. 接下来我们就可以在原来的 jekyll生成tag页中的示例代码基础上加上pager.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
module Jekyll
class TagIndex < 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'), 'tagpage.html')
self.data['tag'] = tag
tag_title_prefix = site.config['tag_title_prefix'] || 'Posts Tagged &ldquo;'
tag_title_suffix = site.config['tag_title_suffix'] || '&rdquo;'
self.data['title'] = "#{tag_title_prefix}#{tag}#{tag_title_suffix}"
self.data['pname'] = "tag/#{tag}"
// 自定义的一个页面标识, 同时也为了后面修改tag单页增加一个url前缀用的
end
end
class TagGenerator < Generator
safe true
def generate(site)
if site.layouts.key? 'tagpage'
dir = site.config['tag_dir'] || 'tag'
site.tags.keys.each do |tag|
write_tag_index(site, File.join(dir, tag), tag)
#write_tag_index(site, File.join(dir, tag.split.map(&:capitalize).join("-")), tag.split.map(&:capitalize).join("-"))
end
end
end
def write_tag_index(site, dir, tag)
// 下述代码有所修改, 注意!
tag_posts = site.posts.find_all {|post| post.tags.include?(tag)}.sort_by {|post| -post.date.to_f}
// 当前tag的所有post
num_pages = TagPager.calculate_pages(tag_posts, site.config['paginate'].to_i)
// 所有post分出的页数
(1..num_pages).each do |page|
pager = TagPager.new(site, page, tag_posts, tag, num_pages)
index = TagIndex.new(site, site.source, dir, tag)
index.pager = pager
index.dir = dir
if page != 1
index.dir = File.join(dir, "page#{page}")
// 生成page路径
end
index.render(site.layouts, site.site_payload)
index.write(site.dest)
site.pages << index
end
end
end

class TagPager < Jekyll::Paginate::Pager
// 继承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

如上, 基本插件部分就没啥事了~ 当然, category的部分几乎可以说是完全一样的, 只需要把对应tag的部分全部替换为category的相应属性就行啦. 这里就不占位的贴代码了.

页面导航组件显示部分

页面级的改动也不多, 因为我的category, 首页, tag页用的是同一个模板, 所以修改起来相对容易~ 只是针对不同的页码调整了以下翻页导航的url构成~ 如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
{% raw %}
{% if paginator.total_pages > 1 %}
{% assign pname = page.pname %}
{% if page.pname == "blog" %}
{% assign pname = "" %}
{% endif %}
<!-- pname就是我之前插件中加入的那个用来表明所属页面属性的, 顺带也故意写成了方便添加url的路径格式, 且下面这些路径还需要根据具体情况自行调整~ -->
<div class="pagination">
{% if paginator.previous_page %}
<a href="{{ paginator.previous_page_path | prepend: "/" | prepend: pname | prepend: "/" | prepend: site.baseurl | replace: '//', '/' }}">&laquo; Prev</a>
{% else %}
<span>&laquo; Prev</span>
{% endif %}

{% for page in (1..paginator.total_pages) %}
{% if page == paginator.page %}
<em>{{ page }}</em>
{% elsif page == 1 %}
<a href="{{ '/' | prepend: pname |prepend: "/"| prepend: site.baseurl | replace: '//', '/' }}">{{ page }}</a>
{% else %}
<a href="{{ site.paginate_path | prepend: "/" | prepend: pname | prepend: "/" | prepend: site.baseurl | replace: '//', '/' | replace: ':num', page }}">{{ page }}</a>
{% endif %}
{% endfor %}

{% if paginator.next_page %}
<a href="{{ paginator.next_page_path | prepend: "/" | prepend: pname | prepend: "/" | prepend: site.baseurl | replace: '//', '/' }}">Next &raquo;</a>
{% else %}
<span>Next &raquo;</span>
{% endif %}
</div>
{% endif %}
{% endraw %}

恩, 完事! 剩下的就是大家根据自己的需要来赋予翻页组件合适的样式喽~

结论

本人的ruby属于初学, 所以代码基本是我参照源码和前人的经验修改而来的~ 也算是学习的过程, 基本参照对象都会列在下面的参考资料中~ 尽请翻看~

参考资料