跳转到主要内容

使用 Oink 创作优美的内容

一本实战教程:用 OINK 创作清晰、优美且易于维护的技术内容。

使用 Oink 创作优美的内容

一本实战教程:用 OINK 创作清晰、优美且易于维护的技术内容。

《使用 Oink 创作优美的内容》是 OINK 参考文档的教程伴侣。参考文档解释每个参数和组件的作用; 本书则沿着一个真实站点的轨迹,从第一次本地预览走到评审与发布。

前三章已放入可直接操作的内容。后续章节在完整演练写作期间,会刻意展示 Book 的草稿状态。

目录

图目录

  1. 图 1-1 — 第一个里程碑是读者能打开的站点,而不是一份仅仅看起来正确的配置文件。

表目录

  1. 表 2-1 — 同一个显式顺序被导航、翻页与生成目录共同使用。
  2. 表 6-1 — 每种交付状态都有自己的证据与交接要求。
  3. 表 A-1 — 同一棵内容树可以生成多种面向不同用途的 Book 输出。

公式目录

  1. 公式 3.1 — 清晰度、准确性或一致性中任何一项降为零,整个页面就会失败。

示例目录

  1. 示例 3-1 — 一份只包含稳定标题、摘要和树中位置的页面契约。

阅读方式

第一次建站时,请按顺序阅读第 1–3 章;开始打磨对外呈现与发布流程后, 再回到第 4–6 章。附录则汇总全书使用的 front matter 模式,便于直接复用。

1 从一个能运行的站点开始

安装唯一必需的工具,启动本地预览,在调整设计前先建立可见的基线。

好的教程首先要给读者一个看得见的结果。对 OINK 而言,这个结果是一个由 Hugo Extended 在本地提供的双语站点——此时还没有改标识、配色或内容架构。

明确结果

完成本章时,你应该拥有英文首页、对应的中文页面、可用的 Docs 与 Blog 路由、本地搜索, 以及颜色模式控件。这条小基线足以在后续工作中区分内容问题、主题问题与部署问题。

OINK 文档站第一次成功本地构建后的页面
图 1-1 第一个里程碑是读者能打开的站点,而不是一份仅仅看起来正确的配置文件。

安装前置工具

OINK 消费站点需要 Hugo Extended 0.160.1 或更高版本。Node.js 属于本仓库的维护者测试工具链, 不是普通消费站点的构建要求。

$ hugo version
hugo v0.160.1+extended

启动本地预览

克隆文档站,进入 checkout,然后启动 Hugo,同时显示草稿、未来内容和已过期内容:

$ git clone https://github.com/pgsty/oink.pgsty.com.git my-docs
$ cd my-docs
$ hugo server -DFE --disableFastRender

打开 Hugo 输出的地址,修改 content/_index.md 里的一句话,再确认浏览器已经显示变更。 一个能对内容修改作出响应的预览,比终端里只显示“服务已启动”更有证明力。

记录基线

在开始定制前,记录四个事实:Hugo 版本、go.mod 中的主题版本、正在评审的 commit, 以及你实际打开的路由。第 2 章会在不丢失这条基线的前提下,把运行中的站点组织成内容树。

完整的安装方式见快速上手从零建站

2 为内容建立结构

让目录、分区索引、页面包与权重共同构成可预期的阅读与导航顺序。

对普通站点而言,OINK 不会另外维护一份导航数据库。内容树就是侧栏树,同一个顺序还会驱动翻页器 与 Book 目录。读者不应该对“下一页是什么”得到三个不同答案。

从读者的问题出发

一级分区应使用读者能辨认的任务或主题命名。小型工程站点通常需要上手指南、参考文档、 运维指南与变更记录。只有当一个目录能为若干页面提供有意义的共享上下文时,才应创建它。

搭建内容树

一棵小型双语文档树

  • content/
    • _index.md
    • _index.zh.md
    • docs/
      • _index.md
      • _index.zh.md
      • start/
        • _index.md
        • _index.zh.md
        • install.md
        • install.zh.md
    • blog/
      • _index.md
      • _index.zh.md

每个读者可以进入的目录都要有 _index.md。译文以 .zh.md 后缀放在英文源文件旁边。 页面拥有图片或下载文件时使用 Page Bundle;没有自属资源时,保留单个 Markdown 文件即可。

明确写出顺序

权重使用 10 的倍数。这些空档便于日后插入新页面,而不必重新给所有同级页面编号。

