# Oink 0.3.0 — 写作、导航与更轻的页面

> Oink 0.3.0 带来增强代码块与代码分组、日常内容组件、嵌套导航与命令面板、 语义化字体预设，并从每个页面移除了 jQuery。

---

LLMS index: [llms.txt](/zh/llms.txt)

---

**发布日期**：2026-08-12 · **主题标签**：
[v0.3.0](https://github.com/pgsty/oink/tree/v0.3.0) · **代码仓库**：
[pgsty/oink](https://github.com/pgsty/oink)

**发布门禁**：上面的标签必须能够公开解析，项目站必须固定到该精确标签，并且线上检查必须通过。在此之前，请把当前源码页面视为发布候选材料。

Oink
0.3.0 是围绕写作与导航的一个版本。写页面时，代码块有了现代化的呈现，并补齐了一组每天都会用到的小组件；读页面时，多了嵌套导航与命令面板；而所有页面都实实在在变轻了——jQuery 已被移除。

模块路径、最低 Hugo 版本以及 Hugo-only 的消费者构建方式均未改变。有三项改动可能影响既有站点，详见[破坏性变更](#breaking-changes)。

## 版本亮点 {#release-highlights}

### 代码块与代码分组 {#code-blocks-and-code-groups}

普通围栏代码块现在会渲染出完整的代码外壳：可选的文件名、语言标签、由服务端输出而非脚本注入的复制按钮、可选的自动换行，以及长代码的折叠。Hugo 原生的高亮选项——行号、行锚点、`hl_lines`、制表符宽度——行为完全不变。

复制行为是确定的，而不是靠猜。`console`、`shell-session`
这类会话 lexer 默认只复制命令，不含提示符与输出；其余语言默认复制整块。对于无法区分二者的 lexer，
`copy=command` 会直接报错——静默复制错误内容比构建失败更糟。

`code-group`
短代码把包管理器、语言、平台这类并列选项组织成同步切换的标签页，并带稳定的 URL
hash，因此一个链接可以直接打开读者需要的那个变体。既有的 `tabpane`
内容继续工作，存储键也保持不变。

完整参数契约见[代码块](/zh/docs/components/code-blocks/)。

### 日常内容组件 {#everyday-content-primitives}

在既有的大型组件之外，0.3.0 补上了作者每天真正会用的小组件：`badge`、`kbd`、
`fields`、`filetree`、`gallery`，以及可选启用的
`image_zoom`。它们全部输出语义化 HTML，其中非交互组件不加载任何 JavaScript，并且每个组件在打印和 Markdown 输出下都有明确定义的呈现方式。

独立的公共 `icon`
短代码仍然有意推迟：在这套 API 被认真设计出来之前，组件只使用私有的、带白名单的图标注册表来做自身装饰。

各组件契约见[组件](/zh/docs/components/)。

### 导航与命令面板 {#navigation-and-command-palette}

顶层菜单在桌面端支持一级下拉，在移动端有对应的折叠面板；父级链接与展开控件分别独立操作，因此父级本身始终可以点击跳转。平铺菜单不受影响。

本地搜索升级为命令面板，具备三种模式：空查询提供快捷入口与页面操作，文本查询返回分组的页面结果，`>`
前缀则只搜索命令。页面可以提供 `search_keywords`、正值的 `search_boost`
以及规范化的排除标记；Lunr 路径与 CJK 子串路径应用同样的加权。

页面操作与面板命令现在走同一套注册表，因此复制文本、在 ChatGPT /
Claude 中打开、查阅源码、查阅编辑历史、打印、切换主题、语言或版本，无论从哪里触发行为都一致。助手提示词在激活时解析浏览器 URL，保留实际部署域名、查询参数与片段；历史链接则使用“编辑此页面”的同一仓库路径。助手入口默认关闭，站点必须显式设置
`params.ui.page_context_menu.assistant_links: true`
才会启用。激活后完整 URL 会离开本站，因此不要在 query 或 fragment 中放置秘密信息。

在可编辑控件之外按
`/`，可以直接以命令模式打开面板。Cmd/Ctrl-K 仍然是通用入口；这个单字符快捷键不会抢占 input、textarea、select 或 contenteditable 区域中的输入。

侧栏新增图标密度策略 `all`、`groups`、`none`。兼容默认值仍是
`all`，起步示例站选用 `groups`。

完整配置面见[迁移参考](https://github.com/pgsty/oink/blob/v0.3.0/docs/prd4-migration-guide.zh.md)。

### 字体预设 {#typography-presets}

字体选择被收敛到七个语义化的 `--td-*-font-family`
角色之后，覆盖界面、正文、标题、代码、展示文字、元信息与打印输出。本次提供两个经过校验的预设：`technical`
保持当前 Oink 外观，`system`
使用平台字体栈且完全不请求 Oink 品牌字体。既有的 Docsy 与 Bootstrap
Sass 字体变量会作为这些角色的初值，因此原有覆盖继续有效。

这只是更大范围设计令牌工作中的字体一层。颜色、表面、圆角、密度与外观预设不在本次发布范围内。

参见[字体令牌](https://github.com/pgsty/oink/blob/v0.3.0/docs/typography-tokens.md)。

### 更轻的页面 {#a-lighter-page}

jQuery 已被移除。此前它以阻塞渲染的方式出现在每个页面的 `<head>`
里——在任何内容之前先加载 87.5
KB——而主题自身的架构原则是只在用到的页面加载对应运行时。文档壳层没有任何地方需要它，而由它驱动的
`offline-search.js` 早已被命令面板取代。

另外两项开销是被消除而不是被接受的。当前输出格式改为从 page
store 读取，不再在每次构建中重复推导数千次；文档壳层配置按语言缓存。在 576 页的构建上，这让模板耗时从 357 毫秒降到 72 毫秒，且生成结果逐字节一致。CJK 搜索改为在建立索引时一次性折叠字段，不再在每次击键时把整个语料重新小写化——800 篇文档的查询从每次击键 3.44 毫秒降到 0.34 毫秒。

在所测项目站快照上，移除 jQuery 与被替代的搜索运行时后，一个典型文档页的 CSS 与 JavaScript 合计减少约 88
KB。后续候选资源变化会使精确总量有所浮动。

### 正确性与本地化 {#correctness-and-localization}

本版本还修复了几项不太显眼但会影响正确性的缺口。Markdown 页面只在当前语言确实发布
`llms.txt`
时才链接它，索引也不再把站外菜单外壳当作内容。内部自定义命令在子路径部署下保持正确前缀，共用内容类型则会解析到正确的产品 root。归档版本横幅与 Giscus 回退文本已经本地化；打印与 Markdown 输出无论属性使用何种引号，都能清理只用于 Image
Zoom 交互的属性。旧搜索链接也会对查询文本做百分号编码，不再遇到 `&` 就截断查询。

主题 CI 现在会真正运行浏览器 runtime 测试，不再把 Hugo 能打包脚本当作唯一信号。终端录屏也会等待配置字体加载后再适配播放器，避免使用 fallback 字体计算错误尺寸。

## 破坏性变更 {#breaking-changes}

**不再加载 jQuery。**
第三方清单此前把它列为界面基础的一部分，因此消费站自己的脚本可能依赖全局
`$`。主题的任何功能都不需要它。仍然需要的站点，请通过项目 JavaScript 自行打包：

```html
<!-- layouts/_partials/hooks/head-end.html -->
<script src="{{ (resources.Get "js/jquery.min.js").RelPermalink }}"></script>
```

**移除 `static/js/tabpane-persist.js`。** `assets/js/code-tabs.js`
已接管旧的持久化契约，保留了 `td-tp-persist`
存储键与 data 属性，因此已写好的标签页内容不受影响。只有直接引用该发布路径的站点需要去掉这个引用。

**正文与标题字体角色直接作用于内容。** 此前只修改原始 `body`
或标题选择器的站点，应改为使用对应的 `--td-*-font-family`
角色或既有的 Sass 变量：

```scss
// 之前
body {
  font-family: 'My Sans', sans-serif;
}

// Oink 0.3.0
:root {
  --td-body-font-family: 'My Sans', sans-serif;
}
```

## 升级到 0.3.0 {#upgrade}

1. 检查项目 JavaScript 是否依赖全局 `$`，如果依赖，请自行打包 jQuery。
2. 删除对 `static/js/tabpane-persist.js` 的直接引用；已写好的 `tabpane`
   内容本身不需要改。
3. 把原始 `body` 或标题字体覆盖迁移到字体角色。
4. 决定是否显式启用助手入口；如启用，请检查 URL 是否含敏感 query 或 fragment 数据，并披露第三方边界。
5. 更新 Hugo 模块并整理模块图。
6. 构建站点，检查有代表性的文档页、博客页、移动端、打印视图与明暗模式。

```sh
hugo mod get github.com/pgsty/oink@v0.3.0
hugo mod tidy
hugo --gc --minify
```

不需要重写任何 Markdown 内容。既有的围栏代码块、`tabpane`
内容、平铺菜单、短代码，以及普通的 Docsy 兼容页面都继续照常工作。

## 兼容性 {#compatibility}

| 契约               | Oink 0.3.0                    |
| ------------------ | ----------------------------- |
| Hugo               | Extended 0.160.1 或更新；未变 |
| 模块路径           | `github.com/pgsty/oink`；未变 |
| 消费端前端工具链   | 无；未变                      |
| 需要的内容迁移     | 无                            |
| 需要的配置迁移     | 无；助手入口需显式启用        |
| 需要的项目 JS 迁移 | 仅当依赖全局 `jQuery` 时      |

## 验证 {#verification}

0.3.0 候选版本通过并列的 Oink 项目站进行验证，因此站点构建针对的是候选主题本身，而不只是它最后固定的发布版本。公开发布前，主题侧必须通过完整契约测试套件、在最低与当前 Hugo 版本上零警告构建示例站、两种字体预设，以及浏览器运行时单元测试。站点侧必须通过格式化、中英文页面配对与稳定标题 ID、渲染后的 Markdown 与站内链接、Hugo 模块 fixture、备用配置构建、Markdown 与 favicon
golden、响应式与组件浏览器行为，以及 axe 无障碍检查。标签、公共模块解析、站点版本钉住与线上冒烟仍是批准后的独立门禁。

## 完整变更集 {#full-change-set}

完整源码差异见
[v0.2.1 到 v0.3.0](https://github.com/pgsty/oink/compare/v0.2.1...v0.3.0)。
