摘要生成中...
AI 摘要
Hunyuan-lite

在捣鼓自己的主题时,有一些时候会在主题配置文件(或 Hexo 配置文件)中插入大量的 HTML 代码。虽然功能是实现了,但是会导致很多问题:

  • 配置文件冗长
  • HTML 内容无代码高亮,不方便格式化
  • 拓展性

为了解决这个问题,我的想法是通过注册勾子实现主题配置的动态加载。

编写脚本并注册勾子

默认地,Hexo 会在 Hexo 命令执行时加载博客项目 scripts 文件夹下的所有脚本。

请不要在 scripts 文件夹下放置执行不了的非脚本文件。

我们在 scripts 文件夹中编写 dynamic_config.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
const fs = require('fs');
const path = require('path');

/**
* 通用函数:读取外部HTML文件并赋值给Hexo配置
* @param {Object} options - 配置项
* @param {string} options.filePath - HTML文件相对路径(相对于Hexo根目录)
* @param {string} options.configPath - 要赋值的主题配置路径(如 "aside.card_announcement.content")
* @param {string} options.failureMsg - 失败日志提示前缀
*/
function loadHtmlToConfig({filePath, configPath, failureMsg}) {
try {
// 拼接完整文件路径
const fullPath = path.join(hexo.base_dir, filePath);

// 验证文件是否存在
if (!fs.existsSync(fullPath)) {
throw new Error(`文件不存在:${fullPath}`);
}

// 读取HTML内容
const htmlContent = fs.readFileSync(fullPath, 'utf8');

// 解析配置路径并赋值(支持多级路径,如 aside.card_announcement.content)
setNestedConfig(hexo.theme.config, configPath, htmlContent);

// 输出成功日志
hexo.log.debug(`✅ 动态配置加载成功 ${configPath}`);
} catch (error) {
// 容错处理:输出警告日志,不中断构建
hexo.log.warn(`⚠️ ${failureMsg}${error.message},使用主题默认内容`);
}
}

/**
* 通用函数:设置嵌套对象的属性值(支持多级路径)
* @param {Object} obj - 目标对象(如 hexo.theme.config)
* @param {string} path - 属性路径(如 "aside.card_announcement.content")
* @param {any} value - 要设置的值
*/
function setNestedConfig(obj, path, value) {
const keys = path.split('.');
const lastKey = keys.pop();

// 逐层查找/创建嵌套对象
const targetObj = keys.reduce((acc, key) => {
if (!acc[key]) acc[key] = {}; // 路径不存在时创建空对象
return acc[key];
}, obj);

// 给最终属性赋值
if (targetObj[lastKey]) { // 仅当原配置存在时赋值(保持原有逻辑)
targetObj[lastKey] = value;
}
}

// 注册Hexo钩子
hexo.extend.filter.register('before_generate', () => {

// 配置列表:新增/修改字段只需修改这个数组,无需改核心逻辑
const dynamicConfigList = [
{
filePath: 'source/_data/dynamic_configs/announcement.html',
configPath: 'aside.card_announcement.content',
failureMsg: '读取侧边栏公告HTML文件失败'
},
{
filePath: 'source/_data/dynamic_configs/footer.html',
configPath: 'footer.custom_text',
failureMsg: '读取页脚自定义文本HTML文件失败'
}
// 新增字段示例:只需添加以下配置项即可
// {
// filePath: 'source/_data/dynamic_configs/nav.html',
// configPath: 'nav.custom_content',
// failureMsg: '读取导航栏自定义内容HTML文件失败'
// }
];

// 遍历配置列表,批量执行加载逻辑
dynamicConfigList.forEach(loadHtmlToConfig);

}, 1);

根据上面代码的提示,自行修改或拓展勾子函数 hexo.extend.filter.register 即可。比如像第一个 aside 的例子。原本我们在 _config.butterfly.yml 的某项配置为:

1
2
3
4
5
6
7
aside:
card_announcement:
enable: true
content: |
很长很长很长的内容
......
有很多很多行

我们可以把这些内容剪切出来放在某一个位置里,比如将内容粘贴到 source/_data/dynamic_configs/announcement.html 文件中即可。 failureMsg 随意写,用于在日志中给出相应的提示。

经测试,这个动态配置甚至可以热更新,HTML 内容修改后会实时反馈到页面中。当然,目前这个脚本还在试用中,如有任何问题,欢迎在评论区进行交流和讨论。

本文参考