-- | This module provides a simple default configuration which behaves similar -- to a tool such as the Jekyll static site generator (). -- -- The idea is that you don't have to write your configuration yourself: you -- just follow some conventions, and Hakyll does the rest. -- -- You can generate a site which will serve as a good starting point by running -- the command-line tool: -- -- > hakyll-contrib small-blog -- -- Hakyll will then generate a simple example site for you. The necessary -- configuration is placed in the @small-blog.hs@ file. Compile and run it to create -- the demo site: -- -- > ghc --make small-blog.hs -- > ./small-blog build -- > ./small-blog preview -- -- So, in order to get your site going, you need to follow the conventions for -- the content on your site. -- -- Images should be placed in the @images\/@ or @img\/@ folder. The are copied -- directly. Other static files (but not images) can be placed in @static\/@ or -- @files\/@. The @favicon.ico@ file is an exception, it is just placed in the -- top-level directory. -- -- CSS files should be placed in @css\/@, and JavaScript files in @js\/@. -- -- Then, we arrive at pages. You can create any number of pages on your site: -- just create files in one of the documents pandoc supports (@.html@, -- @.markdown@, @.rst@, @.lhs@...) in the top-level directory. -- -- These pages may use a number of preconfigured @$key$@'s: -- -- * @$recentPosts$@: A list of recent posts, displayed from most recent to -- oldest. By default, 3 posts are shown, altough this can be configured using -- the 'numberOfRecentPosts' field. -- -- * @$allPosts$@: A list of all posts, displayed from most recent to oldest. -- This is very useful for creating an archive page. -- -- * @$chronologicalPosts$@: Similar to @$allPosts$@, but displays the posts in -- chronological order. -- -- For example usage, look at the example site we generated using -- @hakyll-contrib small-blog@. -- -- Now, one can wonder where these posts come from. Simple: all pages in the -- @posts\/@ directory are considered posts. Note that a naming format of -- -- > posts/year-month-date-title.extension -- -- is mandatory. An example: -- -- > posts/2011-06-19-hello-world.markdown -- -- This allows Hakyll to parse the date easily, among other things. Again, look -- at the example site for some example posts. -- -- Additionaly, there is the @templates\/@ folder. This folder holds the -- templates for your site. For a @small-blog@ configuration, your site should -- have /exactly/ three templates: -- -- * @templates\/default.html@: The main template. This should contain your -- HTML doctype, head, etc. -- -- * @templates\/post.html@: A template which is applied to every post before -- it is rendered using the default template. -- -- * @templates\/post-item.html@: A template which is applied to posts in -- listings (e.g. @$chronologicalPosts$@). -- -- Again, the example should clarify things. -- -- This configuration should be enough to create a small personal website. But, -- we have only touched the surface of what is possible with Hakyll. For more -- information, check out the tutorials at: -- {-# LANGUAGE OverloadedStrings #-} {-# OPTIONS_GHC -fno-warn-unused-do-bind #-} module Hakyll.Contrib.SmallBlog ( SmallBlogConfiguration (..) , defaultSmallBlogConfiguration , smallBlog , smallBlogWith ) where import Control.Arrow ((>>>)) import Text.Pandoc (ParserState, WriterOptions) import Hakyll -- | Configuration datatype for the 'smallBlog' ruleset -- data SmallBlogConfiguration = SmallBlogConfiguration { -- | Number of recent posts that are available numberOfRecentPosts :: Int , -- | Parser state for pandoc, i.e. read options parserState :: ParserState , -- | Writer options for pandoc writerOptions :: WriterOptions , -- | Atom feed configuration atomFeed :: Maybe FeedConfiguration } deriving (Show) -- | Defaults for 'SmallBlogConfiguration' -- defaultSmallBlogConfiguration :: SmallBlogConfiguration defaultSmallBlogConfiguration = SmallBlogConfiguration { numberOfRecentPosts = 3 , parserState = defaultHakyllParserState , writerOptions = defaultHakyllWriterOptions , atomFeed = Nothing } -- | A default configuration for a small blog -- smallBlog :: Rules smallBlog = smallBlogWith defaultSmallBlogConfiguration -- | Version of 'smallBlog' which allows setting a config -- smallBlogWith :: SmallBlogConfiguration -> Rules smallBlogWith conf = do -- Images and static files ["favicon.ico"] --> copy ["img/**", "images/**"] --> copy ["static/**", "files/**"] --> copy ["js/**", "javascript/**"] --> copy -- CSS files ["css/*.css", "style/*.css", "stylesheets/*.css"] --> css -- All templates ["templates/*"] --> template -- "Dynamic" content ["posts/*"] --> post -- Top-level pages ["*.markdown", "*.html", "*.rst", "*.lhs"] --> topLevel -- Rss is optional case atomFeed conf of Nothing -> return () Just f -> do match "atom.xml" $ route idRoute create "atom.xml" $ requireAll_ "posts/*" >>> renderAtom f return () where -- Useful combinator here xs --> f = mapM_ (\p -> match p $ f) xs -- Completely static copy = route idRoute >> compile copyFileCompiler -- CSS directories css = route (setExtension "css") >> compile compressCssCompiler -- Templates template = compile templateCompiler -- Posts post = do route $ setExtension "html" compile $ pageCompilerWith (parserState conf) (writerOptions conf) >>> applyTemplateCompiler "templates/post.html" >>> applyTemplateCompiler "templates/default.html" >>> relativizeUrlsCompiler -- Top-level pages topLevel = do route $ setExtension "html" compile $ pageCompilerWithFields (parserState conf) (writerOptions conf) id topLevelFields >>> applyTemplateCompiler "templates/default.html" >>> relativizeUrlsCompiler -- Add the fields we need to top-level pages topLevelFields = setFieldPostList recentFirst "allPosts" >>> setFieldPostList (take nRecent . recentFirst) "recentPosts" >>> setFieldPostList chronological "chronologicalPosts" -- Create a post list based on ordering/selection setFieldPostList f k = setFieldPageList f "templates/post-item.html" k "posts/*" -- Number of most recent posts to show nRecent = numberOfRecentPosts conf