module Web.Herringbone.Types where
import Data.Char
import Data.Time.Clock
import Data.Time.Format
import System.Locale
import Data.Text (Text)
import qualified Data.Map as M
import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as BL
import qualified Filesystem.Path.CurrentOS as F
import Filesystem.Path.CurrentOS (FilePath)
import Prelude hiding (FilePath)
class ToLazyByteString a where
toLazyByteString :: a -> BL.ByteString
instance ToLazyByteString String where
toLazyByteString = BL.pack . map (fromIntegral . ord)
instance ToLazyByteString FilePath where
toLazyByteString = toLazyByteString . F.encode
instance ToLazyByteString B.ByteString where
toLazyByteString = BL.fromChunks . (: [])
data AssetError = AssetNotFound
| AssetCompileError CompileError
| AmbiguousSources [FilePath]
deriving (Show, Eq)
type CompileError = B.ByteString
data PP = PP
{ ppExtension :: Text
, ppAction :: B.ByteString -> IO (Either CompileError B.ByteString)
}
instance Show PP where
show pp = "<PP: " ++ show (ppExtension pp) ++ ">"
instance Eq PP where
(PP ext1 _) == (PP ext2 _) = ext1 == ext2
instance Ord PP where
compare (PP ext1 _) (PP ext2 _) = compare ext1 ext2
newtype PPs = PPs { unPPs :: M.Map Text PP }
deriving (Show)
noPPs :: PPs
noPPs = PPs M.empty
supportedBy :: PPs -> Text -> Bool
supportedBy pps = flip M.member (unPPs pps)
supportedExts :: PPs -> [Text]
supportedExts = M.keys . unPPs
insertPP :: PP -> PPs -> PPs
insertPP pp = PPs . M.insert (ppExtension pp) pp . unPPs
lookupPP :: Text -> PPs -> Maybe PP
lookupPP ext = M.lookup ext . unPPs
fromList :: [PP] -> PPs
fromList ppList = insertAllPPs ppList noPPs
insertAllPPs :: [PP] -> PPs -> PPs
insertAllPPs ppList pps = foldr insertPP pps ppList
data Herringbone = Herringbone
{ hbSourceDirs :: [FilePath]
, hbDestDir :: FilePath
, hbPPs :: PPs
}
deriving (Show)
newtype LogicalPath = LogicalPath { fromLogicalPath :: [Text] }
deriving (Show)
makeLogicalPath :: [Text] -> Maybe LogicalPath
makeLogicalPath xs = if safe xs then Just $ LogicalPath xs else Nothing
where
safe = all (not . (==) "..")
unsafeMakeLogicalPath :: [Text] -> LogicalPath
unsafeMakeLogicalPath = LogicalPath
toFilePath :: LogicalPath -> FilePath
toFilePath = F.concat . map F.fromText . fromLogicalPath
data Asset = Asset
{ assetSize :: Integer
, assetSourcePath :: FilePath
, assetFilePath :: FilePath
, assetLogicalPath :: LogicalPath
, assetModifiedTime :: UTCTime
}
instance Show Asset where
show (Asset size sourcePath filePath logicalPath modifiedTime) =
"BundledAsset { " ++
"assetSize = " ++ show size ++ ", " ++
"assetSourcePath = " ++ show sourcePath ++ ", " ++
"assetFilePath = " ++ show filePath ++ ", " ++
"assetLogicalPath = " ++ show logicalPath ++ ", " ++
"assetModifiedTime = " ++ showTime modifiedTime ++ " }"
where
showTime = formatTime defaultTimeLocale (dateTimeFmt defaultTimeLocale)