目录

[博客装修] 3. 静态博客生成器 Hugo 预处理

目录

静态博客生成器 Hugo 出于安全考虑并不支持调用外部工具,虽然大概可以通过修改源码解决,但是省事的方法就是使用其他工具。

在使用 Hugo 的情况下,实现对一篇博客进行密码保护。如果不使用 Hugo 内部模板语言手写加密算法,思路大概就是在使用 Hugo 生成前,使用外部的 cli 工具加密对应文件,然后在生成对应 markdown 中使用 Hugo shortcode 提供输入密码的组件和解密显示功能。

这一预处理步骤可以通过很多方法解决。如静态文档生成器 mdbook 提供了预处理器接口,预处理的作用是,在送进 renderer 之前,修改原始的 Markdown 文本。而 Hugo 预处理可以使用 Hugo 模板语言实现。例如在 Hugo 某 page 模板这样写

html

        <div class="content" id="content">
            {{ partial "function/ob.html" .RawContent | markdownify | safeHTML }}
        </div>

function/ob.html 这样写

html

{{/* Obsidian Wiki Link Replacement */}}
{{- $content := . -}}

{{/*  // Handle ![[xxx|xxx]]  */}}
{{- $pattern := `!\[\[(.+?)\|(.+?)\]\]` -}}
{{- $replacement := `![$2]($1)` -}}
{{- $newContent := replaceRE $pattern $replacement $content -}}

{{/*  // Handle ![[xxx]]  */}}
{{- $pattern2 := `!\[\[(.+?)\]\]` -}}
{{- $replacement2 := `![]($1)` -}}
{{- $newContent := replaceRE $pattern2 $replacement2 $newContent -}}

{{/*  // Handle [[xxx|xxx]]  */}}
{{- $pattern3 := `\[\[(.+?)\|(.+?)\]\]` -}}
{{- $replacement3 := `<span class="popover-container"><a href="/$1/" class="popover-link" >\[\[$2\]\]</a><span class="popover"></span></span>` -}}
{{- $newContent := replaceRE $pattern3 $replacement3 $newContent -}}

{{/*  // Handle [[xxx]]  */}}
{{- $pattern4 := `\[\[(.+?)\]\]` -}}
{{- $replacement4 := `<span class="popover-container"><a href="/$1/" class="popover-link" >[[$1]]</a><span class="popover"></span></span>` -}}
{{- $newContent := replaceRE $pattern4 $replacement4 $newContent -}}

{{/*  // Convert markdown  */}}
{{- $result := $newContent -}}

{{- return $newContent -}}

这样就能让 Hugo 简单支持 Wiki 语法。如 [[wiki]][[wiki|wiki]]

稍微复杂的功能,用外部工具更为方便。比如加密,再比如在预处理部分事先从某处下载对应的文件,然后进行解析处理为 markdown 。更具体一点儿的功能,使用 语雀 API 获取一些文档,然后生成 markdown ,最后生成博客发布。或者是调用一些在线表格的 API,把在线表格当 CMS 用。这些功能, Hugo 模板语言是无法实现的。

我这里试过几种方案,首先是使用 Python 等语言。Python 功能强大,生态丰富,但用不上那么多功能反而是包袱。如果在容器内使用,这会有一个相当大的镜像体积。

再就是使用 C++,Go,Rust 等语言。个人博客类的预处理器一般并不会很复杂,也不会频繁修改。所以使用这些语言生成对应的二进制文件,放 Docker 里运行就行了。如果需要修改,也可以预先上传到某个地方,在 hugo 执行前动态的从某处下载对应的二进制文件并运行。

如果想要在容器的使用,还有一种方法就是使用更轻量的脚本语言,比如 Lua。比 Lua 更轻量,使用广泛的就是 Bash 了。如果 Bash 足够熟练,也可以用 Bash 进行字符串的处理,jq JSON 构造解析,curl 发送 http 请求等功能。不过 Lua 轻量的同时,使用起来也是很顺手,选个习惯的就好。

话说回来,如果使用 Lua ,HTTP 请求也是需要安装对应的包的。但是需要注意一些包并不支持 Apline musl 。一个比较方便的方法就是使用 Go 版本的 Lua VM ,如 https://github.com/yuin/gopher-lua 。在这个库的帮助下,我们可以很轻松地使用 Go 编写 Lua 函数,拓展 Lua 功能。这样可以在一些小细节上直接修改 Hugo 博客文件夹下的 Lua 脚本,而不用频繁的修改源码生成二进制文件。而且 Go 本身可以很方便的跨平台编译,Apline musl 也可以轻松支持。

通过使用自己编写和拓展的 Lua VM 也可以替代 Bash 的一些功能,我们就可以不用再使用 jq 处理 json ,curl 发送 HTTP 请求。可以通过拓展函数,把这些步骤都放 Lua 中。对应函数有个现成的 gopher-lua 拓展库 https://github.com/vadv/gopher-lua-libs

参考 gopher-lua-libs 这个库,我们可以使用 Go 更轻松的重构上面的 Wiki 功能需要的函数,然后在调用 hugo 生成前,使用 Lua 调用对应函数,预处理相应文件,替换其中 Wiki 格式链接为 markdown 或更进一步的 html 形式。或实现博客文章密码保护功能。这里就不再赘述了,大模型一问就能给出对应函数。

另外一个轻量的脚本语言解释器是 llrt ,一个 js 解释器,10MB 左右的样子。支持了 fetch,fs 等等。但是想要拓展要写 Rust 并折腾 llrt 编译环境。感觉比用 Rust 写 quickjs 模块还麻烦。不过 llrt 一般就直接搜 npm 的包了,也是挺方便的。