Skip to content

Commit b59e8b1

Browse files
committed
staticFileContent like embedFile
1 parent 8e942c0 commit b59e8b1

2 files changed

Lines changed: 42 additions & 1 deletion

File tree

lib/asset/manifest/src-bin/static-th.hs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ main = do
2525
, " Automatically generated module that provides the 'static' TH function"
2626
, " to generate paths to static assets."
2727
, "-}"
28-
, "module " <> moduleName <> " ( static, staticFilePath ) where"
28+
, "module " <> moduleName <> " ( static, staticFilePath, staticFileContent ) where"
2929
, ""
3030
, "import Obelisk.Asset.TH"
3131
, "import Language.Haskell.TH"
@@ -34,9 +34,11 @@ main = do
3434
, "#ifdef OBELISK_ASSET_PASSTHRU"
3535
, "static = staticAssetRaw"
3636
, "staticFilePath = staticAssetFilePathRaw \"static.out\""
37+
, "staticFileContent = staticAssetFileContent \"static.out\""
3738
, "#else"
3839
, "static = staticAssetHashed " <> show root
3940
, "staticFilePath = staticAssetFilePath " <> show root
41+
, "staticFileContent = staticAssetFileContent " <> show root
4042
, "#endif"
4143
]
4244
}

lib/asset/manifest/src/Obelisk/Asset/TH.hs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,17 @@
22
Description:
33
Template Haskell for generating asset paths.
44
-}
5+
6+
{-# LANGUAGE TemplateHaskellQuotes #-}
7+
{-# LANGUAGE CPP #-}
8+
59
module Obelisk.Asset.TH
610
( assetPath
711
, staticAssetRaw
812
, staticAssetHashed
913
, staticAssetFilePath
1014
, staticAssetFilePathRaw
15+
, staticAssetFileContent
1116
) where
1217

1318
import Obelisk.Asset.Gather
@@ -17,6 +22,15 @@ import Language.Haskell.TH
1722
import Language.Haskell.TH.Syntax
1823
import System.Directory
1924
import 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
2236
hashedAssetFilePath :: 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

Comments
 (0)