    --------------------------------------------------------------------------------
    -- | Provides an easy way to combine several items in a list. The applications
    -- are obvious:
    --
    -- * A post list on a blog
    --
    -- * An image list in a gallery
    --
    -- * A sitemap
    {-# LANGUAGE CPP           #-}
    {-# LANGUAGE TupleSections #-}
    module Hakyll.Web.Template.List
        ( applyTemplateList
        , applyJoinTemplateList
        , chronological
        , recentFirst
        , sortChronological
        , sortRecentFirst
        ) where

    --------------------------------------------------------------------------------
    import           Control.Monad               (liftM)
    #if !MIN_VERSION_base(4,13,0)
    import           Control.Monad.Fail          (MonadFail)
    #endif
    import           Data.List                   (intersperse, sortBy)
    import           Data.Ord                    (comparing)
    import           Data.Time.Locale.Compat     (defaultTimeLocale)

    --------------------------------------------------------------------------------
    import           Hakyll.Core.Compiler
    import           Hakyll.Core.Identifier
    import           Hakyll.Core.Item
    import           Hakyll.Core.Metadata
    import           Hakyll.Web.Template
    import           Hakyll.Web.Template.Context

    --------------------------------------------------------------------------------
    -- | Generate a string of a listing of pages, after applying a template to each
    -- page.
    applyTemplateList :: Template
                      -> Context a
                      -> [Item a]
                      -> Compiler String
    applyTemplateList :: forall a. Template -> Context a -> [Item a] -> Compiler String
    applyTemplateList = String -> Template -> Context a -> [Item a] -> Compiler String
    forall a.
    String -> Template -> Context a -> [Item a] -> Compiler String
    applyJoinTemplateList String
    ""

    --------------------------------------------------------------------------------
    -- | Join a listing of pages with a string in between, after applying a template
    -- to each page.
    applyJoinTemplateList :: String
                          -> Template
                          -> Context a
                          -> [Item a]
                          -> Compiler String
    applyJoinTemplateList :: forall a.
    String -> Template -> Context a -> [Item a] -> Compiler String
    applyJoinTemplateList String
    delimiter Template
    tpl Context a
    context [Item a]
    items = do
        [Item String]
    items' <- (Item a -> Compiler (Item String))
    -> [Item a] -> Compiler [Item String]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
    mapM (Template -> Context a -> Item a -> Compiler (Item String)
    forall a. Template -> Context a -> Item a -> Compiler (Item String)
    applyTemplate Template
    tpl Context a
    context) [Item a]
    items
        String -> Compiler String
    forall a. a -> Compiler a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (String -> Compiler String) -> String -> Compiler String
    forall a b. (a -> b) -> a -> b
    $ [String] -> String
    forall (t :: * -> *) a. Foldable t => t [a] -> [a]
    concat ([String] -> String) -> [String] -> String
    forall a b. (a -> b) -> a -> b
    $ String -> [String] -> [String]
    forall a. a -> [a] -> [a]
    intersperse String
    delimiter ([String] -> [String]) -> [String] -> [String]
    forall a b. (a -> b) -> a -> b
    $ (Item String -> String) -> [Item String] -> [String]
    forall a b. (a -> b) -> [a] -> [b]
    map Item String -> String
    forall a. Item a -> a
    itemBody [Item String]
    items'

    --------------------------------------------------------------------------------
    -- | Sort pages chronologically. Uses the same method as 'dateField' for
    -- extracting the date.
    chronological :: (MonadMetadata m, MonadFail m) => [Item a] -> m [Item a]
    chronological :: forall (m :: * -> *) a.
    (MonadMetadata m, MonadFail m) =>
    [Item a] -> m [Item a]
    chronological =
        (Item a -> m UTCTime) -> [Item a] -> m [Item a]
    forall (m :: * -> *) k a.
    (Monad m, Ord k) =>
    (a -> m k) -> [a] -> m [a]
    sortByM ((Item a -> m UTCTime) -> [Item a] -> m [Item a])
    -> (Item a -> m UTCTime) -> [Item a] -> m [Item a]
    forall a b. (a -> b) -> a -> b
    $ TimeLocale -> Identifier -> m UTCTime
    forall (m :: * -> *).
    (MonadMetadata m, MonadFail m) =>
    TimeLocale -> Identifier -> m UTCTime
    getItemUTC TimeLocale
    defaultTimeLocale (Identifier -> m UTCTime)
    -> (Item a -> Identifier) -> Item a -> m UTCTime
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Item a -> Identifier
    forall a. Item a -> Identifier
    itemIdentifier
      where
        sortByM :: (Monad m, Ord k) => (a -> m k) -> [a] -> m [a]
        sortByM :: forall (m :: * -> *) k a.
    (Monad m, Ord k) =>
    (a -> m k) -> [a] -> m [a]
    sortByM a -> m k
    f [a]
    xs = ([(a, k)] -> [a]) -> m [(a, k)] -> m [a]
    forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
    liftM (((a, k) -> a) -> [(a, k)] -> [a]
    forall a b. (a -> b) -> [a] -> [b]
    map (a, k) -> a
    forall a b. (a, b) -> a
    fst ([(a, k)] -> [a]) -> ([(a, k)] -> [(a, k)]) -> [(a, k)] -> [a]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ((a, k) -> (a, k) -> Ordering) -> [(a, k)] -> [(a, k)]
    forall a. (a -> a -> Ordering) -> [a] -> [a]
    sortBy (((a, k) -> k) -> (a, k) -> (a, k) -> Ordering
    forall a b. Ord a => (b -> a) -> b -> b -> Ordering
    comparing (a, k) -> k
    forall a b. (a, b) -> b
    snd)) (m [(a, k)] -> m [a]) -> m [(a, k)] -> m [a]
    forall a b. (a -> b) -> a -> b
    $
                       (a -> m (a, k)) -> [a] -> m [(a, k)]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
    mapM (\a
    x -> (k -> (a, k)) -> m k -> m (a, k)
    forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
    liftM (a
    x,) (a -> m k
    f a
    x)) [a]
    xs

    --------------------------------------------------------------------------------
    -- | The reverse of 'chronological'
    recentFirst :: (MonadMetadata m, MonadFail m) => [Item a] -> m [Item a]
    recentFirst :: forall (m :: * -> *) a.
    (MonadMetadata m, MonadFail m) =>
    [Item a] -> m [Item a]
    recentFirst = ([Item a] -> [Item a]) -> m [Item a] -> m [Item a]
    forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
    liftM [Item a] -> [Item a]
    forall a. [a] -> [a]
    reverse (m [Item a] -> m [Item a])
    -> ([Item a] -> m [Item a]) -> [Item a] -> m [Item a]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [Item a] -> m [Item a]
    forall (m :: * -> *) a.
    (MonadMetadata m, MonadFail m) =>
    [Item a] -> m [Item a]
    chronological

    --------------------------------------------------------------------------------
    -- | Version of 'chronological' which doesn't need the actual items.
    sortChronological
        :: (MonadMetadata m, MonadFail m) => [Identifier] -> m [Identifier]
    sortChronological :: forall (m :: * -> *).
    (MonadMetadata m, MonadFail m) =>
    [Identifier] -> m [Identifier]
    sortChronological [Identifier]
    ids =
        ([Item ()] -> [Identifier]) -> m [Item ()] -> m [Identifier]
    forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
    liftM ((Item () -> Identifier) -> [Item ()] -> [Identifier]
    forall a b. (a -> b) -> [a] -> [b]
    map Item () -> Identifier
    forall a. Item a -> Identifier
    itemIdentifier) (m [Item ()] -> m [Identifier]) -> m [Item ()] -> m [Identifier]
    forall a b. (a -> b) -> a -> b
    $ [Item ()] -> m [Item ()]
    forall (m :: * -> *) a.
    (MonadMetadata m, MonadFail m) =>
    [Item a] -> m [Item a]
    chronological [Identifier -> () -> Item ()
    forall a. Identifier -> a -> Item a
    Item Identifier
    i () | Identifier
    i <- [Identifier]
    ids]

    --------------------------------------------------------------------------------
    -- | Version of 'recentFirst' which doesn't need the actual items.
    sortRecentFirst
        :: (MonadMetadata m, MonadFail m) => [Identifier] -> m [Identifier]
    sortRecentFirst :: forall (m :: * -> *).
    (MonadMetadata m, MonadFail m) =>
    [Identifier] -> m [Identifier]
    sortRecentFirst [Identifier]
    ids =
        ([Item ()] -> [Identifier]) -> m [Item ()] -> m [Identifier]
    forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
    liftM ((Item () -> Identifier) -> [Item ()] -> [Identifier]
    forall a b. (a -> b) -> [a] -> [b]
    map Item () -> Identifier
    forall a. Item a -> Identifier
    itemIdentifier) (m [Item ()] -> m [Identifier]) -> m [Item ()] -> m [Identifier]
    forall a b. (a -> b) -> a -> b
    $ [Item ()] -> m [Item ()]
    forall (m :: * -> *) a.
    (MonadMetadata m, MonadFail m) =>
    [Item a] -> m [Item a]
    recentFirst [Identifier -> () -> Item ()
    forall a. Identifier -> a -> Item a
    Item Identifier
    i () | Identifier
    i <- [Identifier]
    ids]