-------------------------------------------------------------------------------- {-# LANGUAGE OverloadedStrings #-} import Control.Applicative ((<$>)) import Data.Monoid (mappend) import Hakyll import Data.Map as M import qualified Data.Set as S import Data.Maybe (fromMaybe) import Text.Pandoc.Options config :: Configuration config = defaultConfiguration { deployCommand = "rsync -Havz _site/ rekado@elephly.net:/srv/disk1/rekado/elephly.net" } myFeedConfiguration :: FeedConfiguration myFeedConfiguration = FeedConfiguration { feedTitle = "Rekado's website" , feedDescription = "Music, words, and hacking" , feedAuthorName = "Rekado" , feedAuthorEmail = "rekado+feed@elephly.net" , feedRoot = "http://elephly.net" } -------------------------------------------------------------------------------- main :: IO () main = hakyllWith config $ do match "css/*" $ do route idRoute compile compressCssCompiler match ( "js/libs/*" .||. "js/hyphenator/*" .||. "js/hyphenator/patterns/*" .||. "js/*" .||. "downies/*" .||. "downies/music/*" .||. "images/*" .||. "images/posts/*" .||. "images/posts/*/*" .||. "favicon.ico" ) $ do route idRoute compile copyFileCompiler match ( "static/*.markdown" .||. "static/*/*.markdown" ) $ do route $ setExtension "html" `composeRoutes` gsubRoute "static/" (const "") compile $ pandocCompiler >>= loadAndApplyTemplate "templates/default.html" defaultContext >>= relativizeUrls match "static/*.html" $ do route $ gsubRoute "static/" (const "") compile $ do getResourceBody >>= loadAndApplyTemplate "templates/default.html" defaultContext >>= relativizeUrls match "posts/*.markdown" $ do route $ setExtension "html" compile defaultCompiler --itemTpl <- loadBody "templates/photo.html" --metadata <- getMetadata --let m = M.lookup "photo" metadata -- direct links match "posts/2010-03-28-elephly.markdown" $ version "direct" $ do route $ constRoute "elephly.html" compile defaultCompiler match "posts/2010-03-23-fur-man.markdown" $ version "direct" $ do route $ constRoute "fur-man.html" compile defaultCompiler -- blog post archive create ["posts/index.html"] $ do route idRoute compile $ do let archiveCtx = field "posts" (\_ -> postList recentFirst) `mappend` defaultContext makeItem "" >>= loadAndApplyTemplate "templates/archive.html" archiveCtx >>= loadAndApplyTemplate "templates/default.html" archiveCtx >>= relativizeUrls create ["rss.xml"] $ postFeed renderRss create ["atom.xml"] $ postFeed renderAtom -- always show the most recent blog post create ["index.html"] $ do route idRoute compile $ do mostRecent <- fmap head . recentFirst =<< loadAllSnapshots "posts/*.markdown" "non-relative" makeItem (itemBody mostRecent) >>= relativizeUrls match "templates/*" $ compile templateCompiler -------------------------------------------------------------------------------- postCtx :: Context String postCtx = dateField "date" "%B %e, %Y" `mappend` photoSnippet `mappend` flattrSnippet `mappend` licenseSnippet `mappend` defaultContext -- If a post declares a certain key in the metadata header, -- load the given template, otherwise ignore. snippet :: String -> String -> Identifier -> Context String snippet name key templatePath = field name $ \item -> do metadata <- getMetadata (itemIdentifier item) case M.lookup key metadata of Just file -> itemBody <$> loadAndApplyTemplate templatePath postCtx item _ -> return "" photoSnippet = snippet "photo-snippet" "photo" "templates/photo.html" flattrSnippet = snippet "flattr-snippet" "flattr" "templates/flattr.html" licenseSnippet = snippet "license-snippet" "license" "templates/license.html" postFeed renderer = do route idRoute compile $ do let feedCtx = postCtx `mappend` bodyField "description" posts <- fmap (take 10) . recentFirst =<< loadAllSnapshots "posts/*.markdown" "content" renderer myFeedConfiguration feedCtx posts -------------------------------------------------------------------------------- postList :: ([Item String] -> Compiler [Item String]) -> Compiler String postList sortFilter = do posts <- sortFilter =<< loadAll ("posts/*.markdown" .&&. hasNoVersion) itemTpl <- loadBody "templates/post-item.html" list <- applyTemplateList itemTpl postCtx posts return list customPandocCompiler :: Compiler (Item String) customPandocCompiler = pandocCompilerWith (addRExt [Ext_pipe_tables] defaultHakyllReaderOptions) (addWExt [Ext_pipe_tables] defaultHakyllWriterOptions) where addRExt es opts = opts { readerExtensions = S.union (S.fromList es) (readerExtensions opts) , readerSmart = True } addWExt es opts = opts { writerExtensions = S.union (S.fromList es) (writerExtensions opts) } defaultCompiler = customPandocCompiler >>= loadAndApplyTemplate "templates/post.html" postCtx >>= saveSnapshot "content" >>= loadAndApplyTemplate "templates/default.html" postCtx >>= saveSnapshot "non-relative" >>= relativizeUrls