I'm trying to generate HTML for posts in Hakyll that have a versions entry in their metadata. For example, a post may have versions: Python 3.4, pytest 1.5.2 which would be formatted nicely at the bottom of the post.
To achieve this, I want to create a context which loads the metadata and creates a ListField. Something like the following stub:
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
}
In my post.html template, I have:
...
<section>
$body$
$if(versions)$
<hr />
<ul>
$for(versions)$
<li>$version$</li>
$endfor$
</ul>
$else$
<p>Fail...</p>
$endif$
</section>
...
Yet I have tried many different definitions of versionsCtx and found similar attempts online. None seem to work and the post is always rendered with "Fail...". What am I doing wrong?
EDIT: Updated question with suggestions and clarifications.
There are multiple issues with your code:
getMetadataFieldprovides aMaybetype, which in Haskell has data constructorsJustandNothing, notSomeandNone.makeItemfunction creates anItemalready wrapped in aCompiler, resulting in the following error:While you could try to extract the item from it, it is probably cleaner to create an item from scratch using something like this:
Contexts are being appended is important. It is not evident from your question, but you are probably usingdefaultContext, which includesmetadataField. You haveversionsfield in the metadata block of your posts so when thedefaultContextwins, it will makeversionsavailable as a string field in the template.$if(versions)$for some reason jumps to theelsebranch whenversionsis a string field, which explains why “Fail” is shown. You can see a more informative error in the console when you move theforloop outside the conditional block:In full the code could look something like this: