How do I get only the title & url? (Need to avoid a dependency cycle)

163 views
Skip to first unread message

alexande...@gmail.com

unread,
Sep 28, 2015, 8:21:56 PM9/28/15
to hakyll
I have a box of icons that link to areas of expertise. I use these on /, but I also want to use them on every individual expertise (expertise/*.markdown). To generate them in index.markdown, I need:
      exps <-  loadAll "expertise/*.markdown"

But this will not work when generating "expertise/*.markdown", because it will create a dependency cycle.

How can I include my expertise-list in the expertise/*.markdowns? I only need the title and url of each expertise, so maybe there's a way to make them and not the body?

Here is the relevant code (it's short):
  templates/expertise-list.markdown: http://lpaste.net/8836702036775927808
  templates/expertise.markdown: http://lpaste.net/5854113189783928832
  /index.markdown and expertise/*.markdown: http://lpaste.net/906605211785625600

Any help would be awesome. Right now I generate the icons for /, and just copy the generated src into the expertise template, which is beyond stupid.

Jasper Van der Jeugt

unread,
Oct 1, 2015, 6:29:32 AM10/1/15
to hak...@googlegroups.com
Hello,

There are two approaches to do this.

1. Compile the items twice, using different versions [1]. One version is
actually shown on your site, and the other version is just for
extracting the info you need in the actual version.

In this case, however, since you don't need the page body, there is a
much simpler approach:

2. Just get the metadata for all items using `getMatches`/`getMetadata`.
I took the following snippet from the example site generated by
`hakyll-init`:

match "posts/*" $ do
route $ setExtension "html"
compile $ pandocCompiler
>>= loadAndApplyTemplate "templates/post.html" postCtx
>>= loadAndApplyTemplate "templates/default.html" postCtx
>>= relativizeUrls

Let's show how you can grab the metadata here:

match "posts/*" $ do
route $ setExtension "html"
compile $ do
posts <- getMatches "posts/*"
metadatas <- mapM getMetadata posts

-- Do something with metadatas here to put it in `postCtx`.

pandocCompiler
>>= loadAndApplyTemplate "templates/post.html" postCtx
>>= loadAndApplyTemplate "templates/default.html" postCtx
>>= relativizeUrls

This should be easily adapted to your site?

[1]: http://jaspervdj.be/hakyll/tutorials/06-versions.html

Hope this helps,
Peace,
Jasper
> --
> You received this message because you are subscribed to the Google Groups "hakyll" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to hakyll+un...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

alexande...@gmail.com

unread,
Oct 5, 2015, 10:10:54 AM10/5/15
to hakyll, alexande...@gmail.com
Thank you!

The second approach seems sound. I have a function for converting every expertise/*.markddown to HTML:

mdToHtml :: String -> Rules ()
mdToHtml t = do

  route $ setExtension "html"
  compile $ pandocCompiler
    >>= loadAndApplyTemplate (fromFilePath $ "templates/" ++ t ++ ".markdown")
                             (defaultContext <> fixAmpField)
    >>= renderPandoc
    >>= loadAndApplyTemplate "templates/default.html" defaultContext
    >>= relativizeUrls

I can get the metadata in here by doing:

  compile $ do
    ms <- getMatches (fromGlob $ t ++ "/*")
    md <- mapM getMetadata ms

... before the pandocCompiler. But I don't understand what I need to do to be able to use:

$partial("templates/expertise-list.markdown")$

... in expertise/*.markdown.

I need $expertise$ to be generated with $title$ and $url. I thought I could do something like this (albeit cleaner):

    let ctx = listField t (defaultContext <> fixAmpField)
                          (return ((fromMaybe "" . M.lookup "title") <$> md)
                        <> return ((fromMaybe "" . M.lookup "url")   <$> md))
           <> defaultContext

But that says that it couldn't match [Char] with Hakyll.Core.Item.Item String (on md).

Maybe this is the wrong approach altogether though. I just need $expertise$ so that I can use it like this:

$for(expertise)$
<div class="icon">
<a style="text-decoration: none;" href="$url$">
<img src="/images/$fixAmp(title)$-icon.svg" width="64vmin" class="inactive">
<img src="/images/$fixAmp(title)$-icon-active.svg" width="64vmin" class="active">
$title$
</a>
</div>
$endfor$

... in /templates/expertise-list.markdown.

Any ideas?

alexande...@gmail.com

unread,
Oct 8, 2015, 8:29:26 AM10/8/15
to hakyll, alexande...@gmail.com
By the way, I was able to make it work just fine using versions. That's, as you observed, a bit of an overkill though.

Robin Powell

unread,
Dec 30, 2020, 12:10:11 AM12/30/20
to hakyll
Sorry to necro an old thread :), but I had some surprise trouble with the first approach and I thought people might find my learnings helpful: http://rlpowell.name/computing/general/hakyll_recent_posts.html
Reply all
Reply to author
Forward
0 new messages