Hugo短代码变量影响目录渲染问题求助
问题根源
Hugo生成目录(ToC)的逻辑是先解析Markdown标题提取文本内容,再执行短代码渲染,所以标题中的自定义短代码不会被替换,反而会被转换为占位符字符串(如HAHAHUGOSHORTCODE-s1-HBHB)。
解决方案
以下是三种可行方案,按推荐优先级排序:
方案1:自定义ToC生成逻辑(推荐)
自己实现ToC生成逻辑,在遍历标题时直接执行变量替换,完全在服务端处理:
- 创建模板文件
layouts/partials/custom-toc.html:
{{ $variables := getJSON (printf "data/%s-variables.json" .Site.Params.buildFor) }} {{ $headers := findRE "<h[1-6].*?>(.*?)</h[1-6]>" .Content }} <ul class="toc"> {{ range $headers }} {{ $headerText := replaceRE "<h[1-6].*?>(.*?)</h[1-6]>" "$1" . }} {{/* 批量替换所有params短代码为对应变量值 */}} {{ $processedText := replaceRE "{{< params \"(.*?)\" >}}" (index $variables "$1") $headerText }} {{ $level := replaceRE "<h([1-6]).*?>.*?</h[1-6]>" "$1" . }} {{ $anchor := replaceRE "<h[1-6].*?id=\"(.*?)\".*?>.*?</h[1-6]>" "$1" . }} <li class="toc-item toc-level-{{ $level }}"> <a href="#{{ $anchor }}">{{ $processedText | safeHTML }}</a> </li> {{ end }} </ul>
- 在页面模板(如
layouts/_default/single.html)中,用自定义ToC替换原生的{{ .TableOfContents }}:
{{ partial "custom-toc.html" . }}
方案2:用模板变量替代短代码
直接在标题中使用Hugo模板变量,绕过短代码的渲染顺序问题:
- 在页面的前置参数(Front Matter)中预定义变量:
--- params: bookName: "{{ index (getJSON (printf "data/%s-variables.json" .Site.Params.buildFor)) "bookName" }}" ---
- 在Markdown标题中直接调用变量:
## Access the {{ .Params.bookName }}
原生ToC会直接识别渲染后的标题文本,无需额外修改。
方案3:客户端JS替换(应急方案)
如果不想修改模板结构,可通过JS在页面加载后替换占位符:
在页面底部添加脚本:
<script> document.addEventListener('DOMContentLoaded', function() { const tocLinks = document.querySelectorAll('.toc a'); const bookName = '{{ index (getJSON (printf "data/%s-variables.json" .Site.Params.buildFor)) "bookName" }}'; tocLinks.forEach(link => { link.textContent = link.textContent.replace('HAHAHUGOSHORTCODE-s1-HBHB', bookName); }); }); </script>
此方法依赖客户端JS,仅适合快速临时修复。
内容的提问来源于stack exchange,提问作者Mohammad Siavashi
相关产品推荐
相关产品推荐

