菜单

目录生成

相关源文件

本文档介绍了 Hugo 如何从 Markdown 和其他内容文件中的标题生成目录。该系统会提取内容中的标题元素,构建一个代表文档大纲的分层结构,并提供将此结构渲染为 HTML 的方法。

有关通用 Markdown 处理的信息,请参阅 Markdown 处理

概述

Hugo 会自动从内容文件中的标题生成目录(ToC)。在模板中可以访问此目录,并使用它在页面内创建导航。该系统支持可配置的标题级别范围、有序/无序列表以及标题锚点的自动 ID 生成。

来源:markup/goldmark/toc.go markup/tableofcontents/tableofcontents.go

配置

目录生成可以在 Hugo 配置文件中的 markup.tableOfContents 部分进行配置。

配置选项包括

选项描述默认
startLevel要包含的第一个标题级别(h1-h6)2
endLevel要包含的最后一个标题级别(h1-h6),或 -1 表示所有级别3
ordered是否使用有序 (<ol>) 或无序 (<ul>) 列表false

来源:markup/markup_config/config.go34-36 markup/tableofcontents/tableofcontents.go258-277

目录数据结构

目录由一个分层数据结构表示,该结构反映了文档的大纲。

关键组件

  • Fragments:目录的顶层容器,可以访问所有标题
  • Heading:表示单个标题,包含其 ID、标题、级别和子标题
  • HeadingsMap:提供按 ID 快速查找标题
  • Identifiers:包含所有标题 ID 的排序切片

来源:markup/tableofcontents/tableofcontents.go74-126 markup/tableofcontents/tableofcontents.go26-31

目录生成过程

目录生成过程与 Hugo 的 Markdown 处理管道集成,特别是 Goldmark 解析器。

该过程包括

  1. 在 Markdown 解析过程中,一个特殊的转换器 (tocTransformer) 会提取标题元素
  2. 对于每个标题,它会捕获
    • 标题文本
    • HTML ID(用于链接)
    • 标题级别(h1-h6)
  3. 这些标题使用 tableofcontents.Builder 组织成一个分层结构
  4. 生成的 Fragments 对象存储在页面上下文中,供模板访问

来源:markup/goldmark/toc.go38-141 markup/goldmark/convert.go226-238

标题 ID 生成

为了使标题在目录中可用,每个标题都需要一个唯一的 ID,可以用作锚点链接。Hugo 支持多种 ID 生成策略

策略描述
github兼容 GitHub 的 ID 生成(默认)
github-asciiGitHub 风格的纯 ASCII 版本
blackfriday旧版 Blackfriday 风格的 ID

ID 生成器处理

  • 将文本转换为小写
  • 用连字符替换空格
  • 删除特殊字符(取决于策略)
  • 通过附加数字等方式确保唯一性

来源:markup/goldmark/autoid.go36-159 markup/goldmark/goldmark_config/config.go18-21

在模板中使用目录

可以通过几种方式在模板中访问目录

  1. 使用 .TableOfContents 页面变量,它返回 HTML
  1. 使用 .Fragments 变量访问原始目录结构
  1. 使用 ToHTML 方法进行自定义渲染

来源:markup/tableofcontents/tableofcontents.go150-175 markup/goldmark/toc_integration_test.go48-56

从 HTML 中提取目录

对于未通过 Goldmark 解析器处理的内容,Hugo 提供了一个辅助函数 ExtractTOC,可以从 HTML 内容中提取目录。在某些情况下,这作为备用方案使用。

该函数

  1. 查找包含有序或无序列表的 <nav> 元素
  2. 将此作为目录提取
  3. 为其分配 ID "TableOfContents"
  4. 如果找到目录,则将其从内容中移除

来源:helpers/content.go94-128

输出示例

当使用默认设置渲染时,目录的 HTML 如下所示:

HTML 结构包含

  • 一个包装的 <nav> 元素,ID 为 "TableOfContents"
  • 嵌套的 <ul>(或 <ol> 如果 ordered=true)元素,代表层级结构
  • <li> 元素,包含指向标题锚点的 <a> 链接

来源:markup/tableofcontents/tableofcontents.go183-256 markup/tableofcontents/tableofcontents_test.go37-115

目录如何集成到 Markdown 处理中

目录生成与 Hugo 的 Markdown 处理紧密集成,特别是 Goldmark 解析器。

该过程包括

  1. Goldmark 解析器将 Markdown 处理成抽象语法树(AST)
  2. tocTransformer 遍历 AST 来识别标题节点
  3. 对于每个标题,它会提取文本和 ID 属性
  4. 它使用 tableofcontents.Builder 构建一个分层目录结构
  5. 生成的目录存储在解析器上下文中,之后可以通过页面对象访问

目录转换器在属性处理器之后运行,以确保自定义 ID 被正确捕获。

来源:markup/goldmark/toc.go123-141 markup/goldmark/convert.go109-116 markup/goldmark/internal/extensions/attributes/attributes.go35-47

与其他系统集成

目录生成与 Hugo 的各种功能协同工作

  1. 自定义标题 ID:您可以使用 Markdown 属性语法为标题指定自定义 ID

  2. 自动 ID 生成:如果未提供自定义 ID,Hugo 会根据标题文本自动生成一个

  3. 渲染钩子:您可以使用渲染钩子自定义标题渲染,以控制标题在内容与目录中的显示方式

  4. 多语言支持:目录生成与非 ASCII 字符一起正常工作,如果需要,还可以选择纯 ASCII ID

来源:markup/goldmark/internal/extensions/attributes/attributes.go107-204 markup/goldmark/autoid.go37-85

最佳实践

  1. 从2级开始:默认情况下,Hugo会从2级标题开始生成目录(<h2>),这通常是合适的,因为<h1>通常用于页面标题

  2. 限制深度:为了提高可读性,请通过设置适当的startLevelendLevel值,将目录深度限制为2-3级

  3. 一致的标题结构:遵循逻辑性的标题层次结构(不要跳过级别),以获得最佳的目录结构

  4. 自定义ID:为重要标题使用自定义ID,以确保稳定的锚点链接

  5. 使用不同内容进行测试:使用不同的内容结构测试目录,以确保其正确渲染

来源:markup/tableofcontents/tableofcontents.go258-277 markup/goldmark/toc_integration_test.go22-265