herringbone-embed 0.1.0 → 0.1.1
raw patch · 3 files changed
+53/−86 lines, 3 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Web.Herringbone.Precompile: embedAssets :: IO Herringbone -> Q Exp
- Web.Herringbone.Precompile: precompile :: Herringbone -> IO [(LogicalPath, AssetError)]
+ Web.Herringbone.Embed: embedAssets :: IO Herringbone -> Q Exp
Files
- Web/Herringbone/Embed.hs +51/−0
- Web/Herringbone/Precompile.hs +0/−84
- herringbone-embed.cabal +2/−2
+ Web/Herringbone/Embed.hs view
@@ -0,0 +1,51 @@+{-# LANGUAGE TemplateHaskell #-}+module Web.Herringbone.Embed where++import Control.Monad (forM, (>=>), when)+import Language.Haskell.TH.Syntax (Q, Exp(..), Lit(..), runIO)+import Data.FileEmbed (embedDir)+import Data.ByteString (ByteString)+import qualified Data.ByteString.Char8 as B8+import qualified Filesystem.Path.CurrentOS as F+import qualified Data.Text as T++import Web.Herringbone++-- | Precompile and embed all assets into your source code. Call this function+-- in a Template Haskell splice. Any asset compilation failures will result in+-- a compile error.+--+-- For example:+--+-- > assets :: [(LogicalPath, ByteString)]+-- > assets = $(embedAssets+-- (herringbone+-- (setSourceDir "assets" . setDestDir ".compiled_assets"))+-- )+embedAssets :: IO Herringbone -> Q Exp+embedAssets iohb = do+ hb <- runIO iohb+ errs <- runIO (precompile hb)+ when (not . null $ errs) $+ fail ("the following assets failed to compile:\n" +++ unlines (map show errs))++ SigE expr' _ <- embedDir (F.encodeString $ hbDestDir hb)+ let expr = transformFiles expr'++ type_ <- [t| [(LogicalPath, ByteString)] |]+ return $ SigE expr type_+ where+ transformFiles (ListE tups) =+ let f (TupE [LitE (StringL path), contents]) =+ TupE [logicalPathExp path, contents]+ f _ = error "unexpected Exp in precompileEmbed"+ in ListE $ map f tups+ transformFiles _ = error "unexpected Exp in precompileEmbed"+ logicalPathExp = logicalPathToExp . stringToLogicalPath+ stringToLogicalPath = unsafeMakeLogicalPath . T.splitOn "/" . T.pack+ logicalPathToExp logicalPath =+ AppE+ (VarE 'unsafeMakeLogicalPath)+ (ListE (map (LitE . StringL . T.unpack)+ (fromLogicalPath logicalPath)))
− Web/Herringbone/Precompile.hs
@@ -1,84 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}-module Web.Herringbone.Precompile where--import Language.Haskell.TH.Syntax (Q, Exp(..), Lit(..), runIO)-import Data.FileEmbed (embedDir)-import Data.ByteString (ByteString)-import qualified Data.ByteString.Char8 as B8-import qualified Filesystem.Path.CurrentOS as F-import qualified Data.Text as T-import Control.Monad (forM, (>=>))--import Web.Herringbone-import Web.Herringbone.Internal.GetBuildMapping (getBuildMapping)-import Web.Herringbone.Internal.Types (BuildSpec(..), LogicalPath(..))---- | Precompiles all assets.-precompile :: Herringbone -> IO [(LogicalPath, AssetError)]-precompile hb = do- mapping <- getBuildMapping hb- results <- forM mapping $ \(BuildSpec _ destPath _) -> do- let Just path = toLogicalPath $ destPath- asset <- findAsset hb path- case asset of- Right _ -> return []- Left err -> return [(path, err)]- return $ concat results-- where- toLogicalPath =- toMaybe F.toText >=>- return . T.splitOn "/" >=>- makeLogicalPath - toMaybe f x = case f x of- Right y -> Just y- Left _ -> Nothing---- | Precompile and embed all assets into your source code. Call this function--- in a Template Haskell splice.------ Returns: (Errors, Files) where:------ > type Errors = [(LogicalPath, AssetError)]--- > type Files = [(LogicalPath, ByteString)] ------ The second component is a mapping of filenames to file contents.-embedAssets :: IO Herringbone -> Q Exp-embedAssets iohb = do- hb <- runIO iohb- errs <- runIO (precompile hb)- let errsExp = ListE $ map (\(path, err) ->- TupE [logicalPathToExp path, errToExp err]) errs- SigE filesExp' _ <- embedDir (F.encodeString $ hbDestDir hb)- let filesExp = transformFiles filesExp'- let expr = TupE [errsExp, filesExp]-- type_ <- [t| ([(LogicalPath, AssetError)], [(LogicalPath, ByteString)]) |]- return $ SigE expr type_- where- logicalPathToExp logicalPath =- AppE- (ConE 'LogicalPath)- (ListE (map (LitE . StringL . T.unpack)- (fromLogicalPath logicalPath)))- errToExp e = case e of- AssetNotFound ->- ConE 'AssetNotFound- AssetCompileError err ->- AppE (ConE 'AssetCompileError) $ compileErrToExp err- AmbiguousSources srcs ->- AppE (ConE 'AmbiguousSources) $ sourcesToExp srcs- compileErrToExp err = LitE (StringL (B8.unpack err))- sourcesToExp srcs = ListE $ map filePathToExp srcs- -- Just use a literal because we have an IsString instance- filePathToExp path = LitE (StringL (F.encodeString path))-- transformFiles (ListE tups) = - let f (TupE [LitE (StringL path), contents]) =- TupE [logicalPathExp path, contents]- f _ = error "unexpected Exp in precompileEmbed"- in ListE $ map f tups- transformFiles _ = error "unexpected Exp in precompileEmbed"-- logicalPathExp = logicalPathToExp . stringToLogicalPath- stringToLogicalPath = unsafeMakeLogicalPath . T.splitOn "/" . T.pack
herringbone-embed.cabal view
@@ -1,5 +1,5 @@ name: herringbone-embed-version: 0.1.0+version: 0.1.1 synopsis: Embed preprocessed web assets in your executable with Template Haskell. description: Embed preprocessed web assets in your executable with Template Haskell. license: MIT@@ -11,7 +11,7 @@ cabal-version: >=1.10 library- exposed-modules: Web.Herringbone.Precompile+ exposed-modules: Web.Herringbone.Embed build-depends: base >=4.6 && <5, herringbone, system-filepath,