这是本节的多页打印视图。 .

返回本页常规视图.

高级特性

配置可视化、语言、搜索、版本与外部集成。

这些能力扩展了核心创作流程,包括多语言路由、搜索、版本导航、ECharts、信息图、评论、分析、代码仓库操作、AI智能体发现与打印输出。只启用符合站点受众、无障碍需求、隐私边界与运行环境的功能。

1 - 多语言支持

配置语言、译文、稳定链接与 RTL 布局。

OINK 使用 Hugo 的多语言页面模型,不依赖某个站点专属的域名或模板假设。随仓库提供的站点将英文设为首要语言,将简体中文(zh)设为第二语言。

配置语言

hugo.yaml 中定义默认语言与所有启用的语言:

defaultContentLanguage: en

languages:
  en:
    label: English
    locale: en-US
    weight: 1
    title: Product Documentation
    params:
      description: Product guides and reference
  zh:
    label: 简体中文
    locale: zh-CN
    weight: 2
    title: 产品文档
    params:
      description: 产品指南与参考资料
      time_format_default: 2006年1月2日
      time_format_blog: 2006年1月2日

weight 同时决定语言排序和选择器顺序。label 使用该语言自己的文字显示。locale 为 HTML、备用链接和 Open Graph 元数据提供符合标准的语言标签。

语言专属参数会覆盖全局值;未定义的参数继承全局值。菜单标签不同时,请在每种语言下分别定义菜单。

组织译文内容

Oink 项目站将译文并置保存:

content/docs/
├── install.md
└── install.zh.md

共同的基础文件名会让 Hugo 把这些文件识别为同一页面的不同译文。除非确实需要语言专属差异,否则日期、权重、别名、资源和影响路由的元数据应保持一致。

所有可见文本都需要翻译,包括 front matter 标题与描述、摘要、菜单标签、标签、图片替代文字、提示块和短代码参数。命令、标识符、配置键、文件名、URL 与产品名称应保持原样。

语言树规模很大且由不同团队独立维护时,也可以使用 Hugo 的语言专属 contentDir 模型。不要随意混用两种布局;应选定一种、写入规范,并验证 Hugo 如何关联译文。

自动标题 ID 取决于标题文字,因此翻译后通常会破坏共用的片段链接。请在译文中显式使用英文页面实际渲染出的 ID:

## Configure local search
## 配置本地搜索 {#configure-local-search}

必须检查渲染后的 HTML,不能凭规则猜测。内联 HTML、标点、徽章和短代码都可能影响 Hugo 生成的 ID。对应页面应具有相同的标题顺序和渲染 ID 列表。

语言选择器行为

语言选择器根据 Hugo 配置的站点和页面译文自动生成。只配置一种语言时隐藏;配置两种或更多语言时,统一显示一个语言图标按钮。直接点击会按 weight 顺序切换到下一种语言;悬停半秒或聚焦按钮则展示完整语言菜单。

对于每种目标语言,如果当前页面存在译文,选择器就会链接到该译文;如果不存在,则链接到目标语言首页,避免生成断链或冒充译文的路由。当前语言具有可见状态和 aria-current 状态。

SEO 与文档元数据

每个页面都会输出:

  • 正确的 HTML langdir 值;
  • 当前页面的规范 URL;
  • 为所有配置语言生成带 hreflangrel="alternate" 链接;
  • Open Graph locale 与备用 locale 元数据。

备用目标采用与可见选择器相同的“当前页面译文或目标语言首页”回退规则。请使用正确的生产 baseURL;OINK 支持子路径部署,布局中不得用硬编码绝对路径替代它。

从右向左语言

为 RTL 语言设置 direction: rtl

languages:
  ar:
    label: العربية
    locale: ar
    direction: rtl
    weight: 4

主题会加载已经提交的本地 Bootstrap RTL 产物,自有外壳则使用逻辑 CSS 属性。LTR 与 RTL 站点使用同一个命令:

hugo --gc --minify

消费站点不安装 RTLCSS、PostCSS 或 npm。测试时应使用真实 RTL 内容,并检查导航、代码、表格、图表和双向混排字符串,不能认为选中样式表就已足够。

UI 翻译包

主题 UI 字符串位于 i18n/。OINK 包含英文、简体中文、繁体中文,以及从上游继承的其他翻译包。站点可以创建自己的 i18n/<language>.yaml,只覆盖确实需要修改的字符串;其余值继续回退到主题翻译包。

翻译期间运行:

hugo server --printI18nWarnings

通用译文应贡献到主题中;产品专属语言应留在站点翻译包中。

分语言搜索

启用 offlineSearch: true 后,OINK 会为每种语言生成独立的同源索引。简体中文索引使用主题的 CJK 回退,搜索结果不会离开当前语言。

