点击查看更新记录
更新记录
2022-06-24 整理分享
1. 整理分享正式方案
2022-05-24 方案落地
1. 编写自定义 hexo 辅助函数,生成是自动重定向图片路径
2022-05-23 需求整理
1. 本地 Markdown 相对路径引用,Hexo 发布路径正确转码
2. 全自动生成,主题集成
# 引言
Hexo
资源文件夹 启用后, Markdown
采取相对路径引用图片以便于本地预览 和 Hexo
发布时资源路径重定向冲突。
本文主要解决两者之间的冲突,使得二者能够兼得.
# 需求整理
# Hexo 资源文件夹
如果你的 Hexo
项目中只有少量图片,那最简单的方法就是将它们放在 source/images
文件夹中。然后通过类似于 ![](/images/image.jpg)
的方法访问它们。
但是这样不利于 维护 也不够 优雅, Hexo
资源文件夹就主要解决了这个痛点,资源( Asset
)代表 source
文件夹中除了文章以外的所有文件,例如图片、 CSS
、 JS
文件等。
这样就可以引用 资源文件夹 的图片资源来书写文章了
# 冲突
在启用资源文件夹后,一篇名为 test-post
的文章在 hexo new test-post
创建时 会生成同名文件夹 test-post
.
一般来说 hexo
用户,都是在本地使用 VS Code
之类的编辑器,本地编写预览文章,那么文章的引用很自然的采取 [相对路径]{.blue} 的方式 ![desc](./test-post/imagename.png)
来引用图片,以便于本地能快速预览。
不幸的是,这样在生成时, hexo
不会进行路径重定向,会粗暴的在相对路径前面添加 rooturl/posts/
无法正确重定向
官方给出的解决方案如下
- 使用相对路径引用标签
{% asset_path slug %}
{% asset_img slug [title] %}
{% asset_link slug [title] %}
- 安装
hexo-renderer-marked
插件,使用![desc](imagename.xxx)
方式引用
两种方式都断了本地相对路径引用预览的路,遂两者不可兼得,冲突现。
# 解决方案
Hexo
框架预留了很多接口供主题编写者扩展,用于在不同时机和场景下,对文章渲染进行自定义修改,其中 过滤器(Filter) 给了我们处理 img
标签的一个绝佳机会。
我们可以通过如下流程,注册一个处理 img
的自定义 filter
- 注册
filter
函数,执行时间选择after_post_render
hexo.extend.filter.register('after_post_render', function (data){ | |
// do something | |
}) |
- 编写函数逻辑对
img
标签的data-src
属性进行修改,重定向到文章对应资源文件夹
# 代码实现
在主题文件夹
themes/shoka/scripts/helpers/
下新增脚本image_path_wrap.js
(名字随意叫啥都行)贴入完整代码,代码文件无需在其他地方引入,内部函数注册了即可
'use strict'; | |
var cheerio = require('cheerio'); | |
// http://stackoverflow.com/questions/14480345/how-to-get-the-nth-occurrence-in-a-string | |
function getPosition(str, m, i) { | |
return str.split(m, i).join(m).length; | |
} | |
hexo.extend.filter.register('after_post_render', function (data) { | |
var config = hexo.config; | |
if (config.post_asset_folder) { | |
var link = data.permalink; | |
var beginPos = getPosition(link, '/', 3) + 1; | |
var appendLink = ''; | |
if (/.*\/index\.html$/.test(link)) { | |
appendLink = 'index/'; | |
var endPos = link.lastIndexOf('/'); | |
} | |
else { | |
var endPos = link.lastIndexOf('.'); | |
} | |
link = link.substring(beginPos, endPos) + '/' + appendLink; | |
var toprocess = ['excerpt', 'more', 'content']; | |
for (var i = 0; i < toprocess.length; i++) { | |
var key = toprocess[i]; | |
var $ = cheerio.load(data[key], { | |
ignoreWhitespace: false, | |
xmlMode: false, | |
lowerCaseTags: false, | |
decodeEntities: false | |
}); | |
$('img').each(function () { | |
if ($(this).attr('data-src')) { | |
var src = $(this).attr('data-src').replace('\\', '/'); | |
if (!(/http[s]*.*|\/\/.*/.test(src) | |
|| /^\s+\//.test(src) | |
|| /^\s*\/uploads|images\//.test(src))) { | |
var srcArray = src.split('/').filter(function (elem) { | |
return elem != '' && elem != '.'; | |
}); | |
if (srcArray.length > 1) | |
srcArray.shift(); | |
src = srcArray.join('/'); | |
$(this).attr('data-src', config.root + link + src); | |
console.info && console.info("update link as:-->" + config.root + link + src); | |
} | |
} | |
else { | |
console.info && console.info("no src attr, skipped..."); | |
console.info && console.info($(this)); | |
} | |
}); | |
data[key] = $.html(); | |
} | |
} | |
}); |
- 重新
Hexo
三连
# 结语
以上就是 资源文件夹 图片相对路径引用的修复过程,完美兼容本地预览和生成发布路径重定向问题。