@@ -42,6 +42,7 @@ import Control.Exception (evaluate)
4242import System.IO (hClose)
4343import Control.Concurrent (putMVar, takeMVar, newEmptyMVar, forkIO)
4444import Text.Pandoc.UTF8 as UTF8
45+import Control.Monad (unless)
4546
4647tex2pdf :: String -- ^ tex program (pdflatex, lualatex, xelatex)
4748 -> String -- ^ latex source
@@ -54,7 +55,8 @@ tex2pdf' :: FilePath -- ^ temp directory for output
5455 -> String -- ^ tex source
5556 -> IO (Either ByteString ByteString)
5657tex2pdf' tmpDir program source = do
57− (exit, log', mbPdf) <- runTeXProgram program 3 tmpDir source
58+ let numruns = 2 -- should suffice for toc and hyperrefs
59+ (exit, log', mbPdf) <- runTeXProgram program numruns tmpDir source
5860 let msg = "Error producing PDF from TeX source."
5961 case (exit, mbPdf) of
6062 (ExitFailure _, _) -> return $ Left $
@@ -76,41 +78,29 @@ extractMsg log' = do
7678 then log'
7779 else BC.unlines (msg'' ++ lineno)
7880
79−parseLine :: ByteString -> Bool
80−parseLine ln =
81− if "LaTeX Warning:" `BC.isPrefixOf` ln
82− then if "Rerun" `elem` ws
83− then True
84− else False
85− else False
86− where ws = BC.words ln
87−
88−hasUndefinedRefs :: ByteString -> Bool
89−hasUndefinedRefs = or . map parseLine . BC.lines
90−
9181-- running tex programs
9282
9383-- Run a TeX program on an input bytestring and return (exit code,
9484-- contents of stdout, contents of produced PDF if any). Rerun
95−-- latex as needed to resolve references, but don't run bibtex/biber.
85+-- a fixed number of times to resolve references.
9686runTeXProgram :: String -> Int -> FilePath -> String
9787 -> IO (ExitCode, ByteString, Maybe ByteString)
9888runTeXProgram program runsLeft tmpDir source = do
99− withTempFile tmpDir "tex2pdf" $ \file h -> do
100− UTF8.hPutStr h source
101− hClose h
89+ let file = tmpDir </> "input.tex"
90+ exists <- doesFileExist file
91+ unless exists $ UTF8.writeFile file source
10292 let programArgs = ["-halt-on-error", "-interaction", "nonstopmode",
10393 "-output-directory", tmpDir, file]
10494 (exit, out, err) <- readCommand program programArgs
105− removeFile file
106− let pdfFile = replaceDirectory (replaceExtension file ".pdf") tmpDir
107− pdfExists <- doesFileExist pdfFile
108− pdf <- if pdfExists
109− then Just `fmap` B.readFile pdfFile
110− else return Nothing
111− if hasUndefinedRefs out && runsLeft > 0
95+ if runsLeft > 1
11296 then runTeXProgram program (runsLeft - 1) tmpDir source
113− else return (exit, out <> err, pdf)
97+ else do
98+ let pdfFile = replaceDirectory (replaceExtension file ".pdf") tmpDir
99+ pdfExists <- doesFileExist pdfFile
100+ pdf <- if pdfExists
101+ then Just `fmap` B.readFile pdfFile
102+ else return Nothing
103+ return (exit, out <> err, pdf)
114104
115105-- utility functions
116106
@@ -140,4 +130,4 @@ readCommand cmd args = do
140130 hClose outh
141131 -- wait on the process
142132 ex <- waitForProcess pid
143− return (ex, out, err)
133+ return (ex, out, err)