【Hexo】Hexo插件开发步骤

Hexo的插件嵌入有两种方式,一种是通过脚本(Scripts)的方式引入,一种是通过插件(Packages)的方式将自定义的插件内容发布到npm上。本文主要介绍第二种,如果您的代码很简单,建议您编写脚本,您只需要把 JavaScript 文件放到主题目录的 scripts 文件夹,在启动时就会自动加载。具体操作可参考 Hexo 博客每天自动生成每日早报文章 中2.2相关介绍。

下面是引用官方的一段话,开发Hexo插件至少要包含 2 个文件:一个是主程序index.js,另一个是 package.json,描述插件的用途和所依赖的插件。package.json 中至少要包含 name, version, main 属性。

链接直达https://hexo.io/zh-cn/docs/plugins

如果您的代码较复杂,或是您想要发布到 NPM 上,建议您编写插件。首先,在 node_modules 文件夹中建立文件夹,文件夹名称开头必须为 hexo-,如此一来 Hexo 才会在启动时加载;否则 Hexo 将会忽略它。

文件夹内至少要包含 2 个文件:一个是主程序,另一个是 package.json,描述插件的用途和所依赖的插件。

1
2
3
.
├── index.js
└── package.json

package.json 中至少要包含 name, version, main 属性,例如:

1
2
3
4
5
package.json{
"name": "hexo-my-plugin",
"version": "0.0.1",
"main": "index"
}

一、创建插件项目

创建一个新的目录来存放你的插件项目,文件夹名称开头必须为 hexo-,例如 hexo-footer-plugin

可在任意目录创建,为方便测试也可直接在Hexo项目的node_modules目录下创建

1
mkdir hexo-footer-plugin

进入该目录

1
cd hexo-footer-plugin

初始化一个新的 npm 项目

1
npm init

使用npm init初始化有操作向导,会引导你一步步输入package.json文件的不同参数。

也可使用npm init -y 初始化一个仅包含默认参数的package.json文件

1
2
3
4
5
6
7
8
9
10
11
12
{
"name": "hexo-footer-plugin",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}

然后自行修改,例如

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
{
"name": "hexo-footer-plugin",
"version": "1.0.0",
"description": "A Hexo plugin to add a custom footer with copyright information to posts.",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"hexo",
"plugin",
"footer",
"copyright"
],
"author": {
"name": "Shiguang-coding",
"email": "an_shiguang@163.com",
"url": "https://blog.shiguangdev.cn"
},
"license": "MIT",
"dependencies": {
"hexo": "^5.0.0"
},
"repository": {
"type": "git",
"url": "https://github.com/Shiguang-coding/hexo-footer-plugin.git"
},
"bugs": {
"url": "https://github.com/Shiguang-coding/hexo-footer-plugin/issues"
},
"homepage": "https://github.com/Shiguang-coding/hexo-footer-plugin#readme"
}

在发布npm包时,仓库信息(repository)是一个可选字段,但建议填写。仓库信息可以帮助其他开发者更容易地找到和贡献代码。如果你不想填写仓库信息,可以省略这个字段。

二、编写插件代码

2.1、介绍

可参考官方文档进行开发

Hexo API

Hexo插件文档中文版

Hexo插件文档英文版

工具

您可以使用 Hexo 提供的官方工具插件来加速开发:

除了辅助函数(Helper),Hexo的插件还可划分为不同类型:控制台 (Console)部署器 (Deployer)过滤器 (Filter)生成器 (Generator)迁移器 (Migrator)处理器 (Processor)渲染引擎 (Renderer)标签 (Tag)

Hexo初始化的时候会相应加载插件列表,代码详见 node_modules\hexo\lib\hexo\index.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// Load internal plugins
require('../plugins/console')(this);
require('../plugins/filter')(this);
require('../plugins/generator')(this);
require('../plugins/helper')(this);
require('../plugins/injector')(this);
require('../plugins/processor')(this);
require('../plugins/renderer')(this);
require('../plugins/tag')(this);

// Load config
return Promise.each([
'update_package', // Update package.json
'load_config', // Load config
'load_theme_config', // Load alternate theme config
'load_plugins' // Load external plugins & scripts
], name => require(`./${name}`)(this)).then(() => this.execFilter('after_init', null, { context: this })).then(() => {
// Ready to go!
this.emit('ready');
});
}

插件加载依托于load_plugins.js,其主要函数有loadModulesloadScripts

loadModules : 调用loadModuleList读取package.json,从而进一步加载插件列表(自带&第三方插件)
loadScripts : 加载脚本类插件(自带&主题scripts下的脚本)

1
2
3
4
module.exports = ctx => {
if (!ctx.env.init || ctx.env.safe) return;
return loadModules(ctx).then(() => loadScripts(ctx));
};