请验证 offline-search-index.en.jsonoffline-search-index.zh.json 均已生成,包含预期页面,并能在部署后的 baseURL 下正确解析。

翻译检查清单

  • 支持范围内的每个源页面都有对应 .zh.md 文件。
  • front matter 身份和路由元数据一致。
  • 可见正文、UI 字符串、替代文字和元数据均已翻译。
  • 每个中文 Markdown 标题都有显式稳定 ID。
  • 中英文渲染标题 ID 列表一致。
  • 站内链接与片段在两种语言中都能解析。
  • 导航、面包屑、上一页/下一页链接和搜索保持在当前语言。
  • 日期、标点、空格和技术术语符合目标语言的编辑规范。
  • 生产构建输出正确的 canonical 与备用语言元数据。

Hugo 底层模型请参阅多语言模式

2 - 搜索

配置本地多语言搜索,或显式启用在线服务商。

OINK 默认并推荐使用本地搜索。Hugo 会为每种语言生成独立索引;主题从同源资源提供 Lunr 及其 CJK 回退。站点无需公共爬虫、外部账户、CDN 或网络连接,即可完成构建和搜索。

Google Custom Search 与 Algolia DocSearch 仍作为兼容的在线集成保留。它们默认关闭;只有站点明确接受相应的外部请求、索引方式、可用性与隐私边界时,才应启用。

同一时间只能启用一种搜索实现。

使用 Lunr 的本地搜索

hugo.yaml 中启用本地搜索:

params:
  offlineSearch: true

不要同时配置 gcs_engine_idparams.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 Engine(GCSE)通过 Google 索引搜索公开站点。它需要已经部署且允许爬取的生产站点,并会把查询发送给第三方服务。

Google Programmable Search 中创建搜索引擎后,添加搜索结果页:

---
title: 搜索结果
layout: search
---

随后配置搜索引擎 ID:

params:
  gcs_engine_id: YOUR_ENGINE_ID
  offlineSearch: false

Google 搜索的暗色兼容样式默认不加载。启用 GCSE 时,请在消费站点的 assets/scss/_styles_project.scss 中显式导入:

@import 'td/gcs-search-dark';

为每种支持语言创建译文结果页;必要时使用适合该语言的搜索引擎配置。删除 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.htmllayouts/_partials/algolia/scripts.html,实现站点专属集成。空的覆盖文件会禁用对应主题 partial。

如果现有选项都不合适,站点可以替换搜索输入、结果行为与样式。应尽量复用外壳的对话框与无障碍合同。除非自定义代码与服务商无关,并且能被多个产品复用,否则应保留在站点层。

自定义在线服务商必须显式启用,并说明网络、隐私、索引、故障与离线行为。自定义本地服务商必须从站点或主题发布全部运行时资源,并遵守语言和 baseURL 边界。

3 - 文档版本管理

连接多个文档版本并标记归档版本。

根据项目的发布和版本管理方式,你可能需要让用户访问旧版文档。旧版本的具体部署方式由你决定。本页介绍 OINK 提供的功能:在各个文档版本之间导航,并在归档站点上显示信息横幅。

添加版本下拉菜单

如果在 hugo.tomlhugo.yamlhugo.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.tomlhugo.yamlhugo.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 归档文档

一个文本框,说明当前页面是不再维护的文档快照。
图 1:Kubeflow v0.6 归档文档中的横幅

要在文档站点加入横幅,请在 hugo.tomlhugo.yamlhugo.json 中完成以下修改:

  1. 将站点参数 archived_version 设为 true

    [params]
    archived_version = true
    params:
      archived_version: true
    {
      "params": {
        "archived_version": true
      }
    }
  2. 将站点参数 version 设为归档文档集的版本。例如,如果归档文档对应 0.1 版:

    [params]
    version = "0.1"
    params:
      version: 0.1
    {
      "params": {
        "version": "0.1"
      }
    }
  3. 确认站点参数 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"
      }
    }

4 - Apache ECharts

使用结构化 JSON 或 YAML 创建响应式、本地优先图表。

echarts 短代码使用 Oink 随主题分发的固定版本 Apache ECharts 运行时渲染选项对象。Hugo 在构建阶段解析 JSON 或 YAML,把结果序列化到页面中,并且只在实际使用该组件的页面加载 ECharts。

当定量图表需要精确控制坐标轴、视觉编码、提示或序列时,请使用 ECharts。图表旁边仍要提供文字摘要,不能让结论依赖颜色、指针交互或 JavaScript。

快速开始

{{< echarts height="300px" >}}
xAxis:
  type: category
  data: [草稿, 评审, 发布]
yAxis:
  type: value
