文章处理管线

文章处理管线#

这篇文章将介绍结合本地 Obsidian 知识库与远程站点的文章处理体系, 聚焦于在本地与 hugo 搭建的静态网站中都实现良好的显示效果, 并构建一套相对自动化的文章发布管线.

我们构建的文章处理流程如下所示:

  1. 本地使用 Obsidian 编写与管理.
  2. 使用 pandoc 处理文档, 使其符合 hugo 的文档规范.
  3. 使用 hugo 打包为静态站点.
  4. 发布到托管服务.

因为 Windows 系统对于文件名过于苛刻的限制, 并且我们需要使用命令行工具进行自动化, 将在 Linux 环境下进行处理. 为了照顾本地知识库, 它明显在 Windows 下更方便, 可以将处理管线布置在 WSL 中, 它与 Windows 配合得非常好. 关于 hugo 搭建站点的内容可以查看 这篇文章.

格式化文档#

首先要做的就是保证文章格式能够被 pandoc 正确处理, 且被 hugo 正确识别, 因此一方面要保证元数据的正确, 另一方面要确保正文中没有不被 Obsidian, pandoc 和 hugo 支持的 Markdown 语法.

hugo 依赖于 title 而非文件名显示文章标题, 使用 date 标记文章修改时间, 并且会读取 tags 来分类文章. 为了避免流程出错, 与减轻心智负担, 可以在 Obsidian 中安装 Linter 插件, 它可以自动格式化文档, 并重排与补全元数据. 将 Linter 的 标题别名 部分设置打开, 便可以自动从第一个 # 标签处获取文章标题, 并填写到元数据区, 另外还会将标题名作为别名写入. 如果以前在使用 datetime 字段储存文档修改或编写日期, 强烈建议改为 date 字段, 因为这一键名在 Obsidian 与 hugo 两端都受到良好的支持.

为 Hugo 添加数学支持

为 Hugo 添加数学支持#

本文将聚焦于为 hugo 生成的静态站点添加数学公式渲染支持, 我们将使用 MathJax, 因为相比 KaTeX, 它支持更多 \(\LaTeX\) 语法, 例如 align 对齐环境等.

关于 hugo 的 联合文件系统注入点 相关内容, 请看 这篇文章.

首先在 layouts/partials 中新建 mathjax.html, 用于作为组件被调用.

<!-- layouts/partials/mathjax.html -->
{{ if or .Params.math .Site.Params.math }}
<script>
  window.MathJax = {
    tex: {
      inlineMath: [['\\(', '\\)']],
      displayMath: [['$$', '$$']]
    },
    options: {
      skipHtmlTags: ['script', 'noscript', 'style', 'textarea', 'pre']
    }
  };
</script>
<script
  src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js"
  async>
</script>
{{ end }}

这段代码引入了 MathJax, 并配置渲染块标识符, 内联公式为 \\(...\\), 行间公式为 \$\$...\$\$. 不使用 $...$\\[...\\] 的理由将在后文叙述.

使用 Hugo 搭建静态站点

使用 Hugo 搭建静态站点#

在本地知识库软件编写文章在很多时候已经足够满足我参考的需要, 但若遇上呈给别人台鉴的情况, 终归不够方便. 另外文章虽在 GitHub 保存, 但其缺失对元数据的整理功能, 对于必要的 Markdown 拓展语法支持也不佳, 更关键的是, 其使用的 KaTeX 数学引擎较为简陋, 难以招架文章中出现的连篇累牍的公式. 无奈之下, 恐怕建立一个阅览站点成了唯一可行的选择.

本篇文章着重介绍站点本身的配置与搭建, 关于内容的编写与发布请看 这篇文章.

主题选择#

我希望站点整体上是静态的, 没有过分到眼花缭乱的小动画与动态效果, 主题风格简洁严肃, 就像一本书或一页纸一样, 仅用来供人阅览而不喧宾夺主. 最后我选择的主题是 book, 效果和它的名字一样沉静. 然而不得不说的是, 或许我下面的要求过分了点, 没有让我完全满意的主题, book 也不例外. 于是只好对它进行一番改造了.

特殊语法支持#

一些 Markdown 方言提供了特别有益的拓展语法, 例如 admonitions, 我们希望尽可能地使其可用. 幸运地是 book 主题本身就支持这一语法, 因此我们并不需要大费周章配置. 但如果是不支持此语法的主题, 可以额外安装一个 hugo-admonitions 主题, 并将其置于主要主题之前, 这样便可覆盖原主题来提供 admonitions 支持, 如下

theme = ["hugo-admonitions", "book"]

一定注意 hugo-admonitions 应该放置于主要主题 – 这里是 book– 前面, 因为主题的使用是从前到后的.

另外, 这就是一个 admonition.

带有单位的物理计算

带有单位的物理计算#

Mathematica#

Mathematica 中可以带单位计算; 同样, 可以获取任意物理常数, 并以任意精度进行计算.

要使用物理常数, 首先使用 Quantity 函数获取它并保存在变量里, 接着就可以在运算中使用这一常数的带有单位的精确值. 例如

h = Quantity["PlanckConstant"]

获取了普朗克常量的值并保存在变量 h 中.

如果想要知道该常数在国际单位制下的准确值, 可以使用函数 UnitConvert. 例如

UnitConvert@Quantity["PlanckConstant"]

将给出结果

