From d9a70d2eaf30a3fe4836f8b69a0c32181d84bd00 Mon Sep 17 00:00:00 2001 From: John MacFarlane Date: Thu, 25 Jan 2024 09:41:47 -0800 Subject: Add some kerns where needed between quotes in LaTeX output. Closes #9371. --- src/Text/Pandoc/Writers/LaTeX.hs | 44 +++++++++++++++++++++++++++++----------- test/command/9371.md | 30 +++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 12 deletions(-) create mode 100644 test/command/9371.md diff --git a/src/Text/Pandoc/Writers/LaTeX.hs b/src/Text/Pandoc/Writers/LaTeX.hs index 943f50ef9..4426c8da1 100644 --- a/src/Text/Pandoc/Writers/LaTeX.hs +++ b/src/Text/Pandoc/Writers/LaTeX.hs @@ -775,7 +775,8 @@ inlineListToLaTeX :: PandocMonad m => [Inline] -- ^ Inlines to convert -> LW m (Doc Text) inlineListToLaTeX lst = hcat <$> - mapM inlineToLaTeX (fixLineInitialSpaces . fixInitialLineBreaks $ lst) + mapM inlineToLaTeX + (addKerns . fixLineInitialSpaces . fixInitialLineBreaks $ lst) -- nonbreaking spaces (~) in LaTeX don't work after line breaks, -- so we insert a strut: this is mostly used in verse. where fixLineInitialSpaces [] = [] @@ -790,6 +791,21 @@ inlineListToLaTeX lst = hcat <$> RawInline (Format "latex") "\\hfill\\break\n" : fixInitialLineBreaks xs fixInitialLineBreaks xs = xs + addKerns [] = [] + addKerns (Str s : q@Quoted{} : rest) + | isQuote (T.takeEnd 1 s) = + Str s : RawInline (Format "latex") "\\," : addKerns (q:rest) + addKerns (q@Quoted{} : Str s : rest) + | isQuote (T.take 1 s) = + q : RawInline (Format "latex") "\\," : addKerns (Str s : rest) + addKerns (x:xs) = x : addKerns xs + isQuote "\"" = True + isQuote "'" = True + isQuote "\x2018" = True + isQuote "\x2019" = True + isQuote "\x201C" = True + isQuote "\x201D" = True + isQuote _ = False -- | Convert inline element to LaTeX inlineToLaTeX :: PandocMonad m @@ -928,13 +944,21 @@ inlineToLaTeX (Quoted qt lst) = do DoubleQuote -> "\\enquote" <> braces contents SingleQuote -> "\\enquote*" <> braces contents else do - let s1 = if not (null lst) && isQuoted (head lst) - then "\\," - else empty - let s2 = if not (null lst) && isQuoted (last lst) - then "\\," - else empty - let inner = s1 <> contents <> s2 + let endsWithQuote xs = + case reverse xs of + Quoted{}:_ -> True + Span _ ys : _ -> endsWithQuote ys + Str s:_ -> T.takeEnd 1 s == "'" + _ -> False + let beginsWithQuote xs = + case xs of + Quoted{}:_ -> True + Span _ ys : _ -> beginsWithQuote ys + Str s:_ -> T.take 1 s == "`" + _ -> False + let inner = (if beginsWithQuote lst then "\\," else mempty) + <> contents + <> (if endsWithQuote lst then "\\," else mempty) return $ case qt of DoubleQuote -> if isEnabled Ext_smart opts @@ -944,10 +968,6 @@ inlineToLaTeX (Quoted qt lst) = do if isEnabled Ext_smart opts then char '`' <> inner <> char '\'' else char '\x2018' <> inner <> char '\x2019' - where - isQuoted (Span _ (x:_)) = isQuoted x - isQuoted (Quoted _ _) = True - isQuoted _ = False inlineToLaTeX (Str str) = do setEmptyLine False liftM literal $ stringToLaTeX TextString str diff --git a/test/command/9371.md b/test/command/9371.md new file mode 100644 index 000000000..bb34f87a6 --- /dev/null +++ b/test/command/9371.md @@ -0,0 +1,30 @@ +``` +% pandoc -t latex +"'In this case (A), + +I get a kern to separate the quotes,' he said." + +"'Also in this case (B), I get a kern,' he added." + +"'But in this case (C), there is no kern,' + +he continued." + +"He concluded, + +'Nor in this case (D) is there a kern.'" +^D +``\,'In this case (A), + +I get a kern to separate the quotes,' he said.'' + +``\,`Also in this case (B), I get a kern,' he added.'' + +``\,`But in this case (C), there is no kern,' + +he continued.'' + +``He concluded, + +`Nor in this case (D) is there a kern.'\,'' +``` -- cgit v1.2.3