内容与自定义
1 - Logo 与图片
添加 Logo
默认情况下,OINK 会在顶部导航栏起始位置(即最左侧)显示站点 Logo。把项目的 SVG
Logo 放在 assets/icons/logo.svg,即可覆盖主题中的默认 Logo。
如果不希望顶部导航栏显示 Logo,请在项目配置中把站点参数 navbar_logo 设为
false:
[params.ui]
navbar_logo = falseparams:
ui:
navbar_logo: false{
"params": {
"ui": {
"navbar_logo": false
}
}
}Logo 样式的更多信息请参阅设置项目 Logo 与名称的样式。
使用图标
OINK 默认包含免费版 Font Awesome 图标,其中也包括 GitHub、Stack
Overflow 等站点的 Logo。可以在
Font Awesome 文档中查看全部可用图标、每个图标加入的 Font
Awesome 版本,以及它是否对免费版用户开放。OINK 随发行物内置已经固定版本的字体与图标;确切版本记录在
theme/VENDOR.json 和发布说明中。
你可以把 Font Awesome 图标添加到顶部导航栏、侧栏导航或正文中的任意位置。
添加 favicon
主题本身不提供 favicon 文件,但会 发现并链接
采用约定名称的图标。请生成 favicon 文件,然后放入项目的
static
目录,使其发布到站点根目录——浏览器会在那里探测这些文件。OINK 会按以下顺序,为找到的文件在每个页面的
<head> 中添加 <link> 元素:
| 文件 | 链接 |
|---|---|
favicon.ico | rel="icon"1 |
favicon.svg | rel="icon",并带有 type="image/svg+xml" |
favicon-NxN.png | rel="icon",并带有 type="image/png" sizes="NxN" |
apple-touch-icon.png | rel="apple-touch-icon"(隐含尺寸为 180×180) |
apple-touch-icon-NxN.png | rel="apple-touch-icon",并带有 sizes="NxN" |
如果提供了上述任意方形尺寸变体,OINK 会按尺寸升序添加。
一个现代 favicon.ico 加上 SVG 和
apple-touch-icon.png,足以覆盖常见浏览器与平台的 favicon 需求。如需更多能力:
- 在 hooks/head-end.html 中添加 Web App Manifest
<link>元素。 - 如果需要自定义 favicon 链接本身,请覆盖
layouts/_partials/favicons.html。务必使用
relURL,确保站点baseURL包含子路径时链接仍然正确。
生成 favicon
还没有 favicon?可以通过 favicon.io 或 RealFaviconGenerator 等在线工具,从单张图片生成 favicon。
如果已经有源 SVG 并安装了 ImageMagick,OINK 也保留 gen-favicons
辅助工具。把源 SVG 保存为
static/favicon.svg——主题会直接链接它——再在同一位置生成栅格图标。从站点项目根目录运行命令。
对于上游 Docsy npm 包安装:
npx --no-install gen-favicons static/favicon.svg static/
其他安装方式运行:
node OINK_THEME_DIR/scripts/gen-favicons/cli.mjs static/favicon.svg static/
将 OINK_THEME_DIR 替换为实际主题目录。使用 Git submodule 时通常是
themes/oink/theme;本仓库中则是 theme/。运行带 --help
的命令可以查看尺寸与其他选项。
该辅助工具只用于一次性生成素材,并不是站点构建依赖。消费端生产构建仍然只运行 Hugo;也可以使用其他获准的图片工具生成同名文件。
添加图片
落地页
OINK 的
blocks/cover 短代码可以方便地为落地页添加封面图(也称为 Hero 图片)。短代码会在落地页的页面包中查找文件名包含
background 的图片。
例如,示例站点的落地页 content/en/_index.md 使用同一目录下的图片
content/en/featured-background.jpg;可在 GitHub 上查看 content/en 文件夹。
通过区块的 height
参数设置封面容器及其图片的首选显示高度。要铺满视口高度,请使用 full,并配合
td-below-navbar 辅助类把封面放在顶部导航栏下方:
{{% blocks/cover
title="Welcome to OINK!"
image_anchor="top"
height="full td-below-navbar"
%}}
...
{{% /blocks/cover %}}
要使用较矮的图片,可以选择 min、med、max,或表示图片自然高度的 auto:
{{% blocks/cover
title="About the OINK Example"
image_anchor="bottom"
height="min td-below-navbar"
%}}
...
{{% /blocks/cover %}}
其他页面
要在其他页面中添加行内图片,可以使用
imgproc 短代码。也可以直接使用普通 Markdown 或 HTML 图片,并将图片文件放入项目的
static
目录。该目录的更多信息请参阅添加静态内容。
.ico链接不声明sizes:文件本身会描述所含帧尺寸(浏览器会读取),在链接中声明尺寸只会带来与真实文件不一致的风险。同时提供favicon.svg时,支持 SVG favicon 的浏览器(绝大多数现代浏览器)会优先使用它,.ico则作为回退。 ↩︎
2 - 代码仓库链接与页面信息
OINK 的文档与博客布局可以显示指向当前页面源码仓库的链接:
- 查看页面源码:打开源文件。
- 编辑本页:打开可编辑的源码视图。
- 创建子页面:在当前页面下新建文件,并可使用站点的
assets/stubs/new-page-template.md模板。 - 创建文档 issue:携带页面上下文,在文档仓库中创建 issue。
- 创建项目 issue:可选地把 issue 提交到另一个产品仓库。
内置 URL 模式面向 GitHub 风格的代码仓库。如果使用其他兼容托管服务,请逐项验证;如果 URL 结构不同,应覆盖相应 partial。
链接配置
典型站点配置如下:
params:
github_repo: https://github.com/OWNER/DOCS
github_project_repo: https://github.com/OWNER/PRODUCT
github_branch: main
github_subdir: site
当内容来自多个代码仓库时,可以在全局、单种语言、分区 cascade 或页面 front matter 中设置这些值。
github_repo
文档源码仓库 URL。它用于生成查看、编辑、创建子页面和创建文档 issue 链接:
params:
github_repo: https://github.com/pgsty/oink
省略后将隐藏从仓库派生的页面操作。如果页面源码实际位于消费站点,不要把它错误地指向主题仓库。
github_subdir(可选)
设置从仓库根目录到 Hugo 站点源码的路径。本项目把站点存放在 oink.pgsty.com 中:
params:
github_subdir: oink.pgsty.com
该值是仓库内路径,不是本地绝对路径;除非内容目录就是实际站点根目录,否则也不能直接填写内容目录。
github_project_repo(可选)
设置另一个产品仓库,以显示 创建项目 issue:
params:
github_project_repo: https://github.com/OWNER/PRODUCT
内容缺陷应提交到文档仓库,页面讨论的产品行为应提交到产品仓库。如果读者无法清楚理解两者区别,应省略第二条链接。
github_branch(可选)
设置源码与编辑 URL 使用的分支:
params:
github_branch: main
通常应填写站点源码分支。它不一定是部署分支、自动生成的 Pages 分支或主题修订版本。
path_base_for_github_subdir(可选)
如果某棵内容子树从另一个仓库挂载,请使用分区 cascade。系统会先移除 path
base,再把剩余内容路径附加到 github_subdir:
---
title: Imported reference
cascade:
github_repo: https://github.com/OWNER/UPSTREAM
github_project_repo: https://github.com/OWNER/UPSTREAM
github_subdir: docs
path_base_for_github_subdir: content/reference
---
对于源页面 content/reference/api/client.md,以上配置会把仓库路径映射为
docs/api/client.md。
path_base_for_github_subdir
可以是正则表达式。按语言目录组织内容的站点可以写成:
path_base_for_github_subdir: content/\w+/reference
OINK 将 .md 与 .zh.md
并置保存,通常两种语言使用相同静态 base,因此表达式中不需要语言目录。
如果源文件使用不同名称,请使用 from 和 to 映射。下面把分区 _index.md
映射到上游 README.md:
path_base_for_github_subdir:
from: content/reference/(.*?)/_index.md
to: $1/README.md
请分别从叶子页、分区页和两种语言页面测试查看与编辑链接。正则表达式移除路径过多时,可能生成看似合理却指向错误位置的仓库 URL。
github_url(可选)
github_url 已弃用。新内容应使用
path_base_for_github_subdir
和仓库参数。
旧页面可以在 front matter 中设置完整的自定义编辑 URL:
---
title: Imported page
github_url: https://github.com/OWNER/UPSTREAM/edit/main/README.md
---
使用该值的页面只显示 编辑本页。当目标与 GitHub 不兼容时,更适合使用站点专属模板覆盖。
禁用链接
每种操作都有稳定的 CSS 类:
| 链接 | CSS 类 |
|---|---|
| 查看页面源码 | .td-page-meta__view |
| 编辑本页 | .td-page-meta__edit |
| 创建子页面 | .td-page-meta__child |
| 创建文档 issue | .td-page-meta__issue |
| 创建项目 issue | .td-page-meta__project-issue |
当目标不支持某项操作时,可以在 assets/scss/_styles_project.scss 中将其隐藏:
.td-page-meta__child {
display: none;
}
对于全局不可用的目标,应优先从配置中省略。CSS 隐藏适合选择性策略,但不能让错误链接变正确。
页面最后修改信息
启用 Hugo Git 信息并配置源码仓库:
enableGitInfo: true
params:
github_repo: https://github.com/OWNER/DOCS
OINK 随后可以在文档与博客页显示最后一次提交的日期、主题、hash 和源码链接。CI 必须为当前文件获取足够的 Git 历史;浅克隆可能导致元数据缺失或产生误导。
如果要在特定站点或分区隐藏提示,可以覆盖样式或负责页面元信息的 partial。当 Git 历史不可用时,不要把构建时间冒充为“最后修改”时间。
3 - 打印支持
大多数浏览器都能很好地打印单篇文档,因为页面样式会从打印输出中移除导航外壳。
有些站点适合启用“打印整节”功能(本用户指南就是如此)。选择后,系统会把当前顶层分区(本页所在的“内容与自定义”等)连同全部子页面和子分区渲染为适合打印的格式,并附上该分区的完整目录。
要启用此功能,请在站点的 hugo.toml、hugo.yaml 或 hugo.json 中,为
section 类型添加 print 输出格式:
[outputs]
section = [ "HTML", "RSS", "print" ]outputs:
section:
- HTML
- RSS
- print{
"outputs": {
"section": [
"HTML",
"RSS",
"print"
]
}
}随后,站点右侧导航中会显示“打印整节”链接。
进一步自定义
禁用目录
如果不希望可打印视图显示目录,可以在页面 front matter,或者
hugo.toml、hugo.yaml、hugo.json 中将 disable_toc 参数设为 true:
+++
…
disable_toc = true
…
+++---
…
disable_toc: true
…
---{
…,
"disable_toc": true,
…
}[params.print]
disable_toc = trueparams:
print:
disable_toc: true{
"params": {
"print": {
"disable_toc": true
}
}
}布局钩子
主题定义了多种布局 partial 和钩子,可用来定制打印格式。这些文件位于
layouts/_partials/print。
钩子可以按内容类型定义。例如,如果希望 blog 页与 docs
页使用不同的标题布局,可以创建
layouts/_partials/print/page-heading-<type>.html,例如
page-heading-blog.html。默认实现使用页面标题和描述作为页首标题。
同理,可以通过创建 layouts/_partials/print/content-<type>.html
来定制每个页面的正文格式。
4 - 导航与菜单
OINK 把 Hugo 的内容树和菜单模型组织成一套文档工作台:全局导航栏、可折叠且可调整宽度的分区侧边栏,以及可折叠的页面大纲。同一套结构适用于英文、中文和从右向左书写的语言。
站点导航栏
全局导航栏由 Hugo 的 main
菜单与 OINK 自动生成的控件组成。根据配置和页面类型,其中可以显示版本、语言、颜色模式与搜索控件。
添加 main 菜单项
可以在页面 Front Matter 中定义菜单项:
---
title: 文档
linkTitle: 文档
menu:
main:
weight: 20
pre: <i class="fa-solid fa-book" aria-hidden="true"></i>
---
权重越小,位置越靠前。站点级外部链接写法类似:
menus:
main:
- name: GitHub
identifier: github
weight: 50
url: https://github.com/pgsty/oink
pre: <i class="fa-brands fa-github" aria-hidden="true"></i>
需要在配置中引用菜单项时,应为其设置 identifier。name 或 linkTitle
可以按语言翻译,但标识符必须稳定。
版本菜单
配置 params.versions
后会显示版本选择器。条目可以表示标题、分隔线、正式版本、开发版本或站点变体:
params:
version: v1.0.0
version_menu: v1.0.0
version_menu_pagelinks: true
versions:
- version: v1.1.0-dev
kind: next
url: https://next.example.org/
- version: v1.0.0
kind: latest
url: https://docs.example.org/
version
标识已发布的站点变体,不一定是 Git 引用。安装命令等必须使用可解析标签的内容,应改用项目显式定义的发布引用参数。启用页面链接后,OINK 会先尝试目标版本中的同一路径,找不到时再使用条目配置的 URL。
语言菜单
OINK 根据 Hugo 的 AllTranslations
构造语言目标。当前页面缺少某种语言译文时,会链接到该语言首页,而不是生成损坏的 URL。只配置一种语言时不显示控件;配置两种或更多语言时,直接点击会按
weight
顺序切换到下一种语言,悬停半秒或聚焦控件则打开完整菜单。当前站点按英文、简体中文的顺序循环。目标链接包含
lang、hreflang、locale 与文字方向属性。
浅色/深色主题菜单
启用颜色模式后,导航栏与文档工作台会显示主题控件。详见浅色/深色模式菜单。
搜索框
启用离线搜索后,文档工作台会使用本地搜索对话框。侧边栏按钮会显示当前平台快捷键(Command/Ctrl+K)。在线搜索集成仍可通过显式配置启用。详见搜索。
为导航栏添加图标
在菜单项中使用 pre 或 post。OINK 已在本地提供免费版 Font Awesome 资源:
menus:
main:
- name: 源码
identifier: source
url: https://github.com/pgsty/oink
weight: 50
pre: <i class="fa-brands fa-github" aria-hidden="true"></i>
post: <span class="visually-hidden">(外部链接)</span>
装饰性图标需要设置
aria-hidden="true";链接本身必须保留有意义的文字或无障碍标签。在新标签页打开的外部链接必须使用
rel="noopener"。
侧边导航
文档页与博客页的左侧面板由内容层级自动生成。OINK 按 weight 排序,并在存在
linkTitle 时用它作为标签。分区来自 _index.md;翻译后的分区需要配套
_index.zh.md,才能正确本地化导航元数据。
从侧边栏隐藏页面:
toc_hide: true
从分区落地页摘要中隐藏页面则使用
hide_summary: true。只有页面确实不应出现在这两个发现入口中时,才同时设置二者。
侧边导航选项
常用控制项如下:
params:
ui:
sidebar_menu_compact: true
sidebar_menu_foldable: true
sidebar_menu_truncate: 128
sidebar_cache_limit: 2000
sidebar_search_disable: false
sidebar_width_min: 220
sidebar_width_max: 480
sidebar_item_overflow: ellipsis
sidebar_menu_compact只显示当前分支和附近条目;sidebar_menu_foldable允许读者展开或折叠分区;sidebar_menu_truncate限制条目数,数值过小时会发出构建警告;sidebar_cache_limit在站点规模超过阈值后启用共享导航标记;sidebar_width_min与sidebar_width_max限制桌面端拖拽调整的宽度;sidebar_item_overflow默认为ellipsis,长标签需要换行时改用wrap。
折叠状态、宽度和滚动位置保存在读者本地。移动端会转换为带遮罩层和安全焦点控件的可关闭抽屉。
为侧边导航添加图标
在页面 Front Matter 中设置 icon:
---
title: 运维
icon: fa-solid fa-screwdriver-wrench
---
同级条目的图标用法应保持一致。图标只是辅助线索,不能取代文字标签。
为侧边导航添加手动链接
在所需位置创建占位页面:
---
title: API 状态
weight: 90
manualLink: https://status.example.org/
manualLinkTitle: 实时服务状态
manualLinkTarget: _blank
---
内部内容引用应使用 manualLinkRelref 而不是
manualLink;Hugo 无法解析目标时会令构建失败。OINK 会为新标签页链接补充
noopener。由于 Hugo 仍会为占位文件生成页面,正文应简短说明实际去向。
将分区设为侧边栏根节点(实验性)
启用根侧边栏:
params:
ui:
sidebar_root_enabled: true
sidebar_root_menu: true
然后在分区的 _index.md 中设置:
---
title: API Reference v2
sidebar_root_for: self
sidebar_root_link_self: true
---
self 会把该根节点应用于分区索引及其后代;children
会把索引留在父级树中,只限制其后代。可选的根菜单用于在不同根节点之间切换。根分区可以嵌套,但冗余或无效取值会触发构建警告。
页面目录
Hugo 根据 Markdown 标题生成右侧页面大纲。OINK 将其渲染为固定文档面板,并放置快捷链接、语言与主题控件、仓库元数据和分类标签。读者可以折叠该面板,状态保存在本地。
由 Markdown 短代码({{% ... %}})输出的标题会进入 Hugo 目录;仅由标准短代码({{< ... >}})输出的标题通常不会进入。因此,只要条件允许,内容结构都应保留在 Markdown 中。
目录定制
在单个页面隐藏大纲:
notoc: true
配置 Hugo 收录的标题层级:
markup:
tableOfContents:
startLevel: 2
endLevel: 4
ordered: false
toc_on_this_page
等标签在站点 i18n 资源包中翻译。自定义 CSS 调整大纲轨道或固定面板尺寸后,需要测试活动项跟踪、缩放、键盘焦点,以及完全没有标题的页面。
使用 ScrollSpy 跟踪目录活动项
OINK 使用本地 Bootstrap ScrollSpy 补丁与 IntersectionObserver 跟踪活动标题。工作台会绘制连续轨道、活动区段和位置标记。为某个页面关闭跟踪:
params:
ui:
scrollSpy:
disable: true
旧版 ScrollSpy 配置也接受全局
rootMargin。它会改变条目进入活动状态的时机,应在短分区、长分区和直接片段导航中分别测试。
ScrollSpy 高级定制
优先使用配置与项目 CSS。覆盖 ScrollSpy 属性 Partial 或 docs-shell.js
会形成实现级分支;必须增加浏览器 Fixture,覆盖哈希更新、前进/后退导航、尺寸变化、减少动态效果模式,以及存在重复或缺失 ID 的页面。
面包屑导航
普通内容页上方和分类结果中会显示面包屑。全局关闭方式如下:
params:
ui:
breadcrumb_disable: true
taxonomy_breadcrumb_disable: true
页面或分区 cascade 也可以设置
ui.breadcrumb_disable。面包屑标签来自本地化页面标题,而且必须与侧边栏遵循同一逻辑层级。
标题自链接
使用方站点可以启用 OINK 标题渲染钩子:
{{ partial "td/render-heading.html" . }}
生成的 .td-heading-self-link 控件默认使用
#。它在触控设备上始终可见,在指针设备上则于悬停或聚焦时出现。链接必须支持键盘访问,并保留足以避开固定导航的滚动偏移。
标题别名与页内目标
修改标题可能破坏外部片段链接,因此标题 ID 应按公开路由对待。需要重命名 ID 时,应保留旧 ID 的空锚点,并显式写入新 ID:
## Quickstart <a id="get-started"></a> {#quickstart}
别名和其他页内目标应使用空的 <a id="..."></a>。不要仅为片段目标使用
span。ID 必须唯一、稳定,在可行时使用 ASCII,并在各语言版本中保持一致。
快速开始
这个真实标题演示了 #get-started 与 #quickstart
都能到达同一位置。译文标题应显式写入英文页面渲染后的 ID,不要依赖不同语言各自生成的自动 slug。
实现说明
- 文档为固定界面设置全局滚动偏移;
- 内置块目标使用
td-anchor-no-extra-offset,避免重复应用额外偏移; - 翻译审计会比较英文与中文页面渲染后的标题 ID;
- 删除旧别名属于破坏性文档变更,需要重定向或明确记录兼容性决策。
5 - 短代码
短代码用于表达普通 Markdown 无法承载的行为。OINK 保留 Docsy 核心组件,并新增本地提供的图表、终端录像、信息图、轮播、卡片和折叠组件。浏览器运行时只在实际使用它们的页面加载。
标题、正文、列表、链接、表格和图片应优先使用 Markdown。短代码一旦投入使用,就成为内容 API 的一部分:修改名称或参数可能破坏所有调用它的页面。
短代码分隔符
Hugo 支持两种形式:
{{< name >}}使用标准分隔符,原样传递内部内容;{{% name %}}使用 Markdown 分隔符,在周围内容的上下文中渲染内部 Markdown。
请采用各组件文档指定的形式。嵌套、缩进和空行都会影响结果,在列表和块引用中尤其如此。示例里的
/* ... */ 转义用于防止 Hugo 执行正在展示的短代码。
blocks/* 短代码
块短代码用于组合全宽落地页。color
参数使用 OINK/Bootstrap 语义颜色或项目自定义块样式,height
参数接受各组件说明的取值。
blocks/cover
使用页面包中匹配 *background* 的图片以及可选的 *logo* 创建首屏:
{{< blocks/cover title="OINK" subtitle="本地优先文档"
color="dark" height="max" >}} [开始使用](/zh/docs/get-started/){ .btn
.btn-lg .btn-primary } {{< /blocks/cover >}}
image_anchor 和 logo_anchor 控制图片裁切位置,byline
用于标注图片来源。高度可取 auto、min、med、max 或
full。即使背景无法显示,首屏关键信息也必须保持可读。
blocks/lead
创建醒目的介绍区块:
{{% blocks/lead color="primary" height="min" %}} OINK 只用 Hugo
Extended 即可构建完整文档体验。 {{% /blocks/lead %}}
高度支持 auto、min、med、max 或 full。
blocks/section
创建通用落地页区块:
{{% blocks/section color="light" type="row" height="auto" %}}
### 一个分区
区块内部使用普通 Markdown。 {{% /blocks/section %}}
type 选择容器形式,height 使用块高度取值。标题级别必须与页面大纲保持一致。
blocks/feature
创建单个功能单元,通常放在 Section 中:
{{% blocks/feature icon="fa-solid fa-box-archive"
title="离线可用" url="/zh/docs/oink/local-first/"
url_text="阅读设计说明" %}} 所需浏览器资源均已锁定版本并从本地提供。
{{% /blocks/feature %}}
图标只是装饰,含义必须由 title 和链接文本表达。
blocks/link-down
从当前块添加指向下一块的链接。它必须嵌套在块内。生成目标必须长期稳定时,应显式设置
id。
导航栏下方布局校正
直接位于固定导航下方的块使用 td-below-navbar/td-anchor-no-extra-offset
校正导航栏高度。不要自行添加任意上边距;修改导航栏尺寸后,应验证直接访问片段链接的效果。
辅助短代码
alert
旧版告警短代码仍可使用:
{{% alert title="兼容性说明" color="warning" %}}
新内容优先使用 Markdown 块引用告警。 {{% /alert %}}
color
映射到 Bootstrap 告警后缀。新内容通常应采用添加内容介绍的 Markdown 告警语法。
告警、缩进与示例
开始和结束短代码应与外层列表或块引用对齐,块级 Markdown 前后应保留空行。需要原样展示短代码时,应转义分隔符,不要把活动调用包在另一个组件中。
pageinfo
在 Markdown 外渲染信息面板:
{{% pageinfo color="info" %}} 本页介绍预览接口。 {{% /pageinfo %}}
警告信息应使用语义告警;pageinfo 适合提供页面上下文。
imgproc
处理当前页面包中的图片:
{{% imgproc "architecture" Fit "960x540" %}} OINK 运行时架构。
{{% /imgproc %}}
命令可取 Fit、Resize、Fill 和
Crop,第三个参数遵循 Hugo 图片处理语法。内部文字会成为图注;资源存在
params.byline 时会附加署名。始终提供有意义的替代文字或相邻说明。
swaggerui
嵌入本地纳管的 Swagger UI 运行时:
{{< swaggerui src="/openapi.yaml" >}}
离线或严格 CSP 部署应使用同源规范。远程 src
是显式网络依赖,也可能向该主机暴露读者元数据。当前兼容短代码在一页中只应放置一个 Swagger
UI 实例。
redoc
嵌入本地纳管的 Redoc 运行时:
{{< redoc "openapi.yaml" >}}
第一个参数可以是页面相对、站点相对或显式 HTTP 规范;可选第二个参数包含 Redoc 元素选项。规范内容必须经过审查,大型 Schema 还应测试移动端表现。
iframe
嵌入另一个页面:
{{< iframe src="/demo/" name="demo" id="demo-frame"
sandbox="allow-scripts allow-same-origin" >}}
请设置有描述力的 name、唯一的 id、后备 sub 提示,以及满足需求的最严格
sandbox。默认值支持宽度和自动高度,但跨域文档并不总能测量。iframe 是安全与隐私边界,不是通用布局工具。
OINK 内容组件
以下组件由 OINK 新增。各运行时都在 theme/VENDOR.json
中锁定版本,并按需从同源加载。
details
创建无障碍折叠内容:
{{% details title="显示迁移说明" closed="false" %}} 正文支持 Markdown。
{{% /details %}}
closed 默认为 true。摘要应简洁,而且不得把强制操作隐藏在默认关闭的折叠区中。
asciinema
播放 asciinema .cast 录像:
{{< asciinema file="casts/install.cast" speed="1.25"
markers="0:开始,18:验证" fit="width" >}}
主要参数包括
theme、autoplay、loop、preload、speed、startAt、poster、cols、rows、idleTimeLimit、pauseOnMarkers、markers
和 fit(width、height、both 或 none)。本地录像可以来自 Hugo
assets 或站点相对 URL。不要自动播放,必须清除终端历史中的机密,并为关键步骤提供相邻文字说明。
echarts
根据 JSON 或 YAML 选项对象渲染 Apache ECharts:
{{< echarts height="320px" >}} xAxis: type: category data:
[构建, 测试, 发布] yAxis: type: value series:
- type: bar data: [42, 38, 12] {{< /echarts >}}
height 必须是安全的 CSS 长度;theme 选择 ECharts 主题,full=true
会取消常规正文宽度限制。
短代码内部的 JavaScript 块默认会被拒绝。只有单次调用设置
unsafe=true,或全局设置 params.content.echarts_unsafe=true
时才能执行。该选项允许可执行内容,绝不能为不可信作者启用。应优先使用声明式 JSON/YAML,添加相邻文字摘要,并验证深色模式。
infographic
渲染本地纳管的信息图 DSL:
{{< infographic height="360px" >}} infographic
list-row-simple-horizontal-arrow data items - label 构建 - label 测试 -
label 发布 {{< /infographic >}}
height 可以是 auto 或安全 CSS 长度;full=true
会取消宽度限制。DSL 属于数据,并非任意 HTML。可视化不可用时,相邻正文也必须能表达相同结论。
doc-cards 与 nav-cards
两个容器都接受 1 至 4 的 cols。子卡片接受
title、link、image、alt、icon、desc、accent 与 badge:
{{< nav-cards cols="2" >}}
{{< nav-card title="开始使用" link="/zh/docs/get-started/"
icon="fa-solid fa-rocket" desc="使用 Hugo {version} 构建。" >}} {{< nav-card title="架构" link="/zh/docs/oink/architecture/"
badge="设计" >}}
{{< /nav-cards >}}
doc-card/doc-cards 与其共享渲染契约,适合编辑型内容;nav-card/nav-cards
则明确表示导航。{version}
等描述占位符会从站点参数解析。卡片图片采用延迟加载;除非图片纯属装饰,否则必须提供有意义的
alt。
doc-carousel
把 doc-card 放入支持键盘滚动的轮播:
{{< doc-carousel label="发布亮点" >}}
{{< doc-card title="本地资源" >}}无需 CDN。{{< /doc-card >}}
{{< doc-card title="中英双语" >}}稳定的中英文路由。{{< /doc-card >}}
{{< /doc-carousel >}}
label
为辅助技术命名该区域。上一项/下一项按钮会本地化。信息不能只存在于屏幕外卡片中;禁用脚本后,轨道仍应可用。
param
输出页面参数;根据 Hugo 的 Page.Param 规则,在页面缺省时回退到站点配置:
OINK 版本 {{< param version >}}。
找不到参数会令构建失败。param
适合显示标量值,不应用于注入未经审查的 HTML。内部兼容短代码 _param
还会为旧内容执行带编号的占位符替换。
标签页
标签页用于组织 YAML/TOML/JSON 配置等同一信息的等价表示,不应隐藏连续步骤或互不相关的选择。
{{< tabpane text=true persist=lang >}}
{{< tab header="YAML" lang="yaml" >}} params: offlineSearch: true
{{< /tab >}} {{< tab header="TOML" lang="toml" >}} [params]
offlineSearch = true {{< /tab >}} {{< /tabpane >}}
选择状态保存在浏览器本地。persist 接受 header、lang 或
disabled。已弃用的 persistLang 不应出现在新内容中。
短代码细节
text=true 将内部内容渲染为正文而不是高亮代码;right=true
把标签对齐到末端;langEqualsHeader=true
根据标题推导语言标识。父级默认值可以由单个标签覆盖。
tabpane
父组件会校验布尔值和持久化参数、生成唯一 ID,并确保存在选中项。只有禁用的标题标签确实能提供有用分组信息时才使用它。
tab
tab 必须放在 tabpane 内部。它接受
header、selected、lang、highlight、text、right 和
disabled。只能选中一个标签。面向读者的标题需要翻译,语言标识则必须稳定。
卡片面板
旧版 cardpane/card
组合用于布局 Bootstrap 风格卡片。新的导航表面应优先使用 OINK 内容卡片,既有 Docsy 内容可以继续使用兼容组件。
card 短代码:文本内容
{{% cardpane %}}
{{% card header="说明" title="本地构建" footer="已验证" %}} Markdown
**正文**。 {{% /card %}} {{% /cardpane %}}
header、title、subtitle 和 footer
接受渲染文本。并列卡片应保持简洁,不能用卡片取代标题结构。
card 短代码:程序代码
设置 code=true,并按需设置 lang/highlight:
{{< cardpane >}} {{< card code=true header="Go" lang="go" >}}
fmt.Println("OINK") {{< /card >}} {{< /cardpane >}}
卡片组
cardpane
中相邻的卡片会形成响应式分组。应测试文字长度不一、移动端堆叠、代码溢出以及两种语言版本。
引入外部文件
readfile
短代码在构建期读取仓库文件,并将其渲染为 Markdown 或高亮代码。除非路径以 /
开头,否则路径相对于当前内容文件。
复用文档
{{% readfile "includes/installation.md" %}}
被引入的 Markdown 不是独立发布页面,因此不参加页面配对审计。如果共享正文面向读者,应有意识地创建并选择语言专属的 include 文件;Hugo 不会自动翻译 include。
安装
可复用片段应放在调用方附近的 includes/
目录中。需要明确其所有权,并避免多层嵌套:读者和审阅者应能迅速找到源文件。
引入代码文件
{{< readfile file="includes/config.yaml" code="true" lang="yaml" >}}
code=true 会用 lang 高亮文件。绝不能引入机密、生成的凭据或不可信路径。
错误报告
找不到文件时构建会失败。draft=true
会把失败改为可见的草稿警告,只适合创作阶段,绝不能进入正式发布构建。
条件文本
conditional-text 根据 params.buildCondition 选择内容:
{{% conditional-text include-if="enterprise,preview" %}}
这段文字只出现在匹配的构建中。 {{% /conditional-text %}}
include-if 与 exclude-if
接受条件列表,同一条件不能同时出现在二者中。该功能适用于确实不同的发布变体,不应用来选择语言;多语言内容必须写入翻译后的页面文件。
6 - 分类法支持
OINK 在文档与博客分区中支持 Hugo 分类法。本页既展示默认布局,也可以用来测试生成链接的行为。
术语
使用分类法前,需要理解以下术语:
分类法(Taxonomy):用于对内容进行分类的体系,例如标签、类别、项目、人物。
术语(Term):分类法中的一个键。例如,在“项目”分类法中可以有“项目 A”和“项目 B”。
值(Value):分配给某个术语的一项内容,例如属于特定项目的站点页面。
Hugo 文档提供了一个电影网站分类法示例。
参数
项目配置文件中有多项参数可以控制分类法功能。Hugo 默认启用 tags 与
categories 分类法。要 禁用 分类法,请在项目配置中添加:
disableKinds = ["taxonomy"]disableKinds: [taxonomy]{
"disableKinds": [ "taxonomy" ]
}保持默认设置时,Hugo 会生成 tags 与 categories
的分类法页面。如果要使用其他分类法,需要在配置文件中定义。如果希望自定义分类法与默认的
tags、categories
并存,也必须把默认分类法一并写入配置。每种分类法都需要提供单数与复数标签。
下面的示例在默认 tags 和 categories 之外,又定义了 projects 分类法:
[taxonomies]
tag = "tags"
category = "categories"
project = "projects"taxonomies:
tag: tags
category: categories
project: projects{
"taxonomies": {
"tag": "tags",
"category": "categories",
"project": "projects"
}
}项目配置中的以下参数可控制两类输出:文档和博客文章页显示的分类法术语,以及 OINK 右侧栏显示的“标签云”:
[params.taxonomy]
taxonomyCloud = ["projects", "tags"] # set taxonomyCloud = [] to hide taxonomy clouds
taxonomyCloudTitle = ["Our Projects", "Tag Cloud"] # if used, must have same length as taxonomyCloud
taxonomyPageHeader = ["tags", "categories"] # set taxonomyPageHeader = [] to hide taxonomies on the page headersparams:
taxonomy:
taxonomyCloud:
- projects # remove all entries
- tags # to hide taxonomy clouds
taxonomyCloudTitle: # if used, must have the same
- Our Projects # number of entries as taxonomyCloud
- Tag Cloud
taxonomyPageHeader:
- tags # remove all entries
- categories # to hide taxonomy clouds{
"params": {
"taxonomy": {
"taxonomyCloud": [
"projects",
"tags"
],
"taxonomyCloudTitle": [
"Our Projects",
"Tag Cloud"
],
"taxonomyPageHeader": [
"tags",
"categories"
]
}
}
}以上设置只会在 OINK 右侧栏中显示 projects 和 tags 的分类云(标题分别为“ Our
Projects”和“Tag Cloud”),并在每个页面显示 tags 和 categories
分类法中已经分配的术语。
要禁用所有分类云,请设置 taxonomyCloud = [];如果不想显示已分配术语,请设置
taxonomyPageHeader = []。
默认情况下,分类法的复数标签会用作分类云标题。可以通过 taxonomyCloudTitle
覆盖默认标题,但这样做时,必须为每个启用的分类云手工定义一个标题;taxonomyCloud
与 taxonomyCloudTitle 的长度必须相同。
如果没有设置 taxonomyCloud 或
taxonomyPageHeader,系统会为所有已定义分类法生成相应的分类云或已分配术语。
Partial
显示分类法时默认使用的 partial 经过专门设计,可以方便地在自定义布局中复用。
taxonomy_terms_article
taxonomy_terms_article partial 会显示一篇文章或页面(partial 参数
context,通常是当前页面或上下文 .)在指定分类法(partial 参数
taxo)中分配到的全部术语。
下面是在 layouts/docs/list.html 中为文档分区每个页面的 header 使用它的示例:
{{ $context := . }}
{{ range $taxo, $taxo_map := .Site.Taxonomies }}
{{ partial "taxonomy_terms_article.html" (dict "context" $context "taxo" $taxo ) }}
{{ end }}
它会针对当前页面(或上下文)中的每个已定义分类法,输出一份包含全部已分配术语的列表:
<div class="taxonomy taxonomy-terms-article taxo-categories">
<h5 class="taxonomy-title">Categories:</h5>
<ul class="taxonomy-terms">
<li>
<a
class="taxonomy-term"
href="//localhost:1313/categories/taxonomies/"
data-taxonomy-term="taxonomies"
><span class="taxonomy-label">Taxonomies</span></a
>
</li>
</ul>
</div>
<div class="taxonomy taxonomy-terms-article taxo-tags">
<h5 class="taxonomy-title">Tags:</h5>
<ul class="taxonomy-terms">
<li>
<a
class="taxonomy-term"
href="//localhost:1313/tags/tagging/"
data-taxonomy-term="tagging"
><span class="taxonomy-label">Tagging</span></a
>
</li>
<li>
<a
class="taxonomy-term"
href="//localhost:1313/tags/structuring-content/"
data-taxonomy-term="structuring-content"
><span class="taxonomy-label">Structuring Content</span></a
>
</li>
<li>
<a
class="taxonomy-term"
href="//localhost:1313/tags/labelling/"
data-taxonomy-term="labelling"
><span class="taxonomy-label">Labelling</span></a
>
</li>
</ul>
</div>
taxonomy_terms_article_wrapper
taxonomy_terms_article_wrapper 是 taxonomy_terms_article
的包装 partial,只有一个 context 参数(通常是当前页面或上下文
.)。它会检查项目 hugo.toml、hugo.yaml 或 hugo.json 中的分类法参数,遍历
taxonomyPageHeader 中列出的全部分类法;如果没有设置
taxonomyPageHeader,则遍历页面定义的全部分类法。
taxonomy_terms_cloud
taxonomy_terms_cloud partial 会显示站点(partial 参数
context,通常是当前页面或上下文 .)在指定分类法(partial 参数
taxo)中使用的全部术语,并使用 title 参数作为标题。
下面是在 taxonomy_terms_clouds partial 中显示所有已定义分类法及其术语的示例:
{{ $context := . }}
{{ range $taxo, $taxo_map := .Site.Taxonomies }}
{{ partial "taxonomy_terms_cloud.html" (dict "context" $context "taxo" $taxo "title" ( humanize $taxo ) ) }}
{{ end }}
对于 categories 分类法,它会生成以下 HTML 标记:
<div class="taxonomy taxonomy-terms-cloud taxo-categories">
<h5 class="taxonomy-title">Cloud of Categories</h5>
<ul class="taxonomy-terms">
<li>
<a
class="taxonomy-term"
href="//localhost:1313/categories/category-1/"
data-taxonomy-term="category-1"
><span class="taxonomy-label">category 1</span
><span class="taxonomy-count">3</span></a
>
</li>
<li>
<a
class="taxonomy-term"
href="//localhost:1313/categories/category-2/"
data-taxonomy-term="category-2"
><span class="taxonomy-label">category 2</span
><span class="taxonomy-count">1</span></a
>
</li>
<li>
<a
class="taxonomy-term"
href="//localhost:1313/categories/category-3/"
data-taxonomy-term="category-3"
><span class="taxonomy-label">category 3</span
><span class="taxonomy-count">2</span></a
>
</li>
<li>
<a
class="taxonomy-term"
href="//localhost:1313/categories/category-4/"
data-taxonomy-term="category-4"
><span class="taxonomy-label">category 4</span
><span class="taxonomy-count">6</span></a
>
</li>
</ul>
</div>
taxonomy_terms_clouds
taxonomy_terms_clouds 是 taxonomy_terms_cloud 的包装 partial,只有一个
context 参数(通常是当前页面或上下文
.)。它会检查项目配置中的分类法参数,遍历 taxonomyCloud
列出的全部分类法;如果没有设置 taxonomyCloud,则遍历页面定义的全部分类法。
分类法的多语言支持
对于多语言站点,分类法术语只会在各自语言站点内计数和链接。分类法配置参数也可以按语言分别调整。
7 - 分析、用户反馈与 SEO
OINK 默认不会连接分析、表单、评论或广告服务。这些集成属于站点决策:必须显式启用、记录数据边界,并根据用户与站点所在司法辖区提供必要的同意机制或政策说明。
添加分析
Hugo 为分析服务提供嵌入模板。站点配置 Google Analytics 后,页面浏览量与自定义事件等浏览器使用信息会发送给 Google。这与完全网络隔离的运行环境不兼容,也可能不符合严格的同源内容安全策略(CSP)。
配置
取得站点的 Google Analytics measurement ID,然后使用 Hugo 当前的服务配置:
services:
googleAnalytics:
id: G-YOUR-ID
不要同时设置已经弃用的顶层 googleAnalytics 键。通常只有 Hugo production
环境才会输出分析代码。发布前,请构建生产预览,并检查 HTML 与浏览器网络日志。
禁用分析后,OINK 不会发起 Google Analytics 请求。应彻底删除相关配置,而不是填写虚假 ID。
用户反馈
OINK 可以在文档页底部显示“本页是否有帮助?”小组件。它提供 是 与 否 两个操作,随后显示配置好的响应;响应通常包含创建文档 issue 的链接。

即使不启用分析,响应仍然可以发挥作用:它可以把读者引导到 issue 模板、讨论区、电子邮箱或站点自有的其他反馈渠道。只有站点配置了适当目标后,才会发生数据收集和事件上报。
反馈数据有什么用?
应结合上下文理解反馈,不能把单一分数当作结论。访问量高且反复收到负面反馈的页面是值得优先复查的候选;高评分页面则可能揭示值得在其他页面验证的模式。
应尽可能采用聚焦的编辑变更。例如,只更新一篇过时教程,或者把一小组页面的代码示例提前,然后在合适的时间范围内比较反馈。同时记录发布事件、流量变化、支持事件和其他可能解释变化的因素。
反馈只能提供方向性证据,不能取代用户研究、无障碍评审、支持数据或技术验证。
配置
OINK 默认关闭该小组件。请设置全局默认值,并配置本地化响应。英文配置如下:
params:
ui:
feedback:
enable: false
languages:
en:
params:
ui:
feedback:
yes: >-
Glad to hear it! Please <a
href="https://github.com/OWNER/REPOSITORY/issues/new">tell us how we
can improve</a>.
no: >-
Sorry to hear that. Please <a
href="https://github.com/OWNER/REPOSITORY/issues/new">tell us how we
can improve</a>.
简体中文字符串放在 languages.zh.params 下:
languages:
zh:
params:
ui:
feedback:
yes: >-
很高兴本页对你有帮助!欢迎<a
href="https://github.com/OWNER/REPOSITORY/issues/new">告诉我们如何继续改进</a>。
no: >-
很抱歉本页没有解决问题。请<a
href="https://github.com/OWNER/REPOSITORY/issues/new">告诉我们缺少什么</a>。
可见响应 HTML 属于可信站点配置。内容应保持精简,链接需要经过评审,并且不能插入不可信值。
配置 Google Analytics 后,小组件可以发送自定义 page_helpful 事件。正面操作使用
params.ui.feedback.max_value(默认为 100),负面操作使用 0。
访问反馈数据
使用 Google Analytics 时,可以在服务商的事件报告中查看
page_helpful,并按需创建页面级报告。没有事件并不一定表示没有用户反馈;也可能是分析被阻止或禁用、用户没有同意,或者所选时间范围不正确。
不要仅仅为了显示小组件就启用分析。站点可以保留响应和链接体验,同时关闭事件收集。
在单个页面覆盖反馈设置
在页面 Front Matter 中设置 feedback。页面设置可从任一方向覆盖全局默认值:
---
title: 反馈示例
feedback: true
---
全局默认开启时,可用 feedback: false 隐藏单个页面的小组件。为保持兼容,未设置
feedback 时,hide_feedback: true 仍会隐藏小组件。
设置所有页面的默认值
设置以下站点参数。OINK 默认值为
false;只有大多数文档页都应显示小组件时,才将其设为 true:
params:
ui:
feedback:
enable: false
使用 Fabform 添加联系表单
Fabform 和类似托管表单端点都是可选在线服务。创建账户并评审其数据处理方式后,站点可以把表单提交到分配的端点:
<form action="https://fabform.io/f/{form-id}" method="post">
<label for="email">电子邮箱</label>
<input id="email" name="email" type="email" autocomplete="email" />
<button type="submit">提交</button>
</form>
请替换
{form-id}、翻译可见标签、加入隐私说明,并提供错误与成功状态。该表单无法离线使用。如果站点必须让提交内容留在自身边界内,应优先使用本地或第一方端点。
搜索引擎优化元数据
OINK 会按以下优先级为每个页面选择 HTML meta description:
- 页面 front matter 中的
description; - 对于非索引页,使用 Hugo 计算出的页面摘要;
params中的站点描述。
请为每种语言编写精炼且针对当前页面的描述。不要把英文描述复制到中文页面。搜索元数据无法弥补内容单薄、重复或不准确的问题。
主题还会根据 Hugo 页面译文输出 canonical 与备用语言链接。请使用正确的生产
baseURL、稳定的译文路由和显式译文标题 ID。只有主题尚未提供某类 meta 标签时,才应通过站点的
layouts/_partials/hooks/head-end.html 覆盖添加。
底层服务与内容概念请参阅 Hugo 的 Google Analytics 配置、页面摘要和 Google 的 SEO 入门指南。
8 - 搜索
OINK 默认并推荐使用本地搜索。Hugo 会为每种语言生成独立索引;主题从同源资源提供 Lunr 及其 CJK 回退。站点无需公共爬虫、外部账户、CDN 或网络连接,即可完成构建和搜索。
Google Custom Search 与 Algolia DocSearch 仍作为兼容的在线集成保留。它们默认关闭;只有站点明确接受相应的外部请求、索引方式、可用性与隐私边界时,才应启用。
同一时间只能启用一种搜索实现。
使用 Lunr 的本地搜索
在 hugo.yaml 中启用本地搜索:
params:
offlineSearch: true
不要同时配置 gcs_engine_id 或
params.search.algolia。生产构建完成后,输出中会为每种语言生成一个索引,例如:
offline-search-index.en.json
offline-search-index.zh.json
浏览器加载当前语言的索引,并在不离开页面的情况下显示结果。中文内容使用 OINK 的 CJK 回退,不依赖以空格分词。
测试前构建索引
启动预览前先执行常规构建:
hugo --gc
hugo server --disableFastRender
如果索引变化时 server 已经在运行,请将其重启。对于子路径部署,请确认浏览器从配置的
baseURL 下请求索引,而不是从域名根目录请求。
配置结果摘要与数量限制
设置摘要长度和最大结果数:
params:
offlineSearch: true
offlineSearchSummaryLength: 120
offlineSearchMaxResults: 12
所选限制应确保搜索对话框在移动设备上保持流畅。摘要用于帮助发现内容,不能替代认真编写的页面描述。
排除页面
在页面 front matter 中设置 exclude_search: true:
---
title: Internal index
exclude_search: true
---
该设置适用于工具页、重复页、生成页或测试页。不要仅仅因为当前译文不完整就排除页面;应修复译文。
设置结果面板样式
结果面板会随内容扩展。站点可以在 assets/scss/_styles_project.scss 中限制宽度:
.td-offline-search-results {
max-width: 46rem;
}
覆盖搜索样式时,必须保留键盘焦点、可见选中状态、移动端宽度和深色模式对比度。
搜索入口
OINK 会在品牌外壳中提供搜索入口,也可以在侧栏显示输入框。如果要隐藏侧栏输入框,同时保留主搜索入口,请配置:
params:
ui:
sidebar_search_disable: true
外壳的打开与关闭控件会向辅助技术暴露对话框关系和状态。自定义实现必须保留这些语义。
多语言搜索
搜索始终停留在当前语言。请验证:
- 每种已发布语言都有自己的索引;
- 译文标题、描述和正文出现在对应索引中;
- 结果 URL 包含正确的语言前缀;
- 英文结果不会通过内容回退取代中文结果;
- 结果页上的语言选择器能前往对应译文,或按文档规则回退到语言首页。
中文搜索出现故障时,应先检查生成的中文 JSON,再考虑修改分词。索引缺失或只包含英文,通常属于内容或构建配置问题。
Google Custom Search(可选)
Google Custom Search Engine(GCSE)通过 Google 索引搜索公开站点。它需要已经部署且允许爬取的生产站点,并会把查询发送给第三方服务。
在 Google Programmable Search 中创建搜索引擎后,添加搜索结果页:
---
title: 搜索结果
layout: search
---
随后配置搜索引擎 ID:
params:
gcs_engine_id: YOUR_ENGINE_ID
offlineSearch: false
为每种支持语言创建译文结果页;必要时使用适合该语言的搜索引擎配置。删除
gcs_engine_id 即可禁用 GCSE。
消费站点应在隐私政策中说明外部请求和隐私影响。GCSE 无法在网络隔离部署中使用。
Algolia DocSearch(可选)
Algolia DocSearch 为符合条件的公开文档站点提供托管爬虫和交互式结果面板。取得项目的 application ID、搜索 API key 和索引名称后,配置:
params:
offlineSearch: false
search:
algolia:
appId: YOUR_APP_ID
apiKey: YOUR_SEARCH_API_KEY
indexName: YOUR_INDEX_NAME
只能使用公开的只读搜索 key,绝不能使用管理 key。爬虫规则、语言 facet、索引更新与外部服务声明应与站点配置一同维护。该集成有意与本地优先默认值分离。
可以覆盖主题 partial layouts/_partials/algolia/head.html 和
layouts/_partials/algolia/scripts.html,实现站点专属集成。空的覆盖文件会禁用对应主题 partial。
自定义搜索
如果现有选项都不合适,站点可以替换搜索输入、结果行为与样式。应尽量复用外壳的对话框与无障碍合同。除非自定义代码与服务商无关,并且能被多个产品复用,否则应保留在站点层。
自定义在线服务商必须显式启用,并说明网络、隐私、索引、故障与离线行为。自定义本地服务商必须从站点或主题发布全部运行时资源,并遵守语言和
baseURL 边界。
9 - 添加内容
OINK 沿用 Hugo 的内容模型:Markdown 承载信息,Front Matter 保存页面元数据,布局则把二者渲染成静态站点。本指南说明随项目提供的中英双语样例站采用的内容约定。
内容根目录
站点内容位于 content/ 目录下。多语言站点既可以分别使用
content/en/、content/zh/
等内容根目录,也可以在同一棵挂载目录中使用语言后缀。本仓库采用后一种形式:
content/docs/content/
├── adding-content.md
└── adding-content.zh.md
英文文件是源页面,.zh.md
文件是对应的简体中文译文。Hugo 解析语言后缀后,二者具有相同的逻辑路径。
生成文件以及必须逐字节复制的文件不应放入内容树,而应放入
static/;详见添加静态内容。
内容分区与模板
内容根目录下的每个一级目录都是 Hugo 分区。OINK 提供以下布局:
docs:带分区树、目录、面包屑、上一篇/下一篇导航和仓库链接的文档页;blog:带日期、分类元数据、Feed 和时间倒序列表的文章页;community:展示项目与贡献者链接的社区页;- 默认页面:不显示文档侧边栏的落地页。
Hugo 根据内容所属分区选择布局,因此 content/docs/ 下的页面会使用 docs
布局。只有确实要复用其他分区布局时,才在 Front Matter 中设置 type。
自定义分区
在内容根目录下新建目录;默认布局无法满足需求时,再为页面指定类型:
---
title: 架构决策
description: 项目已经采纳的设计决策。
type: docs
weight: 30
---
如果某项行为适用于整个分区,应在 _index.md 的 cascade
中设置共享值,避免每页重复。只有现有 OINK 布局与 Partial 均不适用时,才在项目的
layouts/ 下新增布局。
以文档为根的站点
EXPERIMENTAL
以文档为主的站点可以把 docs 分区发布到 URL 根路径,同时仍将源码保存在
content/.../docs/ 下:
permalinks:
page:
docs: /:sections[1:]/:slug/
section:
docs: /:sections[1:]
此时,文档分区落地页会成为站点首页。请为每种语言的物理站点根索引添加以下 Front Matter,使其仍可作为链接使用,同时不会争抢相同的输出路径:
build: { render: link }
检查路径冲突
文档会与博客、社区及其他分区共享 URL 根路径。构建时启用
--printPathWarnings,并在发布前解决所有重复目标:
hugo --printPathWarnings
旧版纯文档配置
旧版 Docsy 示例曾通过 Front Matter 的 cascade
强制设置页面类型。迁移到基于永久链接的文档根配置时,应删除这项变通设置,否则首页与分区布局可能出现不一致的解析结果。
页面 Front Matter
Front Matter 是用 YAML、TOML 或 JSON 编写的页面元数据。OINK 样例站使用 YAML:
---
title: Local-first architecture
linkTitle: Local-first
description: How OINK removes browser and build-time CDN dependencies.
weight: 20
date: 2026-08-08
tags: [architecture, offline]
---
title 是实际所需的最小字段。对于持续维护的文档,还应提供简洁的 description
供搜索和页面元数据使用;顺序有意义时应设置
weight。只有导航标签需要更短文本时才使用 linkTitle。
译文应翻译面向读者的元数据,同时保留结构性取值:
---
title: 本地优先架构
linkTitle: 本地优先
description: OINK 如何消除浏览器端与构建期的 CDN 依赖。
weight: 20
date: 2026-08-08
tags: [架构, 离线]
---
不要翻译字段名、短代码名称、配置项、文件路径或稳定标识符。
页脚元数据
文档页与博客页会在站点页脚上方显示紧凑的元数据区域。最后修改日期取自 Hugo 的
.Lastmod 值;以下两个可选 Front Matter 字段用于补充来源说明:
lastmod: 2026-08-09
upstream_attribution: https://upstream.example/docs/page/
downstream_modified: true
upstream_attribution 链接到上游原文及其署名信息;downstream_modified: true
表示下游项目修改过本页。某项说明不适用时,请省略对应字段。
页面正文
除非布局确实要求 HTML,否则页面应使用 Markdown。Hugo 通过 Goldmark 渲染 Markdown,并支持属性、脚注、表格、任务列表、渲染钩子和围栏代码块。
Markdown
即使脱离渲染后的站点,源码也应保持可读:
- 使用 ATX 标题(
## 标题); - 列表、块和围栏代码前后保留空行;
- 代码语言已知时必须标注;
- 使用能说明去向的链接文本和图片替代文本;
- 普通正文按便于审阅的宽度换行,但不要重排代码或 URL。
OINK 为块引用告警以及 Mermaid、数学公式、化学公式、Markmap 和 PlantUML 代码块提供渲染钩子。详见图表与公式。
标记、短代码与内容功能
普通正文优先使用标准 Markdown。需要标签页、卡片、终端录像、API 查看器或安全图表等有实际行为的组件时,再使用短代码。短代码属于内容契约的一部分:应在两种语言中核对其参数,不要把渲染后的 HTML 复制到译文。
告警
OINK 支持 GitHub 风格的块引用告警,也支持可选的 Obsidian 风格标题:
> [!TIP]
>
> 每次发布前都要运行翻译审计。
> [!WARNING] 必须使用稳定锚点
>
> 译文标题必须保留英文页面渲染后的 ID。
语义类型包括 NOTE、TIP、IMPORTANT、WARNING 和
CAUTION,以及与 Bootstrap 兼容的类型和
NB。告警应节制使用:关键信息在屏幕阅读器和打印版中也必须成立。外观设置参见告警。
链接
稳定公开路由使用根路径相对链接,相邻页面或页面包资源使用普通相对链接。Hugo 的
ref 与 relref 短代码可以校验内容引用,并处理语言和永久链接规则:
[配置]({{< ref "/docs/oink/configuration" >}})
编写双语页面时:
- 链接到逻辑页面,不要直接链接
.zh.md文件名; - 片段 ID 应保持语言中立;
- 验证两种语言能否解析到相同片段;
- 目标必须相对于当前主机时使用
relref。
调整路由或标题后,应运行站内链接检查。
内容风格
任务型文档应使用直接、明确的语言:先介绍概念,再给出配置;明确说明默认值;区分本地构建验证、部署与正式发布。中文版遵循
oink.pgsty.com/TRANSLATION.md 中的术语与排版规则。
页面包
独立页面只有一个 Markdown 文件;叶子页面包则由 index.md 和页面资源组成:
content/docs/tutorial/
├── index.md
├── index.zh.md
├── architecture.svg
└── example.yaml
两种语言的页面可以共用同一图片和下载文件。在单主机多语言站点中,Hugo 通常会在语言版本之间共享页面资源,因此不要复制完全相同的二进制资源。只有图片包含需要翻译的文字时才制作本地化版本,并为资源添加清晰的语言后缀。
包含子页面的分区使用分支页面包(_index.md),带资源的末端页面使用叶子页面包(index.md)。
添加文档与博客文章
每个持续维护的英文页面都应在同一目录下配有中文页面:
guide.md
guide.zh.md
页面包则将 index.md 与 index.zh.md
配对。除非语言差异确有必要,否则二者的路由元数据、日期、权重、别名和资源声明应保持一致。
组织文档
目录应反映读者看到的信息架构,而不是实现代码的包结构。每个文档子分区都需要
_index.md 与 _index.zh.md。子页面会按 weight
排列在侧边栏中,权重相同时再使用配置的后备顺序。
层级应尽量浅。页面面向独立任务或受众时才拆分,不要仅仅因为文件较长而拆分。详见组织内容。
文档分区落地页
文档分区的 _index.md 默认会渲染子页面摘要。使用:
simple_list: true
可以改为紧凑列表;使用:
no_list: true
可以关闭自动列表。每种语言都应提供本地化标题和描述,并保持结构选项一致。
组织博客文章
博客文章既可以直接放在 blog/
下,也可以按年份或分类建目录。OINK 使用日期目录,并为每篇文章配对:
blog/2026/
├── oink-release.md
└── oink-release.zh.md
文章通常包含:
---
title: OINK 1.0
description: A local-first Docsy distribution.
date: 2026-08-08
author: OINK maintainers
tags: [release]
---
不同语言版本的发布日期与作者身份应保持一致。标题、描述、分类标签、图注和正文需要翻译;提交 ID、发布标签、命令和 URL 不应翻译。
使用一级落地页
默认布局适用于首页、产品概览和其他不需要文档侧边栏的入口页。
自定义样例站页面
随项目提供的首页是 content/_index.md,其中文译文是
content/_index.zh.md。它与 OINK 其余页面使用同一套本地资源和主题流水线。品牌调整应修改站点内容与项目资源,不要为了品牌外观去编辑已经纳管的运行时文件。
构建自己的落地页
使用标准 Markdown 和blocks/* 短代码组合落地页。关键信息必须保留为文本,行动链接应说明实际去向,并在两种语言中分别测试移动端和桌面端布局。
添加社区页面
创建 community/_index.md 和 community/_index.zh.md。社区布局会读取
params.links.user 与 params.links.developer:
params:
links:
user:
- name: 用户论坛
url: https://community.example.org/
icon: fa-solid fa-comments
desc: 提问并分享解决方案
developer:
- name: GitHub
url: https://github.com/pgsty/oink
icon: fa-brands fa-github
desc: 源码、议题与拉取请求
条目可以设置 rel;对于外部 HTTP 链接,OINK 也会按需补充
noopener。贡献指南不在约定的文档路径时,请在社区页 Front Matter 中设置
params.contributingUrl。
添加静态内容
static/ 下的文件不会经过 Markdown 渲染或指纹处理,而是原样复制到发布根目录:
static/reference/api/index.html
会发布为
/reference/api/index.html。该目录适合外部生成的参考站点、验证文件以及要求稳定文件名的下载内容。需要缩放、指纹或页面包相对寻址的资源,应优先使用页面资源或 Hugo
Pipes。
OINK 的浏览器运行时有意从主题或站点自身提供。新增依赖库时,必须本地纳管并锁定版本,在
theme/VENDOR.json 中登记,而且不得引入隐式 CDN 后备地址。
RSS Feed
Hugo 会为首页和列表分区生成 Feed。只有站点确实没有 Feed 消费者时才全局关闭:
disableKinds: [RSS]
分区声明自定义输出格式时,应显式保留 RSS:
outputs:
section: [HTML, RSS, print]
检查每种语言生成的 Feed URL,并核对标题、摘要、日期、规范 URL 与 hreflang
关系。
站点地图
Hugo 默认生成 sitemap.xml。站点级设置如下:
sitemap:
changefreq: monthly
filename: sitemap.xml
priority: 0.5
页面可以覆盖这些值:
---
title: 发布说明
sitemap:
priority: 0.8
---
应把 changefreq 与 priority
视为提示而非承诺。部署前应排除草稿、私有内容和非规范副本,并检查每种发布语言生成的站点地图。
10 - 图表与公式
OINK 支持 KaTeX、Mermaid、Markmap、PlantUML 和 Diagrams.net。KaTeX、Mermaid 与 Markmap 使用构建期能力或主题随附的同源资源。PlantUML 和 Diagrams.net 编辑器需要显式配置服务端点;主题不会静默使用公共服务。
使用 KaTeX 支持 LaTeX
KaTeX 可以在 Web 上渲染 TeX 数学公式。Hugo 内置的 KaTeX 支持可以在构建期间渲染公式,因此读者不需要连接远程数学服务。
行内公式
行内公式使用 Goldmark 中配置的 passthrough 分隔符。条件允许时,应把公式前后的空格与标点留在公式之外。
独立显示公式
使用 math 代码块独立显示公式:
```math
E = mc^2
```
启用 KaTeX 支持
math 与 chem
代码块会自动使用主题渲染钩子。对于行内公式和使用分隔符的公式,请启用 Goldmark 的
passthrough 扩展,并设置适合站点的分隔符。随仓库提供的 oink.pgsty.com
配置展示了方括号、双美元符号和圆括号分隔符。
启用 passthrough 扩展
相关 YAML 结构如下:
markup:
goldmark:
extensions:
passthrough:
enable: true
delimiters:
block: []
inline: []
请根据 Hugo 文档填写分隔符数组。所选分隔符不能与站点正文或代码冲突,并且必须在所有构建环境中保持一致。
添加 passthrough 渲染钩子
对于使用分隔符的数学公式,请在站点中创建
layouts/_markup/render-passthrough.html:
{{ partial "scripts/math.html" . }}
也可以把钩子放在对应布局目录下,将其限制到某种内容类型或某个分区。限制作用域可以避免把无关内容当作数学 passthrough 处理。
化学方程式与物理单位
Hugo 内置 KaTeX 支持 mhchem 扩展。化学方程式可以使用 chem
代码块;同一扩展也支持物理单位。方程式与单位语法请参阅 mhchem 手册。
使用 Mermaid 绘图
Mermaid 可以在浏览器中把文本定义转换为图表。使用 mermaid 代码块:
```mermaid
flowchart LR
源码 --> Hugo --> 静态文件
```
flowchart LR 源码 --> Hugo --> 静态文件
主题会检测代码块、发布固定版本的本地 Mermaid 运行时,并且在该页只加载一次。不使用 Mermaid 的页面不会加载运行时。
站点级 Mermaid 设置位于 params.mermaid:
params:
mermaid:
theme: neutral
flowchart:
diagramPadding: 6
每幅图也可以通过 Mermaid 支持的 front matter 覆盖设置。图表源码应保持可读,并同时测试深浅色模式。对于图表无法渲染时仍必须传达的信息,请提供相邻正文。
使用 PlantUML 绘制 UML 图
PlantUML 支持时序图、用例图、类图、状态图和其他面向 UML 的图表。plantuml
代码块包含图表源码:
```plantuml
actor Reader
participant Browser
participant "PlantUML endpoint" as Server
Reader -> Browser: Open page
Browser -> Server: Request encoded diagram
Server --> Browser: SVG
```
PlantUML 需要渲染端点。只有在配置了获准使用的本地或显式远程服务后才应启用:
params:
plantuml:
enable: true
theme: default
svg_image_url: https://plantuml.internal.example/plantuml/svg/
svg: false
浏览器会把编码后的图表源码发送给端点。请评审其保密性、可用性、CSP 与离线影响。网络隔离站点应使用内部端点或提交预渲染图片,默认配置不能指向公共演示服务器。
使用 Markmap 支持思维导图
Markmap 可以把 Markdown 大纲转换为交互式思维导图:
```markmap
# 本地优先
## 构建
- Hugo Extended
## 浏览器
- 本地脚本
- 本地字体
```
# 本地优先
## 构建
- Hugo Extended
## 浏览器
- 本地脚本
- 本地字体需要时可以全局启用:
params:
markmap:
enable: true
运行时采用固定版本并从本地提供。底层大纲本身也应有用,同时不要依赖只能通过指针完成的交互。
使用 Diagrams.net 绘图
Diagrams.net(draw.io)可以导出包含可编辑图表副本的 SVG 与 PNG。显式配置编辑器端点后,OINK 可以检测这些图片并显示
编辑 操作。
params:
drawio:
enable: true
drawio_server: https://drawio.internal.example/
导出时请启用 Include a copy of my diagram。页面可以离线显示导出图片,但打开编辑器需要连接配置的服务。编辑器保存时会把更新后的文件下载到浏览器,不会直接写入文档仓库。
公共 Diagrams.net 端点属于在线集成。如果编辑过程必须留在组织内部,请部署获准使用的自托管编辑器,并让
drawio_server 指向它。
资源与创作检查清单
- 当可评审 diff 很重要时,优先使用文本图表。
- 为关键信息提供替代文字或相邻正文。
- 测试深浅色、移动端、打印和减少动态效果模式。
- 在
theme/VENDOR.json中固定本地运行时,并且只在使用时加载。 - 绝不能把机密写入会发送给服务端点的图表源码。
- 无法接受在线渲染器时,使用预渲染输出。
- 在子路径
baseURL下验证所有资源与端点 URL。
11 - 外观与风格
OINK 在 Bootstrap 与 Docsy 基础上提供完整的视觉系统,并将字体、图标、样式和浏览器端代码全部本地化。使用方无需重建 Node 依赖树,就能通过设计变量和项目样式完成定制。
项目样式
Hugo Extended 通过 Hugo Pipes 编译主题 SCSS。项目覆盖项会进入同一个资源包,因此生产构建可以对一份同源样式表完成压缩、指纹和完整性校验。
项目样式文件
在站点的 assets/scss/ 目录中覆盖以下文件:
| 文件 | 用途 |
|---|---|
_variables_project.scss | 在 Bootstrap 与 OINK 默认值之前设置变量 |
_variables_project_after_bs.scss | 设置依赖 Bootstrap 定义的变量或映射 |
_styles_project.scss | 在主题组件样式之后加载项目选择器 |
先从最小覆盖项开始:
// assets/scss/_variables_project.scss
$primary: #315f8f;
$secondary: #b4762e;
// assets/scss/_styles_project.scss
.td-content {
--td-content-max-width: 78ch;
}
普通品牌定制不要直接修改纳管的 Bootstrap、Font Awesome 或本地字体文件。主题更新会覆盖这些改动,也会模糊依赖边界。
高级样式定制
OINK 的 SCSS 导入顺序如下:
- Bootstrap 函数;
- 项目变量;
- OINK 默认值与 Bootstrap;
- Bootstrap 之后的项目变量;
- OINK 组件与本地品牌层;
- 项目样式。
稳定的设计决策应通过变量或 CSS 自定义属性表达。没有合适设计变量时才覆盖选择器,而且作用域应尽量缩小到具体组件。许多颜色会随主题变化,因此必须检查浅色与深色输出。
⚠️ 重置内部样式
OINK 的内部 Partial 并不是公开 Sass API。单独导入或屏蔽内部文件会让站点耦合到仓库布局和导入顺序。产品确实需要完全不同的页面框架时,应覆盖 Hugo 布局或有意识地维护主题分支,而不是重置整份样式表。
额外样式
隔离的第三方 CSS 可以通过钩子发布为本地资源:
{{ $extra := resources.Get "css/extra.css" | minify | fingerprint }}
<link rel="stylesheet" href="{{ $extra.RelPermalink }}"
integrity="{{ $extra.Data.Integrity }}" crossorigin="anonymous">
将模板放在
layouts/partials/hooks/head-end.html。如果规则属于站点设计系统,应优先写入项目 SCSS 文件。绝不能把远程样式表当作隐式后备资源。
颜色与颜色主题
主题各处都可以使用 Bootstrap 语义颜色与 OINK 品牌设计变量。语义名称比具体色值更能说明用途。
站点颜色
在编译前设置 Bootstrap 变量:
$primary: #315f8f;
$secondary: #b4762e;
$success: #2c7a4b;
$warning: #9a6700;
$danger: #b42318;
OINK 的标准品牌层还公开
--td-brand-elev、--td-brand-silk、--td-brand-copper、--td-brand-header-bg
和 --td-brand-mark-gradient 等 CSS 属性。应同时在 :root 与
[data-bs-theme='dark'] 中成对覆盖:
:root {
--td-brand-copper: #a66722;
}
[data-bs-theme='dark'] {
--td-brand-copper: #e0a35c;
}
浅色/深色主题与模式支持
颜色 主题 是组件采用的配色方案,颜色 模式
则是整个站点当前处于浅色还是深色状态。OINK 使用 Bootstrap 的
data-bs-theme="light|dark"
属性,并把读者明确选择的模式保存在浏览器本地存储中。没有明确选择时,站点跟随
prefers-color-scheme。
每个自定义组件都必须为两种模式定义可读状态,包括悬停、焦点、禁用、选中和代码颜色。不能只用颜色传递含义。
浅色/深色模式
样例站默认启用颜色模式支持并显示选择器:
params:
ui:
showLightDarkModeMenu: true
选择器会在页面进入正常交互前更新文档,以减少错误主题闪烁。OINK 的脚本从本地加载,不会联系外部服务。
为站点选择主题或颜色模式
多数站点应使用默认自动行为。只有完整视觉系统已经在某种模式下通过测试,而且读者确实不需要另一种模式时,才应强制指定。截图不足以完成验证:还要检查真实正文、表格、告警、表单、图表、代码和焦点指示器。
禁用深色模式
如需禁用深色模式并隐藏菜单:
params:
ui:
showLightDarkModeMenu: false
实验值 enable-only (experimental)
会启用主题感知样式,但不显示选择器。该配置面仍可能变化,只能作为过渡选项使用。
选择具有良好对比度的颜色
所有组件状态都应满足 WCAG 对比度要求,并以浏览器实际计算后的颜色为准,包括叠加在图片上的半透明图层。作为工作基线,普通文字的对比度至少为 4.5:1,大号文字至少为 3:1;焦点和非文本界面指示器同样需要足够对比度。自动化工具可以发现常见问题,但仍需进行键盘和人工视觉审查。
字体
OINK 不会拉取 Google Fonts。主题使用的 Open Sans、Chakra Petch、IBM Plex
Mono 与 Font Awesome 字体文件均保存在本地。由于历史原因,旧版 Sass 变量
$td-enable-google-fonts 实际控制的是随主题提供的 Open Sans 字体。
在 _variables_project.scss 中设置字体:
$td-enable-google-fonts: true;
$font-family-sans-serif: 'Noto Sans SC', 'Open Sans', system-ui, sans-serif;
$font-family-monospace: 'IBM Plex Mono', ui-monospace, monospace;
新增字体时,应制作所需子集并自行托管,包含必要字形,设置
font-display: swap,在 theme/VENDOR.json
中记录许可证,并测试 CJK 后备字体。页面渲染不能依赖字体 CDN。
CSS 工具类
在允许原始 HTML 的 Markdown 和布局中可以使用 Bootstrap 工具类。内容优先使用语义化 Markdown 与 OINK 短代码;工具类只适合在不同断点下仍易于理解的小范围表现调整。项目级模式应写入
_styles_project.scss。
代码块
OINK 默认支持 Hugo Chroma,并提供本地纳管的 Prism 兼容选项。一个站点应统一选择一种高亮器;同时启用会产生重复标记或样式。
使用 Chroma 进行代码高亮
Chroma 在 Hugo 构建期间运行,不需要浏览器端高亮器。代码块应指定语言:
```go
fmt.Println("hello")
```
Chroma 基础样式配置
在 Hugo 中配置标记渲染:
markup:
highlight:
guessSyntax: false
noClasses: false
lineNos: false
OINK 使用基于 class 的输出,以便浅色和深色模式采用不同样式。重新生成配色时,应将 CSS 保存在本地,并结合品牌背景完成审查。
浅色/深色代码样式及其他配置
主题在 theme/assets/scss/td/chroma/
中提供两套 Chroma 配色,并按模式应用。项目覆盖项应在相应主题属性下定位
.chroma,不要硬编码全局背景。
选择控制台代码块内容
终端记录使用
console。OINK 会调整提示符和输出的选中行为,使读者复制命令时不会带上装饰性提示符。命令与输出应各占一行,而且不能只靠颜色区分。
未指定语言的代码块
没有标签的围栏会渲染为纯代码。只有确实不存在相应语法时才这样做;命令会话应标为
console 或 bash,不要让 Chroma 猜测。
复制到剪贴板
除非 params.disable_click2copy_chroma
为 true,否则 Chroma 会显示复制按钮。已部署站点中的剪贴板访问需要安全上下文。该控件必须支持键盘操作,而且不应复制行号或提示符。
使用 Prism 进行代码高亮
设置:
params:
prism_syntax_highlighting: true
即可使用 OINK 本地提供的 prism.js 与
prism.css。这是面向既有站点的兼容选项;若要尽量减少浏览器负担,优先使用 Chroma。
没有语言的代码块
Prism 同样会把没有标签的代码块当作纯文本。应补充正确的语言 class,而不是启用启发式检测。
扩展 Prism 语言或插件
构建并纳管准确的 Prism 资源包,通过受控主题变更替换本地文件,记录版本与许可证,并添加覆盖该语言或插件的 Fixture。运行时不得从 CDN 拉取 Prism 组件。
导航栏
OINK 导航栏包含项目标识、主菜单、按需显示的版本与语言选择器、颜色模式控件以及搜索。小屏幕上,溢出的主菜单项仍可通过横向滚动访问。
默认外观
导航栏使用本地品牌配色和固定的最小高度。
移动端
品牌与操作控件保持可见,主菜单可以滚动。应测试较长的中文标签、200% 缩放、触控目标、焦点顺序以及两种页面方向。
桌面端
主菜单在一行内展开;版本、语言、模式和搜索控件保持分组。不要添加过多自定义入口,以免把控件挤出视口。
覆盖图上的默认半透明效果
blocks/cover
短代码会把导航栏标记为覆盖图感知状态。导航栏起初为半透明,页面滚动后恢复常规背景。
自定义导航栏
行为通过配置调整,表现通过项目 SCSS 调整。覆盖导航栏 Partial 时,必须保留导航地标、焦点顺序、无障碍标签和响应式溢出行为。
导航栏高度
在主题样式编译前覆盖
$td-navbar-min-height。锚点偏移、侧边栏高度、移动端换行和覆盖图都依赖该值,因此必须重新测试。
背景颜色与透明度
在两种模式下分别设置 --td-navbar-bg-color 或
--td-brand-header-bg。背景为半透明时,应在所有覆盖图上验证对比度,并为滚动状态提供不透明背景。
设置导航栏浅色/深色主题
覆盖图需要浅色前景控件时,页面可以在 Front Matter 或 cascade 中设置
ui.navbar_theme: dark。这只会调整导航栏组件样式,不会强制改变整个站点的颜色模式。
自定义覆盖图上的半透明效果
可以在站点级禁用半透明:
params:
ui:
navbar_translucent_over_cover_disable: true
覆盖图不可预测,或无障碍审查无法保证对比度时,应优先关闭该效果。
设置项目徽标与名称样式
徽标 Partial 覆盖项放在 layouts/partials/,源资源放在 assets/ 或
static/。具有信息含义的标志应提供有意义的替代文本;纯装饰标志应使用空替代文本。SVG 必须包含 view
box,并为两种模式继承或定义颜色。
OINK 样例使用带本地渐变效果的文字标识。站点标题在语言配置中修改,视觉变量在项目 SCSS 中修改;可选择的文字能够胜任时,不要用图片替代品牌名称。
浅色/深色模式菜单
params.ui.showLightDarkModeMenu
为 true 时显示选择器。应把它留在共享导航中,使颜色状态在所有语言和页面类型中保持一致。
告警
Markdown 告警类型会映射到语义化 OINK/Bootstrap 样式。.alert-*
与告警渲染钩子应成对调整,保留可见标签或图标,并测试每种背景中的链接和行内代码。语法参见添加内容。
表格
Markdown 表格具有响应式和主题感知样式。单元格应保持简洁,表头应使用真正的标题单元格;需要上下文时可在自定义 HTML 中添加标题,并在移动端测试横向溢出。不能用表格布局互不相关的内容。
自定义模板
Hugo 会优先解析站点布局,再解析主题布局。只复制确实需要修改的最小 Partial,并在同步上游时进行对比;覆盖完整
baseof.html 可能会悄然遗漏后续的无障碍与资源流水线修复。
在 head 或 body 末尾添加代码
Head 附加内容使用 layouts/partials/hooks/head-end.html,脚本或结束集成使用
layouts/partials/hooks/body-end.html。资源应自行托管,只在需要的页面加载,并与生产 CSP 保持兼容。
在页面正文前添加横幅
根据页面参数设置条件,并覆盖相应钩子或内容 Partial。横幅不得遮挡页面标题、困住键盘焦点,也不能把锚点目标挤到固定导航下方。
为 body 元素添加自定义 class
在页面 Front Matter 或分区 cascade 中设置 body_class:
---
body_class: product-reference
---
OINK 会把该值追加到自动生成的 body class。请使用项目专属且有语义的名称,绝不能向该字段写入不可信内容。
12 - 文档版本管理
根据项目的发布和版本管理方式,你可能需要让用户访问旧版文档。旧版本的具体部署方式由你决定。本页介绍 OINK 提供的功能:在各个文档版本之间导航,并在归档站点上显示信息横幅。
添加版本下拉菜单
如果在 hugo.toml、hugo.yaml 或 hugo.json 中添加
[params.versions],OINK 会在顶部导航栏加入版本下拉选择器。请为每个需要加入菜单的版本指定 URL 和名称,例如:
# Add your release versions here
[[params.versions]]
version = "master"
url = "https://master.kubeflow.org"
[[params.versions]]
version = "v0.2"
url = "https://v0-2.kubeflow.org"
[[params.versions]]
version = "v0.3"
url = "https://v0-3.kubeflow.org"params:
versions:
- version: master
url: 'https://master.kubeflow.org'
- version: v0.2
url: 'https://v0-2.kubeflow.org'
- version: v0.3
url: 'https://v0-3.kubeflow.org'{
"params": {
"versions": [
{
"version": "master",
"url": "https://master.kubeflow.org"
},
{
"version": "v0.2",
"url": "https://v0-2.kubeflow.org"
},
{
"version": "v0.3",
"url": "https://v0-3.kubeflow.org"
}
]
}
}别忘了加入当前版本,这样用户才能返回!
版本下拉菜单的默认标题是 Releases。要修改标题,请在 hugo.toml、hugo.yaml
或 hugo.json 中调整站点参数 version_menu:
[params]
version_menu = "Releases"params:
version_menu: Releases{
"params": {
"version_menu": "Releases"
}
}如果把 version_menu_pagelinks 参数设为
true,版本下拉菜单会链接到其他版本中的当前页面,而不是它们的首页。如果文档在不同版本之间变化不大,这项功能会很有用。请注意:如果当前页面在另一版本中不存在,链接就会失效。
还可以分别配置每个菜单项:
- 如果菜单标签不是版本号,使用
name代替version。 - 将
name设为---可添加菜单分隔线。 - 省略
url可渲染禁用的文本项,例如分组标题。 - 设置
kind可添加与类型对应的 CSS 类。详情请参阅导航与菜单。 - 即使全局
version_menu_pagelinks参数为true,仍可在某个菜单项上设置pagelinks: false,让它始终链接到该版本首页。
例如:
params:
version_menu: v1.2
version_menu_pagelinks: true
versions:
- name: '**Versions**'
- version: v1.3-dev
kind: next
url: https://next.example.com
- version: v1.2
kind: latest
url: https://docs.example.com
- name: ---
- name: Preview variant
kind: home
pagelinks: false
url: https://preview.example.com
要进一步了解 OINK 菜单,请参阅导航与菜单。
在归档文档站点显示横幅
如果为旧版文档创建归档快照,可以在归档文档的每个页面顶部添加提示,告诉读者他们正在查看不再维护的快照,并提供指向最新版本的链接。
例如,可以查看 Kubeflow v0.6 归档文档:

要在文档站点加入横幅,请在 hugo.toml、hugo.yaml 或 hugo.json
中完成以下修改:
将站点参数
archived_version设为true:[params] archived_version = trueparams: archived_version: true{ "params": { "archived_version": true } }将站点参数
version设为归档文档集的版本。例如,如果归档文档对应 0.1 版:[params] version = "0.1"params: version: 0.1{ "params": { "version": "0.1" } }确认站点参数
url_latest_version包含希望读者前往的网站 URL。大多数情况下,它应该是最新版文档的 URL:[params] url_latest_version = "https://your-latest-doc-site.com"params: url_latest_version: https://your-latest-doc-site.com{ "params": { "url_latest_version": "https://your-latest-doc-site.com" } }
13 - AI 智能体支持
本页介绍的功能仍处于实验阶段,适合早期采用和评估。后续版本可能会调整输出细节和验证范围。要跟踪智能体支持功能的阶段性演进,请参阅 Improve support for AI-agent doc consumption #2614。
功能
站点显式启用后,OINK 会提供以下面向用户和机器可读的行为:
- 支持 Markdown 输出格式。项目的
outputs配置决定哪些页面类型发布 Markdown。 - 发现机制:页面 HTML 的 header 会包含指向该页 Markdown 版本的
rel="alternate"链接。 - 查看 Markdown:页面元信息区域会显示指向 Markdown 版本的“查看 Markdown”链接。
llms.txt:位于站点根目录的内容清单文件。
本页其余部分介绍如何启用各项功能,并结合示例讨论相应的验证与指标。
启用 Markdown 输出
Hugo 提供多种内置输出格式,其中包括
markdown。要启用 Markdown 输出,请在 Hugo 的 outputs 配置中,把 markdown
加入需要支持的页面类型。例如:
outputs:
home: [HTML, markdown]
page: [HTML, markdown]
section: [HTML, RSS, print, markdown]
[outputs]
home = [ "HTML", "markdown" ]
page = [ "HTML", "markdown" ]
section = [ "HTML", "RSS", "print", "markdown" ]
{
"outputs": {
"home": ["HTML", "markdown"],
"page": ["HTML", "markdown"],
"section": ["HTML", "RSS", "print", "markdown"]
}
}
让页面退出 Markdown 输出
默认情况下,无论 Hugo 的 outputs 映射位于多文件站点配置还是页面 front
matter 中,它都会对每种页面类型执行 完整替换,而不是合并1。添加
markdown 时,请保留站点已经依赖的所有格式,例如以上示例中分区使用的 RSS 和
print。
如果要让某些页面不输出 Markdown,请在页面 front matter 中把 outputs 设为仅
HTML,或者在排除 markdown 的同时列出该页原本的全部默认输出格式。例如:
---
title: HTML-only test page
outputs: [HTML]
---
...
启用 llms.txt
llms.txt
是一种简单的文本格式,用来列出指向站点机器可读内容的链接。智能体可以轻松发现和解析它,它也能补充信息更丰富但结构更复杂的 Markdown 输出。进一步了解请参阅
llmstxt.org。
OINK 会在站点根目录生成
llms.txt,其中包含首页、主菜单页面,以及存在时的 Markdown 备用版本链接。要启用它,请在 Hugo 的
outputs 配置中为首页添加 LLMS。例如:
outputs:
home: [HTML, markdown, LLMS]
page: [HTML, markdown]
section: [HTML, RSS, print, markdown]
本站生成的 llms.txt 示例请参阅 /llms.txt。
自定义输出
OINK 通过 layouts/all.md 渲染 Markdown 输出,并通过 layouts/index.llms.txt
生成 llms.txt。你可以在多个层级覆盖默认行为:
- 按类型:在项目的
layouts/下添加home.md或_default/single.md等模板,为特定 Hugo 类型定制 Markdown 输出。 - 按短代码:为项目本地短代码添加输出格式专属短代码模板,使其在适当场景输出便于 Markdown 使用的内容。
- 按页面:为需要精心设计智能体视图的高价值页面提供专属内容或结构。
服务端支持
虽然不属于 OINK 的支持范围,站点仍可通过服务端内容协商,帮助智能体发现和访问 Markdown 内容。例如,在与 HTML 相同的 URL 上响应
Accept: text/markdown。
验证与指标
我们使用 AFDocs
评估面向智能体内容的基础结构支持,并验证生成的输出是否满足配置的检查项。我们也鼓励站点针对智能体访问模式实现自己的监控和指标,例如记录对 Markdown
URL 或 llms.txt
的请求,并统计其使用情况。详情请参阅智能体支持检查。
oink.pgsty.com 项目包含 AFDocs
配置和 npm 脚本,维护者可据此对已部署 URL 评分。这些检查与 OINK 的智能体支持目标有重合,包括 Markdown
URL、llms.txt 和相关类别。
评分表示例
评分表示例包括:
OpenTelemetry 智能体评分在线报告;
本站的 AFDocs 评分表:
oink.pgsty.com评分表Running in oink.pgsty.com…
Agent-Friendly Docs Scorecard
http://localhost:1313 · 4/26/2026, 5:43:59 AM
Overall Score: 100 / 100 (A+)
Category Scores: Content Discoverability 100 / 100 (A+) Markdown Availability 100 / 100 (A+) Page Size and Truncation Risk 100 / 100 (A+) Content Structure 100 / 100 (A+) URL Stability and Redirects 100 / 100 (A+) Observability and Content Health 100 / 100 (A+) Authentication and Access 100 / 100 (A+)
Check Results:
Content Discoverability PASS llms-txt-exists llms.txt found at 1 location(s) PASS llms-txt-valid llms.txt follows the proposed structure (H1, blockquote, heading-delimited link sections) PASS llms-txt-size llms.txt is 1,131 characters (under 50,000 threshold) PASS llms-txt-links-resolve All 13 same-origin links resolve (13 total links) PASS llms-txt-links-markdown 13/13 same-origin links point to markdown content (100%) PASS llms-txt-directive llms.txt directive found in all 13 pages, near the top of content Markdown Availability PASS markdown-url-support 13/13 pages support .md URLs (100%) PASS content-negotiation 13/13 pages support content negotiation (100%) Page Size and Truncation Risk PASS rendering-strategy All 13 pages contain server-rendered content PASS page-size-markdown All 13 pages under 50K chars (median 2K, max 9K) PASS page-size-html All 13 pages convert under 50K chars (median 2K, 0% boilerplate) Content Structure PASS tabbed-content-serialization No tabbed content detected across 13 pages PASS section-header-quality No tabbed content found; header quality check not applicable PASS markdown-code-fence-validity All 1 code fences properly closed across 14 pages URL Stability and Redirects PASS http-status-codes All 13 pages return proper error codes for bad URLs PASS redirect-behavior No redirects detected across 13 pages Observability and Content Health PASS cache-header-hygiene All 14 endpoints have appropriate cache headers Authentication and Access PASS auth-gate-detection All 13 pages are publicly accessible SKIP auth-alternative-access All docs pages are publicly accessible; no alternative access paths neededFull spec: https://agentdocsspec.com/spec/
这些检查的配置详情请参阅智能体支持检查。
这与 Hugo 文档描述的 front matter 配置行为不同,但截至 Hugo 0.158.0,我们的测试确认实际行为如此。 ↩︎