如何在Hakyll/Pandoc中为标题添加自链接?
给Hakyll博客标题添加自链接的实现方案
方法一:启用Pandoc章节Div+CSS样式
- 修改站点配置文件:在
site.hs中启用Pandoc的writerSectionDivs选项,让每个标题对应带ID的容器:
import Hakyll import Text.Pandoc.Options main :: IO () main = hakyll $ do -- 保留原有路由和规则 match "posts/*" $ do route $ setExtension "html" compile $ pandocCompilerWith defaultHakyllReaderOptions customWriterOpts >>= loadAndApplyTemplate "templates/post.html" postCtx >>= loadAndApplyTemplate "templates/default.html" postCtx >>= relativizeUrls customWriterOpts :: WriterOptions customWriterOpts = defaultHakyllWriterOptions { writerSectionDivs = True }
- 添加CSS样式:在全局CSS文件中加入以下代码,实现hover时显示锚点链接:
h1, h2, h3, h4, h5, h6 { position: relative; padding-left: 1.2em; } .header-anchor { position: absolute; left: 0; opacity: 0; transition: opacity 0.2s; text-decoration: none; color: #999; } h1:hover .header-anchor, h2:hover .header-anchor, h3:hover .header-anchor, h4:hover .header-anchor, h5:hover .header-anchor, h6:hover .header-anchor { opacity: 1; } .header-anchor::before { content: "#"; }
方法二:使用Pandoc过滤器直接注入链接
如果需要更灵活的控制,可编写Pandoc过滤器给每个标题添加自链接:
- 编写过滤器函数:在
site.hs中添加以下代码:
import Hakyll import Text.Pandoc import Text.Pandoc.Walk -- 给标题添加自链接 addHeaderAnchors :: Pandoc -> Pandoc addHeaderAnchors = walk transformHeader where transformHeader :: Block -> Block transformHeader header@(Header _ (id', _, _) _) | not (null id') = let anchor = Link ("header-anchor", [], []) [Str "#"] ("#" <> id', "") newContent = anchor : headerContent header in setHeaderContent newContent header transformHeader x = x -- 辅助函数:获取和设置标题内容 headerContent :: Block -> [Inline] headerContent (Header _ _ content) = content headerContent _ = [] setHeaderContent :: [Inline] -> Block -> Block setHeaderContent content (Header level attr _) = Header level attr content setHeaderContent _ x = x
- 应用过滤器到编译流程:修改文章编译规则,加载过滤器:
match "posts/*" $ do route $ setExtension "html" compile $ pandocCompilerWithTransform defaultHakyllReaderOptions defaultHakyllWriterOptions addHeaderAnchors >>= loadAndApplyTemplate "templates/post.html" postCtx >>= loadAndApplyTemplate "templates/default.html" postCtx >>= relativizeUrls
两种方法都能实现:访客将鼠标悬停在标题上时,会显示#样式的锚点链接,点击即可直接获取该章节的锚点URL,无需查看页面源代码。
内容的提问来源于stack exchange,提问作者Joe
相关产品推荐
相关产品推荐

