From e3dfb2646d950a6c468835cca5da759cf098ee75 Mon Sep 17 00:00:00 2001 From: John MacFarlane Date: Fri, 30 Dec 2011 14:30:45 -0800 Subject: Add support for internal links to LaTeX writer. Based on a patch by B. Scott Michel. --- src/Text/Pandoc/Writers/LaTeX.hs | 77 ++++++++++++++++++++++++++-------------- 1 file changed, 50 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/Text/Pandoc/Writers/LaTeX.hs b/src/Text/Pandoc/Writers/LaTeX.hs index fa715df25..164d350be 100644 --- a/src/Text/Pandoc/Writers/LaTeX.hs +++ b/src/Text/Pandoc/Writers/LaTeX.hs @@ -109,9 +109,9 @@ pandocToLaTeX options (Pandoc (Meta title authors date) blocks) = do blocks'' <- if writerBeamer options then toSlides blocks' else return blocks' - body <- blockListToLaTeX blocks'' + body <- mapM (elementToLaTeX options) $ hierarchicalize blocks'' biblioTitle <- liftM (render colwidth) $ inlineListToLaTeX lastHeader - let main = render colwidth body + let main = render colwidth $ cat body st <- get let biblioFiles = intercalate "," $ map dropExtension $ writerBiblioFiles options citecontext = case writerCiteMethod options of @@ -154,8 +154,15 @@ pandocToLaTeX options (Pandoc (Meta title authors date) blocks) = do then renderTemplate context template else main --- escape things as needed for LaTeX +-- | Convert Elements to LaTeX +elementToLaTeX :: WriterOptions -> Element -> State WriterState Doc +elementToLaTeX _ (Blk block) = blockToLaTeX block +elementToLaTeX opts (Sec level _ id' title' elements) = do + header' <- sectionHeader id' level title' + innerContents <- mapM (elementToLaTeX opts) elements + return $ cat (header' : innerContents) +-- escape things as needed for LaTeX stringToLaTeX :: Bool -> String -> String stringToLaTeX isUrl = escapeStringUsing latexEscapes where latexEscapes = backslashEscapes "{}$%&_" ++ @@ -335,30 +342,7 @@ blockToLaTeX (DefinitionList lst) = do return $ text ("\\begin{description}" ++ inc) $$ vcat items $$ "\\end{description}" blockToLaTeX HorizontalRule = return $ "\\begin{center}\\rule{3in}{0.4pt}\\end{center}" $$ blankline -blockToLaTeX (Header level lst) = do - txt <- inlineListToLaTeX lst - let noNote (Note _) = Str "" - noNote x = x - let lstNoNotes = bottomUp noNote lst - -- footnotes in sections don't work unless you specify an optional - -- argument: \section[mysec]{mysec\footnote{blah}} - optional <- if lstNoNotes == lst - then return empty - else do - res <- inlineListToLaTeX lstNoNotes - return $ char '[' <> res <> char ']' - let stuffing = optional <> char '{' <> txt <> char '}' - book <- liftM stBook get - let level' = if book then level - 1 else level - let headerWith x y = text x <> y $$ blankline - return $ case level' of - 0 -> headerWith "\\chapter" stuffing - 1 -> headerWith "\\section" stuffing - 2 -> headerWith "\\subsection" stuffing - 3 -> headerWith "\\subsubsection" stuffing - 4 -> headerWith "\\paragraph" stuffing - 5 -> headerWith "\\subparagraph" stuffing - _ -> txt $$ blankline +blockToLaTeX (Header level lst) = sectionHeader "" level lst blockToLaTeX (Table caption aligns widths heads rows) = do modify $ \s -> s{ stInTable = True, stTableNotes = [] } headers <- if all null heads @@ -426,6 +410,45 @@ defListItemToLaTeX (term, defs) = do def' <- liftM vsep $ mapM blockListToLaTeX defs return $ "\\item" <> brackets term' $$ def' +-- | Craft the section header, inserting the secton reference, if supplied. +sectionHeader :: [Char] + -> Int + -> [Inline] + -> State WriterState Doc +sectionHeader ref level lst = do + txt <- inlineListToLaTeX lst + let noNote (Note _) = Str "" + noNote x = x + let lstNoNotes = bottomUp noNote lst + -- footnotes in sections don't work unless you specify an optional + -- argument: \section[mysec]{mysec\footnote{blah}} + optional <- if lstNoNotes == lst + then return empty + else do + res <- inlineListToLaTeX lstNoNotes + return $ char '[' <> res <> char ']' + let stuffing = optional <> char '{' <> txt <> char '}' + book <- liftM stBook get + let level' = if book then level - 1 else level + let refLabel lab = (if (not . null) ref + then text "\\hyperdef" + <> braces empty + <> braces (text ref) + <> braces (lab <> text "\\label" + <> braces (text ref)) + else lab) + $$ blankline + let headerWith x y = refLabel $ text x <> y + return $ case level' of + 0 -> headerWith "\\chapter" stuffing + 1 -> headerWith "\\section" stuffing + 2 -> headerWith "\\subsection" stuffing + 3 -> headerWith "\\subsubsection" stuffing + 4 -> headerWith "\\paragraph" stuffing + 5 -> headerWith "\\subparagraph" stuffing + _ -> txt $$ blankline + + -- | Convert list of inline elements to LaTeX. inlineListToLaTeX :: [Inline] -- ^ Inlines to convert -> State WriterState Doc -- cgit v1.2.3