tA's crappy blog
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

166 lines
5.0KB

  1. {-# LANGUAGE OverloadedStrings #-}
  2. import Data.Monoid ((<>))
  3. import Data.List (sortBy,isSuffixOf)
  4. import Data.Typeable
  5. import GHC.IO.Encoding
  6. import Hakyll
  7. import Hakyll.Favicon (faviconsRules, faviconsField)
  8. import System.FilePath.Posix (takeBaseName,takeDirectory,(</>))
  9. main :: IO ()
  10. main = do
  11. -- Set the encoding so w3c doesnt complain
  12. setLocaleEncoding utf8
  13. hakyllWith rfConf $ do
  14. -- Generate the favicons
  15. faviconsRules "icons/favicon.svg"
  16. -- Straight copying of files
  17. match (fromList ["humans.txt", "robots.txt", "fonts/*"]) $ do
  18. route idRoute
  19. compile copyFileCompiler
  20. -- CSS needs to be compiled and minified
  21. match "css/*" $ do
  22. route idRoute
  23. compile compressCssCompiler
  24. -- Load pages that need to be formatted
  25. match (fromList ["about.md", "contact.md"]) $ do
  26. route $ cleanRoute
  27. compile $ pandocCompiler
  28. >>= loadAndApplyTemplate "templates/default.html" ctx
  29. >>= relativizeUrls
  30. >>= cleanIndexUrls
  31. -- Render Atom + Rss feeds
  32. create ["atom.xml"] $ do
  33. route idRoute
  34. (compileFeed renderAtom)
  35. create ["rss.xml"] $ do
  36. route idRoute
  37. (compileFeed renderRss)
  38. -- Compile the templates
  39. match "templates/*" $ compile templateBodyCompiler
  40. -- Compile the archive page and post list
  41. match "archive.md" $ do
  42. route $ cleanRoute
  43. compile $ do
  44. posts <- recentFirst =<< loadAll "posts/*"
  45. let archiveCtx =
  46. listField "posts" postCtx (return posts) <>
  47. ctx
  48. pandocCompiler
  49. >>= loadAndApplyTemplate "templates/archive.html" archiveCtx
  50. >>= loadAndApplyTemplate "templates/default.html" archiveCtx
  51. >>= relativizeUrls
  52. >>= cleanIndexUrls
  53. -- Compile and load posts
  54. match "index.md" $ do
  55. route $ setExtension "html"
  56. compile $ pandocCompiler
  57. >>= loadAndApplyTemplate "templates/index.html" ctx
  58. >>= relativizeUrls
  59. >>= cleanIndexUrls
  60. compile $ do
  61. posts <- (return . (take 5))
  62. =<< recentFirst
  63. =<< loadAll "posts/*"
  64. let indexCtx =
  65. listField "posts" postCtx (return posts) <> ctx
  66. pandocCompiler
  67. >>= applyAsTemplate indexCtx
  68. >>= loadAndApplyTemplate "templates/index.html" indexCtx
  69. >>= loadAndApplyTemplate "templates/default.html" indexCtx
  70. >>= relativizeUrls
  71. >>= cleanIndexUrls
  72. -- Compile posts + save snapshots for the web feeds
  73. match "posts/*" $ do
  74. route $ cleanRoute
  75. compile $ pandocCompiler
  76. >>= loadAndApplyTemplate "templates/post.html" postCtx
  77. >>= saveSnapshot "content"
  78. >>= loadAndApplyTemplate "templates/default.html" postCtx
  79. >>= relativizeUrls
  80. >>= cleanIndexUrls
  81. >>= cleanIndexHtmls
  82. -- Set the input/output directories
  83. rfConf :: Configuration
  84. rfConf = defaultConfiguration
  85. { destinationDirectory = "_http"
  86. , storeDirectory = "_store"
  87. , tmpDirectory = "_tmp"
  88. , providerDirectory = "_input"
  89. }
  90. -- Agnememnon the Fuck-Upperer - Conquerer of Small Type Declarations
  91. compileFeed ::
  92. (FeedConfiguration
  93. -> Context String
  94. -> [Item String]
  95. -> Compiler (Item String)
  96. ) -> Rules ()
  97. -- For those left alive, this abstracts out creating
  98. -- Atom and RSS feeds
  99. compileFeed f = compile $ do
  100. let feedCtx = postCtx <>
  101. bodyField "description"
  102. posts <- fmap (take 10) . recentFirst
  103. =<< loadAllSnapshots "posts/*" "content"
  104. f feedConfig feedCtx posts
  105. -- The configuration for our Atom/RSS feeds
  106. feedConfig :: FeedConfiguration
  107. feedConfig = FeedConfiguration {
  108. feedTitle = "Regular Flolloping"
  109. , feedDescription = "tA's Blog"
  110. , feedAuthorName = "Shaun Kerr"
  111. , feedAuthorEmail = "s@p7.co.nz"
  112. , feedRoot = "https://regularflolloping.com"
  113. }
  114. -- Our default context for pages
  115. ctx :: Context String
  116. ctx = defaultContext <>
  117. faviconsField
  118. -- Default context for posts
  119. postCtx :: Context String
  120. postCtx =
  121. (dateField "date" "%B %e, %Y") <> ctx
  122. -- Functions to convert pages to /name/index.html
  123. cleanRoute :: Routes
  124. cleanRoute = customRoute createIndexRoute
  125. where
  126. createIndexRoute ident =
  127. takeDirectory p </> takeBaseName p </> "index.html"
  128. where p = toFilePath ident
  129. cleanIndexUrls :: Item String -> Compiler (Item String)
  130. cleanIndexUrls = return . fmap (withUrls cleanIndex)
  131. cleanIndexHtmls :: Item String -> Compiler (Item String)
  132. cleanIndexHtmls = return . fmap (replaceAll pattern replacement)
  133. where
  134. pattern = "/index.html"
  135. replacement = const "/"
  136. cleanIndex :: String -> String
  137. cleanIndex url
  138. | idx `isSuffixOf` url = take (length url - length idx) url
  139. | otherwise = url
  140. where idx = "index.html"