on master help sign in
Fix encoding errors with unixFilter
97d8187Jasper Van der Jeugt
src/Hakyll/Core/Compiler.hs+16−3
@@ -92,6 +92,7 @@ module Hakyll.Core.Compiler
92 , getRoute
92 , getRoute
93 , getRouteFor
93 , getRouteFor
94 , getResourceString
94 , getResourceString
95+ , getResourceLBS
95 , fromDependency
96 , fromDependency
96 , require_
97 , require_
97 , require
98 , require
@@ -119,6 +120,7 @@ import System.FilePath (takeExtension)
119
120
120import Data.Binary (Binary)
121import Data.Binary (Binary)
121import Data.Typeable (Typeable)
122import Data.Typeable (Typeable)
123+import Data.ByteString.Lazy (ByteString)
122
124
123import Hakyll.Core.Identifier
125import Hakyll.Core.Identifier
124import Hakyll.Core.Identifier.Pattern
126import Hakyll.Core.Identifier.Pattern
@@ -182,14 +184,25 @@ getRouteFor = fromJob $ \identifier -> CompilerM $ do
182-- | Get the resource we are compiling as a string
184-- | Get the resource we are compiling as a string
183--
185--
184getResourceString :: Compiler Resource String
186getResourceString :: Compiler Resource String
187+getResourceString = getResourceWith resourceString
188+
189+-- | Get the resource we are compiling as a lazy bytestring
190+--
191+getResourceLBS :: Compiler Resource ByteString
192+getResourceLBS = getResourceWith resourceLBS
193+
194+-- | Overloadable function for 'getResourceString' and 'getResourceLBS'
195+--
196+getResourceWith :: (ResourceProvider -> Resource -> IO a)
197+ -> Compiler Resource a
185−getResourceString = fromJob $ \resource -> CompilerM $ do
198+getResourceWith reader = fromJob $ \resource -> CompilerM $ do
186 let identifier = unResource resource
199 let identifier = unResource resource
187 provider <- compilerResourceProvider <$> ask
200 provider <- compilerResourceProvider <$> ask
188 if resourceExists provider resource
201 if resourceExists provider resource
189− then liftIO $ resourceString provider resource
202+ then liftIO $ reader provider resource
190 else throwError $ error' identifier
203 else throwError $ error' identifier
191 where
204 where
192− error' id' = "Hakyll.Core.Compiler.getResourceString: resource "
205+ error' id' = "Hakyll.Core.Compiler.getResourceWith: resource "
193 ++ show id' ++ " not found"
206 ++ show id' ++ " not found"
194
207
195-- | Auxiliary: get a dependency
208-- | Auxiliary: get a dependency
src/Hakyll/Core/Resource/Provider.hs+5−5
@@ -36,13 +36,13 @@ import Hakyll.Core.Resource
36--
36--
37data ResourceProvider = ResourceProvider
37data ResourceProvider = ResourceProvider
38 { -- | A list of all resources this provider is able to provide
38 { -- | A list of all resources this provider is able to provide
39− resourceList :: [Resource]
39+ resourceList :: [Resource]
40 , -- | Retrieve a certain resource as string
40 , -- | Retrieve a certain resource as string
41− resourceString :: Resource -> IO String
41+ resourceString :: Resource -> IO String
42 , -- | Retrieve a certain resource as lazy bytestring
42 , -- | Retrieve a certain resource as lazy bytestring
43− resourceLazyByteString :: Resource -> IO LB.ByteString
43+ resourceLBS :: Resource -> IO LB.ByteString
44 , -- | Cache keeping track of modified items
44 , -- | Cache keeping track of modified items
45− resourceModifiedCache :: MVar (Map Resource Bool)
45+ resourceModifiedCache :: MVar (Map Resource Bool)
46 }
46 }
47
47
48-- | Create a resource provider
48-- | Create a resource provider
@@ -61,7 +61,7 @@ resourceExists provider = flip elem $ resourceList provider
61-- | Retrieve a digest for a given resource
61-- | Retrieve a digest for a given resource
62--
62--
63resourceDigest :: ResourceProvider -> Resource -> IO [Word8]
63resourceDigest :: ResourceProvider -> Resource -> IO [Word8]
64−resourceDigest provider = digest MD5 <=< resourceLazyByteString provider
64+resourceDigest provider = digest MD5 <=< resourceLBS provider
65
65
66-- | Check if a resource was modified
66-- | Check if a resource was modified
67--
67--
src/Hakyll/Core/UnixFilter.hs+48−13
@@ -2,14 +2,20 @@
2--
2--
3module Hakyll.Core.UnixFilter
3module Hakyll.Core.UnixFilter
4 ( unixFilter
4 ( unixFilter
5+ , unixFilterLBS
5 ) where
6 ) where
6
7
7import Control.Concurrent (forkIO)
8import Control.Concurrent (forkIO)
8−import System.IO (hPutStr, hClose, hGetContents)
9import System.Posix.Process (executeFile, forkProcess)
9import System.Posix.Process (executeFile, forkProcess)
10import System.Posix.IO ( dupTo, createPipe, stdInput
10import System.Posix.IO ( dupTo, createPipe, stdInput
11 , stdOutput, closeFd, fdToHandle
11 , stdOutput, closeFd, fdToHandle
12 )
12 )
13+import System.IO ( Handle, hPutStr, hClose, hGetContents
14+ , hSetEncoding, localeEncoding
15+ )
16+
17+import Data.ByteString.Lazy (ByteString)
18+import qualified Data.ByteString.Lazy as LB
13
19
14import Hakyll.Core.Compiler
20import Hakyll.Core.Compiler
15
21
@@ -26,25 +32,54 @@ import Hakyll.Core.Compiler
26--
32--
27-- The code is fairly straightforward, given that we use @.scss@ for sass:
33-- The code is fairly straightforward, given that we use @.scss@ for sass:
28--
34--
35+-- > match "style.scss" $ do
29−-- > route "style.scss" $ setExtension "css"
36+-- > route $ setExtension "css"
30−-- > compile "style.scss" $
31−-- > getResourceString >>> unixFilter "sass" ["-s", "--scss"]
37+-- > compile $ getResourceString >>> unixFilter "sass" ["-s", "--scss"]
32−-- > >>> arr compressCss
38+-- > >>> arr compressCss
33--
39--
34unixFilter :: String -- ^ Program name
40unixFilter :: String -- ^ Program name
35 -> [String] -- ^ Program args
41 -> [String] -- ^ Program args
36 -> Compiler String String -- ^ Resulting compiler
42 -> Compiler String String -- ^ Resulting compiler
43+unixFilter = unixFilterWith writer reader
44+ where
45+ writer handle input = do
46+ hSetEncoding handle localeEncoding
47+ hPutStr handle input
48+ reader handle = do
49+ hSetEncoding handle localeEncoding
50+ hGetContents handle
51+
52+-- | Variant of 'unixFilter' that should be used for binary files
53+--
54+-- > match "music.wav" $ do
55+-- > route $ setExtension "ogg"
56+-- > compile $ getResourceLBS >>> unixFilter "oggenc" ["-"]
57+--
58+unixFilterLBS :: String -- ^ Program name
59+ -> [String] -- ^ Program args
60+ -> Compiler ByteString ByteString -- ^ Resulting compiler
61+unixFilterLBS = unixFilterWith LB.hPutStr LB.hGetContents
62+
63+-- | Overloaded compiler
64+--
65+unixFilterWith :: (Handle -> i -> IO ()) -- ^ Writer
66+ -> (Handle -> IO o) -- ^ Reader
67+ -> String -- ^ Program name
68+ -> [String] -- ^ Program args
69+ -> Compiler i o -- ^ Resulting compiler
37−unixFilter programName args =
70+unixFilterWith writer reader programName args =
38 timedCompiler ("Executing external program " ++ programName) $
71 timedCompiler ("Executing external program " ++ programName) $
39− unsafeCompiler $ \input -> unixFilterIO programName args input
72+ unsafeCompiler $ unixFilterIO writer reader programName args
40
73
41-- | Internally used function
74-- | Internally used function
42--
75--
43−unixFilterIO :: String
76+unixFilterIO :: (Handle -> i -> IO ())
44− -> [String]
77+ -> (Handle -> IO o)
45 -> String
78 -> String
46− -> IO String
79+ -> [String]
80+ -> i
81+ -> IO o
47−unixFilterIO programName args input = do
82+unixFilterIO writer reader programName args input = do
48 -- Create pipes
83 -- Create pipes
49 (stdinRead, stdinWrite) <- createPipe
84 (stdinRead, stdinWrite) <- createPipe
50 (stdoutRead, stdoutWrite) <- createPipe
85 (stdoutRead, stdoutWrite) <- createPipe
@@ -68,9 +103,9 @@ unixFilterIO programName args input = do
68 -- Write the input to the child pipe
103 -- Write the input to the child pipe
69 _ <- forkIO $ do
104 _ <- forkIO $ do
70 stdinWriteHandle <- fdToHandle stdinWrite
105 stdinWriteHandle <- fdToHandle stdinWrite
71− hPutStr stdinWriteHandle input
106+ writer stdinWriteHandle input
72 hClose stdinWriteHandle
107 hClose stdinWriteHandle
73
108
74 -- Receive the output from the child
109 -- Receive the output from the child
75 stdoutReadHandle <- fdToHandle stdoutRead
110 stdoutReadHandle <- fdToHandle stdoutRead
76− hGetContents stdoutReadHandle
111+ reader stdoutReadHandle
src/Hakyll/Core/Writable.hs+4
@@ -8,6 +8,7 @@ module Hakyll.Core.Writable
8import Data.Word (Word8)
8import Data.Word (Word8)
9
9
10import qualified Data.ByteString as SB
10import qualified Data.ByteString as SB
11+import qualified Data.ByteString.Lazy as LB
11import Text.Blaze (Html)
12import Text.Blaze (Html)
12import Text.Blaze.Renderer.String (renderHtml)
13import Text.Blaze.Renderer.String (renderHtml)
13
14
@@ -25,6 +26,9 @@ instance Writable [Char] where
25instance Writable SB.ByteString where
26instance Writable SB.ByteString where
26 write p = SB.writeFile p
27 write p = SB.writeFile p
27
28
29+instance Writable LB.ByteString where
30+ write p = LB.writeFile p
31+
28instance Writable [Word8] where
32instance Writable [Word8] where
29 write p = write p . SB.pack
33 write p = write p . SB.pack
30
34