summaryrefslogtreecommitdiff
path: root/web
diff options
context:
space:
mode:
authorJasper Van der Jeugt <m@jaspervdj.be>2013-01-13 11:20:30 +0100
committerJasper Van der Jeugt <m@jaspervdj.be>2013-01-13 11:20:30 +0100
commit408a991b5eb2a766402b6c9b6caeada98665bfa4 (patch)
treed0c6dbf2466e9c804c3a817cf1fdf0a9258ce212 /web
parentc59d113caef12dfeaff6d7d6c6af5e5f23723152 (diff)
downloadhakyll-408a991b5eb2a766402b6c9b6caeada98665bfa4.tar.gz
Finish tutorial on snapshots/feeds
Diffstat (limited to 'web')
-rw-r--r--web/tutorials/05-snapshots-feeds.markdown90
1 files changed, 89 insertions, 1 deletions
diff --git a/web/tutorials/05-snapshots-feeds.markdown b/web/tutorials/05-snapshots-feeds.markdown
index d113aa2..230a703 100644
--- a/web/tutorials/05-snapshots-feeds.markdown
+++ b/web/tutorials/05-snapshots-feeds.markdown
@@ -22,7 +22,10 @@ myFeedConfiguration = FeedConfiguration
}
```
-Now, we'll create the actual feed.
+Simple feed rendering
+---------------------
+
+Now, let's look at how we actually create a feed. Two functions are available:
```haskell
renderAtom :: FeedConfiguration
@@ -37,3 +40,88 @@ renderRss :: FeedConfiguration
-> [Item String]
-> Compiler (Item String)
```
+
+As you can see, they have exactly the same signature: we're going to use
+`renderAtom` in this tutorial, but it's trivial to change this to an RSS feed.
+
+```haskell
+create ["atom.xml"] $ do
+ route idRoute
+ compile $ do
+ let feedCtx = postCtx `mappend`
+ constField "description" "This is the post description"
+
+ posts <- take 10 . recentFirst <$> loadAll "posts/*"
+ renderAtom myFeedConfiguration feedCtx posts
+```
+
+There we go! We simply take the 10 last posts and pass them to `renderAtom`,
+with our configuration and a `Context`.
+
+It's a bit of a problem that we don't have a description for our posts, and the
+Atom/RSS feed renderer requires this. One option is to add a `description: Foo`
+header to our all posts. However, the description is the body text as it appears
+in most RSS readers, so we would prefer to include the entire content of the
+posts here.
+
+Snapshots
+---------
+
+This poses a problem: if we just `load` all posts and take their content: we get
+the *finished, processed* content. This means all templates have been applied at
+that point (including `templates/default.html`). We don't want to include our
+entire site with navigation in the RSS feed, but rather just the post HTML.
+
+Snapshots provide a solution to this problem. They allow you to save an `Item`
+at any point during its compilation, so you can `load` it later. Let's apply
+this to our concrete problem.
+
+```haskell
+match "posts/*" $ do
+ route $ setExtension "html"
+ compile $ pandocCompiler
+ >>= loadAndApplyTemplate "templates/post.html" postCtx
+ >>= loadAndApplyTemplate "templates/default.html" postCtx
+ >>= relativizeUrls
+```
+
+now becomes:
+
+```haskell
+match "posts/*" $ do
+ route $ setExtension "html"
+ compile $ pandocCompiler
+ >>= loadAndApplyTemplate "templates/post.html" postCtx
+ >>= saveSnapshot "content"
+ >>= loadAndApplyTemplate "templates/default.html" postCtx
+ >>= relativizeUrls
+```
+
+The `saveSnapshot` function is really simple: it takes an item and returns the
+same item, after saving it. This return value makes it easier to use
+`saveSnapshot` in a chain of compilers as we did in the above example, but you
+can discard it if you want.
+
+```haskell
+type Snapshot = String
+
+saveSnapshot :: (Typeable a, Binary a)
+ => Snapshot -> Item a -> Compiler (Item a)
+```
+
+Including the post body
+-----------------------
+
+With this modification, we can update our Atom code. Instead of loading the
+compiled posts, we just load their content (i.e. the snapshot we just took).
+
+We update the `Context` to map `$description$` to the post body, and we're done!
+
+```haskell
+create ["atom.xml"] $ do
+ route idRoute
+ compile $ do
+ let feedCtx = postCtx `mappend` bodyField "description"
+ posts <- take 10 . recentFirst <$> loadAllSnapshots "posts/*" "content"
+ renderAtom myFeedConfiguration feedCtx posts
+```