summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
Diffstat (limited to 'examples')
-rw-r--r--examples/hakyll/examples/brochure.zipbin3672 -> 3689 bytes
-rw-r--r--examples/hakyll/images/arrow-composition.pngbin16066 -> 0 bytes
-rw-r--r--examples/hakyll/images/tutorial8-categories.pngbin9377 -> 0 bytes
-rw-r--r--examples/hakyll/images/tutorial8-tags.pngbin8631 -> 0 bytes
-rw-r--r--examples/hakyll/tutorials/part01.markdown235
-rw-r--r--examples/hakyll/tutorials/part02.markdown91
-rw-r--r--examples/hakyll/tutorials/part03.markdown174
-rw-r--r--examples/hakyll/tutorials/part04.markdown60
-rw-r--r--examples/hakyll/tutorials/part05.markdown157
-rw-r--r--examples/hakyll/tutorials/part06.markdown84
-rw-r--r--examples/hakyll/tutorials/part07.markdown221
-rw-r--r--examples/hakyll/tutorials/part08.markdown97
-rw-r--r--examples/hakyll/tutorials/part09.markdown104
13 files changed, 0 insertions, 1223 deletions
diff --git a/examples/hakyll/examples/brochure.zip b/examples/hakyll/examples/brochure.zip
index bcdfc67..619d9a9 100644
--- a/examples/hakyll/examples/brochure.zip
+++ b/examples/hakyll/examples/brochure.zip
Binary files differ
diff --git a/examples/hakyll/images/arrow-composition.png b/examples/hakyll/images/arrow-composition.png
deleted file mode 100644
index 947561a..0000000
--- a/examples/hakyll/images/arrow-composition.png
+++ /dev/null
Binary files differ
diff --git a/examples/hakyll/images/tutorial8-categories.png b/examples/hakyll/images/tutorial8-categories.png
deleted file mode 100644
index 0567917..0000000
--- a/examples/hakyll/images/tutorial8-categories.png
+++ /dev/null
Binary files differ
diff --git a/examples/hakyll/images/tutorial8-tags.png b/examples/hakyll/images/tutorial8-tags.png
deleted file mode 100644
index d8ae73e..0000000
--- a/examples/hakyll/images/tutorial8-tags.png
+++ /dev/null
Binary files differ
diff --git a/examples/hakyll/tutorials/part01.markdown b/examples/hakyll/tutorials/part01.markdown
deleted file mode 100644
index f96993a..0000000
--- a/examples/hakyll/tutorials/part01.markdown
+++ /dev/null
@@ -1,235 +0,0 @@
----
-title: Quickstart
-what: explains how to create a simple brochure site
----
-
-## Getting started
-
-First, make sure you have Hakyll installed. The recommended way to do this is
-through [hackage] using [cabal-install]. This tutorial also assumes you have a
-basic knowledge of Haskell.
-
-[hackage]: http://hackage.haskell.org/
-[cabal-install]: http://www.haskell.org/haskellwiki/Cabal-Install
-
-~~~~~
-[jasper@alice ~]$ cabal install hakyll
-~~~~~
-
-## Building a simple static site
-
-As an example to get started with, we're going to develop a so called
-"Brochure Site" for an imaginary company. The first step is to create a
-directory for our new site.
-
-~~~~~
-[jasper@alice Sites]$ mkdir brochure
-[jasper@alice Sites]$ cd brochure/
-[jasper@alice brochure]$
-~~~~~
-
-I have a [zip file] with the files we need for this
-tutorial available. Please unzip it in the brochure directory we just created.
-We'll first have a look at what we're going to create (because we're curious
-and all that).
-
-[zip file]: $root/examples/brochure.zip
-
-~~~~~
-[jasper@alice brochure]$ ghc --make hakyll.hs
-[1 of 1] Compiling Main ( hakyll.hs, hakyll.o )
-Linking hakyll ...
-[jasper@alice brochure]$ ./hakyll preview
-Starting hakyll server on port 8000...
-~~~~~
-
-If you now point your browser at [localhost:8000] you should see our simple
-brochure site.
-
-[localhost:8000]: http://localhost:8000/
-
-## hakyll.hs
-
-The main configuration file of a Hakyll site is traditionally called
-`hakyll.hs`. It is nothing special, just a small Haskell program. There is no
-magic going on.
-
-~~~~~{.haskell}
-import Text.Hakyll (hakyll)
-import Control.Monad.Trans (liftIO)
-main = hakyll "http://example.com" $ do
- liftIO $ putStrLn "I'm in your computer, generating your site!"
-~~~~~
-
-Note how we wrap everything in the `hakyll` function. This is useful because
-it will generate a very nice main function. We also pass the full site URL to
-the `hakyll` function. If you don't have an URL for your site yet, it doesn't
-really matter for now; just fill in anything then. The URL is only used for
-certain specific purposes where a full URL is needed, such as rendering RSS
-feeds.
-
-## Context
-
-Let's look at one of the most important types in Hakyll.
-
-~~~~~{.haskell}
-type Context = Map String String
-~~~~~
-
-A `Context` is a key-value mapping, used to represent pieces of information.
-One way to write such a `Context`, is a page.
-
-## Pages
-
-Another important concept in Hakyll is pages. Pages are text files that can be
-written in markdown, html, rst... basically anything Pandoc supports.
-Furthermore, they can also contain some metadata. The metadata is placed in the
-file header and surrounded by `---` lines. Each line should contain a
-`key: value` pair. Let's have a look at the `index.markdown` page.
-
- ---
- title: About
- ---
- Nullam imperdiet sodales orci vitae molestie.
- Nunc quam orci, pharetra a rhoncus vitae,
- eleifend id felis. Suspendisse potenti...
-
-This contains one `key: value` pair, namely `title: About`. The rest of the
-file is treated as markdown by pandoc. If you want to know more about
-markdown, I think [this](http://daringfireball.net/projects/markdown/syntax)
-is a pretty good page.
-
-## Templates
-
-Another concept are the so-called templates. Templates are text files (usually
-html files) containing a number of keys. The syntax for these keys is
-`$identifier`. Our example site contains one template, namely
-`templates/default.html`. Let's have a better look at that.
-
-~~~~~{.html}
-<html>
- <head>
- <title>MyAweSomeCompany - $title</title>
- <link rel="stylesheet" type="text/css"
- href="$$root/css/default.css" />
- <link rel="stylesheet" type="text/css"
- href="$$root/css/syntax.css" />
- </head>
- <body>
- <h1>MyAweSomeCompany - $title</h1>
- <div id="navigation">
- <a href="$$root/index.html">Home</a>
- <a href="$$root/about.html">About</a>
- <a href="$$root/code.html">Code</a>
- </div>
-
- $body
- </body>
-</html>
-~~~~~
-
-We can see how our `Page` would fit in. When we render the page we saw using
-this template, `$title` would be replaced by `About`, and `$body` would be
-replaced by the body of the about page. `body` is the traditional name for the
-body of any page - that is the convention in Hakyll. Also note that in this
-case, `$body` would be replaced by a chunk of html - the result of the
-markdown-to-html conversion.
-
-## The $$root key
-
-There are a few "special" keys in Hakyll: one of them is the $$root key. What
-is so special about it? Well, internally, it is treated differently - but this
-should not concern you. The thing is that it is the only key you can also use
-in __Pages__.
-
-It will be substituted by a relative url part (like `..` or `../..`) so it
-points to the root directory of your site. It is recommended to use this
-whenever you need it, it can save you some time from messing with absolute
-and relative URL's.
-
-## Putting it all together
-
-Now, we'll render the page using the `renderChain` function. This function
-takes a list of templates and a `Context`. In our case, we only have one
-template, and our `Context` is the about page we just saw - we can load that
-using the `createPage` function.
-
-~~~~~{.haskell}
-import Text.Hakyll (hakyll)
-import Text.Hakyll.Render (renderChain)
-import Text.Hakyll.CreateContext (createPage)
-main = hakyll "http://example.com" $ do
- renderChain ["templates/default.html"]
- (createPage "index.markdown")
-~~~~~
-
-Or, to render all our three pages:
-
-~~~~~{.haskell}
-import Text.Hakyll (hakyll)
-import Text.Hakyll.Render (renderChain)
-import Text.Hakyll.CreateContext (createPage)
-main = hakyll "http://example.com" $ do
- render "about.rst"
- render "index.markdown"
- render "code.lhs"
- where render = renderChain ["templates/default.html"]
- . createPage
-~~~~~
-
-As you can see, we can render a variety of formats. This will create the
-following files:
-
-~~~~~
-_site/about.html
-_site/index.html
-_site/code.html
-~~~~~
-
-## CSS, images and other static files
-
-Now, we also have a css file we would like to have in the `_site` directory.
-Static files can be rendered using the `static` function in Hakyll. We could
-use:
-
-~~~~~{.haskell}
-import Text.Hakyll (hakyll)
-import Text.Hakyll.Render (static)
-main = hakyll "http://example.com" $ do
- static "css/default.css"
-~~~~~
-
-This would work, but let's not forget that Hakyll also has css compression. If
-we want to use that, we would use `css` instead of `static`.
-
-~~~~~{.haskell}
-import Text.Hakyll (hakyll)
-import Text.Hakyll.Render (css)
-main = hakyll "http://example.com" $ do
- css "css/default.css"
-~~~~~
-
-If we were to create another css file, we would have to add a line to our
-`hakyll.hs` configuration file. This is pretty stupid, because the whole
-directory `css` contains only css files. That's why Hakyll has a `directory`
-function, which will execute a given function on an entire directory. So,
-our example would become:
-
-~~~~~{.haskell}
-import Text.Hakyll (hakyll)
-import Text.Hakyll.Render (css)
-import Text.Hakyll.File (directory)
-main = hakyll "http://example.com" $ do
- directory css "css"
-~~~~~
-
-## Deploying
-
-To setup your site, simply copy the contents of `_site` to your hosting provider
-using your favorite piece of software.
-
-## The gist of it
-
-- You render "pages" with "templates".
-- The most common render function is `renderChain`.
-- Hakyll also deals with static files and css.
diff --git a/examples/hakyll/tutorials/part02.markdown b/examples/hakyll/tutorials/part02.markdown
deleted file mode 100644
index 3df3c1f..0000000
--- a/examples/hakyll/tutorials/part02.markdown
+++ /dev/null
@@ -1,91 +0,0 @@
----
-title: Arrows: A Crash Course
-what: illustrates how Arrows are used in hakyll
----
-
-## Do I really need to know this stuff?
-
-Maybe. You don't need it when you only use the basic Hakyll functions, but
-Arrows are used a lot in the Hakyll code, and a lot of the more advanced
-features make use of Arrows. Besides, it's a pretty interesting subject.
-
-## What is an "Arrow"
-
-Arrows are comparable with monads. In fact, monads are a subset of arrows.
-Arrows allow you to represent a "computation". This is all pretty vague, so
-let's skip directly to the Arrows used in Hakyll.
-
-## HakyllAction
-
-The Arrow used throughout Hakyll is called `HakyllAction`. Arrows have two
-type parameters, so it's actually `HakyllAction a b`. You can think of `a`
-as the input for our action, and `b` is the corresponding output. Let's look
-at the type of `createPage`:
-
-~~~~~{.haskell}
-createPage :: FilePath -> HakyllAction () Context
-~~~~~
-
-So, you give `createPage` a `FilePath`, and it creates a `HakyllAction` that
-produces a `Context` out of thin air. Now, we want to render the `Context` we
-just loaded with a template. The type of the `render` function is:
-
-~~~~~{.haskell}
-render :: FilePath -> HakyllAction Context Context
-~~~~~
-
-We pass the file name of a template to the `render` function, and we get a
-`HakyllAction` that creates a `Context` from another `Context`. The result
-of the `render` operation (so basically the rendered template) will be placed
-in the `$body` field of the new `Context`. But we still haven't saved our
-result, so let's do that using the `writePage` function.
-
-~~~~~{.haskell}
-writePage :: HakyllAction Context ()
-~~~~~
-
-This function writes our result and returns nothing.
-
-## Composition
-
-Now, let's look at the big picture.
-
-![Arrow illustration]($root/images/arrow-composition.png)
-
-If these were regular functions, we could've composed them using the `.`
-operator. Since they're arrows, we'll have to use the `>>>` operator.
-
-~~~~~{.haskell}
-test :: HakyllAction () ()
-test = createPage "test.markdown"
- >>> render "template.html"
- >>> writePage
-~~~~~
-
-Now, we only have to execute our test.
-
-~~~~~{.haskell}
-runHakyllActionIfNeeded test
-~~~~~
-
-## Aso, the point emerges
-
-The `runHakyllActionIfNeeded` suggests why we use arrows. `HakyllAction` is more
-than just a function, it also tracks dependencies. This causes Hakyll to only
-execute our functions when it is really needed. In this particular case, `test`
-would only be executed if either `test.markdown` or `template.html` were
-recently changed.
-
-## So what's renderChain then?
-
-Now, we have done pretty much the same as we did with the `renderChain` function
-in the first part. That's right, the `renderChain` is more or less implemented
-like this. So, you will probably use `renderChain` in most cases, but it's
-handy if you know how it works.
-
-## The gist of it
-
-- Arrows really aren't complicated.
-- Compose them using `>>>`.
-- `HakyllAction` tracks dependencies for you. Use it.
-- In most cases, you will just use `renderChain`.
diff --git a/examples/hakyll/tutorials/part03.markdown b/examples/hakyll/tutorials/part03.markdown
deleted file mode 100644
index 0ba633e..0000000
--- a/examples/hakyll/tutorials/part03.markdown
+++ /dev/null
@@ -1,174 +0,0 @@
----
-title: How to write pages
-what: elaborates a little on writing pages
----
-
-## The structure of a Page
-
-The most important thing to realize is that a page is reduced to a `Context`,
-and therefore is just a key-value mapping. Another example:
-
- ---
- title: About
- author: Mia Wallace
- ---
- Hello there! This is
- a simple about page.
-
-This will produce the following mapping:
-
-- `$title`: About
-- `$author`: Mia Wallace
-- `$body`: Hello there! This is a simple about page.
-
-`$body` is the traditional name for the main body part of a page. If the page
-has a `.markdown` extension for example, this would also be rendered by pandoc.
-But pages are more flexible. The following is also a valid page:
-
- Hello there! This is
- a simple about page.
-
-This will produce one key-value pair:
-
-- `$body`: Hello there! This is a simple about page.
-
-But Hakyll can do more than this. You can add extra sections, apart from the
-body, and even leave out the body.
-
- ---
- author: Vincent Vega
-
- --- prelude
- A small introduction goes here. I can write *markdown*
- here, by the way. Well, assuming this page has a
- `.markdown` extension.
-
- --- main
- I can write some more things here.
-
- ---
- The body comes last, and is optional.
-
-This will produce the following:
-
-- `$author`: Vincent Vega
-- `$prelude`: A small introduction goes here. I can write *markdown* here, by the
- way. Well, assuming this page has a `.markdown` extension.
-- `$main`: I can write some more things here.
-- `$body`: The body comes last, and is optional.
-
-The example from this tutorial (we will see later) uses this to build a
-three-column system for the website, separating content from layout.
-
-## Combining Contexts
-
-Now you know that pages, and `Context`s in general, are basically nothing more
-than key-values mappings, it is time to abuse this fact. There is another
-way to create a `Context`, called `combine`.
-
-The type signature of the `combine` function does a pretty good job at
-explaining it:
-
-~~~~~{.haskell}
-combine :: HakyllAction () Context
- -> HakyllAction () Context
- -> HakyllAction () Context
-~~~~~
-
-This means we can take two `Context`s values and combine them. This is
-basically a `Map.union`: The result will contain all keys from both `Context`s,
-with there corresponding values. If a key is present in both `Context`s, the
-value from the first argument will be chosen. This is, for example, almost
-always the case with the `$url` field (since almost all `Context`s have an url
-in Hakyll).
-
-Combining two `Context`s, but overriding the `$url` is quite common, so there is
-another function that helps us here:
-
-~~~~~{.haskell}
-combineWithUrl :: FilePath
- -> HakyllAction () Context
- -> HakyllAction () Context
- -> HakyllAction () Context
-~~~~~
-
-## The example
-
-Now that we have the tools, we'll get on to the example. This time, we'll
-be making a more advanced brochure site. Here [is a zip file] containing the
-source code for the tutorial.
-
-[is a zip file]: $root/examples/morepages.zip
-
-Every page consists of three sections, originally named `section1`, `section2`
-and `section3`. So our pages look more or less like this:
-
- ---
- title: About
-
- --- section1
- ## Mattis
- Nullam imperdiet sodales orci vitae molestie. Nunc...
-
- --- section2
- ## Orci
- Vivamus eget mauris sit amet nulla laoreet lobortis.
- Nulla in...
-
- --- section3
- ## Augue
- In urna ante, pulvinar et imperdiet nec, fermentum ac...
-
-The cool thing is we do not have to specify how these will be layed out. In our
-template, we decide to use a simple three column system:
-
-~~~~~{.html}
-<div class="column"> $section1 </div>
-<div class="column"> $section2 </div>
-<div class="column"> $section3 </div>
-~~~~~
-
-The columns are then floated using css. So far so good, but what if we wanted
-an additional text block on every page? An easy solution would be to add this
-to the template, but then our layout-content separation idea will be broken
-again. So we simply add to the template:
-
-~~~~~{.html}
-<div class="footer"> $footer </div>
-~~~~~
-
-And now we will use `combine` to put the footer on every page - so we need to
-add the footer page to every `Context`. We write a small auxiliary function
-that combines a given `Context` with the footer:
-
-~~~~~{.haskell}
-withFooter = flip combine $ createPage "footer.markdown"
-~~~~~
-
-Note that we use `flip` here - we want `footer.markdown` to be our second
-argument. That is because Hakyll will take the `$url` from the first `Context`,
-so all pages would be rendered to `footer.html` - obviously not what we want.
-Now, were we previously wrote:
-
-~~~~~{.haskell}
-render "about.markdown"
-where render = renderChain ["templates/default.html"]
- . createPage
-~~~~~
-
-We simply have to add our footer:
-
-~~~~~{.haskell}
-render "about.markdown"
-where render = renderChain ["templates/default.html"]
- . withFooter
- . createPage
-~~~~~
-
-And now every page will include the footer.
-
-## The gist of it
-
-- Pages are just key-value mappings.
-- You can have multiple sections in every page.
-- Combine pages using the `combine` function.
diff --git a/examples/hakyll/tutorials/part04.markdown b/examples/hakyll/tutorials/part04.markdown
deleted file mode 100644
index 22fc846..0000000
--- a/examples/hakyll/tutorials/part04.markdown
+++ /dev/null
@@ -1,60 +0,0 @@
----
-title: How to write templates
-what: more information on template writing
----
-
-## Simple templates
-
-Simple templates are simply HTML files, with `$identifiers`. An example:
-
-~~~~~{.html}
-<html>
- <head>
- <title>$title</title>
- </head>
- <body>
- $body
- </body>
-</html>
-~~~~~
-
-## Markup in templates
-
-Most of the examples in these tutorials use HTML for templates. However, since
-Hakyll 2.2, it is possible use other markup languages in your templates. Simply
-use an appropriate extension, and Hakyll will pick it up. For example, you could
-write your `templates/post.markdown` template as:
-
- # $title
-
- _On $date_
-
- $body
-
-__Warning__: you shouldn't use markdown for your "root" template, as these
-templates will never insert things like the doctype for you -- so you always
-need at least one top-level HTML template.
-
-## Hamlet templates
-
-From Hakyll 2.3 onwards, it is possible to use [hamlet] templates. You can find
-more information about hamlet on that website. Usage is fairly simple -- since
-pages are strictly key-value mappings, only `$variable$` control is supported in
-hamlet templates. As an example, here is the template that can be used for the
-brochure site, but in hamlet:
-
- !!!
- %html
- %head
- %title MyAweSomeCompany - $$title$
- %body
- %h1 MyAweSomeCompany - $$title$
- #navigation
- %a!href="$$root$/index.html" Home
- %a!href="$$root$/about.html" About
- %a!href="$$root$/code.html" Code
- $body$
-
-Hakyll will recognise hamlet templates automatically by the `.hamlet` extension.
-
-[hamlet]: http://docs.yesodweb.com/hamlet/
diff --git a/examples/hakyll/tutorials/part05.markdown b/examples/hakyll/tutorials/part05.markdown
deleted file mode 100644
index be71714..0000000
--- a/examples/hakyll/tutorials/part05.markdown
+++ /dev/null
@@ -1,157 +0,0 @@
----
-title: Creating a Blog
-what: creates a simple blog
----
-
-## Creating a simple blog with Hakyll
-
-After we created a simple brochure site, we're going to try something more
-advanced: we are going to create a simple blog system.
-
-A [zip file] containing the source for this tutorial is also available.
-
-[zip file]: $root/examples/simpleblog.zip
-
-Blogs, as you probably know, are composed of posts. In Hakyll, we're going
-to use simple pages for posts. All posts are located in the `posts`
-directory. But we're not going to use the `directory` command here - you will
-see why later. First, some trivial things like css.
-
-~~~~~{.haskell}
-main = hakyll "http://example.com" $ do
- directory css "css"
-~~~~~
-
-## Finding the posts
-
-`Text.Hakyll.File` contains a handy function `getRecursiveContents`, which will
-provide us with all the blog posts. The blog posts have a
-`yyyy-mm-dd-title.extension` naming scheme. This is just a simple trick so we
-can sort them easily (sorting on filename implies sorting on date). You could of
-course name them whatever you want, but it's always a good idea to stick to the
-conventions. They contain some metadata, too:
-
- title: A first post
- author: Julius Caesar
- date: November 5, 2009
- ---
- Lorem ipsum dolor sit amet, consectetur adipiscing elit.
- Vivamus pretium leo adipiscing lectus iaculis lobortis.
- Vivamus scelerisque velit dignissim metus...
-
-Now, we find the posts and sort them reversed, so the most recent post will
-become the first item in the list:
-
-~~~~~{.haskell}
-postPaths <- liftM (reverse . sort) $ getRecursiveContents "posts"
-~~~~~
-
-Our `postPaths` value is now of the type `[FilePath]`. We want to be able to
-render all posts, so we pass them to the `createPage` function.
-
-~~~~~{.haskell}
-let postPages = map createPage postPaths
-~~~~~
-
-We have two templates we want to render our posts with: first we would like to
-render them using `templates/post.html`, and we want to render the result
-using `templates/default.html`. This can be done with the `renderChain`
-function:
-
-~~~~~{.haskell}
-mapM_ (renderChain [ "templates/post.html"
- , "templates/default.html"
- ]) postPages
-~~~~~
-
-Remember that the `renderChain` works by rendering the item using the first
-template, creating a new page with the render result in the `$body` field, and
-so on until it has been rendered with all templates.
-
-Now, we have the posts rendered. What is left is to generate some kind of index
-page with links to those posts. We want one general list showing all posts, and
-we want to show a few recent posts on the index page.
-
-## Creating listings.
-
-`createPage` is the easiest way of reading a `Context`. But in this case, we
-want something more custom, so we'll use the `createCustomPage` function. This
-allows us to create a more specific `Context`.
-
-~~~~~{.haskell}
-createCustomPage :: FilePath
- -> [(String, Either String (HakyllAction () String))]
- -> HakyllAction () Context
-~~~~~
-
-The first argument is the `url` of the page to generate. For our index page,
-this will be, `index.html`. The second argument is obviously our `key: value`
-mapping. But why the `Either`? This, once again, is about dependency handling.
-The idea is that you can choose which type to use for the value:
-
-- `String`: Simply a `String`.
-- `HakyllAction () String`: Here, you can give an `HakyllAction` Arrow action
- that can produce a String. However - this action _will not be executed_ when
- the file in `_site` is up-to-date.
-
-However, in this specific case - a list of posts - there is an easier, and more
-high-level approach than `createCustomPage`[^1]. Let's look at the type
-signature of `createListing`:
-
-~~~~~{.haskell}
-createListing :: FilePath
- -> [FilePath]
- -> [HakyllAction () Context]
- -> [(String, Either String (HakyllAction () String))]
- -> HakyllAction () Context
-~~~~~
-
-[^1]: Since Hakyll-1.3 onwards.
-
-The first argument is the destination url. For our blog, this is of course
-`index.html`. The second argument is a list templates to render _each_ `Context`
-with. We use only `templates/postitem.html` here. This is, as you can see, a
-simple template:
-
-~~~~~{.html}
-<li>
- <a href="$$root/$url">$title</a>
- - <em>$date</em> - by <em>$author</em>
-</li>
-~~~~~
-
-We then give a list of `Context`s to render. For our index, these are the 3 last
-posts. The last argument of the `createListing` functions lets you specify
-additional key-value pairs, like in `createCustomPage`. We use this to set the
-title of our page. So, we create our index page using:
-
-~~~~~{.haskell}
-let index = createListing "index.html"
- ["templates/postitem.html"]
- (take 3 postPages)
- [("title", Left "Home")]
-~~~~~
-
-The result of this will be a `HakyllAction () Context`. This `Context`'s `$body`
-will contain a concatenation of all the 3 posts, rendered with the
-`templates/postitem.html` template.
-
-Now, we only have to render it: first using the `index.html` template - which
-adds some more information to our index - then using the
-`templates/default.html` template.
-
-~~~~~{.haskell}
-renderChain ["index.html", "templates/default.html"] index
-~~~~~
-
-Note that the `index.html` in the `renderChain` list is also a template. Now,
-you might want to take your time to read the `index.html` template and the other
-files in the zip so you understand what is going on here.
-
-## The gist of it
-
-- You can find blogposts using `getRecursiveContents`.
-- The convention is to call them `yyyy-mm-dd-rest-of-title.extension`. This
- allows us to sort them easily.
-- You can use `createCustomPage` or `createListing` to create custom pages and
- simple listings.
diff --git a/examples/hakyll/tutorials/part06.markdown b/examples/hakyll/tutorials/part06.markdown
deleted file mode 100644
index d64dc55..0000000
--- a/examples/hakyll/tutorials/part06.markdown
+++ /dev/null
@@ -1,84 +0,0 @@
----
-title: Creating feeds
-what: adds an rss feed to the simple blog
----
-
-## Adding Feeds
-
-In this tutorial, we're going to add an RSS feed to the blog we wrote in the
-previous part. Here is a [zip file] containing the source.
-
-[zip file]: $root/examples/feedblog.zip
-
-You will be glad to hear that Hakyll has native support for RSS as well as Atom
-feeds[^1]. This simplifies our object a lot.
-
-[^1]: Since Hakyll-2.0
-
-This is the first time that the absolute URL of your site you have to give to
-the `hakyll` function actually matters. That's because the specifications of
-those feed formats dictate you need the full URL of them.
-
-## Creating a configuration
-
-The first thing to do is creating a configuration for your feed. You could
-place this code outside of your main function, as is done in the example.
-
-~~~~~{.haskell}
-myFeedConfiguration = FeedConfiguration
- { feedUrl = "rss.xml"
- , feedTitle = "SimpleBlog RSS feed."
- , feedDescription = "Simple demo of a feed created with Hakyll."
- , feedAuthorName = "Jasper Van der Jeugt"
- }
-~~~~~
-
-Note that we enter the url of the feed in our configuration. So the function
-to render our feed only takes two arguments, the configuration and a list of
-items to put in the feed. Let's put the three most recent posts in our feed.
-
-~~~~~{.haskell}
-renderRss myFeedConfiguration (take 3 postPages)
-~~~~~
-
-## But it's not that easy
-
-If you look at our generated RSS feed (build the site), you will see
-`$description` tags appearing in our final render. We don't want that! How
-did they get there in the first place?
-
-To render feeds, Hakyll expects a number of fields in the renderables you put
-in the feed. They are:
-
-- `$title`: Title of the item. This is set in our posts, since we use a `title`
- metadata field.
-- `$url`: Url of the item. This is automatically set by Hakyll, so you shouldn't
- worry about it.
-- `$description`: A description of our item to appear in the feed reader.
-
-The latter is obviously the problem: we don't have a description in our posts.
-In fact, we would like to copy the `$body` key to the `$description` key, so
-people can read the full post in their feed readers.
-
-## Where arrows come in
-
-The `Text.Hakyll.ContextManipulations` module contains a number of simple
-functions that create Arrows for us. One of these functions is `copyValue`,
-which takes a source and a destination key. So, we need to pass our
-items through this Arrow first.
-
-~~~~~{.haskell}
-renderRss myFeedConfiguration $
- map (>>> copyValue "body" "description") (take 3 postPages)
-~~~~~
-
-And that's that, now our feed gets rendered properly. Exercise for the reader
-is to add a Atom feed[^2].
-
-[^2]: Hint: look around in the [reference]($root/reference.html).
-
-## The gist of it
-
-- Hakyll has native support for RSS and Atom feeds.
-- The items must contain `$title` and `$description` fields.
-- Arrows can be used to copy values in a `Context`.
diff --git a/examples/hakyll/tutorials/part07.markdown b/examples/hakyll/tutorials/part07.markdown
deleted file mode 100644
index d017a1e..0000000
--- a/examples/hakyll/tutorials/part07.markdown
+++ /dev/null
@@ -1,221 +0,0 @@
----
-title: Tags and manipulations
-what: enhances our blog with tags and explains context manipulations.
----
-
-## Context manipulations
-
-Here, have [a zip file]($root/examples/tagblog.zip) for this tutorial.
-
-You probably remember that `Context` objects are just key-value mappings. We can
-render those with templates, and then the `$key`'s in the template get
-substituted by the appropriate values. This is a rather flexible system, but
-there are limitations. Some of these limitations can be solved using
-_context manipulations_.
-
-Like rendering actions, _context manipulations_ are also simply
-`HakyllAction Context Context` arrows. The `Text.Hakyll.ContextManipulations`
-contains some functions to easily construct easy variants.
-
-One of the most general functions is the `renderValue` function. Let's have a
-look at it's type.
-
-~~~~~{.haskell}
-renderValue :: String
- -> String
- -> (String -> String)
- -> HakyllAction Context Context
-~~~~~
-
-This is the preferred way of creating context manipulations. The first argument
-is the `key` to manipulate. The second argument is the `key` where the new value
-should be placed. If this is the same as the first argument, it will be
-replaced. The third argument is the function to manipulate the `value` with.
-
-As a simple example, let's write a function that puts the `$title` in uppercase.
-
-~~~~~{.haskell}
-import Data.Char (toUpper)
-
-titleUpper :: HakyllAction Context Context
-titleUpper = renderValue "title" "title" $ map toUpper
-~~~~~
-
-Because the destination `key` is the same as the source `key`, we can also use
-the `changeValue` function here.
-
-~~~~~{.haskell}
-titleUpper = changeValue "title" $ map toUpper
-~~~~~
-
-For further reading, refer to the `Text.Hakyll.ContextManipulations`
-documentation.
-
-## Applying Context Manipulations
-
-Because we're dealing with Arrows again, we can use `>>>` to apply our
-manipulations. For example, we could use or title manipulation like this:
-
-~~~~~{.haskell}
-renderChain ["templates/default.html"]
- (createPage "index.markdown" >>> titleUpper)
-~~~~~
-
-## Rendering dates
-
-As you remember, in our previous blog, all posts had a file name like
-`posts/yyyy-mm-dd-title.extension`, as is the Hakyll convention. But they also
-had a metadata field `date`, containing a human-readable date. This is not very
-D.R.Y., of course! Hakyll has a specialized `renderValue` function to deal with
-dates encoded in paths: `renderDate`.
-
-~~~~~{.haskell}
-postManipulation :: HakyllAction Context Context
-postManipulation = renderDate "date" "%B %e, %Y" "Unknown date"
-~~~~~
-
-That manipulation will:
-- Read the date from the file name the post was loaded from.
-- Parse the date and render it in a `%B %e, %Y` format. This is a
- `Month day, Year` format.
-- Put the result in the `date` metadata field.
-- If the date could not be parsed, it will put `"Unknown date"` in the `date`
- metadata field.
-
-So, we can throw away our `date: ` lines from our posts, and still use `$date`
-in our templates.
-
-## Abstracting the post list
-
-Now, we're going to render tags. This is also done using context manipulations.
-Hakyll has a specialized module to deal with tags, provided by
-`Text.Hakyll.Tags`. This module assumes tags are comma separated, and placed in
-the `tags` metadata field.
-
- ---
- title: A third post
- author: Publius Ovidius Naso
- tags: epic fail, ovidius
- ---
- Pellentesque tempor blandit elit, vel...
-
-But first things first. We need to render a post list for every tag. We already
-had some code to render a list of all posts. We're just going to abstract this
-code into a more general function:
-
-~~~~{.haskell}
-renderPostList url title posts = do
- let list = createListingWith url ["templates/postitem.html"]
- posts [("title", Left title)]
- renderChain ["posts.html", "templates/default.html"] list
-~~~~~
-
-Our "render all posts" action can now be written as:
-
-~~~~~{.haskell}
-renderPostList "posts.html" "All posts" renderablePosts
-~~~~~
-
-## Tag links
-
-We want to display the tags for our post under the title. But if we use the
-`$tags` key in a template, we will just have the plain tags - they will not be
-clickable. We can again solve this with a `ContextManipulation`. We have a
-function that produces an url for a given tag:
-
-~~~~~{.haskell}
-tagToUrl tag = "$root/tags/" ++ removeSpaces tag ++ ".html"
-~~~~~
-
-`removeSpaces` is an auxiliary function from `Text.Hakyll.File`. Now, there is
-a specialized `renderValue` function for creating linked tags called
-`renderTagLinks`. This function simply takes a function that produces an url
-for a given tag - the function we just wrote. Let's extend our
-`postManipulation`.
-
-~~~~~{.haskell}
-postManipulation :: HakyllAction Context Context
-postManipulation = renderDate "date" "%B %e, %Y" "Unknown date"
- >>> renderTagLinks tagToUrl
-~~~~~
-
-We apply this manipulation when we load the tags.
-
-~~~~~{.haskell}
-let renderablePosts =
- map ((>>> postManipulation) . createPage) postPaths
-~~~~~
-
-So, the `renderTagLinks` function replaces the `$tags` value from
-`epic fail, random` to `<a href="$root/tags/epic-fail.html">epic fail</a>, ...`.
-If we click a tag, we get a `404`. That's because we haven't generated the
-post lists for every tag.
-
-## The Tag Map
-
-Hakyll provides a function called `readTagMap`. Let's inspect it's type.
-
-~~~~~{.haskell}
-type TagMap = Map String [HakyllAction () Context]
-readTagMap String [FilePath] -> HakyllAction () TagMap
-~~~~~
-
-You give it a list of paths, and it creates a map that, for every tag, holds
-a number of posts. We can easily use this to render a post list for every tag.
-The first argument given is an "identifier", unique to this tag map. Hakyll
-needs this so it can cache the tags.
-
-~~~~~{.haskell}
-let tagMap = readTagMap "postTags" postPaths
-~~~~~
-
-When we have the `TagMap`, we can need to render a post list for every tag.
-There is a function in Hakyll designed more or less for this purpose:
-`withTagMap`. This takes a `TagMap` and an action to execute for every tag and
-it's associated posts. We pass a small function to it we create ourselves[^1]:
-
-[^1]: Exercise for the reader: why do we use `>>> postManipulation` again here?
-
-~~~~~{.haskell}
-let renderListForTag tag posts =
- renderPostList (tagToUrl tag)
- ("Posts tagged " ++ tag)
- (map (>>> postManipulation) posts)
-withTagMap tagMap renderPostList
-~~~~~
-
-There we go. We now have clickable tags, and a post list for every tag.
-
-## A Tag Cloud
-
-A tag cloud is a commonly found thing on blogs. Hakyll also provides code to
-generate a tag cloud. Let's have a look at the `renderTagCloud` function.
-
-~~~~~{.haskell}
-renderTagCloud :: (String -> String)
- -> Float
- -> Float
- -> HakyllAction TagMap String
-~~~~~
-
-The first argument is, once again, a function to create an url for a given tag.
-Then, we give a minimum and a maximum font size in percent, and we get a tag
-cloud Arrow back. We can add this to our index:
-
-~~~~~{.haskell}
-let tagCloud = tagMap >>> renderTagCloud tagToUrl 100 200
- index = createListing "index.html"
- ["templates/postitem.html"]
- (take 3 renderablePosts)
- [ ("title", Left "Home")
- , ("tagcloud", Right tagCloud)
- ]
-renderChain ["index.html", "templates/default.html"] index
-~~~~~
-
-## The gist of it
-
-- There's some handy, simple functions in `Text.Hakyll.ContextManipulations`.
-- Seperate tags by commas and put them in the `$tags` field.
-- Use `withTagMap` to render a list for every tag.
-- Hakyll can also create tag clouds.
diff --git a/examples/hakyll/tutorials/part08.markdown b/examples/hakyll/tutorials/part08.markdown
deleted file mode 100644
index ec27153..0000000
--- a/examples/hakyll/tutorials/part08.markdown
+++ /dev/null
@@ -1,97 +0,0 @@
----
-title: Interlude
-what: gives some various tips and tricks about Hakyll (quite handy, read this!)
----
-
-## Syntax-highlighting
-
-Pandoc (which Hakyll uses as a backend) offers powerful syntax highlighting.
-To enable this, Pandoc needs to be compiled with highlighting support. If this
-is not the case, you can fix this using:
-
-~~~~~
-[jasper@alice ~]$ cabal install --reinstall -fhighlighting pandoc
-~~~~~
-
-## Auto-compilation
-
-Hakyll features a simple _auto-compilation_ mode. This is invoked by running
-
-~~~~~
-[jasper@alice ~]$ ./hakyll preview
-Starting hakyll server on port 8000...
-~~~~~
-
-Now, Hakyll will recompile your site when you refresh in your browser. This will
-not update your site automatically when `hakyll.hs` changes. So if you make any
-changes to the configuration file, you'll have to compile it again, and then you
-can enter `preview` mode again.
-
-If you use a custom `HakyllConfiguration`, you can select your custom
-`PreviewMode`:
-
-- `BuildOnRequest`: rebuild site when the preview server receives a request
- (default).
-- `BuildOnInterval`: build when you change files.
-
-## When to rebuild
-
-If you execute a `./hakyll build`, Hakyll will build your site incrementally.
-This means it will be very fast, but it will not pick up _all_ changes.
-
-- In case you edited `hakyll.hs`, you first want to compile it again.
-- It is generally recommended to do a `./hakyll rebuild` before you deploy your
- site.
-
-After rebuilding your site, all files will look as "modified" to the filesystem.
-This means that when you upload your site, it will usually transfer all files --
-this can generate more traffic than necessary, since it is possible that some
-files were not actually modified. If you use `rsync`, you can counter this using
-the `--checksum` option.
-
-## Pretty URL's
-
-There is an option in Hakyll to produce pretty URL's, which is disabled by
-default because it can be confusing when you're first introduced to Hakyll.
-
-It can be enabled this way:
-
-~~~~~{.haskell}
-import Text.Hakyll
-import Text.Hakyll.HakyllMonad
-
-myConfig :: HakyllConfiguration
-myConfig = (defaultHakyllConfiguration "http://jaspervdj.be")
- { enableIndexUrl = True
- }
-
-main = hakyllWithConfiguration myConfig $ do
- -- Further code here
-~~~~~
-
-The effect will be that the internal `toUrl` function will behave differently.
-A few examples:
-
-- `about.html` will be rendered to `about/index.html`.
-- `posts/2010-02-16-a-post.markdown` will be rendered to
- `posts/2010-02-16-a-post/index.html`.
-- However, `index.markdown` will still be rendered to `index.html`. Likewise,
- `posts/index.html` would be rendered to `posts.index.html`.
-
-The benefit of this is simply prettier URL's. That is, if you consider
-`example.com/about` prettier than `example.com/about.html`.
-
-## Default values
-
-At some point, you might want to use a number of global key-value pairs, for
-example, `$author`. There are two possible ways to achieve this.
-
-- There is an option in `HakyllConfiguration` supporting this, called
- `additionalContext`. For an example on how to use `HakyllConfiguration`, see
- the pretty URL's section above.
-
-- Another option is to use a `defaults.markdown` file, simply containing some
- metadata, and then `combine` this file with other pages. The advantage is
- that autocompilation mode will pick up changes in this file[^1].
-
-[^1]: Original idea by zenzike.
diff --git a/examples/hakyll/tutorials/part09.markdown b/examples/hakyll/tutorials/part09.markdown
deleted file mode 100644
index 4cc1d43..0000000
--- a/examples/hakyll/tutorials/part09.markdown
+++ /dev/null
@@ -1,104 +0,0 @@
----
-title: CategoryBlog
-what: explains how to use categories instead of tags
----
-
-## Categories
-
-Most people familiar with "tags" will also know the concept "categories".
-
-![Tags illustration]($root/images/tutorial8-tags.png)
-
-In fact, tags are harder to implement because they have to be represented as a
-many-to-many relation, and categories are a simple 1-to-many relation.
-
-![Tags illustration]($root/images/tutorial8-categories.png)
-
-This is also the reason you can "simulate" categories using tags. In this
-tutorial we will adapt the blog to use categories instead of tags. Here is
-[a zip file]($root/examples/categoryblog.zip) containing the files used in this
-tutorial.
-
-## About category support
-
-Categories are simpler, but they are usually used in custom ways. That's why
-Hakyll provides less "standard" functions to deal with them. But this gives us
-another chance to learn some of the things we can do with Hakyll.
-
-## Reading Categories
-
-Tags are located in the `tags` metadata field. Since one post can only belong
-in one category, a different approach was chosen here. The category of a post
-is determined by the subfolder it is in. Here you see the directory layout for
-our posts using categories:
-
- posts
- |-- coding
- | |-- 2009-11-05-a-first-post.markdown
- | |-- 2009-11-28-a-third-post.markdown
- | `-- 2009-12-04-this-blog-aint-dead.markdown
- `-- random
- |-- 2009-11-10-another-post.markdown
- `-- 2009-12-23-almost-christmas.markdown
-
-Because we find all our posts in different subdirectories, sorting them is a
-little harder: we still want them sorted by date, so it boils down to sorting
-them by "base name". I hope it does not surprise you Hakyll provides a function
-for that:
-
-~~~~~{.haskell}
-postPaths <- liftM (reverse . sortByBaseName)
- (getRecursiveContents "posts")
-~~~~~
-
-We reverse them again, because we want the most recent posts first. Now, we can
-use the `readCategoryMap` function instead of `readTagMap`, which has the same
-signature, but assigns categories based on the folders the posts are in.
-
-~~~~~{.haskell}
-categoryMap <- readCategoryMap "categoryMap" renderablePosts
-~~~~~
-
-The rest of the `hakyll.hs` is very similar to the one in the previous
-tutorial, except we want to render a category list instead of a tag cloud.
-
-## Rendering a category list
-
-Because rendering a category list is quite easy, and it would be hard to
-write a "general" function for this, hakyll does not provide such a function --
-but it is not hard to write. First, we write an auxiliary function that produces
-a list item for one category:
-
-~~~~~{.haskell}
-categoryListItem category posts =
- "<li>" ++ link category (categoryToUrl category)
- ++ " - " ++ show (length posts) ++ " items.</li>"
-~~~~~
-
-This is nothing more that some basic string concatenation to create a `li` HTML
-element. The function that applies this on every element in the `TagMap` is more
-interesting:
-
-~~~~~{.haskell}
-categoryList :: HakyllAction TagMap String
-categoryList = arr $ uncurry categoryListItem <=< toList
-~~~~~
-
-This function might seem a little harder to understand if you are not familiar
-with the `<=<` operator -- but it's just right-to-left monad composition in the
-list monad. `uncurry categoryListItem <=< toList` is a pure function we want to
-execute on the `TagMap`. But this is not possible in Hakyll[^1]. We need to make
-an arrow of this function. The `arr` function solves this problem easily.
-
-[^1]: This is a feature, not a bug. It helps dependency handling.
-
-We then add this to our index page, and we are done. Feel free to hack around
-with the source code. If you still have questions, feel free to ask them at the
-[google discussion group](http://groups.google.com/group/hakyll).
-
-## The gist of it
-
-- Hakyll supports categories as well as tags.
-- Tags are actually a generalization of categories.
-- Use `readCategoryMap` to read categories.
-- You need to write some custom functions to render category lists etc.