diff options
Diffstat (limited to 'web')
25 files changed, 929 insertions, 0 deletions
diff --git a/web/about.markdown b/web/about.markdown new file mode 100644 index 0000000..108663b --- /dev/null +++ b/web/about.markdown @@ -0,0 +1,36 @@ +--- +title: About +--- + +## Code + +The code for Hakyll is freely available on +[github](http://github.com/jaspervdj/Hakyll/). Patches and suggestions are +always very welcome. + +## Inspiration + +Hakyll is not the only static site generator out there. It was inspired by the +following awesome projects: + +- [yst](http://github.com/jgm/yst) +- [nanoc](http://nanoc.stoneship.org/) +- [Jekyll](http://jekyllrb.com/) + +## License + +Hakyll is available under a BSD license. Note, however, that pandoc is +released under a GPL license. Since you'll probably use Hakyll with pandoc, +you will have to license your code under a GPL-compatible license. + +## Authors + +Hakyll was originally written by [Jasper Van der Jeugt](http://jaspervdj.be), +who still maintains the package. Contributors: + +- [seschwar](http://github.com/seschwar) +- [JD Marble](http://github.com/jdmarble) +- [sargon](http://github.com/sargon) +- [Paolo Veronelli](http://github.com/paolino) +- [Benedict Eastaugh](http://extralogical.net/) +- [Nicolas Wu](http://zenzike.com/) diff --git a/web/changelog.markdown b/web/changelog.markdown new file mode 100644 index 0000000..9c6c2cf --- /dev/null +++ b/web/changelog.markdown @@ -0,0 +1,137 @@ +--- +title: Changelog +--- + +## Hakyll 3.1.1 + +- Allow `group` in rules DSL + +## Hakyll 3.1 + +- New `match` function in rules DSL +- More expressive `Pattern`s + +## Hakyll 3 + +- Complete rewrite + +## Hakyll 2.4.1 + +- Add a number of utility functions +- Fix bug in `enableIndexUrl` mode + +## Hakyll 2.4 + +- Arrow based interface to pandoc +- Easier custom fields + +## Hakyll 2.3 + +- Ability to choose between preview modes. +- Simple static configuration available. +- Support hamlet templates. + +## Hakyll 2.2.2 + +- Cabal dependency fixes. + +## Hakyll 2.2.1 + +- Allow custom time locale for `renderDate`. +- Render RSS feeds with `CDATA` sections. + +## Hakyll 2.2 + +- Allow markup languages in templates. + +## Hakyll 2.1.1 + +- Fix issues in autocompilation/preview mode. + +## Hakyll 2.1 + +May 21, 2010 + +- Expose pandoc options to HakyllConfiguration. +- Allow dashes in pages. +- Some typo's and bugs fixed. + +## Hakyll 2.0 + +March 31, 2010 + +- Rewrite of the API to a clean, Arrow based API. +- Added built-in support for RSS and Atom. +- Added more documentation. +- Added pagination. +- Many bugfixes. + +## Hakyll 1.4 + +February 17, 2010 + +- Added an autocompilation feature. +- Support for index URL's (`enableIndexUrl`). + +## Hakyll 1.3 + +January 30, 2010 + +- Added categories in addition to tags. +- Added `createListing` and `createListingWith` function for a more high-level + way to create listings. + +## Hakyll 1.2 + +January 27, 2010 + +- `Data.Binary` is now used for serialization. +- Rewrite of the caching system. +- Specialized data structure for templates. +- Caching of pages and templates. + +## Hakyll 1.1 + +January 19, 2010 + +- Switched to a custom `Hakyll` monad stack instead of the `IO` monad. +- Page sections. +- Combining renderables. +- `renderAndConcat` can now use multiple templates. + +## Hakyll 1.0 + +January 14, 2009 + +- First stable release. +- Custom templating system. +- Added `$root` key for relative URL's. + +## Hakyll 0.4 + +January 8, 2010 + +- Added examples. +- Added `ContextManipulation` type. + +## Hakyll 0.3 + +December 28, 2009 + +- Added a general `directory` function. +- Added CSS compression. +- Added tag support. +- Added a simple HTTP server for testing purposes. + +## Hakyll 0.2 + +December 16, 2010 + +- Abstracted `Renderable` type. +- Added simple caching and dependency checking. + +## Hakyll 0.1 + +December 5, 2009 + +- Initial release. diff --git a/web/css/default.css b/web/css/default.css new file mode 100644 index 0000000..06f664c --- /dev/null +++ b/web/css/default.css @@ -0,0 +1,118 @@ +html { + padding: 0px; + margin: 0px; + background-color: white; + color: black; + font-family: sans-serif; + line-height: 160%; +} + +body { + padding: 0px 0px 60px 0px; + margin: 0px; +} + +div#header { + height: 32px; + padding: 20px 0px 20px 60px; +} + +div#header img { + display: inline; + vertical-align: middle; +} + +div#header h1 { + padding-left: 10px; + display: inline; + text-transform: uppercase; + vertical-align: middle; +} + +div#main { + margin: 0px auto 0px auto; + width: 860px; +} + +div#sidebar { + margin-right: 30px; + width: 160px; + float: left; + text-align: right; +} + +div#sidebar a { + display: block; + font-size: 110%; + text-decoration: none; + margin-bottom: 10px; + text-transform: uppercase; +} + +div#content { + width: 670px; + float: right; +} + +div#footer { + padding-top: 30px; + clear: both; + font-size: 90%; + text-align: center; +} + +a { + color: black; +} + +h2 { + font-size: 120%; + text-transform: uppercase; +} + +h3 { + font-size: 100%; + text-transform: uppercase; +} + +h1 a, h2 a, h3 a { + text-decoration: none; +} + +div.column { + width: 50%; + float: left; +} + +div.column p { + padding-right: 15px; +} + +img { + display: block; + margin: 10px auto 10px auto; + border: none; +} + +ul { + list-style-type: square; + padding-left: 1em; + margin-left: 1em; +} + +code { + background-color: rgb(250, 250, 250); + border: 1px solid rgb(200, 200, 200); + padding-left: 4px; + padding-right: 4px; +} + +pre code { + display: block; + padding: 8px; + margin-bottom: 2em; +} + +p.caption { + display: none; +} diff --git a/web/css/syntax.css b/web/css/syntax.css new file mode 100644 index 0000000..1aed859 --- /dev/null +++ b/web/css/syntax.css @@ -0,0 +1,18 @@ +/* Generated by pandoc. */ +table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode, table.sourceCode pre + { margin: 0; padding: 0; border: 0; vertical-align: baseline; border: none; } +td.lineNumbers { border-right: 1px solid #AAAAAA; text-align: right; color: #AAAAAA; padding-right: 5px; padding-left: 5px; } +td.sourceCode { padding-left: 5px; } +pre.sourceCode span.kw { color: #007020; font-weight: bold; } +pre.sourceCode span.dt { color: #902000; } +pre.sourceCode span.dv { color: #40a070; } +pre.sourceCode span.bn { color: #40a070; } +pre.sourceCode span.fl { color: #40a070; } +pre.sourceCode span.ch { color: #4070a0; } +pre.sourceCode span.st { color: #4070a0; } +pre.sourceCode span.co { color: #60a0b0; font-style: italic; } +pre.sourceCode span.ot { color: #007020; } +pre.sourceCode span.al { color: red; font-weight: bold; } +pre.sourceCode span.fu { color: #06287e; } +pre.sourceCode span.re { } +pre.sourceCode span.er { color: red; font-weight: bold; } diff --git a/web/examples.markdown b/web/examples.markdown new file mode 100644 index 0000000..453a22e --- /dev/null +++ b/web/examples.markdown @@ -0,0 +1,27 @@ +--- +title: Examples +--- + +## Simple examples + +A number of simple examples are available in the GitHub repository. They can be +found [here](https://github.com/jaspervdj/hakyll/tree/master/examples). The +README located in that directory explains which example does what. + +## People using Hakyll + +A lot of sites running Hakyll also publish the source code. This is a very +interesting resource to learn from as well. If you're using Hakyll for your +site, and the source code is available, please notify me so I can add you to +this list. This list has no particular ordering. + +- <http://jaspervdj.be/>, + [source](https://github.com/jaspervdj/jaspervdj) +- <http://ethanschoonover.com/>, + [source](https://github.com/altercation/ethanschoonover.com) +- <http://extralogical.net/>, + [source](https://github.com/beastaugh/extralogical.net) +- <http://blog.demotera.com/>, + [source](https://bitbucket.org/paul_r/blog-de-demotera) +- <http://projects.haskell.org/diagrams/>, + [source](http://patch-tag.com/r/byorgey/diagrams-doc/snapshot/current/content/pretty/web/) diff --git a/web/examples/brochure.zip b/web/examples/brochure.zip Binary files differnew file mode 100644 index 0000000..cfbe052 --- /dev/null +++ b/web/examples/brochure.zip diff --git a/web/examples/feedblog.zip b/web/examples/feedblog.zip Binary files differnew file mode 100644 index 0000000..0adaf1e --- /dev/null +++ b/web/examples/feedblog.zip diff --git a/web/examples/morepages.zip b/web/examples/morepages.zip Binary files differnew file mode 100644 index 0000000..617e0f6 --- /dev/null +++ b/web/examples/morepages.zip diff --git a/web/examples/simpleblog.zip b/web/examples/simpleblog.zip Binary files differnew file mode 100644 index 0000000..a67f362 --- /dev/null +++ b/web/examples/simpleblog.zip diff --git a/web/examples/tagblog.zip b/web/examples/tagblog.zip Binary files differnew file mode 100644 index 0000000..d758225 --- /dev/null +++ b/web/examples/tagblog.zip diff --git a/web/hakyll.hs b/web/hakyll.hs new file mode 100644 index 0000000..df92ddd --- /dev/null +++ b/web/hakyll.hs @@ -0,0 +1,53 @@ +{-# LANGUAGE OverloadedStrings #-} +import Hakyll +import Control.Monad (forM_) +import Control.Arrow ((>>>), arr) +import Text.Pandoc + +main :: IO () +main = hakyll $ do + match "css/*" $ do + route idRoute + compile compressCssCompiler + + -- Static directories + forM_ ["images/*", "examples/*", "reference/**"] $ \f -> match f $ do + route idRoute + compile copyFileCompiler + + -- Pages + forM_ pages $ \p -> match p $ do + route $ setExtension "html" + compile $ pageCompiler + >>> requireA "sidebar.markdown" (setFieldA "sidebar" $ arr pageBody) + >>> applyTemplateCompiler "templates/default.html" + >>> relativizeUrlsCompiler + + -- Tutorial + match "tutorial.markdown" $ do + route $ setExtension "html" + compile $ readPageCompiler + >>> pageRenderPandocWith defaultHakyllParserState withToc + >>> requireA "sidebar.markdown" (setFieldA "sidebar" $ arr pageBody) + >>> applyTemplateCompiler "templates/default.html" + >>> relativizeUrlsCompiler + + -- Sidebar + match "sidebar.markdown" $ compile pageCompiler + + -- Templates + match "templates/*" $ compile templateCompiler + where + withToc = defaultHakyllWriterOptions + { writerTableOfContents = True + , writerTemplate = "<h2>Table of contents</h2>\n$toc$\n$body$" + , writerStandalone = True + } + + pages = [ "about.markdown" + , "changelog.markdown" + , "examples.markdown" + , "index.markdown" + , "philosophy.markdown" + , "reference.markdown" + ] diff --git a/web/images/brochure-files.png b/web/images/brochure-files.png Binary files differnew file mode 100644 index 0000000..41af36e --- /dev/null +++ b/web/images/brochure-files.png diff --git a/web/images/hakyll-system-1.png b/web/images/hakyll-system-1.png Binary files differnew file mode 100644 index 0000000..69e850c --- /dev/null +++ b/web/images/hakyll-system-1.png diff --git a/web/images/hakyll-system-2.png b/web/images/hakyll-system-2.png Binary files differnew file mode 100644 index 0000000..eb424a9 --- /dev/null +++ b/web/images/hakyll-system-2.png diff --git a/web/images/hakyll-system-3.png b/web/images/hakyll-system-3.png Binary files differnew file mode 100644 index 0000000..cdffe2d --- /dev/null +++ b/web/images/hakyll-system-3.png diff --git a/web/images/lambda.png b/web/images/lambda.png Binary files differnew file mode 100644 index 0000000..fbf34a8 --- /dev/null +++ b/web/images/lambda.png diff --git a/web/index.markdown b/web/index.markdown new file mode 100644 index 0000000..ee44cf3 --- /dev/null +++ b/web/index.markdown @@ -0,0 +1,43 @@ +--- +title: Home +--- + +## Overview + +Hakyll is a [Haskell](http://haskell.org) library for generating static sites, +mostly aimed at small-to-medium sites and personal blogs. It is written in a +very configurable way and uses an [xmonad](http://xmonad.org)-like DSL for +configuration. + +Integration with [pandoc](http://johnmacfarlane.net/pandoc/) gives us markdown +and TeX support, including syntax highlighting and other goodies. + +## The Hakyll System + +### Write your content in whatever format you prefer + +![Write your content](/images/hakyll-system-1.png) + +### Create compilation rules in a Haskell EDSL + +![Write your rules](/images/hakyll-system-2.png) + +### Compile it to HTML and upload it! + +![Compile it](/images/hakyll-system-3.png) + +## Hakyll 3 + +Hakyll 3 has been released, and it can be installed by running +`cabal install hakyll`. For a limited time (but as long as is necessary) you can +access the old site and documentation [here](/hakyll2). + +## Getting Started + +You can get the latest version from hackage using `cabal install hakyll`. Then, +you can: + +- read the [tutorial](/tutorial.html); +- mail the [google discussion group](http://groups.google.com/group/hakyll); +- ask questions on the IRC channel: `#hakyll` on + [freenode](http://freenode.net/). diff --git a/web/philosophy.markdown b/web/philosophy.markdown new file mode 100644 index 0000000..07a20c3 --- /dev/null +++ b/web/philosophy.markdown @@ -0,0 +1,28 @@ +--- +title: Philosophy +--- + +## Small-to-medium sites + +Hakyll was written to be used for small-to-medium sites. You can do some +advanced things with it, but don't use it to build a big online shop. + +## Hakyll.hs + +It should be possible to put all configuration in one file, so data and +configuration can be strictly separated. In addition, we think this file should +never exceed a 100 lines of code. + +## High-level + +Hakyll tries to provide as many high-level functions as possible for common +tasks, while the lower-level functions should also be accessible. If you think +you're writing something that can be used for many sites, please send a patch, +or your `hakyll.hs`, and we will see what we can do. + +## Well-documented + +A key to being easy-to-use is documentation. That's why we try to provide as +many working examples as possible. If you ever create a site using hakyll, +please consider open-sourcing it, as people might be able to learn from your +code. diff --git a/web/reference.markdown b/web/reference.markdown new file mode 100644 index 0000000..9b4d9e4 --- /dev/null +++ b/web/reference.markdown @@ -0,0 +1,10 @@ +--- +title: Reference +--- + +## Reference + +We keep a copy of the reference of the latest stable version here. This +reference is automatically generated by +[Haddock](http://www.haskell.org/haddock/). You can +[find it here](reference/index.html). diff --git a/web/sidebar.markdown b/web/sidebar.markdown new file mode 100644 index 0000000..8396c75 --- /dev/null +++ b/web/sidebar.markdown @@ -0,0 +1,9 @@ +## Navigation + +[home](/index.html) +[philosophy](/philosophy.html) +[about](/about.html) +[tutorial](/tutorial.html) +[examples](/examples.html) +[reference](/reference.html) +[changelog](/changelog.html) diff --git a/web/templates/default.html b/web/templates/default.html new file mode 100644 index 0000000..040292c --- /dev/null +++ b/web/templates/default.html @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" +"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <title>Hakyll - $title$</title> + + <!-- Stylesheets. --> + <link rel="stylesheet" type="text/css" href="/css/default.css" /> + <link rel="stylesheet" type="text/css" href="/css/syntax.css" /> + + <!-- Metadata. --> + <meta name="keywords" content="hakyll,static site generator,static,site,generator,haskell,blog"/> + <meta name="description" content="Hakyll - A Static Site Generator in Haskell."/> + + <!-- Flattr JS --> + <!-- + <script type="text/javascript"> + /* <![CDATA[ */ + (function() { + var s = document.createElement('script'), t = + document.getElementsByTagName('script')[0]; + s.type = 'text/javascript'; + s.async = true; + s.src = 'http://api.flattr.com/js/0.6/load.js?mode=auto'; + t.parentNode.insertBefore(s, t); + })(); + /* ]]> */ + </script> + --> + </head> + <body> + <div id="main"> + <div id="header"> + <img src="/images/lambda.png" alt="lambda" /> + <h1>Hakyll - $title$</h1> + </div> + <!-- Sidebar. --> + <div id="sidebar"> + $sidebar$ + + <!-- Flattr button --> + <!-- + <a class="FlattrButton" style="display:none;" rev="flattr;button:compact;" href="http://jaspervdj.be/hakyll"></a> + <noscript><a href="http://flattr.com/thing/291889/Hakyll" target="_blank"> <img src="http://api.flattr.com/button/flattr-badge-large.png" alt="Flattr this" title="Flattr this" border="0" /></a></noscript> + --> + </div> + + <div id="content"> + $body$ + </div> + + <div id="footer"> + Site proudly generated by <a href="http://github.com/jaspervdj/hakyll">hakyll</a>. + </div> + </div> + + <!-- Google Analytics --> + <script type="text/javascript"> + var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www."); + document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E")); + </script> + <script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-11993001-1"); + pageTracker._trackPageview(); + } catch(err) {} + </script> + </body> + +</html> diff --git a/web/templates/tutorial.html b/web/templates/tutorial.html new file mode 100644 index 0000000..6ce60b6 --- /dev/null +++ b/web/templates/tutorial.html @@ -0,0 +1,10 @@ +$body + +<h2>Helping out</h2> + +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 +<a href="http://groups.google.com/group/hakyll">give some feedback</a> about +the tutorials, and especially report errors or difficulties you encountered. +Thanks! diff --git a/web/templates/tutorialitem.html b/web/templates/tutorialitem.html new file mode 100644 index 0000000..01fb298 --- /dev/null +++ b/web/templates/tutorialitem.html @@ -0,0 +1,3 @@ +<li> + <a href="$url">$title</a> $what. +</li> diff --git a/web/templates/tutorials.html b/web/templates/tutorials.html new file mode 100644 index 0000000..6cbb4ac --- /dev/null +++ b/web/templates/tutorials.html @@ -0,0 +1,14 @@ +<h2>Tutorials about Hakyll</h2> +<p> + Here is a list of tutorials I've written about Hakyll: +</p> +<ul> + $body +</ul> +<p> + All these tutorials assume you are using the latest stable version of + Hakyll. If this is not the case, you might want to update using: + <pre><code>ghc-pkg unregister hakyll +cabal update +cabal install hakyll</code></pre> +</p> diff --git a/web/tutorial.markdown b/web/tutorial.markdown new file mode 100644 index 0000000..920249d --- /dev/null +++ b/web/tutorial.markdown @@ -0,0 +1,351 @@ +--- +title: Tutorial +--- + +Why static websites? +-------------------- + +Modern web frameworks make it easy to create huge dynamic websites. Why would +anyone still care about a static website? + +- Static websites are fast, because it's simply files served directly from the + hard disk. +- Static websites are secure. Nobody has ever found an SQL injection in static + pages. +- Static websites are easy to deploy. Just copy them to your webhost using + (S)FTP/rsync/scp and you are done. They work on all webhosts: no CGI or extra + modules needed for the web server. + +Why Hakyll? +----------- + +Hakyll is a [Haskell] library meant for creating small-to-medium sized static +websites. It is a powerful publishing tool, precisely because of the power of +Haskell. By using the awesome [pandoc] library, it is able to create your +website from a large variety of input formats. + +[Haskell]: http://haskell.org/ +[pandoc]: http://johnmacfarlane.net/pandoc/ + +Features include: + +- easy templating system; +- a simple HTTP server for previewing and compiling your website on the go; +- powerful syntax highlighting; +- modules for common items such as tags and feeds; +- easily extensible. + +Let's get started! +------------------ + +We're going to discuss a small brochure site to start with. You can find all +code and files necessary to build this site [right here](/examples/brochure.zip) +-- feel free to look at them as we go trough the tutorial, in fact, it might be +very learnful to have a closer look at the files as we discuss them. There's a +number of files we will use: + + about.rst A simple page written in RST format + code.lhs Another page with some code (which can be highlighted) + css Directory for CSS files + |- default.css The main CSS file + \- syntax.css CSS file for code syntax highlighting + hakyll.hs Our code to generate the site + images Directory for images + \- haskell-logo.png The logo of my favorite programming language + index.markdown A simple page in markdown format + templates Directory for templates + \- default.html The main template for the site + +By default, hakyll will compile everything to the `_site` directory. We can try +this like this: + + [jasper@phoenix] ghc --make hakyll.hs + [jasper@phoenix] ./hakyll build + +Instead of using `build`, we can also use `preview`, which will fire up a +webserver serving the `_site` directory, so have a look! + +All files have been compiled, and their output has been placed in the `_site` +directory as illustrated in this diagram: + +![Brochure files](/images/brochure-files.png) + +No magic is involved at all -- we will precisely study how and why our items are +compiled like that. All of this is specified in the `hakyll.hs` file. + +### Images + +Let's start of with the `images/haskell-logo.png` file, because the processing +of this file is very simple: it is simply copied to the output directory. Let's +look at the relevant lines in the `hakyll.hs` file: + +~~~~~{.haskell} +match "images/*" $ do + route idRoute + compile copyFileCompiler +~~~~~ + +The first line specifies we will describe the process for compiling everything +in the `images/` folder: hakyll uses globs for this [^pattern]. + +[^pattern]: A little caveat is that these globs are not `String`s but + `Pattern`s, so you need the `OverloadedStrings` extension. + +We can see two simple rules next: [route] and [compile]. + +- [route] determines how the input file(s) get mapped to the output files. + [route] only deals with file names -- not with the actual content! +- [compile], on the other hand, determines how the file content is processed. + +[route]: /reference/Hakyll-Core-Rules.html#v:route +[compile]: /reference/Hakyll-Core-Rules.html#v:compile + +In this case, we select the [idRoute]: which means the file name will be kept +the same (`_site` will always be prepended automatically). This explains the +name of [idRoute]: much like the `id` function in Haskell, it also maps values +to themselves. + +[idRoute]: /reference/Hakyll-Core-Routes.html#v:idRoute + +For our compiler, we use [copyFileCompiler], meaning that we don't process the +content at all, we just copy the file. + +[copyFileCompiler]: /reference/Hakyll-Core-Writable-CopyFile.html#v:copyFileCompiler + +### CSS + +If we look at how the two CSS files are processed, we see something which looks +very familiar: + +~~~~~{.haskell} +match "css/*" $ do + route idRoute + compile compressCssCompiler +~~~~~ + +Indeed, the only difference with the images is that have now chosen for +[compressCssCompiler] -- a compiler which *does* process the content. Let's have +a quick look at the type of [compressCssCompiler]: + +[compressCssCompiler]: /reference/Hakyll-Web-CompressCss.html#v:compressCssCompiler + +~~~~~{.haskell} +compressCssCompiler :: Compiler Resource String +~~~~~ + +Intuitively, we can see this as a process which takes a `Resource` and produces +a `String`. + +- A `Resource` is simply the Hakyll representation of an item -- usually just a + file on the disk. +- The produced string is the processed CSS. + +We can wonder what Hakyll does with the resulting `String`. Well, it simply +writes this to the file specified in the `route`! As you can see, routes and +compilers work together to produce your site. + +### Templates + +Next, we can see that the templates are compiled: + +~~~~~{.haskell} +match "templates/*" $ compile templateCompiler +~~~~~ + +Let's start with the basics: what is a template? An example template gives us a +good impression: + +~~~~~ +<html> + <head> + <title>Hakyll Example - $title$</title> + </head> + <body> + <h1>$title$</h1> + + $body$ + </body> +</html> +~~~~~ + +A template is a text file to lay our some content. The content it lays out is +called a page -- we'll see that in the next section. The syntax for templates is +intentionally very simplistic. You can bind some content by referencing the name +of the content *field* by using `$field$`, and that's it. + +You might have noticed how we specify a compiler (`compile`), but we don't set +any `route`. Why is this? + +Precisely because we don't want to our template to end up anywhere in our site +directory! We want to use it to lay out other items -- so we need to load +(compile) it, but we don't want to give it a real destination. + +By using the `templates/*` pattern, we compile all templates in one go. + +### Pages + +The code for pages looks suspiciously more complicated: + +~~~~~~{.haskell} +match (list ["about.rst", "index.markdown", "code.lhs"]) $ do + route $ setExtension "html" + compile $ pageCompiler + >>> applyTemplateCompiler "templates/default.html" + >>> relativizeUrlsCompiler +~~~~~~ + +But we'll see shortly that this actually fairly straightforward. Let's begin by +exploring what a *page* is. + +~~~~~~ +--- +title: Home +author: Jasper +--- + +So, I decided to create a site using Hakyll and... +~~~~~~ + +A page consists of two parts: a body, and metadata. As you can see above, the +syntax is not hard. The metadata part is completely optional, this is the same +page without metadata: + +~~~~~~ +So, I decided to create a site using Hakyll and... +~~~~~~ + +Hakyll supports a number of formats for the page body. Markdown, HTML and RST +are probably the most common. Hakyll will automatically guess the right format +if you use the right extension for your page. + +~~~~~~{.haskell} +match (list ["about.rst", "index.markdown", "code.lhs"]) $ do +~~~~~~ + +We see a more complicated pattern here. Some sets of files cannot be described +easily by just one pattern, and here the [list] function can help us out. In +this case, we have three specific pages we want to compile. + +[list]: /reference/Hakyll-Core-Identifier-Pattern.html#v:list + +~~~~~~{.haskell} +route $ setExtension "html" +~~~~~~ + +For our pages, we do not want to use `idRoute` -- after all, we want to generate +`.html` files, not `.markdown` files or something similar! The [setExtension] +route allows you to simply replace the extension of an item, which is what we +want here. + +[setExtension]: /reference/Hakyll-Core-Routes.html#v:setExtension + +~~~~~~{.haskell} +compile $ pageCompiler + >>> applyTemplateCompiler "templates/default.html" + >>> relativizeUrlsCompiler +~~~~~~ + +How should we process these pages? [pageCompiler] is the default compiler for +pages. [pageCompiler] does a few things: + +- It parses the page into body and metadata +- It adds some extra metadata fields such as `$url$` and `$path$` (you shouldn't + worry about these for now) +- It fill in possible `$key$`'s in it's own body +- It renders the page using pandoc + +Which basically means that we end up with a `Page` that has the HTML content we +want as body. But we don't just want the plain content on our website -- we want +to decorate it with a template, for starters. + +[pageCompiler]: /reference/Hakyll-Web-Page.html#v:pageCompiler + +Different compilers can be chained in a pipeline-like way using Arrows. Arrows +form a complicated subject, but fortunately, most Hakyll users need not be +concerned with the details. If you are interested, you can find some information +on the [Understanding arrows] page -- but the only thing you really *need* to +know is that you can chain compilers using the `>>>` operator. + +[Understanding arrows]: http://en.wikibooks.org/wiki/Haskell/Understanding_arrows + +The `>>>` operator is a lot like a flipped function composition (`flip (.)`) in +Haskell, with the important difference that `>>>` is more general and works on +all Arrows -- including Hakyll compilers. + +Here, we apply three compilers sequentially: + +1. We load and render the page using `pageCompiler` +2. We apply the template we previously loaded using [applyTemplateCompiler] +3. We relativize the URL's on the page using [relativizeUrlsCompiler] + +[applyTemplateCompiler]: /reference/Hakyll-Web-Template.html#v:applyTemplateCompiler +[relativizeUrlsCompiler]: /reference/Hakyll-Web-RelativizeUrls.html#v:relativizeUrlsCompiler + +Relativizing URL's is a very handy feature. It means that we can just use +absolute URL's everywhere in our templates and code, e.g.: + +~~~~~{.haskell} +<link rel="stylesheet" type="text/css" href="/css/default.css" /> +~~~~~ + +And Hakyll will translate this to a relative URL for each page. This means we +can host our site at `example.com` and `example.com/subdir` without changing a +single line of code. + +More tutorials are in the works... + +Various tips and tricks +----------------------- + +### Syntax highlighting + +Syntax highlighting is enabled by default in Hakyll. However, you also need to +enable it in pandoc. If no syntax highlighting shows up, try + + [jasper@phoenix] cabal install --reinstall -fhighlighting pandoc + +### 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. + +Problems +-------- + +### regex-pcre dependency on Mac OS + +Hakyll requires [regex-pcre], which might fail to build on Mac OS. To solve +this problem, make sure the [pcre] C library is installed (via homebrew or +macports). Then install [regex-pcre] using: + + cabal install --extra-include-dirs=/usr/local/include regex-pcre + +or + + cabal install --extra-include-dirs=/opt/local/include regex-pcre + +...and proceed to install Hakyll the regular way. + +[regex-pcre]: http://hackage.haskell.org/package/regex-pcre +[pcre]: http://www.pcre.org/ + +### "File name does not match module name" on Mac OS + + Hakyll.hs:1:1: + File name does not match module name: + Saw: `Main' + Expected: `Hakyll' + +Is an error encountered on Mac OS when `hakyll.hs` is located on a +case-insensitive filesystem. A workaround is to rename it to something that +isn't the name of the module, for example, `site.hs`. |