[TOC]

博客搭建有一段时间了,但是链接地址却和文件名紧紧绑定在一起,及其不方便扩展,也给写作带来些许不便。

于是乎,今天便想着来搞搞;为了生成永久链接,这里使用abbrlink这个插件。

安装

//局部安装
npm install hexo-abbrlink --save

嗯哼~ 安装失败….再来

cnpm install hexo-abbrlink --save

ok了,这里配置了镜像,还是cnpm好用;

配置

继续,开始配置外部的 _config.yml

permalink: article/:abbrlink/  # 此处可以自己设置,也可以直接使用 :/abbrlink
abbrlink:
alg: crc32 #算法: crc16(default) and crc32
rep: hex #进制: dec(default) and hex
drafts: false #(true)Process draft,(false)Do not process draft. false(default)
# Generate categories from directory-tree
# depth: the max_depth of directory-tree you want to generate, should > 0
auto_category:
enable: false #true(default)
depth: #3(default)
over_write: false
auto_title: false #enable auto title, it can auto fill the title by path
auto_date: false #enable auto date, it can auto fill the date by time today
force: false #enable force mode,in this mode, the plugin will ignore the cache, and calc the abbrlink for every post even it already had abbrlink.

大家应该都看得懂了~

不过这里有个注意事项,auto_category 默认是true,这里我设置成false;下面是auto_category的源码:

var opt_AutoCategoryEnable = config.auto_category && config.auto_category.enable;
var overwrite = config.auto_category && config.auto_category.over_write;
if (opt_AutoCategoryEnable && overwrite) {
var categories = data.source.split('/');
var opt_AutoCategoryDepth = config.auto_category.depth || 3;
var depth = opt_AutoCategoryDepth || categories.length - 2;
if (categories.length - 2 == 0 || depth == 0) {
tmpPost.categories = this.config.default_category;
} else {
var newCategories = categories.slice(1, 1 + Math.min(depth, categories.length - 2));
//prevents duplicate file changes
if (
!Array.isArray(tmpPost.categories) ||
!tmpPost.categories.join('_') == newCategories.join('_')
) {
tmpPost.categories = newCategories;
}
}
}

我们来查看一下hexo-abbrlink的版本

npm view hexo-abbrlink versions --json
[
"1.0.0",
"1.0.1",
"1.0.2",
"1.0.3",
"2.0.1",
"2.0.2",
"2.0.4",
"2.0.5",
"2.1.5",
"2.1.6",
"2.2.0",
"2.2.1"
]

默认安装的是最新版是2.2.1;

abbrlink 的原理是在每篇文章的属性里加上一个16位/32位的十六进制的数,来作为文章唯一的id。具体内部实现依靠hexo-fs插件来进行写入生成;

执行

在配置好以上内容之后,就可以开始执行生成索引了,这是最后一步了。

hexo generate

可执行了以上命令之后,情况又不妙了~

FATAL Something's wrong. Maybe you can find the solution here: https://hexo.io/docs/troubleshooting.html
Error: EEXIST: file already exists, mkdir 'F:\software2\MyGithubPage\hexo\source\_posts\Android'
at Object.mkdirSync (fs.js:729:3)
at Object.writeFileSync (F:\software2\MyGithubPage\hexo\node_modules\_hexo-fs@3.1.0@hexo-fs\lib\fs.js:63:6)
at Hexo.logic (F:\software2\MyGithubPage\hexo\node_modules\_hexo-abbrlink@2.2.1@hexo-abbrlink\lib\logic.js:98:20)
at Hexo.tryCatcher (F:\software2\MyGithubPage\hexo\node_modules\bluebird\js\release\util.js:16:23)
at Hexo.<anonymous> (F:\software2\MyGithubPage\hexo\node_modules\bluebird\js\release\method.js:15:34)
at Promise.each.filter (F:\software2\MyGithubPage\hexo\node_modules\hexo\lib\extend\filter.js:62:52)
at tryCatcher (F:\software2\MyGithubPage\hexo\node_modules\bluebird\js\release\util.js:16:23)
at Object.gotValue (F:\software2\MyGithubPage\hexo\node_modules\bluebird\js\release\reduce.js:166:18)
at Object.gotAccum (F:\software2\MyGithubPage\hexo\node_modules\bluebird\js\release\reduce.js:155:25)
at Object.tryCatcher (F:\software2\MyGithubPage\hexo\node_modules\bluebird\js\release\util.js:16:23)
at Promise._settlePromiseFromHandler (F:\software2\MyGithubPage\hexo\node_modules\bluebird\js\release\promise.js:547:31)
at Promise._settlePromise (F:\software2\MyGithubPage\hexo\node_modules\bluebird\js\release\promise.js:604:18)
at Promise._settlePromise0 (F:\software2\MyGithubPage\hexo\node_modules\bluebird\js\release\promise.js:649:10)
at Promise._settlePromises (F:\software2\MyGithubPage\hexo\node_modules\bluebird\js\release\promise.js:729:18)
at _drainQueueStep (F:\software2\MyGithubPage\hexo\node_modules\bluebird\js\release\async.js:93:12)
at _drainQueue (F:\software2\MyGithubPage\hexo\node_modules\bluebird\js\release\async.js:86:9)
at Async._drainQueues (F:\software2\MyGithubPage\hexo\node_modules\bluebird\js\release\async.js:102:5)
at Immediate.Async.drainQueues [as _onImmediate] (F:\software2\MyGithubPage\hexo\node_modules\bluebird\js\release\async.js:15:14)
at runCallback (timers.js:693:18)
at tryOnImmediate (timers.js:664:5)
at processImmediate (timers.js:646:5)

报了一堆堆栈日志,通过观察,我们可以看到程序是在执行了 logic.js 之后,接着执行 fs.js 报错的;文件已存在,程序还在强行创建!!!!

为了一探究竟,我们进入到logic.js 中看看

fs.writeFileSync(data.full_source, postStr, 'utf-8');

程序是执行了这段代码导致的,如果abbrlink不存在的话,该插件会遍历文件夹中的文件进行写入,然后创建新的文件夹;继续追,查看下package.json

"dependencies": {
"hexo-front-matter": "^1.0.0",
"hexo-fs": "^3.1.0"
},

依赖的最新的fs是3.1。进入hexo-js中,

function writeFileSync(path, data, options) {
if (!path) throw new TypeError('path is required!');

fs.mkdirSync(dirname(path), { recursive: true });
fs.writeFileSync(path, data, options);
}

好家伙,直接就创建了,都不检查下的吗??

手动修改hexo-fs

路径:\node_modules\_hexo-fs@3.1.0@hexo-fs\lib\fs.js 文件

在文件中添加以下函数:

function checkParentSync(path) {
if (!path) throw new TypeError('path is required!');

var parent = dirname(path);
var exist = fs.existsSync(parent);

if (exist) return;

try {
mkdirsSync(parent);
} catch (err) {
if (err.code !== 'EEXIST') throw err;
}
}

将fs.mkdirSync 注释掉,增加 checkParentSync(path); 的调用。

//fs.mkdirSync(dirname(path), { recursive: true });
checkParentSync(path);

最后,大功告成~:happy: