使用Obsidian写Hexo博客

搭建好Hexo博客后,接下来经常要做的就是写博客,使用 hexo new post title 可以自动创建文件,而且也支持模板,但是你仍然需要使用一种 markdown 编辑器打开这个文件进行编辑,如果你需要在文章中插入图片,你可能要单独把图片放到资源目录中,然后在博客中引用图片,仅仅这一点不方便就能把我劝退。Hexo很方便进行扩展,同时我经常使用的markdown编辑器Obsidian也支持扩展,两者一结合就能很方便的写博客。

除了博客内容的图片这一个问题外,还有就是默认创建的博客文件都在 _posts 目录下面,如果写的内容很多,这种一个目录的管理方式就会很乱,将文章按类别放到不同目录中会更方便易用。配合几个插件就能实现这些。

需要这么多插件会不会很麻烦?除了Obsidian因为网络原因不方便访问外,Hexo直接通过npm i xxxx --save 就能安装。接下来说一下整个配置过程。

1. Obsidian 打开 _posts 目录

使用 Obsidian 管理博客的时候,我们不需要从博客的根目录打开,只需要打开 _posts 目录即可,后续的所有操作都是在该目录进行的,和 Obsidian 有关的配置和插件都会安装到该目录下面的 .obsidian 中,Hexo 默认忽略 . 开头的隐藏文件,不会对 Hexo 产生影响,这个配置目录是可以直接提交到 git 上面的,在任何位置从 git clone 后,用 Obsidian 打开后都不需要重新配置,使用起来很方便。

Obsidian 想方便的使用,这一步很关键,记得打开 _posts 目录,范围小了,事就少。

2. 博客内插入图片

2.1 配置 Hexo 插件

先解决插入图片的问题,首先配置 Hexo 的配置文件 _config.yml ,启用下面的配置:

1
post_asset_folder: true

官方文档对这个属性有 详细介绍 ,使用 hexo new post title 时会自动创建和文章同名的目录,可以将图片放到这个目录中,在博客中使用相对目录的资源地址即可。

如果文章改名了,目录可不会自动改名,但是可以通过 Obsidian 来方便的改名和自动处理图片。

Hexo 中插入图片都推荐用的 tag 方式,例如: {% asset_path slug %},这种方式在 markdown 中不通用,我们肯定要用 markdown 格式的图片: ![](image.jpg),官方虽然有一定的支持,但是不好用,针对这个问题,我们使用 hexo-image-link 插件,通过 npm install hexo-image-link --save 安装插件即可,不需要额外配置。

2.2 配置 Obsidian 插件

接下来在 Obsidian 中配置 Custom Attachment location 插件,有两种安装方式:

1 插件市场

在插件市场搜索 Custom Attachment location,安装并激活即可

2 手动安装

latest release 下载 main.jsmanifest.json,放到  _posts/.obsidian/plugins/obsidian-custom-attachment-location/. 目录中,在 Obsidian 中启用插件。

按照下图配置该插件。

图中第一个 Location 是上传附件(粘贴图片到文章)时,自动创建一个目录,目录的名字设置为 ../${filename} 和当前文章同名,第二个图片格式可以随意,日期也随意。第四个 自动重命名附件文件夹 要开启,当我们从 Obsidian 修改文件名的时候,附件的目录可以自动同步修改,这就解决了 Hexo 中还需要手动改名的问题 (文章内的相对目录名也需要改)。

做到这一步,写博客时就可以随意的往文章内粘贴图片了,截图、网页复制的图片,本地的图片,随便往里面粘贴,都会自动将图片放到指定的目录中,这种顺畅的操作才令人舒心。

3. 目录和类别管理

我们不仅需要流畅的书写,还要方便的管理,通过插件 hexo-auto-category 可以支持创建多级目录存放博客文章,并且根据多级目录创建分层的类别信息,多级类别效果如下:

对应生成的类别结构

在 hexo-auto-category 插件中,作者只针对 post 类型的内容进行处理,不支持其他格式,而且没法配置支持其他类型,所以我使用的时候直接把代码复制修改了,如果你只需要处理 post 类型,通过命令 npm install hexo-auto-category --save 安装即可,如果你也想修改,可以参考下面代码修改:

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
'use strict';
var front = require('hexo-front-matter');
var fs = require('hexo-fs');
hexo.extend.filter.register('before_post_render', function(data) {
var log = this.log;
log.i("Auto Category, Title: %s, Layout: %s", data.title, data.layout);
//这里在原来基础上增加了page和gallery类型
if (['post','page','gallery'].indexOf(data.layout) === -1)
return data;
if (!this.config.render_drafts && data.source.startsWith("_drafts/"))
return data;
if (this.config.auto_category.enable) {
let postStr;
var tmpPost = front.parse(data.raw);
var categories = data.source.split('/');
var depth = this.config.auto_category.depth || categories.length-2;
if (depth==0) {
return data;
}
var newCategories = categories.slice(1, 1 + Math.min(depth, categories.length - 2));
if (tmpPost.categories) {
let postCategories = tmpPost.categories;
if (typeof(tmpPost.categories) === "object"){
postCategories = tmpPost.categories.join("_");
}
if (postCategories == newCategories.join("_")) return data;
}
tmpPost.categories = newCategories
if(this.config.auto_category.multiple)
tmpPost.categories = tmpPost.categories.map(category => [category]);
postStr = front.stringify(tmpPost);
postStr = '---\n' + postStr;
fs.writeFile(data.full_source, postStr, 'utf-8');
log.i("Generated: categories [%s] for post [%s]", tmpPost.categories, categories[categories.length-1]);
}
return data
}, 15);

