Search code examples
haskellhakyll

Hakyll - Using makeItem with data to create a list in HTML


I have a list of categories. Each category itself has a list of sub-categories: [(Category,[SubCategory])]. I would like to get the following HTML output in a single page:

<h2>Category 1</h2>

<ul>
  <li>Subcategory 1</li>
  <li>Subcategory 2</li>
</ul>

<h2>Category 2</h2>

<ul>
  <li>Subcategory 1</li>
  <li>Subcategory 2</li>
</ul>

I can't find a good way to do this. Would I need to do apply makeItem to the list and do something like

categoryList = [("Category 1",["Subcategory 1","Subcategory 2"])]

compile $ do
  makeItem (map fst categoryList)
  >>= loadAndApplyTemplate "templates/categories.html" defaultContext

How could I add the subcategories in a context so they're available in the template?

Perhaps I need to split up both creation steps (something like mapM $ makeItem (map fst categoryList) >> loadAndApplyTemplate ".." contextWithCategories and then, in some way, refer to that generated data in the actual page generation) ?


Solution

  • I've solved the problem myself. See this post for a detailed description.

    Here's the code that actually does it:

    create ["test.html"] $ do
      route idRoute
      compile $ do
      let ctx =
              listField "parents" 
                        (
                         field "parent" (return . fst . itemBody) <>
                         listFieldWith "children" 
                                       (field "child" (return . itemBody)) 
                                       (sequence . map makeItem . snd . itemBody)
                        ) 
                        (sequence [makeItem ("p1",["c1","c2"]), 
                                   makeItem ("p2",["p3","p4"])]) <>
              defaultContext
      makeItem ""
          >>= loadAndApplyTemplate "templates/testing.html" ctx
          >>= loadAndApplyTemplate "templates/default.html" defaultContext
          >>= relativizeUrls