@@ -18,10 +18,9 @@ module Text.Pandoc.Writers.LaTeX (
18 writeLaTeX
18 writeLaTeX
19 , writeBeamer
19 , writeBeamer
21−import Control.Applicative ((<|>))
22import Control.Monad.State.Strict
21import Control.Monad.State.Strict
23−import Data.Char (isAlphaNum, isAscii, isDigit, isLetter, isSpace, ord)
22+import Data.Char (isDigit)
24−import Data.List (intersperse, nubBy, (\\), uncons)
23+import Data.List (intersperse, nubBy, (\\))
25import Data.Maybe (catMaybes, fromMaybe, isJust, mapMaybe, isNothing)
24import Data.Maybe (catMaybes, fromMaybe, isJust, mapMaybe, isNothing)
26import qualified Data.Map as M
25import qualified Data.Map as M
27import Data.Text (Text)
26import Data.Text (Text)
@@ -33,7 +32,7 @@ import Text.Pandoc.BCP47 (Lang (..), getLang, renderLang)
33import Text.Pandoc.Class.PandocMonad (PandocMonad, report, toLang)
32import Text.Pandoc.Class.PandocMonad (PandocMonad, report, toLang)
34import Text.Pandoc.Definition
33import Text.Pandoc.Definition
35import Text.Pandoc.Highlighting (formatLaTeXBlock, formatLaTeXInline, highlight,
34import Text.Pandoc.Highlighting (formatLaTeXBlock, formatLaTeXInline, highlight,
36− styleToLaTeX, toListingsLanguage)
35+ styleToLaTeX)
37import Text.Pandoc.ImageSize
36import Text.Pandoc.ImageSize
38import Text.Pandoc.Logging
37import Text.Pandoc.Logging
39import Text.Pandoc.Options
38import Text.Pandoc.Options
@@ -46,11 +45,12 @@ import Text.Pandoc.Writers.LaTeX.Table (tableToLaTeX)
46import Text.Pandoc.Writers.LaTeX.Citation (citationsToNatbib,
45import Text.Pandoc.Writers.LaTeX.Citation (citationsToNatbib,
47 citationsToBiblatex)
46 citationsToBiblatex)
48import Text.Pandoc.Writers.LaTeX.Types (LW, WriterState (..), startingState)
47import Text.Pandoc.Writers.LaTeX.Types (LW, WriterState (..), startingState)
49−import Text.Pandoc.Writers.LaTeX.Lang (toPolyglossiaEnv, toPolyglossia,
48+import Text.Pandoc.Writers.LaTeX.Lang (toPolyglossia, toBabel)
50− toBabel)
49+import Text.Pandoc.Writers.LaTeX.Util (stringToLaTeX, StringContext(..),
51+ wrapDiv, hypertarget, labelFor,
52+ getListingsLanguage, mbBraced)
51import Text.Pandoc.Writers.Shared
53import Text.Pandoc.Writers.Shared
52−import Text.Printf (printf)
53−import qualified Data.Text.Normalize as Normalize
54import qualified Text.Pandoc.Writers.AnnotatedTable as Ann
54import qualified Text.Pandoc.Writers.AnnotatedTable as Ann
56-- | Convert Pandoc to LaTeX.
56-- | Convert Pandoc to LaTeX.
@@ -244,152 +244,6 @@ pandocToLaTeX options (Pandoc meta blocks) = do
244 Nothing -> main
244 Nothing -> main
245 Just tpl -> renderTemplate tpl context'
245 Just tpl -> renderTemplate tpl context'
247−data StringContext = TextString
252−-- escape things as needed for LaTeX
253−stringToLaTeX :: PandocMonad m => StringContext -> Text -> LW m Text
254−stringToLaTeX context zs = do
255− opts <- gets stOptions
257− foldr (go opts context) mempty $ T.unpack $
258− if writerPreferAscii opts
259− then Normalize.normalize Normalize.NFD zs
262− go :: WriterOptions -> StringContext -> Char -> String -> String
264− let ligatures = isEnabled Ext_smart opts && ctx == TextString
265− isUrl = ctx == URLString
267− if writerPreferAscii opts && ctx == TextString
268− then uncons xs >>= \(c,_) -> lookupAccent c
273− cmd <> "{" <> s <> "}" <> drop 1 xs -- drop combining accent
278− cmd <> "{" <> [c] <> "}" <> drop 1 xs -- drop combining accent
285− | isSpace c -> cs <> "{}" <> xs
288− _ -> cs <> "{}" <> xs
291− '`':_ -> cs <> "\\," <> xs -- add thin space
292− '\'':_ -> cs <> "\\," <> xs -- add thin space
295− '?' | ligatures -> -- avoid ?` ligature
297− '`':_ -> emits "?{}"
299− '!' | ligatures -> -- avoid !` ligature
301− '`':_ -> emits "!{}"
305− '`' | ctx == CodeString -> emitcseq "\\textasciigrave"
306− '$' | not isUrl -> emits "\\$"
309− '_' | not isUrl -> emits "\\_"
311− '-' | not isUrl -> case xs of
312− -- prevent adjacent hyphens from forming ligatures
313− ('-':_) -> emits "-\\/"
315− '~' | not isUrl -> emitcseq "\\textasciitilde"
316− '^' -> emits "\\^{}"
317− '\\'| isUrl -> emitc '/' -- NB. / works as path sep even on Windows
318− | otherwise -> emitcseq "\\textbackslash"
319− '|' | not isUrl -> emitcseq "\\textbar"
320− '<' -> emitcseq "\\textless"
321− '>' -> emitcseq "\\textgreater"
322− '[' -> emits "{[}" -- to avoid interpretation as
323− ']' -> emits "{]}" -- optional arguments
324− '\'' | ctx == CodeString -> emitcseq "\\textquotesingle"
326− '\x200B' -> emits "\\hspace{0pt}" -- zero-width space
327− '\x202F' -> emits "\\,"
328− '\x2026' -> emitcseq "\\ldots"
329− '\x2018' | ligatures -> emitquote "`"
330− '\x2019' | ligatures -> emitquote "'"
331− '\x201C' | ligatures -> emitquote "``"
332− '\x201D' | ligatures -> emitquote "''"
333− '\x2014' | ligatures -> emits "---"
334− '\x2013' | ligatures -> emits "--"
335− _ | writerPreferAscii opts
337− 'ı' -> emitcseq "\\i"
338− 'ȷ' -> emitcseq "\\j"
339− 'å' -> emitcseq "\\aa"
340− 'Å' -> emitcseq "\\AA"
341− 'ß' -> emitcseq "\\ss"
342− 'ø' -> emitcseq "\\o"
343− 'Ø' -> emitcseq "\\O"
344− 'Ł' -> emitcseq "\\L"
345− 'ł' -> emitcseq "\\l"
346− 'æ' -> emitcseq "\\ae"
347− 'Æ' -> emitcseq "\\AE"
348− 'œ' -> emitcseq "\\oe"
349− 'Œ' -> emitcseq "\\OE"
350− '£' -> emitcseq "\\pounds"
351− '€' -> emitcseq "\\euro"
352− '©' -> emitcseq "\\copyright"
354− | otherwise -> emitc x
356−lookupAccent :: Char -> Maybe String
357−lookupAccent '\779' = Just "\\H"
358−lookupAccent '\768' = Just "\\`"
359−lookupAccent '\769' = Just "\\'"
360−lookupAccent '\770' = Just "\\^"
361−lookupAccent '\771' = Just "\\~"
362−lookupAccent '\776' = Just "\\\""
363−lookupAccent '\775' = Just "\\."
364−lookupAccent '\772' = Just "\\="
365−lookupAccent '\781' = Just "\\|"
366−lookupAccent '\817' = Just "\\b"
367−lookupAccent '\807' = Just "\\c"
368−lookupAccent '\783' = Just "\\G"
369−lookupAccent '\777' = Just "\\h"
370−lookupAccent '\803' = Just "\\d"
371−lookupAccent '\785' = Just "\\f"
372−lookupAccent '\778' = Just "\\r"
373−lookupAccent '\865' = Just "\\t"
374−lookupAccent '\782' = Just "\\U"
375−lookupAccent '\780' = Just "\\v"
376−lookupAccent '\774' = Just "\\u"
377−lookupAccent '\808' = Just "\\k"
378−lookupAccent '\8413' = Just "\\textcircled"
379−lookupAccent _ = Nothing
381−toLabel :: PandocMonad m => Text -> LW m Text
382−toLabel z = go `fmap` stringToLaTeX URLString z
384− go = T.concatMap $ \x -> case x of
385− _ | (isLetter x || isDigit x) && isAscii x -> T.singleton x
386− | x `elemText` "_-+=:;." -> T.singleton x
387− | otherwise -> T.pack $ "ux" <> printf "%x" (ord x)
389−-- | Puts contents into LaTeX command.
390−inCmd :: Text -> Doc Text -> Doc Text
391−inCmd cmd contents = char '\\' <> literal cmd <> braces contents
393toSlides :: PandocMonad m => [Block] -> LW m [Block]
247toSlides :: PandocMonad m => [Block] -> LW m [Block]
394toSlides bs = do
248toSlides bs = do
395 opts <- gets stOptions
249 opts <- gets stOptions
@@ -854,91 +708,6 @@ sectionHeader classes ident level lst = do
854 braces txtNoNotes
708 braces txtNoNotes
855 else empty
709 else empty
857−mapAlignment :: Text -> Text
858−mapAlignment a = case a of
860− "top-baseline" -> "t"
865−wrapDiv :: PandocMonad m => Attr -> Doc Text -> LW m (Doc Text)
866−wrapDiv (_,classes,kvs) t = do
867− beamer <- gets stBeamer
868− let align dir txt = inCmd "begin" dir $$ txt $$ inCmd "end" dir
869− lang <- toLang $ lookup "lang" kvs
870− let wrapColumns = if beamer && "columns" `elem` classes
872− let valign = maybe "T" mapAlignment (lookup "align" kvs)
873− totalwidth = maybe [] (\x -> ["totalwidth=" <> x])
874− (lookup "totalwidth" kvs)
875− onlytextwidth = filter ("onlytextwidth" ==) classes
876− options = text $ T.unpack $ T.intercalate "," $
877− valign : totalwidth ++ onlytextwidth
878− in inCmd "begin" "columns" <> brackets options
880− $$ inCmd "end" "columns"
882− wrapColumn = if beamer && "column" `elem` classes
886− (brackets . text . T.unpack . mapAlignment)
887− (lookup "align" kvs)
888− w = maybe "0.48" fromPct (lookup "width" kvs)
889− in inCmd "begin" "column" <>
891− braces (literal w <> "\\textwidth")
893− $$ inCmd "end" "column"
897− Just (ds, '%') -> case safeRead ds of
898− Just digits -> showFl (digits / 100 :: Double)
901− wrapDir = case lookup "dir" kvs of
902− Just "rtl" -> align "RTL"
903− Just "ltr" -> align "LTR"
905− wrapLang txt = case lang of
906− Just lng -> let (l, o) = toPolyglossiaEnv lng
909− else brackets $ literal o
910− in inCmd "begin" (literal l) <> ops
911− $$ blankline <> txt <> blankline
912− $$ inCmd "end" (literal l)
914− return $ wrapColumns . wrapColumn . wrapDir . wrapLang $ t
916−hypertarget :: PandocMonad m => Bool -> Text -> Doc Text -> LW m (Doc Text)
917−hypertarget _ "" x = return x
918−hypertarget addnewline ident x = do
919− ref <- literal `fmap` toLabel ident
920− return $ text "\\hypertarget"
922− <> braces ((if addnewline && not (isEmpty x)
926−labelFor :: PandocMonad m => Text -> LW m (Doc Text)
927−labelFor "" = return empty
929− ref <- literal `fmap` toLabel ident
930− return $ text "\\label" <> braces ref
932−-- Determine listings language from list of class attributes.
933−getListingsLanguage :: [Text] -> Maybe Text
934−getListingsLanguage xs
935− = foldr ((<|>) . toListingsLanguage) Nothing xs
937−mbBraced :: Text -> Text
938−mbBraced x = if not (T.all isAlphaNum x)
939− then "{" <> x <> "}"
942-- | Convert list of inline elements to LaTeX.
711-- | Convert list of inline elements to LaTeX.
943inlineListToLaTeX :: PandocMonad m
712inlineListToLaTeX :: PandocMonad m
944 => [Inline] -- ^ Inlines to convert
713 => [Inline] -- ^ Inlines to convert
@@ -963,10 +732,6 @@ inlineListToLaTeX lst = hcat <$>
963 fixInitialLineBreaks xs
732 fixInitialLineBreaks xs
964 fixInitialLineBreaks xs = xs
733 fixInitialLineBreaks xs = xs
966−isQuoted :: Inline -> Bool
967−isQuoted (Quoted _ _) = True
970-- | Convert inline element to LaTeX
735-- | Convert inline element to LaTeX
971inlineToLaTeX :: PandocMonad m
736inlineToLaTeX :: PandocMonad m
972 => Inline -- ^ Inline to convert
737 => Inline -- ^ Inline to convert
@@ -1102,6 +867,9 @@ inlineToLaTeX (Quoted qt lst) = do
1102 if isEnabled Ext_smart opts
867 if isEnabled Ext_smart opts
1103 then char '`' <> inner <> char '\''
868 then char '`' <> inner <> char '\''
1104 else char '\x2018' <> inner <> char '\x2019'
869 else char '\x2018' <> inner <> char '\x2019'
871+ isQuoted (Quoted _ _) = True
1105inlineToLaTeX (Str str) = do
873inlineToLaTeX (Str str) = do
1106 setEmptyLine False
874 setEmptyLine False
1107 liftM literal $ stringToLaTeX TextString str
875 liftM literal $ stringToLaTeX TextString str