git.iko.soy/typeable/pandoc
on master help sign in
Added Text.Pandoc.PDF module, 'pdf' as new output option.

The module calls pdflatex to produce the PDF, and is basically shell scripting in haskell. But this is better than the existing markdown2pdf script, which is limited to POSIX. git-svn-id: https://pandoc.googlecode.com/svn/trunk@1394 788f1e2b-df1e-0410-8736-df70ead52e1b

commit0f4bdc6b7d52e1a2ce5db8f0df5fb06a5fdce324 authorfiddlosopher <fiddlosopher@788f1e2b-df1e-0410-8736-df70ead52e1b> dateSun 10 Aug 2008, 17:33 (18 years ago) parentf435d14
4 files changed+176−160
Main.hs+55−51 README+22−5 Text/Pandoc/PDF.hs+98−104 pandoc.cabal+1
Main.hs+55−51
@@ -20,10 +20,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2020{- |
2121 Module : Main
2222 Copyright : Copyright (C) 2006-8 John MacFarlane
23− License : GNU GPL, version 2 or above
23+ License : GNU GPL, version 2 or above
2424
2525 Maintainer : John MacFarlane <jgm@berkeley@edu>
26− Stability : alpha
26+ Stability : alpha
2727 Portability : portable
2828
2929Parses command-line options and calls the appropriate readers and
@@ -32,6 +32,7 @@ writers.
3232module Main where
3333import Text.Pandoc
3434import Text.Pandoc.ODT
35+import Text.Pandoc.PDF
3536import Text.Pandoc.Shared ( joinWithSep, HTMLMathMethod (..) )
3637import Text.Pandoc.Highlighting ( languages )
3738import System.Environment ( getArgs, getProgName, getEnvironment )
@@ -98,7 +99,7 @@ readers = [("native" , readPandoc)
9899-- | Reader for native Pandoc format.
99100readPandoc :: ParserState -> String -> Pandoc
100101readPandoc _ input = read input
101−
102+
102103-- | Association list of formats and pairs of writers and default headers.
103104writers :: [ ( String, ( WriterOptions -> Pandoc -> String, String ) ) ]
104105writers = [("native" , (writeDoc, ""))
@@ -108,6 +109,7 @@ writers = [("native" , (writeDoc, ""))
108109 ,("opendocument" , (writeOpenDocument, defaultOpenDocumentHeader))
109110 ,("odt" , (writeOpenDocument, defaultOpenDocumentHeader))
110111 ,("latex" , (writeLaTeX, defaultLaTeXHeader))
112+ ,("pdf" , (writeLaTeX, defaultLaTeXHeader))
111113 ,("context" , (writeConTeXt, defaultConTeXtHeader))
112114 ,("texinfo" , (writeTexinfo, ""))
113115 ,("man" , (writeMan, ""))
@@ -118,8 +120,7 @@ writers = [("native" , (writeDoc, ""))
118120 ]
119121
120122isNonTextOutput :: String -> Bool
121−isNonTextOutput "odt" = True
122−isNonTextOutput _ = False
123+isNonTextOutput = (`elem` ["odt", "pdf"])
123124
124125-- | Writer for Pandoc native format.
125126writeDoc :: WriterOptions -> Pandoc -> String
@@ -205,7 +206,7 @@ options =
205206 (\arg opt -> return opt { optWriter = map toLower arg })
206207 "FORMAT")
207208 "" -- ("(" ++ (joinWithSep ", " $ map fst writers) ++ ")")
208−
209+
209210 , Option "s" ["standalone"]
210211 (NoArg
211212 (\opt -> return opt { optStandalone = True }))
@@ -250,7 +251,7 @@ options =
250251
251252 , Option "m" ["asciimathml"]
252253 (OptArg
253− (\arg opt -> return opt { optHTMLMathMethod =
254+ (\arg opt -> return opt { optHTMLMathMethod =
254255 ASCIIMathML arg })
255256 "URL")
256257 "" -- "Use ASCIIMathML script in html output"
@@ -290,13 +291,13 @@ options =
290291 , Option "" ["toc", "table-of-contents"]
291292 (NoArg
292293 (\opt -> return opt { optTableOfContents = True }))
293− "" -- "Include table of contents"
294+ "" -- "Include table of contents"
294295
295296 , Option "c" ["css"]
296297 (ReqArg
297− (\arg opt -> do
298+ (\arg opt -> do
298299 let old = optCSS opt
299− return opt { optCSS = old ++ [arg],
300+ return opt { optCSS = old ++ [arg],
300301 optStandalone = True })
301302 "CSS")
302303 "" -- "Link to CSS style sheet"
@@ -340,17 +341,17 @@ options =
340341
341342 , Option "T" ["title-prefix"]
342343 (ReqArg
343− (\arg opt -> return opt { optTitlePrefix = arg,
344+ (\arg opt -> return opt { optTitlePrefix = arg,
344345 optStandalone = True })
345346 "STRING")
346347 "" -- "String to prefix to HTML window title"
347−
348+
348349 , Option "D" ["print-default-header"]
349350 (ReqArg
350351 (\arg _ -> do
351352 let header = case (lookup arg writers) of
352353 Just (_, h) -> h
353− Nothing -> error ("Unknown reader: " ++ arg)
354+ Nothing -> error ("Unknown reader: " ++ arg)
354355 hPutStr stdout header
355356 exitWith ExitSuccess)
356357 "FORMAT")
@@ -376,7 +377,7 @@ options =
376377 (NoArg
377378 (\opt -> return opt { optIgnoreArgs = True }))
378379 "" -- "Ignore command-line arguments."
379−
380+
380381 , Option "v" ["version"]
381382 (NoArg
382383 (\_ -> do
@@ -398,15 +399,15 @@ options =
398399-- Returns usage message
399400usageMessage :: String -> [OptDescr (Opt -> IO Opt)] -> String
400401usageMessage programName opts = usageInfo
401− (programName ++ " [OPTIONS] [FILES]" ++ "\nInput formats: " ++
402− (joinWithSep ", " $ map fst readers) ++ "\nOutput formats: " ++
402+ (programName ++ " [OPTIONS] [FILES]" ++ "\nInput formats: " ++
403+ (joinWithSep ", " $ map fst readers) ++ "\nOutput formats: " ++
403404 (joinWithSep ", " $ map fst writers) ++ "\nOptions:")
404405 opts
405−
406+
406407-- Determine default reader based on source file extensions
407408defaultReaderName :: [FilePath] -> String
408409defaultReaderName [] = "markdown"
409−defaultReaderName (x:xs) =
410+defaultReaderName (x:xs) =
410411 case takeExtension (map toLower x) of
411412 ".xhtml" -> "html"
412413 ".html" -> "html"
@@ -441,6 +442,7 @@ defaultWriterName x =
441442 ".texinfo" -> "texinfo"
442443 ".db" -> "docbook"
443444 ".odt" -> "odt"
445+ ".pdf" -> "pdf"
444446 ['.',y] | y `elem` ['1'..'9'] -> "man"
445447 _ -> "html"
446448
@@ -464,7 +466,7 @@ main = do
464466 else
465467 return ()
466468
467− let defaultOpts' = if compatMode
469+ let defaultOpts' = if compatMode
468470 then defaultOpts { optReader = "markdown"
469471 , optWriter = "html"
470472 , optStrict = True }
@@ -513,11 +515,11 @@ main = do
513515 let sources = if ignoreArgs then [] else args
514516
515517 -- assign reader and writer based on options and filenames
516− let readerName' = if null readerName
518+ let readerName' = if null readerName
517519 then defaultReaderName sources
518520 else readerName
519521
520− let writerName' = if null writerName
522+ let writerName' = if null writerName
521523 then defaultWriterName outputFile
522524 else writerName
523525
@@ -539,74 +541,76 @@ main = do
539541 -- remove DOS line endings
540542 tabFilter _ ('\r':'\n':xs) = '\n':(tabFilter tabStop xs)
541543 tabFilter _ ('\r':xs) = '\n':(tabFilter tabStop xs)
542− tabFilter spsToNextStop ('\t':xs) =
544+ tabFilter spsToNextStop ('\t':xs) =
543545 if preserveTabs
544− then '\t':(tabFilter tabStop xs)
545− else replicate spsToNextStop ' ' ++ tabFilter tabStop xs
546− tabFilter 1 (x:xs) =
546+ then '\t':(tabFilter tabStop xs)
547+ else replicate spsToNextStop ' ' ++ tabFilter tabStop xs
548+ tabFilter 1 (x:xs) =
547549 x:(tabFilter tabStop xs)
548− tabFilter spsToNextStop (x:xs) =
550+ tabFilter spsToNextStop (x:xs) =
549551 x:(tabFilter (spsToNextStop - 1) xs)
550552
551− let standalone' = (standalone && not strict) || writerName' == "odt"
553+ let standalone' = (standalone && not strict) || isNonTextOutput writerName'
552554
553555#ifdef _CITEPROC
554556 refs <- if null modsFile then return [] else readModsColletionFile modsFile
555557#endif
556558
557− let startParserState =
559+ let startParserState =
558560 defaultParserState { stateParseRaw = parseRaw,
559− stateTabStop = tabStop,
561+ stateTabStop = tabStop,
560562 stateSanitizeHTML = sanitize,
561563 stateStandalone = standalone',
562564#ifdef _CITEPROC
563565 stateCitations = map citeKey refs,
564566#endif
565− stateSmart = smart || writerName' `elem`
567+ stateSmart = smart || writerName' `elem`
566568 ["latex", "context"],
567569 stateColumns = columns,
568570 stateStrict = strict }
569571 let csslink = if null css
570572 then ""
571− else concatMap
573+ else concatMap
572574 (\f -> "<link rel=\"stylesheet\" href=\"" ++
573575 f ++ "\" type=\"text/css\" media=\"all\" />\n")
574576 css
575− let header = (if (customHeader == "DEFAULT")
577+ let header = (if (customHeader == "DEFAULT")
576578 then defaultHeader
577579 else customHeader) ++ csslink ++ includeHeader
578580 let writerOptions = WriterOptions { writerStandalone = standalone',
579− writerHeader = header,
581+ writerHeader = header,
580582 writerTitlePrefix = titlePrefix,
581− writerTabStop = tabStop,
583+ writerTabStop = tabStop,
582584 writerTableOfContents = toc &&
583585 (not strict) &&
584586 writerName' /= "s5",
585587 writerHTMLMathMethod = mathMethod,
586588 writerS5 = (writerName' == "s5"),
587589 writerIgnoreNotes = False,
588− writerIncremental = incremental,
590+ writerIncremental = incremental,
589591 writerNumberSections = numberSections,
590− writerIncludeBefore = includeBefore,
592+ writerIncludeBefore = includeBefore,
591593 writerIncludeAfter = includeAfter,
592594 writerStrictMarkdown = strict,
593595 writerReferenceLinks = referenceLinks,
594596 writerWrapText = wrap }
595597
596− let writeOutput = if writerName' == "odt"
597− then if outputFile == "-"
598− then \_ -> do
599− hPutStrLn stderr ("Error: Cannot write " ++ writerName ++
600− " output to stdout.\n" ++
601− "Specify an output file using the -o option.")
602− exitWith $ ExitFailure 5
603− else let sourceDirRelative = if null sources
604− then ""
605− else takeDirectory (head sources)
606− in saveOpenDocumentAsODT outputFile sourceDirRelative
607− else if outputFile == "-"
608− then putStrLn
609− else writeFile outputFile . (++ "\n")
598+ if isNonTextOutput writerName' && outputFile == "-"
599+ then do hPutStrLn stderr ("Error: Cannot write " ++ writerName ++ " output to stdout.\n" ++
600+ "Specify an output file using the -o option.")
601+ exitWith $ ExitFailure 5
602+ else return ()
603+
604+ let sourceDirRelative = if null sources
605+ then ""
606+ else takeDirectory (head sources)
607+
608+ let writeOutput = case writerName' of
609+ "odt" -> saveOpenDocumentAsODT outputFile sourceDirRelative
610+ "pdf" -> saveLaTeXAsPDF outputFile sourceDirRelative
611+ _ -> if outputFile == "-"
612+ then putStrLn
613+ else writeFile outputFile . (++ "\n")
610614
611615 fmap (reader startParserState . tabFilter tabStop . joinWithSep "\n")
612616 (readSources sources) >>=
@@ -615,7 +619,7 @@ main = do
615619#endif
616620 writeOutput . writer writerOptions
617621
618− where
622+ where
619623 readSources [] = mapM readSource ["-"]
620624 readSources sources = mapM readSource sources
621625 readSource "-" = getContents
README+22−5
@@ -82,11 +82,28 @@ To convert `hello.html` from html to markdown:
8282 pandoc -f html -t markdown hello.html
8383
8484Supported output formats include `markdown`, `latex`, `context`
85−(ConTeXt), `html`, `rtf` (rich text format), `rst` (reStructuredText),
86−`docbook` (DocBook XML), `opendocument` (OpenDocument XML), `odt`
87−(OpenOffice text document), `texinfo`, (GNU Texinfo), `mediawiki`
88−(MediaWiki markup), `man` (groff man), and `s5` (which produces an
89−HTML file that acts like powerpoint).
85+(ConTeXt), `pdf`, `html`, `rtf` (rich text format), `rst`
86+(reStructuredText), `docbook` (DocBook XML), `opendocument`
87+(OpenDocument XML), `odt` (OpenOffice text document), `texinfo`, (GNU
88+Texinfo), `mediawiki` (MediaWiki markup), `man` (groff man), and `s5`
89+(which produces an HTML file that acts like powerpoint).
90+
91+Notes:
92+
93+- For `odt` output, you must have `zip` in the path. If you
94+ don't have it installed, you can get the free [Info-ZIP].
95+
96+- For `pdf` output, you must have `pdflatex` and `bibtex` in the
97+ path. You should also have the following LaTeX packages installed:
98+ `unicode`, `fancyhdr` (if you have verbatim text in footnotes),
99+ `graphicx` (if you use images), `array` (if you use tables), and
100+ `ulem` (if you use strikeout text). If they are not already included
101+ in your LaTeX distribution, you can get them from [CTAN]. A full
102+ [TeX Live] or [MacTeX] distribution will have all of these packages.
103+
104+ [Info-ZIP]: http://www.info-zip.org/Zip.html
105+ [TeX Live]: http://www.tug.org/texlive/
106+ [MacTeX]: http://www.tug.org/mactex/
90107
91108Supported input formats include `markdown`, `html`, `latex`, and `rst`.
92109Note that the `rst` reader only parses a subset of reStructuredText
Text/Pandoc/PDF.hs+98−104
@@ -1,4 +1,4 @@
1−{-# LANGUAGE TemplateHaskell, CPP #-}
1+{-# LANGUAGE CPP #-}
22{-
33Copyright (C) 2008 John MacFarlane <jgm@berkeley.edu>
44
@@ -18,7 +18,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1818-}
1919
2020{- |
21− Module : Text.Pandoc.ODT
21+ Module : Text.Pandoc.PDF
2222 Copyright : Copyright (C) 2006-7 John MacFarlane
2323 License : GNU GPL, version 2 or above
2424
@@ -26,119 +26,113 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2626 Stability : alpha
2727 Portability : portable
2828
29−Functions for producing an ODT file from OpenDocument XML.
29+Functions for producing a PDF file from LaTeX.
3030-}
31−module Text.Pandoc.ODT ( saveOpenDocumentAsODT ) where
32−import Text.Pandoc.TH ( binaryContentsOf )
33−import Data.Maybe ( fromJust )
34−import Data.List ( partition, intersperse )
31+module Text.Pandoc.PDF ( saveLaTeXAsPDF ) where
32+import Data.List ( isInfixOf )
3533import System.Directory
36−import System.FilePath ( (</>), takeDirectory, takeFileName, splitDirectories )
34+import System.FilePath ( (</>), (<.>), takeBaseName )
3735import System.Process ( runProcess, waitForProcess )
3836import System.Exit
39−import Text.XML.Light
40−import Text.XML.Light.Cursor
37+import System.Environment ( getEnvironment )
4138import Text.Pandoc.Shared ( withTempDir )
42−import Network.URI ( isURI )
43−import qualified Data.ByteString as B ( writeFile, pack )
44−import Data.ByteString.Internal ( c2w )
45−import Prelude hiding ( writeFile, readFile )
46−import System.IO ( stderr )
39+import Prelude hiding ( writeFile, readFile, putStrLn )
40+import System.IO ( stderr, openFile, IOMode (..) )
4741#ifdef _UTF8STRING
4842import System.IO.UTF8
4943#else
5044import Text.Pandoc.UTF8
5145#endif
5246
53−-- | Produce an ODT file from OpenDocument XML.
54−saveOpenDocumentAsODT :: FilePath -- ^ Pathname of ODT file to be produced.
55− -> FilePath -- ^ Relative directory of source file.
56− -> String -- ^ OpenDocument XML contents.
57− -> IO ()
58−saveOpenDocumentAsODT destinationODTPath sourceDirRelative xml = do
59− let zipCmd = "zip"
60− -- check for zip in path:
61− zipPathMaybe <- findExecutable zipCmd
62− let zipPath = case zipPathMaybe of
63− Nothing -> error $ "The '" ++ zipCmd ++
64− "' command, which is needed to build an ODT file, was not found.\n" ++
65− "It can be obtained from http://www.info-zip.org/Zip.html\n" ++
66− "Debian (and Debian-based) linux: apt-get install zip\n" ++
67− "Windows: See http://gnuwin32.sourceforge.net/packages/zip.htm"
47+-- | Produce an PDF file from LaTeX.
48+saveLaTeXAsPDF :: FilePath -- ^ Pathname of PDF file to be produced.
49+ -> FilePath -- ^ Relative directory of source file.
50+ -> String -- ^ LaTeX document.
51+ -> IO ()
52+saveLaTeXAsPDF destinationPDFPath sourceDirRelative latex = do
53+ -- check for pdflatex and bibtex in path:
54+ latexPathMaybe <- findExecutable "pdflatex"
55+ bibtexPathMaybe <- findExecutable "bibtex"
56+ let latexPath = case latexPathMaybe of
57+ Nothing -> error $ "The 'pdflatex' command, which is needed to build an PDF file, was not found."
6858 Just x -> x
69− withTempDir "pandoc-odt" $ \tempDir -> do
70− let tempODT = tempDir </> "reference.odt"
71− B.writeFile tempODT $ B.pack $ map c2w $(binaryContentsOf $ "odt-styles" </> "reference.odt")
72− xml' <- handlePictures tempODT sourceDirRelative xml
73− writeFile (tempDir </> "content.xml") xml'
74− ph <- runProcess zipPath ["-9", "-q", "-r", tempODT, "content.xml", "Pictures"]
75− (Just tempDir) Nothing Nothing Nothing (Just stderr)
76− ec <- waitForProcess ph -- requires compilation with -threaded
77− case ec of
78− ExitSuccess -> copyFile tempODT destinationODTPath
79− _ -> error "Error creating ODT." >> exitWith ec
80−
81−-- | Find <draw:image ... /> elements and copy the file (xlink:href attribute) into Pictures/ in
82−-- the zip file. If filename is a URL, attempt to download it. Modify xlink:href attributes
83−-- to point to the new locations in Pictures/. Return modified XML.
84−handlePictures :: FilePath -- ^ Path of ODT file in temp directory
85− -> FilePath -- ^ Directory (relative) containing source file
86− -> String -- ^ OpenDocument XML string
87− -> IO String -- ^ Modified XML
88−handlePictures tempODT sourceDirRelative xml = do
89− let parsed = case parseXMLDoc xml of
90− Nothing -> error "Could not parse OpenDocument XML."
91− Just x -> x
92− let cursor = case (fromForest $ elContent parsed) of
93− Nothing -> error "ODT appears empty"
94− Just x -> x
95− cursor' <- scanPictures tempODT sourceDirRelative cursor
96− let modified = parsed { elContent = toForest $ root cursor' }
97− return $ showTopElement modified
98−
99−scanPictures :: FilePath -> FilePath -> Cursor -> IO Cursor
100−scanPictures tempODT sourceDirRelative cursor = do
101− cursor' <- handleTree tempODT sourceDirRelative cursor
102− case right cursor' of
103− Just n -> scanPictures tempODT sourceDirRelative n
104− Nothing -> return cursor'
105−
106−handleTree :: FilePath -> FilePath -> Cursor -> IO Cursor
107−handleTree tempODT sourceDirRelative cursor = do
108− case firstChild cursor of
109− Nothing -> modifyContentM (handleContent tempODT sourceDirRelative) cursor
110− Just n -> scanPictures tempODT sourceDirRelative n >>= return . fromJust . parent
59+ let bibtexPath = case bibtexPathMaybe of
60+ Nothing -> error $ "The 'bibtex' command, which is needed to build an PDF file, was not found."
61+ Just x -> x
62+ sourceDirAbsolute <- getCurrentDirectory >>= return . (</> sourceDirRelative) >>= canonicalizePath
63+ withTempDir "pandoc-pdf" $ \tempDir -> do
64+ env <- getEnvironment
65+ let env' = ("TEXINPUTS", ".:" ++ sourceDirAbsolute ++ ":") : env
66+ let baseName = "input"
67+ writeFile (tempDir </> baseName <.> "tex") latex
68+ let runLatex = runProgram latexPath ["-interaction=nonstopmode", baseName] tempDir env'
69+ let runBibtex = runProgram bibtexPath [baseName] tempDir env'
70+ messages1 <- runLatex
71+ let logPath = tempDir </> baseName <.> "log"
72+ tocExists <- doesFileExist (tempDir </> baseName <.> "toc")
73+ logContents <- readFile logPath
74+ let undefinedRefs = "There were undefined references" `isInfixOf` logContents
75+ let needsBibtex = "itation" `isInfixOf` logContents
76+ if needsBibtex
77+ then runBibtex >>= hPutStr stderr . unlines
78+ else return ()
79+ if tocExists || undefinedRefs
80+ then do
81+ messages2 <- runLatex
82+ logContents' <- readFile logPath
83+ let stillUndefinedRefs = "There were undefined references" `isInfixOf` logContents'
84+ if stillUndefinedRefs
85+ then runLatex >>= hPutStr stderr . unlines
86+ else hPutStr stderr $ unlines messages2
87+ else
88+ hPutStr stderr $ unlines messages1
89+ let pdfPath = tempDir </> baseName <.> "pdf"
90+ pdfExists <- doesFileExist pdfPath
91+ if pdfExists
92+ then copyFile pdfPath destinationPDFPath
93+ else error "The PDF could not be created."
11194
112−-- | If content is an image link, handle it appropriately.
113−-- Otherwise, handle children if any.
114−handleContent :: FilePath -> FilePath -> Content -> IO Content
115−handleContent tempODT sourceDirRelative content@(Elem el) = do
116− if qName (elName el) == "image"
117− then do
118− let (hrefs, rest) = partition (\a -> qName (attrKey a) == "href") $ elAttribs el
119− let href = case hrefs of
120− [] -> error $ "No href found in " ++ show el
121− [x] -> x
122− _ -> error $ "Multiple hrefs found in " ++ show el
123− if isURI $ attrVal href
124− then return content
125− else do -- treat as filename
126− let oldLoc = sourceDirRelative </> attrVal href
127− fileExists <- doesFileExist oldLoc
128− if fileExists
129− then do
130− let pref = take 230 $ concat $ intersperse "_" $
131− splitDirectories $ takeDirectory $ attrVal href
132− let newLoc = "Pictures" </> pref ++ "_" ++ (takeFileName $ attrVal href)
133− let tempDir = takeDirectory tempODT
134− createDirectoryIfMissing False $ tempDir </> takeDirectory newLoc
135− copyFile oldLoc $ tempDir </> newLoc
136− let newAttrs = (href { attrVal = newLoc }) : rest
137− return $ Elem (el { elAttribs = newAttrs })
138− else do
139− hPutStrLn stderr $ "Warning: Unable to find image at " ++ oldLoc ++ " - ignoring."
140− return content
141− else return content
142−
143−handleContent _ _ c = return c -- not Element
95+runProgram :: FilePath -- ^ pathname of executable
96+ -> [String] -- ^ arguments
97+ -> FilePath -- ^ working directory
98+ -> [(String, String)] -- ^ environment
99+ -> IO [String]
100+runProgram cmdPath arguments workingDir env = do
101+ let runOutputPath = workingDir </> "output" <.> "tmp"
102+ runOutput <- openFile runOutputPath WriteMode
103+ ph <- runProcess cmdPath arguments (Just workingDir) (Just env) Nothing (Just runOutput) (Just runOutput)
104+ ec <- waitForProcess ph -- requires compilation with -threaded
105+ case ec of
106+ ExitSuccess -> return []
107+ _ -> do
108+ output <- readFile runOutputPath
109+ if (takeBaseName cmdPath) == "bibtex"
110+ then return $! lines output
111+ else do
112+ return $!
113+ (if "`ucs.sty' not found" `isInfixOf` output
114+ then ["Please install the 'unicode' package from CTAN:",
115+ " http://www.ctan.org/tex-archive/macros/latex/contrib/unicode/"]
116+ else []) ++
117+ (if "`ulem.sty' not found" `isInfixOf` output
118+ then ["Please install the 'ulem' package from CTAN:",
119+ " http://www.ctan.org/tex-archive/macros/latex/contrib/misc/"]
120+ else []) ++
121+ (if "`graphicx.sty' not found" `isInfixOf` output
122+ then ["Please install the 'graphicx' package from CTAN:",
123+ " http://www.ctan.org/tex-archive/macros/latex/required/graphics/"]
124+ else []) ++
125+ (if "`fancyhdr.sty' not found" `isInfixOf` output
126+ then ["Please install the 'fancyhdr' package from CTAN:",
127+ " http://www.ctan.org/tex-archive/macros/latex/contrib/fancyhdr/"]
128+ else []) ++
129+ (if "`array.sty' not found" `isInfixOf` output
130+ then ["Please install the 'array' package from CTAN:",
131+ " http://www.ctan.org/tex-archive/macros/latex/required/tools/"]
132+ else []) ++
133+ (filter isUseful $ lines output)
134+ where isUseful ln = take 1 ln == "!" ||
135+ take 2 ln == "l." ||
136+ "Error" `isInfixOf` ln ||
137+ "error" `isInfixOf` ln
144138
pandoc.cabal+1
@@ -165,6 +165,7 @@ Library
165165 Text.Pandoc.CharacterReferences,
166166 Text.Pandoc.Shared,
167167 Text.Pandoc.ODT,
168+ Text.Pandoc.PDF,
168169 Text.Pandoc.ASCIIMathML,
169170 Text.Pandoc.DefaultHeaders,
170171 Text.Pandoc.Highlighting,