hexo-next-主题构建首页动态更新目录

1 问题及需求

问题

  • 首页(home)默认显示按日期排序的文章列表,使用 <!-- more --> 省略内容仍显得繁杂冗长;
  • 分类(categories)页面虽然有按类型、日期排序的文章列表,但切换分类需要往返多次。

需求

  • 建立一个首页目录,将文章分类(categories 参数)和标题,分别作为列表的一级、二级显示;
  • 标题即为文章链接,点击可直接到达;想查看其他分类,直接回到首页即可。

2 解决方案

2.1 建立文件

source/ 下建立 index.md,命名标题,内容留空。

2.2 关闭默认首页

修改 hexo 配置文件 _config.yml,找到 index_generator 配置项,修改 path 属性为一个无效值:

1
2
3
4
index_generator:
path: 'xxxx'
per_page: 10
order_by: -date

此时启动项目后,首页将不再出现文章列表,转而显示 index.md 内容。

注:index.md 在渲染后成为 index.html

3 动态更新目录

若文章分类多,每次更新、调整文章都需要将相应链接手工同步到首页也是一件相当繁琐的事情。因此有必要考虑自动更新首页。

3.1 hexo 加载顺序

根据 hexo 文档 https://hexo.io/zh-cn/api/posts#%E6%B8%B2%E6%9F%93 关于渲染顺序的说明,要实现 index.md 的写入,要在 hexo g 命令执行之前完成,可引入 before_post_render 过滤器实现该需求。

3.2 hexo 过滤器

过滤器文档:https://hexo.io/zh-cn/api/filter#%E6%A6%82%E8%A6%81

在主题目录下 themes\next\filters\ 新建 index.js,添加 priority 分别为 9 和 10 的两个 before_post_render 过滤器,如下所示:

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
'use strict'

const categoriesMap = new Map();

hexo.extend.filter.register('before_post_render', data => {

// 首页目录不显示草稿内容
if (data.source.indexOf("_drafts") >= 0) {
return data;
}

if (data.path.indexOf("index") < 0 && data.categories.length > 0) {

let curCategorie = data.categories.data[0].name;

if (categoriesMap.has(curCategorie)) {
let valueArray = categoriesMap.get(curCategorie);
valueArray = valueArray.concat(` - [${data.title}](/${data.path})\n`)
categoriesMap.set(curCategorie, valueArray);
} else {
categoriesMap.set(curCategorie, [` - [${data.title}](/${data.path})\n`]);
}
}
return data;
}, 9);

hexo.extend.filter.register('before_post_render', data => {
// 精确定位index.html,防止误写其他路径不同但同名的文件
if (data.path.indexOf("index") === 0) {

for (let key of categoriesMap.keys()) {
data.content += `- ${key}\n`
let valueArray = categoriesMap.get(key);
valueArray.forEach(element => {
data.content += element;
});
}
return data;
}
return data;
}, 10);

代码说明

  • 第一个过滤器遍历全部文章,获取所有现存的分类及所属文章链接;
  • 第二个过滤器写入 index.html

3.3 有关属性

为探究 data 为何物,可打断点观察其结构:

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
{
title: "DataGrip-2018.3.4-数据导出配置案例",
date: {……文章生成日期的有关参数(略)},
_content: "……正文内容(略)",
source: "_posts/DataGrip-2018-3-4-数据导出配置案例.md",
raw: "……正文内容(略)",
slug: "DataGrip-2018-3-4-数据导出配置案例",
published: true,
updated: {……文章更新日期的有关参数(略)},
comments: true,
layout: "post",
photos: [
],
link: "",
_id: "cljzhnjmb001oz0u6en5ab6xb",
path: "2022/12/07/DataGrip-2018-3-4-数据导出配置案例/",
permalink: "http://www.dcheng.site/2022/12/07/DataGrip-2018-3-4-%E6%95%B0%E6%8D%AE%E5%AF%BC%E5%87%BA%E9%85%8D%E7%BD%AE%E6%A1%88%E4%BE%8B/",
full_source: "C:\\mainProjects\\blog\\source\\_posts\\DataGrip-2018-3-4-数据导出配置案例.md",
asset_dir: "C:\\mainProjects\\blog\\source\\_posts\\DataGrip-2018-3-4-数据导出配置案例\\",
tags: {
data: [
{
name: "DataGrip",
_id: "cljzhnjmc001uz0u6hlov172o",
slug: "DataGrip",
path: "tags/DataGrip/",
permalink: "http://www.dcheng.site/tags/DataGrip/",
posts: {
data: [
],
length: 0,
},
length: 0,
},
],
length: 1,
},
categories: {
data: [
{
name: "配置案例",
_id: "cljzhnjmc001tz0u6967u3bji",
slug: "配置案例",
path: "categories/配置案例/",
permalink: "http://www.dcheng.site/categories/%E9%85%8D%E7%BD%AE%E6%A1%88%E4%BE%8B/",
posts: {
data: [
],
length: 0,
},
length: 0,
},
],
length: 1,
},
content: "……正文内容(略)",
site: {
data: {
},
},
}

4 最终效果

图1-默认效果

图1-默认效果

图2-动态目录效果

图2-动态目录效果