12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061 |
- {-# LANGUAGE OverloadedStrings #-}
- {-# LANGUAGE TemplateHaskell #-}
- module AppCache where
- import Control.Monad (when)
- import Control.Monad.Trans.Writer
- import Data.Hashable (hashWithSalt)
- import Data.List (intercalate)
- import qualified Data.Set as Set
- import Data.Text (Text)
- import Data.Text (pack)
- import Language.Haskell.TH.Syntax
- import Yesod.Core
- import Yesod.Routes.TH
- newtype AppCache = AppCache { unAppCache :: Text }
- appCache :: [ResourceTree String] -> Q Exp
- appCache trees = do
- piecesSet <- execWriterT $ mapM_ (goTree id) trees
- let body = unlines $ map toPath $ Set.toList piecesSet
- hash = hashWithSalt 0 body
- total = concat
- [ "CACHE MANIFEST\n# Version: "
- , show hash
- , "\n\nCACHE:\n"
- , body
- ]
- [|return (AppCache (pack total))|]
- where
- toPath [] = "/"
- toPath x = concatMap ('/':) x
- goTree :: Monad m
- => ([String] -> [String])
- -> ResourceTree String
- -> WriterT (Set.Set [String]) m ()
- goTree front (ResourceLeaf res) = do
- pieces' <- goPieces (resourceName res) $ resourcePieces res
- when ("CACHE" `elem` resourceAttrs res) $
- tell $ Set.singleton $ front pieces'
- goTree front (ResourceParent name pieces trees) = do
- pieces' <- goPieces name pieces
- mapM_ (goTree $ front . (pieces' ++)) trees
- goPieces :: Monad m => String -> [(CheckOverlap, Piece String)] -> m [String]
- goPieces name =
- mapM (goPiece . snd)
- where
- goPiece (Static s) = return s
- goPiece (Dynamic _) = fail $ concat
- [ "AppCache only applies to fully-static paths, but "
- , name
- , " has dynamic pieces."
- ]
- instance ToContent AppCache where
- toContent = toContent . unAppCache
- instance ToTypedContent AppCache where
- toTypedContent = TypedContent "text/cache-manifest" . toContent
|