nani.wtf/ssg/src/Main.hs

239 lines
5.8 KiB
Haskell
Raw Normal View History

2020-09-22 04:03:52 +02:00
{-# LANGUAGE OverloadedStrings #-}
import Control.Monad (forM_)
import Data.Maybe (fromMaybe)
import Hakyll
2021-07-31 12:58:54 +02:00
import qualified Data.Text as T
import qualified Data.Text.Slugger as Slugger
2020-09-22 04:03:52 +02:00
import Text.Pandoc
( 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,
2021-06-13 06:02:29 +02:00
WriterOptions (writerHighlightStyle),
2020-09-22 04:03:52 +02:00
extensionsFromList,
githubMarkdownExtensions,
readerExtensions,
writerExtensions,
)
2021-06-13 06:02:29 +02:00
import Text.Pandoc.Highlighting (Style, breezeDark, styleToCss)
2020-09-22 04:03:52 +02:00
2021-08-03 02:01:55 +02:00
--------------------------------------------------------------------------------
2020-09-22 04:03:52 +02:00
-- CONFIG
root :: String
root =
2021-06-13 06:02:29 +02:00
"https://my-site.com"
2020-09-22 04:03:52 +02:00
siteName :: String
siteName =
"My Site Name"
config :: Configuration
config =
defaultConfiguration
2021-08-03 02:01:55 +02:00
{ destinationDirectory = "dist"
, ignoreFile = const False
, previewHost = "127.0.0.1"
, previewPort = 8000
, providerDirectory = "src"
, storeDirectory = "ssg/_cache"
, tmpDirectory = "ssg/_tmp"
2020-09-22 04:03:52 +02:00
}
2021-08-03 02:01:55 +02:00
--------------------------------------------------------------------------------
2020-09-22 04:03:52 +02:00
-- BUILD
main :: IO ()
main = hakyllWith config $ do
forM_
2021-08-03 02:01:55 +02:00
[ "CNAME"
, "favicon.ico"
, "robots.txt"
, "_config.yml"
, "images/*"
, "js/*"
, "fonts/*"
2020-09-22 04:03:52 +02:00
]
$ \f -> match f $ do
route idRoute
compile copyFileCompiler
2021-06-13 06:02:29 +02:00
2020-09-22 04:03:52 +02:00
match "css/*" $ do
route idRoute
compile compressCssCompiler
2021-06-13 06:02:29 +02:00
2020-09-22 04:03:52 +02:00
match "posts/*" $ do
let ctx = constField "type" "article" <> postCtx
2021-06-13 06:02:29 +02:00
2020-09-22 04:03:52 +02:00
route $ metadataRoute titleRoute
compile $
pandocCompilerCustom
>>= loadAndApplyTemplate "templates/post.html" ctx
>>= saveSnapshot "content"
>>= loadAndApplyTemplate "templates/default.html" ctx
2021-06-13 06:02:29 +02:00
2020-09-22 04:03:52 +02:00
match "index.html" $ do
route idRoute
compile $ do
posts <- recentFirst =<< loadAll "posts/*"
2021-06-13 06:02:29 +02:00
2020-09-22 04:03:52 +02:00
let indexCtx =
listField "posts" postCtx (return posts)
<> constField "root" root
<> constField "siteName" siteName
<> defaultContext
2021-06-13 06:02:29 +02:00
2020-09-22 04:03:52 +02:00
getResourceBody
>>= applyAsTemplate indexCtx
>>= loadAndApplyTemplate "templates/default.html" indexCtx
2021-06-13 06:02:29 +02:00
match "templates/*" $
compile templateBodyCompiler
2021-06-13 06:02:29 +02:00
2020-09-22 04:03:52 +02:00
create ["sitemap.xml"] $ do
route idRoute
compile $ do
posts <- recentFirst =<< loadAll "posts/*"
2021-06-13 06:02:29 +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)
2021-06-13 06:02:29 +02:00
2020-09-22 04:03:52 +02:00
makeItem ("" :: String)
>>= loadAndApplyTemplate "templates/sitemap.xml" sitemapCtx
2021-06-13 06:02:29 +02:00
2020-09-22 04:03:52 +02:00
create ["rss.xml"] $ do
route idRoute
compile (feedCompiler renderRss)
2021-06-13 06:02:29 +02:00
2020-09-22 04:03:52 +02:00
create ["atom.xml"] $ do
route idRoute
compile (feedCompiler renderAtom)
2021-06-13 06:02:29 +02:00
create ["css/code.css"] $ do
route idRoute
compile (makeStyle pandocHighlightStyle)
2021-08-03 02:01:55 +02:00
--------------------------------------------------------------------------------
2021-06-13 06:02:29 +02:00
-- COMPILER HELPERS
makeStyle :: Style -> Compiler (Item String)
makeStyle =
makeItem . compressCss . styleToCss
2021-08-03 02:01:55 +02:00
--------------------------------------------------------------------------------
2020-09-22 04:03:52 +02:00
-- 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
2021-08-03 02:01:55 +02:00
--------------------------------------------------------------------------------
2020-09-22 04:03:52 +02:00
-- TITLE HELPERS
replaceAmp :: String -> String
replaceAmp =
replaceAll "&" (const "&amp;")
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
2021-08-03 02:01:55 +02:00
--------------------------------------------------------------------------------
2020-09-22 04:03:52 +02:00
-- PANDOC
pandocCompilerCustom :: Compiler (Item String)
pandocCompilerCustom =
pandocCompilerWith pandocReaderOpts pandocWriterOpts
pandocExtensionsCustom :: Extensions
pandocExtensionsCustom =
githubMarkdownExtensions
<> extensionsFromList
2021-08-03 02:01:55 +02:00
[ Ext_fenced_code_attributes
, Ext_gfm_auto_identifiers
, Ext_implicit_header_references
, Ext_smart
, Ext_footnotes
2020-09-22 04:03:52 +02:00
]
pandocReaderOpts :: ReaderOptions
pandocReaderOpts =
defaultHakyllReaderOptions
{ readerExtensions = pandocExtensionsCustom
}
pandocWriterOpts :: WriterOptions
pandocWriterOpts =
defaultHakyllWriterOptions
{ writerExtensions = pandocExtensionsCustom
2021-06-13 06:02:29 +02:00
, writerHighlightStyle = Just pandocHighlightStyle
2020-09-22 04:03:52 +02:00
}
2021-06-13 06:02:29 +02:00
pandocHighlightStyle :: Style
pandocHighlightStyle =
breezeDark -- https://hackage.haskell.org/package/pandoc/docs/Text-Pandoc-Highlighting.html
2020-09-22 04:03:52 +02:00
-- 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
2021-08-03 02:01:55 +02:00
{ feedTitle = "My Site"
, feedDescription = "My Site Description"
, feedAuthorName = "My Name"
, feedAuthorEmail = "me@myemail.com"
, feedRoot = root
2020-09-22 04:03:52 +02:00
}
2021-08-03 02:01:55 +02:00
--------------------------------------------------------------------------------
2020-09-22 04:03:52 +02:00
-- CUSTOM ROUTE
getTitleFromMeta :: Metadata -> String
getTitleFromMeta =
fromMaybe "no title" . lookupString "title"
fileNameFromTitle :: Metadata -> FilePath
fileNameFromTitle =
2021-07-31 12:58:54 +02:00
T.unpack . (`T.append` ".html") . Slugger.toSlug . T.pack . getTitleFromMeta
2020-09-22 04:03:52 +02:00
titleRoute :: Metadata -> Routes
titleRoute =
constRoute . fileNameFromTitle