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/templatehtml/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 -}}

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

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

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

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

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

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

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


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

相关推荐
ICT系统集成阿祥2 小时前
XXXX银行培训干校无线AP故障排查优化案例
运维·网络
.普通人2 小时前
树莓派4Linux 单个gpio口驱动编写
linux
随猿Fa3 小时前
提升运维效率:深度集成 SSH Config,实现企业级隧道自动化管理
运维·自动化·ssh
勇气要爆发3 小时前
Docker:软件开发的“标准集装箱”
运维·docker·容器
luckily灬3 小时前
Docker执行hello-world报错&Docker镜像源DNS解析异常处理
linux·docker
REDcker4 小时前
C++ 崩溃堆栈捕获库详解
linux·开发语言·c++·tcp/ip·架构·崩溃·堆栈
产幻少年4 小时前
用户登录日志表和系统日志
运维·服务器·数据库
技术小李...4 小时前
Linux7.2安装Lsync3.1.2文件同步服务
linux·lsync
Frank_refuel4 小时前
Linux常用指令详解
linux·运维·服务器