git.iko.soy/typeable/pandoc
on master help sign in
Allow use of ConTeXt to generate PDFs.

pandoc my.md -t context -o my.pdf will now create a PDF using ConTeXt rather than LaTeX. Closes #2463.

commit8193ebcd99a1f11e2ab74600ee403f6b100dac32 authorJohn MacFarlane <jgm@berkeley.edu> dateTue 20 Oct 2015, 08:15 (11 years ago) parent82d2719
3 files changed+91−14
README+17−6 pandoc.hs+10−6 src/Text/Pandoc/PDF.hs+64−2
README+17−6
@@ -24,7 +24,7 @@ markup], [Haddock markup], [OPML], [Emacs Org mode], [DocBook],
2424[FictionBook2], [Textile], [groff man] pages, [Emacs Org mode],
2525[AsciiDoc], [InDesign ICML], and [Slidy], [Slideous], [DZSlides],
2626[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.
2828
2929Pandoc's enhanced version of markdown includes syntax for [footnotes],
3030[tables], flexible [ordered lists], [definition lists], [fenced code blocks],
@@ -167,7 +167,7 @@ Creating a PDF
167167--------------
168168
169169To 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:
171171
172172 pandoc test.txt -o test.pdf
173173
@@ -189,7 +189,12 @@ be used for [smart punctuation] if added to the template. The
189189optionally be used for [citation rendering]. These are included with
190190all recent versions of [TeX Live].
191191
192−PDF output can be controlled using [variables for LaTeX].
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+
196+PDF output can be controlled using [variables for LaTeX]
197+or [variables for ConTeXt].
193198
194199[`amsfonts`]: https://ctan.org/pkg/amsfonts
195200[`amsmath`]: https://ctan.org/pkg/amsmath
@@ -992,9 +997,9 @@ customize the `default.opendocument` template. For `pdf` output,
992997customize the `default.latex` template.
993998
994999Templates contain *variables*, which allow for the inclusion of
995−arbitrary information at any point in the file. Variables may be set
996−within the document using [YAML metadata blocks][Extension: `yaml_metadata_block`].
997−They may also be set at the
1000+arbitrary information at any point in the file. Variables may be set
1001+within the document using [YAML metadata blocks][Extension:
1002+`yaml_metadata_block`]. They may also be set at the
9981003command line using the `-V/--variable` option: variables set in this
9991004way override metadata fields with the same name.
10001005
@@ -1201,6 +1206,12 @@ LaTeX variables are used when [creating a PDF].
12011206[`mathpazo`]: https://ctan.org/pkg/mathpazo
12021207[LaTeX font encodings]: https://ctan.org/pkg/encguide
12031208
1209+Variables for ConTeXt
1210+---------------------
1211+
1212+`papersize`
1213+: paper size (defaults to `letter`)
1214+
12041215Variables for man pages
12051216-----------------------
12061217
pandoc.hs+10−6
@@ -1173,6 +1173,7 @@ main = do
11731173
11741174 let laTeXOutput = "latex" `isPrefixOf` writerName' ||
11751175 "beamer" `isPrefixOf` writerName'
1176+ let conTeXtOutput = "context" `isPrefixOf` writerName'
11761177
11771178 writer <- if ".lua" `isSuffixOf` writerName'
11781179 -- note: use non-lowercased version writerName
@@ -1256,7 +1257,7 @@ main = do
12561257 _ -> Nothing
12571258
12581259 let readerOpts = def{ readerSmart = smart || (texLigatures &&
1259− (laTeXOutput || "context" `isPrefixOf` writerName'))
1260+ (laTeXOutput || conTeXtOutput))
12601261 , readerStandalone = standalone'
12611262 , readerParseRaw = parseRaw
12621263 , readerColumns = columns
@@ -1367,17 +1368,20 @@ main = do
13671368 PureStringWriter f
13681369 | pdfOutput -> do
13691370 -- make sure writer is latex or beamer
1370− unless laTeXOutput $
1371+ unless (laTeXOutput || conTeXtOutput) $
13711372 err 47 $ "cannot produce pdf output with " ++ writerName' ++
13721373 " writer"
13731374
1375+ let texprog = if conTeXtOutput
1376+ then "context"
1377+ else latexEngine
13741378 -- check for latex program
1375− mbLatex <- findExecutable latexEngine
1379+ mbLatex <- findExecutable texprog
13761380 when (mbLatex == Nothing) $
1377− err 41 $ latexEngine ++ " not found. " ++
1378− latexEngine ++ " is needed for pdf output."
1381+ err 41 $ texprog ++ " not found. " ++
1382+ texprog ++ " is needed for pdf output."
13791383
1380− res <- makePDF latexEngine f writerOptions doc'
1384+ res <- makePDF texprog f writerOptions doc'
13811385 case res of
13821386 Right pdf -> writeBinary pdf
13831387 Left err' -> do
src/Text/Pandoc/PDF.hs+64−2
@@ -47,7 +47,7 @@ import Data.Maybe (fromMaybe)
4747import qualified Text.Pandoc.UTF8 as UTF8
4848import Text.Pandoc.Definition
4949import Text.Pandoc.Walk (walkM)
50−import Text.Pandoc.Shared (fetchItem', warn, withTempDir)
50+import Text.Pandoc.Shared (fetchItem', warn, withTempDir, inDirectory)
5151import Text.Pandoc.Options (WriterOptions(..))
5252import Text.Pandoc.MIME (extensionFromMimeType, getMimeType)
5353import Text.Pandoc.Process (pipeProcess)
@@ -71,7 +71,9 @@ makePDF program writer opts doc = withTempDir "tex2pdf." $ \tmpdir -> do
7171 doc' <- handleImages opts tmpdir doc
7272 let source = writer opts doc'
7373 args = writerLaTeXArgs opts
74− tex2pdf' (writerVerbose opts) args tmpdir program source
74+ case program of
75+ "context" -> context2pdf (writerVerbose opts) tmpdir source
76+ _ -> tex2pdf' (writerVerbose opts) args tmpdir program source
7577
7678handleImages :: WriterOptions
7779 -> FilePath -- ^ temp dir to store images
@@ -166,6 +168,14 @@ extractMsg log' = do
166168 then log'
167169 else BC.unlines (msg'' ++ lineno)
168170
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+
169179-- running tex programs
170180
171181-- 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
224234 else return Nothing
225235 return (exit, out <> err, pdf)
226236
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