diff options
Diffstat (limited to 'src/Text/Pandoc/PDF.hs')
-rw-r--r-- | src/Text/Pandoc/PDF.hs | 94 |
1 files changed, 79 insertions, 15 deletions
diff --git a/src/Text/Pandoc/PDF.hs b/src/Text/Pandoc/PDF.hs index f466fcb72..0e533ede8 100644 --- a/src/Text/Pandoc/PDF.hs +++ b/src/Text/Pandoc/PDF.hs @@ -34,6 +34,7 @@ import Data.ByteString.Lazy (ByteString) import qualified Data.ByteString.Lazy as B import qualified Data.ByteString.Lazy.Char8 as BC import qualified Data.ByteString as BS +import Text.Pandoc.Compat.Monoid ((<>)) import System.Exit (ExitCode (..)) import System.FilePath import System.IO (stderr, stdout) @@ -47,7 +48,7 @@ import Data.Maybe (fromMaybe) import qualified Text.Pandoc.UTF8 as UTF8 import Text.Pandoc.Definition import Text.Pandoc.Walk (walkM) -import Text.Pandoc.Shared (fetchItem', warn, withTempDir) +import Text.Pandoc.Shared (fetchItem', warn, withTempDir, inDirectory) import Text.Pandoc.Options (WriterOptions(..)) import Text.Pandoc.MIME (extensionFromMimeType, getMimeType) import Text.Pandoc.Process (pipeProcess) @@ -71,7 +72,9 @@ makePDF program writer opts doc = withTempDir "tex2pdf." $ \tmpdir -> do doc' <- handleImages opts tmpdir doc let source = writer opts doc' args = writerLaTeXArgs opts - tex2pdf' (writerVerbose opts) args tmpdir program source + case program of + "context" -> context2pdf (writerVerbose opts) tmpdir source + _ -> tex2pdf' (writerVerbose opts) args tmpdir program source handleImages :: WriterOptions -> FilePath -- ^ temp dir to store images @@ -83,10 +86,10 @@ handleImage' :: WriterOptions -> FilePath -> Inline -> IO Inline -handleImage' opts tmpdir (Image ils (src,tit)) = do +handleImage' opts tmpdir (Image attr ils (src,tit)) = do exists <- doesFileExist src if exists - then return $ Image ils (src,tit) + then return $ Image attr ils (src,tit) else do res <- fetchItem' (writerMediaBag opts) (writerSourceURL opts) src case res of @@ -96,20 +99,20 @@ handleImage' opts tmpdir (Image ils (src,tit)) = do let basename = showDigest $ sha1 $ BL.fromChunks [contents] let fname = tmpdir </> basename <.> ext BS.writeFile fname contents - return $ Image ils (fname,tit) + return $ Image attr ils (fname,tit) _ -> do warn $ "Could not find image `" ++ src ++ "', skipping..." - return $ Image ils (src,tit) + return $ Image attr ils (src,tit) handleImage' _ _ x = return x convertImages :: FilePath -> Inline -> IO Inline -convertImages tmpdir (Image ils (src, tit)) = do +convertImages tmpdir (Image attr ils (src, tit)) = do img <- convertImage tmpdir src newPath <- case img of Left e -> src <$ warn e Right fp -> return fp - return (Image ils (newPath, tit)) + return (Image attr ils (newPath, tit)) convertImages _ x = return x -- Convert formats which do not work well in pdf to png @@ -127,7 +130,7 @@ convertImage tmpdir fname = E.catch (Right fileOut <$ JP.savePngImage fileOut img) $ \(e :: E.SomeException) -> return (Left (show e)) where - fileOut = replaceDirectory (replaceExtension fname (".png")) tmpdir + fileOut = replaceDirectory (replaceExtension fname ".png") tmpdir mime = getMimeType fname doNothing = return (Right fname) @@ -147,8 +150,8 @@ tex2pdf' verbose args tmpDir program source = do let logmsg = extractMsg log' let extramsg = case logmsg of - x | ("! Package inputenc Error" `BC.isPrefixOf` x - && program /= "xelatex") + x | "! Package inputenc Error" `BC.isPrefixOf` x + && program /= "xelatex" -> "\nTry running pandoc with --latex-engine=xelatex." _ -> "" return $ Left $ logmsg <> extramsg @@ -166,6 +169,14 @@ extractMsg log' = do then log' else BC.unlines (msg'' ++ lineno) +extractConTeXtMsg :: ByteString -> ByteString +extractConTeXtMsg log' = do + let msg' = take 1 $ + dropWhile (not . ("tex error" `BC.isPrefixOf`)) $ BC.lines log' + if null msg' + then log' + else BC.unlines msg' + -- running tex programs -- Run a TeX program on an input bytestring and return (exit code, @@ -188,18 +199,18 @@ runTeXProgram verbose program args runNumber numRuns tmpDir source = do let programArgs = ["-halt-on-error", "-interaction", "nonstopmode", "-output-directory", tmpDir'] ++ args ++ [file'] env' <- getEnvironment - let sep = searchPathSeparator:[] + let sep = [searchPathSeparator] let texinputs = maybe (tmpDir' ++ sep) ((tmpDir' ++ sep) ++) $ lookup "TEXINPUTS" env' let env'' = ("TEXINPUTS", texinputs) : [(k,v) | (k,v) <- env', k /= "TEXINPUTS"] when (verbose && runNumber == 1) $ do - putStrLn $ "[makePDF] temp dir:" + putStrLn "[makePDF] temp dir:" putStrLn tmpDir' - putStrLn $ "[makePDF] Command line:" + putStrLn "[makePDF] Command line:" putStrLn $ program ++ " " ++ unwords (map show programArgs) putStr "\n" - putStrLn $ "[makePDF] Environment:" + putStrLn "[makePDF] Environment:" mapM_ print env'' putStr "\n" putStrLn $ "[makePDF] Contents of " ++ file' ++ ":" @@ -224,3 +235,56 @@ runTeXProgram verbose program args runNumber numRuns tmpDir source = do else return Nothing return (exit, out <> err, pdf) +context2pdf :: Bool -- ^ Verbose output + -> FilePath -- ^ temp directory for output + -> String -- ^ ConTeXt source + -> IO (Either ByteString ByteString) +context2pdf verbose tmpDir source = inDirectory tmpDir $ do + let file = "input.tex" + UTF8.writeFile file source +#ifdef _WINDOWS + -- note: we want / even on Windows, for TexLive + let tmpDir' = changePathSeparators tmpDir +#else + let tmpDir' = tmpDir +#endif + let programArgs = "--batchmode" : [file] + env' <- getEnvironment + let sep = [searchPathSeparator] + let texinputs = maybe (".." ++ sep) ((".." ++ sep) ++) + $ lookup "TEXINPUTS" env' + let env'' = ("TEXINPUTS", texinputs) : + [(k,v) | (k,v) <- env', k /= "TEXINPUTS"] + when verbose $ do + putStrLn "[makePDF] temp dir:" + putStrLn tmpDir' + putStrLn "[makePDF] Command line:" + putStrLn $ "context" ++ " " ++ unwords (map show programArgs) + putStr "\n" + putStrLn "[makePDF] Environment:" + mapM_ print env'' + putStr "\n" + putStrLn $ "[makePDF] Contents of " ++ file ++ ":" + B.readFile file >>= B.putStr + putStr "\n" + (exit, out, err) <- pipeProcess (Just env'') "context" programArgs BL.empty + when verbose $ do + B.hPutStr stdout out + B.hPutStr stderr err + putStr "\n" + let pdfFile = replaceExtension file ".pdf" + pdfExists <- doesFileExist pdfFile + mbPdf <- if pdfExists + -- We read PDF as a strict bytestring to make sure that the + -- temp directory is removed on Windows. + -- See https://github.com/jgm/pandoc/issues/1192. + then (Just . B.fromChunks . (:[])) `fmap` BS.readFile pdfFile + else return Nothing + let log' = out <> err + case (exit, mbPdf) of + (ExitFailure _, _) -> do + let logmsg = extractConTeXtMsg log' + return $ Left logmsg + (ExitSuccess, Nothing) -> return $ Left "" + (ExitSuccess, Just pdf) -> return $ Right pdf + |