summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--web/site.hs2
-rw-r--r--web/tutorials/05-arrows.markdown223
-rw-r--r--web/tutorials/06-guide.markdown129
-rw-r--r--web/tutorials/guide.markdown99
4 files changed, 100 insertions, 353 deletions
diff --git a/web/site.hs b/web/site.hs
index f8b3794..6130bea 100644
--- a/web/site.hs
+++ b/web/site.hs
@@ -67,5 +67,5 @@ config :: Configuration
config = defaultConfiguration
{ verbosity = Debug
, deployCommand = "rsync --checksum -ave 'ssh -p 2222' \
- \_site/* jaspervdj@jaspervdj.be:jaspervdj.be/hakyll"
+ \_site/* jaspervdj@jaspervdj.be:jaspervdj.be/tmp/hakyll4"
}
diff --git a/web/tutorials/05-arrows.markdown b/web/tutorials/05-arrows.markdown
deleted file mode 100644
index 3f2e244..0000000
--- a/web/tutorials/05-arrows.markdown
+++ /dev/null
@@ -1,223 +0,0 @@
----
-title: Arrow Magic: Metadata Dependent Page Generation
-author: Florian Hars
----
-
-## Supporting a "published: false" attribute on pages
-
-Many content management systems or blog platforms support
-some kind of workflow that display articles differently or
-not at all depending on which state the article is in, for
-example whether it has a "published" attribute or not.
-Hakyll has no built-in support for anything like this, but since
-its compilers are just arrows, it is easy to implement arbitrary
-metadata dependent behaviour for rendering pages.
-
-Let's start by adding support for a "published" attributes to the
-`simpleblog` example. We want to consider a blog post published if it
-has a `published` metadata element that does not have the value
-`false`. A function to test for this is simple:
-
-~~~~~{.haskell}
-isPublished :: Page a -> Bool
-isPublished p =
- let published = getField "published" p in
- published /= "" && published /= "false"
-~~~~~
-
-The next step is to write a function that tags a page with its
-published status, which can be either unpublished or published, using
-the standard `Either` datatype and then transform this function
-into a `Compiler`. The latter can be done with the standard `arr`
-function from `Control.Arrow`, which lifts a function into an arrow:
-
-~~~~~{.haskell}
-isPagePublished :: Compiler (Page a) (Either (Page a) (Page a))
-isPagePublished = arr (\p -> if isPublished p then Right p else Left p)
-~~~~~
-
-For the next processing steps we now need a compiler that takes an
-`Either (Page a) (Page a)` instead of the usual `Page a` as an
-input. But the former can be built up from the latter using some
-standard combinators from the `Control.Arrow` library. The simplest
-one is `|||`, which takes two compilers (arrows) with the same output
-type and returns a new compiler that takes an `Either` of the input
-types of the Compilers as an input. Maybe we just want to render our
-unpublished posts with a big warning that they are provisional, so we
-just want to render the unpublished `Left` pages with another template
-than the published `Right` pages:
-
-~~~~~{.haskell}
- match "posts/*" $ do
- route $ setExtension ".html"
- compile $ pageCompiler
- >>> isPagePublished
- >>> (applyTemplateCompiler "templates/embargo-post.html"
- ||| applyTemplateCompiler "templates/post.html")
- >>> applyTemplateCompiler "templates/default.html"
- >>> relativizeUrlsCompiler
-~~~~~
-
-With the conditional rendering in place, the next step is to hide
-the unpublished posts from the homepage and the list of posts.
-Both lists are generated from the results of a requireAllA call.
-The last argument of requireAllA is a Compiler, and requireAllA
-passes a pair consisting of the currently rendered page and a list
-of all the required pages. All we have to do to suppress the pages
-is to write a Compiler that takes such a pair as input, leaves the
-first element of the pair unchanged and filters out all the unpublished
-pages from list in the second element of the pair and then pass the
-output from this compiler to the existing compilers handling the
-list generation for the `index` and `posts` pages.
-
-Again, we can use a function from `Control.Arrow` to build this
-compiler from simpler ones, in this case it is `***`, which combines
-two arrows to one arrow from pairs to pairs. For our purposes, we
-combine the identity arrow, which leaves its input unchanged, and an
-ordinary `filter` on a list lifted into the compiler arrow:
-
-~~~~~{.haskell}
-filterPublished :: Compiler (Page a, [Page b]) (Page a, [Page b])
-filterPublished = id *** arr (filter isPublished)
-~~~~~
-
-All that remains to do is to chain this compiler in front of the existing
-compilers passed to requireAllA in the code for `posts.html`
-
-~~~~~{.haskell}
- >>> requireAllA "posts/*" (filterPublished >>> addPostList)
-~~~~~
-
-and for `index.html`:
-
-~~~~~{.haskell}
- >>> requireAllA "posts/*"
- (filterPublished
- >>> (id *** arr (take 3 . reverse . sortByBaseName))
- >>> addPostList)
-~~~~~
-
-You may have noticed that the code for the index page uses the same
-`id *** something` construct to extract some elements from the list
-of all posts.
-
-## Don't generate unpublished pages at all
-
-The above code will treat unpublished posts differently and hide them
-from all lists of posts, but they will still be generated, and someone
-who knows their URLs will still be able to access them. That may be
-what you need, but sometimes you might want to suppress them
-completely. The simplest way to do so is to leave the rendering
-pipeline for `"posts/*"` unchanged and just add the `isPagePublished`
-compiler at the end. This will not compile, since hakyll knows how to
-write a `Page String`, but not how to write an `Either (Page String)
-(Page String)`. But that can be amended by a simple type class
-declaration:
-
-~~~~~{.haskell}
-instance Writable b => Writable (Either a b) where
- write p (Right b) = write p b
- write _ _ = return ()
-~~~~~
-
-Now hakyll will happily generate published pages and ignore
-unpublished ones. This solution is of course slightly wasteful, as at
-will apply all the templates to an unpublished page before finally
-discarding it. You can avoid this by using the `+++` function, which
-does for the sum datatype `Either` what `***` does for the product
-type pair:
-
-~~~~~{.haskell}
- match "posts/*" $ do
- route $ setExtension ".html"
- compile $ pageCompiler
- >>> isPagePublished
- >>> (id +++ (applyTemplateCompiler "templates/post.html"
- >>> applyTemplateCompiler "templates/default.html"
- >>> relativizeUrlsCompiler))
-~~~~~
-
-The other problem with this solution is more severe: hakyll will no
-longer generate the index and posts pages due to a rare problem in
-haskell land: a runtime type error. Hakyll tries to be smart and reuse
-the parsed pages from the `match "posts/*"` when processing the
-`requireAllA "posts/*"` calls by caching them. But the compilers there
-still expect a list of pages instead of a list of eithers, so we have
-to replace `filterPublised` with something that works on the
-latter. Luckily (or, probably, by design), `Data.Either` provides just
-the function we need, so the new filtering compiler is actually
-shorter that the original, even though it has a more intimidating
-type:
-
-~~~~~{.haskell}
-filterPublishedE :: Compiler (Page a, [Either (Page b) (Page b)]) (Page a, [Page b])
-filterPublishedE = id *** arr rights
-~~~~~
-
-## Timed releases
-
-Exploiting the fact that compilers are arrows, we can do more mixing
-and matching of compilers to further refine how hakyll deals with page
-attributes like `published`. Maybe you want `cron` to update your blog
-while you are on vacation, so you want posts to be considered
-published if the `published` field is either `true` or a time in the
-past.
-
-If you happen to live in the UK in winter or enjoy to do time zone
-calculation in your head, your new function to test if a page is
-published and the compiler derived from it might then look like this
-
-~~~~~{.haskell}
-isPublishedYet :: Page a -> UTCTime -> Bool
-isPublishedYet page time =
- let published = getField "published" page in
- published == "true" || after published
- where
- after published =
- let publishAt = parseTime defaultTimeLocale "%Y-%m-%d %H:%M" published in
- fromMaybe False (fmap (\embargo -> embargo < time) publishAt)
-
-isPagePublishedYet :: Compiler (Page a, UTCTime) (Either (Page a) (Page a))
-isPagePublishedYet = arr (\(p,t) -> if isPublishedYet p t then Right p else Left p)
-~~~~~
-
-This compiler has a pair of a page and a time as its input, and we can
-use yet another function from `Control.Arrow` to construct a compiler
-that generates the input for it, the function `&&&`. It takes two
-compilers (arrows) with the same input type and constructs a compiler
-from that type to a pair of the output types of the two compilers.
-For the first argument we take the `pageCompiler` which we already
-call at the beginning of the page compilation. The second argument
-should be a compiler with the same input type as `pageCompiler` that
-returns the current time. But the current time lives in the IO monad
-and does not at all depend on the resource the current page is
-generated from, so we have to cheat a little bit by calling
-`unsafeCompiler` with a function that ignores its argument and returns
-an `IO UTCTime`, which `unsafeCompiler` will unwrap for us:
-
-~~~~~{.haskell}
- match "posts/*" $ do
- route $ setExtension ".html"
- compile $ (pageCompiler &&& (unsafeCompiler (\_ -> getCurrentTime)))
- >>> isPagePublishedYet
- >>> (id +++ ( ... as above ...))
-~~~~~
-
-This is all we have to change if we don't generate unpublished pages
-at all. If we just hide them from the lists, the call to `|||`
-discards the information that a page is not (yet) published that was
-encoded in the `Either`. In that case we could use the `setField`
-function from `Hakyll.Web.Page.Metadata` to rewrite the `published`
-field of the left and right pages in `isPagePublished(Yet)` to
-canonical values that the original `isPublished` function called from
-`filterPublished` understands:
-
-~~~~~{.haskell}
-isPagePublishedYet = arr (\(p,t) -> if isPublishedYet p t then pub p else unpub p)
- where
- pub p = Right $ setField "published" "true" p
- unpub p = Left $ setField "published" "false" p
-~~~~~
-
-The final version of this code can be found in the timedblog example,
-together with the required `import` statements.
diff --git a/web/tutorials/06-guide.markdown b/web/tutorials/06-guide.markdown
deleted file mode 100644
index e8c5800..0000000
--- a/web/tutorials/06-guide.markdown
+++ /dev/null
@@ -1,129 +0,0 @@
----
-title: A Guide to the Hakyll Module Zoo
-author: Brent Yorgey
----
-
-The hakyll package [contains a bewildering array](/reference/) of
-modules, and it's hard to know where to look when you are just getting
-started---especially since many of them are only used by hakyll
-internally and not that useful to website authors. This guide
-provides a quick reference to the contents of the most important and
-useful modules.
-
-## Core modules
-
-These are the modules containing the fundamental tools and concepts
-you need to get started building a site with hakyll.
-
-* [Hakyll.Core.Compiler](/reference/Hakyll-Core-Compiler.html)
-
- This is one of the modules you should look at first. It defines the
- fundamental `Compiler` type and has a bunch of documentation explaining how to
- use `Compiler`s and their `Arrow`-based interface.
-
- It also defines many primitive `Compiler`s as well as several
- variants on `require`, which allow you to bring together multiple
- resources to create a single output.
-
-* [Hakyll.Core.Routes](/reference/Hakyll-Core-Routes.html)
-
- Specify where compiled items should go in the output site.
-
-* [Hakyll.Core.Rules](/reference/Hakyll-Core-Rules.html)
-
- Specify which compilers and routes should be used on which
- resources.
-
- Also has combinators for grouping (necessary if you want to use
- the same resources for multiple purposes), creating outputs that
- are not based on any resources, and even dynamically generating
- compilers.
-
-* [Hakyll.Core.Identifier.Pattern](/reference/Hakyll-Core-Identifier-Pattern.html)
-
- Combinators for creating *patterns*, i.e. predicates that pick out
- a set of resources: filesystem globs, arbitrary predicates,
- explicit lists, regular expressions, and so on.
-
-* [Hakyll.Web.Page](/reference/Hakyll-Web-Page.html)
-
- A `Page`, consisting of some metadata and a body, is one of the
- most fundamental structures used by hakyll. This module has some
- documentation explaining how pages work, and defines a number of
- compilers and utilities for working with them.
-
-* [Hakyll.Web.Page.Metadata](/reference/Hakyll-Web-Page-Metadata.html)
-
- Utilities for manipulating page metadata.
-
-* [Hakyll.Web.Template](/reference/Hakyll-Web-Template.html)
-
- Templates specify how to take the content of a `Page` and turn
- it into HTML output.
-
-* [Hakyll.Main](/reference/Hakyll-Main.html)
-
- The main `hakyll` function that runs the whole show. There is
- also a `hakyllWith` function which allows for a custom
- configuration.
-
-## Pre-packaged solutions
-
-These modules contain some "pre-packaged" solutions for common
-situations. They can be used as-is, or their source can be used as
-inspiration for your own tools.
-
-* [Hakyll.Web.Page.List](/reference/Hakyll-Web-Page-List.html)
-
- Combine several pages into a list, such as a list of posts, images
- in a gallery, etc.
-
-* [Hakyll.Web.Feed](/reference/Hakyll-Web-Feed.html)
-
- Create RSS feeds.
-
-* [Hakyll.Web.Tags](/reference/Hakyll-Web-Tags.html)
-
- Work with tags and categories.
-
-## Useful utilities
-
-* [Hakyll.Core.UnixFilter](/reference/Hakyll-Core-UnixFilter.html)
-
- Use any unix utility as a compiler.
-
-* [Hakyll.Core.Util.Arrow](/reference/Hakyll-Core-Util-Arrow.html)
-
- A few utilities for working with arrows, including a constant
- arrow, unit arrow, and running an entire list of arrows on a
- single input.
-
-* [Hakyll.Core.Util.File](/reference/Hakyll-Core-Util-File.html)
-
- Utility functions for working with the file system.
-
-* [Hakyll.Core.Util.String](/reference/Hakyll-Core-Util-String.html)
-
- A few utility functions for working with `String`s (trim spaces,
- find and replace, split on regexp).
-
-* [Hakyll.Core.Writable.WritableTuple](/reference/Hakyll-Core-Writable-WritableTuple.html)
-
- A utility type covering the situation where you generate some
- data, some of which you want to write to disk, and some of which
- you don't want to write but will be needed in order to generate
- something else later.
-
-## Advanced customization
-
-* [Hakyll.Core.Writable](/reference/Hakyll-Core-Writable.html)
-
- The `Writable` class is for resources which can be written to disk
- as part of the output site. You can specify how to write your own
- custom types to disk by giving them a `Writable` instance.
-
-* [Hakyll.Web.Pandoc](/reference/Hakyll-Web-Pandoc.html)
-
- Some compilers for running pandoc. Normally they are run
- automatically as part of, for example, `pageCompiler`; but
- sometimes it is useful to be able to run pandoc explicitly.
diff --git a/web/tutorials/guide.markdown b/web/tutorials/guide.markdown
new file mode 100644
index 0000000..8376952
--- /dev/null
+++ b/web/tutorials/guide.markdown
@@ -0,0 +1,99 @@
+---
+title: A Guide to the Hakyll Module Zoo
+author: Brent Yorgey
+---
+
+The hakyll package [contains a bewildering array](/reference/) of modules, and
+it's hard to know where to look when you are just getting started -- especially
+since many of them are mostly just used by Hakyll internally and not that useful
+to website authors. This guide provides a quick reference to the contents of the
+most important and useful modules.
+
+## Core modules
+
+These are the modules containing the fundamental tools and concepts
+you need to get started building a site with hakyll.
+
+* [Hakyll.Core.Compiler](/reference/Hakyll-Core-Compiler.html)
+
+ This is one of the modules you should look at first. It defines the
+ fundamental `Compiler` type and primitive `Compiler`s as well as several
+ variants on `load`, which allow you to bring together multiple resources to
+ create a single output.
+
+* [Hakyll.Core.Routes](/reference/Hakyll-Core-Routes.html)
+
+ Specify where compiled items should go in the output site.
+
+* [Hakyll.Core.Rules](/reference/Hakyll-Core-Rules.html)
+
+ Specify which compilers and routes should be used on which resources. Also
+ has combinators for versions (necessary if you want to use the same
+ resources for multiple purposes).
+
+* [Hakyll.Core.Identifier.Pattern](/reference/Hakyll-Core-Identifier-Pattern.html)
+
+ Combinators for creating *patterns*, i.e. predicates that pick out a set of
+ resources: filesystem globs, explicit lists, regular expressions, and so on.
+
+* [Hakyll.Web.Page](/reference/Hakyll-Web-Pandoc.html)
+
+ Provides functions for rendering your pages using pandoc, with a varying
+ degree of high-levelness.
+
+* [Hakyll.Web.Template](/reference/Hakyll-Web-Template.html)
+
+ Templates specify how to take the content of an item and turn it into HTML
+ output.
+
+* [Hakyll.Web.Template.Context](/reference/Hakyll-Web-Template-Context.html)
+
+ You can't do much with a `Template` if you don't have a `Context`: this
+ module provides some predefined `Context`s and the tools to build your own.
+
+* [Hakyll.Main](/reference/Hakyll-Main.html)
+
+ The main `hakyll` function that runs the whole show. There is also a
+ `hakyllWith` function which allows for a custom configuration.
+
+## Pre-packaged solutions
+
+These modules contain some "pre-packaged" solutions for common situations. They
+can be used as-is, or their source can be used as inspiration for your own
+tools.
+
+* [Hakyll.Web.Page.List](/reference/Hakyll-Web-Page-List.html)
+
+ Combine several pages into a list, such as a list of posts, images in a
+ gallery, etc.
+
+* [Hakyll.Web.Feed](/reference/Hakyll-Web-Feed.html)
+
+ Create RSS feeds.
+
+* [Hakyll.Web.Tags](/reference/Hakyll-Web-Tags.html)
+
+ Work with tags and categories.
+
+## Useful utilities
+
+* [Hakyll.Core.UnixFilter](/reference/Hakyll-Core-UnixFilter.html)
+
+ Use any unix utility as a compiler.
+
+* [Hakyll.Core.Util.File](/reference/Hakyll-Core-Util-File.html)
+
+ Utility functions for working with the file system.
+
+* [Hakyll.Core.Util.String](/reference/Hakyll-Core-Util-String.html)
+
+ A few utility functions for working with `String`s (trim spaces, find and
+ replace, split on regexp).
+
+## Advanced customization
+
+* [Hakyll.Core.Writable](/reference/Hakyll-Core-Writable.html)
+
+ The `Writable` class is for resources which can be written to disk as part
+ of the output site. You can specify how to write your own custom types to
+ disk by giving them a `Writable` instance.