Tutorial: Rules, routes and compilers
Basic rules
While changing the content is nice, you’ll have time for that once your site is
configured. Configuration is done using the site.hs file: let’s take a look at
it!
main :: IO ()
main = hakyll $ do
...Hakyll configurations are in the Rules monad. In order to run them, the
hakyll function is used, so your main function usually starts this way.
hakyllWith is also available, this function allows you specify a custom
Configuration.
Some actual rules look like this:
match "images/*" $ do
route idRoute
compile copyFileCompiler
match "css/*" $ do
route idRoute
compile compressCssCompilerThis is a declarative DSL: the order in which you write the rules makes little difference, Hakyll will use dependency tracking to determine the correct order.
We group the different rules using match. The first argument for match is a
Pattern. The OverloadedStrings extension allows us to just write Strings
here, which are interpreted as globs — all files in the images/ directory,
and all files in the css/ directory.
However, we can see that one item makes no use of match, but uses create
instead.
create ["archive.html"] $ do
route idRoute
compile $ do
...Don’t pay attention to the somewhat complicated-looking stuff in compile –
this will become clear soon. The real question here is why we use create
instead of match.
The answer is simple: there is no archive.html file in our project directory!
So if we were to use match, no file would be matched, and hence, nothing
would appear in the output directory. create, however, ensures the items
listed are always produced.
Basic routes
The route function is used for determining the output file. For example, you
probably want to write the processed contents of contact.markdown to
_site/contact.html and not _site/contact.markdown.
idRoute is a commonly used route and just keeps the filename. We use this for
e.g. the images and CSS files.
setExtension is another common route which takes a single argument: the
desired extension of the resulting file. In order to route contact.markdown to
_site/contact.html, use:
route $ setExtension "html"customRoute is a more advanced higher-order function which allows for even
more customization. You want to route contact.markdown to
_site/nwodkram.tcatnoc? No problem, just use:
route $ customRoute $ reverse . toFilePathMore information can be found in the Routes module.
Basic compilers
The compile function determines how the content is produced for a certain
item. compile takes a value of the type Compiler (Item a). Let’s look at
some common examples:
copyFileCompileris self-explanatory, the output is exactly the same as the input;compressCssCompilerperforms some simple build-in compression transformations for CSS;pandocCompilerreads markdown, reStructuredText, or another input format and renders it as HTML (if you want to pass specific options to pandoc, usepandocCompilerWith).
Compilers are very flexible: Compiler is a Monad and Item is a Functor.
A good example to illustrate the Monad instance for Compiler is
relativizeUrls :: Item String -> Compiler (Item String)This compiler traverses your HTML and changes absolute URLs (e.g.
/posts/foo.markdown into relative ones: ../posts/foo.markdown). This is
extremely useful if you want to deploy your site in a subdirectory (e.g.
jaspervdj.be/hakyll instead of jaspervdj.be). Combining this with the
pandocCompiler gives us:
pandocCompiler >>= relativizeUrls :: Compiler (Item String)For a real website, you probably also want to use templates in order to give your pages produced by pandoc a nice layout. We tackle this in the next tutorial.
Other tutorials
Find links to other tutorials.Documentation inaccurate or out-of-date? Found a typo?
Hakyll is an open source project, and one of the hardest parts is writing correct, up-to-date, and understandable documentation. Therefore, the authors would really appreciate it if you would give feedback about the tutorials, and especially report errors or difficulties you encountered. If you have a github account, you can use the issue system. Thanks! If you run into any problems, all questions are welcome in the above google group, or you could try the IRC channel,#hakyll on
irc.libera.chat (we do not have
a channel on Freenode anymore).
Hakyll