Hakyll如何为文章列表模板填充包含标签的上下文?
问题根源
你的listContextWith实现中调用getUnderlying时,获取的是当前正在编译的博客索引页(blog.md)的标识符,而非每一篇单独文章的标识符,因此无法读取到单篇文章的tags元数据,导致标签区域渲染为空。
修复步骤
1. 新增标签字段生成函数
新增专门从单篇文章元数据提取标签的辅助函数:
import Hakyll (trim, splitAll, lookupString, getMetadata, getUnderlying, fromFilePath, listField, defaultContext) -- 从当前文章的元数据提取标签,生成模板可用的列表字段 tagsField :: String -> Context String tagsField key = listField key defaultContext $ do postId <- getUnderlying metadata <- getMetadata postId let tags = maybe [] (map trim . splitAll ",") $ lookupString key metadata -- 生成标签对应的Item,模板中可直接用$body$读取标签内容 return $ map (\tag -> Item (fromFilePath $ "tag-" ++ tag) tag) tags
2. 调整文章上下文
把标签字段绑定到单篇文章的上下文postCtx中,同时补充你模板需要的preview字段:
postCtx :: Context String postCtx = dateField "date" "%d/%m/%Y" <> tagsField "tags" -- 注入标签列表字段 -- 若预览内容直接写在文章元数据的preview字段中,可删除下一行,defaultContext会自动读取 <> snippetField "preview" -- 自动生成文章摘要作为预览,按需使用 <> defaultContext
3. 简化索引页编译逻辑
你原来的listContextWith、listContext、tagContext都可以直接删除,直接使用修改后的postCtx作为文章列表的上下文即可:
main = do ... match "blog.md" $ do route $ setExtension "html" compile $ do posts <- recentFirst =<< loadAll "posts/*" let indexCtx = listField "posts" postCtx (return posts) `mappend` defaultContext pandocCompiler >>= loadAndApplyTemplate "templates/blogindex.html" indexCtx >>= relativizeUrls
原理解释
把tagsField绑定到postCtx后,每次渲染单篇文章条目时,getUnderlying获取的就是对应文章的标识符,能够正确读取单篇文章的tags元数据,和你的模板逻辑完全匹配。
内容的提问来源于stack exchange,提问作者iluvAS
相关产品推荐
相关产品推荐