series:
  - type: bar
    data: [12, 9, 4]
{{< /echarts >}}

这个示例表示有 12 页草稿、9 页正在评审,另有 4 页可以发布。

Oink 如何加载图表

短代码会创建唯一的图表容器,并把解析后的选项保存到 application/json 元素中。即使同一页包含多个图表,页面也只会加入一次本地 ECharts 运行时与 Oink 初始化脚本。

未设置 theme 时,Oink 会按照站点当前配色模式初始化图表,并在读者切换模式时重新绘制。ResizeObserver 会让图表随容器缩放。显式指定 ECharts 主题后,该图表不再自动跟随站点配色模式。

短代码参数

参数 默认值 行为
height 400px 接受非负数字与 pxrememvhvw% 单位
theme 未设置 使用指定的 ECharts 主题;未设置时跟随站点的深色或浅色模式
full false 设为 true 后移除 Oink 的常规正文宽度限制

无效高度会让 Hugo 构建失败。短代码正文必须能够解析成 ECharts 选项对象;格式错误的 JSON 或 YAML 同样会在构建期报错,而不是静默生成空白图表。

选择指南

  • 图表示例集演示数据集、柱状图、折线图、面积图、饼图、散点图、图例与视觉编码;
  • 回调与可信代码解释格式化函数、数据驱动样式、$fn:name 桥接方式及其安全边界。

请先使用声明式 JSON 或 YAML;只有 ECharts 选项无法用数据表达时,才添加 JavaScript 回调。

创作检查清单

  • 在正文中说明图表结论与数据范围;
  • 明确标注坐标轴、单位、序列与时间范围;
  • 不要只依靠颜色区分重要数值;
  • 在站点深浅两种配色模式中检查图例与提示;
  • 使用窄屏和较长译文标签测试图表;
  • 多个序列共用记录时,优先使用共享 dataset
  • 非演示数据应注明来源与观察日期;
  • 动画无助于理解时不要启用,自定义效果还应尊重减少动态效果偏好。

延伸参考

OINK 负责记录包装层与交付行为,完整选项 Schema 则以 Apache ECharts 为准。图表专用配置请查阅 ECharts 概念手册数据集指南选项参考。主题发行版随附的准确运行时版本与许可证记录在 VENDOR.json 中。

4.1 - ECharts 图表示例集

复制适合文档页面的声明式 ECharts 实用模式。

本页示例只使用结构化 YAML,不需要回调代码,因此处于最简单的 ECharts 创作与审查边界内。所有数字均为演示数据。

复用数据集

ECharts dataset 把记录与视觉编码分开。序列可以按名称引用维度,比重复维护多组平行数组更容易审查。

从数据集创建柱状图

{{< echarts height="320px" >}}
dataset:
  source:
    - [stage, minutes]
    - [草稿, 18]
    - [评审, 11]
    - [发布, 4]
xAxis: { type: category }
yAxis: { type: value, name: 分钟 }
series:
  - type: bar
    encode: { x: stage, y: minutes }
{{< /echarts >}}

示例表示中位耗时从撰写草稿的 18 分钟,逐步下降到发布阶段的 4 分钟。

折线与面积对比

多个序列描述同一组时间区间时,可以共用分类轴。面积填充突出总量,折线则保留各序列的趋势。

{{< echarts height="340px" >}}
tooltip: { trigger: axis }
legend: { data: [英文, 中文] }
xAxis:
  type: category
  data: [周一, 周二, 周三, 周四, 周五]
yAxis: { type: value, name: 页面 }
series:
  - name: 英文
    type: line
    smooth: true
    areaStyle: { opacity: 0.12 }
    data: [5, 8, 7, 11, 13]
  - name: 中文
    type: line
    smooth: true
    areaStyle: { opacity: 0.12 }
    data: [4, 6, 8, 9, 13]
{{< /echarts >}}

两种语言的评审队列都在周五达到 13 页;中文队列起点少一页,随后逐步追平。

环形占比图

环形图适合类别较少的部分与整体对比。请限制类别数量、直接显示标签,并在正文中给出总数。

{{< echarts height="340px" >}}
tooltip: { trigger: item }
legend: { bottom: 0 }
series:
  - name: 文档页面
    type: pie
    radius: [42%, 68%]
    avoidLabelOverlap: true
    label: { formatter: "{b}: {c}" }
    data:
      - { name: 指南, value: 28 }
      - { name: 参考, value: 17 }
      - { name: 教程, value: 11 }
      - { name: 概念, value: 8 }
{{< /echarts >}}

这组 64 页文档包含 28 页指南、17 页参考、11 页教程与 8 页概念说明。

使用视觉编码的散点图

