aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfiddlosopher <fiddlosopher@788f1e2b-df1e-0410-8736-df70ead52e1b>2009-12-31 01:08:56 +0000
committerfiddlosopher <fiddlosopher@788f1e2b-df1e-0410-8736-df70ead52e1b>2009-12-31 01:08:56 +0000
commit2033da8e47d8a3416eed82f0a1ef816236202a68 (patch)
tree8653cc7da7813d1a6449b485950ac2c805283156
parent26ce0d04ec461f10c92597bb054763b3820a125a (diff)
downloadpandoc-2033da8e47d8a3416eed82f0a1ef816236202a68.tar.gz
Revised LaTeX writer to use templates.
git-svn-id: https://pandoc.googlecode.com/svn/trunk@1675 788f1e2b-df1e-0410-8736-df70ead52e1b
-rw-r--r--data/headers/LaTeX.header42
-rw-r--r--src/Text/Pandoc/Writers/LaTeX.hs119
-rw-r--r--tests/writer.latex22
3 files changed, 90 insertions, 93 deletions
diff --git a/data/headers/LaTeX.header b/data/headers/LaTeX.header
index f6f1d4e7c..d41a60276 100644
--- a/data/headers/LaTeX.header
+++ b/data/headers/LaTeX.header
@@ -4,5 +4,47 @@
\usepackage[utf8x]{inputenc}
\usepackage{listings}
\lstnewenvironment{code}{\lstset{language=Haskell,basicstyle=\small\ttfamily}}{}
+\usepackage{fancyvrb}
+\usepackage{enumerate}
+\usepackage{array}
+% This is needed because raggedright in table elements redefines \\:
+\newcommand{\PreserveBackslash}[1]{\let\temp=\\#1\let\\=\temp}
+\let\PBS=\PreserveBackslash
+\usepackage[normalem]{ulem}
+\newcommand{\textsubscr}[1]{\ensuremath{_{\scriptsize\textrm{#1}}}}
+\usepackage[breaklinks=true]{hyperref}
+\usepackage{url}
+\usepackage{graphicx}
+
\setlength{\parindent}{0pt}
\setlength{\parskip}{6pt plus 2pt minus 1pt}
+\VerbatimFootnotes % allows verbatim text in footnotes
+$if(numbersections)$
+$else$
+\setcounter{secnumdepth}{0}
+$endif$
+
+$if(title)$
+\title{$title$}
+$endif$
+$if(authors)$
+\author{$authors$}
+$endif$
+$if(date)$
+\date{$date$}
+$endif$
+
+\begin{document}
+\maketitle
+
+$if(toc)$
+\tableofcontents
+$endif$
+$if(before)$
+$before$
+$endif$
+$body$
+$if(after)$
+$after$
+$endif$
+\end{document}
diff --git a/src/Text/Pandoc/Writers/LaTeX.hs b/src/Text/Pandoc/Writers/LaTeX.hs
index af23f9285..d550482fe 100644
--- a/src/Text/Pandoc/Writers/LaTeX.hs
+++ b/src/Text/Pandoc/Writers/LaTeX.hs
@@ -30,81 +30,45 @@ Conversion of 'Pandoc' format into LaTeX.
module Text.Pandoc.Writers.LaTeX ( writeLaTeX ) where
import Text.Pandoc.Definition
import Text.Pandoc.Shared
+import Text.Pandoc.Templates
import Text.Printf ( printf )
import Data.List ( (\\), isSuffixOf, intercalate, intersperse )
import Data.Char ( toLower )
-import qualified Data.Set as S
import Control.Monad.State
import Control.Monad (liftM)
import Text.PrettyPrint.HughesPJ hiding ( Str )
data WriterState =
- WriterState { stIncludes :: S.Set String -- strings to include in header
- , stInNote :: Bool -- @True@ if we're in a note
+ WriterState { stInNote :: Bool -- @True@ if we're in a note
, stOLLevel :: Int -- level of ordered list nesting
, stOptions :: WriterOptions -- writer options, so they don't have to be parameter
}
--- | Add line to header.
-addToHeader :: String -> State WriterState ()
-addToHeader str = do
- st <- get
- let includes = stIncludes st
- put st {stIncludes = S.insert str includes}
-
-- | Convert Pandoc to LaTeX.
writeLaTeX :: WriterOptions -> Pandoc -> String
writeLaTeX options document =
- render $ evalState (pandocToLaTeX options document) $
- WriterState { stIncludes = S.empty, stInNote = False, stOLLevel = 1, stOptions = options }
+ evalState (pandocToLaTeX options document) $
+ WriterState { stInNote = False, stOLLevel = 1, stOptions = options }
-pandocToLaTeX :: WriterOptions -> Pandoc -> State WriterState Doc
-pandocToLaTeX options (Pandoc meta blocks) = do
- main <- blockListToLaTeX blocks
- head' <- if writerStandalone options
- then latexHeader options meta
- else return empty
- let before = if null (writerIncludeBefore options)
- then empty
- else text (writerIncludeBefore options)
- let after = if null (writerIncludeAfter options)
- then empty
- else text (writerIncludeAfter options)
- let body = before $$ main $$ after
- let toc = if writerTableOfContents options
- then text "\\tableofcontents\n"
- else empty
- let foot = if writerStandalone options
- then text "\\end{document}"
- else empty
- return $ head' $$ toc $$ body $$ foot
-
--- | Insert bibliographic information into LaTeX header.
-latexHeader :: WriterOptions -- ^ Options, including LaTeX header
- -> Meta -- ^ Meta with bibliographic information
- -> State WriterState Doc
-latexHeader options (Meta title authors date) = do
+pandocToLaTeX :: WriterOptions -> Pandoc -> State WriterState String
+pandocToLaTeX options (Pandoc (Meta title authors date) blocks) = do
+ main <- liftM render $ blockListToLaTeX blocks
titletext <- if null title
- then return empty
- else inlineListToLaTeX title >>= return . inCmd "title"
- headerIncludes <- get >>= return . S.toList . stIncludes
- let extras = text $ unlines headerIncludes
- let verbatim = if "\\usepackage{fancyvrb}" `elem` headerIncludes
- then text "\\VerbatimFootnotes % allows verbatim text in footnotes"
- else empty
- let authorstext = text $ "\\author{" ++
- intercalate "\\\\" (map stringToLaTeX authors) ++ "}"
- let datetext = if date == ""
- then empty
- else text $ "\\date{" ++ stringToLaTeX date ++ "}"
- let maketitle = if null title then empty else text "\\maketitle"
- let secnumline = if (writerNumberSections options)
- then empty
- else text "\\setcounter{secnumdepth}{0}"
- let baseHeader = text $ writerHeader options
- let header = baseHeader $$ extras
- return $ header $$ secnumline $$ verbatim $$ titletext $$ authorstext $$
- datetext $$ text "\\begin{document}" $$ maketitle $$ text ""
+ then return ""
+ else liftM render $ inlineListToLaTeX title
+ let context = [ ("before", writerIncludeBefore options)
+ , ("after", writerIncludeAfter options)
+ , ("toc", if writerTableOfContents options then "yes" else "")
+ , ("body", main)
+ , ("title", titletext)
+ , ("authors", intercalate "\\\\" $ map stringToLaTeX authors)
+ , ("date", stringToLaTeX date) ]
+ let templ = if writerStandalone options
+ then writerHeader options
+ else "$if(toc)$\\tableofcontents\n$endif$" ++
+ "$if(before)$$before$\n$endif$" ++
+ "$body$$if(after)$$after$\n$endif$"
+ return $ renderTemplate context templ
-- escape things as needed for LaTeX
@@ -150,13 +114,12 @@ blockToLaTeX (BlockQuote lst) = do
return $ text "\\begin{quote}" $$ contents $$ text "\\end{quote}"
blockToLaTeX (CodeBlock (_,classes,_) str) = do
st <- get
- env <- if writerLiterateHaskell (stOptions st) && "haskell" `elem` classes &&
+ let env = if writerLiterateHaskell (stOptions st) && "haskell" `elem` classes &&
"literate" `elem` classes
- then return "code"
- else if stInNote st
- then do addToHeader "\\usepackage{fancyvrb}"
- return "Verbatim"
- else return "verbatim"
+ then "code"
+ else if stInNote st
+ then "Verbatim"
+ else "verbatim"
return $ text ("\\begin{" ++ env ++ "}\n") <> text str <>
text ("\n\\end{" ++ env ++ "}")
blockToLaTeX (RawHtml _) = return empty
@@ -169,12 +132,11 @@ blockToLaTeX (OrderedList (start, numstyle, numdelim) lst) = do
put $ st {stOLLevel = oldlevel + 1}
items <- mapM listItemToLaTeX lst
modify (\s -> s {stOLLevel = oldlevel})
- exemplar <- if numstyle /= DefaultStyle || numdelim /= DefaultDelim
- then do addToHeader "\\usepackage{enumerate}"
- return $ char '[' <>
- text (head (orderedListMarkers (1, numstyle,
- numdelim))) <> char ']'
- else return empty
+ let exemplar = if numstyle /= DefaultStyle || numdelim /= DefaultDelim
+ then char '[' <>
+ text (head (orderedListMarkers (1, numstyle,
+ numdelim))) <> char ']'
+ else empty
let resetcounter = if start /= 1 && oldlevel <= 4
then text $ "\\setcounter{enum" ++
map toLower (toRomanNumeral oldlevel) ++
@@ -214,10 +176,6 @@ blockToLaTeX (Table caption aligns widths heads rows) = do
headers $$ text "\\hline" $$ vcat rows' $$
text "\\end{tabular}"
let centered txt = text "\\begin{center}" $$ txt $$ text "\\end{center}"
- addToHeader $ "\\usepackage{array}\n" ++
- "% This is needed because raggedright in table elements redefines \\\\:\n" ++
- "\\newcommand{\\PreserveBackslash}[1]{\\let\\temp=\\\\#1\\let\\\\=\\temp}\n" ++
- "\\let\\PBS=\\PreserveBackslash"
return $ if isEmpty captionText
then centered tableBody <> char '\n'
else text "\\begin{table}[h]" $$ centered tableBody $$
@@ -276,7 +234,6 @@ inlineToLaTeX (Strong lst) =
inlineListToLaTeX (deVerb lst) >>= return . inCmd "textbf"
inlineToLaTeX (Strikeout lst) = do
contents <- inlineListToLaTeX $ deVerb lst
- addToHeader "\\usepackage[normalem]{ulem}"
return $ inCmd "sout" contents
inlineToLaTeX (Superscript lst) =
inlineListToLaTeX (deVerb lst) >>= return . inCmd "textsuperscript"
@@ -284,17 +241,12 @@ inlineToLaTeX (Subscript lst) = do
contents <- inlineListToLaTeX $ deVerb lst
-- oddly, latex includes \textsuperscript but not \textsubscript
-- so we have to define it (using a different name so as not to conflict with memoir class):
- addToHeader "\\newcommand{\\textsubscr}[1]{\\ensuremath{_{\\scriptsize\\textrm{#1}}}}"
return $ inCmd "textsubscr" contents
inlineToLaTeX (SmallCaps lst) =
inlineListToLaTeX (deVerb lst) >>= return . inCmd "textsc"
inlineToLaTeX (Cite _ lst) =
inlineListToLaTeX lst
inlineToLaTeX (Code str) = do
- st <- get
- if stInNote st
- then do addToHeader "\\usepackage{fancyvrb}"
- else return ()
let chr = ((enumFromTo '!' '~') \\ str) !! 0
return $ text $ "\\verb" ++ [chr] ++ str ++ [chr]
inlineToLaTeX (Quoted SingleQuote lst) = do
@@ -327,16 +279,13 @@ inlineToLaTeX (HtmlInline _) = return empty
inlineToLaTeX (LineBreak) = return $ text "\\\\"
inlineToLaTeX Space = return $ char ' '
inlineToLaTeX (Link txt (src, _)) = do
- addToHeader "\\usepackage[breaklinks=true]{hyperref}"
case txt of
[Code x] | x == src -> -- autolink
- do addToHeader "\\usepackage{url}"
- return $ text $ "\\url{" ++ x ++ "}"
+ do return $ text $ "\\url{" ++ x ++ "}"
_ -> do contents <- inlineListToLaTeX $ deVerb txt
return $ text ("\\href{" ++ src ++ "}{") <> contents <>
char '}'
-inlineToLaTeX (Image _ (source, _)) = do
- addToHeader "\\usepackage{graphicx}"
+inlineToLaTeX (Image _ (source, _)) =
return $ text $ "\\includegraphics{" ++ source ++ "}"
inlineToLaTeX (Note contents) = do
st <- get
diff --git a/tests/writer.latex b/tests/writer.latex
index 0e9cd5dfc..09fdc4077 100644
--- a/tests/writer.latex
+++ b/tests/writer.latex
@@ -4,22 +4,27 @@
\usepackage[utf8x]{inputenc}
\usepackage{listings}
\lstnewenvironment{code}{\lstset{language=Haskell,basicstyle=\small\ttfamily}}{}
-\setlength{\parindent}{0pt}
-\setlength{\parskip}{6pt plus 2pt minus 1pt}
-
+\usepackage{fancyvrb}
+\usepackage{enumerate}
+\usepackage{array}
+% This is needed because raggedright in table elements redefines \\:
+\newcommand{\PreserveBackslash}[1]{\let\temp=\\#1\let\\=\temp}
+\let\PBS=\PreserveBackslash
+\usepackage[normalem]{ulem}
\newcommand{\textsubscr}[1]{\ensuremath{_{\scriptsize\textrm{#1}}}}
\usepackage[breaklinks=true]{hyperref}
-\usepackage[normalem]{ulem}
-\usepackage{enumerate}
-\usepackage{fancyvrb}
-\usepackage{graphicx}
\usepackage{url}
+\usepackage{graphicx}
-\setcounter{secnumdepth}{0}
+\setlength{\parindent}{0pt}
+\setlength{\parskip}{6pt plus 2pt minus 1pt}
\VerbatimFootnotes % allows verbatim text in footnotes
+\setcounter{secnumdepth}{0}
+
\title{Pandoc Test Suite}
\author{John MacFarlane\\Anonymous}
\date{July 17, 2006}
+
\begin{document}
\maketitle
@@ -847,3 +852,4 @@ This paragraph should not be part of the note, as it is not
indented.
\end{document}
+