hexo#02#Hexo分类名称以及排序

本次对Hexo的修改,主要完成如下两个功能:

  • 第一,Hexo的分类默认使用名称按照字典排序,我希望是自己可以方便指定分类序号,从而按序号排序显示;
  • 第二,Hexo的分类名称需要直接写在Post文档categories的字段,后续如果需要修改某个分类名称,需要修改多个文档,我希望是给每个分类起个别名,Post文档中使用该别名,在特定的文档中定义别名和真实名称的映射关系,然后Hexo生成静态页面时,Hexo自动对别名进行替换。

0x00 实现步骤

  • 第一,在博客项目的根目录创建文件categories.json,文件中定义别名和真实名称的映射关系;
  • 第二,自己创建创建一个模块,该模块中完成categories.json读取、别名到真实名称的转换以及分类排序等三个功能。并将该模块发布到npmjs.org;
  • 第三,修改node_modules\hexo\dist\plugins\helper\list_categories.js中的listCategoriesHelper函数,使用我们上述自定义的分类函数,来生成静态文件。
  • 第四,修改themes\next\layout_macro\sidebar.swig 和 themes\next\layout_macro\post.swig,完成别名到真实名称的转换;

0x01 第一步:创建文件categories.json

在项目根目录创建映射文件:

我们以当前博客网站的分类作为演示,其内容如下:

0x02 第二步:实现自己的函数,并定义为新的模块

我给这个模块起了名字叫做 hexo-mancode,该模块的文件index.js内容如下:

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
fs = require('fs');

global.pages_mancode = {};

// 完成分类映射表的读取
hexo.extend.filter.register('before_generate', function(){
this.log.info("hexo_mancode: before_generate ****");

global.pages_mancode = JSON.parse(fs.readFileSync("./categories.json", "utf8"));
});

// 别名与真实名称的映射
hexo.extend.helper.register('my_list_categories', function(catname){
var item = global.pages_mancode.categories.find(item => { return item.cat == catname; } );

return (item == undefined)?"没有分类":item.name;
});

// 分类按指定的需要进行排序
hexo.extend.helper.register('my_list_sortfunc', function() {
return (av, bv) => {
var as = global.pages_mancode.categories.find(item => { return item.cat == av.name; } );
var bs = global.pages_mancode.categories.find(item => { return item.cat == bv.name; } );

if (as == undefined && bs == undefined)
{
return av.name < bv.name ?-1:(av.name > bv.name ?1:0);
}
else if (as != undefined && bs != undefined)
{
return as.order < bs.order?-1:(as.order > bs.order?1:0);
}
else if (as == undefined)
{
return 1;
}
else if (bs == undefined)
{
return -1;
}
}
});

文件创建完毕之后,将该模块发布到npmjs.org,发布模块的具体方法请参考当前博客的其他文章。

修改package.json文件,增加对hexo-mancode的依赖和自动下载。

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
{
"name": "hexo-site",
"version": "0.0.0",
"private": true,
"scripts": {
"build": "hexo generate",
"clean": "hexo clean",
"deploy": "hexo deploy",
"server": "hexo server"
},
"hexo": {
"version": "7.3.0"
},
"dependencies": {
"hexo": "^7.3.0",
"hexo-generator-archive": "^2.0.0",
"hexo-generator-category": "^2.0.0",
"hexo-generator-index": "^4.0.0",
"hexo-generator-tag": "^2.0.0",
"hexo-renderer-ejs": "^2.0.0",
"hexo-renderer-marked": "^6.3.0",
"hexo-renderer-stylus": "^3.0.1",
"hexo-server": "^3.0.0",
"hexo-theme-landscape": "^1.0.0",
"hexo-mancode": "^1.0.0"
}
}

0x03 第三步:修改模块hexo的list_categories.js函数

node_modules\hexo\dist\plugins\helper\list_categories.js文件的位置,如下图所示:

