stagen-0.2.0: library/Stagen/File.hs
module Stagen.File where
import qualified Data.Text.Lazy as TL
import qualified Data.Text.Lazy.IO as TL
import qualified Text.Parsec as P
import qualified Text.Parsec.String as P
import Data.Text.Conversions (toText)
import Data.Monoid ((<>))
import Control.Monad (when)
import System.FilePath.Find
import Text.Markdown
import Text.Blaze.Html.Renderer.Text (renderHtml)
import Stagen.Opts
import Stagen.Page
import Stagen.Date
fromMarkdown :: Verbose -> FilePath -> FilePath -> IO (FilePath, Page)
fromMarkdown verbose baseUrl mdPath = do
let htmlPath = changeExtension mdPath "html"
page <- readPage baseUrl mdPath
when (verbose == Verbose) (putStrLn htmlPath)
return (htmlPath, page)
eligable :: [FilePath] -> FindClause Bool
eligable ignore = do
isMarkdown <- (== ".md") <$> extension
name <- fileName
let isFileName = and (map (/= name) ignore)
return (isMarkdown && isFileName)
absoluteUrl :: FilePath -> FilePath -> TL.Text
absoluteUrl baseUrl path = TL.fromStrict . toText $ changeExtension (baseUrl <> "/" <> path) "html"
readPage :: FilePath -> FilePath -> IO Page
readPage baseUrl path = do
content <- TL.readFile path
let pageAbsoluteUrl = absoluteUrl baseUrl (drop 2 path)
let pageDate = parseMay datePrefix (baseName path)
let pageTitle = mkTitle content
let pageContent = render content
return Page{..}
mkTitle :: TL.Text -> TL.Text
mkTitle content = TL.filter (not . isMarkdownChar) (TL.takeWhile isNotNewLine content)
where
isMarkdownChar ch = ch == '_' || ch == '*' || ch == '#' || ch == '>'
isNotNewLine ch = ch /= '\n' && ch /= '\r'
changeExtension :: FilePath -> String -> FilePath
changeExtension path newExtension
| hasExt = basename ++ newExtension
| otherwise = path ++ ('.' : newExtension)
where
revPath = reverse path
hasExt = elem '.' (takeWhile (/= '/') revPath)
basename = reverse (dropWhile (/= '.') revPath)
render :: TL.Text -> TL.Text
render = renderHtml . markdown def
parseMay :: P.Parser a -> String -> Maybe a
parseMay p src = case P.parse p "" src of
Left _ -> Nothing
Right x -> Just x
baseName :: FilePath -> FilePath
baseName path = basename
where
revPath = reverse path
revName = takeWhile (/= '/') revPath
basename = reverse (dropWhile (/= '.') revName)