diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/Site.hs | 123 |
1 files changed, 119 insertions, 4 deletions
diff --git a/src/Site.hs b/src/Site.hs index d1afbce..dde7047 100644 --- a/src/Site.hs +++ b/src/Site.hs | |||
| @@ -1,16 +1,131 @@ | |||
| 1 | {-# LANGUAGE OverloadedStrings #-} | 1 | {-# LANGUAGE OverloadedStrings, RankNTypes, StandaloneDeriving, FlexibleInstances #-} |
| 2 | 2 | ||
| 3 | import Hakyll | 3 | import Hakyll |
| 4 | 4 | ||
| 5 | import Data.Monoid (Monoid(..), mconcat, (<>)) | ||
| 6 | import Control.Monad (liftM) | ||
| 7 | import Data.Char (toLower, isSpace, isAlphaNum) | ||
| 8 | import Data.Maybe (mapMaybe, fromMaybe) | ||
| 9 | import Data.Map (Map) | ||
| 10 | import qualified Data.Map as Map | ||
| 11 | import Data.List (take, reverse) | ||
| 12 | import Data.Default | ||
| 13 | import Text.Pandoc.Options (WriterOptions(..), ObfuscationMethod(..)) | ||
| 14 | import Control.Applicative (Alternative(..), Applicative(..)) | ||
| 15 | |||
| 16 | import System.FilePath (replaceExtension) | ||
| 17 | |||
| 5 | main :: IO () | 18 | main :: IO () |
| 6 | main = hakyllWith config $ do | 19 | main = hakyllWith config $ do |
| 7 | match "/posts/*" $ do | 20 | match "templates/*" $ compile templateCompiler |
| 21 | |||
| 22 | match "css/*" $ do | ||
| 23 | route idRoute | ||
| 24 | compile copyFileCompiler | ||
| 25 | |||
| 26 | match "posts/*" $ do | ||
| 8 | route $ setExtension ".html" | 27 | route $ setExtension ".html" |
| 9 | compile $ do | 28 | compile $ do |
| 29 | getResourceBody >>= saveSnapshot "content" | ||
| 10 | pandocCompiler | 30 | pandocCompiler |
| 11 | >>= saveSnapshot "content" | ||
| 12 | >>= loadAndApplyTemplate "templates/default.html" defaultContext | 31 | >>= loadAndApplyTemplate "templates/default.html" defaultContext |
| 13 | >>= relativizeUrls | 32 | >>= relativizeUrls |
| 14 | 33 | ||
| 34 | tags <- buildTags "posts/*" tagTranslation' >>= addTag "All Posts" "posts/*" | ||
| 35 | |||
| 36 | tagsRules tags $ \tag pattern -> do | ||
| 37 | route idRoute | ||
| 38 | compile $ do | ||
| 39 | let ctx = mconcat [ constField "title" tag | ||
| 40 | , listField "posts" defaultContext $ chronological =<< loadAll pattern | ||
| 41 | , defaultContext | ||
| 42 | ] | ||
| 43 | makeItem "" | ||
| 44 | >>= loadAndApplyTemplate "templates/post-list.html" ctx | ||
| 45 | >>= loadAndApplyTemplate "templates/default.html" ctx | ||
| 46 | >>= relativizeUrls | ||
| 47 | |||
| 48 | let | ||
| 49 | tags' = tags { tagsMakeId = fromFilePath . (`replaceExtension` "rss") . toFilePath . tagsMakeId tags} | ||
| 50 | |||
| 51 | tagsRules tags' $ \tag pattern -> do | ||
| 52 | route idRoute | ||
| 53 | compile $ do | ||
| 54 | let | ||
| 55 | feedCtx = mconcat [ bodyField "description" | ||
| 56 | , defaultContext | ||
| 57 | ] | ||
| 58 | renderRss (feedConfig tag) feedCtx =<< loadAllSnapshots pattern "content" | ||
| 59 | |||
| 60 | match "index.md" $ do | ||
| 61 | route $ setExtension ".html" | ||
| 62 | compile $ do | ||
| 63 | let ctx = mconcat [ listField "tags" defaultContext $ mapM (\(k, _) -> renderTag k tags) $ tagsMap tags | ||
| 64 | , constField "title" "Index" | ||
| 65 | , defaultContext | ||
| 66 | ] | ||
| 67 | item <- getResourceBody | ||
| 68 | pandocCompilerWith def (def { writerEmailObfuscation = NoObfuscation }) | ||
| 69 | >>= loadAndApplyTemplate "templates/index.html" ctx | ||
| 70 | >>= loadAndApplyTemplate "templates/default.html" ctx | ||
| 71 | >>= relativizeUrls | ||
| 72 | |||
| 73 | deriving instance Eq (Item String) | ||
| 74 | |||
| 75 | feedConfig :: String -> FeedConfiguration | ||
| 76 | feedConfig tagName = FeedConfiguration { feedTitle = "dirty-haskell.org: " ++ tagName | ||
| 77 | , feedDescription = "dirty-haskell.org — A Blog." | ||
| 78 | , feedAuthorName = "G. Kleen" | ||
| 79 | , feedAuthorEmail = "blog@dirty-haskell.org" | ||
| 80 | , feedRoot = "https://dirty-haskell.org" | ||
| 81 | } | ||
| 82 | |||
| 83 | renderTag :: String -- ^ Tag name | ||
| 84 | -> Tags | ||
| 85 | -> Compiler (Item String) | ||
| 86 | renderTag tag tags = do | ||
| 87 | ellipsisItem <- makeItem "" | ||
| 88 | let | ||
| 89 | ids = fromMaybe [] $ lookup tag $ tagsMap tags | ||
| 90 | postCtx = mconcat [ listField "posts" (ellipsisContext ellipsisItem) $ liftM (withEllipsis ellipsisItem) $ chronological =<< mapM load ids | ||
| 91 | , constField "title" tag | ||
| 92 | , constField "rss" ("tags/" ++ tagTranslation tag ++ ".rss") | ||
| 93 | , constField "url" ("tags/" ++ tagTranslation tag ++ ".html") | ||
| 94 | , defaultContext | ||
| 95 | ] | ||
| 96 | makeItem "" | ||
| 97 | >>= loadAndApplyTemplate "templates/post-list.html" postCtx | ||
| 98 | >>= loadAndApplyTemplate "templates/tag.html" postCtx | ||
| 99 | where | ||
| 100 | ellipsisContext item = mconcat [ boolField "ellipsis" (== item) | ||
| 101 | , defaultContext | ||
| 102 | ] | ||
| 103 | boolField name f = field name (\i -> if f i | ||
| 104 | then pure (error $ unwords ["no string value for bool field:",name]) | ||
| 105 | else empty) | ||
| 106 | withEllipsis ellipsisItem xs | ||
| 107 | | length xs > max = [ellipsisItem] ++ takeEnd (max - 1) xs | ||
| 108 | | otherwise = xs | ||
| 109 | takeEnd i = reverse . take i . reverse | ||
| 110 | max = 4 | ||
| 111 | |||
| 112 | tagTranslation' :: String -> Identifier | ||
| 113 | tagTranslation' = fromCapture "tags/*.html" . tagTranslation | ||
| 114 | |||
| 115 | tagTranslation :: String -> String | ||
| 116 | tagTranslation = mapMaybe charTrans | ||
| 117 | where | ||
| 118 | charTrans c | ||
| 119 | | isSpace c = Just $ '-' | ||
| 120 | | isAlphaNum c = Just $ toLower c | ||
| 121 | | otherwise = Nothing | ||
| 122 | |||
| 123 | addTag :: MonadMetadata m => String -> Pattern -> Tags -> m Tags | ||
| 124 | addTag name pattern tags = do | ||
| 125 | ids <- getMatches pattern | ||
| 126 | return $ tags { tagsMap = tagsMap tags ++ [(name, ids)] } | ||
| 127 | |||
| 15 | config :: Configuration | 128 | config :: Configuration |
| 16 | config = defaultConfiguration | 129 | config = defaultConfiguration { providerDirectory = "provider" |
| 130 | , deployCommand = "rsync -av --progress -c --delete-delay -m _site/ gkleen@surtr.yggdrasil.li:/var/www/dirty-haskell.org/" | ||
| 131 | } | ||
