根据每个页面的元数据有条不紊地在上下文中包含一个字段

时间:2017-10-14 23:41:32

标签: haskell hakyll

我想在我的Hakyll网站上下文中添加一个字段。如果元数据中存在某个键,那么我想转换相应的值并将其包含在上下文中。如果元数据中不存在该键,则不应向上下文添加任何内容。

我写了这个函数应该做我所描述的:

-- | Creates a new field based on the item's metadata. If the metadata field is
-- not present then no field will actually be created. Otherwise, the value will
-- be passed to the given function and the result of that function will be used
-- as the field's value.
transformedMetadataField :: String -> String -> (String -> String) -> Context a
transformedMetadataField key itemName f = field key $ \item -> do
    fieldValue <- getMetadataField (itemIdentifier item) itemName
    return $ maybe (fail $ "Value of " ++ itemName ++ " is missing") f fieldValue

但是,如果元数据字段不存在,那么这仍然会将字段插入上下文中,并将空字符串作为其值。例如,我在我的上下文中有这一行:

transformedMetadataField "meta_description" "meta_description" escapeHtml

我有这个模板:

$if(meta_description)$
    <meta name="description" content="$meta_description$"/>
$endif$

在元数据中没有meta_description的网页上,会生成以下HTML:

    <meta name="description" content=""/>

而我想要的却是根本不生产任何标签。

我在transformedMetadataField函数中做错了什么?

2 个答案:

答案 0 :(得分:1)

您需要返回Control.Applicative&#34;空&#34;让一个领域完全不存在。我自己的代码中的一个例子:

-- What we're trying to do is produce a field that *doesn't* match
-- key in the case where the metadata "header" is not set to "no" or
-- "false"; matching it and returning false or whatever
-- (makeHeaderField above) isn't working, so any call to "field" is
-- guaranteed to not work
makeHeaderField :: String -> Context a
makeHeaderField key = Context $ \k _ i -> do
    if key == k then do
      value <- getMetadataField (itemIdentifier i) "header"
      if isJust value then
        if elem (fromJust value) [ "no", "No", "false", "False" ] then
          -- Compiler is an instance of Alternative from
          -- Control.Applicative ; see Hakyll/Core/Compiler/Internal.hs
          CA.empty
        else
          return $ StringField $ fromJust value
      else
        return $ StringField "yes makeheader"
    else
      CA.empty

哦,我忘记了:正如我上面的代码注释所指出的,你不能使用hakyll&#34;字段&#34;在这种情况下的功能,因为&#34;字段&#34;在字段名称匹配的情况下,始终将字段视为existant。您必须复制&#34;字段&#34;中的代码。如上所述(CA是Control.Applicative),在你想要的地方获得你自己的CA.empty回报。

答案 1 :(得分:0)

对于后人,这是我最终得到的功能,感谢@ rlpowell的回答。

-- | Creates a new field based on the item's metadata. If the metadata
-- field is not present then no field will actually be created.
-- Otherwise, the value will be passed to the given function and the
-- result of that function will be used as the field's value.
transformedMetadataField :: String -> String -> (String -> String) -> Context a
transformedMetadataField newKey originalKey f = Context $ \k _ i -> do
    if k == newKey
       then do
           value <- getMetadataField (itemIdentifier i) originalKey
           maybe empty (return . StringField . f) value
       else empty