visualMap 无需回调即可编码第三个维度。下面把构建规模同时映射为点的大小与颜色。

{{< echarts height="360px" >}}
tooltip: { trigger: item }
xAxis: { type: value, name: 构建秒数 }
yAxis: { type: value, name: 页面数 }
visualMap:
  - type: continuous
    dimension: 2
    min: 10
    max: 50
    inRange: { symbolSize: [10, 32], color: ["#60a5fa", "#f97316"] }
    right: 0
    top: middle
series:
  - type: scatter
    encode: { x: 0, y: 1, tooltip: [0, 1, 2] }
    data:
      - [1.8, 24, 12]
      - [2.6, 41, 22]
      - [3.9, 67, 35]
      - [5.1, 92, 48]
{{< /echarts >}}

在这组演示数据中,页面较多的站点构建时间也更长。点的大小和颜色同时编码第三个数值,因此颜色不是唯一线索。

生产环境说明

数据量较小且属于编辑内容时,可以把示例数据放在图表旁边。对于大型或生成的数据集,应在站点内容流水线中生成选项,并审查最终页面源码。Oink不会自动从远程端点获取图表数据;增加网络请求属于站点主动选择的集成,也会改变本地优先与隐私边界。

4.2 - ECharts 回调与可信代码

结构化选项不足时,使用经过审查的格式化与样式函数。

大多数 ECharts 选项都应保持为声明式 JSON 或 YAML。自定义格式化器、数据驱动样式等合法选项需要函数时,Oink 可以通过 JavaScript 围栏代码块与 $fn:name 引用支持这些场景。

可信作者边界

回调代码会在每位访问者的浏览器中执行,拥有页面同源环境下的常规 JavaScript 权限。Oink 会安全序列化结构化图表选项,但不会沙箱隔离作者提供的回调。只有可信的项目作者才能添加或审查这类代码。

短代码会输出行内注册脚本,因此回调还可能改变站点的内容安全策略(CSP)要求。能够用声明式选项表达同一行为时,请不要使用回调。

注册并引用函数

在短代码中加入一个或多个 jsjavascript 围栏。使用具名 varletconst 赋值或函数声明定义每个函数,再从 YAML 或 JSON 中通过 $fn:name 引用。

{{< echarts height="320px" >}}
```js
var formatMinutes = function (value) {
  return value + ' 分钟';
};
```

```yaml
yAxis:
  type: value
  axisLabel: { formatter: $fn:formatMinutes }
```
{{< /echarts >}}

Oink 会先移除 JavaScript 围栏,再解析剩余选项;初始化图表时注册具名函数,并在调用 chart.setOption() 前替换 $fn:name 值。

示例:标签与颜色

下面的图表会格式化耗时标签,并突出显示最慢阶段。演示数据表示撰写耗时 18 分钟、评审耗时 11 分钟、发布耗时 4 分钟。

回调检查清单

  • 函数应保持确定性,而且只负责图表呈现;
  • 不得读取 Cookie、凭据、存储或无关页面内容;
  • 不得从格式化或样式回调中获取远程数据;
  • 同一页包含多个图表时,使用唯一且含义清晰的函数名;
  • 从外部示例复制的代码仍属于源码,必须审查并核对许可证;
  • 按实际输入范围测试缺失值、null、字符串与数字;
  • 检查站点深浅配色、窄屏、打印与减少动态效果行为。

故障排查

如果 $fn:name 没有解析,请确认拼写与同一页面中的具名声明完全一致,并确认围栏语言是 jsjavascript。没有赋给名称的匿名表达式无法注册。

如果 Hugo 在渲染前失败,请先把正文缩减为有效 JSON 或 YAML,再逐个加入回调。浏览器控制台报错则表示结构化选项已经解析成功,但回调执行或某个 ECharts 选项仍需检查。

5 - 使用 AntV 创建信息图

把简洁的声明式数据转换成本地 SVG 信息图。

infographic 短代码使用 Oink 随主题分发的固定版本 AntV Infographic 运行时渲染 DSL。它适合展示流程、时间线、循环、漏斗、路线图与紧凑信息摘要;如果统计图显得过于生硬,可以选择信息图。

DSL 会作为数据序列化,不会作为任意 HTML 或可执行代码插入页面。浏览器运行时把它转换成 SVG,并且只在实际使用该短代码的页面加载。

快速开始

{{< infographic >}}
infographic list-row-simple-horizontal-arrow
data
  title 文档工作流
  items
    - label 草稿
      desc 写出第一个版本
    - label 评审
      desc 检查事实与语言
    - label 发布
      desc 构建并验证站点
{{< /infographic >}}

下图展示同样的三个步骤:草稿阶段写出初版,评审阶段核对事实与语言,发布阶段则构建并验证站点。

