Github + Hexo + Butterfly 建站笔记(七) - 解决一些遗留问题
路径名大小写变换导致的不可访问问题
问题描述
如果你有使用英文命名的习惯,那么在使用 Hexo 的过程中可能会遇到这样一个问题:当将文件名的大小写改变时,重新 deploy 到 git 仓库后使用路径无法访问了。
另外,导致文件名的大小写改变也可以是间接导致的。如,改变文章的 tags 或 categories 的大小写,Hexo 会为你生成与其一致的文件夹。
而我遇到的就是后面一种问题,因为我习惯将 tags 命名为英文,但是一次大小写不统一于是统一改成了首字母大写,然后就导致了上面的问题。如无法访问 https://jamhus-tao.github.io/tags/Butterfly,因为其路径应该是 https://jamhus-tao.github.io/tags/butterfly。
导致原因
其实遇到这类问题我们很自然的想到是是否忽略大小写不统一,这个问题我们日常编程中也很常见,Hexo 为我们提供了 hexo clean 的命令清除本地生成的数据,但这时似乎不顶用了。
导致这个问题的并不是本地的 Hexo 出了问题,而是远程的 Github 出了问题。使用 hexo clean 可以将本地生成的文件清理的很干净,但是我们忘记了将本地分支 push 到远程时并不清除远程的上一个分支,git 是增量式记录的,它会计算与上一次提交的差异,然后将差异附加。但是 git 忽略大小写,而网页路径区分大小写,这就导致了将本地分支 push 上去之后,远程的文件名依然为 butterfly,而在生成的网页文件中的链接是 Butterfly,网页路径又区分大小写而无法访问。
解决方案
知道了问题,解决这个方案就很简单,我们只需要绕过 git 的增量式记录即可。
首先在 .deploy_git 目录下打开命令行,删除除 .git 外的所有文件后 commit 然后拉取前一个 commit 重新 commit 一遍,这样就可以强制更新所有信息。
1 | # 先删除所有除 .git 外的文件 |
URL 变换导致的外站链接失效问题
吐槽:HEXO 的 URL 令我诟病
在 hexo 中,URL 生成的默认规则是 :year/:month/:day/:title,也就是说一条生成的 URL 包含发布时间和文章名称这些信息。但我个人不是很喜欢这样的规则,查阅 hexo 官方文档也发现它是可配置的:

