在 Hakyll 中从元数据创建列表字段
Creating a list field from metadata in Hakyll
我正在尝试为 Hakyll 中的 post 生成 HTML,它们的元数据中有 versions
条目。例如,post 可能有 versions: Python 3.4, pytest 1.5.2
,它可以很好地格式化在 post.
的底部
为此,我想创建一个加载元数据并创建 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
定义,并在网上找到了类似的尝试。 None 似乎有效并且 post 总是用 "Fail..." 渲染。我做错了什么?
编辑:更新问题并提供建议和说明。
您的代码存在多个问题:
getMetadataField
提供了一个 Maybe
类型,在 Haskell 中有数据构造函数 Just
和 Nothing
,而不是 Some
和 None
.
makeItem
函数创建一个 Item
已经包裹在 Compiler
中,导致以下错误:
• 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
}
- 我没有看到您将新创建的上下文添加到 post 上下文中。你做到了吗?
- 如docs, the order
Context
s are being appended is important. It is not evident from your question, but you are probably using defaultContext
, which includes metadataField
所述。您的 post 的元数据块中有 versions
字段,因此当 defaultContext
获胜时,它将使 versions
可用作模板中的字符串字段。当 versions
是字符串字段时,$if(versions)$
由于某种原因跳转到 else
分支,这解释了为什么显示“失败”。当您将 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
}
我正在尝试为 Hakyll 中的 post 生成 HTML,它们的元数据中有 versions
条目。例如,post 可能有 versions: Python 3.4, pytest 1.5.2
,它可以很好地格式化在 post.
为此,我想创建一个加载元数据并创建 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
定义,并在网上找到了类似的尝试。 None 似乎有效并且 post 总是用 "Fail..." 渲染。我做错了什么?
编辑:更新问题并提供建议和说明。
您的代码存在多个问题:
getMetadataField
提供了一个Maybe
类型,在 Haskell 中有数据构造函数Just
和Nothing
,而不是Some
和None
.makeItem
函数创建一个Item
已经包裹在Compiler
中,导致以下错误:
• 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
}
- 我没有看到您将新创建的上下文添加到 post 上下文中。你做到了吗?
- 如docs, the order
Context
s are being appended is important. It is not evident from your question, but you are probably usingdefaultContext
, which includesmetadataField
所述。您的 post 的元数据块中有versions
字段,因此当defaultContext
获胜时,它将使versions
可用作模板中的字符串字段。当versions
是字符串字段时,$if(versions)$
由于某种原因跳转到else
分支,这解释了为什么显示“失败”。当您将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
}