语法结构

信息图通常包含:

  1. infographic TEMPLATE:选择内置 AntV 模板;
  2. data 块:包含可选的 titledesc
  3. items 列表:包含 labeldesc,以及可选的 value 和嵌套 children
  4. 可选的 theme 块:选择内置主题或显式颜色。

缩进决定结构。标签应保持简短,描述用于补充上下文;模板表达的视觉关系必须与正文一致。装饰性的序列不能替代真实的层级或对比关系。

短代码参数

参数 默认值 行为
height auto 接受 auto,或非负数字与 pxrememvhvw% 单位
full false 设为 true 后移除 Oink 的常规正文宽度限制

无效高度与空 DSL 正文会让 Hugo 构建失败。DSL Schema 或模板错误则由浏览器运行时显示在信息图容器中。

AntV 主题属于 DSL,而不是短代码参数。它不会自动跟随 Oink 站点配色模式,因此必须在深浅两种模式中检查前景、背景与页面周围区域的对比度。

选择指南

AntV 包含大量模板。请优先选择足以解释关系的最小视觉形式,不要只追求最具装饰性的模板。

创作与无障碍

  • 在图形前后使用普通正文概括同一结论;
  • 保持阅读顺序有意义,并缩短标签;
  • 不要只通过颜色或形状传递状态;
  • 检查长译文标签、窄屏、打印与站点深浅两种配色模式;
  • 本地优先页面应避免远程图片或图标标识;确需使用时,必须显式审查网络与许可证边界;
  • 非演示数值应注明来源与日期。

SVG 可以提高视觉保真度,但不能保证每种模板都能提供与原生标题、列表、表格相同的语义结构。关键指令必须继续出现在相邻正文中。

延伸参考

OINK 负责记录短代码与交付边界。完整 DSL、模板图库与主题模型请查阅 AntV Infographic 文档图库源码仓库。Oink 主题的 VENDOR.json 记录随附版本、校验值与 MIT 许可证文件。

5.1 - 流程、时间线与循环

根据顺序关系选择横向、时间线或循环模板。

不同序列模板回答不同问题。横向流程强调有序交接,时间线强调先后顺序,循环则强调末尾阶段会再次回到起点。相邻正文必须说明真正重要的是哪一种关系。

横向流程

简短的从左到右流程可以使用 list-row-simple-horizontal-arrow。请缩短标签,并在窄屏下确认渲染顺序仍然清晰。

{{< infographic >}}
infographic list-row-simple-horizontal-arrow
data
  title 文档交付
  items
    - label 规划
      desc 明确读者与预期结果
    - label 撰写
      desc 完成最小而完整的页面
    - label 评审
      desc 核对事实、语言与链接
    - label 交付
      desc 构建并验证线上路由
{{< /infographic >}}

该流程从规划进入撰写和评审,最后得到经过单独验证的线上结果。

时间顺序

时间或版本先后是主要关系时,使用 sequence-timeline-simple

{{< infographic >}}
infographic sequence-timeline-simple
data
  title 发布证据
  items
    - label 源码就绪
      desc 范围、文案、归属与评审全部完成
    - label 检查通过
      desc 主题与项目站测试套件通过
    - label 标签公开
      desc 不可变模块版本可以解析
    - label 站点部署
      desc 生产路由通过冒烟测试
{{< /infographic >}}

这条时间线区分四项证据:测试通过不能跳过公开标签与部署阶段。

持续循环

只有最后一项确实会把工作送回第一项时,才使用 sequence-circular-simple。存在终止状态的流程不应画成循环。

{{< infographic height="480px" >}}
infographic sequence-circular-simple
data
  title 文档维护循环
  items
    - label 观察
      desc 收集支持请求与搜索信号
    - label 排序
      desc 选择要解决的读者问题
    - label 改进
      desc 更新内容与示例
    - label 验证
      desc 检查链接、渲染与结果
{{< /infographic >}}

验证会产生新的观察结果,因此维护循环会再次回到第一阶段。

选择原则

如果去掉箭头或时间轴也不会改变含义,请改用原生列表或卡片。信息图应该揭示关系,而不是装饰一组彼此无关的陈述。

5.2 - 信息图布局、漏斗与主题

无需自定义 JavaScript,即可展示分组、收窄与风格化信息。

AntV 模板由结构、数据项与标题样式组成。切换模板也会改变隐含关系,因此应先审查含义,再考虑外观。下面的示例只使用扁平 items 数据,不包含远程图标。

分组事实网格

多项事实围绕同一主题,但没有固定顺序时,可以使用 list-grid-badge-card

