一、 引言
众所周知,Hexo 是一个快速、简洁且高效的博客框架。 它使用 Markdown 或 其他标记语言 解析文章,在几秒内,即可利用靓丽的主题生成静态网页。
目前 Hexo 拥有 400+ 的主题,使用者可以在众多的主题中进行选择;当然我们也可以使用任何兼容的模板引擎创建自己的主题,从而应用到个人博客中。
不过比较遗憾的是,这么多的美观、强大、可定制的主题之中,我们只能选择其中一个主题来生成自己的静态博客。
笔者在接触 Hexo 之后,也被它众多的主题所吸引,同时也在考虑如何让个人博客可以在众多的主题间切换呢?【小孩子才会选择,大人全都要】。
二、 Diversity 主题
随着接触越多的 Hexo 的核心 API 和源码,一个在多主题中自由切换的 Hexo 主题 应运而生,取名 Diversity,即多样性。
2.1 Hexo 控制台命令
在介绍 Diversity 主题的运行原理之前,我们先来看看 Hexo 的一些关键控制台命令,比如:
hexo generate
: 生成静态文件(一般在public
目录下)。hexo server
:启动服务器。 默认情况下,访问网址为:http://localhost:4000/
。hexo clean
:清除缓存文件(db.json
) 和已生成的静态文件 (一般在public
目录下)。
2.2 Hexo 核心 API
翻看官方网站的 核心API概述 ,可以看到一个完整的 Hexo 实例运行流程如下:
初始化 :首先,需要新建一个
Hexo
实例。 一个新的实例需要两个参数:网站根目录base_dir
,以及包含初始化选项的对象。 接着执行init
方法后,Hexo 会加载插件及配置文件。1
2
3
4
5
6var Hexo = require("hexo");
var hexo = new Hexo(process.cwd(), {});
hexo.init().then(function () {
// ...
});加载文件 :Hexo 提供了两种方法来加载文件:
load
和watch
。load
用于加载source
文件夹中的所有文件以及主题数据。watch
执行与load
相同的操作,但还会开始连续监视文件更改。执行指令 :任何控制台命令都可以通过在 Hexo 实例上使用
call
方法来显式调用。这样的调用需要两个参数:控制台命令的名称和 一个选项参数。不同的控制台命令有不同的选项可用。1
2
3hexo.call("generate", {}).then(function () {
// ...
});退出 :无论控制台命令完成与否,都应调用
exit
方法。 这样 Hexo 就能优雅地退出,并完成保存数据库等重要工作。1
2
3
4hexo
.call("generate", args)
.then(() => hexo1.exit())
.catch(err => hexo1.exit(err));
2.3 运行原理
通过上述 Hexo 核心 API 的了解,相信大家已经比较清楚 Hexo 实例的运行流程了。
那 Diversity 主题是如何实现多个主题自由切换的呢?
笔者的想法就是在我们运行Hexo的控制台命令时,可以针对Diversity主题中配置的多主题目录列表的每个主题,都创建一个 Hexo 实例并执行当前指令。
如下是 _config.diversity.yml
中的配置:
1 | # 多主题目录列表 |
这个时候读者可能就要问了,那不同的主题是如何区分处理的呢?
2.3.1 多主题配置相关
不同主题的根配置 _config.xml
需要单独配置,在你的 Hexo 项目根目录,添加 config 目录,为上述多主题列表中的每个主题添加一个对应主题名的配置目录,并在该配置目录下添加对应的 _config.yml
【直接从你原来项目根目录下的 _config.yml
复制一份即可】,形如:
1 | ├─config |
修改上述各主题配置目录下的 _config.yml
,以 landscape 举例:
1 | - url: http://example.com |
只要按上述添加好配置,
当运行 generate
指令时,Diversity 主题可以针对不同的主题生成不同的静态页面【例如:landscape
的静态页面就将生成在 public/landscape
】。
当运行 server
指令时,Diversity 主题可以针对不同的主题启动不同的Http服务【例如:landscape
的本地地址 http://localhost:4002/landscape
】。
另外在你的 Hexo 项目根目录下,我们依旧可以添加不同主题独立的 _config.[theme].yml
文件,更多了解请查看官方《配置》
2.3.2 多主题执行指令
在 Diversity 主题的 script
目录新增 index.js
,用于处理多主题执行指令。
主题目录中的
script
目录为脚本文件夹。 在启动时,Hexo 会加载此文件夹内的 JavaScript 文件。 请参见 plugins. 以获得更多信息。
我们来看看核心的处理逻辑:
首先,从Hexo的主题配置中获取多主题目录列表;
1
2const themeConfig = hexo.config.theme_config;
const themes = themeConfig.themes;然后,获取hexo执行的控制台命令;
1
2
3
4
5
6
7
8
9// 获取控制台命令的别名
const { alias } = hexo.extend.console;
// 获取hexo执行命令
const cmd = alias[hexo.env.cmd];
// 当前项目根目录
const cwd = process.cwd();
hexo.log.info('Cmd =', cmd);
themeConfig.cmd = cmd;最后,遍历多主题目录列表
themes
,针对每个主题创建一个 Hexo 实例并执行当前的控制台命令。每个主题都有对应的_config.yml
,可从上面的介绍了解到,位于项目根目录的config
目录中的主题名目录下。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// 多主题目录配置的数组索引
let index = 0;
// 循环处理配置的多主题列表
themes.forEach(function(theme) {
themeConfig.index = index;
if (Util.isMatchCmd(cmd)) {
hexo.log.info('Theme', (index + 1), '=', theme);
const {args} = hexo.env;
const fileName = '_config.yml';
args.output = path_1.join(cwd, 'config', theme);
if (!Util.isExist(args.output, fileName)) {
hexo.log.error('Please add the [' + fileName + '] file in [' + args.output + '].');
return;
}
args.config = path_1.join(args.output, fileName);
const hexo1 = new Hexo(cwd, args);
require('./config')(hexo1, themeConfig);
hexo1.init()
.then(() => require('./helper')(hexo1, themeName))
.then(() => require('./generator')(hexo1, themeName))
.then(() => hexo1.call(cmd, args))
.then(() => hexo1.exit())
.catch(err => hexo1.exit(err));
}
// 下一个主题
index++;
});
2.4 版本演进
2.4.1 V1版本
主题选择页:
鼠标左右拖拽滚动展示:
鼠标滚轮前后滚动展示:
已配置的主题,鼠标悬停自动翻转展示详情:
主题直达按钮,用于跳转对应主题博客页面:
主题来源按钮,用于跳转对应的主题开源项目:
2.4.2 V2版本
2.4.2.1 PC 端
个人博客页【尚未设置过默认主题】:
主题选择页:
设置默认主题【当然V1
版本中的拖动和滚动展示同样支持,这里就不展示了】:
取消默认主题,并重新设置新的默认主题:
已有默认主题,直接重新设置默认主题:
2.4.2.2 Phone 端
个人博客页【尚未设置过默认主题】:
主题选择页:
左右箭头切换滚动展示,左滑右滑切换滚动展示:
设置默认主题:
2.5 后续展望
本篇博文截止,Diversity 主题的版本是 2.2.6。
后续该项目将会持续更新中,包括但不限于首页,友链,留言,关于等等。
三、 总结
Diversity 主题 解决了 Hexo 站点只能在线接入一个主题运行的痛点,使用者可以在配置的主题中自由切换展示。
如果你也有兴趣,不妨来试试接入 Diversity 吧!!!
有任何的问题,欢迎来评论区和我讨论!