项目 权重 为什么放在这里
快速上手 10 建立可运行的基线
创作内容 20 在可运行站点上继续搭建
定制站点 30 在结构之后改变呈现
运行维护 40 验证并发布结果
表 2-1 同一个显式顺序被导航、翻页与生成目录共同使用。

建立稳定地址

任何可能被其它页面引用的标题,都要显式写出 ID。英文页面与中文页面虽然显示不同的标题, 却使用同一个 ID。这会让链接、页内目录与整书打印在两种语言中始终对齐。

第一章建立的可见基线是一处明确的参考点。 本章的内容树则为后续每项变更确定了相对于这条基线的稳定位置。

完整规则见编写页面组织内容

3 组合出值得阅读的页面

把散文、提示块、代码、媒体、表格与数学公式组合在一起,而不把页面变成组件目录。

组件应该帮助论证,而不是与内容争夺注意力。先写普通散文,只有当读者需要比较、验证、复制 或停下来思考时,才引入额外结构。

让每个内容块只做一件事

先写出那句话

如果你无法用一句话解释某个组件为什么应该出现在这里, 那就先保留普通正文,直到需求变得明确。

用提示块表达前置条件或风险,用表格对齐重复字段,用代码块放置读者可以执行的材料, 只在形状或空间关系承载了散文无法表达的信息时才使用图片。

从一份小型页面契约开始

示例 3-1 一份只包含稳定标题、摘要和树中位置的页面契约。
---
title: 备份集群
description: 创建并验证一份可恢复的备份。
weight: 20
---

## 验证备份 {#verify-backup}

标题命名读者的任务,描述说明预期结果,权重确定页面的位置, 而显式标题 ID 则为其它页面提供稳定的引用目标。

不用装饰数量衡量质量

有用的页面需要同时平衡三项独立属性:

Q=Cclarity×Aaccuracy×Kconsistency Q = C_{clarity} \times A_{accuracy} \times K_{consistency}
公式 3.1 清晰度、准确性或一致性中任何一项降为零,整个页面就会失败。

这里刻意使用乘法:视觉精美无法弥补错误命令,准确的正文在读者找不到或无法按步骤执行时, 同样会失败。

连接证据

示例 3-1 作为源码模式, 再用 公式 3.1 作为评审问题。第 4 章会把两者用到站点级视觉系统上。

组件参考的起点是组件。只有当教程引入了某项真实需求时, 才需要阅读对应组件的独立页面。

4 塑造阅读体验

把稳固的内容结构变成一份可辨识、响应式且双语对齐的出版物。

设计应该在内容树已经可用之后开始。本章将把品牌、首页编排、导航、排版、页面宽度与语言行为 连成一套可评审的系统。

建立视觉层级

先处理标题、导语、正文、层级标题与局部导航。在加入色彩或装饰前,读者就应该明白下一个动作由哪个区域承接。 OINK 提供层级,站点变量提供身份。

完整演练将替换站点名、标识、字标、favicon、强调色与字体,同时确保深浅两种颜色模式都清晰可读。

编排首页

首页是数据,而不是一份一次性模板。YAML 分区注册表应该讲述一个简短故事:项目是什么、服务谁、 读者下一步能做什么,以及在哪里可以看到主题的真实使用案例。

本节的完整版会从双语 data/home 文件中组装 Hero、组件矩阵、Case 画廊与最终行动入口。

保持导航可预期

顶部菜单、外壳根切换器、侧栏、页内大纲与翻页器各自回答不同问题。在桌面端与移动端同时评审它们, 并确保两种语言显示同一套内容顺序。

同时设计两种语言

译文是对等页面,不是最后的收尾步骤。在把面向读者的文字译成自然中文时,保持路由语义、显式标题 ID、 菜单顺序、图片与功能参数不变。

在完整演练落地前,请参考品牌与外观首页与落地页多语言

5 发布不止于参考页面的内容

用 Docs、Blog、Case、Book 与发布页面分别回答读者的不同需求。

同一个站点可以发布多种知识,而不必把它们强行塞进同一种布局。内容类型选择页面外壳, front matter 变体则在同一外壳内调整呈现。

让发布界面匹配读者

  • Docs 回答任务或参考问题,并显示它在内容树中的位置。
  • Blog 是带日期、作者、分类法、订阅源与分享能力的文章。
  • Case 说明真实站点如何应用主题。
  • Book 章节组成有意设计的阅读顺序,并提供稳定交叉引用。
  • 发布注记把版本、迁移方法与验证证据连接起来。

配置 Blog 家族

