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
,
以及无法正常换行 ,不过图片倒是可以正常显示。
但我就问了,为什么我有办法修好,你修不好???好吧,可能官方已经忘记要修复这个问题了。