Drop system-filepath
This commit is contained in:
parent
ae555aa6f0
commit
48a3bdeadb
@ -1,3 +1,7 @@
|
|||||||
|
## 1.5.0
|
||||||
|
|
||||||
|
* Drop system-filepath
|
||||||
|
|
||||||
## 1.4.0.3
|
## 1.4.0.3
|
||||||
|
|
||||||
Fix bug when `StaticRoute` constructor is not imported.
|
Fix bug when `StaticRoute` constructor is not imported.
|
||||||
|
|||||||
@ -11,7 +11,6 @@ module Yesod.EmbeddedStatic.Css.AbsoluteUrl (
|
|||||||
, absCssUrlsProd
|
, absCssUrlsProd
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Prelude hiding (FilePath)
|
|
||||||
import Yesod.EmbeddedStatic.Generators
|
import Yesod.EmbeddedStatic.Generators
|
||||||
import Yesod.EmbeddedStatic.Types
|
import Yesod.EmbeddedStatic.Types
|
||||||
|
|
||||||
@ -22,7 +21,7 @@ import qualified Data.Text.IO as T
|
|||||||
import qualified Data.Text.Lazy.Encoding as TL
|
import qualified Data.Text.Lazy.Encoding as TL
|
||||||
import Control.Monad ((>=>))
|
import Control.Monad ((>=>))
|
||||||
import Data.Maybe (fromMaybe)
|
import Data.Maybe (fromMaybe)
|
||||||
import Filesystem.Path.CurrentOS ((</>), collapse, FilePath, fromText, toText, encodeString, decodeString)
|
import System.FilePath ((</>))
|
||||||
|
|
||||||
import Yesod.EmbeddedStatic.Css.Util
|
import Yesod.EmbeddedStatic.Css.Util
|
||||||
|
|
||||||
@ -35,7 +34,7 @@ absCssUrlsFileProd :: FilePath -- ^ Anchor relative urls to here
|
|||||||
-> FilePath
|
-> FilePath
|
||||||
-> IO BL.ByteString
|
-> IO BL.ByteString
|
||||||
absCssUrlsFileProd dir file = do
|
absCssUrlsFileProd dir file = do
|
||||||
contents <- T.readFile (encodeString file)
|
contents <- T.readFile file
|
||||||
return $ TL.encodeUtf8 $ absCssUrlsProd dir contents
|
return $ TL.encodeUtf8 $ absCssUrlsProd dir contents
|
||||||
|
|
||||||
absCssUrlsProd :: FilePath -- ^ Anchor relative urls to here
|
absCssUrlsProd :: FilePath -- ^ Anchor relative urls to here
|
||||||
@ -47,14 +46,14 @@ absCssUrlsProd dir contents =
|
|||||||
where
|
where
|
||||||
toAbsoluteUrl (UrlReference rel) = T.concat
|
toAbsoluteUrl (UrlReference rel) = T.concat
|
||||||
[ "url('/"
|
[ "url('/"
|
||||||
, (either id id $ toText $ collapse $ dir </> fromText rel)
|
, (T.pack $ dir </> T.unpack rel)
|
||||||
, "')"
|
, "')"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
-- | Equivalent to passing the same string twice to 'absoluteUrlsAt'.
|
-- | Equivalent to passing the same string twice to 'absoluteUrlsAt'.
|
||||||
absoluteUrls :: FilePath -> Generator
|
absoluteUrls :: FilePath -> Generator
|
||||||
absoluteUrls f = absoluteUrlsAt (encodeString f) f
|
absoluteUrls f = absoluteUrlsAt f f
|
||||||
|
|
||||||
-- | Equivalent to passing @return@ to 'absoluteUrlsWith'.
|
-- | Equivalent to passing @return@ to 'absoluteUrlsWith'.
|
||||||
absoluteUrlsAt :: Location -> FilePath -> Generator
|
absoluteUrlsAt :: Location -> FilePath -> Generator
|
||||||
@ -74,7 +73,7 @@ absoluteUrlsWith ::
|
|||||||
-> Maybe (CssGeneration -> IO BL.ByteString) -- ^ Another filter function run after this one (for example @return . yuiCSS . cssContent@) or other CSS filter that runs after this filter.
|
-> Maybe (CssGeneration -> IO BL.ByteString) -- ^ Another filter function run after this one (for example @return . yuiCSS . cssContent@) or other CSS filter that runs after this filter.
|
||||||
-> Generator
|
-> Generator
|
||||||
absoluteUrlsWith loc file mpostFilter =
|
absoluteUrlsWith loc file mpostFilter =
|
||||||
return [ cssProductionFilter (absCssUrlsFileProd (decodeString loc) >=> postFilter . mkCssGeneration loc file) loc file
|
return [ cssProductionFilter (absCssUrlsFileProd loc >=> postFilter . mkCssGeneration loc file) loc file
|
||||||
]
|
]
|
||||||
where
|
where
|
||||||
postFilter = fromMaybe (return . cssContent) mpostFilter
|
postFilter = fromMaybe (return . cssContent) mpostFilter
|
||||||
|
|||||||
@ -1,19 +1,18 @@
|
|||||||
{-# LANGUAGE OverloadedStrings, QuasiQuotes, TemplateHaskell, TupleSections, GeneralizedNewtypeDeriving #-}
|
{-# LANGUAGE OverloadedStrings, QuasiQuotes, TemplateHaskell, TupleSections, GeneralizedNewtypeDeriving #-}
|
||||||
module Yesod.EmbeddedStatic.Css.Util where
|
module Yesod.EmbeddedStatic.Css.Util where
|
||||||
|
|
||||||
import Prelude hiding (FilePath)
|
|
||||||
import Control.Applicative
|
import Control.Applicative
|
||||||
import Control.Monad (void, foldM)
|
import Control.Monad (void, foldM)
|
||||||
import Data.Hashable (Hashable)
|
import Data.Hashable (Hashable)
|
||||||
import Data.Monoid
|
import Data.Monoid
|
||||||
import Network.Mime (MimeType, defaultMimeLookup)
|
import Network.Mime (MimeType, defaultMimeLookup)
|
||||||
import Filesystem.Path.CurrentOS (FilePath, directory, (</>), dropExtension, filename, toText, decodeString, encodeString, fromText, absolute)
|
|
||||||
import Text.CSS.Parse (parseBlocks)
|
import Text.CSS.Parse (parseBlocks)
|
||||||
import Language.Haskell.TH (litE, stringL)
|
import Language.Haskell.TH (litE, stringL)
|
||||||
import Text.CSS.Render (renderBlocks)
|
import Text.CSS.Render (renderBlocks)
|
||||||
import Yesod.EmbeddedStatic.Types
|
import Yesod.EmbeddedStatic.Types
|
||||||
import Yesod.EmbeddedStatic (pathToName)
|
import Yesod.EmbeddedStatic (pathToName)
|
||||||
import Data.Default (def)
|
import Data.Default (def)
|
||||||
|
import System.FilePath ((</>), takeFileName, takeDirectory, dropExtension)
|
||||||
|
|
||||||
import qualified Blaze.ByteString.Builder as B
|
import qualified Blaze.ByteString.Builder as B
|
||||||
import qualified Blaze.ByteString.Builder.Char.Utf8 as B
|
import qualified Blaze.ByteString.Builder.Char.Utf8 as B
|
||||||
@ -63,7 +62,7 @@ parseBackgroundImage :: T.Text -> T.Text -> EithUrl
|
|||||||
parseBackgroundImage n v = (n, case P.parseOnly parseUrl v of
|
parseBackgroundImage n v = (n, case P.parseOnly parseUrl v of
|
||||||
Left _ -> Left v -- Can't parse url
|
Left _ -> Left v -- Can't parse url
|
||||||
Right url -> -- maybe we should find a uri parser
|
Right url -> -- maybe we should find a uri parser
|
||||||
if any (`T.isPrefixOf` url) ["http://", "https://", "//"] || absolute (fromText url)
|
if any (`T.isPrefixOf` url) ["http://", "https://", "/"]
|
||||||
then Left v
|
then Left v
|
||||||
else Right $ UrlReference url)
|
else Right $ UrlReference url)
|
||||||
|
|
||||||
@ -79,9 +78,9 @@ parseCssUrls = parseCssWith checkForUrl
|
|||||||
|
|
||||||
parseCssFileWith :: (T.Text -> T.Text -> EithUrl) -> FilePath -> IO Css
|
parseCssFileWith :: (T.Text -> T.Text -> EithUrl) -> FilePath -> IO Css
|
||||||
parseCssFileWith urlParser fp = do
|
parseCssFileWith urlParser fp = do
|
||||||
mparsed <- parseCssWith urlParser <$> T.readFile (encodeString fp)
|
mparsed <- parseCssWith urlParser <$> T.readFile fp
|
||||||
case mparsed of
|
case mparsed of
|
||||||
Left err -> fail $ "Unable to parse " ++ encodeString fp ++ ": " ++ err
|
Left err -> fail $ "Unable to parse " ++ fp ++ ": " ++ err
|
||||||
Right css -> return css
|
Right css -> return css
|
||||||
|
|
||||||
parseCssFileUrls :: FilePath -> IO Css
|
parseCssFileUrls :: FilePath -> IO Css
|
||||||
@ -101,7 +100,7 @@ loadImages dir css loadImage = foldM load M.empty $ concat [map snd block | (_,b
|
|||||||
load imap (Left _) = return imap
|
load imap (Left _) = return imap
|
||||||
load imap (Right f) | f `M.member` imap = return imap
|
load imap (Right f) | f `M.member` imap = return imap
|
||||||
load imap (Right f@(UrlReference path)) = do
|
load imap (Right f@(UrlReference path)) = do
|
||||||
img <- loadImage (dir </> fromText path)
|
img <- loadImage (dir </> T.unpack path)
|
||||||
return $ maybe imap (\i -> M.insert f i imap) img
|
return $ maybe imap (\i -> M.insert f i imap) img
|
||||||
|
|
||||||
|
|
||||||
@ -129,14 +128,14 @@ cssProductionFilter prodFilter loc file =
|
|||||||
, ebLocation = loc
|
, ebLocation = loc
|
||||||
, ebMimeType = "text/css"
|
, ebMimeType = "text/css"
|
||||||
, ebProductionContent = prodFilter file
|
, ebProductionContent = prodFilter file
|
||||||
, ebDevelReload = [| develPassThrough $(litE (stringL loc)) $(litE (stringL $ encodeString file)) |]
|
, ebDevelReload = [| develPassThrough $(litE (stringL loc)) $(litE (stringL file)) |]
|
||||||
, ebDevelExtraFiles = Nothing
|
, ebDevelExtraFiles = Nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
cssProductionImageFilter :: (FilePath -> IO BL.ByteString) -> Location -> FilePath -> Entry
|
cssProductionImageFilter :: (FilePath -> IO BL.ByteString) -> Location -> FilePath -> Entry
|
||||||
cssProductionImageFilter prodFilter loc file =
|
cssProductionImageFilter prodFilter loc file =
|
||||||
(cssProductionFilter prodFilter loc file)
|
(cssProductionFilter prodFilter loc file)
|
||||||
{ ebDevelReload = [| develBgImgB64 $(litE (stringL loc)) $(litE (stringL $ encodeString file)) |]
|
{ ebDevelReload = [| develBgImgB64 $(litE (stringL loc)) $(litE (stringL file)) |]
|
||||||
, ebDevelExtraFiles = Just [| develExtraFiles $(litE (stringL loc)) |]
|
, ebDevelExtraFiles = Just [| develExtraFiles $(litE (stringL loc)) |]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,8 +157,8 @@ parseBackground loc file = do
|
|||||||
url <- PBL.takeWhile (/= 39) -- single quote
|
url <- PBL.takeWhile (/= 39) -- single quote
|
||||||
void $ PBL.string "')"
|
void $ PBL.string "')"
|
||||||
|
|
||||||
let b64 = B64.encode $ T.encodeUtf8 (either id id $ toText (directory file)) <> url
|
let b64 = B64.encode $ T.encodeUtf8 (T.pack $ takeDirectory file) <> url
|
||||||
newUrl = B.fromString (encodeString $ filename $ decodeString loc) <> B.fromString "/" <> B.fromByteString b64
|
newUrl = B.fromString (takeFileName loc) <> B.fromString "/" <> B.fromByteString b64
|
||||||
|
|
||||||
return $ B.fromByteString "background-image"
|
return $ B.fromByteString "background-image"
|
||||||
<> B.fromByteString s1
|
<> B.fromByteString s1
|
||||||
@ -175,12 +174,12 @@ parseDev loc file b = do
|
|||||||
(PBL.endOfInput *> (pure $! b <> b')) <|> (parseDev loc file $! b <> b')
|
(PBL.endOfInput *> (pure $! b <> b')) <|> (parseDev loc file $! b <> b')
|
||||||
|
|
||||||
develPassThrough :: Location -> FilePath -> IO BL.ByteString
|
develPassThrough :: Location -> FilePath -> IO BL.ByteString
|
||||||
develPassThrough _ = BL.readFile . encodeString
|
develPassThrough _ = BL.readFile
|
||||||
|
|
||||||
-- | Create the CSS during development
|
-- | Create the CSS during development
|
||||||
develBgImgB64 :: Location -> FilePath -> IO BL.ByteString
|
develBgImgB64 :: Location -> FilePath -> IO BL.ByteString
|
||||||
develBgImgB64 loc file = do
|
develBgImgB64 loc file = do
|
||||||
ct <- BL.readFile $ encodeString file
|
ct <- BL.readFile file
|
||||||
case PBL.eitherResult $ PBL.parse (parseDev loc file mempty) ct of
|
case PBL.eitherResult $ PBL.parse (parseDev loc file mempty) ct of
|
||||||
Left err -> error err
|
Left err -> error err
|
||||||
Right b -> return $ B.toLazyByteString b
|
Right b -> return $ B.toLazyByteString b
|
||||||
@ -190,7 +189,7 @@ develExtraFiles :: Location -> [T.Text] -> IO (Maybe (MimeType, BL.ByteString))
|
|||||||
develExtraFiles loc parts =
|
develExtraFiles loc parts =
|
||||||
case reverse parts of
|
case reverse parts of
|
||||||
(file:dir) | T.pack loc == T.intercalate "/" (reverse dir) -> do
|
(file:dir) | T.pack loc == T.intercalate "/" (reverse dir) -> do
|
||||||
let file' = T.decodeUtf8 $ B64.decodeLenient $ T.encodeUtf8 $ either id id $ toText $ dropExtension $ fromText file
|
let file' = T.decodeUtf8 $ B64.decodeLenient $ T.encodeUtf8 $ T.pack $ dropExtension $ T.unpack file
|
||||||
ct <- BL.readFile $ T.unpack file'
|
ct <- BL.readFile $ T.unpack file'
|
||||||
return $ Just (defaultMimeLookup file', ct)
|
return $ Just (defaultMimeLookup file', ct)
|
||||||
_ -> return Nothing
|
_ -> return Nothing
|
||||||
|
|||||||
@ -60,8 +60,6 @@ module Yesod.Static
|
|||||||
#endif
|
#endif
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Prelude hiding (FilePath)
|
|
||||||
import qualified Prelude
|
|
||||||
import System.Directory
|
import System.Directory
|
||||||
import Control.Monad
|
import Control.Monad
|
||||||
import Data.FileEmbed (embedDir)
|
import Data.FileEmbed (embedDir)
|
||||||
@ -96,9 +94,9 @@ import Data.Conduit.List (sourceList, consume)
|
|||||||
import Data.Conduit.Binary (sourceFile)
|
import Data.Conduit.Binary (sourceFile)
|
||||||
import qualified Data.Conduit.Text as CT
|
import qualified Data.Conduit.Text as CT
|
||||||
import Data.Functor.Identity (runIdentity)
|
import Data.Functor.Identity (runIdentity)
|
||||||
import qualified Filesystem.Path.CurrentOS as F
|
import System.FilePath ((</>), (<.>), FilePath, takeDirectory)
|
||||||
import Filesystem.Path.CurrentOS ((</>), (<.>), FilePath)
|
import qualified System.FilePath as F
|
||||||
import Filesystem (createTree)
|
import System.Directory (createDirectoryIfMissing)
|
||||||
import qualified Data.Text.Lazy as TL
|
import qualified Data.Text.Lazy as TL
|
||||||
import qualified Data.Text.Lazy.Encoding as TLE
|
import qualified Data.Text.Lazy.Encoding as TLE
|
||||||
import Data.Default
|
import Data.Default
|
||||||
@ -123,18 +121,18 @@ type StaticRoute = Route Static
|
|||||||
-- Does not have index files or directory listings. The static
|
-- Does not have index files or directory listings. The static
|
||||||
-- files' contents /must not/ change, however new files can be
|
-- files' contents /must not/ change, however new files can be
|
||||||
-- added.
|
-- added.
|
||||||
static :: Prelude.FilePath -> IO Static
|
static :: FilePath -> IO Static
|
||||||
static dir = do
|
static dir = do
|
||||||
hashLookup <- cachedETagLookup dir
|
hashLookup <- cachedETagLookup dir
|
||||||
return $ Static $ webAppSettingsWithLookup (F.decodeString dir) hashLookup
|
return $ Static $ webAppSettingsWithLookup dir hashLookup
|
||||||
|
|
||||||
-- | Same as 'static', but does not assumes that the files do not
|
-- | Same as 'static', but does not assumes that the files do not
|
||||||
-- change and checks their modification time whenever a request
|
-- change and checks their modification time whenever a request
|
||||||
-- is made.
|
-- is made.
|
||||||
staticDevel :: Prelude.FilePath -> IO Static
|
staticDevel :: FilePath -> IO Static
|
||||||
staticDevel dir = do
|
staticDevel dir = do
|
||||||
hashLookup <- cachedETagLookupDevel dir
|
hashLookup <- cachedETagLookupDevel dir
|
||||||
return $ Static $ webAppSettingsWithLookup (F.decodeString dir) hashLookup
|
return $ Static $ webAppSettingsWithLookup dir hashLookup
|
||||||
|
|
||||||
-- | Produce a 'Static' based on embedding all of the static files' contents in the
|
-- | Produce a 'Static' based on embedding all of the static files' contents in the
|
||||||
-- executable at compile time.
|
-- executable at compile time.
|
||||||
@ -148,7 +146,7 @@ staticDevel dir = do
|
|||||||
-- directory itself. With embedded static, that will not work.
|
-- directory itself. With embedded static, that will not work.
|
||||||
-- You can easily change @addStaticContent@ to @\_ _ _ -> return Nothing@ as a workaround.
|
-- You can easily change @addStaticContent@ to @\_ _ _ -> return Nothing@ as a workaround.
|
||||||
-- This will cause yesod to embed those assets into the generated HTML file itself.
|
-- This will cause yesod to embed those assets into the generated HTML file itself.
|
||||||
embed :: Prelude.FilePath -> Q Exp
|
embed :: FilePath -> Q Exp
|
||||||
embed fp = [|Static (embeddedSettings $(embedDir fp))|]
|
embed fp = [|Static (embeddedSettings $(embedDir fp))|]
|
||||||
|
|
||||||
instance RenderRoute Static where
|
instance RenderRoute Static where
|
||||||
@ -178,14 +176,14 @@ instance YesodSubDispatch Static m where
|
|||||||
where
|
where
|
||||||
Static set = ysreGetSub $ yreSite $ ysreParentEnv
|
Static set = ysreGetSub $ yreSite $ ysreParentEnv
|
||||||
|
|
||||||
notHidden :: Prelude.FilePath -> Bool
|
notHidden :: FilePath -> Bool
|
||||||
notHidden "tmp" = False
|
notHidden "tmp" = False
|
||||||
notHidden s =
|
notHidden s =
|
||||||
case s of
|
case s of
|
||||||
'.':_ -> False
|
'.':_ -> False
|
||||||
_ -> True
|
_ -> True
|
||||||
|
|
||||||
getFileListPieces :: Prelude.FilePath -> IO [[String]]
|
getFileListPieces :: FilePath -> IO [[String]]
|
||||||
getFileListPieces = flip evalStateT M.empty . flip go id
|
getFileListPieces = flip evalStateT M.empty . flip go id
|
||||||
where
|
where
|
||||||
go :: String
|
go :: String
|
||||||
@ -232,7 +230,7 @@ getFileListPieces = flip evalStateT M.empty . flip go id
|
|||||||
-- Note that dots (@.@), dashes (@-@) and slashes (@\/@) are
|
-- Note that dots (@.@), dashes (@-@) and slashes (@\/@) are
|
||||||
-- replaced by underscores (@\_@) to create valid Haskell
|
-- replaced by underscores (@\_@) to create valid Haskell
|
||||||
-- identifiers.
|
-- identifiers.
|
||||||
staticFiles :: Prelude.FilePath -> Q [Dec]
|
staticFiles :: FilePath -> Q [Dec]
|
||||||
staticFiles dir = mkStaticFiles dir
|
staticFiles dir = mkStaticFiles dir
|
||||||
|
|
||||||
-- | Same as 'staticFiles', but takes an explicit list of files
|
-- | Same as 'staticFiles', but takes an explicit list of files
|
||||||
@ -245,11 +243,11 @@ staticFiles dir = mkStaticFiles dir
|
|||||||
--
|
--
|
||||||
-- This can be useful when you have a very large number of static
|
-- This can be useful when you have a very large number of static
|
||||||
-- files, but only need to refer to a few of them from Haskell.
|
-- files, but only need to refer to a few of them from Haskell.
|
||||||
staticFilesList :: Prelude.FilePath -> [Prelude.FilePath] -> Q [Dec]
|
staticFilesList :: FilePath -> [FilePath] -> Q [Dec]
|
||||||
staticFilesList dir fs =
|
staticFilesList dir fs =
|
||||||
mkStaticFilesList dir (map split fs) True
|
mkStaticFilesList dir (map split fs) True
|
||||||
where
|
where
|
||||||
split :: Prelude.FilePath -> [String]
|
split :: FilePath -> [String]
|
||||||
split [] = []
|
split [] = []
|
||||||
split x =
|
split x =
|
||||||
let (a, b) = break (== '/') x
|
let (a, b) = break (== '/') x
|
||||||
@ -265,38 +263,38 @@ staticFilesList dir fs =
|
|||||||
-- on the future. Browsers still will be able to cache the
|
-- on the future. Browsers still will be able to cache the
|
||||||
-- contents, however they'll need send a request to the server to
|
-- contents, however they'll need send a request to the server to
|
||||||
-- see if their copy is up-to-date.
|
-- see if their copy is up-to-date.
|
||||||
publicFiles :: Prelude.FilePath -> Q [Dec]
|
publicFiles :: FilePath -> Q [Dec]
|
||||||
publicFiles dir = mkStaticFiles' dir False
|
publicFiles dir = mkStaticFiles' dir False
|
||||||
|
|
||||||
|
|
||||||
mkHashMap :: Prelude.FilePath -> IO (M.Map F.FilePath S8.ByteString)
|
mkHashMap :: FilePath -> IO (M.Map FilePath S8.ByteString)
|
||||||
mkHashMap dir = do
|
mkHashMap dir = do
|
||||||
fs <- getFileListPieces dir
|
fs <- getFileListPieces dir
|
||||||
hashAlist fs >>= return . M.fromList
|
hashAlist fs >>= return . M.fromList
|
||||||
where
|
where
|
||||||
hashAlist :: [[String]] -> IO [(F.FilePath, S8.ByteString)]
|
hashAlist :: [[String]] -> IO [(FilePath, S8.ByteString)]
|
||||||
hashAlist fs = mapM hashPair fs
|
hashAlist fs = mapM hashPair fs
|
||||||
where
|
where
|
||||||
hashPair :: [String] -> IO (F.FilePath, S8.ByteString)
|
hashPair :: [String] -> IO (FilePath, S8.ByteString)
|
||||||
hashPair pieces = do let file = pathFromRawPieces dir pieces
|
hashPair pieces = do let file = pathFromRawPieces dir pieces
|
||||||
h <- base64md5File file
|
h <- base64md5File file
|
||||||
return (F.decodeString file, S8.pack h)
|
return (file, S8.pack h)
|
||||||
|
|
||||||
pathFromRawPieces :: Prelude.FilePath -> [String] -> Prelude.FilePath
|
pathFromRawPieces :: FilePath -> [String] -> FilePath
|
||||||
pathFromRawPieces =
|
pathFromRawPieces =
|
||||||
foldl' append
|
foldl' append
|
||||||
where
|
where
|
||||||
append a b = a ++ '/' : b
|
append a b = a ++ '/' : b
|
||||||
|
|
||||||
cachedETagLookupDevel :: Prelude.FilePath -> IO ETagLookup
|
cachedETagLookupDevel :: FilePath -> IO ETagLookup
|
||||||
cachedETagLookupDevel dir = do
|
cachedETagLookupDevel dir = do
|
||||||
etags <- mkHashMap dir
|
etags <- mkHashMap dir
|
||||||
mtimeVar <- newIORef (M.empty :: M.Map F.FilePath EpochTime)
|
mtimeVar <- newIORef (M.empty :: M.Map FilePath EpochTime)
|
||||||
return $ \f ->
|
return $ \f ->
|
||||||
case M.lookup f etags of
|
case M.lookup f etags of
|
||||||
Nothing -> return Nothing
|
Nothing -> return Nothing
|
||||||
Just checksum -> do
|
Just checksum -> do
|
||||||
fs <- getFileStatus $ F.encodeString f
|
fs <- getFileStatus f
|
||||||
let newt = modificationTime fs
|
let newt = modificationTime fs
|
||||||
mtimes <- readIORef mtimeVar
|
mtimes <- readIORef mtimeVar
|
||||||
oldt <- case M.lookup f mtimes of
|
oldt <- case M.lookup f mtimes of
|
||||||
@ -305,15 +303,15 @@ cachedETagLookupDevel dir = do
|
|||||||
return $ if newt /= oldt then Nothing else Just checksum
|
return $ if newt /= oldt then Nothing else Just checksum
|
||||||
|
|
||||||
|
|
||||||
cachedETagLookup :: Prelude.FilePath -> IO ETagLookup
|
cachedETagLookup :: FilePath -> IO ETagLookup
|
||||||
cachedETagLookup dir = do
|
cachedETagLookup dir = do
|
||||||
etags <- mkHashMap dir
|
etags <- mkHashMap dir
|
||||||
return $ (\f -> return $ M.lookup f etags)
|
return $ (\f -> return $ M.lookup f etags)
|
||||||
|
|
||||||
mkStaticFiles :: Prelude.FilePath -> Q [Dec]
|
mkStaticFiles :: FilePath -> Q [Dec]
|
||||||
mkStaticFiles fp = mkStaticFiles' fp True
|
mkStaticFiles fp = mkStaticFiles' fp True
|
||||||
|
|
||||||
mkStaticFiles' :: Prelude.FilePath -- ^ static directory
|
mkStaticFiles' :: FilePath -- ^ static directory
|
||||||
-> Bool -- ^ append checksum query parameter
|
-> Bool -- ^ append checksum query parameter
|
||||||
-> Q [Dec]
|
-> Q [Dec]
|
||||||
mkStaticFiles' fp makeHash = do
|
mkStaticFiles' fp makeHash = do
|
||||||
@ -321,7 +319,7 @@ mkStaticFiles' fp makeHash = do
|
|||||||
mkStaticFilesList fp fs makeHash
|
mkStaticFilesList fp fs makeHash
|
||||||
|
|
||||||
mkStaticFilesList
|
mkStaticFilesList
|
||||||
:: Prelude.FilePath -- ^ static directory
|
:: FilePath -- ^ static directory
|
||||||
-> [[String]] -- ^ list of files to create identifiers for
|
-> [[String]] -- ^ list of files to create identifiers for
|
||||||
-> Bool -- ^ append checksum query parameter
|
-> Bool -- ^ append checksum query parameter
|
||||||
-> Q [Dec]
|
-> Q [Dec]
|
||||||
@ -355,7 +353,7 @@ mkStaticFilesList fp fs makeHash = do
|
|||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
base64md5File :: Prelude.FilePath -> IO String
|
base64md5File :: FilePath -> IO String
|
||||||
base64md5File = fmap (base64 . encode) . hashFile
|
base64md5File = fmap (base64 . encode) . hashFile
|
||||||
where encode d = Byteable.toBytes (d :: Digest MD5)
|
where encode d = Byteable.toBytes (d :: Digest MD5)
|
||||||
|
|
||||||
@ -402,18 +400,18 @@ combineStatics' combineType CombineSettings {..} routes = do
|
|||||||
ltext <- qRunIO $ preProcess $ TL.fromChunks texts
|
ltext <- qRunIO $ preProcess $ TL.fromChunks texts
|
||||||
bs <- qRunIO $ postProcess fps $ TLE.encodeUtf8 ltext
|
bs <- qRunIO $ postProcess fps $ TLE.encodeUtf8 ltext
|
||||||
let hash' = base64md5 bs
|
let hash' = base64md5 bs
|
||||||
suffix = csCombinedFolder </> F.decodeString hash' <.> extension
|
suffix = csCombinedFolder </> hash' <.> extension
|
||||||
fp = csStaticDir </> suffix
|
fp = csStaticDir </> suffix
|
||||||
qRunIO $ do
|
qRunIO $ do
|
||||||
createTree $ F.directory fp
|
createDirectoryIfMissing True $ takeDirectory fp
|
||||||
L.writeFile (F.encodeString fp) bs
|
L.writeFile fp bs
|
||||||
let pieces = map T.unpack $ T.splitOn "/" $ either id id $ F.toText suffix
|
let pieces = map T.unpack $ T.splitOn "/" $ T.pack suffix
|
||||||
[|StaticRoute (map pack pieces) []|]
|
[|StaticRoute (map pack pieces) []|]
|
||||||
where
|
where
|
||||||
fps :: [F.FilePath]
|
fps :: [FilePath]
|
||||||
fps = map toFP routes
|
fps = map toFP routes
|
||||||
toFP (StaticRoute pieces _) = csStaticDir </> F.concat (map F.fromText pieces)
|
toFP (StaticRoute pieces _) = csStaticDir </> F.joinPath (map T.unpack pieces)
|
||||||
readUTFFile fp = sourceFile (F.encodeString fp) =$= CT.decode CT.utf8
|
readUTFFile fp = sourceFile fp =$= CT.decode CT.utf8
|
||||||
postProcess =
|
postProcess =
|
||||||
case combineType of
|
case combineType of
|
||||||
JS -> csJsPostProcess
|
JS -> csJsPostProcess
|
||||||
@ -435,7 +433,7 @@ combineStatics' combineType CombineSettings {..} routes = do
|
|||||||
--
|
--
|
||||||
-- Since 1.2.0
|
-- Since 1.2.0
|
||||||
data CombineSettings = CombineSettings
|
data CombineSettings = CombineSettings
|
||||||
{ csStaticDir :: F.FilePath
|
{ csStaticDir :: FilePath
|
||||||
-- ^ File path containing static files.
|
-- ^ File path containing static files.
|
||||||
--
|
--
|
||||||
-- Default: static
|
-- Default: static
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
name: yesod-static
|
name: yesod-static
|
||||||
version: 1.4.0.4
|
version: 1.5.0
|
||||||
license: MIT
|
license: MIT
|
||||||
license-file: LICENSE
|
license-file: LICENSE
|
||||||
author: Michael Snoyman <michael@snoyman.com>
|
author: Michael Snoyman <michael@snoyman.com>
|
||||||
@ -46,8 +46,6 @@ library
|
|||||||
, conduit-extra
|
, conduit-extra
|
||||||
, cryptohash-conduit >= 0.1
|
, cryptohash-conduit >= 0.1
|
||||||
, cryptohash >= 0.11
|
, cryptohash >= 0.11
|
||||||
, system-filepath >= 0.4.6 && < 0.5
|
|
||||||
, system-fileio >= 0.3
|
|
||||||
, data-default
|
, data-default
|
||||||
, mime-types >= 0.1
|
, mime-types >= 0.1
|
||||||
, hjsmin
|
, hjsmin
|
||||||
@ -104,8 +102,6 @@ test-suite tests
|
|||||||
, conduit
|
, conduit
|
||||||
, cryptohash-conduit
|
, cryptohash-conduit
|
||||||
, cryptohash
|
, cryptohash
|
||||||
, system-filepath
|
|
||||||
, system-fileio
|
|
||||||
, data-default
|
, data-default
|
||||||
, mime-types
|
, mime-types
|
||||||
, hjsmin
|
, hjsmin
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user