普通 Blog 分区可以选择行列表、卡片或表格。需要沉浸式开场的分区仍然保留同一类型, 只改变四个相互独立的呈现键:

type: blog
featured_image: hero
toc_style: flow
toc_taxonomies: false
sidebar_enabled: false

这就是沉浸式阅读所演示的契约。没有第二种 Article 类型, 也没有被复制的发布流水线。

把样例变成 Case 案例

Case 索引使用 Blog 卡片形式,每个内部页面则先说明站点、源码、语言模式、规模与 OINK 能力, 再链接到线上成果。保留内部说明页,能让 showcase 成为文档的一部分,而不只是一面外链标识墙。

让 Book 与 Docs 相互补充

参考页面保持完备,并能独立搜索。教程则从参考中选出一条路径,每次只引入一项决策, 在读者需要完整参数表时再链接回参考文档。

完整演练将使用同一组源事实,新增一篇文章、一个 Case 案例与一篇短 Book 章节, 再比较三者的阅读体验。

6 有把握地交付

区分本地预览、仓库集成、主题发布与站点部署,并用对应证据验证每一种状态。

发布是一串可以分别验证的状态。本地预览成功,只能证明内容与主题可以在当前工作区共同渲染; 它并不能证明远端模块标签已经存在,也不能证明公开站点已经部署了这一版本。

为每种交付状态命名

状态 证据 不能证明什么
本地预览 站点可以使用指定的本地主题检出完成渲染 公开主题版本已经发布
站点集成 内容、配置与依赖变更已经一起审阅 托管平台已经部署这些变更
主题发布 不使用本地替换时,公开标签与模块校验和可以解析 消费站点已经升级
站点部署 公开版本与代表性路由可以访问 每种语言和视口都正确
表 6-1 每种交付状态都有自己的证据与交接要求。

验证最小且有效的范围

先运行直接负责当前契约的检查器,再逐步扩大范围。对于本站,使用相邻主题检出的严格构建 是一项明确的本地开发操作:

HUGO_MODULE_REPLACEMENTS='github.com/pgsty/oink -> /path/to/oink' \
  npm run build -- --panicOnWarning

公开发布之前,要去掉本地替换再次构建,并验证 go.mod 选中的模块。记录每条命令及其结果, 让下一位维护者能够复现结论。

审阅真正渲染出的结果

自动检查可以发现坏链接、重复 ID、无效短代码与无障碍回归,却无法判断 Hero 裁切是否合适, 也无法判断密集表格在手机上是否仍然易读。请在桌面与窄屏下抽查具有代表性的中英文路由, 覆盖导航、主题控件、代码块以及整书输出。

交接事实,而不是暗示

有效的交接应列出变更文件、命令与结果、已知限制,以及尚未发生的下一种状态。引用 表 6-1,准确说明当前到达了哪一步, 不要用一个“完成”混淆验证、发布与部署。

完整的运维参考见预览站点部署站点排查构建问题

A Front Matter 模式

可复制调整的 Book 根页、章节、沉浸式 Blog 文章与整书输出契约。

这些模式刻意保持精简。先复制建立内容契约所需的字段;只有在真实的读者需求出现时, 才加入额外的展示选项。

Book 栏目根页

type: book
book_kind: book
outputs: [HTML, print, markdown]
cascade:
  type: book
  book_draft_banner: true

根页声明 Book 外壳与生成输出。它不需要章节编号;编号属于阅读顺序中真正出现的内容。

Book 章节

book_kind: chapter
book_number: 1
book_status: draft
weight: 10

使用 book_status: draft 表达可见的编辑状态。它与 Hugo 的 draft: true 不同: 页面会保留在普通构建中,审阅者仍然可以阅读尚未完成的章节。

沉浸式 Blog 文章

type: blog
authors: [oink, vonng]
featured_image: hero
toc_style: flow
toc_taxonomies: false
sidebar_enabled: false

文章仍然属于 Blog 家族,Feed、作者、系列与分享能力都会保留;以上字段只改变阅读呈现。

生成输出矩阵

输出 范围 典型用途
HTML 单个根页或章节 阅读、导航与搜索
print 完整的 Book 审阅、打印与 PDF 转换
markdown 保留源码结构的 Book 导出与下游处理
表 A-1 同一棵内容树可以生成多种面向不同用途的 Book 输出。

Book 根页生成的目录、插图、表格、公式与示例索引会一起证明这些契约。中英文页面必须对齐 显式标题 ID 与对象 ID,确保每种格式都保留相同的引用关系。