83、【Ubuntu】【Hugo】搭建私人博客:文章目录(二)

【声明】本博客所有内容均为个人业余时间创作,所述技术案例均来自公开开源项目(如Github,Apache基金会),不涉及任何企业机密或未公开技术,如有侵权请联系删除

背景

上篇 blog
【Ubuntu】【Hugo】搭建私人博客:文章目录(一)

分析了文章的目录 TOC 功能,并分析了 PaperMod 主题下的默认 toc.html 模板,其中分析完了【提取标题】,下面继续【<details> 可折叠容器】的分析

搭建私人博客

继续看 【<details> 可折叠容器】

  • {``{if (.Param "TocOpen") }} open{``{ end }}:Hugo 模板语法,作用是如果在文章的标题开头写了 TocOpen = true,比如

    或者在 hugo.toml 配置文件中,加入了这个全局配置项,那么 Hugo 在渲染这里时,会自动加上 open 这个属性,这里就会变成 <details open>,表示页面一打开,目录就展开(本来默认是收起的)
  • accesskey="c":设置一个快捷键 ,在大多数浏览器中,按下 Alt + C(Windows)就能聚焦到这个 <summary> 上
  • titile="...":鼠标悬停在这里时,显示的提示文字,告诉用户这里可以使用快捷键

OK,看第三部分:选择 TOC 的生成方式

如果在文章,或 hugo.toml 的全局配置中,启用了配置项 UseHugoToc = true,就会直接使用 Hugo 内置的 .TableOfContents,更简单,但样式(风格)和 PaperMod 不一定是匹配的,否则就执行下面复杂的手动解析过程(PaperMod 默认方式,样式更统一)

第四部分:手动构建嵌套列表(核心难点)

这部分很复杂,因为 Hugo 模板语言没有循环栈,或者递归函数,只能用模拟栈的方式去处理嵌套层级

这里要区分下 Hugo 模板语言和 Go 语言,虽然 Hugo 是用 Go 语言开发的,但在比如 toc.html 这样模板文件上,写的不是 Go 代码,而是 Hugo 的模板语言(基于 Go 的 text/template 和 html/template)

这个模板语言有如下特点:

  • 支持变量,if 条件判断,range 循环等
  • 不支持函数定义,递归,复杂数据结构的操作(比如栈,队列等)
  • 不能直接把字符串转成整数,所以这里需要用 len (seq "$headerLevel") 这样的技巧

简单来说,Hugo 模板是一个受限,表达能力有限的 DSL(领域特定语言),和完整的 Go 语言有很大区别

OK,继续看这段代码

go 复制代码
 {{- $largest := 6 -}}
 {{- range $headers -}}
 {{- $headerLevel := index (findRE "[1-6]" . 1) 0 -}}
 {{- $headerLevel := len (seq $headerLevel) -}}
 {{- if lt $headerLevel $largest -}}
 {{- $largest = $headerLevel -}}

这段代码的的含义是,找出最小标题级别,比如(h2 是 2,h3 是 3,则最小是 2),这里 $largest 实际上是最小的标题数字(对应最高层级,比如 h2 在标题上比 h3 要大)

这里可能有人会有疑问,如果按这么说的话,那最小的不都是 h1 吗?

答案是不一定,因为有人可能不按常理出牌,他可能会跳过 h1 标题,直接用 h2,甚至 h3 标题开头,就比如

md 复制代码
---
title: "跳过 h1 的文章"
toc: true
---

## 这是 h2 标题
一些内容...

### 这是 h3 子标题
更多内容...

可以看到,这里并没有 h1 标题,所以 PaperMod 的 toc.html 处理中,并不假设必须有 h1 或 h2,而是动态找出所有标题中最小的层级(比如全是 h3/h4,就以 h3 为根),并以这个最小层级作为 TOC 的顶层,所有更深的标题都作为它的子项,相当于把 h3 当做逻辑上的顶级标题来对待,就好像一本书,如果第一章直接从 【1.3 小节】开始(中间没有【1.1 小节】,【1.2 小节】),那就把 【1.3 小节】当成第一章的主标题来列目录,虽然奇怪,但是技术上可行


OK,本篇先到这里,如有疑问,欢迎评论区留言讨论,祝各位功力大涨,技术更上一层楼!!!更多内容见下篇 blog
【Ubuntu】【Hugo】搭建私人博客:文章目录(三)

相关推荐
大哥您好3 小时前
QEMU 11.1.2 多架构编译指南(x86_64 / aarch64 / riscv64)
linux·服务器
道满科技4 小时前
Function Calling 参数总出错?只修参数就行
linux·windows·python
Gauss松鼠会4 小时前
高斯数据库(openGauss)的物理存储结构
运维·服务器·数据库·sql·opengauss·经验总结
Android系统攻城狮4 小时前
Linux Gstreamer深度解析之gst_audio_ring_buffer_prepare_read调用流程与实战(七十四)
linux·运维·服务器·gstreamer音视频·音视频进阶
杨云龙UP4 小时前
PostgreSQL 18.4 数据库整库迁移实战:pg_dump 备份与 pg_restore 恢复完整操作手册
运维·服务器·数据库·postgresql·pg_dump·pg_restore
我科绝伦(Huanhuan Zhou)5 小时前
Linux 通用压力测试脚本合集:磁盘 + 网络
linux·网络·压力测试
无人生还别怕6 小时前
如何安装任意版本docker
运维·docker·容器
T0uken6 小时前
Colab:SSH 访问免费 GPU Server
运维·ssh
Python大数据分析@6 小时前
通过 MCP 实现 AI Agent自动化数据采集
运维·人工智能·爬虫·自动化
Initialize293086 小时前
告警一条接一条刷屏?五步治理告警风暴
运维