git.iko.soy/typeable/pandoc
on master help sign in
Revised LaTeX writer to use templates.

git-svn-id: https://pandoc.googlecode.com/svn/trunk@1675 788f1e2b-df1e-0410-8736-df70ead52e1b

commit2033da8e47d8a3416eed82f0a1ef816236202a68 authorfiddlosopher <fiddlosopher@788f1e2b-df1e-0410-8736-df70ead52e1b> dateThu 31 Dec 2009, 01:08 (17 years ago) parent26ce0d0
3 files changed+90−93
data/headers/LaTeX.header+42 src/Text/Pandoc/Writers/LaTeX.hs+34−85 tests/writer.latex+14−8
data/headers/LaTeX.header+42
@@ -4,5 +4,47 @@
44\usepackage[utf8x]{inputenc}
55\usepackage{listings}
66\lstnewenvironment{code}{\lstset{language=Haskell,basicstyle=\small\ttfamily}}{}
7+\usepackage{fancyvrb}
8+\usepackage{enumerate}
9+\usepackage{array}
10+% This is needed because raggedright in table elements redefines \\:
11+\newcommand{\PreserveBackslash}[1]{\let\temp=\\#1\let\\=\temp}
12+\let\PBS=\PreserveBackslash
13+\usepackage[normalem]{ulem}
14+\newcommand{\textsubscr}[1]{\ensuremath{_{\scriptsize\textrm{#1}}}}
15+\usepackage[breaklinks=true]{hyperref}
16+\usepackage{url}
17+\usepackage{graphicx}
18+
719\setlength{\parindent}{0pt}
820\setlength{\parskip}{6pt plus 2pt minus 1pt}
21+\VerbatimFootnotes % allows verbatim text in footnotes
22+$if(numbersections)$
23+$else$
24+\setcounter{secnumdepth}{0}
25+$endif$
26+
27+$if(title)$
28+\title{$title$}
29+$endif$
30+$if(authors)$
31+\author{$authors$}
32+$endif$
33+$if(date)$
34+\date{$date$}
35+$endif$
36+
37+\begin{document}
38+\maketitle
39+
40+$if(toc)$
41+\tableofcontents
42+$endif$
43+$if(before)$
44+$before$
45+$endif$
46+$body$
47+$if(after)$
48+$after$
49+$endif$
50+\end{document}
src/Text/Pandoc/Writers/LaTeX.hs+34−85
@@ -30,81 +30,45 @@ Conversion of 'Pandoc' format into LaTeX.
3030module Text.Pandoc.Writers.LaTeX ( writeLaTeX ) where
3131import Text.Pandoc.Definition
3232import Text.Pandoc.Shared
33+import Text.Pandoc.Templates
3334import Text.Printf ( printf )
3435import Data.List ( (\\), isSuffixOf, intercalate, intersperse )
3536import Data.Char ( toLower )
36−import qualified Data.Set as S
3737import Control.Monad.State
3838import Control.Monad (liftM)
3939import Text.PrettyPrint.HughesPJ hiding ( Str )
4040
4141data WriterState =
42− WriterState { stIncludes :: S.Set String -- strings to include in header
43− , stInNote :: Bool -- @True@ if we're in a note
42+ WriterState { stInNote :: Bool -- @True@ if we're in a note
4443 , stOLLevel :: Int -- level of ordered list nesting
4544 , stOptions :: WriterOptions -- writer options, so they don't have to be parameter
4645 }
4746
48−-- | Add line to header.
49−addToHeader :: String -> State WriterState ()
50−addToHeader str = do
51− st <- get
52− let includes = stIncludes st
53− put st {stIncludes = S.insert str includes}
54−
5547-- | Convert Pandoc to LaTeX.
5648writeLaTeX :: WriterOptions -> Pandoc -> String
5749writeLaTeX options document =
58− render $ evalState (pandocToLaTeX options document) $
59− WriterState { stIncludes = S.empty, stInNote = False, stOLLevel = 1, stOptions = options }
50+ evalState (pandocToLaTeX options document) $
51+ WriterState { stInNote = False, stOLLevel = 1, stOptions = options }
6052
61−pandocToLaTeX :: WriterOptions -> Pandoc -> State WriterState Doc
62−pandocToLaTeX options (Pandoc meta blocks) = do
63− main <- blockListToLaTeX blocks
64− head' <- if writerStandalone options
65− then latexHeader options meta
66− else return empty
67− let before = if null (writerIncludeBefore options)
68− then empty
69− else text (writerIncludeBefore options)
70− let after = if null (writerIncludeAfter options)
71− then empty
72− else text (writerIncludeAfter options)
73− let body = before $$ main $$ after
74− let toc = if writerTableOfContents options
75− then text "\\tableofcontents\n"
76− else empty
77− let foot = if writerStandalone options
78− then text "\\end{document}"
79− else empty
80− return $ head' $$ toc $$ body $$ foot
81−
82−-- | Insert bibliographic information into LaTeX header.
83−latexHeader :: WriterOptions -- ^ Options, including LaTeX header
84− -> Meta -- ^ Meta with bibliographic information
85− -> State WriterState Doc
86−latexHeader options (Meta title authors date) = do
53+pandocToLaTeX :: WriterOptions -> Pandoc -> State WriterState String
54+pandocToLaTeX options (Pandoc (Meta title authors date) blocks) = do
55+ main <- liftM render $ blockListToLaTeX blocks
8756 titletext <- if null title
88− then return empty
89− else inlineListToLaTeX title >>= return . inCmd "title"
90− headerIncludes <- get >>= return . S.toList . stIncludes
91− let extras = text $ unlines headerIncludes
92− let verbatim = if "\\usepackage{fancyvrb}" `elem` headerIncludes
93− then text "\\VerbatimFootnotes % allows verbatim text in footnotes"
94− else empty
95− let authorstext = text $ "\\author{" ++
96− intercalate "\\\\" (map stringToLaTeX authors) ++ "}"
97− let datetext = if date == ""
98− then empty
99− else text $ "\\date{" ++ stringToLaTeX date ++ "}"
100− let maketitle = if null title then empty else text "\\maketitle"
101− let secnumline = if (writerNumberSections options)
102− then empty
103− else text "\\setcounter{secnumdepth}{0}"
104− let baseHeader = text $ writerHeader options
105− let header = baseHeader $$ extras
106− return $ header $$ secnumline $$ verbatim $$ titletext $$ authorstext $$
107− datetext $$ text "\\begin{document}" $$ maketitle $$ text ""
57+ then return ""
58+ else liftM render $ inlineListToLaTeX title
59+ let context = [ ("before", writerIncludeBefore options)
60+ , ("after", writerIncludeAfter options)
61+ , ("toc", if writerTableOfContents options then "yes" else "")
62+ , ("body", main)
63+ , ("title", titletext)
64+ , ("authors", intercalate "\\\\" $ map stringToLaTeX authors)
65+ , ("date", stringToLaTeX date) ]
66+ let templ = if writerStandalone options
67+ then writerHeader options
68+ else "$if(toc)$\\tableofcontents\n$endif$" ++
69+ "$if(before)$$before$\n$endif$" ++
70+ "$body$$if(after)$$after$\n$endif$"
71+ return $ renderTemplate context templ
10872
10973-- escape things as needed for LaTeX
11074
@@ -150,13 +114,12 @@ blockToLaTeX (BlockQuote lst) = do
150114 return $ text "\\begin{quote}" $$ contents $$ text "\\end{quote}"
151115blockToLaTeX (CodeBlock (_,classes,_) str) = do
152116 st <- get
153− env <- if writerLiterateHaskell (stOptions st) && "haskell" `elem` classes &&
117+ let env = if writerLiterateHaskell (stOptions st) && "haskell" `elem` classes &&
154118 "literate" `elem` classes
155− then return "code"
156− else if stInNote st
157− then do addToHeader "\\usepackage{fancyvrb}"
158− return "Verbatim"
159− else return "verbatim"
119+ then "code"
120+ else if stInNote st
121+ then "Verbatim"
122+ else "verbatim"
160123 return $ text ("\\begin{" ++ env ++ "}\n") <> text str <>
161124 text ("\n\\end{" ++ env ++ "}")
162125blockToLaTeX (RawHtml _) = return empty
@@ -169,12 +132,11 @@ blockToLaTeX (OrderedList (start, numstyle, numdelim) lst) = do
169132 put $ st {stOLLevel = oldlevel + 1}
170133 items <- mapM listItemToLaTeX lst
171134 modify (\s -> s {stOLLevel = oldlevel})
172− exemplar <- if numstyle /= DefaultStyle || numdelim /= DefaultDelim
173− then do addToHeader "\\usepackage{enumerate}"
174− return $ char '[' <>
175− text (head (orderedListMarkers (1, numstyle,
176− numdelim))) <> char ']'
177− else return empty
135+ let exemplar = if numstyle /= DefaultStyle || numdelim /= DefaultDelim
136+ then char '[' <>
137+ text (head (orderedListMarkers (1, numstyle,
138+ numdelim))) <> char ']'
139+ else empty
178140 let resetcounter = if start /= 1 && oldlevel <= 4
179141 then text $ "\\setcounter{enum" ++
180142 map toLower (toRomanNumeral oldlevel) ++
@@ -214,10 +176,6 @@ blockToLaTeX (Table caption aligns widths heads rows) = do
214176 headers $$ text "\\hline" $$ vcat rows' $$
215177 text "\\end{tabular}"
216178 let centered txt = text "\\begin{center}" $$ txt $$ text "\\end{center}"
217− addToHeader $ "\\usepackage{array}\n" ++
218− "% This is needed because raggedright in table elements redefines \\\\:\n" ++
219− "\\newcommand{\\PreserveBackslash}[1]{\\let\\temp=\\\\#1\\let\\\\=\\temp}\n" ++
220− "\\let\\PBS=\\PreserveBackslash"
221179 return $ if isEmpty captionText
222180 then centered tableBody <> char '\n'
223181 else text "\\begin{table}[h]" $$ centered tableBody $$
@@ -276,7 +234,6 @@ inlineToLaTeX (Strong lst) =
276234 inlineListToLaTeX (deVerb lst) >>= return . inCmd "textbf"
277235inlineToLaTeX (Strikeout lst) = do
278236 contents <- inlineListToLaTeX $ deVerb lst
279− addToHeader "\\usepackage[normalem]{ulem}"
280237 return $ inCmd "sout" contents
281238inlineToLaTeX (Superscript lst) =
282239 inlineListToLaTeX (deVerb lst) >>= return . inCmd "textsuperscript"
@@ -284,17 +241,12 @@ inlineToLaTeX (Subscript lst) = do
284241 contents <- inlineListToLaTeX $ deVerb lst
285242 -- oddly, latex includes \textsuperscript but not \textsubscript
286243 -- so we have to define it (using a different name so as not to conflict with memoir class):
287− addToHeader "\\newcommand{\\textsubscr}[1]{\\ensuremath{_{\\scriptsize\\textrm{#1}}}}"
288244 return $ inCmd "textsubscr" contents
289245inlineToLaTeX (SmallCaps lst) =
290246 inlineListToLaTeX (deVerb lst) >>= return . inCmd "textsc"
291247inlineToLaTeX (Cite _ lst) =
292248 inlineListToLaTeX lst
293249inlineToLaTeX (Code str) = do
294− st <- get
295− if stInNote st
296− then do addToHeader "\\usepackage{fancyvrb}"
297− else return ()
298250 let chr = ((enumFromTo '!' '~') \\ str) !! 0
299251 return $ text $ "\\verb" ++ [chr] ++ str ++ [chr]
300252inlineToLaTeX (Quoted SingleQuote lst) = do
@@ -327,16 +279,13 @@ inlineToLaTeX (HtmlInline _) = return empty
327279inlineToLaTeX (LineBreak) = return $ text "\\\\"
328280inlineToLaTeX Space = return $ char ' '
329281inlineToLaTeX (Link txt (src, _)) = do
330− addToHeader "\\usepackage[breaklinks=true]{hyperref}"
331282 case txt of
332283 [Code x] | x == src -> -- autolink
333− do addToHeader "\\usepackage{url}"
334− return $ text $ "\\url{" ++ x ++ "}"
284+ do return $ text $ "\\url{" ++ x ++ "}"
335285 _ -> do contents <- inlineListToLaTeX $ deVerb txt
336286 return $ text ("\\href{" ++ src ++ "}{") <> contents <>
337287 char '}'
338−inlineToLaTeX (Image _ (source, _)) = do
339− addToHeader "\\usepackage{graphicx}"
288+inlineToLaTeX (Image _ (source, _)) =
340289 return $ text $ "\\includegraphics{" ++ source ++ "}"
341290inlineToLaTeX (Note contents) = do
342291 st <- get
tests/writer.latex+14−8
@@ -4,22 +4,27 @@
44\usepackage[utf8x]{inputenc}
55\usepackage{listings}
66\lstnewenvironment{code}{\lstset{language=Haskell,basicstyle=\small\ttfamily}}{}
7−\setlength{\parindent}{0pt}
8−\setlength{\parskip}{6pt plus 2pt minus 1pt}
9−
7+\usepackage{fancyvrb}
8+\usepackage{enumerate}
9+\usepackage{array}
10+% This is needed because raggedright in table elements redefines \\:
11+\newcommand{\PreserveBackslash}[1]{\let\temp=\\#1\let\\=\temp}
12+\let\PBS=\PreserveBackslash
13+\usepackage[normalem]{ulem}
1014\newcommand{\textsubscr}[1]{\ensuremath{_{\scriptsize\textrm{#1}}}}
1115\usepackage[breaklinks=true]{hyperref}
12−\usepackage[normalem]{ulem}
13−\usepackage{enumerate}
14−\usepackage{fancyvrb}
15−\usepackage{graphicx}
1616\usepackage{url}
17+\usepackage{graphicx}
1718
18−\setcounter{secnumdepth}{0}
19+\setlength{\parindent}{0pt}
20+\setlength{\parskip}{6pt plus 2pt minus 1pt}
1921\VerbatimFootnotes % allows verbatim text in footnotes
22+\setcounter{secnumdepth}{0}
23+
2024\title{Pandoc Test Suite}
2125\author{John MacFarlane\\Anonymous}
2226\date{July 17, 2006}
27+
2328\begin{document}
2429\maketitle
2530
@@ -847,3 +852,4 @@ This paragraph should not be part of the note, as it is not
847852indented.
848853
849854\end{document}
855+