@@ -39,6 +39,7 @@ module Text.Pandoc.Class ( PandocMonad(..)
39 , PandocIO(..)
39 , PandocIO(..)
40 , PandocPure(..)
40 , PandocPure(..)
41 , PandocExecutionError(..)
41 , PandocExecutionError(..)
43 , runIOorExplode
44 , runIOorExplode
@@ -73,6 +74,7 @@ import qualified System.Environment as IO (lookupEnv)
73import System.FilePath.Glob (match, compile)
74import System.FilePath.Glob (match, compile)
74import System.FilePath ((</>))
75import System.FilePath ((</>))
75import qualified System.FilePath.Glob as IO (glob)
76import qualified System.FilePath.Glob as IO (glob)
77+import qualified System.Directory as IO (getModificationTime)
76import Control.Monad.State hiding (fail)
78import Control.Monad.State hiding (fail)
77import Control.Monad.Reader hiding (fail)
79import Control.Monad.Reader hiding (fail)
78import Control.Monad.Except hiding (fail)
80import Control.Monad.Except hiding (fail)
@@ -80,6 +82,8 @@ import Data.Word (Word8)
80import Data.Typeable
82import Data.Typeable
81import Data.Default
83import Data.Default
82import System.IO.Error
84import System.IO.Error
86+import qualified Data.Map as M
84class (Functor m, Applicative m, Monad m, MonadError PandocExecutionError m) => PandocMonad m where
88class (Functor m, Applicative m, Monad m, MonadError PandocExecutionError m) => PandocMonad m where
85 lookupEnv :: String -> m (Maybe String)
89 lookupEnv :: String -> m (Maybe String)
@@ -105,6 +109,8 @@ class (Functor m, Applicative m, Monad m, MonadError PandocExecutionError m) =>
105 glob :: String -> m [FilePath]
109 glob :: String -> m [FilePath]
106 setMediaBag :: MediaBag -> m ()
110 setMediaBag :: MediaBag -> m ()
107 insertMedia :: FilePath -> Maybe MimeType -> BL.ByteString -> m ()
111 insertMedia :: FilePath -> Maybe MimeType -> BL.ByteString -> m ()
112+ getModificationTime :: FilePath -> m UTCTime
109--Some functions derived from Primitives:
115--Some functions derived from Primitives:
@@ -190,6 +196,11 @@ instance PandocMonad PandocIO where
190 modify $ \st -> st{ioStMediaBag = mb}
196 modify $ \st -> st{ioStMediaBag = mb}
191 insertMedia fp mime bs =
197 insertMedia fp mime bs =
192 modify $ \st -> st{ioStMediaBag = MB.insertMedia fp mime bs (ioStMediaBag st) }
198 modify $ \st -> st{ioStMediaBag = MB.insertMedia fp mime bs (ioStMediaBag st) }
199+ getModificationTime fp = do
200+ eitherMtime <- liftIO (tryIOError $ IO.getModificationTime fp)
202+ Right mtime -> return mtime
203+ Left _ -> throwError $ PandocFileReadError fp
194data PureState = PureState { stStdGen :: StdGen
205data PureState = PureState { stStdGen :: StdGen
195 , stWord8Store :: [Word8] -- should be
206 , stWord8Store :: [Word8] -- should be
@@ -210,15 +221,26 @@ instance Default PureState where
210 , stWarnings = []
221 , stWarnings = []
211 , stUniqStore = [1..]
222 , stUniqStore = [1..]
212 , stMediaBag = mempty
223 , stMediaBag = mempty
227+data FileInfo = FileInfo { infoFileMTime :: UTCTime
228+ , infoFileContents :: B.ByteString
231+newtype FileTree = FileTree {unFileTree :: M.Map FilePath FileInfo}
234+getFileInfo :: FilePath -> FileTree -> Maybe FileInfo
235+getFileInfo fp tree = M.lookup fp $ unFileTree tree
215data PureEnv = PureEnv { envEnv :: [(String, String)]
237data PureEnv = PureEnv { envEnv :: [(String, String)]
216 , envTime :: UTCTime
238 , envTime :: UTCTime
217 , envReferenceDocx :: Archive
239 , envReferenceDocx :: Archive
218 , envReferenceODT :: Archive
240 , envReferenceODT :: Archive
219− , envFiles :: [(FilePath, B.ByteString)]
241+ , envFiles :: FileTree
220− , envUserDataDir :: [(FilePath, B.ByteString)]
242+ , envUserDataDir :: FileTree
221− , envCabalDataDir :: [(FilePath, B.ByteString)]
243+ , envCabalDataDir :: FileTree
222 , envFontFiles :: [FilePath]
244 , envFontFiles :: [FilePath]
@@ -229,9 +251,9 @@ instance Default PureEnv where
229 , envTime = posixSecondsToUTCTime 0
251 , envTime = posixSecondsToUTCTime 0
230 , envReferenceDocx = emptyArchive
252 , envReferenceDocx = emptyArchive
231 , envReferenceODT = emptyArchive
253 , envReferenceODT = emptyArchive
232− , envFiles = []
254+ , envFiles = mempty
233− , envUserDataDir = []
255+ , envUserDataDir = mempty
234− , envCabalDataDir = []
256+ , envCabalDataDir = mempty
235 , envFontFiles = []
257 , envFontFiles = []
@@ -277,7 +299,7 @@ instance PandocMonad PandocPure where
277 _ -> M.fail "uniq store ran out of elements"
299 _ -> M.fail "uniq store ran out of elements"
278 readFileLazy fp = do
300 readFileLazy fp = do
279 fps <- asks envFiles
301 fps <- asks envFiles
280− case lookup fp fps of
302+ case infoFileContents <$> getFileInfo fp fps of
281 Just bs -> return (BL.fromStrict bs)
303 Just bs -> return (BL.fromStrict bs)
282 Nothing -> throwError $ PandocFileReadError fp
304 Nothing -> throwError $ PandocFileReadError fp
283 readDataFile Nothing "reference.docx" = do
305 readDataFile Nothing "reference.docx" = do
@@ -289,13 +311,13 @@ instance PandocMonad PandocPure where
289 BL.toStrict <$> (readFileLazy fname')
311 BL.toStrict <$> (readFileLazy fname')
290 readDataFile (Just userDir) fname = do
312 readDataFile (Just userDir) fname = do
291 userDirFiles <- asks envUserDataDir
313 userDirFiles <- asks envUserDataDir
292− case lookup (userDir </> fname) userDirFiles of
314+ case infoFileContents <$> (getFileInfo (userDir </> fname) userDirFiles) of
293 Just bs -> return bs
315 Just bs -> return bs
294 Nothing -> readDataFile Nothing fname
316 Nothing -> readDataFile Nothing fname
295 fail = M.fail
317 fail = M.fail
296 fetchItem _ fp = do
318 fetchItem _ fp = do
297 fps <- asks envFiles
319 fps <- asks envFiles
298− case lookup fp fps of
320+ case infoFileContents <$> (getFileInfo fp fps) of
299 Just bs -> return (Right (bs, getMimeType fp))
321 Just bs -> return (Right (bs, getMimeType fp))
300 Nothing -> return (Left $ E.toException $ PandocFileReadError fp)
322 Nothing -> return (Left $ E.toException $ PandocFileReadError fp)
@@ -317,3 +339,9 @@ instance PandocMonad PandocPure where
318 insertMedia fp mime bs =
340 insertMedia fp mime bs =
319 modify $ \st -> st{stMediaBag = MB.insertMedia fp mime bs (stMediaBag st) }
341 modify $ \st -> st{stMediaBag = MB.insertMedia fp mime bs (stMediaBag st) }
343+ getModificationTime fp = do
344+ fps <- asks envFiles
345+ case infoFileMTime <$> (getFileInfo fp fps) of
346+ Just tm -> return tm
347+ Nothing -> throwError $ PandocFileReadError fp