22Description:
33 Template Haskell for generating asset paths.
44-}
5+
6+ {-# LANGUAGE TemplateHaskellQuotes #-}
7+ {-# LANGUAGE CPP #-}
8+
59module Obelisk.Asset.TH
610 ( assetPath
711 , staticAssetRaw
812 , staticAssetHashed
913 , staticAssetFilePath
1014 , staticAssetFilePathRaw
15+ , staticAssetFileContent
1116 ) where
1217
1318import Obelisk.Asset.Gather
@@ -17,6 +22,15 @@ import Language.Haskell.TH
1722import Language.Haskell.TH.Syntax
1823import System.Directory
1924import System.FilePath.Posix
25+ import System.IO.Unsafe (unsafePerformIO )
26+ import qualified Data.ByteString as BS
27+
28+ #if MIN_VERSION_template_haskell(2, 16, 0)
29+ import qualified Data.ByteString.Internal as BSI
30+ #endif
31+
32+ import qualified Data.ByteString.Char8 as Char8
33+ import Data.ByteString.Unsafe (unsafePackAddressLen )
2034
2135-- | Produces the hashed path of a file
2236hashedAssetFilePath :: FilePath -> FilePath -> Q FilePath
@@ -87,3 +101,28 @@ staticAssetWorker root staticOut fp = do
87101 when (not exists) $
88102 fail $ " The file " <> fp <> " was not found in " <> staticOut
89103 returnQ $ LitE $ StringL $ root </> fp
104+
105+ -- | read the file contents of a static asset at compile time into 'ByteString'
106+ -- like 'embedFile' from package @file-embed@
107+ --
108+ -- > import qualified Data.ByteString
109+ -- >
110+ -- > myFile :: Data.ByteString.ByteString
111+ -- > myFile = $(staticAssetFileContentRaw "dirName/fileName")
112+ staticAssetFileContent :: FilePath -> FilePath -> Q Exp
113+ staticAssetFileContent root fp = do
114+ qAddDependentFile $ root </> fp
115+ bs <- runIO (BS. readFile $ root </> fp)
116+ -- the following is copy-paste from
117+ -- https://hackage.haskell.org/package/file-embed-0.0.15.0/docs/src/Data.FileEmbed.html#bsToExp
118+ -- assuming template-haskell >= 2.8.0
119+ returnQ $ VarE 'unsafePerformIO
120+ `AppE ` (VarE 'unsafePackAddressLen
121+ `AppE ` LitE (IntegerL $ fromIntegral $ Char8. length bs)
122+ #if MIN_VERSION_template_haskell(2, 16, 0)
123+ `AppE ` LitE (bytesPrimL (
124+ let BSI. PS ptr off sz = bs
125+ in mkBytes ptr (fromIntegral off) (fromIntegral sz))))
126+ #else
127+ `AppE ` LitE (StringPrimL $ BS. unpack bs))
128+ #endif
0 commit comments