Blog index page.

38 views
Skip to first unread message

Donald Ephraim Curtis

unread,
May 27, 2011, 11:40:17 PM5/27/11
to hakyll
I have seen Jasper and Ethan's webpage source and seen how they list
posts for a blog, but I don't want a list. I would like a page that
has the first 5 posts for my blog on one page (including the bodies).

I've posted my code for your auditing: https://github.com/milkypostman/hakyllbox


The problem I run into is that when it renders my list (index.html) it
is recursing on $body$ in my individual files.

So, if I have post1.md, hakyll is rendering post1.md based on its
initial rule (meaning its wrapping it up in my "base.html"). Then
when it does to insert it into "index.html" it's including the initial
wrapping of base.html.

Basically, I have three levels,

I have,

thought.html - design of an individual posting (includes $title$ and
$body$)
thoughts.html - design of a collection of posts, right now just the
posts themselves (a $thoughts$ tag which is set to the content of all
posts)
base.html - my base site design (including a $body$ tag)

each of my files is under:

brain/post1.md
brain/post2.md

so post1.md is getting rendered once using default.html (to generating
brain/post1.html),
then it's getting rendered AGAIN with THAT content into my index.

This is really hard to explain but easy to see if you download the
code and run it. You'll see exactly what the problem is.

Jasper Van der Jeugt

unread,
May 28, 2011, 3:04:07 AM5/28/11
to hak...@googlegroups.com
Hello,

(Editorial note: the right solution is at the bottom of this mail. The
rest is purely informative.)

You can fix this using the group [1] function. It's growing on me that
the documentation here is insufficient, since a lot of issues seem to
be resolved using this function. Anyway:

You can render a "clean" version of your posts in a separate group:

-- We introduce a separate group in which the
-- posts are rendered without any templates
group "clean" $ do
match "brain/*.md" $ do
compile $ pageCompiler

And then require only these in your brain/index.html page:

match "brain/index.html" $ route idRoute
create "brain/index.html" $ constA mempty
>>> arr (setField "title" "brains")
-- To create the post list, we require the clean posts only
>>> requireAllA ("brain/*.md" `mappend` inGroup (Just "clean")) postList
>>> applyTemplateCompiler "templates/thoughts.html"
>>> applyTemplateCompiler "templates/base.html"

This will work, but it will cause another problem: the $url$ key is
not set in the "clean" posts, since they have no route. Giving them a
route would not help either, since then they would overwrite the
regular posts!

-- We introduce a separate group in which the
-- posts are rendered without any templates
group "clean" $ do
match "brain/*.md" $ do
compile $ pageCompiler &&& getIdentifier
>>> arr (\(p, i) -> setField "url" (fileToDirectory i) p)

Setting a custom $url$ key like that, however, helps. Now, the only
remaining problem for me was that I had to add relativizeUrlsCompiler
at the end of the brain/index.html compiler to make all links correct:

match "brain/index.html" $ route idRoute
create "brain/index.html" $ constA mempty
>>> arr (setField "title" "brains")
-- To create the post list, we require the clean posts only
>>> requireAllA ("brain/*.md" `mappend` inGroup (Just "clean")) postList
>>> applyTemplateCompiler "templates/thoughts.html"
>>> applyTemplateCompiler "templates/base.html"
>>> relativizeUrlsCompiler

At which point I got everything working. A matter of seconds later,
however, a much better, cleaner and simpler solution struck my mind,
so you might as well disregard all of the above.

Instead of using the group function, you can just copy the body to,
say, the $content$ field before the base template is applied:

match "brain/*.md" $ do
route $ cleanURL
compile $ pageCompiler
>>> arr (copyBodyToField "content")
>>> applyTemplateCompiler "templates/base.html"

And then, use that field instead of $body$ in templates/thought.html:

<h1><a href="$url$">$title$</a><h1>

$content$

I know it might be a matter of personal taste, but I'd prefer the
second solution.

[1]: http://jaspervdj.be/hakyll/reference/Hakyll-Core-Rules.html#v:group

Cheers,
Jasper

Donald Ephraim Curtis

unread,
May 28, 2011, 3:21:18 AM5/28/11
to hak...@googlegroups.com
Thanks Jasper,

You can see in my code I *did* play with the group thing a bit but two things,

1. I'm a complete newbie at Haskell, I'm not so sure I know what a Monad is yet.

2. I had no idea how to "focus" on a group, like you do with "mappend inGroup ...". In fact I'm don't know what mappend and mconcat and even the backticks (`) around mappend do.

Anyways, thanks for the help and I definitely agree that the latter solution is better.

My hope is just to get *something* going and then have time to play around learning more Haskell and about the Hakyll stuff. But I'll make sure to make a post summarizing and posting what I end up with. I am thinking for the moment that I kind of like the list of posts now that I have things sorted out.

But I've got more troubles just getting filenames right and things like that, yet I think I have those figured out. Bits at a time.

Thanks,
Donald

Reply all
Reply to author
Forward
0 new messages