Hugo 主題開發 - Table of Contents 跟隨閱讀進度標示章節
前一陣子久違的更新一下 blog 主題 hugo-theme-monochrome,加了一個 TOC 跟隨閱讀進度標示章節的功能。
之前的做法,只是簡單的把 TOC 渲染出來,不過因為左右兩邊很空,一直都有想要把他調整到右邊然後做到跟隨閱讀進度同步,只是總是想著能用就好就擱置了 (X)。
實際研究出來後覺得做法滿酷的,所以在這邊記錄一下。
問題
主要會遇到的問題是 hugo 預設會將文章渲染出以下樣子:
| |
但這個功能會需要以下這個結構比較好做:
| |
所以會需要一些小技巧在渲染 html 時,就將 section 切好,方便後續使用 javascript 控制。
將渲染的文章拆解成 section
利用到的技巧是 Hugo 的 Heading render hooks,透過 layouts/_markup/render-heading.html 自訂 header 的 render template:
| |
所以上面的例子 html 在渲染時,會產生出以下的內容,存在 .Content 內:
| |
之後進到 layout 的 template render 時,就可以透過正則把前面偷偷插入的 <!-- end-chunk --> 來拆解 section,將內部的 section 內容取出,順便將 data-anchor 的 id 取出,包在 <section> 內:
layouts/single.html
| |
就可以變出這個結構了:
| |
透過 Javascript 的 IntersectionObserver 追蹤目前閱讀進度
有了以上的準備,就可以用 Javascript 的 IntersectionObserver 來實現閱讀進度的追蹤:
toc-tracker.js
| |
當 section 進入當前視角時,去對 #TableOfContents li a[href="#${id}"] 對應 id 的 entry 加上 class,就可以做出跟隨閱讀進度的效果了。