git.iko.soy/typeable/pandoc
on master help sign in
Allow use of ConTeXt to generate PDFs.
8193ebcJohn MacFarlane
README+17−6
@@ -24,7 +24,7 @@ markup], [Haddock markup], [OPML], [Emacs Org mode], [DocBook],
24[FictionBook2], [Textile], [groff man] pages, [Emacs Org mode],
24[FictionBook2], [Textile], [groff man] pages, [Emacs Org mode],
25[AsciiDoc], [InDesign ICML], and [Slidy], [Slideous], [DZSlides],
25[AsciiDoc], [InDesign ICML], and [Slidy], [Slideous], [DZSlides],
26[reveal.js] or [S5] HTML slide shows. It can also produce [PDF] output
26[reveal.js] or [S5] HTML slide shows. It can also produce [PDF] output
27−on systems where LaTeX is installed.
27+on systems where LaTeX or ConTeXt is installed.
28
28
29Pandoc's enhanced version of markdown includes syntax for [footnotes],
29Pandoc's enhanced version of markdown includes syntax for [footnotes],
30[tables], flexible [ordered lists], [definition lists], [fenced code blocks],
30[tables], flexible [ordered lists], [definition lists], [fenced code blocks],
@@ -167,7 +167,7 @@ Creating a PDF
167--------------
167--------------
168
168
169To produce a PDF, specify an output file with a `.pdf` extension.
169To produce a PDF, specify an output file with a `.pdf` extension.
170−Pandoc will use LaTeX to convert it to PDF:
170+By default, pandoc will use LaTeX to convert it to PDF:
171
171
172 pandoc test.txt -o test.pdf
172 pandoc test.txt -o test.pdf
173
173
@@ -189,7 +189,12 @@ be used for [smart punctuation] if added to the template. The
189optionally be used for [citation rendering]. These are included with
189optionally be used for [citation rendering]. These are included with
190all recent versions of [TeX Live].
190all recent versions of [TeX Live].
191
191
192+Alternatively, you can ask pandoc to use ConTeXt to create the PDF.
193+To do this, specify an output file with a `.pdf` extension,
194+as before, but add `-t context` to the command line.
195+
192−PDF output can be controlled using [variables for LaTeX].
196+PDF output can be controlled using [variables for LaTeX]
197+or [variables for ConTeXt].
193
198
194[`amsfonts`]: https://ctan.org/pkg/amsfonts
199[`amsfonts`]: https://ctan.org/pkg/amsfonts
195[`amsmath`]: https://ctan.org/pkg/amsmath
200[`amsmath`]: https://ctan.org/pkg/amsmath
@@ -992,9 +997,9 @@ customize the `default.opendocument` template. For `pdf` output,
992customize the `default.latex` template.
997customize the `default.latex` template.
993
998
994Templates contain *variables*, which allow for the inclusion of
999Templates contain *variables*, which allow for the inclusion of
995−arbitrary information at any point in the file. Variables may be set
1000+arbitrary information at any point in the file. Variables may be set
996−within the document using [YAML metadata blocks][Extension: `yaml_metadata_block`].
1001+within the document using [YAML metadata blocks][Extension:
997−They may also be set at the
1002+`yaml_metadata_block`]. They may also be set at the
998command line using the `-V/--variable` option: variables set in this
1003command line using the `-V/--variable` option: variables set in this
999way override metadata fields with the same name.
1004way override metadata fields with the same name.
1000
1005
@@ -1201,6 +1206,12 @@ LaTeX variables are used when [creating a PDF].
1201[`mathpazo`]: https://ctan.org/pkg/mathpazo
1206[`mathpazo`]: https://ctan.org/pkg/mathpazo
1202[LaTeX font encodings]: https://ctan.org/pkg/encguide
1207[LaTeX font encodings]: https://ctan.org/pkg/encguide
1203
1208
1209+Variables for ConTeXt
1210+---------------------
1211+
1212+`papersize`
1213+: paper size (defaults to `letter`)
1214+
1204Variables for man pages
1215Variables for man pages
1205-----------------------
1216-----------------------
1206
1217
pandoc.hs+10−6
@@ -1173,6 +1173,7 @@ main = do
1173
1173
1174 let laTeXOutput = "latex" `isPrefixOf` writerName' ||
1174 let laTeXOutput = "latex" `isPrefixOf` writerName' ||
1175 "beamer" `isPrefixOf` writerName'
1175 "beamer" `isPrefixOf` writerName'
1176+ let conTeXtOutput = "context" `isPrefixOf` writerName'
1176
1177
1177 writer <- if ".lua" `isSuffixOf` writerName'
1178 writer <- if ".lua" `isSuffixOf` writerName'
1178 -- note: use non-lowercased version writerName
1179 -- note: use non-lowercased version writerName
@@ -1256,7 +1257,7 @@ main = do
1256 _ -> Nothing
1257 _ -> Nothing
1257
1258
1258 let readerOpts = def{ readerSmart = smart || (texLigatures &&
1259 let readerOpts = def{ readerSmart = smart || (texLigatures &&
1259− (laTeXOutput || "context" `isPrefixOf` writerName'))
1260+ (laTeXOutput || conTeXtOutput))
1260 , readerStandalone = standalone'
1261 , readerStandalone = standalone'
1261 , readerParseRaw = parseRaw
1262 , readerParseRaw = parseRaw
1262 , readerColumns = columns
1263 , readerColumns = columns
@@ -1367,17 +1368,20 @@ main = do
1367 PureStringWriter f
1368 PureStringWriter f
1368 | pdfOutput -> do
1369 | pdfOutput -> do
1369 -- make sure writer is latex or beamer
1370 -- make sure writer is latex or beamer
1370− unless laTeXOutput $
1371+ unless (laTeXOutput || conTeXtOutput) $
1371 err 47 $ "cannot produce pdf output with " ++ writerName' ++
1372 err 47 $ "cannot produce pdf output with " ++ writerName' ++
1372 " writer"
1373 " writer"
1373
1374
1375+ let texprog = if conTeXtOutput
1376+ then "context"
1377+ else latexEngine
1374 -- check for latex program
1378 -- check for latex program
1375− mbLatex <- findExecutable latexEngine
1379+ mbLatex <- findExecutable texprog
1376 when (mbLatex == Nothing) $
1380 when (mbLatex == Nothing) $
1377− err 41 $ latexEngine ++ " not found. " ++
1381+ err 41 $ texprog ++ " not found. " ++
1378− latexEngine ++ " is needed for pdf output."
1382+ texprog ++ " is needed for pdf output."
1379
1383
1380− res <- makePDF latexEngine f writerOptions doc'
1384+ res <- makePDF texprog f writerOptions doc'
1381 case res of
1385 case res of
1382 Right pdf -> writeBinary pdf
1386 Right pdf -> writeBinary pdf
1383 Left err' -> do
1387 Left err' -> do
src/Text/Pandoc/PDF.hs+64−2
@@ -47,7 +47,7 @@ import Data.Maybe (fromMaybe)
47import qualified Text.Pandoc.UTF8 as UTF8
47import qualified Text.Pandoc.UTF8 as UTF8
48import Text.Pandoc.Definition
48import Text.Pandoc.Definition
49import Text.Pandoc.Walk (walkM)
49import Text.Pandoc.Walk (walkM)
50−import Text.Pandoc.Shared (fetchItem', warn, withTempDir)
50+import Text.Pandoc.Shared (fetchItem', warn, withTempDir, inDirectory)
51import Text.Pandoc.Options (WriterOptions(..))
51import Text.Pandoc.Options (WriterOptions(..))
52import Text.Pandoc.MIME (extensionFromMimeType, getMimeType)
52import Text.Pandoc.MIME (extensionFromMimeType, getMimeType)
53import Text.Pandoc.Process (pipeProcess)
53import Text.Pandoc.Process (pipeProcess)
@@ -71,7 +71,9 @@ makePDF program writer opts doc = withTempDir "tex2pdf." $ \tmpdir -> do
71 doc' <- handleImages opts tmpdir doc
71 doc' <- handleImages opts tmpdir doc
72 let source = writer opts doc'
72 let source = writer opts doc'
73 args = writerLaTeXArgs opts
73 args = writerLaTeXArgs opts
74+ case program of
75+ "context" -> context2pdf (writerVerbose opts) tmpdir source
74− tex2pdf' (writerVerbose opts) args tmpdir program source
76+ _ -> tex2pdf' (writerVerbose opts) args tmpdir program source
75
77
76handleImages :: WriterOptions
78handleImages :: WriterOptions
77 -> FilePath -- ^ temp dir to store images
79 -> FilePath -- ^ temp dir to store images
@@ -166,6 +168,14 @@ extractMsg log' = do
166 then log'
168 then log'
167 else BC.unlines (msg'' ++ lineno)
169 else BC.unlines (msg'' ++ lineno)
168
170
171+extractConTeXtMsg :: ByteString -> ByteString
172+extractConTeXtMsg log' = do
173+ let msg' = take 1 $
174+ dropWhile (not . ("tex error" `BC.isPrefixOf`)) $ BC.lines log'
175+ if null msg'
176+ then log'
177+ else BC.unlines msg'
178+
169-- running tex programs
179-- running tex programs
170
180
171-- Run a TeX program on an input bytestring and return (exit code,
181-- Run a TeX program on an input bytestring and return (exit code,
@@ -224,3 +234,55 @@ runTeXProgram verbose program args runNumber numRuns tmpDir source = do
224 else return Nothing
234 else return Nothing
225 return (exit, out <> err, pdf)
235 return (exit, out <> err, pdf)
226
236
237+context2pdf :: Bool -- ^ Verbose output
238+ -> FilePath -- ^ temp directory for output
239+ -> String -- ^ ConTeXt source
240+ -> IO (Either ByteString ByteString)
241+context2pdf verbose tmpDir source = inDirectory tmpDir $ do
242+ let file = "input.tex"
243+ UTF8.writeFile file source
244+#ifdef _WINDOWS
245+ -- note: we want / even on Windows, for TexLive
246+ let tmpDir' = changePathSeparators tmpDir
247+#else
248+ let tmpDir' = tmpDir
249+#endif
250+ let programArgs = ["--batchmode"] ++ [file]
251+ env' <- getEnvironment
252+ let sep = searchPathSeparator:[]
253+ let texinputs = maybe (".." ++ sep) ((".." ++ sep) ++)
254+ $ lookup "TEXINPUTS" env'
255+ let env'' = ("TEXINPUTS", texinputs) :
256+ [(k,v) | (k,v) <- env', k /= "TEXINPUTS"]
257+ when verbose $ do
258+ putStrLn $ "[makePDF] temp dir:"
259+ putStrLn tmpDir'
260+ putStrLn $ "[makePDF] Command line:"
261+ putStrLn $ "context" ++ " " ++ unwords (map show programArgs)
262+ putStr "\n"
263+ putStrLn $ "[makePDF] Environment:"
264+ mapM_ print env''
265+ putStr "\n"
266+ putStrLn $ "[makePDF] Contents of " ++ file ++ ":"
267+ B.readFile file >>= B.putStr
268+ putStr "\n"
269+ (exit, out, err) <- pipeProcess (Just env'') "context" programArgs BL.empty
270+ when verbose $ do
271+ B.hPutStr stdout out
272+ B.hPutStr stderr err
273+ putStr "\n"
274+ let pdfFile = replaceExtension file ".pdf"
275+ pdfExists <- doesFileExist pdfFile
276+ mbPdf <- if pdfExists
277+ -- We read PDF as a strict bytestring to make sure that the
278+ -- temp directory is removed on Windows.
279+ -- See https://github.com/jgm/pandoc/issues/1192.
280+ then (Just . B.fromChunks . (:[])) `fmap` BS.readFile pdfFile
281+ else return Nothing
282+ let log' = out <> err
283+ case (exit, mbPdf) of
284+ (ExitFailure _, _) -> do
285+ let logmsg = extractConTeXtMsg log'
286+ return $ Left logmsg
287+ (ExitSuccess, Nothing) -> return $ Left ""
288+ (ExitSuccess, Just pdf) -> return $ Right pdf