修改后的文件内容(修改前的list_categories.js修改后的list_categories.js):

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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
"use strict";
const hexo_util_1 = require("hexo-util");
function listCategoriesHelper(categories, options) {
if (!options && (!categories || !Object.prototype.hasOwnProperty.call(categories, 'length'))) {
options = categories;
categories = this.site.categories;
}
categories = categories;
if (!categories || !categories.length)
return '';
options = options || {};
const { style = 'list', transform, separator = ', ', suffix = '', mysort } = options;
const showCount = Object.prototype.hasOwnProperty.call(options, 'show_count') ? options.show_count : true;
const className = options.class || 'category';
const depth = options.depth ? parseInt(String(options.depth), 10) : 0;
const orderby = options.orderby || 'name';
const order = options.order || 1;
const showCurrent = options.show_current || false;
const childrenIndicator = Object.prototype.hasOwnProperty.call(options, 'children_indicator') ? options.children_indicator : false;
const prepareQuery = parent => {
const query = {};
if (parent) {
query.parent = parent;
}
else {
query.parent = { $exists: false };
}
return categories.find(query).sort(orderby, order);
};

// 增加的函数
const myhtml = () => {
let mhtml = "";
var sortBy = mysort?mysort():(a, b)=>{ return (a.name < b.name)?-1:(a.name>b.name?1:0); };
categories.data.sort(sortBy).forEach((cat) => {
mhtml += `<li class="${className}-list-item">`;
mhtml += `<a class="${className}-list-link" href="${hexo_util_1.url_for.call(this, cat.path)}${suffix}">`;
mhtml += transform ? transform(cat.name) : cat.name;
mhtml += '</a>';

mhtml += `<span class="${className}-list-count">${cat.length}</span>`;

mhtml += '</li>';
});

return mhtml;
}

const hierarchicalList = (level, parent) => {
let result = '';

prepareQuery(parent).forEach((cat) => {

let child;
if (!depth || level + 1 < depth) {
child = hierarchicalList(level + 1, cat._id);
}
let isCurrent = false;
if (showCurrent && this.page) {
for (let j = 0; j < cat.length; j++) {
const post = cat.posts.data[j];
if (post && post._id === this.page._id) {
isCurrent = true;
break;
}
}
// special case: category page
isCurrent = isCurrent || (this.page.base && this.page.base.startsWith(cat.path));
}
const additionalClassName = child && childrenIndicator ? ` ${childrenIndicator}` : '';
result += `<li class="${className}-list-item${additionalClassName}">`;
result += `<a class="${className}-list-link${isCurrent ? ' current' : ''}" href="${hexo_util_1.url_for.call(this, cat.path)}${suffix}">`;
result += transform ? transform(cat.name) : cat.name;
result += '</a>';
if (showCount) {
result += `<span class="${className}-list-count">${cat.length}</span>`;
}
if (child) {
result += `<ul class="${className}-list-child">${child}</ul>`;
}
result += '</li>';
});
return result;
};

const flatList = (level, parent) => {
let result = '';
prepareQuery(parent).forEach((cat, i) => {
if (i || level)
result += separator;
result += `<a class="${className}-link" href="${hexo_util_1.url_for.call(this, cat.path)}${suffix}">`;
result += transform ? transform(cat.name) : cat.name;
if (showCount) {
result += `<span class="${className}-count">${cat.length}</span>`;
}
result += '</a>';
if (!depth || level + 1 < depth) {
result += flatList(level + 1, cat._id);
}
});
return result;
};
if (style === 'list') {
//return `<ul class="${className}-list">${hierarchicalList(0)}</ul>`;

return `<ul class="${className}-list">${myhtml()}</ul>`;
}
return flatList(0);
}
module.exports = listCategoriesHelper;

0x04 第四步:修改布局文件 sidebar.swig 和 post.swig 完成名称映射

themes\next\layout_macro\sidebar.swig文件修改如下:

themes\next\layout_macro\post.swig文件修改如下:

0x05 第五步:使用方法

第一:如果重新安装模块,也就是重建node_modules文件夹,需要在执行 npm install 之后,手动修改 list_categories.js 文件。

第二:如果新增加分类或者调整分类的排序,需要调整categories.json中内容。

第三:post文档指定分类别名的方法,如下图所示:

0x06 参考资料