部分插件如果存在编译错误则Hexo会无法正常启动且输出错误日志,根据日志检查错误相应调整即可。

2.2、开发示例

在你的插件目录中创建一个 index.js 文件,并编写你的插件代码。例如:

想要了解更多过滤器及执行顺序可参考 过滤器列表事件

1
2
3
hexo.extend.filter.register('after_post_render', function(data){
// 你的插件逻辑
});

假设我们需要做一个给文章添加版权声明的插件,hexo-footer-plugin,创建 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
hexo.extend.filter.register('after_post_render', function(data){
// 添加调试信息,打印当前时间戳和消息
console.log("Debug: hexo-footer-plugin is running at", new Date().toISOString());

const { config } = hexo;

const isEnabled = config['hexo-footer-plugin']?.enable;

if(!isEnabled){
console.warn("hexo-footer-plugin 插件尚未启用!!");
return;
}
const copyrightOwner = config['hexo-footer-plugin']?.copyright_owner;

if (!copyrightOwner) {
console.warn("Warning: copyright_owner is not set in the configuration.");
return data;
}

console.log("copyrightOwner:", copyrightOwner);

// 构建版权声明字符串
var footer = "\n<div id='custom-footer'>© " + new Date().getFullYear() + " " + copyrightOwner + "</div>";

// 将版权声明添加到文章内容的末尾
data.content += footer;

// 再次添加调试信息,确认版权声明已被添加
console.log("Debug: footer added to post content");

// 返回修改后的内容
return data;
});

这段代码 通过hexo.config 获取配置文件中的特定参数,配置项位于 hexo-footer-plugin 下的copyright_owner,用于配置版权所有人,以下是如何获取这个配置参数的示例:

1
2
3
4
5
6
const { config } = hexo;

// 获取 hexo-footer-plugin 下的 copyright_owner 配置
const copyrightOwner = config['hexo-footer-plugin']?.copyright_owner;

console.log(copyrightOwner);

在这段代码中,我们首先从 hexo 实例中获取配置对象 config。然后,我们通过点符号访问嵌套的配置项。注意,我们使用了可选链 ?. 来避免在配置项不存在时抛出错误。

如果 hexo-footer-plugincopyright_owner 在配置文件中不存在,copyrightOwner 将保持未定义状态,而不会引发错误。

2.3、本地测试

2.3.1、初始化Hexo项目

我们重新初始化一个Hexo项目

1
2
hexo init blog
cd blog

初始化好后可以先执行三连命令运行看下效果

1
hexo clean && hexo g && hexo s

image-20240622113429888

2.3.2、安装插件依赖

1、通过 npm install 安装

在你的 Hexo 项目目录中,使用以下命令将本地插件链接到你的 Hexo 项目:

1
npm install /path/to/your/hexo-footer-plugin

例如我Hexo项目目录为 D:\hexo\test\blog,插件存放目录为 D:\hexo\plugins\hexo-footer-plugin

执行安装命令,由于npm安装较慢,我使用的cnpm进行安装

1
cnpm install ../../plugins/hexo-footer-plugin

image-20240622102520309

可以看到控制台提示成功添加一个依赖,插件名称 hexo-footer-plugin 版本号 ^1.0.0

image-20240622102831825

我们到Hexo项目node_modules检查一下

image-20240622103404276

再检查下Hexo项目根目录下package.json引入的依赖 dependencies

image-20240622103454733

或者通过命令 npm ls 查看引入的依赖

image-20240622103609849

或者,你也可以使用 npm link 命令来创建一个全局链接,然后在 Hexo 项目中使用这个链接:

以管理员权限执行命令,否则会出现 npm ERR! errno -4048 错误

1
2
3
4
cd /path/to/your/hexo-footer-plugin
npm link
cd /path/to/your/hexo-project
npm link hexo-footer-plugin

更多关于 npm link命令的内容详见 npm link 基本使用

执行npm ls 查看link是否创建成功

image-20240622111938844

检查Hexo项目根目录 package.json文件,如果没有 dependencies 部分,可以手动创建一个。然后,添加你链接的包的名称和版本。例如,如果你链接的包名为 my-package,你可以这样添加:

1
2
3
4
5
{
"dependencies": {
"my-package": "file:../path/to/my-package"
}
}

例如此处我需要修改为

1
2
3
4
5
{
"dependencies": {
"hexo-footer-plugin": "file:./../../plugins/hexo-footer-plugin"
}
}
3、手动引入依赖

直接复制插件目录 hexo-footer-plugin 到Hexo项目 node_modules文件夹内

修改Hexo项目根目录 package.json文件,在dependencies 部分添加插件依赖

1
2
3
4
5
{
"dependencies": {
"hexo-footer-plugin": "^1.0.0"
}
}

