Discussion:
[hakyll] Getting fields from a list of Item
c***@gmail.com
2016-12-31 19:07:04 UTC
Permalink
This post seems to be close to what I'm after:
https://groups.google.com/forum/#!searchin/hakyll/post$20list%7Csort:relevance/hakyll/jkHracVKm_Y/mbjGakjZJC0J

Basically, I'd like to be able to get the metadata for pages from within my
template.

This gets me the *names* of the pages

match "v/**" $ do
route $ customRoute $ \ident -> dropExtension (toFilePath ident) </> "index.html"
compile $ do
ident <- getUnderlying

vCtx <- case splitDirectories $ toFilePath ident of
_:v:_ -> do
pages <- getMatches $ fromGlob $ versionsDir </> v </> "*"
return $
listField "pages" docCtx (return [Item p "" | p <- pages])
<> docCtx

other -> error $ "Expected at least 2 elements, got: " <> show other

pandocCompiler
= loadAndApplyTemplate "templates/doc.html" vCtx
= loadAndApplyTemplate "templates/default.html" vCtx
= processUrls
But I can't seem to access the $url$ or $title$, they all return the same
value as the identifier.

$for(pages)$
<li>
<li class="toctree-l1">
<a class="" href="$url$">$title$</a>
</li>
</li>
$endfor$


I see that there's getMetadata, but it's not clear to me how to pack that
into an Item. Adding them as separate fields doesn't work since they need
to be in a list. Any ideas?
--
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+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Beerend Lauwers
2017-01-01 07:56:10 UTC
Permalink
Hi Cary,

The load and loadAll functions are probably what you're looking for: they
take an Identifier (or a Pattern in the case of loadAll) and give you back
Items. Here's a link to the Hackage
documentation: https://hackage.haskell.org/package/hakyll-4.9.2.0/docs/Hakyll-Core-Compiler.html

Jasper also has some basic examples
here: https://jaspervdj.be/hakyll/tutorials/04-compilers.html#loading-items

What you're doing right now, is taking the name of a page and putting it in
an Item, which is a simple wrapper around an arbitrary data structure. With
itemBody, we can access the data structure of an Item and pull out data
from it for use it in a field. In the section "Completing the puzzle" of my
blog post on list fields, you can see this in
action: http://beerendlauwers.be/posts/2015-08-17-hacking-on-hakyll-pt-2.html

To be clear, I'm not saying you should manually map the data to the fields
with itemBody - that's what Contexts are for. You just need to load the
entire data structure with the load functions and pass them to the listField
.

Kind Regards,
Beerend Lauwers
Post by c***@gmail.com
https://groups.google.com/forum/#!searchin/hakyll/post$20list%7Csort:relevance/hakyll/jkHracVKm_Y/mbjGakjZJC0J
Basically, I'd like to be able to get the metadata for pages from within
my template.
This gets me the *names* of the pages
match "v/**" $ do
route $ customRoute $ \ident -> dropExtension (toFilePath ident) </> "index.html"
compile $ do
ident <- getUnderlying
vCtx <- case splitDirectories $ toFilePath ident of
_:v:_ -> do
pages <- getMatches $ fromGlob $ versionsDir </> v </> "*"
return $
listField "pages" docCtx (return [Item p "" | p <- pages])
<> docCtx
other -> error $ "Expected at least 2 elements, got: " <> show other
pandocCompiler
= loadAndApplyTemplate "templates/doc.html" vCtx
= loadAndApplyTemplate "templates/default.html" vCtx
= processUrls
But I can't seem to access the $url$ or $title$, they all return the same
value as the identifier.
$for(pages)$
<li>
<li class="toctree-l1">
<a class="" href="$url$">$title$</a>
</li>
</li>
$endfor$
I see that there's getMetadata, but it's not clear to me how to pack that
into an Item. Adding them as separate fields doesn't work since they need
to be in a list. Any ideas?
--
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+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
c***@estatico.io
2017-01-04 20:48:11 UTC
Permalink
Thanks, that post helped me finally grok Items. Fwiw, I actually wrote a
simple type class to make some of this easier

-- | Type class describing how to build a field definition for a type.
class Field a where
fieldContext :: Context a

-- | Create a list field from a list of values which define an instance for
Field.
autoListField :: Field a => String -> [a] -> Context b
autoListField name xs = listField name fieldContext $ traverse makeItem xs

This makes encoding your own data types as Items much easier.

Best,

Cary
Post by Beerend Lauwers
Hi Cary,
The load and loadAll functions are probably what you're looking for: they
take an Identifier (or a Pattern in the case of loadAll) and give you
https://hackage.haskell.org/package/hakyll-4.9.2.0/docs/Hakyll-Core-Compiler.html
https://jaspervdj.be/hakyll/tutorials/04-compilers.html#loading-items
What you're doing right now, is taking the name of a page and putting it
in an Item, which is a simple wrapper around an arbitrary data structure.
With itemBody, we can access the data structure of an Item and pull out
data from it for use it in a field. In the section "Completing the puzzle"
http://beerendlauwers.be/posts/2015-08-17-hacking-on-hakyll-pt-2.html
To be clear, I'm not saying you should manually map the data to the fields
with itemBody - that's what Contexts are for. You just need to load the
entire data structure with the load functions and pass them to the
listField.
Kind Regards,
Beerend Lauwers
Post by c***@gmail.com
https://groups.google.com/forum/#!searchin/hakyll/post$20list%7Csort:relevance/hakyll/jkHracVKm_Y/mbjGakjZJC0J
Basically, I'd like to be able to get the metadata for pages from within
my template.
This gets me the *names* of the pages
match "v/**" $ do
route $ customRoute $ \ident -> dropExtension (toFilePath ident) </> "index.html"
compile $ do
ident <- getUnderlying
vCtx <- case splitDirectories $ toFilePath ident of
_:v:_ -> do
pages <- getMatches $ fromGlob $ versionsDir </> v </> "*"
return $
listField "pages" docCtx (return [Item p "" | p <- pages])
<> docCtx
other -> error $ "Expected at least 2 elements, got: " <> show other
pandocCompiler
= loadAndApplyTemplate "templates/doc.html" vCtx
= loadAndApplyTemplate "templates/default.html" vCtx
= processUrls
But I can't seem to access the $url$ or $title$, they all return the same
value as the identifier.
$for(pages)$
<li>
<li class="toctree-l1">
<a class="" href="$url$">$title$</a>
</li>
</li>
$endfor$
I see that there's getMetadata, but it's not clear to me how to pack that
into an Item. Adding them as separate fields doesn't work since they need
to be in a list. Any ideas?
--
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+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Loading...