{{< infographic >}}
infographic list-grid-badge-card
data
  title 文档质量门槛
  items
    - label 准确性
      desc 命令与版本符合产品事实
    - label 覆盖度
      desc 包含必要概念与任务
    - label 语言
      desc 中英文保持等价
    - label 交付
      desc 线上路由与评审源码一致
{{< /infographic >}}

这四项门槛彼此并列,不应把其中一项画成另一项的前提。

逐步收窄的漏斗

每个阶段都会有意减少总体数量时,使用 sequence-funnel-simple。请加入 value 字段,并在正文中重复这些数字。

{{< infographic height="460px" >}}
infographic sequence-funnel-simple
data
  title 文档评审漏斗
  items
    - label 完成草稿
      value 40
      desc 提交评审的页面
    - label 事实核对
      value 34
      desc 验证命令与论断
    - label 语言评审
      value 31
      desc 对齐中英文内容
    - label 完成发布
      value 28
      desc 验证线上页面
{{< /infographic >}}

40 页草稿经过评审后,得到 34 页已核对事实的页面、31 页已完成语言评审的页面,以及 28 页经过验证的线上页面。

内置手绘主题

主题只改变样式,不改变数据含义。hand-drawn 适合非正式规划材料,也可以使用自定义主色与站点视觉保持一致。

{{< infographic >}}
infographic sequence-stairs-front-simple
data
  title 从笔记到可维护文档
  items
    - label 记录
      desc 写下观察到的行为
    - label 解释
      desc 补充上下文与读者目标
    - label 验证
      desc 测试示例与链接
    - label 维护
      desc 指定负责人和更新路径
theme hand-drawn
  colorPrimary #2563eb
{{< /infographic >}}

选择模板家族

关系 推荐起点
有序交接 list-row-simple-horizontal-arrowsequence-steps-simple
时间或路线图 sequence-timeline-simplesequence-roadmap-vertical-simple
重复循环 sequence-circular-simplesequence-circle-arrows-indexed-card
并列事实 list-grid-badge-cardlist-grid-compact-card
逐步减少 sequence-funnel-simplesequence-pyramid-simple
层级 hierarchy-tree-*hierarchy-mindmap-*

模板可用性取决于随附 AntV 版本。采用较少见的模板前,请使用真实中英文内容渲染,并固定其 VENDOR.json 已包含该模板的 Oink 发行版。

布局检查清单

  • 并列标签应保持语法一致;
  • 只有数值单位或含义明确时才使用 value
  • 避免固定高度裁掉译文;
  • 只有周围页面与打印布局确有需要时才设置 full=true
  • 分别检查模板含义、对比度、溢出与阅读顺序;
  • 网络隔离文档不得引用远程图标或图片。

6 - 使用 giscus 添加评论

使用 giscus 添加 GitHub 评论。

OINK 在 params.comments 下提供与 Hextra 兼容的评论配置,并通过该配置支持 giscus。giscus 会为每个内容页关联一条由 GitHub Discussions 保存的评论线程,读者通过 GitHub OAuth 登录后即可发表评论。

giscus 如何工作

页面加载时,giscus 会在配置的仓库中查找与当前页面匹配的 Discussion。如果没有找到,读者首次发表评论或表态时,giscus bot 会自动创建一条。维护者直接在 GitHub Discussions 中审核和管理评论。

所有人都可以阅读公开评论。读者发表评论时,选择 使用 GitHub 登录,并授权 giscus app 代表自己发帖。OINK 不会索取或保存读者的 GitHub 密码或访问令牌。

准备 GitHub 仓库

配置 OINK 前,请完成以下准备:

  1. 使用 公开 GitHub 仓库保存评论线程。访客无法读取私有仓库中的 Discussions。
  2. 在仓库的 Settings > Features启用 GitHub Discussions
  3. 为该仓库安装 giscus GitHub App。没有此 App,访客无法评论或表态。
  4. 选择一个 Discussion 分类。giscus 推荐使用 Announcements 类型,以便只有维护者和 giscus bot 能创建新的 Discussions。

仓库 ID 与分类 ID 是公开标识符,不是凭据。不要在 Hugo 配置中加入 GitHub personal access token、OAuth secret 或密码。

生成仓库配置

打开 giscus.app 并填写配置表单:

  1. 选择界面语言。
  2. OWNER/REPOSITORY 格式填写仓库,并等待验证成功。
  3. 选择页面与 Discussion 的映射方式。OINK 默认使用 pathname
  4. 选择 Discussion 分类和可选功能。
  5. 找到生成的 <script> 代码块。

把以下生成值复制到 OINK 配置中:

生成的属性 OINK 配置键
data-repo repo
data-repo-id repoId
data-category category
data-category-id categoryId

选择稳定的映射方式