2.3.3、修改配置文件

在Hexo主配置文件 _config.yml 中添加插件的配置,注意不是主题的_config.yml

1
2
3
hexo-footer-plugin:
enable: true
copyright_owner: Your Name

也有说需要添加下面这条配置的,我不添加也是可以的

1
2
plugins:
- hexo-footer-plugin

这段代码是 Hexo 配置文件_config.yml 中的一部分,用于指定 Hexo 博客项目所使用的插件。具体来说,这段代码的含义和作用如下:

  1. 含义
    • plugins:这是一个配置项,用于列出当前 Hexo 项目所使用的所有插件。
    • - hexo-footer-plugin:这是插件列表中的一个条目,表示当前项目使用了名为 hexo-footer-plugin 的插件。
  2. 作用
    • 插件管理:通过在 _config.yml 文件中列出插件,Hexo 在启动时会自动加载这些插件,并执行插件中定义的各种功能。
    • 功能扩展hexo-footer-plugin 是一个自定义插件,通过在 _config.yml 中声明它,Hexo 会在生成博客内容时调用该插件,从而实现特定的功能扩展。例如,在你的例子中,hexo-footer-plugin 可能用于在每篇文章的末尾添加版权声明。

总结来说,这段代码的作用是告诉 Hexo 在生成博客内容时要加载并使用 hexo-footer-plugin 插件,以便实现该插件所提供的功能。

2.3.4、重新运行并测试插件

1
hexo clean && hexo g && hexo s

注意: 此处每次运行一定要执行 hexo clean 插件才会执行生效

能看到文章底部出现版权声明就说明插件运行成功了

image-20240622114630268

控制台也会有相应日志输出

image-20240622114806936

三、发布到 NPM

确保你的插件目录中包含 index.js 文件,这是插件的入口文件。

添加 README.md 文件,提供插件的详细说明、安装方法和使用示例。

添加 LICENSE 文件,声明你的插件使用的开源许可证。

如果你还没有 npm 账号,需要先注册一个:

1
npm adduser

如果你已经有账号,直接登录:

1
npm login

提示回车打开浏览器访问页面,无论注册或登录都需要获取一次性密码(One-time Password),即邮箱验证码

发布你的插件:

1
npm publish

控制台提示如下信息即代表发布成功

image-20240622124723244

发布成功后可直接在NPM官网查询

image-20240622124934704

如果要更新插件的话,改下版本号重新发布即可。

四、安装并使用插件

4.1、安装插件

安装前先将Hexo根目录下node_modules目录以及package.json刚才引入的依赖移除重新执行项目确保原配置已失效,或者重新初始化个Hexo项目。

在你的 Hexo 项目目录中,使用以下命令安装你的插件:

1
npm install hexo-footer-plugin --save

或者

1
cnpm install hexo-footer-plugin --save

如下

image-20240622125310889

4.2、修改配置文件

在你的 Hexo 项目配置文件 _config.yml 中添加插件的配置:

1
2
3
hexo-footer-plugin:
enable: true
copyright_owner: Your Name

4.3、重新运行并测试插件

1
hexo clean && hexo g && hexo s

注意: 此处每次运行一定要执行 hexo clean 插件才会执行生效

五、文档和宣传

在 GitHub 上创建一个仓库,并将你的插件代码推送到这个仓库。

在 README 文件中提供详细的安装和使用说明。

在 Hexo 社区或其他相关论坛宣传你的插件。

六、提交插件到 Hexo 插件列表

打开 Hexo 官方插件列表的 GitHub 仓库:hexojs/site

点击右上角的 “Fork” 按钮,将仓库 fork 到你自己的 GitHub 账户。

克隆你 fork 的仓库到本地:

1
git clone https://github.com/YOUR_GITHUB_USERNAME/site.git

进入 source/_data/plugins 目录并创建your-plugin-name.yml文件,添加你的插件信息。例如:

1
2
3
4
5
6
description: A Hexo plugin to add a custom footer with copyright information to posts.
link: https://github.com/Shiguang-coding/hexo-footer-plugin
tags:
- plugin
- footer
- copyright

提交并推送你的更改:

1
2
3
git add source/_data/plugins/your-plugin-name.yml
git commit -m "Add my Hexo plugin"
git push origin master

你的 GitHub 仓库页面中,点击 “New pull request” 按钮,提交你的更改给 Hexo 官方插件列表。

提交 pull request 后,Hexo 团队会审核你的插件。一旦审核通过,你的插件就会被添加到 Hexo 官方插件列表中。

参考

Hexo API

Hexo 贡献

Hexo Plugins

hexo-butterfly-npm标签插件开发

Hexo + Typora + 开发Hexo插件 解决图片路径不一致