我是基于 fluid 主题做的修改,直接将 fluid 主题的所有内容放在了 themes 文件夹,按照 fluid 的目录规范放在了 themes/fluid/scripts/filters 目录中。

这个插件需要在 _config.yml 中配置:

1
2
3
4
5
6
# Generate categories from directory-tree
# Dependencies: https://github.com/xu-song/hexo-auto-category
# depth: the depth of directory-tree you want to generate, should > 0
auto_category:
enable: true
depth:

配置这个后就能用目录结构来管理博客文章。

4. 文章模板

除了上面的配置外,我还试了 hexo-abbrlink 插件,这个插件直接包含了上面的目录类别管理,我没有使用这个插件,但是使用了这里的短链接方式,短链接通过 Obsidian 模板的方式自动生成。

模板使用 Templater 插件,也是两种安装方式,参考前面的 Custom Attachment location

我们在 _posts 下面创建一个 template 目录存放模板文件,为了避免模板被 hexo 当成文章处理,需要先配置 _config.yml 忽略该目录:

1
2
exclude:
- template/**/*

创建一个 post.md 模板,模板内容示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
---
title: '<% tp.file.title %>'
description:
abbrlink: <%* date = tp.date.now("YYYYMMDDhhmmss"); %><% tp.user.hash_8c_2(date) %>
layout: post
date: <% tp.date.now("YYYY-MM-DD HH:mm:ss") %>
updated: <% tp.date.now("YYYY-MM-DD HH:mm:ss") %>
banner_img: /cover/01/1.webp
index_img: /cover/01/1.webp
hide: false
archive: false
categories:
tags:
---

具体有哪些属性需要看你选择的主题,这里需要特别说明的是 abbrlink 短链接属性,这里会使用 Templater 模板调用函数生成一个短链接,如果你不需要随机值,还可以考虑直接用日期+时分秒生成一个字符串,只要唯一不冲突即可。

这里调用的 hash_8c_2 是一个自定义方法,在 template 下面创建 scripts 目录,添加 hash_8c_2.js 文件,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/*
hash_8c_2.js

code by tree_fly, itreefly.com
2023-02-27
*/
function hash_8c_2(message) {
try {
let crypto = require('node:crypto');
var hash = crypto.createHash("md5").update(message).digest("hex");

return hash.substring(2, 10); //equal to 'cut -c 3-10'
} catch (err) {
return "";
}
}
module.exports = hash_8c_2;

参考来源: https://itreefly.com/posts/e5113722.html

接下来配置 Templater 插件:

这里主要就是配置了两个路径,第一个 template 是模板路径,第二个 template/scripts 是脚本路径,配置脚本点下面的刷新就会出现可用的自定义方法。

当我们创建一篇新的博客时,按下图操作就可以选择模板插入到当前博客中:

插入内容如下:

由于想要使用短链接,使用 abbrlink 生成的值作为URL,还需要配置 _config.yml

1
permalink: ':layout/:abbrlink.html'

我在地址中还增加了 :layout 部分,示例地址如下:

5. 总结

整个操作起来挺麻烦的,写到一半我都写不下去了,如果有人喜欢这种方式,或者喜欢我改造的这个博客主题,可以留言给我,我可以把主题以及整个博客整理出一个框架开源出来方便大家使用。直接基于现成环境写的时候,上面所有这些操作都是配置好的,你可以把重点放在内容创作上。

博客地址: https://blog.mybatis.io/

大家还可以说说你们打开博客的速度怎么样,当我第一篇发出去后,首批打开博客的人说加载速度很慢,图片很多,而且都比较大,打开慢就避免不了。为了解决慢的问题,我后续采用了下面几种方式来加速访问:

  1. 文章内容的图片自动转换为 webp 格式,这种格式的压缩率很高,图片瘦身效果很好。
  2. 首页索引图自动生成webp格式的缩略图,变的更小,加载更快
  3. 给博客加多个域名,让资源从不同域名加载,增加并发,加快整体速度

上面这些优化方式都是通过插件实现的,实现的过程也不是一帆风顺,第一种想了两天才实现,第二个想了好几天才实现,最后一个简单,直接上手配合 Copilot 写,包含测试用了不到两个小时。后续会把这3个优化方式也写出来简单讲讲。


使用Obsidian写Hexo博客
https://blog.mybatis.io/post/71d3538c.html
作者
Liuzh
发布于
2024年6月30日
许可协议