From efab53729d95cc69a8205bb691db9c12e9e06096 Mon Sep 17 00:00:00 2001 From: Jasper Van der Jeugt Date: Mon, 13 Jun 2011 18:26:04 +0200 Subject: Update website a bit --- web/tutorials/01-installation.markdown | 36 ++++ web/tutorials/02-basics.markdown | 292 +++++++++++++++++++++++++++++++++ web/tutorials/faq.markdown | 53 ++++++ 3 files changed, 381 insertions(+) create mode 100644 web/tutorials/01-installation.markdown create mode 100644 web/tutorials/02-basics.markdown create mode 100644 web/tutorials/faq.markdown (limited to 'web/tutorials') diff --git a/web/tutorials/01-installation.markdown b/web/tutorials/01-installation.markdown new file mode 100644 index 0000000..5f763e5 --- /dev/null +++ b/web/tutorials/01-installation.markdown @@ -0,0 +1,36 @@ +--- +title: Installation +--- + +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. diff --git a/web/tutorials/02-basics.markdown b/web/tutorials/02-basics.markdown new file mode 100644 index 0000000..bebc452 --- /dev/null +++ b/web/tutorials/02-basics.markdown @@ -0,0 +1,292 @@ +--- +title: The basics +--- + +## 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](http://github.com/jaspervdj/hakyll-examples/tree/master/brochure) +-- feel free to look at them as we go trough the tutorial. To fetch all examples +in order to play with them locally, use: + + git clone git://github.com/jaspervdj/hakyll-examples.git + +or nagivate to the download menu on GitHub. + +Now, for this first tutorial, 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. You can +view the full `hakyll.hs` file online [here][brochure-hakyll.hs], or you can +look in the directory you cloned or downloaded. + +[brochure-hakyll.hs]: http://github.com/jaspervdj/hakyll-examples/blob/master/brochure/hakyll.hs + +## 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: + +~~~~~ + + + Hakyll Example - $$title$$ + + +

$$title$$

+ + $$body$$ + + +~~~~~ + +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? + +We need to compile the template because we will need it later. If we compile a +page later using `templates/default.html`, Hakyll needs to know what +`templates/default.html` is. Note that we could move template compilation to the +bottom of our code. The order doesn't matter -- Hakyll will determine that for +you. But if you don't compile `templates/default.html` as a template, Hakyll +will not be able to take it into account when deciding the compilation order. + +So, the `compile` needs to be there -- but why don't we set a `route` here? +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} + +~~~~~ + +Using the [relativizeUrlsCompiler], Hakyll will change this to: + +~~~~~{.haskell} + +~~~~~ + +when we are compiling `index.html`, or + +~~~~~{.haskell} + +~~~~~ + +when we are compiling (some imaginary) `posts/foo.html`. So 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... diff --git a/web/tutorials/faq.markdown b/web/tutorials/faq.markdown new file mode 100644 index 0000000..f8a3087 --- /dev/null +++ b/web/tutorials/faq.markdown @@ -0,0 +1,53 @@ +--- +title: FAQ +--- + +## Does Hakyll support 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 should I rebuild and when should I build? + +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. + +## Problem with 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`. -- cgit v1.2.3