按照我个人对于 URL 的理解,URL 除了保证唯一、持久有效外。如果它希望被频繁转发,那么它至少要是短小的,最好还是方便记忆,特征鲜明的。例如我们来评价一下下面的 URL 命名:
1 | https://jamhus-tao.github.io/posts/id/175/ # 短小精干,转发方便, 看着舒服 |
hexo 事实上也提供了一些清爽的 url 规则。比如 id 和 hash 两个选项,但是它们依然存在一些问题:id 是不可持久的,也就是你 clean 仓库之后重新生成可能原来的 id 就打乱了,那么你分享在外站链接也就全部失效了;另外 hash 是由发文时间和文章标题生成的,有时候希望改下标题原链接同样会失效。
问题重述
所以我们希望解决的问题是:如何在 hexo 内维护稳定且方便的链接,这个链接不应与任何未来可能修改的文章信息关联。
最后我们还会解决博客长期维护的历史问题:即之前使用过的链接已经更换,我需要将所有历史链接重定向到新链接。
设置长期有效链接
这里建议你将配置文件中的默认 URL 生成规则设置为 hash,因为我个人更倾向这种清爽且相对稳定的方式。具体参考:Permalinks | Hexo 官方文档
然后我们应该养成为每篇文章命名长期有效链接的习惯,每篇文章的自定义链接可以写在 YAML Front Matter 中的 permalink 字段,如果该字段被设置,它将替代默认方案。具体参考:Front-matter | Hexo 官方文档
这里有个技巧,在 scaffolds 目录下可以书写文章模板,使用 hexo new post 实际就会生成一份到 source/_posts 目录下。下面是一个示例:
1 | title: Github + Hexo + Butterfly 建站笔记(七) - 解决一些遗留问题 |
重定向历史链接
我现在希望将历史链接全部重定向到新链接,hexo 本身并不支持这个功能,这需要我们自己外挂一些脚本。首先我们需要在 YAML Front Matter 中加入 otherlink 字段,并在这个字段中加入其他链接。
1 | title: Github + Hexo + Butterfly 建站笔记(七) - 解决一些遗留问题 |
然后为重定向网页创建一个模板到 scaffolds/skip.html。网页跳转的非常快,用最简单的网页即可,当然你也可以魔改,做些定时跳转,但是我对 html 不是很熟悉。
1 |
|
然后我们需要提供脚本,为我们生成需要的跳转网页,将它合并到博客中,它的原理我就不具体介绍了,这里我们选择使用 python 来完成这项工作,将它命名为 otherlink.py。
1 | import os |
在每次部署前你需要先运行这个脚本:
1 | hexo g && hexo d # 原先部署命令 |
当然如果你明确重定向内容没有改变,可以不执行这行命令。另外,该命令是一次执行的,也就是说不能在 hexo s 中动态更新。
为什么我的锚不起作用
问题描述
锚其实就是目录中的一个链接,它起到在同一篇文章中跳转子标题的作用,我们有时候会遇到一个麻烦:分明我的目录加了标题,为什么生成的网页无法实现跳转?
导致原因
这个问题实际上并不是 hexo 的问题,当然也不一定是你的问题,如果你经常遇到这个问题,可能是你的习惯不符合标准。当然,我好像也没听说 Markdown 有严格的规范的说法,所以我说这只是约定不统一的问题。
那么 hexo 认为的规范是什么? hexo 认为一篇文章应该只有(至多)一个一级标题,因此它不会为一级标题生成跳转链接,至于是否会在侧边栏生成标题,具体的行为还得看你的主题。
锚本质是什么? 其实锚本质就是网页中一个标签的 id 属性,现在的浏览器都支持输入 #id 来定位到特定位置。当然,hexo 也不会为你的一级标题生成它的 id。
解决方案
那么如何解决这个问题,其实答案也很显然了,我们有两个解决方案:
- 遵循
hexo的Markdown规范,全部为你的标题添加一级。这个工作量其实不大,我们可以借助一些工具。 - 使用外挂脚本,为缺失的标签重新生成
id,这步需要解析html源码,同时需要修改原文和侧边栏两个部分。
我这边选择了第一个方法,因为我们将使用的 正则表达式 可以很快的解决这个问题(OK,如果你熟悉正则表达式,看到这里就结束了)。后面我们尽量遵循 hexo 规范即可。
- 使用你的任何主流本地编辑器(或者 IDE)打开文章目录,然后打开替换功能。VSCode 的替换快捷键是
Ctrl+H,全局替换是Ctrl+Shift+H;Jetbrain 的替换快捷键是Ctrl+R,全局替换是Ctrl+Shift+R。点击替换栏的.*按钮即可使用正则替换,主流编辑器应该都支持使用正则匹配替换。 - 输入查找栏
^(#+? )、替换栏#$1,注意请不要立即开始替换,因为我还将提供一些警告和备选方案。 - 明确警告并选择适合的备选方案后点击全部替换(
Replace All),完成。
警告和备选方案↓↓↓
警告一: 你的文章可能包含一些代码注释,很多语言的注释可能是以 # 提示的,这些被包含在正则替换中。下面提供一些备选方案:
- 你的注释
#会被替换为##,这依然符合注释,你认为这无伤大雅,直接替换即可。 - 标题前和后通常都会换行,如果你也是严格这么做的,那么可以采取此方案。输入查找栏
^(#+? .+)\n\n、替换栏#$1\n\n。 - 如果你没有使用
##等对注释分级的习惯,那么可以采取此方案。输入查找栏^(#{2,}? )、替换栏#$1,这样做可以完成二级以上标题替换,后面使用原方案逐条筛选。 - 最坏的方案,使用原方案高亮后逐条筛选替换。
警告二: 不要直接使用全局替换,如果你的一些文章原先保有使用二级标题的习惯。你可以使用全局查找 # 定位这些包含大量一级标题的文章。
关于 Butterfly 标签外挂 label 在行首的 BUG
问题描述
问题描述: `Butterfly` 自己也说,当标签外挂中的 label 出现在行首时存在 BUG,并称这是 `hexo` 自己存在的问题。例如公式显示异常:$x^2+y^2=r^2$,引用显示异常:`Butterfly`, 以及无法正常换行 ,不过图片倒是可以正常显示。
但我就问了,为什么我有办法修好,你修不好???好吧,可能官方已经忘记要修复这个问题了。
解决方案
在每个 {% label "..." %} 前增加一个空字符就可以解决这个问题,我问 ChatGPT ,它告诉我存在一个零宽空格 U+200B ,这样就又解决了美观问题。
1 | ​{% label "问题描述:" %} `Butterfly` 自己也说,当标签外挂中的 label 出现在行首时存在 BUG, |
问题描述: Butterfly 自己也说,当标签外挂中的 label 出现在行首时存在 BUG,
并称这是 hexo 自己存在的问题。例如公式显示异常:,引用显示异常:Butterfly,
以及无法正常换行 ,不过图片倒是可以正常显示。

但我就问了,为什么我有办法修好,你修不好???好吧,可能官方已经忘记要修复这个问题了。
