-- | Rules for a post group: its index page and its posts
module MathiasSM.Rules.PostGroup (processPostGroup) where

import Hakyll (
    Compiler,
    Context,
    Rules,
    compile,
    getResourceString,
    listField,
    loadAllSnapshots,
    matchMetadata,
    metadataRoute,
    recentFirst,
    route,
    saveSnapshot,
 )
import MathiasSM.CleanURL (pathRoute)
import MathiasSM.Compile (applyTemplates, finish, runPandoc)
import MathiasSM.Config (SiteConfig, minimalTemplate, postSnapshot, postTemplate, postsPattern, resolveTemplate, siteEnv)
import MathiasSM.Content (isHidden, isTemplated, requirePost)
import MathiasSM.Context (globalContext, postSocialTagsContext)
import MathiasSM.Context.Nav (navContext)
import MathiasSM.Rules.SinglePages (Page (..), page, processPage)
import MathiasSM.Theme (applyContentAsTemplate)

-- | Processes a group: its index page and all the item pages
processPostGroup :: SiteConfig -> String -> Rules ()
processPostGroup :: SiteConfig -> String -> Rules ()
processPostGroup SiteConfig
cfg String
groupName = do
    SiteConfig -> String -> Rules ()
processPostGroupIndex SiteConfig
cfg String
groupName
    SiteConfig -> String -> Rules ()
processPostGroupItems SiteConfig
cfg String
groupName

-- | Builds the group index page as an archive page
processPostGroupIndex :: SiteConfig -> String -> Rules ()
processPostGroupIndex :: SiteConfig -> String -> Rules ()
processPostGroupIndex SiteConfig
cfg String
groupName =
    SiteConfig -> Page -> Rules ()
processPage SiteConfig
cfg (SiteConfig -> String -> Page
page SiteConfig
cfg String
groupName){pageContext = getCtx cfg groupName, pageTemplates = [resolveTemplate cfg "with-posts.html"]}

{- | Builds each item/post page

Anything but a draft must have valid front matter, or the build fails.
-}
processPostGroupItems :: SiteConfig -> String -> Rules ()
processPostGroupItems :: SiteConfig -> String -> Rules ()
processPostGroupItems SiteConfig
cfg String
groupName =
    Pattern -> (Metadata -> Bool) -> Rules () -> Rules ()
matchMetadata (SiteConfig -> String -> Pattern
postsPattern SiteConfig
cfg String
groupName) (Bool -> Bool
not (Bool -> Bool) -> (Metadata -> Bool) -> Metadata -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Env -> Metadata -> Bool
isHidden (SiteConfig -> Env
siteEnv SiteConfig
cfg)) (Rules () -> Rules ()) -> Rules () -> Rules ()
forall a b. (a -> b) -> a -> b
$ do
        Routes -> Rules ()
route (Routes -> Rules ()) -> Routes -> Rules ()
forall a b. (a -> b) -> a -> b
$ (Metadata -> Routes) -> Routes
metadataRoute Metadata -> Routes
pathRoute
        Compiler (Item String) -> Rules ()
forall a.
(Binary a, Typeable a, Writable a) =>
Compiler (Item a) -> Rules ()
compile (Compiler (Item String) -> Rules ())
-> Compiler (Item String) -> Rules ()
forall a b. (a -> b) -> a -> b
$ do
            _ <- Compiler Post
requirePost
            templated <- isTemplated
            getResourceString
                >>= (if templated then applyContentAsTemplate cfg (globalContext cfg) else return)
                >>= runPandoc
                >>= saveSnapshot (postSnapshot groupName)
                >>= applyTemplates (globalContext cfg) [minimalTemplate cfg, postTemplate cfg]
                >>= finish cfg (postSocialTagsContext cfg <> navContext cfg groupName <> globalContext cfg)

-- | Build context for archive page
getCtx :: SiteConfig -> String -> Compiler (Context String)
getCtx :: SiteConfig -> String -> Compiler (Context String)
getCtx SiteConfig
cfg String
groupName = do
    posts <- [Item String] -> Compiler [Item String]
forall (m :: * -> *) a.
(MonadMetadata m, MonadFail m) =>
[Item a] -> m [Item a]
recentFirst ([Item String] -> Compiler [Item String])
-> Compiler [Item String] -> Compiler [Item String]
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Pattern -> String -> Compiler [Item String]
forall a.
(Binary a, Typeable a) =>
Pattern -> String -> Compiler [Item a]
loadAllSnapshots (SiteConfig -> String -> Pattern
postsPattern SiteConfig
cfg String
groupName) (String -> String
postSnapshot String
groupName)
    return $ listField "posts" (globalContext cfg) (return posts) <> globalContext cfg