映射方式决定每个页面对应哪一条 Discussion。如果发布路径稳定,而且同一个仓库需要服务多个域名或预览环境,pathname 是合适的默认值。

修改 mapping、移动页面或变更永久 URL,可能让 giscus 查找另一条 Discussion。应在开始收集评论前选定映射方式;迁移时保留重定向或 Discussion 标题。如果相似页面路径可能误选线程,请启用严格匹配。

全站启用评论

把生成的标识符加入消费站点的 hugo.yml,并设置 enable: true

params:
  comments:
    enable: true
    type: giscus
    giscus:
      repo: OWNER/REPOSITORY
      repoId: REPOSITORY_ID
      category: Announcements
      categoryId: CATEGORY_ID
      mapping: pathname
      strict: 0
      reactionsEnabled: 1
      emitMetadata: 0
      inputPosition: top
      theme: auto
      loading: lazy

请用 giscus.app 生成的准确值替换所有大写占位符。OINK 只有在 reporepoIdcategorycategoryId 全部存在时才会渲染 giscus。必填值缺失或只有空白字符时,Hugo 会发出警告并跳过 giscus,而不会让构建失败。

配置参考

配置键 默认值 用途
enable false 在全站启用所选评论服务。
type giscus 选择 giscus;目前不支持其他服务商名称。
repo OWNER/REPOSITORY 格式的公开仓库。
repoId giscus.app 生成的仓库 node ID。
category GitHub Discussions 分类名称。
categoryId giscus.app 生成的分类 node ID。
mapping pathname 把当前页面映射到 Discussion。
term specificnumber 等映射方式提供所需参数。
strict 0 设为 1 时严格匹配 Discussion 标题。
reactionsEnabled 1 显示 Discussion 主帖的表态。
emitMetadata 0 向父页面发送 Discussion 元数据消息。
inputPosition top 把评论编辑器放在 topbottom
theme auto 跟随 OINK 主题,或选择内置/自定义 giscus 主题。
lang 当前页面语言 覆盖自动选择的 giscus 界面语言。
loading lazy 读者接近评论区时才加载 iframe。
ariaLabel Comments 为辅助技术标记评论区域。
errorMessage 加载错误文本 替换 giscus 无法加载时显示的消息。

功能开关值既可以使用 YAML 布尔值,也可以使用 giscus 风格的 01

语言、主题与无障碍文本

OINK 会根据当前 Hugo 语言选择 giscus locale。简体中文、繁体中文和香港繁体中文会分别映射到对应的 giscus locale;不支持的语言会回退到英文。只有自动选择不合适时,才需要设置 lang

使用 theme: auto 时,iframe 会跟随 OINK 的明暗主题选择器和浏览器首选配色。设置内置 giscus 主题名称或自定义主题 URL 后,将不再自动切换。

多语言站点应在每种语言的参数中翻译评论区域标签和加载失败文本。语言参数会与全局仓库配置合并:

languages:
  en:
    params:
      comments:
        giscus:
          ariaLabel: Comments
          errorMessage: Comments could not be loaded.
  zh:
    params:
      comments:
        giscus:
          ariaLabel: 评论
          errorMessage: 评论加载失败。

覆盖单个页面

front matter 中的 comments 字段可以从任一方向覆盖全局开关。

启用单个页面

hugo.yml 中保留完整仓库配置、关闭全局开关,然后让选定页面显式启用评论:

---
title: 社区设计笔记
comments: true
---

禁用单个页面

全局启用评论后,可让不适合评论的静态页面显式退出:

---
title: 安全政策
comments: false
---

显式设置 comments: false 会同时禁用该页的 giscus 和旧版 Disqus。

与 Disqus 共存

迁移期间,OINK 会保持与现有 Hugo Disqus 配置兼容。当某页的有效 giscus 配置处于启用状态时,OINK 会抑制 Disqus,确保只渲染一套评论系统。如果启用了 giscus,但必填设置不完整,OINK 会发出警告、跳过 giscus,并可保留已配置的 Disqus 作为回退。

迁移完成并确认所有预期页面都使用 giscus 后,再删除 Disqus 服务配置。

内容安全策略

严格的内容安全策略(CSP)必须同时在 script-srcframe-src 中允许 giscus。请把以下来源合并到站点现有策略中,不要替换其他指令:

script-src 'self' https://giscus.app;
frame-src 'self' https://giscus.app;

OINK 初始化器仍是同源打包资源,而且只会加入启用 giscus 的页面。如果外部脚本加载失败或没有创建 iframe,OINK 会结束加载状态,并在实时状态区域显示 errorMessage

