module Web.Herringbone.BuildAsset where
import Control.Monad.Reader
import Data.Time
import Filesystem.Path.CurrentOS (FilePath, (</>))
import qualified Filesystem as F
import Prelude hiding (FilePath)
import Web.Herringbone.Types
buildAsset :: Herringbone
-> LogicalPath
-> FilePath
-> [PP]
-> IO (Either CompileError Asset)
buildAsset hb logPath sourcePath pps = do
let destPath = hbDestDir hb </> toFilePath logPath
sourceModifiedTime <- F.getModified sourcePath
compileNeeded <- shouldCompile sourceModifiedTime destPath
result <- if compileNeeded
then compileAsset hb logPath sourcePath destPath pps
else return $ Right ()
either (return . Left)
(\_ -> do size <- F.getSize destPath
return . Right $ Asset
size
sourcePath
destPath
logPath
sourceModifiedTime)
result
shouldCompile :: UTCTime -> FilePath -> IO Bool
shouldCompile sourceModifiedTime destPath = do
exists <- F.isFile destPath
if not exists
then return True
else do
destModifiedTime <- F.getModified destPath
return $ sourceModifiedTime > destModifiedTime
compileAsset :: Herringbone
-> LogicalPath
-> FilePath
-> FilePath
-> [PP]
-> IO (Either CompileError ())
compileAsset hb logPath sourcePath destPath pps = do
sourceData <- F.readFile sourcePath
let computation = chainEither (map ppAction pps) sourceData
let readerData = PPReader
{ ppReaderHb = hb
, ppReaderLogicalPath = logPath
, ppReaderSourcePath = sourcePath
, ppReaderPPs = pps
}
result <- runPPM computation readerData
either (return . Left)
(\resultData -> do F.writeFile destPath resultData
return (Right ()))
result
chainEither :: Monad m => [a -> m (Either b a)] -> a -> m (Either b a)
chainEither fs m = foldl go z fs
where
go = \acc f -> acc >>= either (return . Left) f
z = return (Right m)