blog/site.hs
2020-04-02 14:54:42 +02:00

183 lines
6 KiB
Haskell

--------------------------------------------------------------------------------
{-# LANGUAGE OverloadedStrings #-}
import qualified Data.Map as Map
import Data.Monoid (mappend)
import qualified Text.CSL as CSL
import Text.CSL.Pandoc (processCites)
import Text.Pandoc
import Text.Pandoc.Options
import Text.Pandoc.Highlighting
import Hakyll
import Hakyll.Core.Compiler.Internal (compilerProvider, compilerAsk)
import Hakyll.Core.Provider (resourceFilePath)
--------------------------------------------------------------------------------
main :: IO ()
main = hakyll $ do
match "images/**" $ do
route idRoute
compile copyFileCompiler
match "favicon.ico" $ do
route idRoute
compile copyFileCompiler
match "files/*" $ do
route idRoute
compile copyFileCompiler
match "css/*" $ do
route idRoute
compile compressCssCompiler
match "bib/*" $ compile biblioCompiler
match "csl/*" $ compile cslCompiler
match "posts/*" $ do
route $ setExtension "html"
compile $ customPandocCompiler
>>= loadAndApplyTemplate "templates/post.html" postCtx
>>= saveSnapshot "content"
>>= loadAndApplyTemplate "templates/default.html" postCtx
>>= relativizeUrls
match "projects/*" $ do
route $ setExtension "html"
compile $ customPandocCompiler
>>= loadAndApplyTemplate "templates/project.html" postCtx
>>= loadAndApplyTemplate "templates/default.html" postCtx
>>= relativizeUrls
match (fromList ["contact.org", "cv.org", "skills.org", "projects.org"]) $ do
route $ setExtension "html"
compile $ customPandocCompiler
>>= loadAndApplyTemplate "templates/default.html" defaultContext
>>= relativizeUrls
create ["archive.html"] $ do
route idRoute
compile $ do
posts <- recentFirst =<< loadAll "posts/*"
let archiveCtx =
listField "posts" postCtx (return posts) `mappend`
constField "title" "Archives" `mappend`
defaultContext
makeItem ""
>>= loadAndApplyTemplate "templates/archive.html" archiveCtx
>>= loadAndApplyTemplate "templates/default.html" archiveCtx
>>= relativizeUrls
create ["projects.html"] $ do
route idRoute
compile $ do
posts <- recentFirst =<< loadAll "projects/*"
let archiveCtx =
listField "projects" postCtx (return posts) `mappend`
constField "title" "Projects" `mappend`
defaultContext
makeItem ""
>>= loadAndApplyTemplate "templates/projects.html" archiveCtx
>>= loadAndApplyTemplate "templates/default.html" archiveCtx
>>= relativizeUrls
create ["atom.xml"] $ do
route idRoute
compile (feedCompiler renderAtom)
create ["rss.xml"] $ do
route idRoute
compile (feedCompiler renderRss)
match "index.html" $ do
route idRoute
compile $ do
posts <- fmap (take 10) $ recentFirst =<< loadAll "posts/*"
let indexCtx =
listField "posts" postCtx (return posts) `mappend`
defaultContext
getResourceBody
>>= applyAsTemplate indexCtx
>>= loadAndApplyTemplate "templates/default.html" indexCtx
>>= relativizeUrls
match "templates/*" $ compile templateBodyCompiler
--------------------------------------------------------------------------------
feedConfiguration :: FeedConfiguration
feedConfiguration =
FeedConfiguration
{ feedTitle = "Dimitri Lozeve's Blog"
, feedDescription = "Recent posts"
, feedAuthorName = "Dimitri Lozeve"
, feedAuthorEmail = "dimitri+web@lozeve.com"
, feedRoot = "https://www.lozeve.com"
}
postCtx :: Context String
postCtx =
dateField "date" "%B %e, %Y" `mappend`
defaultContext
feedCtx :: Context String
feedCtx = postCtx <> bodyField "description"
-- Add links to references ------------------------------------------
-- Source: https://github.com/jaspervdj/hakyll/issues/471#issuecomment-244540329
addLinkCitations (Pandoc meta a) =
let prevMap = unMeta meta
newMap = Map.insert "link-citations" (MetaBool True) prevMap
newMeta = Meta newMap
in Pandoc newMeta a
myReadPandocBiblio :: ReaderOptions
-> Item CSL
-> Item Biblio
-> (Item String)
-> Compiler (Item Pandoc)
myReadPandocBiblio ropt csl biblio item = do
-- Parse CSL file, if given
provider <- compilerProvider <$> compilerAsk
style <- unsafeCompiler $
CSL.readCSLFile Nothing . (resourceFilePath provider) . itemIdentifier $ csl
-- We need to know the citation keys, add then *before* actually parsing the
-- actual page. If we don't do this, pandoc won't even consider them
-- citations!
let Biblio refs = itemBody biblio
pandoc <- itemBody <$> readPandocWith ropt item
let pandoc' = processCites style refs (addLinkCitations pandoc)
return $ fmap (const pandoc') item
-- Pandoc compiler with KaTeX and bibliography support --------------------
customPandocCompiler :: Compiler (Item String)
customPandocCompiler =
let customExtensions = extensionsFromList [Ext_latex_macros]
defaultExtensions = writerExtensions defaultHakyllWriterOptions
newExtensions = defaultExtensions `mappend` customExtensions
writerOptions = defaultHakyllWriterOptions
{ writerExtensions = newExtensions
, writerHTMLMathMethod = KaTeX ""
}
readerOptions = defaultHakyllReaderOptions
in do
csl <- load $ fromFilePath "csl/chicago-author-date.csl"
bib <- load $ fromFilePath "bib/bibliography.bib"
writePandocWith writerOptions <$>
(getResourceBody >>= myReadPandocBiblio readerOptions csl bib)
type FeedRenderer = FeedConfiguration
-> Context String
-> [Item String]
-> Compiler (Item String)
feedCompiler :: FeedRenderer -> Compiler (Item String)
feedCompiler renderer =
renderer feedConfiguration feedCtx
=<< fmap (take 10) . recentFirst
=<< loadAllSnapshots "posts/*" "content"