49 lines
1.8 KiB
Haskell
49 lines
1.8 KiB
Haskell
{-# LANGUAGE GHC2021 #-}
|
|
{-# LANGUAGE OverloadedStrings #-}
|
|
-- | Pagination helpers.
|
|
--
|
|
-- NOTE: This module must not import Contexts or Tags to avoid cycles.
|
|
-- Callers (Site.hs) pass contexts in as parameters.
|
|
module Pagination
|
|
( pageSize
|
|
, sortAndGroup
|
|
, blogPaginateRules
|
|
) where
|
|
|
|
import Hakyll
|
|
|
|
|
|
-- | Items per page across all paginated lists.
|
|
pageSize :: Int
|
|
pageSize = 20
|
|
|
|
-- | Sort identifiers by date (most recent first) and split into pages.
|
|
sortAndGroup :: (MonadMetadata m, MonadFail m) => [Identifier] -> m [[Identifier]]
|
|
sortAndGroup ids = paginateEvery pageSize <$> sortRecentFirst ids
|
|
|
|
-- | Page identifier for the blog index.
|
|
-- Page 1 → blog/index.html
|
|
-- Page N → blog/page/N/index.html
|
|
blogPageId :: PageNumber -> Identifier
|
|
blogPageId 1 = fromFilePath "blog/index.html"
|
|
blogPageId n = fromFilePath $ "blog/page/" ++ show n ++ "/index.html"
|
|
|
|
-- | Build and rule-ify a paginated blog index.
|
|
-- @itemCtx@: context for individual posts (postCtx).
|
|
-- @baseCtx@: site-level context (siteCtx).
|
|
blogPaginateRules :: Context String -> Context String -> Rules ()
|
|
blogPaginateRules itemCtx baseCtx = do
|
|
paginate <- buildPaginateWith sortAndGroup ("content/blog/*.md" .&&. hasNoVersion) blogPageId
|
|
paginateRules paginate $ \pageNum pat -> do
|
|
route idRoute
|
|
compile $ do
|
|
posts <- recentFirst =<< loadAll (pat .&&. hasNoVersion)
|
|
let ctx = listField "posts" itemCtx (return posts)
|
|
<> paginateContext paginate pageNum
|
|
<> constField "title" "Blog"
|
|
<> baseCtx
|
|
makeItem ""
|
|
>>= loadAndApplyTemplate "templates/blog-index.html" ctx
|
|
>>= loadAndApplyTemplate "templates/default.html" ctx
|
|
>>= relativizeUrls
|