haskellscopehakyll

How can I include post teasers in my installation?


I'm following the official instructions on the Hakyll site to get post teasers up and running on my site. Unfortunately, I've hit a snag, and the instructions aren't much help.

I'm getting an out-of-scope error for the item value referenced in this snippet:

loadAndApplyTemplate
     "template/postitem.html"
     (teaserField "teaser" "content" <> defaultContext)
     item

When embedding it into my site.hs. On a side note for reproducibility's sake, it also wasn't made clear where the <> operator came from; this required the import of one of Literate Haskell's modules.

It's completely unclear where this reference to item came from, and because it's a fairly common word, I have to sift through thousands of results even when using find and grep on my machine.

What should I declare or import to gain access to item here?


Solution

  • The tutorial page isn't a complete example. item isn't a reference to some function. It's just a placeholder name for an Item. Usually you'll get it from pandocCompiler or one of the many other "compilers". In this example, loadAndApplyTemplate is just like any other use of it. The only difference is that $teaser$ will be bound to the teaser text in the template.

    That said, this isn't that great of an example since you usually want to use the teaser text on page listing multiple posts. This will probably involve using listField to make a collection of posts that you will iterate upon in the template. For example, this is the rule for my index page:

    match "index.html" $ do
        route idRoute
        compile $ do
            posts <- fmap (take indexRecentPostCount) . recentFirst =<< loadAllSnapshots postsPattern "postContent"
            let indexCtx =
                    constField "title" "Home" <>
                    baseCtx
    
            getResourceBody
                >>= applyAsTemplate (listField "posts" (teaserField "teaser" "postContent" <> postCtx) (return posts) <> indexCtx)
                >>= loadAndApplyDefaultTemplate indexCtx
                >>= relativizeUrls
    

    The "item" in this case is what getResourceBody returns, i.e. the body of index.html. This binds $posts$ to a list of posts. Ignoring the metadata, my index.html is just:

    $for(posts)$
        $partial("templates/teaser.html")$
    $endfor$
    

    $teaser$ is then bound in the template/teaser.html template.