packages feed

heckle-0.1.0.0: src/Heckle.hs

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE FlexibleInstances #-}

module Heckle where

--Blaze HTML
import Text.Blaze.Html5 as H hiding (main, map)
import Text.Blaze.Html5.Attributes as A
import Text.Blaze.Html.Renderer.Pretty

--Pandoc
import Text.Pandoc.Options
import Text.Pandoc.Readers.Markdown
import Text.Pandoc.Definition
import Text.Pandoc.Writers.HTML

--TagSoup
import Text.HTML.TagSoup

--Other
import Data.List.Split
import Control.Applicative
import Data.Map.Lazy as Map (lookup)
import Control.Monad

data Post = Post {
  filename :: String
  , pd :: Pandoc
  , postTitle :: String
  , postDate :: String
  }
          deriving (Eq, Show)

getMD :: FilePath -> Either String String
getMD s = case splitOn "." s of
            [fn, "md"] -> Right fn
            _ -> Left "Not a PDF file"

getMeta :: (Meta -> [Inline]) -> Pandoc -> Either String String
getMeta f (Pandoc m _) = case f m of
  [] -> Left "Couldn't find it"
  ((Str s):xs) -> Right s
  (_:xs) -> Left "Not a string??"

createPost :: Show a => String -> Either a Pandoc -> Either String Post
createPost _ (Left e) = Left (show e)
createPost fn (Right pd) = 
	Post <$> pure fn <*> pure pd <*> getMeta docTitle pd <*> getMeta docDate pd

filenameToPost :: String -> IO (Either String Post)
filenameToPost fn = do
	native <- fmap (readMarkdown def) (readFile ("posts/" ++ fn ++ ".md"))
	return (createPost fn native)
        
writeHTML :: Post -> IO ()
writeHTML p = do
	let html = writeHtmlString def (pd p)
	writeFile ("posts/" ++ (filename p) ++ ".html") html 

postsToHtml :: [Post] -> Html
postsToHtml xs = do
  ul ! A.id "blog-posts" $
    forM_ xs h
  where
    h s = li ! class_ "blog-post" $ do
            a ! class_ "post-link" ! href (stringValue ("posts/"++filename s++".html")) $ toHtml (postTitle s)
            H.div ! class_ "post-date" $ toHtml (postDate s)

injectPosts :: String -> Html -> Either String String 
injectPosts layout ul = case splitFile of
                        [beginning, end] -> Right (renderTags (beginning ++ parseTags (show ul) ++ end))
                        _ ->  Left "Broken layout file"
  where
    splitFile = splitOn [(TagOpen "ul" [("id","blog-posts")]), (TagClose "ul")] (parseTags layout)

instance Show Html where
  show = renderHtml