packages feed

mathblog-0.6: src/MB/Gen/Post.hs

{-# LANGUAGE ScopedTypeVariables #-}
module MB.Gen.Post
    ( generatePosts
    , postTemplateAttrs
    )
where

import Data.Default
import Control.Applicative
import Control.Monad
import Control.Monad.Trans
import Data.Maybe
import qualified Data.Map as M
import Text.StringTemplate
    ( setManyAttrib )

import qualified Text.Pandoc as Pandoc
import MB.Processing
import MB.Types
import MB.Templates

import MB.Gen.Base

renderPostTemplate :: Blog -> Post -> (Maybe Post, Maybe Post) -> Template -> String -> String
renderPostTemplate blog post nextPrev postTemplate postHtml =
    let pAttrs = postTemplateAttrs blog post
        tmplWithPostAttrs =
            setManyAttrib [("post_authors", postAuthors post)] $
            setManyAttrib [("post", pAttrs)] $
            setManyAttrib [ ("next_post_url", postUrl <$> (fst nextPrev))
                          , ("prev_post_url", postUrl <$> (snd nextPrev))
                          ]
            postTemplate

        attrs = [ ("post_html", postHtml)
                ]
    in fillTemplate blog tmplWithPostAttrs attrs

postTemplateAttrs :: Blog -> Post -> M.Map String String
postTemplateAttrs blog post =
    let datestr = postDate post <|> Just (postModificationString post)
    in M.fromList [ ("title", getPostTitle blog post BlogPost)
                  , ("date", fromJust datestr)
                  , ("url", postUrl post)
                  , ("basename", postBaseName post)
                  , ("tex_macros", postTeXMacros post)
                  ]

generatePosts :: BlogM ()
generatePosts = do
  blog <- theBlog

  let toRender = zip (blogPosts blog) [0..]

  forM_ toRender $ \(post, pos) ->
      renderSingle post pos

renderSingle :: Post -> Int -> BlogM ()
renderSingle post pos = do
  blog <- theBlog
  conf <- theConfig

  let st = inputFSState blog
      renderCauses p =
          catMaybes $ [ if postModificationTime p > ifsBaselineMTime st
                        then Just PostModified
                        else Nothing
                      , if ifsPostIndexMTime st > ifsBaselineMTime st
                        then Just PostIndex
                        else Nothing
                      , if ifsConfigMTime st > ifsBaselineMTime st
                        then Just Config
                        else Nothing
                      , if forceRegeneration conf
                        then Just Forced
                        else Nothing
                      , if ifsTemplateMTime st > ifsBaselineMTime st
                        then Just Template
                        else Nothing
                      ]

  if null (renderCauses post) then
      return () else
      do
        let nextPost = if pos == 0
                       then Nothing
                       else Just (blogPosts blog !! (pos - 1))

            prevPost = if pos == (length $ blogPosts blog) - 1
                       then Nothing
                       else Just (blogPosts blog !! (pos + 1))

        notify $ PostRender post $ renderCauses post

        -- Steps:

        -- Transform AST with preprocessors;
        newPost <- applyPreProcessors post

        -- Render the transformed AST as HTML using Pandoc;
        let writerOpts = getWriterOptions blog def
            postBodyHtml = Pandoc.writeHtmlString writerOpts (postAst newPost)

        withTemplate (ifsPageTemplatePath $ inputFS blog) $ \pageTmpl ->
            withTemplate (ifsPostTemplatePath $ inputFS blog) $ \postTmpl ->
                do
                  -- Embed the converted Pandoc HTML into the postTemplate;
                  let postPageHtml = renderPostTemplate blog post (nextPost, prevPost) postTmpl postBodyHtml
                      -- Embed the postTemplate result in the pageTemplate.
                      finalPageHtml = buildPage blog postPageHtml (Just $ getRawPostTitle blog post) pageTmpl

                  -- Write the final, complete page HTML to the post
                  -- HTML file location.
                  liftIO $ writeFile (ofsPostFinalHtml (outputFS blog) post) finalPageHtml

                  -- Give postprocessors a chance to transform the
                  -- final HTML.
                  applyPostProcessors (ofsPostFinalHtml (outputFS blog) post) BlogPost