@@ -39,6 +39,7 @@ import Text.Pandoc.Shared
39import Text.Pandoc.Writers.Shared
39import Text.Pandoc.Writers.Shared
40import Text.Pandoc.Options
40import Text.Pandoc.Options
41import Text.Pandoc.Templates
41import Text.Pandoc.Templates
42+import Text.Pandoc.Logging
42import Text.Printf ( printf )
43import Text.Printf ( printf )
43import Network.URI ( isURI, unEscapeString )
44import Network.URI ( isURI, unEscapeString )
44import Data.Aeson (object, (.=), FromJSON)
45import Data.Aeson (object, (.=), FromJSON)
@@ -57,7 +58,7 @@ import Text.Pandoc.Slides
57import Text.Pandoc.Highlighting (highlight, styleToLaTeX,
58import Text.Pandoc.Highlighting (highlight, styleToLaTeX,
58 formatLaTeXInline, formatLaTeXBlock,
59 formatLaTeXInline, formatLaTeXBlock,
59 toListingsLanguage)
60 toListingsLanguage)
60−import Text.Pandoc.Class (PandocMonad)
61+import Text.Pandoc.Class (PandocMonad, report)
62data WriterState =
63data WriterState =
63 WriterState { stInNote :: Bool -- true if we're in a note
64 WriterState { stInNote :: Bool -- true if we're in a note
@@ -110,17 +111,20 @@ startingState options = WriterState {
111-- | Convert Pandoc to LaTeX.
112-- | Convert Pandoc to LaTeX.
112writeLaTeX :: PandocMonad m => WriterOptions -> Pandoc -> m String
113writeLaTeX :: PandocMonad m => WriterOptions -> Pandoc -> m String
113−writeLaTeX options document = return $
114+writeLaTeX options document =
114− evalState (pandocToLaTeX options document) $
115+ evalStateT (pandocToLaTeX options document) $
115 startingState options
116 startingState options
117-- | Convert Pandoc to LaTeX Beamer.
118-- | Convert Pandoc to LaTeX Beamer.
118writeBeamer :: PandocMonad m => WriterOptions -> Pandoc -> m String
119writeBeamer :: PandocMonad m => WriterOptions -> Pandoc -> m String
119−writeBeamer options document = return $
120+writeBeamer options document =
120− evalState (pandocToLaTeX options document) $
121+ evalStateT (pandocToLaTeX options document) $
121 (startingState options){ stBeamer = True }
122 (startingState options){ stBeamer = True }
124+type LW m = StateT WriterState m
126+pandocToLaTeX :: PandocMonad m
123−pandocToLaTeX :: WriterOptions -> Pandoc -> State WriterState String
127+ => WriterOptions -> Pandoc -> LW m String
124pandocToLaTeX options (Pandoc meta blocks) = do
128pandocToLaTeX options (Pandoc meta blocks) = do
125 -- Strip off final 'references' header if --natbib or --biblatex
129 -- Strip off final 'references' header if --natbib or --biblatex
126 let method = writerCiteMethod options
130 let method = writerCiteMethod options
@@ -279,7 +283,7 @@ pandocToLaTeX options (Pandoc meta blocks) = do
279 Just tpl -> renderTemplate' tpl context'
283 Just tpl -> renderTemplate' tpl context'
281-- | Convert Elements to LaTeX
285-- | Convert Elements to LaTeX
282−elementToLaTeX :: WriterOptions -> Element -> State WriterState Doc
286+elementToLaTeX :: PandocMonad m => WriterOptions -> Element -> LW m Doc
283elementToLaTeX _ (Blk block) = blockToLaTeX block
287elementToLaTeX _ (Blk block) = blockToLaTeX block
284elementToLaTeX opts (Sec level _ (id',classes,_) title' elements) = do
288elementToLaTeX opts (Sec level _ (id',classes,_) title' elements) = do
285 modify $ \s -> s{stInHeading = True}
289 modify $ \s -> s{stInHeading = True}
@@ -294,7 +298,7 @@ data StringContext = TextString
294 deriving (Eq)
298 deriving (Eq)
296-- escape things as needed for LaTeX
300-- escape things as needed for LaTeX
297−stringToLaTeX :: StringContext -> String -> State WriterState String
301+stringToLaTeX :: PandocMonad m => StringContext -> String -> LW m String
298stringToLaTeX _ [] = return ""
302stringToLaTeX _ [] = return ""
299stringToLaTeX ctx (x:xs) = do
303stringToLaTeX ctx (x:xs) = do
300 opts <- gets stOptions
304 opts <- gets stOptions
@@ -339,7 +343,7 @@ stringToLaTeX ctx (x:xs) = do
339 '\x2013' | ligatures -> "--" ++ rest
343 '\x2013' | ligatures -> "--" ++ rest
340 _ -> x : rest
344 _ -> x : rest
342−toLabel :: String -> State WriterState String
346+toLabel :: PandocMonad m => String -> LW m String
343toLabel z = go `fmap` stringToLaTeX URLString z
347toLabel z = go `fmap` stringToLaTeX URLString z
344 where go [] = ""
348 where go [] = ""
345 go (x:xs)
349 go (x:xs)
@@ -351,14 +355,14 @@ toLabel z = go `fmap` stringToLaTeX URLString z
351inCmd :: String -> Doc -> Doc
355inCmd :: String -> Doc -> Doc
352inCmd cmd contents = char '\\' <> text cmd <> braces contents
356inCmd cmd contents = char '\\' <> text cmd <> braces contents
354−toSlides :: [Block] -> State WriterState [Block]
358+toSlides :: PandocMonad m => [Block] -> LW m [Block]
355toSlides bs = do
359toSlides bs = do
356 opts <- gets stOptions
360 opts <- gets stOptions
357 let slideLevel = fromMaybe (getSlideLevel bs) $ writerSlideLevel opts
361 let slideLevel = fromMaybe (getSlideLevel bs) $ writerSlideLevel opts
358 let bs' = prepSlides slideLevel bs
362 let bs' = prepSlides slideLevel bs
359 concat `fmap` (mapM (elementToBeamer slideLevel) $ hierarchicalize bs')
363 concat `fmap` (mapM (elementToBeamer slideLevel) $ hierarchicalize bs')
361−elementToBeamer :: Int -> Element -> State WriterState [Block]
365+elementToBeamer :: PandocMonad m => Int -> Element -> LW m [Block]
362elementToBeamer _slideLevel (Blk b) = return [b]
366elementToBeamer _slideLevel (Blk b) = return [b]
363elementToBeamer slideLevel (Sec lvl _num (ident,classes,kvs) tit elts)
367elementToBeamer slideLevel (Sec lvl _num (ident,classes,kvs) tit elts)
364 | lvl > slideLevel = do
368 | lvl > slideLevel = do
@@ -408,8 +412,9 @@ isLineBreakOrSpace Space = True
408isLineBreakOrSpace _ = False
412isLineBreakOrSpace _ = False
410-- | Convert Pandoc block element to LaTeX.
414-- | Convert Pandoc block element to LaTeX.
415+blockToLaTeX :: PandocMonad m
411−blockToLaTeX :: Block -- ^ Block to convert
416+ => Block -- ^ Block to convert
412− -> State WriterState Doc
417+ -> LW m Doc
413blockToLaTeX Null = return empty
418blockToLaTeX Null = return empty
414blockToLaTeX (Div (identifier,classes,kvs) bs) = do
419blockToLaTeX (Div (identifier,classes,kvs) bs) = do
415 beamer <- gets stBeamer
420 beamer <- gets stBeamer
@@ -541,10 +546,12 @@ blockToLaTeX (CodeBlock (identifier,classes,keyvalAttr) str) = do
541 | not (null classes) && isJust (writerHighlightStyle opts)
546 | not (null classes) && isJust (writerHighlightStyle opts)
542 -> highlightedCodeBlock
547 -> highlightedCodeBlock
543 | otherwise -> rawCodeBlock
548 | otherwise -> rawCodeBlock
544−blockToLaTeX (RawBlock f x)
549+blockToLaTeX b@(RawBlock f x)
545 | f == Format "latex" || f == Format "tex"
550 | f == Format "latex" || f == Format "tex"
546 = return $ text x
551 = return $ text x
553+ report $ BlockNotRendered b
547− | otherwise = return empty
554+ return empty
548blockToLaTeX (BulletList []) = return empty -- otherwise latex error
555blockToLaTeX (BulletList []) = return empty -- otherwise latex error
549blockToLaTeX (BulletList lst) = do
556blockToLaTeX (BulletList lst) = do
550 incremental <- gets stIncremental
557 incremental <- gets stIncremental
@@ -652,14 +659,15 @@ toColDescriptor align =
652 AlignCenter -> "c"
659 AlignCenter -> "c"
653 AlignDefault -> "l"
660 AlignDefault -> "l"
655−blockListToLaTeX :: [Block] -> State WriterState Doc
662+blockListToLaTeX :: PandocMonad m => [Block] -> LW m Doc
656blockListToLaTeX lst = vsep `fmap` mapM blockToLaTeX lst
663blockListToLaTeX lst = vsep `fmap` mapM blockToLaTeX lst
658−tableRowToLaTeX :: Bool
665+tableRowToLaTeX :: PandocMonad m
659 -> [Alignment]
667 -> [Alignment]
660 -> [Double]
668 -> [Double]
661 -> [[Block]]
669 -> [[Block]]
662− -> State WriterState Doc
670+ -> LW m Doc
663tableRowToLaTeX header aligns widths cols = do
671tableRowToLaTeX header aligns widths cols = do
664 -- scale factor compensates for extra space between columns
672 -- scale factor compensates for extra space between columns
665 -- so the whole table isn't larger than columnwidth
673 -- so the whole table isn't larger than columnwidth
@@ -700,8 +708,8 @@ displayMathToInline :: Inline -> Inline
700displayMathToInline (Math DisplayMath x) = Math InlineMath x
708displayMathToInline (Math DisplayMath x) = Math InlineMath x
701displayMathToInline x = x
709displayMathToInline x = x
703−tableCellToLaTeX :: Bool -> (Double, Alignment, [Block])
711+tableCellToLaTeX :: PandocMonad m => Bool -> (Double, Alignment, [Block])
704− -> State WriterState Doc
712+ -> LW m Doc
705tableCellToLaTeX _ (0, _, blocks) =
713tableCellToLaTeX _ (0, _, blocks) =
706 blockListToLaTeX $ walk fixLineBreaks $ walk displayMathToInline blocks
714 blockListToLaTeX $ walk fixLineBreaks $ walk displayMathToInline blocks
707tableCellToLaTeX header (width, align, blocks) = do
715tableCellToLaTeX header (width, align, blocks) = do
@@ -734,7 +742,7 @@ notesToLaTeX ns = (case length ns of
734 $ map (\x -> "\\footnotetext" <> braces x)
742 $ map (\x -> "\\footnotetext" <> braces x)
735 $ reverse ns)
743 $ reverse ns)
737−listItemToLaTeX :: [Block] -> State WriterState Doc
745+listItemToLaTeX :: PandocMonad m => [Block] -> LW m Doc
738listItemToLaTeX lst
746listItemToLaTeX lst
739 -- we need to put some text before a header if it's the first
747 -- we need to put some text before a header if it's the first
740 -- element in an item. This will look ugly in LaTeX regardless, but
748 -- element in an item. This will look ugly in LaTeX regardless, but
@@ -744,7 +752,7 @@ listItemToLaTeX lst
744 | otherwise = blockListToLaTeX lst >>= return . (text "\\item" $$) .
752 | otherwise = blockListToLaTeX lst >>= return . (text "\\item" $$) .
747−defListItemToLaTeX :: ([Inline], [[Block]]) -> State WriterState Doc
755+defListItemToLaTeX :: PandocMonad m => ([Inline], [[Block]]) -> LW m Doc
748defListItemToLaTeX (term, defs) = do
756defListItemToLaTeX (term, defs) = do
749 term' <- inlineListToLaTeX term
757 term' <- inlineListToLaTeX term
750 -- put braces around term if it contains an internal link,
758 -- put braces around term if it contains an internal link,
@@ -762,11 +770,12 @@ defListItemToLaTeX (term, defs) = do
762 "\\item" <> brackets term'' $$ def'
770 "\\item" <> brackets term'' $$ def'
764-- | Craft the section header, inserting the secton reference, if supplied.
772-- | Craft the section header, inserting the secton reference, if supplied.
773+sectionHeader :: PandocMonad m
765−sectionHeader :: Bool -- True for unnumbered
774+ => Bool -- True for unnumbered
766 -> [Char]
775 -> [Char]
768 -> [Inline]
777 -> [Inline]
769− -> State WriterState Doc
778+ -> LW m Doc
770sectionHeader unnumbered ident level lst = do
779sectionHeader unnumbered ident level lst = do
771 txt <- inlineListToLaTeX lst
780 txt <- inlineListToLaTeX lst
772 plain <- stringToLaTeX TextString $ concatMap stringify lst
781 plain <- stringToLaTeX TextString $ concatMap stringify lst
@@ -831,7 +840,7 @@ sectionHeader unnumbered ident level lst = do
831 braces txtNoNotes
840 braces txtNoNotes
832 else empty
841 else empty
834−hypertarget :: String -> Doc -> State WriterState Doc
843+hypertarget :: PandocMonad m => String -> Doc -> LW m Doc
835hypertarget ident x = do
844hypertarget ident x = do
836 ref <- text `fmap` toLabel ident
845 ref <- text `fmap` toLabel ident
837 internalLinks <- gets stInternalLinks
846 internalLinks <- gets stInternalLinks
@@ -842,15 +851,16 @@ hypertarget ident x = do
842 <> braces x
851 <> braces x
845−labelFor :: String -> State WriterState Doc
854+labelFor :: PandocMonad m => String -> LW m Doc
846labelFor "" = return empty
855labelFor "" = return empty
847labelFor ident = do
856labelFor ident = do
848 ref <- text `fmap` toLabel ident
857 ref <- text `fmap` toLabel ident
849 return $ text "\\label" <> braces ref
858 return $ text "\\label" <> braces ref
851-- | Convert list of inline elements to LaTeX.
860-- | Convert list of inline elements to LaTeX.
861+inlineListToLaTeX :: PandocMonad m
852−inlineListToLaTeX :: [Inline] -- ^ Inlines to convert
862+ => [Inline] -- ^ Inlines to convert
853− -> State WriterState Doc
863+ -> LW m Doc
854inlineListToLaTeX lst =
864inlineListToLaTeX lst =
855 mapM inlineToLaTeX (fixBreaks $ fixLineInitialSpaces lst)
865 mapM inlineToLaTeX (fixBreaks $ fixLineInitialSpaces lst)
856 >>= return . hcat
866 >>= return . hcat
@@ -878,8 +888,9 @@ isQuoted (Quoted _ _) = True
878isQuoted _ = False
888isQuoted _ = False
880-- | Convert inline element to LaTeX
890-- | Convert inline element to LaTeX
891+inlineToLaTeX :: PandocMonad m
881−inlineToLaTeX :: Inline -- ^ Inline to convert
892+ => Inline -- ^ Inline to convert
882− -> State WriterState Doc
893+ -> LW m Doc
883inlineToLaTeX (Span (id',classes,kvs) ils) = do
894inlineToLaTeX (Span (id',classes,kvs) ils) = do
884 ref <- toLabel id'
895 ref <- toLabel id'
885 let linkAnchor = if null id'
896 let linkAnchor = if null id'
@@ -980,10 +991,12 @@ inlineToLaTeX (Math InlineMath str) =
980 return $ "\\(" <> text str <> "\\)"
991 return $ "\\(" <> text str <> "\\)"
981inlineToLaTeX (Math DisplayMath str) =
992inlineToLaTeX (Math DisplayMath str) =
982 return $ "\\[" <> text str <> "\\]"
993 return $ "\\[" <> text str <> "\\]"
983−inlineToLaTeX (RawInline f str)
994+inlineToLaTeX il@(RawInline f str)
984 | f == Format "latex" || f == Format "tex"
995 | f == Format "latex" || f == Format "tex"
985 = return $ text str
996 = return $ text str
998+ report $ InlineNotRendered il
986− | otherwise = return empty
999+ return empty
987inlineToLaTeX (LineBreak) = return $ "\\\\" <> cr
1000inlineToLaTeX (LineBreak) = return $ "\\\\" <> cr
988inlineToLaTeX SoftBreak = do
1001inlineToLaTeX SoftBreak = do
989 wrapText <- gets (writerWrapText . stOptions)
1002 wrapText <- gets (writerWrapText . stOptions)
@@ -1066,7 +1079,7 @@ protectCode (x@(Code _ _) : xs) = ltx "\\mbox{" : x : ltx "}" : xs
1066 where ltx = RawInline (Format "latex")
1079 where ltx = RawInline (Format "latex")
1067protectCode (x : xs) = x : protectCode xs
1080protectCode (x : xs) = x : protectCode xs
1069−citationsToNatbib :: [Citation] -> State WriterState Doc
1082+citationsToNatbib :: PandocMonad m => [Citation] -> LW m Doc
1070citationsToNatbib (one:[])
1083citationsToNatbib (one:[])
1071 = citeCommand c p s k
1084 = citeCommand c p s k
@@ -1113,12 +1126,14 @@ citationsToNatbib cits = do
1113 SuppressAuthor -> citeCommand "citeyear" p s k
1126 SuppressAuthor -> citeCommand "citeyear" p s k
1114 NormalCitation -> citeCommand "citealp" p s k
1127 NormalCitation -> citeCommand "citealp" p s k
1129+citeCommand :: PandocMonad m
1116−citeCommand :: String -> [Inline] -> [Inline] -> String -> State WriterState Doc
1130+ => String -> [Inline] -> [Inline] -> String -> LW m Doc
1117citeCommand c p s k = do
1131citeCommand c p s k = do
1118 args <- citeArguments p s k
1132 args <- citeArguments p s k
1119 return $ text ("\\" ++ c) <> args
1133 return $ text ("\\" ++ c) <> args
1135+citeArguments :: PandocMonad m
1121−citeArguments :: [Inline] -> [Inline] -> String -> State WriterState Doc
1136+ => [Inline] -> [Inline] -> String -> LW m Doc
1122citeArguments p s k = do
1137citeArguments p s k = do
1123 let s' = case s of
1138 let s' = case s of
1124 (Str (x:[]) : r) | isPunctuation x -> dropWhile (== Space) r
1139 (Str (x:[]) : r) | isPunctuation x -> dropWhile (== Space) r
@@ -1132,7 +1147,7 @@ citeArguments p s k = do
1132 (_ , _ ) -> brackets pdoc <> brackets sdoc
1147 (_ , _ ) -> brackets pdoc <> brackets sdoc
1133 return $ optargs <> braces (text k)
1148 return $ optargs <> braces (text k)
1135−citationsToBiblatex :: [Citation] -> State WriterState Doc
1150+citationsToBiblatex :: PandocMonad m => [Citation] -> LW m Doc
1136citationsToBiblatex (one:[])
1151citationsToBiblatex (one:[])
1137 = citeCommand cmd p s k
1152 = citeCommand cmd p s k