$$\frac{132521403}{200000000000000000000000000000000000000000} \mathrm{kg ~ m^2 / s}$$

要定义带有单位的变量, 依旧使用 Quantity, 只需如下所示

Quantity[600*^6, "Hz"] (* 给出 600000000 Hz *)

Quantity[1, "kg m/s^2"] (* 给出 1 kg m/s^2 *)

软件在解析单位时较慢, 但识别较为精确.

还可以使用语法 Ctrl+= 输入, 这其实是自然语言输入, 可以替换函数 Quantity, 只需按下 Ctrl+= 后输入想要的常数或带单位量即可. 例如 600*^6Hz, 1 kg m/s^2, Planck Constant 等等, 都可被正常识别.

ESP32 环境配置与开发

ESP32 环境配置与开发#

我必须承认, esp idf 是我配置过最困难的开发环境.

本篇文章的开发环境选择是 Visual Studio Codeesp idf. 以 微雪电子 ESP32-S3-Nano 开发板 为例; 这款开发板理论上与 Arduino Nano esp32 开发板完全兼容. 在 这里 可以找到 Arduino 开发板的引脚定义.

esp idf 安装与配置#

esp idf 有两种安装途径: 通过官方安装器; 或是通过 VSCode 插件安装.

上述两种方式安装的 esp idf 互不兼容.

鉴于我们将在 VSCode 中进行开发, 所以最好选择第二种: 通过插件安装.

具体的安装过程可以在 官方教程 找到.

安装 USB 设备驱动#

安装 Zadig. 启动它, 选择 Options > List All Devices. 此时应该能在下拉菜单中找到两个 USB JTAG/serial debug unit, 分别以 Interface 0Interface 2 区分. 下面分别设置这两个的驱动.

关于知识库框架结构的一些想法

关于知识库框架结构的一些想法#

因为我的各种文档或笔记过于分散凌乱, 非常需要进行统一管理. 但是使用的技术栈千差万别, 有纯文字用 markdown 写的, 有使用 jupyter 笔记本内嵌代码的, 有使用 mathematica 的, 有用 typstlatex 写更专业的出版级文档的, 也有主要写代码附文说明的. 现有的知识库框架不可能支持如此多种类的文件管理, 事实上传统的知识库软件仅能做到管理文字内容, 并且也很难做到与其他编辑器的通用. 例如编写代码另附文档的情况, 势必要在其他编辑器处进行代码的编辑, 也当然希望在那里就完成文档的修改, 而不必打开特定的知识库管理或文档软件.

我想通过 git submoduleobsidian 协同构建一个包罗万象的知识库框架, 力图让专业的软件做专业的事, 而不必让知识库管理它能力范围之外的文件, 例如源代码啊, 交互式笔记本啊什么的.

obsidiangit submodule#

obsidian 本质上还是文字编辑软件, 在不加插件的前提下, 只有基础的文字编辑功能 (依托 markdown 标记语言). 因此我们只让 obsidian 管理博文和各类文档, 并辅以 git 进行版本控制.

项目结构如下:

.
├─ Blog
└─ Work
    ├─ A
    └─ B
    ...

其中 Blog 是记录日常或简单知识的文章; 而偏知识向或更专业的, 以及不使用 markdown 语言写的内容都放置于 Work 目录下, 每组另外再分目录.

Windows 下的现代 C/C++ 开发环境配置

Windows 下的现代 C/C++ 开发环境配置#

首先应该确保电脑上有这些必需的软件:

  • CMake
  • Ninja
  • vcpkg
  • MSVC 套件

MSVC 安装#

可以使用 Visual Studio 安装工具 针对性地安装 MSVC 套件而不必安装全套 Visual Studio .

只需在下载的 Visual Studio Installer 中选择 单个组件 → 编译器、生成工具和运行时 → MSVC vXXX - VS 2022 C++ x64/x86 生成工具 选项进行安装. 建议安装最新版本.

MSVC 环境必须经过初始化才可以使用. 安装完成后会自动出现 Developer Command Prompt for VS 20xx (即 开发人员命令提示符 ) 和 Developer PowerShell for VS 20xx (即 开发人员 PowerShell ), 这两个终端就是已经初始化的环境, 在这两个终端中可以直接调用编译器. 另外 Visual Studio 还提供了初始化脚本来初始化编译器环境.

vcpkg 安装#

访问 vcpkg 的 GitHub 仓库以查看安装说明.

在移动介质中安装操作系统

在移动介质中安装操作系统#

所需工具:

  • 安装了任意 linux 发行版的电脑
  • 此处使用安装了 debian 的 VMware 虚拟机
  • 系统安装光盘文件 (.iso 文件)
  • 我选择的发行版是 debian
  • 容量足够的移动介质 (如 U 盘)

1. 检查移动介质 (如 U 盘) 的分区表类型#

我们计划使用更现代的 UEFI 引导操作系统启动, 为了具有更好的兼容性, 移动介质的分区表类型应为 GPT.

因此第一步是将 MBR 类型的移动介质转换为 GPT 分区表类型. 假如你的介质已为 GPT, 可以跳过此章.

1.1. 检查分区表类型#

使用 fdisk 命令检查介质:

# fdisk -l
Disk /dev/sdb: 15.24 GiB, 16358834176 bytes, 31950848 sectors
Disk model: SD/MMC
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x00109879

上面显示了在我的机器上返回的信息, 其中: