2020-09-22 04:03:52 +02:00
|
|
|
{-# LANGUAGE OverloadedStrings #-}
|
|
|
|
|
|
|
|
import Control.Monad (forM_)
|
|
|
|
import Data.Maybe (fromMaybe)
|
|
|
|
import qualified Data.Text as T
|
|
|
|
import Hakyll
|
|
|
|
import Slug (toSlug)
|
|
|
|
import Text.Pandoc
|
2020-10-21 09:59:05 +02:00
|
|
|
( Extension (Ext_fenced_code_attributes, Ext_footnotes, Ext_gfm_auto_identifiers, Ext_implicit_header_references, Ext_smart),
|
2020-09-22 04:03:52 +02:00
|
|
|
Extensions,
|
|
|
|
ReaderOptions,
|
|
|
|
WriterOptions,
|
|
|
|
extensionsFromList,
|
|
|
|
githubMarkdownExtensions,
|
|
|
|
readerExtensions,
|
|
|
|
writerExtensions,
|
|
|
|
)
|
|
|
|
|
|
|
|
-- CONFIG
|
|
|
|
|
|
|
|
root :: String
|
|
|
|
root =
|
2020-09-23 12:58:47 +02:00
|
|
|
"https://rpearce.github.io/hakyll-nix-template"
|
2020-09-22 04:03:52 +02:00
|
|
|
|
|
|
|
siteName :: String
|
|
|
|
siteName =
|
|
|
|
"My Site Name"
|
|
|
|
|
|
|
|
config :: Configuration
|
|
|
|
config =
|
|
|
|
defaultConfiguration
|
|
|
|
{ destinationDirectory = "../dist",
|
|
|
|
ignoreFile = const False,
|
|
|
|
previewHost = "127.0.0.1",
|
|
|
|
previewPort = 8000,
|
|
|
|
providerDirectory = "../src",
|
|
|
|
storeDirectory = "../hakyll-cache",
|
|
|
|
tmpDirectory = "../hakyll-cache/tmp"
|
|
|
|
}
|
|
|
|
|
|
|
|
-- BUILD
|
|
|
|
|
|
|
|
main :: IO ()
|
|
|
|
main = hakyllWith config $ do
|
|
|
|
forM_
|
|
|
|
[ "CNAME",
|
|
|
|
"favicon.ico",
|
|
|
|
"robots.txt",
|
|
|
|
"_config.yml",
|
|
|
|
"images/*",
|
|
|
|
"js/*",
|
|
|
|
"fonts/*"
|
|
|
|
]
|
|
|
|
$ \f -> match f $ do
|
|
|
|
route idRoute
|
|
|
|
compile copyFileCompiler
|
|
|
|
match "css/*" $ do
|
|
|
|
route idRoute
|
|
|
|
compile compressCssCompiler
|
|
|
|
match "posts/*" $ do
|
|
|
|
let ctx = constField "type" "article" <> postCtx
|
|
|
|
route $ metadataRoute titleRoute
|
|
|
|
compile $
|
|
|
|
pandocCompilerCustom
|
|
|
|
>>= loadAndApplyTemplate "templates/post.html" ctx
|
|
|
|
>>= saveSnapshot "content"
|
|
|
|
>>= loadAndApplyTemplate "templates/default.html" ctx
|
|
|
|
match "index.html" $ do
|
|
|
|
route idRoute
|
|
|
|
compile $ do
|
|
|
|
posts <- recentFirst =<< loadAll "posts/*"
|
|
|
|
let indexCtx =
|
|
|
|
listField "posts" postCtx (return posts)
|
|
|
|
<> constField "root" root
|
|
|
|
<> constField "siteName" siteName
|
|
|
|
<> defaultContext
|
|
|
|
getResourceBody
|
|
|
|
>>= applyAsTemplate indexCtx
|
|
|
|
>>= loadAndApplyTemplate "templates/default.html" indexCtx
|
|
|
|
match "templates/*" $ compile templateBodyCompiler
|
|
|
|
create ["sitemap.xml"] $ do
|
|
|
|
route idRoute
|
|
|
|
compile $ do
|
|
|
|
posts <- recentFirst =<< loadAll "posts/*"
|
2020-09-23 03:55:39 +02:00
|
|
|
let pages = posts
|
2020-09-22 04:03:52 +02:00
|
|
|
sitemapCtx =
|
|
|
|
constField "root" root
|
|
|
|
<> constField "siteName" siteName
|
|
|
|
<> listField "pages" postCtx (return pages)
|
|
|
|
makeItem ("" :: String)
|
|
|
|
>>= loadAndApplyTemplate "templates/sitemap.xml" sitemapCtx
|
|
|
|
create ["rss.xml"] $ do
|
|
|
|
route idRoute
|
|
|
|
compile (feedCompiler renderRss)
|
|
|
|
create ["atom.xml"] $ do
|
|
|
|
route idRoute
|
|
|
|
compile (feedCompiler renderAtom)
|
|
|
|
|
|
|
|
-- CONTEXT
|
|
|
|
|
|
|
|
feedCtx :: Context String
|
|
|
|
feedCtx =
|
|
|
|
titleCtx
|
|
|
|
<> postCtx
|
|
|
|
<> bodyField "description"
|
|
|
|
|
|
|
|
postCtx :: Context String
|
|
|
|
postCtx =
|
|
|
|
constField "root" root
|
|
|
|
<> constField "siteName" siteName
|
|
|
|
<> dateField "date" "%Y-%m-%d"
|
|
|
|
<> defaultContext
|
|
|
|
|
|
|
|
titleCtx :: Context String
|
|
|
|
titleCtx =
|
|
|
|
field "title" updatedTitle
|
|
|
|
|
|
|
|
-- TITLE HELPERS
|
|
|
|
|
|
|
|
replaceAmp :: String -> String
|
|
|
|
replaceAmp =
|
|
|
|
replaceAll "&" (const "&")
|
|
|
|
|
|
|
|
replaceTitleAmp :: Metadata -> String
|
|
|
|
replaceTitleAmp =
|
|
|
|
replaceAmp . safeTitle
|
|
|
|
|
|
|
|
safeTitle :: Metadata -> String
|
|
|
|
safeTitle =
|
|
|
|
fromMaybe "no title" . lookupString "title"
|
|
|
|
|
|
|
|
updatedTitle :: Item a -> Compiler String
|
|
|
|
updatedTitle =
|
|
|
|
fmap replaceTitleAmp . getMetadata . itemIdentifier
|
|
|
|
|
|
|
|
-- PANDOC
|
|
|
|
|
|
|
|
pandocCompilerCustom :: Compiler (Item String)
|
|
|
|
pandocCompilerCustom =
|
|
|
|
pandocCompilerWith pandocReaderOpts pandocWriterOpts
|
|
|
|
|
|
|
|
pandocExtensionsCustom :: Extensions
|
|
|
|
pandocExtensionsCustom =
|
|
|
|
githubMarkdownExtensions
|
|
|
|
<> extensionsFromList
|
2020-10-21 09:59:05 +02:00
|
|
|
[ Ext_fenced_code_attributes,
|
|
|
|
Ext_gfm_auto_identifiers,
|
|
|
|
Ext_implicit_header_references,
|
2020-09-22 04:03:52 +02:00
|
|
|
Ext_smart,
|
|
|
|
Ext_footnotes
|
|
|
|
]
|
|
|
|
|
|
|
|
pandocReaderOpts :: ReaderOptions
|
|
|
|
pandocReaderOpts =
|
|
|
|
defaultHakyllReaderOptions
|
|
|
|
{ readerExtensions = pandocExtensionsCustom
|
|
|
|
}
|
|
|
|
|
|
|
|
pandocWriterOpts :: WriterOptions
|
|
|
|
pandocWriterOpts =
|
|
|
|
defaultHakyllWriterOptions
|
|
|
|
{ writerExtensions = pandocExtensionsCustom
|
|
|
|
}
|
|
|
|
|
|
|
|
-- FEEDS
|
|
|
|
|
|
|
|
type FeedRenderer =
|
|
|
|
FeedConfiguration ->
|
|
|
|
Context String ->
|
|
|
|
[Item String] ->
|
|
|
|
Compiler (Item String)
|
|
|
|
|
|
|
|
feedCompiler :: FeedRenderer -> Compiler (Item String)
|
|
|
|
feedCompiler renderer =
|
|
|
|
renderer feedConfiguration feedCtx
|
|
|
|
=<< recentFirst
|
|
|
|
=<< loadAllSnapshots "posts/*" "content"
|
|
|
|
|
|
|
|
feedConfiguration :: FeedConfiguration
|
|
|
|
feedConfiguration =
|
|
|
|
FeedConfiguration
|
|
|
|
{ feedTitle = "My Site",
|
|
|
|
feedDescription = "My Site Description",
|
|
|
|
feedAuthorName = "My Name",
|
|
|
|
feedAuthorEmail = "me@myemail.com",
|
|
|
|
feedRoot = root
|
|
|
|
}
|
|
|
|
|
|
|
|
-- CUSTOM ROUTE
|
|
|
|
|
|
|
|
getTitleFromMeta :: Metadata -> String
|
|
|
|
getTitleFromMeta =
|
|
|
|
fromMaybe "no title" . lookupString "title"
|
|
|
|
|
|
|
|
fileNameFromTitle :: Metadata -> FilePath
|
|
|
|
fileNameFromTitle =
|
|
|
|
T.unpack . (`T.append` ".html") . toSlug . T.pack . getTitleFromMeta
|
|
|
|
|
|
|
|
titleRoute :: Metadata -> Routes
|
|
|
|
titleRoute =
|
|
|
|
constRoute . fileNameFromTitle
|