使用Jekyll在Github上搭建个人博客(文章分类索引)

2012 查看

系列文章传送门:

使用Jekyll在Github上搭建个人博客(环境搭建)

使用Jekyll在Github上搭建个人博客(博客编写)

使用Jekyll在Github上搭建个人博客(分页实现)

今天又滚出去野了一天,打牌输了,好在输的不多,聊天聊到了以后的路子,不太好走啊...

使用Category分类

一般来说,一个个人博客的文章会分为很多种,比如说有记录生活情感的、技术交流的、转载他人的等等,而在jekyll中,可以使用Category进行分类,使用方法非常简单

为文章定义分类

首先要确定文章属于哪个分类。这个配置可以设置在文章的头信息中,使用category或者categories确定,如文章属于“test”类别:

---
layout: MyTemplate
title: Category Sample
category: test
---

或者使用categories,这个属性接受一个数组,代表这篇文章所述的类,如文章属于“test”和“sample”类别:

---
layout: MyTemplate
title: Category Sample
categories: [test, sample]
---

加入这些信息后,文章所属分类就定义好了。但是还需要在页面(或者模板)中输出分类所有的文章才能完成以分类为基础的索引功能

输出所有分类

所有的分类信息都被存储在site对象的categories中,所以可以通过liquid的for标签进行输出:

{% for category in site.categories %}
<h2>{{ category | first }}</h2>
</span>{{ category | last | size }}</span>
<ul class="arc-list">
    {% for post in category.last %}
        <li>{{ post.date | date:"%d/%m/%Y"}}<a href="{{ post.url }}">{{ post.title }}</a></li>
    {% endfor %}
</ul>
{% endfor %}

上面代码可以看到,首先从site中取出所有categories的信息,分别输出。categories的元素为一个两个元素的数组,第一个元素为category的名字,第二个元素则为一个数组,保存有该分类下文章的列表

于是乎就很简单了:
* 使用{{ category | first }}输出分类的名称
* 使用{{ category | last | size }}输出该分类下文章的数目
* 遍历category.last输出所有文章的信息,构建到该文章的索引

这样就完成了在一个页面上输出所有分类,及其所有文章索引的方法了。但是需要注意的是,这种方式只能获取所有分类,而不能获取某个单一分类下的文章。毕竟jekyll编译完成后是静态页面,没有办法动态生成(除非为每一个分类都创建一个html文件,并在首页上创建一大堆通向这些html文件的a标签)。事实上,这个问题有一个解决方法是使用jekyll插件去解决。但是github不支持三方jekyll插件。所以必须绕个弯子来实现这种方式

输出单个分类下的所有文章

我们可以轻松获得所有分类下的所有文章,但是没有办法只输出一个分类下的文章。

首先可以想到的解决方法方法:首先把所有分类和所有文章的html生成好,然后全部隐藏。把需要显示的分类的名称放在url中,使用javascript读取名称出来后根据名称显示该分类。这样做有一个坏处:如果文章数较多,而每个文章都有很多分类,那么就会出现html文件很大,加载很慢的情况。

于是乎又想到一种方法,将所有的数据压缩在JSON中,然后通过javascript解析JSON对象,然后动态生成html。这种方法不过是一个折中,如果需要生成的html较为复杂,完全可以使用第一种方法。但如果只是简单的索引,这种方法就足够了。根据需要考量吧。下面放一点简单的源码来介绍一下这种方法:

var dataStr = '{ {% for cat in site.categories %}{% if cat[0] != site.categories.first[0] %},{% endif %}"{{ cat[0] }}":[{% for post in cat[1] %}{% if post != cat[1].first %},{% endif %}{"url":"{{post.url}}", "title":"{{post.title}}", "date":"{{post.date | date:"%d/%m/%Y"}}"}{% endfor %}]{% endfor %} }',
    data = JSON.parse(dataStr),
    curTag = $.query.get("cat"),
    archieves = data[curTag];

