从 Hakyll 中的元数据创建列表字段



我正在尝试为Hakyll中的帖子生成HTML,这些帖子的元数据中有versions条目。例如,帖子可能有versions: Python 3.4, pytest 1.5.2,该在帖子底部的格式很好。

为此,我想创建一个加载元数据并创建一个ListField的上下文。类似于以下存根的内容:

versionsCtx :: Context String
versionsCtx = listFieldWith "versions" ctx (item -> do
versions <- getMetadataField (itemIdentifier item) "versions"
return $ case versions of
Just lst -> map (mkVersinoItem . trim) $ splitAll "," lst
Nothing  -> [])
where ctx = field "version" (return . itemBody)
mkVersionItem version = Item {
itemIdentifier = fromString ("version/" ++ version),
itemBody = version
}

在我的post.html模板中,我有:

...
<section>
$body$
$if(versions)$
<hr />
<ul>
$for(versions)$
<li>$version$</li>
$endfor$
</ul>
$else$
<p>Fail...</p>
$endif$
</section>
...

然而,我尝试了许多不同的versionsCtx定义,并在网上找到了类似的尝试。似乎都不起作用,帖子总是以"失败..."呈现。我做错了什么?

编辑:更新了带有建议和澄清的问题。

您的代码存在多个问题:

  1. getMetadataField提供了一个Maybe类型,在Haskell中,它有数据构造函数JustNothing,而不是SomeNone
  2. makeItem函数创建一个已经包装在Compiler中的Item,导致以下错误:
• Couldn't match type ‘Compiler (Item String)’ with ‘Item String’
Expected type: Compiler [Item String]
Actual type: Compiler [Compiler (Item String)]

虽然您可以尝试从中提取项目,但使用如下所示的内容从头开始创建项目可能更干净:

mkVersionItem version = Item {
itemIdentifier = fromString ("version/" ++ version),
itemBody = version
}
  1. 我没有看到您将新创建的上下文添加到帖子上下文中。你做到了吗?
  2. 如文档中所述,附加Context的顺序很重要。从您的问题中看不出来,但您可能正在使用defaultContext,其中包括metadataField.您在帖子的元数据块中versions字段,因此当defaultContext获胜时,它将versions作为模板中的字符串字段提供。$if(versions)$由于某种原因跳转到else分支,当versions是字符串字段时,这就解释了为什么显示"Fail"。当您将for循环移到条件块之外时,您可以在控制台中看到一个信息量更大的错误:
[ERROR] Hakyll.Web.Template.applyTemplateWith: expected ListField but got StringField for expr versions

完整的代码可能如下所示:

import           Data.String (fromString)
postCtx :: Context String
postCtx =
versionsCtx `mappend`
dateField "date" "%B %e, %Y" `mappend`
defaultContext
versionsCtx :: Context String
versionsCtx = listFieldWith "versions" ctx (item -> do
versions <- getMetadataField (itemIdentifier item) "versions"
return $ case versions of
Just lst -> map (mkVersionItem . trim) $ splitAll "," lst
Nothing     -> []
)
where
ctx = field "version" (return . itemBody)
mkVersionItem version = Item {
itemIdentifier = fromString ("version/" ++ version),
itemBody = version
}