git.iko.soy/typeable/pandoc
on master help sign in
LaTeX writer: fix error with line breaks after empty content.

LaTeX requires something before a line break, so we insert a `~` if no printable content has yet been emitted. Closes #2874.

commitee160d7c4cc912554fe0a1c7ff9fb802e9e72b64 authorJohn MacFarlane <jgm@berkeley.edu> dateTue 25 Apr 2017, 15:00 (9 years ago) parentd17f0da
2 files changed+42−19
src/Text/Pandoc/Writers/LaTeX.hs+28−19 test/command/2874.md+14
src/Text/Pandoc/Writers/LaTeX.hs+28−19
@@ -81,6 +81,7 @@ data WriterState =
8181 , stInternalLinks :: [String] -- list of internal link targets
8282 , stUsesEuro :: Bool -- true if euro symbol used
8383 , stBeamer :: Bool -- produce beamer
84+ , stEmptyLine :: Bool -- true if no content on line
8485 }
8586
8687startingState :: WriterOptions -> WriterState
@@ -107,7 +108,8 @@ startingState options = WriterState {
107108 , stIncremental = writerIncremental options
108109 , stInternalLinks = []
109110 , stUsesEuro = False
110− , stBeamer = False }
111+ , stBeamer = False
112+ , stEmptyLine = True }
111113
112114-- | Convert Pandoc to LaTeX.
113115writeLaTeX :: PandocMonad m => WriterOptions -> Pandoc -> m String
@@ -680,7 +682,8 @@ toColDescriptor align =
680682 AlignDefault -> "l"
681683
682684blockListToLaTeX :: PandocMonad m => [Block] -> LW m Doc
683−blockListToLaTeX lst = vsep `fmap` mapM blockToLaTeX lst
685+blockListToLaTeX lst =
686+ vsep `fmap` mapM (\b -> setEmptyLine True >> blockToLaTeX b) lst
684687
685688tableRowToLaTeX :: PandocMonad m
686689 => Bool
@@ -882,7 +885,7 @@ inlineListToLaTeX :: PandocMonad m
882885 => [Inline] -- ^ Inlines to convert
883886 -> LW m Doc
884887inlineListToLaTeX lst =
885− mapM inlineToLaTeX (fixBreaks $ fixLineInitialSpaces lst)
888+ mapM inlineToLaTeX (fixLineInitialSpaces lst)
886889 >>= return . hcat
887890 -- nonbreaking spaces (~) in LaTeX don't work after line breaks,
888891 -- so we turn nbsps after hard breaks to \hspace commands.
@@ -894,14 +897,6 @@ inlineListToLaTeX lst =
894897 fixNbsps s = let (ys,zs) = span (=='\160') s
895898 in replicate (length ys) hspace ++ [Str zs]
896899 hspace = RawInline "latex" "\\hspace*{0.333em}"
897− -- linebreaks after blank lines cause problems:
898− fixBreaks [] = []
899− fixBreaks ys@(LineBreak : LineBreak : _) =
900− case span (== LineBreak) ys of
901− (lbs, rest) -> RawInline "latex"
902− ("\\\\[" ++ show (length lbs) ++
903− "\\baselineskip]") : fixBreaks rest
904− fixBreaks (y:ys) = y : fixBreaks ys
905900
906901isQuoted :: Inline -> Bool
907902isQuoted (Quoted _ _) = True
@@ -927,9 +922,9 @@ inlineToLaTeX (Span (id',classes,kvs) ils) = do
927922 return $ (if null id'
928923 then empty
929924 else "\\protect" <> linkAnchor) <>
930− if null cmds
931− then braces contents
932− else foldr inCmd contents cmds
925+ (if null cmds
926+ then braces contents
927+ else foldr inCmd contents cmds)
933928inlineToLaTeX (Emph lst) =
934929 inlineListToLaTeX lst >>= return . inCmd "emph"
935930inlineToLaTeX (Strong lst) =
@@ -1007,18 +1002,27 @@ inlineToLaTeX (Quoted qt lst) = do
10071002 if isEnabled Ext_smart opts
10081003 then char '`' <> inner <> char '\''
10091004 else char '\x2018' <> inner <> char '\x2019'
1010−inlineToLaTeX (Str str) = liftM text $ stringToLaTeX TextString str
1011−inlineToLaTeX (Math InlineMath str) =
1005+inlineToLaTeX (Str str) = do
1006+ setEmptyLine False
1007+ liftM text $ stringToLaTeX TextString str
1008+inlineToLaTeX (Math InlineMath str) = do
1009+ setEmptyLine False
10121010 return $ "\\(" <> text str <> "\\)"
1013−inlineToLaTeX (Math DisplayMath str) =
1011+inlineToLaTeX (Math DisplayMath str) = do
1012+ setEmptyLine False
10141013 return $ "\\[" <> text str <> "\\]"
10151014inlineToLaTeX il@(RawInline f str)
10161015 | f == Format "latex" || f == Format "tex"
1017− = return $ text str
1016+ = do
1017+ setEmptyLine False
1018+ return $ text str
10181019 | otherwise = do
10191020 report $ InlineNotRendered il
10201021 return empty
1021−inlineToLaTeX (LineBreak) = return $ "\\\\" <> cr
1022+inlineToLaTeX (LineBreak) = do
1023+ emptyLine <- gets stEmptyLine
1024+ setEmptyLine True
1025+ return $ (if emptyLine then "~" else "") <> "\\\\" <> cr
10221026inlineToLaTeX SoftBreak = do
10231027 wrapText <- gets (writerWrapText . stOptions)
10241028 case wrapText of
@@ -1048,6 +1052,7 @@ inlineToLaTeX (Link _ txt (src, _)) =
10481052 return $ text ("\\href{" ++ src' ++ "}{") <>
10491053 contents <> char '}'
10501054inlineToLaTeX (Image attr _ (source, _)) = do
1055+ setEmptyLine False
10511056 modify $ \s -> s{ stGraphics = True }
10521057 opts <- gets stOptions
10531058 let showDim dir = let d = text (show dir) <> "="
@@ -1073,6 +1078,7 @@ inlineToLaTeX (Image attr _ (source, _)) = do
10731078 (if inHeading then "\\protect\\includegraphics" else "\\includegraphics") <>
10741079 dims <> braces (text source'')
10751080inlineToLaTeX (Note contents) = do
1081+ setEmptyLine False
10761082 inMinipage <- gets stInMinipage
10771083 modify (\s -> s{stInNote = True})
10781084 contents' <- blockListToLaTeX contents
@@ -1100,6 +1106,9 @@ protectCode (x@(Code _ _) : xs) = ltx "\\mbox{" : x : ltx "}" : xs
11001106 where ltx = RawInline (Format "latex")
11011107protectCode (x : xs) = x : protectCode xs
11021108
1109+setEmptyLine :: PandocMonad m => Bool -> LW m ()
1110+setEmptyLine b = modify $ \st -> st{ stEmptyLine = b }
1111+
11031112citationsToNatbib :: PandocMonad m => [Citation] -> LW m Doc
11041113citationsToNatbib (one:[])
11051114 = citeCommand c p s k
test/command/2874.mdnew file+14
@@ -0,0 +1,14 @@
1+```
2+% pandoc -f html -t latex
3+<a></a>
4+<br/>
5+^D
6+{}~\\
7+```
8+
9+```
10+% pandoc -f html -t latex
11+<a name="foo"></a><br/>
12+^D
13+\protect\hypertarget{foo}{}{}~\\
14+```