首先通过上面介绍过的方法构建JSON字符串,这里只是一个模板,读取了所有分类,并以分类名称为key,文章列表为value构建了一个对象。文章列表的元素也是一个对象,有date,url,title三个值,分别表示文章的日期、url路径、标题,帮助生成索引。解析完之后就可以通过url中的category的名称取出来了。这里使用了一个叫jQuery.query的插件,专门取url的参数并进行包装。

综上所述,比如只显示单一分类的页面叫showCategory.html,要显示java分类,那么首页中给个a标签,href为/showCategory.html?cat=java就行了,方便快捷(笑)

类别为中文时问题

Windows下,使用UTF-8编码时当category为中文时,在通过url进入文章时,会出现如下错误

Internal Server Error
"\xAE\xBE" from GBK to UTF-8

我并不知道这个编码为何会需要从GBK转换为UTF-8,所以只能通过其他方式进行避开。网上应该会有人解答这个问题,需要进一步去查了,这里讲一下我怎么避开的吧

首先介绍一下jekyll的Permalinks这个配置,这个配置定义了文章被jekyll处理后生成结果的最终路径,默认为/:categories/:year/:month/:day/:title.html,也就是说,如一篇文章叫“2014-2-6-this-is-a-title.md”,在文章中定义的文类为[测试, new],那么最终这篇文章的路径将会是“_site/测试/new/2014/02/06/this-is-a-title.html”,也就是说如果category为中文名称的话,中文将会出现在url中。然后就会根据中文去jekyll的action中索引,然后导致错误。

避开方法就是去掉根据permlinks中的categories,因为一般情况下根据时间来生成文件夹就已经够了,在_config.yml中新增一行:

permalink: /:year/:month/:day/:title

规则可以自己定,具体参照jekyll的Permlinks配置介绍页面,别出现categories就行了

使用文章标签索引文章

现在很多博客都支持给文章添加标签,表示这篇文章具体是哪几方面的技术。jekyll也是支持标签的,而且不需要额外的插件。使用方法和categories类似

给文章添加标签

文章中的标签配置使用tags来定义,内容为一个数组,放在文章的头中,如本文的标签定义:

---
layout: MyTemplate
title: 使用Jekyll在Github上搭建个人博客(文章分类索引)
tags: [github, jekyll]
---

输出所有标签

一般情况下,标签与文章为很复杂的多对多关系,所以如果生成所有标签及含有该标签的所有文章,html将会非常庞大,所以一般只是生成所有的标签,然后通过点击标签到达该标签的索引页面,页面中仅显示含有该标签的文章。

输出所有标签,可以通过liquid的for标签遍历site.tags来实现:

{% for tag in site.tags %}
    <a href="/show_by_tag.html?tag={{ tag[0] }}"> {{ tag[0] }}</a>
{% endfor %}

tag[0]是标签的名称

输出含有某标签的所有文章数

实现思路和上面categories一样,先生成JSON字符串再通过javascript动态生成html,具体代码:

var dataStr = '{ {% for tag in site.tags %}{% if tag[0] != site.tags.first[0] %},{% endif %}"{{ tag[0] }}":[{% for post in tag[1] %}{% if post != tag[1].first %},{% endif %}{"url":"{{post.url}}", "title":"{{post.title}}", "date":"{{post.date | date:"%d/%m/%Y"}}"}{% endfor %}]{% endfor %} }',
    data = JSON.parse(dataStr),
    curTag = $.query.get("tag"),
    archieves = data[curTag];

这里还是一样,使用jQuery.query插件获取url中的参数,和上面的<a href="/show_by_tag.html?tag={{ tag[0] }}"> {{ tag[0] }}</a>相对应

标签没有字符集问题,放心使用吧

总结

文章的分类其实实现并不难,但是需要绕点小弯子。如果有更好的不需要使用插件的方法希望能告知我,感激不尽