验证集成

  1. 构建站点,并确认没有必填键缺失警告:

    hugo --minify
  2. 启动本地预览,打开应启用评论的页面:

    hugo server --disableFastRender
  3. 确认 giscus iframe 显示 使用 GitHub 登录,并采用当前页面语言。

  4. 在 OINK 的明暗主题之间切换;使用 theme: auto 时,评论组件应同步切换。

  5. 打开设置了 comments: false 的页面,确认其中没有 giscus 或 Disqus 组件。

  6. 提交一条测试评论,然后确认预期 Discussion 出现在指定分类中,并可在 GitHub 上管理。

首次评论或表态创建 Discussion 之前,浏览器控制台提示找不到 Discussion 属于正常现象。

故障排查

  • 构建警告缺少必填键:在 giscus.app 重新生成配置,并原样复制四个必填标识符。
  • 评论组件没有出现:检查 params.comments.enableparams.comments.type、页面的 comments front matter,以及 Hugo 警告输出。
  • GitHub 登录或发帖失败:确认仓库公开、已启用 Discussions,而且已为该仓库安装 giscus GitHub App。
  • 浏览器阻止 giscus:检查控制台和响应头,并在适用的 CSP 指令中允许 https://giscus.app
  • 找不到已有评论线程:恢复原来的映射方式和页面路径,或者在修改 URL 前有计划地重命名或迁移 Discussion。
  • 界面语言不正确:检查 Hugo 语言名称与 locale,或显式设置 params.comments.giscus.lang

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 的链接。

页面询问内容是否有帮助,并提供“是”和“否”两个按钮。
图 1:页面反馈组件

即使不启用分析,响应仍然可以发挥作用:它可以把读者引导到 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:

  1. 页面 front matter 中的 description
  2. 对于非索引页,使用 Hugo 计算出的页面摘要;
  3. params 中的站点描述。

请为每种语言编写精炼且针对当前页面的描述。不要把英文描述复制到中文页面。搜索元数据无法弥补内容单薄、重复或不准确的问题。

主题还会根据 Hugo 页面译文输出 canonical 与备用语言链接。请使用正确的生产 baseURL、稳定的译文路由和显式译文标题 ID。只有主题尚未提供某类 meta 标签时,才应通过站点的 layouts/_partials/hooks/head-end.html 覆盖添加。

底层服务与内容概念请参阅 Hugo 的 Google Analytics 配置页面摘要和 Google 的 SEO 入门指南

8 - 代码仓库链接与页面信息

帮助读者查看、编辑页面源码,并针对源码报告问题。

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,因此表达式中不需要语言目录。

如果源文件使用不同名称,请使用 fromto 映射。下面把分区 _index.md 映射到上游 README.md

path_base_for_github_subdir:
  from: content/reference/(.*?)/_index.md
  to: $1/README.md

请分别从叶子页、分区页和两种语言页面测试查看与编辑链接。正则表达式移除路径过多时,可能生成看似合理却指向错误位置的仓库 URL。

github_url(可选)

旧页面可以在 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 历史不可用时,不要把构建时间冒充为“最后修改”时间。

9 - AI 智能体支持

向 AI 智能体与工具提供 Markdown 和发现元数据。

功能

站点显式启用后,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 输出

如果要让某些页面不输出 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.html 渲染 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 needed
      

    Full spec: https://agentdocsspec.com/spec/

这些检查的配置详情请参阅智能体支持检查


  1. 这与 Hugo 文档描述的 front matter 配置行为不同,但截至 Hugo 0.158.0,我们的测试确认实际行为如此。 ↩︎

10 - 打印支持

配置单页与整节文档的打印输出。

大多数浏览器都能很好地打印单篇文档,因为页面样式会从打印输出中移除导航外壳。

有些站点适合启用“打印整节”功能(本用户指南就是如此)。选择后,系统会把当前顶层分区(例如本页所在的“高级特性”)连同全部子页面和子分区渲染为适合打印的格式,并附上该分区的完整目录。

要启用此功能,请在站点的 hugo.tomlhugo.yamlhugo.json 中,为 section 类型添加 print 输出格式:

[outputs]
section = [ "HTML", "RSS", "print" ]
outputs:
  section:
    - HTML
    - RSS
    - print
{
  "outputs": {
    "section": [
      "HTML",
      "RSS",
      "print"
    ]
  }
}

随后,站点右侧导航中会显示“打印整节”链接。

进一步自定义

禁用目录

如果不希望可打印视图显示目录,可以在页面 front matter,或者 hugo.tomlhugo.yamlhugo.json 中将 disable_toc 参数设为 true

+++

disable_toc = true

+++
---

disable_toc: true

---
{
  …,
  "disable_toc": true,
  
}
[params.print]
disable_toc = true
params:
  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 来定制每个页面的正文格式。