组织内容
_index.md 与 weight、栏目首页样式、图标与折叠、隐藏页面、把文档放在任意路径。OINK 不需要单独配置导航:content/ 下的目录结构就是侧栏树。本页覆盖目录与文件的摆放、栏目首页、排序、图标、折叠、隐藏,以及多根侧栏。
目录就是侧栏
一个目录是一个栏目(Hugo 称 section),目录里的 Markdown 文件是它的页面,嵌套目录是它的子栏目。侧栏按这棵树逐层渲染,顺序由 weight 决定,标签取 linkTitle,缺省时取 title。左侧这棵树的源码如下:
content/docs/ 的前两层
content/
docs/
- _index.zh.md栏目根:type: docs + cascade
about/简介
- _index.zh.md
- features.zh.md
start/快速上手
- _index.zh.md
write/创作内容(本栏目)
- _index.zh.mdweight: 30
- pages.zh.mdweight: 10
- organize.zh.mdweight: 20
- frontmatter.zh.mdweight: 30
components/组件
- _index.zh.md
每个目录都要有 _index.md
栏目首页是目录里的 _index.md(中文为 _index.zh.md)。缺少它时 Hugo 仍会生成栏目,但没有标题、描述、图标与 weight:侧栏那一行显示目录名,排序不受控制。
栏目 _index.md 另有一项专属能力:用 cascade 把共享设置一次下推给整棵子树,不必每页重复。
排序:weight 用 10 的倍数
同一栏目里的页面按 weight 升序排列,weight 相同时才退回日期与 linkTitle 字母序。一律用 10 的倍数(10、20、30),此后往中间插页不必改动其它页。栏目自身的 weight 决定它在父级里的位置。
没写 weight 的页面视为 0,Hugo 把它们排在所有写了 weight 的页面之后,彼此按日期与标题排列。这个顺序会随内容改动漂移,因此每页都写上 weight。
单文件还是页面包
没有自身资源的页面用单文件 slug.md;带图片、cast、示例文件的页面改成目录加 index.md,资源与它同放。两种形态在侧栏里没有区别,URL 也相同。详见编写页面。
栏目首页显示子页列表还是卡片
_index.md 的正文之后,主题自动接上子页索引,两种样式:
list 是主题默认,每个子页一行标题加描述;cards 是链接卡片网格,读取子页的 icon、linkTitle 与 description。本站用 cards,本栏目首页即是例子。单个栏目需要另一种样式时在它的 front matter 里覆盖:
两个页面级开关不受样式影响:simple_list: true 渲染紧凑的项目符号列表,no_list: true 不生成索引,用于正文自行手写导航的场合。
卡片样式下 description 即卡片正文。描述控制在一句话、单行可显示。
侧栏图标
在页面或栏目的 front matter 里写一对 Font Awesome class:
图标密度是站点级策略,用于避免叶子页全部带图标:
| 取值 | 效果 |
|---|---|
all |
每个写了 icon 的条目都显示(未设置时的兼容默认值) |
groups |
只有根节点和有子页的节点显示图标,普通叶子页不显示 |
none |
侧栏不显示任何条目图标 |
新站点建议显式写 groups:保留分组的语义标识,去掉叶子层的图标。本站使用这个设置,左侧只有六个栏目带图标。
展开与折叠
有子页的栏目在侧栏里带一个折叠箭头。OINK 保存整栏折叠、宽度和滚动位置;各分支的读者选择可由站点通过侧栏运行时 API 自行持久保存。默认行为:当前页所在的那条路径展开,其余收起;博客类栏目默认展开。
站点级的折叠、紧凑模式、初始展开层数、宽度与截断在布局与页面类型里配;键的完整定义见配置总览。
从侧栏里藏起来
| front matter | 效果 |
|---|---|
toc_hide: true |
页面不出现在侧栏树里(页面本身照常发布,链接照常可用) |
hide_summary: true |
页面不出现在栏目首页的子页索引里 |
sidebar_divider: true |
这一项不再是链接,而是侧栏里的一条分组标题 |
manual_link: https://… |
侧栏这一行指向别处;配 manual_link_title、manual_link_target: _blank 用 |
toc_hide 与 hide_summary 控制两个不同的入口,两处都不该出现时才同时设置。
不发布目录页的分组
自 OINK 1.1 起,分隔分区保留子页,同时让标题不再跳转,修复了 v1.0.0
子页丢失的问题。目录只负责组织子页时,使用这样的 _index.md:
标题显示为分组标签,启用侧栏折叠时按钮负责展开子页;子页仍进入翻页、搜索、导航 JSON 和 Print。
没有 JavaScript 时分组保持展开。省略 build,即可继续发布分区页面,同时保留侧栏的
非链接标题。叶子分隔项保持原来的外观。
toc_hide 会隐藏分区的整棵子树;no_list 只移除分区正文的子页列表,hide_summary
只移除父页面列表中的一项,都不能代替分组。build.render: link 保留 permalink,却不
发布页面;不发布的分组应使用 never,避免其他导航把它当成可访问的目标。
外壳由 type 决定,不是路径
文档外壳(侧栏、目录、面包屑、翻页器)不取决于目录名,只取决于页面的 type 是否在 params.ui.shell_types 里:
文档因此可以放在任意路径,用 cascade 指定 type 即可。例如把一套手册放在 content/handbook/,栏目根的写法如下:
文档目录不叫 docs 时,type: docs 之外还要写 sidebar_root_for: self。否则侧栏会按 params.ui.docs_section(默认 docs)去找根,读者在 /handbook/ 下却看到 /docs/ 的树。
多根侧栏
侧栏树默认以读者所在的顶层栏目为根,树上方一行标出当前的根。规模较大的子树可以自己成为一个根,例如带版本的 API 参考或一本独立的手册:
| 取值 | 语义 |
|---|---|
self |
这个栏目的首页及其全部后代都以它为侧栏根 |
children |
首页仍留在父级树里,只有后代以它为根 |
根节点上方的切换器是全站的:它列出所有顶层栏目,加上站内所有 sidebar_root_for: self 的栏目。只有一个入口时它退化成一个普通链接,两个及以上才是下拉菜单。在顶层栏目或嵌套自根的 _index.md 中写 sidebar_root_menu: false,可将其排除在全站候选之外;浏览该分区时,当前根仍保留为位置提示。
切换器下方,栏目首页仍是树里的第一个链接:切换器选择一棵树,根链接指向一篇文档。sidebar_root_link_self: false 让根那一行改为指向父级栏目。
验证
必须 Total in …,没有 ERROR / WARN。--printPathWarnings 报出两个页面指向同一输出路径的情况,改目录结构时较常出现。
在浏览器里逐项确认:
- 侧栏里的顺序与写下的
weight一致,新栏目出现在预期位置; - 栏目首页的子页索引齐全(缺项来自
hide_summary或缺少_index.zh.md); - 面包屑与翻页器的顺序与侧栏一致,翻页器读的是同一棵树;
- 换语言之后树的形状相同(每个
_index.md都要有.zh.md对等文件)。
侧栏条目超过 params.ui.sidebar_menu_truncate 时构建给出警告,并指出应调到多少。这个警告不可忽略:被截断的条目不会出现在侧栏里。
通过站点代码控制分支
window.OinkSidebar 自 OINK 1.1 起提供;v1.0.0 不提供该 API。
站点代码应在主题脚本之后加载,例如使用 layouts/_partials/hooks/body-end.html,
读取或恢复分支状态前先等待 ready。以下示例展开侧栏的第一个分组:
区域 ID 使用按钮现有的 aria-controls 值;getState(id) 返回 {id, expanded}
或 null。按钮、区域与无障碍状态一致后,变化会在 document 上触发一次
oink:sidebar-disclosure 事件,detail 为 {id, expanded, source};重复写入相同
状态不发事件。通过 API 恢复时,当前页面的祖先分组保持展开,读者仍可主动折叠。
主题不保存单个分支的偏好。站点自行增加这项功能时,应为存储键区分语言与导航版本, 容忍存储不可用,并忽略当前页面不存在的 ID。完整生命周期见 侧栏契约。
相关
- 编写页面 — 单页怎么写
- 页面参数 — 这页出现的每个 front matter 键的完整定义
- 布局与页面类型 — 站点级的外壳、侧栏与目录设置
- 导航与菜单 — 顶栏菜单、面包屑与翻页器
- 多语言 — 双语目录树怎么保持一致