@@ -76,6 +76,8 @@ module Text.Pandoc.Shared (
7676 renderTags',
7777 -- * File handling
7878 inDirectory,
79+ getDefaultReferenceDocx,
80+ getDefaultReferenceODT,
7981 readDataFile,
8082 readDataFileUTF8,
8183 fetchItem,
@@ -119,6 +121,7 @@ import Control.Monad (msum, unless, MonadPlus(..))
119121import Text.Pandoc.Pretty (charWidth)
120122import Text.Pandoc.Compat.Locale (defaultTimeLocale)
121123import Data.Time
124+import Data.Time.Clock.POSIX
122125import System.IO (stderr)
123126import System.IO.Temp
124127import Text.HTML.TagSoup (renderTagsOptions, RenderOptions(..), Tag(..),
@@ -129,7 +132,8 @@ import Text.Pandoc.Compat.Monoid
129132import Data.ByteString.Base64 (decodeLenient)
130133import Data.Sequence (ViewR(..), ViewL(..), viewl, viewr)
131134import qualified Data.Text as T (toUpper, pack, unpack)
132−import Data.ByteString.Lazy (toChunks)
135+import Data.ByteString.Lazy (toChunks, fromChunks)
136+import qualified Data.ByteString.Lazy as BL
133137
134138#ifdef EMBED_DATA_FILES
135139import Text.Pandoc.Data (dataFiles)
@@ -145,6 +149,7 @@ import Network.HTTP.Client.TLS (tlsManagerSettings)
145149import System.Environment (getEnv)
146150import Network.HTTP.Types.Header ( hContentType)
147151import Network (withSocketsDo)
152+import Codec.Archive.Zip
148153#else
149154import Network.URI (parseURI)
150155import Network.HTTP (findHeader, rspBody,
@@ -742,7 +747,73 @@ inDirectory path action = E.bracket
742747 setCurrentDirectory
743748 (const $ setCurrentDirectory path >> action)
744749
750+getDefaultReferenceDocx :: Maybe FilePath -> IO Archive
751+getDefaultReferenceDocx datadir = do
752+ let paths = ["[Content_Types].xml",
753+ "_rels/.rels",
754+ "docProps/app.xml",
755+ "docProps/core.xml",
756+ "word/document.xml",
757+ "word/fontTable.xml",
758+ "word/footnotes.xml",
759+ "word/numbering.xml",
760+ "word/settings.xml",
761+ "word/webSettings.xml",
762+ "word/styles.xml",
763+ "word/_rels/document.xml.rels",
764+ "word/_rels/footnotes.xml.rels",
765+ "word/theme/theme1.xml"]
766+ let toLazy = fromChunks . (:[])
767+ let pathToEntry path = do epochtime <- (floor . utcTimeToPOSIXSeconds) <$>
768+ getCurrentTime
769+ contents <- toLazy <$> readDataFile datadir
770+ ("docx/" ++ path)
771+ return $ toEntry path epochtime contents
772+ mbArchive <- case datadir of
773+ Nothing -> return Nothing
774+ Just d -> do
775+ exists <- doesFileExist (d </> "reference.docx")
776+ if exists
777+ then return (Just (d </> "reference.docx"))
778+ else return Nothing
779+ case mbArchive of
780+ Just arch -> toArchive <$> BL.readFile arch
781+ Nothing -> foldr addEntryToArchive emptyArchive <$>
782+ mapM pathToEntry paths
783+
784+getDefaultReferenceODT :: Maybe FilePath -> IO Archive
785+getDefaultReferenceODT datadir = do
786+ let paths = ["mimetype",
787+ "manifest.rdf",
788+ "styles.xml",
789+ "content.xml",
790+ "meta.xml",
791+ "settings.xml",
792+ "Configurations2/accelerator/current.xml",
793+ "Thumbnails/thumbnail.png",
794+ "META-INF/manifest.xml"]
795+ let pathToEntry path = do epochtime <- floor `fmap` getPOSIXTime
796+ contents <- (fromChunks . (:[])) `fmap`
797+ readDataFile datadir ("odt/" ++ path)
798+ return $ toEntry path epochtime contents
799+ mbArchive <- case datadir of
800+ Nothing -> return Nothing
801+ Just d -> do
802+ exists <- doesFileExist (d </> "reference.odt")
803+ if exists
804+ then return (Just (d </> "reference.odt"))
805+ else return Nothing
806+ case mbArchive of
807+ Just arch -> toArchive <$> BL.readFile arch
808+ Nothing -> foldr addEntryToArchive emptyArchive <$>
809+ mapM pathToEntry paths
810+
811+
745812readDefaultDataFile :: FilePath -> IO BS.ByteString
813+readDefaultDataFile "reference.docx" =
814+ (BS.concat . toChunks . fromArchive) <$> getDefaultReferenceDocx Nothing
815+readDefaultDataFile "reference.odt" =
816+ (BS.concat . toChunks . fromArchive) <$> getDefaultReferenceODT Nothing
746817readDefaultDataFile fname =
747818#ifdef EMBED_DATA_FILES
748819 case lookup (makeCanonical fname) dataFiles of