跳到主内容

关于博客从 Hexo 迁移到 Nikola 这件事

由于在编写内容的时候受够了 Markdown 那有限的表达力,因此一直在寻找能够支持 reStructuredText 的博客生成器, 在经过多篇文章 1 2 的安利,加上对自身 Python 编程能力的自信,跳入了 Nikola 的阵营。

使用体验上的更新

nikola 使用 nikola new_post 创建的博文脚手架会带有 reST 注释风格 3 的元数据,但是我一般都换成 YAML 风格,Nikola 能直接识别。 一共有这些字段,在 Nikola Handbook 的 Metadate Fields 中有解释 5

title

文章的标题,这是方便人类阅读的,因此推荐使用任何 Unicode 符号。

slug

文章的 slug 名,这是方便 URL 和文件系统解析的,因此推荐使用 ASCII 符号, 在文章创建时, nikola 会强行将 title 中的非 ASCII 符号替换掉。对于中文,会替换成无音调的拼音字母。

这个词语在此语境下的表意在词典里查不到,不过 MDN 上有一个词条 4 解释了它的含义。目前没有汉语翻译。

认真处理这个字段,有利于 URL 的语义性,也有助于 SEOSearch Engine Optimiziation (搜索引擎优化)。

date

文章的创建日期。

tags

文章的标签,是一对多的关系,在 YAML 风格下可以传入一个列表。如果仍使用 reST 注释风格的话,就传入用逗号分隔的列表。

category

文章的分类,是一对一的关系,要么不分类,要么只能分一个。

link

源文件的链接,在一些主题下可能渲染。对于我来说,没有设置它的需求。

description

文章的描述,用在 HTML 头的 <meta> 元素中,有助于 SEOSearch Engine Optimiziation (搜索引擎优化)。

type

文章的类型,如果设置,将会在 <article> 元素中加上一个 CSS 类。 需要主题配合以呈现不同样式。

其他还有一些有用的元数据:

previewimage

设定一个地址,用于充当预览图(需要主题支持)。

template

单独设置该篇文档的渲染模板。

status

文章状态,可选值 published (default), featured, draft, or private。 分别表示发布、未来发布、草稿和私有。

published

文章被渲染到 index 中,任何人都可以访问

featured

表示正在写作,但没有完成,在不同主题会有不同的渲染样式。

draft

不会渲染到输出中。

private

渲染到输出,但是不渲染到 index,只能通过完整链接访问。

在 Hexo 中,可以使用 <!-- more --> 来将内容分成两部分,前半部分在 Index(时间线) 中呈现。在 Nikola,可以用 reST 注释 ..TEASER_END 来实现 6

同时,在 conf.py 需要将 INDEX_TEASERS 设置为 True。

对主题的处理

和 Hexo 丰富的主题生态相比, Nikola 的确有些贫瘠。 对于 Nikola 而言,它的衍生主题都必须继承自 basebootstrap 之一。 默认的模板引擎是 mako,但也可以换成 Jinja2。

其对主题的继承关系非常傻瓜式:现用主题有的文件,就从现用主题读取,没有的,从父主题读取。

自带的默认主题满足不了我的需求,一个是需要加 has_math 字段才渲染公式, 我们希望这是个默认行为;另一个是要从谷歌 API 加载字体,这导致我们的网页渲染异常的慢,最好取消掉,就用每台机器都有的默认字体好了。

首先,找到默认使用的主题 bootblog4 模板所在的文件夹,然后整个复制过来,确保所有的文件都可以被我们改写掉。

Nikola 的内置主题文件位于 nikola 包的 data/themes 目录下,例如 .venv/Lib/site-packages/nikola/data/themes/bootblog4/templates

Nikola 将在站点根目录的 themes/<theme name> 目录下加载主题。 我将在主题修改完成后发布在 https://github.com/zombie110year/nikola-theme-zomhub 上。

测试一下语法高亮和 \(\KaTeX\) 数学公式渲染:

def get_nikola(url: str = "https://getnikola.org/):
    """下载 Nikola 主页的 HTML"""
    resp = requests.get(url)
    if resp.status_code == 200:
        print(resp.text)
\begin{equation*} E = mc^2 \end{equation*}

对插件的处理

Nikola 相比文档生成工具 Sphinx 还是有一些不足,比如缺少一些 Directive 和 Role。 基于 docutils 提供的 Directive 和 Role 可以在 https://docutils.sourceforge.io/docs/ 查看。

构建 Nikola 插件的内容可以在 https://learn-rst.zombie110year.top 查看。

这里急需补充的 Directive 有两个:highlight 和 literalinclude,前者设置默认代码块的词法高亮,后者则拥有相比 include 更强的导入表现能力。

这些我用到的插件,会发布在 https://github.com/zombie110year/nikola-plugin-zomhub 上。