前言
最近起了写博客的欲望,但是感觉 typecho 用起来不是很喜欢,于是通过先找主题再确定博客系统的原则选择了 hexo。
但是发现 hexo 的这个文件结构属实是比较丑陋。
一般有两种结构
- 图片和图片在单独的目录下,文章通过相对/绝对路径引用
- 开启
post_asset_folder,得到这样的结构1 2 3 4 5
| _posts ├── article1/ ├── article2/ ├── article1.md ├── article2.md
|
即使是第二种结构,也不够优雅,因为 title 出现太多次了,文章一多找依赖也麻烦。搜索了老半天居然没发现有人吐槽这个,我差点想换 hugo。
实现
看了下 hexo 的源码,找到了结构二的实现。
1 2 3 4 5 6 7 8 9 10
| // hexo/lib/plugins/processor/post.js function scanAssetDir(ctx, post) { if (!ctx.config.post_asset_folder) return; const assetDir = post.asset_dir; const baseDir = ctx.base_dir; const baseDirLength = baseDir.length; const PostAsset = ctx.model('PostAsset'); // ... }
|
如果开启了 post_asset_folder,就会把 md 同名的资源文件夹里识别为资源文件夹。
那么 asset_dir 是如何定义的呢?
1 2 3 4 5 6
| // hexo/lib/models/post.js // 声明了一个 getter Post.virtual('asset_dir').get(function() { const src = this.full_source; return src.substring(0, src.length - extname(src).length) + sep; });
|
所以思路很简单,只要把 asset_dir 改成 md 所在就可以了。
这里就用到了 hexo 的插件机制,把这个 getter patch 了一下,改成了 md 所在的目录。
1 2 3 4 5 6 7 8
| 'use strict';const { dirname, sep } = require('path'); hexo.database.model('Post').schema.virtual('asset_dir').get(function() { const src = this.full_source; return dirname(src) + sep; });
|
使用方式
我把这个插件发布到了 npm 上,可以直接安装使用。
1 2 3 4
| // npm npm install hexo-asset-dir --save // pnpm pnpm i hexo-asset-dir
|
然后在 _config.yml 里面设置 post_asset_folder: true 和 new_post_name: :title/index.md。
这样的目录结构就会是
1 2 3 4 5 6 7
| _posts ├── example ├── image.jpg └── index.md ├── example2 ├── image.jpg └── index.md
|
效果

还有
不过我用的这个 fluid 主题的缩略图功能不支持这样的相对路径,还需要再一次插件 hack。
1 2 3 4 5 6 7
| const relative = /^[^/](?!.*:\/\/)/hexo.extend.filter.register('before_post_render', function(data){ if (data.index_img && relative.test(data.index_img)) data.index_img = data.path + data.index_img; return data; });
|
把以上脚本命名为 hexo-fluid-index-img.js 放置到 scripts 目录下即可。