@@ -1,3 +1,6 @@
2+{-# LANGUAGE FlexibleInstances #-}
3+{-# LANGUAGE MultiParamTypeClasses #-}
1{-# LANGUAGE OverloadedStrings #-}
4{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE PatternGuards #-}
5{-# LANGUAGE PatternGuards #-}
3{-# LANGUAGE ScopedTypeVariables #-}
6{-# LANGUAGE ScopedTypeVariables #-}
@@ -18,58 +21,50 @@ module Text.Pandoc.Readers.LaTeX ( readLaTeX,
18 applyMacros,
21 applyMacros,
19 rawLaTeXInline,
22 rawLaTeXInline,
20 rawLaTeXBlock,
23 rawLaTeXBlock,
21− inlineCommand
24+ inlineCommand,
24import Control.Applicative (many, optional, (<|>))
29import Control.Applicative (many, optional, (<|>))
25import Control.Monad
30import Control.Monad
26import Control.Monad.Except (throwError)
31import Control.Monad.Except (throwError)
27−import Data.Char (isDigit, isLetter, isAlphaNum, toUpper, chr)
32+import Data.Char (isDigit, isLetter, toUpper, chr)
28import Data.Default
33import Data.Default
29import Data.List (intercalate)
34import Data.List (intercalate)
30import qualified Data.Map as M
35import qualified Data.Map as M
31import Data.Maybe (fromMaybe, maybeToList)
36import Data.Maybe (fromMaybe, maybeToList)
32import qualified Data.Set as Set
37import qualified Data.Set as Set
38+import qualified Data.Sequence as Seq
33import Data.Text (Text)
39import Data.Text (Text)
34import qualified Data.Text as T
40import qualified Data.Text as T
35−import Skylighting (defaultSyntaxMap)
36import System.FilePath (addExtension, replaceExtension, takeExtension)
41import System.FilePath (addExtension, replaceExtension, takeExtension)
37−import Text.Collate.Lang (renderLang)
42+import Text.Pandoc.BCP47 (Lang (..), renderLang)
38−import Text.Pandoc.Builder as B
43+import Text.Pandoc.Builder
39import Text.Pandoc.Class.PandocPure (PandocPure)
44import Text.Pandoc.Class.PandocPure (PandocPure)
40import Text.Pandoc.Class.PandocMonad (PandocMonad (..), getResourcePath,
45import Text.Pandoc.Class.PandocMonad (PandocMonad (..), getResourcePath,
41− readFileFromDirs, report,
46+ readFileFromDirs, report, setResourcePath,
42− setResourcePath)
47+ setTranslations, translateTerm)
43import Text.Pandoc.Error (PandocError (PandocParseError, PandocParsecError))
48import Text.Pandoc.Error (PandocError (PandocParseError, PandocParsecError))
44−import Text.Pandoc.Highlighting (languagesByExtension)
49+import Text.Pandoc.Highlighting (fromListingsLanguage, languagesByExtension)
45import Text.Pandoc.ImageSize (numUnit, showFl)
50import Text.Pandoc.ImageSize (numUnit, showFl)
46import Text.Pandoc.Logging
51import Text.Pandoc.Logging
47import Text.Pandoc.Options
52import Text.Pandoc.Options
48import Text.Pandoc.Parsing hiding (blankline, many, mathDisplay, mathInline,
53import Text.Pandoc.Parsing hiding (blankline, many, mathDisplay, mathInline,
49 optional, space, spaces, withRaw, (<|>))
54 optional, space, spaces, withRaw, (<|>))
50−import Text.Pandoc.Readers.LaTeX.Types (Tok (..), TokType (..))
55+import Text.Pandoc.Readers.LaTeX.Types (ExpansionPoint (..), Macro (..),
56+ ArgSpec (..), Tok (..), TokType (..))
51import Text.Pandoc.Readers.LaTeX.Parsing
57import Text.Pandoc.Readers.LaTeX.Parsing
52−import Text.Pandoc.Readers.LaTeX.Citation (citationCommands, cites)
58+import Text.Pandoc.Readers.LaTeX.Accent (accentCommands)
53−import Text.Pandoc.Readers.LaTeX.Math (dollarsMath, inlineEnvironments,
55− mathDisplay, mathInline,
56− newtheorem, theoremstyle, proof,
58import Text.Pandoc.Readers.LaTeX.Table (tableEnvironments)
59import Text.Pandoc.Readers.LaTeX.Table (tableEnvironments)
59−import Text.Pandoc.Readers.LaTeX.Macro (macroDef)
60+import Text.Pandoc.Readers.LaTeX.Lang (polyglossiaLangToBCP47,
60−import Text.Pandoc.Readers.LaTeX.Lang (inlineLanguageCommands,
62− babelLangToBCP47, setDefaultLanguage)
61+ babelLangToBCP47)
63−import Text.Pandoc.Readers.LaTeX.SIunitx (siunitxCommands)
62+import Text.Pandoc.Readers.LaTeX.SIunitx
64−import Text.Pandoc.Readers.LaTeX.Inline (acronymCommands, refCommands,
65− nameCommands, charCommands,
67− biblatexInlineCommands,
68− verbCommands, rawInlineOr,
70import Text.Pandoc.Shared
63import Text.Pandoc.Shared
64+import qualified Text.Pandoc.Translations as Translations
71import Text.Pandoc.Walk
65import Text.Pandoc.Walk
72−import Data.List.NonEmpty (nonEmpty)
66+import qualified Text.Pandoc.Builder as B
74-- for debugging:
69-- for debugging:
75-- import Text.Pandoc.Extensions (getDefaultExtensions)
70-- import Text.Pandoc.Extensions (getDefaultExtensions)
@@ -77,17 +72,16 @@ import Data.List.NonEmpty (nonEmpty)
77-- import Debug.Trace (traceShowId)
72-- import Debug.Trace (traceShowId)
79-- | Parse LaTeX from string and return 'Pandoc' document.
74-- | Parse LaTeX from string and return 'Pandoc' document.
80−readLaTeX :: (PandocMonad m, ToSources a)
75+readLaTeX :: PandocMonad m
81 => ReaderOptions -- ^ Reader options
76 => ReaderOptions -- ^ Reader options
82− -> a -- ^ Input to parse
77+ -> Text -- ^ String to parse (assumes @'\n'@ line endings)
83 -> m Pandoc
78 -> m Pandoc
84readLaTeX opts ltx = do
79readLaTeX opts ltx = do
85− let sources = toSources ltx
86 parsed <- runParserT parseLaTeX def{ sOptions = opts } "source"
80 parsed <- runParserT parseLaTeX def{ sOptions = opts } "source"
87− (tokenizeSources sources)
81+ (tokenize "source" (crFilter ltx))
88 case parsed of
82 case parsed of
89 Right result -> return result
83 Right result -> return result
90− Left e -> throwError $ PandocParsecError sources e
84+ Left e -> throwError $ PandocParsecError ltx e
92parseLaTeX :: PandocMonad m => LP m Pandoc
86parseLaTeX :: PandocMonad m => LP m Pandoc
93parseLaTeX = do
87parseLaTeX = do
@@ -98,7 +92,11 @@ parseLaTeX = do
98 let doc' = doc bs
92 let doc' = doc bs
99 let headerLevel (Header n _ _) = [n]
93 let headerLevel (Header n _ _) = [n]
100 headerLevel _ = []
94 headerLevel _ = []
101− let bottomLevel = maybe 1 minimum $ nonEmpty $ query headerLevel doc'
95+#if MIN_VERSION_safe(0,3,18)
96+ let bottomLevel = minimumBound 1 $ query headerLevel doc'
98+ let bottomLevel = minimumDef 1 $ query headerLevel doc'
102 let adjustHeaders m (Header n attr ils) = Header (n+m) attr ils
100 let adjustHeaders m (Header n attr ils) = Header (n+m) attr ils
103 adjustHeaders _ x = x
101 adjustHeaders _ x = x
104 let (Pandoc _ bs') =
102 let (Pandoc _ bs') =
@@ -133,11 +131,11 @@ resolveRefs _ x = x
135rawLaTeXBlock :: (PandocMonad m, HasMacros s, HasReaderOptions s)
133rawLaTeXBlock :: (PandocMonad m, HasMacros s, HasReaderOptions s)
136− => ParserT Sources s m Text
134+ => ParserT Text s m Text
137rawLaTeXBlock = do
135rawLaTeXBlock = do
138 lookAhead (try (char '\\' >> letter))
136 lookAhead (try (char '\\' >> letter))
139 inp <- getInput
137 inp <- getInput
140− let toks = tokenizeSources inp
138+ let toks = tokenize "source" inp
141 snd <$> (rawLaTeXParser toks False (macroDef (const mempty)) blocks
139 snd <$> (rawLaTeXParser toks False (macroDef (const mempty)) blocks
142 <|> rawLaTeXParser toks True
140 <|> rawLaTeXParser toks True
143 (do choice (map controlSeq
141 (do choice (map controlSeq
@@ -164,14 +162,14 @@ beginOrEndCommand = try $ do
164 (txt <> untokenize rawargs)
162 (txt <> untokenize rawargs)
166rawLaTeXInline :: (PandocMonad m, HasMacros s, HasReaderOptions s)
164rawLaTeXInline :: (PandocMonad m, HasMacros s, HasReaderOptions s)
167− => ParserT Sources s m Text
165+ => ParserT Text s m Text
168rawLaTeXInline = do
166rawLaTeXInline = do
169 lookAhead (try (char '\\' >> letter))
167 lookAhead (try (char '\\' >> letter))
170 inp <- getInput
168 inp <- getInput
171− let toks = tokenizeSources inp
169+ let toks = tokenize "source" inp
172 raw <- snd <$>
170 raw <- snd <$>
173 ( rawLaTeXParser toks True
171 ( rawLaTeXParser toks True
174− (mempty <$ (controlSeq "input" >> skipMany rawopt >> braced))
172+ (mempty <$ (controlSeq "input" >> skipMany opt >> braced))
176 <|> rawLaTeXParser toks True (inlineEnvironment <|> inlineCommand')
174 <|> rawLaTeXParser toks True (inlineEnvironment <|> inlineCommand')
@@ -179,11 +177,11 @@ rawLaTeXInline = do
179 finalbraces <- mconcat <$> many (try (string "{}")) -- see #5439
177 finalbraces <- mconcat <$> many (try (string "{}")) -- see #5439
180 return $ raw <> T.pack finalbraces
178 return $ raw <> T.pack finalbraces
182−inlineCommand :: PandocMonad m => ParserT Sources ParserState m Inlines
180+inlineCommand :: PandocMonad m => ParserT Text ParserState m Inlines
183inlineCommand = do
181inlineCommand = do
184 lookAhead (try (char '\\' >> letter))
182 lookAhead (try (char '\\' >> letter))
185 inp <- getInput
183 inp <- getInput
186− let toks = tokenizeSources inp
184+ let toks = tokenize "source" inp
187 fst <$> rawLaTeXParser toks True (inlineEnvironment <|> inlineCommand')
185 fst <$> rawLaTeXParser toks True (inlineEnvironment <|> inlineCommand')
@@ -192,6 +190,12 @@ inlineCommand = do
192word :: PandocMonad m => LP m Inlines
190word :: PandocMonad m => LP m Inlines
193word = str . untoken <$> satisfyTok isWordTok
191word = str . untoken <$> satisfyTok isWordTok
193+regularSymbol :: PandocMonad m => LP m Inlines
194+regularSymbol = str . untoken <$> satisfyTok isRegularSymbol
195+ where isRegularSymbol (Tok _ Symbol t) = not $ T.any isSpecial t
196+ isRegularSymbol _ = False
197+ isSpecial c = c `Set.member` specialChars
195inlineGroup :: PandocMonad m => LP m Inlines
199inlineGroup :: PandocMonad m => LP m Inlines
196inlineGroup = do
200inlineGroup = do
197 ils <- grouped inline
201 ils <- grouped inline
@@ -232,6 +236,16 @@ mkImage options (T.unpack -> src) = do
232 _ -> return src
236 _ -> return src
233 return $ imageWith attr (T.pack src') "" alt
237 return $ imageWith attr (T.pack src') "" alt
239+doxspace :: PandocMonad m => LP m Inlines
241+ (space <$ lookAhead (satisfyTok startsWithLetter)) <|> return mempty
242+ where startsWithLetter (Tok _ Word t) =
244+ Just (c, _) | isLetter c -> True
246+ startsWithLetter _ = False
235removeDoubleQuotes :: Text -> Text
249removeDoubleQuotes :: Text -> Text
236removeDoubleQuotes t =
250removeDoubleQuotes t =
237 Data.Maybe.fromMaybe t $ T.stripPrefix "\"" t >>= T.stripSuffix "\""
251 Data.Maybe.fromMaybe t $ T.stripPrefix "\"" t >>= T.stripSuffix "\""
@@ -281,11 +295,23 @@ quoted' f starter ender = do
281lit :: Text -> LP m Inlines
295lit :: Text -> LP m Inlines
282lit = pure . str
296lit = pure . str
298+enquote :: PandocMonad m => Bool -> Maybe Text -> LP m Inlines
299+enquote starred mblang = do
301+ let lang = mblang >>= babelLangToBCP47
302+ let langspan = case lang of
304+ Just l -> spanWith ("",[],[("lang", renderLang l)])
305+ quoteContext <- sQuoteContext <$> getState
306+ if starred || quoteContext == InDoubleQuote
307+ then singleQuoted . langspan <$> withQuoteContext InSingleQuote tok
308+ else doubleQuoted . langspan <$> withQuoteContext InDoubleQuote tok
284blockquote :: PandocMonad m => Bool -> Maybe Text -> LP m Blocks
310blockquote :: PandocMonad m => Bool -> Maybe Text -> LP m Blocks
285blockquote cvariant mblang = do
311blockquote cvariant mblang = do
286 citepar <- if cvariant
312 citepar <- if cvariant
287 then (\xs -> para (cite xs mempty))
313 then (\xs -> para (cite xs mempty))
288− <$> cites inline NormalCitation False
314+ <$> cites NormalCitation False
289 else option mempty $ para <$> bracketed inline
315 else option mempty $ para <$> bracketed inline
290 let lang = mblang >>= babelLangToBCP47
316 let lang = mblang >>= babelLangToBCP47
291 let langdiv = case lang of
317 let langdiv = case lang of
@@ -296,13 +322,224 @@ blockquote cvariant mblang = do
296 optional $ symbolIn (".:;?!" :: [Char]) -- currently ignored
322 optional $ symbolIn (".:;?!" :: [Char]) -- currently ignored
297 return $ blockQuote . langdiv $ (bs <> citepar)
323 return $ blockQuote . langdiv $ (bs <> citepar)
325+doAcronym :: PandocMonad m => Text -> LP m Inlines
328+ return . mconcat $ [spanWith ("",[],[("acronym-label", untokenize acro),
329+ ("acronym-form", "singular+" <> form)])
330+ $ str $ untokenize acro]
332+doAcronymPlural :: PandocMonad m => Text -> LP m Inlines
333+doAcronymPlural form = do
336+ return . mconcat $ [spanWith ("",[],[("acronym-label", untokenize acro),
337+ ("acronym-form", "plural+" <> form)]) $
338+ mconcat [str $ untokenize acro, plural]]
340+doverb :: PandocMonad m => LP m Inlines
342+ Tok _ Symbol t <- anySymbol
343+ marker <- case T.uncons t of
344+ Just (c, ts) | T.null ts -> return c
347+ code . untokenize <$>
348+ manyTill (notFollowedBy newlineTok >> verbTok marker) (symbol marker)
350+verbTok :: PandocMonad m => Char -> LP m Tok
351+verbTok stopchar = do
352+ t@(Tok pos toktype txt) <- anyTok
353+ case T.findIndex (== stopchar) txt of
356+ let (t1, t2) = T.splitAt i txt
358+ setInput $ Tok (incSourceColumn pos i) Symbol (T.singleton stopchar)
359+ : totoks (incSourceColumn pos (i + 1)) (T.drop 1 t2) ++ inp
360+ return $ Tok pos toktype t1
362+listingsLanguage :: [(Text, Text)] -> Maybe Text
363+listingsLanguage opts =
364+ case lookup "language" opts of
366+ Just l -> fromListingsLanguage l `mplus` Just l
368+dolstinline :: PandocMonad m => LP m Inlines
370+ options <- option [] keyvals
371+ let classes = maybeToList $ listingsLanguage options
372+ doinlinecode classes
374+domintinline :: PandocMonad m => LP m Inlines
377+ cls <- untokenize <$> braced
380+doinlinecode :: PandocMonad m => [Text] -> LP m Inlines
381+doinlinecode classes = do
382+ Tok _ Symbol t <- anySymbol
383+ marker <- case T.uncons t of
384+ Just (c, ts) | T.null ts -> return c
386+ let stopchar = if marker == '{' then '}' else marker
388+ codeWith ("",classes,[]) . T.map nlToSpace . untokenize <$>
389+ manyTill (verbTok stopchar) (symbol stopchar)
391+nlToSpace :: Char -> Char
395+mathDisplay :: Text -> Inlines
396+mathDisplay = displayMath . trimMath
398+mathInline :: Text -> Inlines
399+mathInline = math . trimMath
401+dollarsMath :: PandocMonad m => LP m Inlines
404+ display <- option False (True <$ symbol '$')
405+ (do contents <- try $ untokenize <$> pDollarsMath 0
407+ then mathDisplay contents <$ symbol '$'
408+ else return $ mathInline contents)
409+ <|> (guard display >> return (mathInline ""))
411+-- Int is number of embedded groupings
412+pDollarsMath :: PandocMonad m => Int -> LP m [Tok]
414+ tk@(Tok _ toktype t) <- anyTok
417+ , n == 0 -> return []
420+ (tk :) . (tk' :) <$> pDollarsMath n
421+ | t == "{" -> (tk :) <$> pDollarsMath (n+1)
424+ then (tk :) <$> pDollarsMath (n-1)
426+ _ -> (tk :) <$> pDollarsMath n
430+addPrefix :: [Inline] -> [Citation] -> [Citation]
431+addPrefix p (k:ks) = k {citationPrefix = p ++ citationPrefix k} : ks
434+addSuffix :: [Inline] -> [Citation] -> [Citation]
435+addSuffix s ks@(_:_) =
437+ in init ks ++ [k {citationSuffix = citationSuffix k ++ s}]
440+simpleCiteArgs :: PandocMonad m => LP m [Citation]
441+simpleCiteArgs = try $ do
442+ first <- optionMaybe $ toList <$> opt
443+ second <- optionMaybe $ toList <$> opt
444+ keys <- try $ bgroup *> manyTill citationLabel egroup
445+ let (pre, suf) = case (first , second ) of
446+ (Just s , Nothing) -> (mempty, s )
447+ (Just s , Just t ) -> (s , t )
448+ _ -> (mempty, mempty)
449+ conv k = Citation { citationId = k
450+ , citationPrefix = []
451+ , citationSuffix = []
452+ , citationMode = NormalCitation
454+ , citationNoteNum = 0
456+ return $ addPrefix pre $ addSuffix suf $ map conv keys
458+citationLabel :: PandocMonad m => LP m Text
462+ (many1 (satisfyTok isWordTok <|> symbolIn bibtexKeyChar)
464+ <* optional (symbol ',')
466+ where bibtexKeyChar = ".:;?!`'()/*@_+=-&[]" :: [Char]
468+cites :: PandocMonad m => CitationMode -> Bool -> LP m [Citation]
469+cites mode multi = try $ do
472+ multiprenote <- optionMaybe $ toList <$> paropt
473+ multipostnote <- optionMaybe $ toList <$> paropt
474+ let (pre, suf) = case (multiprenote, multipostnote) of
475+ (Just s , Nothing) -> (mempty, s)
476+ (Nothing , Just t) -> (mempty, t)
477+ (Just s , Just t ) -> (s, t)
478+ _ -> (mempty, mempty)
479+ tempCits <- many1 simpleCiteArgs
481+ (k:ks) -> case ks of
482+ (_:_) -> return $ (addMprenote pre k : init ks) ++
483+ [addMpostnote suf (last ks)]
484+ _ -> return [addMprenote pre (addMpostnote suf k)]
486+ else count 1 simpleCiteArgs
487+ let cs = concat cits
488+ return $ case mode of
489+ AuthorInText -> case cs of
490+ (c:rest) -> c {citationMode = mode} : rest
492+ _ -> map (\a -> a {citationMode = mode}) cs
493+ where mprenote (k:ks) = (k:ks) ++ [Space]
495+ mpostnote (k:ks) = [Str ",", Space] ++ (k:ks)
496+ mpostnote _ = mempty
497+ addMprenote mpn (k:ks) =
498+ let mpnfinal = case citationPrefix k of
499+ (_:_) -> mprenote mpn
501+ in addPrefix mpnfinal (k:ks)
502+ addMprenote _ _ = []
503+ addMpostnote = addSuffix . mpostnote
505+citation :: PandocMonad m => Text -> CitationMode -> Bool -> LP m Inlines
506+citation name mode multi = do
507+ (c,raw) <- withRaw $ cites mode multi
508+ return $ cite c (rawInline "latex" $ "\\" <> name <> untokenize raw)
510+handleCitationPart :: Inlines -> [Citation]
511+handleCitationPart ils =
512+ let isCite Cite{} = True
514+ (pref, rest) = break isCite (toList ils)
516+ (Cite cs _:suff) -> addPrefix pref $ addSuffix suff cs
519+complexNatbibCitation :: PandocMonad m => CitationMode -> LP m Inlines
520+complexNatbibCitation mode = try $ do
522+ withRaw $ concat <$> do
524+ items <- mconcat <$>
525+ many1 (notFollowedBy (symbol ';') >> inline)
528+ return $ map handleCitationPart items
531+ (c:cits) -> return $ cite (c{ citationMode = mode }:cits)
532+ (rawInline "latex" $ "\\citetext" <> untokenize raw)
534+inNote :: Inlines -> Inlines
536+ note $ para $ ils <> str "."
299inlineCommand' :: PandocMonad m => LP m Inlines
538inlineCommand' :: PandocMonad m => LP m Inlines
300inlineCommand' = try $ do
539inlineCommand' = try $ do
301 Tok _ (CtrlSeq name) cmd <- anyControlSeq
540 Tok _ (CtrlSeq name) cmd <- anyControlSeq
302 guard $ name /= "begin" && name /= "end" && name /= "and"
541 guard $ name /= "begin" && name /= "end" && name /= "and"
303− star <- if T.all isAlphaNum name
304− then option "" ("*" <$ symbol '*' <* sp)
542+ star <- option "" ("*" <$ symbol '*' <* sp)
306 overlay <- option "" overlaySpecification
543 overlay <- option "" overlaySpecification
307 let name' = name <> star <> overlay
544 let name' = name <> star <> overlay
308 let names = ordNub [name', name] -- check non-starred as fallback
545 let names = ordNub [name', name] -- check non-starred as fallback
@@ -316,6 +553,22 @@ inlineCommand' = try $ do
316tok :: PandocMonad m => LP m Inlines
553tok :: PandocMonad m => LP m Inlines
317tok = tokWith inline
554tok = tokWith inline
556+opt :: PandocMonad m => LP m Inlines
558+ toks <- try (sp *> bracketedToks <* sp)
559+ -- now parse the toks as inlines
561+ parsed <- runParserT (mconcat <$> many inline) st "bracketed option" toks
563+ Right result -> return result
564+ Left e -> throwError $ PandocParsecError (untokenize toks) e
566+paropt :: PandocMonad m => LP m Inlines
567+paropt = parenWrapped inline
569+inBrackets :: Inlines -> Inlines
570+inBrackets x = str "[" <> x <> str "]"
319unescapeURL :: Text -> Text
572unescapeURL :: Text -> Text
320unescapeURL = T.concat . go . T.splitOn "\\"
573unescapeURL = T.concat . go . T.splitOn "\\"
@@ -327,107 +580,345 @@ unescapeURL = T.concat . go . T.splitOn "\\"
327 , isEscapable c = t
580 , isEscapable c = t
328 | otherwise = "\\" <> t
581 | otherwise = "\\" <> t
583+mathEnvWith :: PandocMonad m
584+ => (Inlines -> a) -> Maybe Text -> Text -> LP m a
585+mathEnvWith f innerEnv name = f . mathDisplay . inner <$> mathEnv name
586+ where inner x = case innerEnv of
588+ Just y -> "\\begin{" <> y <> "}\n" <> x <>
589+ "\\end{" <> y <> "}"
591+mathEnv :: PandocMonad m => Text -> LP m Text
595+ res <- manyTill anyTok (end_ name)
596+ return $ stripTrailingNewlines $ untokenize res
598+inlineEnvironment :: PandocMonad m => LP m Inlines
599+inlineEnvironment = try $ do
601+ name <- untokenize <$> braced
602+ M.findWithDefault mzero name inlineEnvironments
604+inlineEnvironments :: PandocMonad m => M.Map Text (LP m Inlines)
605+inlineEnvironments = M.fromList [
606+ ("displaymath", mathEnvWith id Nothing "displaymath")
607+ , ("math", math <$> mathEnv "math")
608+ , ("equation", mathEnvWith id Nothing "equation")
609+ , ("equation*", mathEnvWith id Nothing "equation*")
610+ , ("gather", mathEnvWith id (Just "gathered") "gather")
611+ , ("gather*", mathEnvWith id (Just "gathered") "gather*")
612+ , ("multline", mathEnvWith id (Just "gathered") "multline")
613+ , ("multline*", mathEnvWith id (Just "gathered") "multline*")
614+ , ("eqnarray", mathEnvWith id (Just "aligned") "eqnarray")
615+ , ("eqnarray*", mathEnvWith id (Just "aligned") "eqnarray*")
616+ , ("align", mathEnvWith id (Just "aligned") "align")
617+ , ("align*", mathEnvWith id (Just "aligned") "align*")
618+ , ("alignat", mathEnvWith id (Just "aligned") "alignat")
619+ , ("alignat*", mathEnvWith id (Just "aligned") "alignat*")
620+ , ("dmath", mathEnvWith id Nothing "dmath")
621+ , ("dmath*", mathEnvWith id Nothing "dmath*")
622+ , ("dgroup", mathEnvWith id (Just "aligned") "dgroup")
623+ , ("dgroup*", mathEnvWith id (Just "aligned") "dgroup*")
624+ , ("darray", mathEnvWith id (Just "aligned") "darray")
625+ , ("darray*", mathEnvWith id (Just "aligned") "darray*")
330inlineCommands :: PandocMonad m => M.Map Text (LP m Inlines)
628inlineCommands :: PandocMonad m => M.Map Text (LP m Inlines)
331−inlineCommands = M.unions
629+inlineCommands =
332− [ accentCommands tok
333− , citationCommands inline
334− , siunitxCommands tok
340− , enquoteCommands tok
341− , inlineLanguageCommands tok
630+ M.union inlineLanguageCommands $
342− , biblatexInlineCommands tok
631+ M.union (accentCommands tok) $
345− rest = M.fromList
632+ M.fromList
346− [ ("emph", extractSpaces emph <$> tok)
633+ [ ("emph", extractSpaces emph <$> tok)
347− , ("textit", extractSpaces emph <$> tok)
634+ , ("textit", extractSpaces emph <$> tok)
348− , ("textsl", extractSpaces emph <$> tok)
635+ , ("textsl", extractSpaces emph <$> tok)
349− , ("textsc", extractSpaces smallcaps <$> tok)
636+ , ("textsc", extractSpaces smallcaps <$> tok)
350− , ("textsf", extractSpaces (spanWith ("",["sans-serif"],[])) <$> tok)
637+ , ("textsf", extractSpaces (spanWith ("",["sans-serif"],[])) <$> tok)
351− , ("textmd", extractSpaces (spanWith ("",["medium"],[])) <$> tok)
638+ , ("textmd", extractSpaces (spanWith ("",["medium"],[])) <$> tok)
352− , ("textrm", extractSpaces (spanWith ("",["roman"],[])) <$> tok)
639+ , ("textrm", extractSpaces (spanWith ("",["roman"],[])) <$> tok)
353− , ("textup", extractSpaces (spanWith ("",["upright"],[])) <$> tok)
640+ , ("textup", extractSpaces (spanWith ("",["upright"],[])) <$> tok)
354− , ("texttt", ttfamily)
641+ , ("texttt", ttfamily)
355− , ("sout", extractSpaces strikeout <$> tok)
642+ , ("sout", extractSpaces strikeout <$> tok)
356− , ("alert", skipopts >> spanWith ("",["alert"],[]) <$> tok) -- beamer
643+ , ("alert", skipopts >> spanWith ("",["alert"],[]) <$> tok) -- beamer
644+ , ("lq", return (str "‘"))
645+ , ("rq", return (str "’"))
646+ , ("textquoteleft", return (str "‘"))
647+ , ("textquoteright", return (str "’"))
648+ , ("textquotedblleft", return (str "“"))
649+ , ("textquotedblright", return (str "”"))
357− , ("textsuperscript", extractSpaces superscript <$> tok)
650+ , ("textsuperscript", extractSpaces superscript <$> tok)
358− , ("textsubscript", extractSpaces subscript <$> tok)
651+ , ("textsubscript", extractSpaces subscript <$> tok)
652+ , ("textbackslash", lit "\\")
653+ , ("backslash", lit "\\")
654+ , ("slash", lit "/")
359− , ("textbf", extractSpaces strong <$> tok)
655+ , ("textbf", extractSpaces strong <$> tok)
360− , ("textnormal", extractSpaces (spanWith ("",["nodecor"],[])) <$> tok)
656+ , ("textnormal", extractSpaces (spanWith ("",["nodecor"],[])) <$> tok)
361− , ("underline", underline <$> tok)
657+ , ("underline", underline <$> tok)
658+ , ("ldots", lit "…")
659+ , ("vdots", lit "\8942")
661+ , ("mdots", lit "…")
664+ , ("label", rawInlineOr "label" dolabel)
665+ , ("ref", rawInlineOr "ref" $ doref "ref")
666+ , ("cref", rawInlineOr "cref" $ doref "ref") -- from cleveref.sty
667+ , ("vref", rawInlineOr "vref" $ doref "ref+page") -- from varioref.sty
668+ , ("eqref", rawInlineOr "eqref" $ doref "eqref") -- from amsmath.sty
362− , ("mbox", rawInlineOr "mbox" $ processHBox <$> tok)
669+ , ("mbox", rawInlineOr "mbox" $ processHBox <$> tok)
363− , ("hbox", rawInlineOr "hbox" $ processHBox <$> tok)
670+ , ("hbox", rawInlineOr "hbox" $ processHBox <$> tok)
364− , ("lettrine", rawInlineOr "lettrine" lettrine)
671+ , ("lettrine", rawInlineOr "lettrine" lettrine)
365− , ("(", mathInline . untokenize <$> manyTill anyTok (controlSeq ")"))
672+ , ("(", mathInline . untokenize <$> manyTill anyTok (controlSeq ")"))
366− , ("[", mathDisplay . untokenize <$> manyTill anyTok (controlSeq "]"))
673+ , ("[", mathDisplay . untokenize <$> manyTill anyTok (controlSeq "]"))
367− , ("ensuremath", mathInline . untokenize <$> braced)
674+ , ("ensuremath", mathInline . untokenize <$> braced)
368− , ("texorpdfstring", const <$> tok <*> tok)
675+ , ("texorpdfstring", const <$> tok <*> tok)
685+ , ("qed", lit "\a0\x25FB")
369− -- old TeX commands
686+ -- old TeX commands
370− , ("em", extractSpaces emph <$> inlines)
687+ , ("em", extractSpaces emph <$> inlines)
371− , ("it", extractSpaces emph <$> inlines)
688+ , ("it", extractSpaces emph <$> inlines)
372− , ("sl", extractSpaces emph <$> inlines)
689+ , ("sl", extractSpaces emph <$> inlines)
373− , ("bf", extractSpaces strong <$> inlines)
690+ , ("bf", extractSpaces strong <$> inlines)
374− , ("tt", code . stringify . toList <$> inlines)
691+ , ("tt", code . stringify . toList <$> inlines)
375− , ("rm", inlines)
692+ , ("rm", inlines)
376− , ("itshape", extractSpaces emph <$> inlines)
693+ , ("itshape", extractSpaces emph <$> inlines)
377− , ("slshape", extractSpaces emph <$> inlines)
694+ , ("slshape", extractSpaces emph <$> inlines)
378− , ("scshape", extractSpaces smallcaps <$> inlines)
695+ , ("scshape", extractSpaces smallcaps <$> inlines)
379− , ("bfseries", extractSpaces strong <$> inlines)
696+ , ("bfseries", extractSpaces strong <$> inlines)
380− , ("MakeUppercase", makeUppercase <$> tok)
697+ , ("MakeUppercase", makeUppercase <$> tok)
381− , ("MakeTextUppercase", makeUppercase <$> tok) -- textcase
698+ , ("MakeTextUppercase", makeUppercase <$> tok) -- textcase
382− , ("uppercase", makeUppercase <$> tok)
699+ , ("uppercase", makeUppercase <$> tok)
383− , ("MakeLowercase", makeLowercase <$> tok)
700+ , ("MakeLowercase", makeLowercase <$> tok)
384− , ("MakeTextLowercase", makeLowercase <$> tok)
701+ , ("MakeTextLowercase", makeLowercase <$> tok)
385− , ("lowercase", makeLowercase <$> tok)
702+ , ("lowercase", makeLowercase <$> tok)
703+ , ("/", pure mempty) -- italic correction
704+ , ("\\", linebreak <$ (do inTableCell <- sInTableCell <$> getState
705+ guard $ not inTableCell
708+ , (",", lit "\8198")
709+ , ("@", pure mempty)
711+ , ("ps", pure $ str "PS." <> space)
712+ , ("TeX", lit "TeX")
713+ , ("LaTeX", lit "LaTeX")
715+ , ("textless", lit "<")
716+ , ("textgreater", lit ">")
386− , ("thanks", skipopts >> note <$> grouped block)
717+ , ("thanks", skipopts >> note <$> grouped block)
387− , ("footnote", skipopts >> note <$> grouped block)
718+ , ("footnote", skipopts >> note <$> grouped block)
388− , ("passthrough", tok) -- \passthrough macro used by latex writer
719+ , ("passthrough", tok) -- \passthrough macro used by latex writer
389− -- for listings
720+ -- for listings
722+ , ("lstinline", dolstinline)
723+ , ("mintinline", domintinline)
725+ , ("url", (\url -> link url "" (str url)) . unescapeURL . untokenize <$>
727+ , ("nolinkurl", code . unescapeURL . untokenize <$> bracedUrl)
728+ , ("href", do url <- bracedUrl
730+ link (unescapeURL $ untokenize url) "" <$> tok)
390− , ("includegraphics", do options <- option [] keyvals
731+ , ("includegraphics", do options <- option [] keyvals
391− src <- braced
732+ src <- braced
392− mkImage options .
733+ mkImage options . unescapeURL . removeDoubleQuotes $
394− removeDoubleQuotes $ untokenize src)
734+ untokenize src)
395− -- hyperref
735+ , ("enquote*", enquote True Nothing)
396− , ("url", (\url -> link url "" (str url)) . unescapeURL . untokenize <$>
736+ , ("enquote", enquote False Nothing)
397− bracedUrl)
737+ -- foreignquote is supposed to use native quote marks
398− , ("nolinkurl", code . unescapeURL . untokenize <$> bracedUrl)
738+ , ("foreignquote*", braced >>= enquote True . Just . untokenize)
399− , ("href", do url <- bracedUrl
739+ , ("foreignquote", braced >>= enquote False . Just . untokenize)
400− sp
740+ -- hypehnquote uses regular quotes
401− link (unescapeURL $ untokenize url) "" <$> tok)
741+ , ("hyphenquote*", braced >>= enquote True . Just . untokenize)
402− , ("hyperlink", hyperlink)
742+ , ("hyphenquote", braced >>= enquote False . Just . untokenize)
403− , ("hyperref", hyperref)
743+ , ("figurename", doTerm Translations.Figure)
744+ , ("prefacename", doTerm Translations.Preface)
745+ , ("refname", doTerm Translations.References)
746+ , ("bibname", doTerm Translations.Bibliography)
747+ , ("chaptername", doTerm Translations.Chapter)
748+ , ("partname", doTerm Translations.Part)
749+ , ("contentsname", doTerm Translations.Contents)
750+ , ("listfigurename", doTerm Translations.ListOfFigures)
751+ , ("listtablename", doTerm Translations.ListOfTables)
752+ , ("indexname", doTerm Translations.Index)
753+ , ("abstractname", doTerm Translations.Abstract)
754+ , ("tablename", doTerm Translations.Table)
755+ , ("enclname", doTerm Translations.Encl)
756+ , ("ccname", doTerm Translations.Cc)
757+ , ("headtoname", doTerm Translations.To)
758+ , ("pagename", doTerm Translations.Page)
759+ , ("seename", doTerm Translations.See)
760+ , ("seealsoname", doTerm Translations.SeeAlso)
761+ , ("proofname", doTerm Translations.Proof)
762+ , ("glossaryname", doTerm Translations.Glossary)
763+ , ("lstlistingname", doTerm Translations.Listing)
764+ , ("cite", citation "cite" NormalCitation False)
765+ , ("Cite", citation "Cite" NormalCitation False)
766+ , ("citep", citation "citep" NormalCitation False)
767+ , ("citep*", citation "citep*" NormalCitation False)
768+ , ("citeal", citation "citeal" NormalCitation False)
769+ , ("citealp", citation "citealp" NormalCitation False)
770+ , ("citealp*", citation "citealp*" NormalCitation False)
771+ , ("autocite", citation "autocite" NormalCitation False)
772+ , ("smartcite", citation "smartcite" NormalCitation False)
773+ , ("footcite", inNote <$> citation "footcite" NormalCitation False)
774+ , ("parencite", citation "parencite" NormalCitation False)
775+ , ("supercite", citation "supercite" NormalCitation False)
776+ , ("footcitetext", inNote <$> citation "footcitetext" NormalCitation False)
777+ , ("citeyearpar", citation "citeyearpar" SuppressAuthor False)
778+ , ("citeyear", citation "citeyear" SuppressAuthor False)
779+ , ("autocite*", citation "autocite*" SuppressAuthor False)
780+ , ("cite*", citation "cite*" SuppressAuthor False)
781+ , ("parencite*", citation "parencite*" SuppressAuthor False)
782+ , ("textcite", citation "textcite" AuthorInText False)
783+ , ("citet", citation "citet" AuthorInText False)
784+ , ("citet*", citation "citet*" AuthorInText False)
785+ , ("citealt", citation "citealt" AuthorInText False)
786+ , ("citealt*", citation "citealt*" AuthorInText False)
787+ , ("textcites", citation "textcites" AuthorInText True)
788+ , ("cites", citation "cites" NormalCitation True)
789+ , ("autocites", citation "autocites" NormalCitation True)
790+ , ("footcites", inNote <$> citation "footcites" NormalCitation True)
791+ , ("parencites", citation "parencites" NormalCitation True)
792+ , ("supercites", citation "supercites" NormalCitation True)
793+ , ("footcitetexts", inNote <$> citation "footcitetexts" NormalCitation True)
794+ , ("Autocite", citation "Autocite" NormalCitation False)
795+ , ("Smartcite", citation "Smartcite" NormalCitation False)
796+ , ("Footcite", inNote <$> citation "Footcite" NormalCitation False)
797+ , ("Parencite", citation "Parencite" NormalCitation False)
798+ , ("Supercite", citation "Supercite" NormalCitation False)
799+ , ("Footcitetext", inNote <$> citation "Footcitetext" NormalCitation False)
800+ , ("Citeyearpar", citation "Citeyearpar" SuppressAuthor False)
801+ , ("Citeyear", citation "Citeyear" SuppressAuthor False)
802+ , ("Autocite*", citation "Autocite*" SuppressAuthor False)
803+ , ("Cite*", citation "Cite*" SuppressAuthor False)
804+ , ("Parencite*", citation "Parencite*" SuppressAuthor False)
805+ , ("Textcite", citation "Textcite" AuthorInText False)
806+ , ("Textcites", citation "Textcites" AuthorInText True)
807+ , ("Cites", citation "Cites" NormalCitation True)
808+ , ("Autocites", citation "Autocites" NormalCitation True)
809+ , ("Footcites", inNote <$> citation "Footcites" NormalCitation True)
810+ , ("Parencites", citation "Parencites" NormalCitation True)
811+ , ("Supercites", citation "Supercites" NormalCitation True)
812+ , ("Footcitetexts", inNote <$> citation "Footcitetexts" NormalCitation True)
813+ , ("citetext", complexNatbibCitation NormalCitation)
814+ , ("citeauthor", (try (tok *> sp *> controlSeq "citetext") *>
815+ complexNatbibCitation AuthorInText)
816+ <|> citation "citeauthor" AuthorInText False)
817+ , ("nocite", mempty <$ (citation "nocite" NormalCitation False >>=
819+ , ("hyperlink", hyperlink)
404− , ("hypertarget", hypertargetInline)
820+ , ("hypertarget", hypertargetInline)
821+ -- glossaries package
822+ , ("gls", doAcronym "short")
823+ , ("Gls", doAcronym "short")
824+ , ("glsdesc", doAcronym "long")
825+ , ("Glsdesc", doAcronym "long")
826+ , ("GLSdesc", doAcronym "long")
827+ , ("acrlong", doAcronym "long")
828+ , ("Acrlong", doAcronym "long")
829+ , ("acrfull", doAcronym "full")
830+ , ("Acrfull", doAcronym "full")
831+ , ("acrshort", doAcronym "abbrv")
832+ , ("Acrshort", doAcronym "abbrv")
833+ , ("glspl", doAcronymPlural "short")
834+ , ("Glspl", doAcronymPlural "short")
835+ , ("glsdescplural", doAcronymPlural "long")
836+ , ("Glsdescplural", doAcronymPlural "long")
837+ , ("GLSdescplural", doAcronymPlural "long")
839+ , ("ac", doAcronym "short")
840+ , ("acf", doAcronym "full")
841+ , ("acs", doAcronym "abbrv")
842+ , ("acl", doAcronym "long")
843+ , ("acp", doAcronymPlural "short")
844+ , ("acfp", doAcronymPlural "full")
845+ , ("acsp", doAcronymPlural "abbrv")
846+ , ("aclp", doAcronymPlural "long")
847+ , ("Ac", doAcronym "short")
848+ , ("Acf", doAcronym "full")
849+ , ("Acs", doAcronym "abbrv")
850+ , ("Acl", doAcronym "long")
851+ , ("Acp", doAcronymPlural "short")
852+ , ("Acfp", doAcronymPlural "full")
853+ , ("Acsp", doAcronymPlural "abbrv")
854+ , ("Aclp", doAcronymPlural "long")
856+ , ("si", skipopts *> dosi tok)
858+ , ("SIrange", doSIrange True tok)
859+ , ("numrange", doSIrange False tok)
860+ , ("numlist", doSInumlist)
405− -- hyphenat
863+ -- hyphenat
864+ , ("bshyp", lit "\\\173")
865+ , ("fshyp", lit "/\173")
866+ , ("dothyp", lit ".\173")
867+ , ("colonhyp", lit ":\173")
406− , ("nohyphens", tok)
869+ , ("nohyphens", tok)
407− , ("textnhtt", ttfamily)
870+ , ("textnhtt", ttfamily)
408− , ("nhttfamily", ttfamily)
871+ , ("nhttfamily", ttfamily)
409− -- LaTeX colors
872+ -- LaTeX colors
410− , ("textcolor", coloredInline "color")
873+ , ("textcolor", coloredInline "color")
411− , ("colorbox", coloredInline "background-color")
874+ , ("colorbox", coloredInline "background-color")
876+ , ("faCheck", lit "\10003")
877+ , ("faClose", lit "\10007")
879+ , ("xspace", doxspace)
412− -- etoolbox
880+ -- etoolbox
413− , ("ifstrequal", ifstrequal)
881+ , ("ifstrequal", ifstrequal)
414− , ("newtoggle", braced >>= newToggle)
882+ , ("newtoggle", braced >>= newToggle)
415− , ("toggletrue", braced >>= setToggle True)
883+ , ("toggletrue", braced >>= setToggle True)
416− , ("togglefalse", braced >>= setToggle False)
884+ , ("togglefalse", braced >>= setToggle False)
417− , ("iftoggle", try $ ifToggle >> inline)
885+ , ("iftoggle", try $ ifToggle >> inline)
887+ , ("RN", romanNumeralUpper)
888+ , ("Rn", romanNumeralLower)
890+ , ("foreignlanguage", foreignlanguage)
418− -- include
891+ -- include
419− , ("input", rawInlineOr "input" $ include "input")
892+ , ("input", rawInlineOr "input" $ include "input")
420− -- soul package
893+ -- soul package
421− , ("ul", underline <$> tok)
894+ , ("ul", underline <$> tok)
422− -- ulem package
895+ -- ulem package
423− , ("uline", underline <$> tok)
896+ , ("uline", underline <$> tok)
424− -- plain tex stuff that should just be passed through as raw tex
897+ -- plain tex stuff that should just be passed through as raw tex
425− , ("ifdim", ifdim)
898+ , ("ifdim", ifdim)
900+ , ("mkbibquote", spanWith nullAttr . doubleQuoted <$> tok)
901+ , ("mkbibemph", spanWith nullAttr . emph <$> tok)
902+ , ("mkbibitalic", spanWith nullAttr . emph <$> tok)
903+ , ("mkbibbold", spanWith nullAttr . strong <$> tok)
905+ spanWith nullAttr . (\x -> str "(" <> x <> str ")") <$> tok)
907+ spanWith nullAttr . (\x -> str "[" <> x <> str "]") <$> tok)
908+ , ("autocap", spanWith nullAttr <$> tok)
909+ , ("textnormal", spanWith ("",["nodecor"],[]) <$> tok)
911+ (\x -> spanWith ("",[],[("bibstring",x)]) (str x)) . untokenize
913+ , ("adddot", pure (str "."))
914+ , ("adddotspace", pure (spanWith nullAttr (str "." <> space)))
915+ , ("addabbrvspace", pure space)
916+ , ("hyphen", pure (str "-"))
428lettrine :: PandocMonad m => LP m Inlines
919lettrine :: PandocMonad m => LP m Inlines
429lettrine = do
920lettrine = do
430− optional rawopt
921+ optional opt
433 return $ extractSpaces (spanWith ("",["lettrine"],[])) x <> smallcaps y
924 return $ extractSpaces (spanWith ("",["lettrine"],[])) x <> smallcaps y
@@ -447,18 +938,32 @@ alterStr :: (Text -> Text) -> Inline -> Inline
447alterStr f (Str xs) = Str (f xs)
938alterStr f (Str xs) = Str (f xs)
448alterStr _ x = x
939alterStr _ x = x
941+foreignlanguage :: PandocMonad m => LP m Inlines
943+ babelLang <- untokenize <$> braced
944+ case babelLangToBCP47 babelLang of
945+ Just lang -> spanWith ("", [], [("lang", renderLang lang)]) <$> tok
948+inlineLanguageCommands :: PandocMonad m => M.Map Text (LP m Inlines)
949+inlineLanguageCommands = M.fromList $ mk <$> M.toList polyglossiaLangToBCP47
951+ mk (polyglossia, bcp47Func) =
952+ ("text" <> polyglossia, inlineLanguage bcp47Func)
954+inlineLanguage :: PandocMonad m => (Text -> Lang) -> LP m Inlines
955+inlineLanguage bcp47Func = do
956+ o <- option "" $ T.filter (\c -> c /= '[' && c /= ']')
958+ let lang = renderLang $ bcp47Func o
959+ extractSpaces (spanWith ("", [], [("lang", lang)])) <$> tok
450hyperlink :: PandocMonad m => LP m Inlines
961hyperlink :: PandocMonad m => LP m Inlines
451hyperlink = try $ do
962hyperlink = try $ do
452 src <- untokenize <$> braced
963 src <- untokenize <$> braced
453 lab <- tok
964 lab <- tok
454 return $ link ("#" <> src) "" lab
965 return $ link ("#" <> src) "" lab
456−hyperref :: PandocMonad m => LP m Inlines
458− url <- (("#" <>) . untokenize <$> try (sp *> bracketedToks <* sp))
459− <|> untokenize <$> (bracedUrl <* bracedUrl <* bracedUrl)
462hypertargetBlock :: PandocMonad m => LP m Blocks
967hypertargetBlock :: PandocMonad m => LP m Blocks
463hypertargetBlock = try $ do
968hypertargetBlock = try $ do
464 ref <- untokenize <$> braced
969 ref <- untokenize <$> braced
@@ -473,6 +978,31 @@ hypertargetInline = try $ do
473 ils <- grouped inline
978 ils <- grouped inline
474 return $ spanWith (ref, [], []) ils
979 return $ spanWith (ref, [], []) ils
981+romanNumeralUpper :: (PandocMonad m) => LP m Inlines
983+ str . toRomanNumeral <$> romanNumeralArg
985+romanNumeralLower :: (PandocMonad m) => LP m Inlines
987+ str . T.toLower . toRomanNumeral <$> romanNumeralArg
989+romanNumeralArg :: (PandocMonad m) => LP m Int
990+romanNumeralArg = spaces *> (parser <|> inBraces)
1000+ s <- untokenize <$> many1 (satisfyTok isWordTok)
1001+ let (digits, rest) = T.span isDigit s
1002+ unless (T.null rest) $
1003+ Prelude.fail "Non-digits in argument to \\Rn or \\RN"
476newToggle :: (Monoid a, PandocMonad m) => [Tok] -> LP m a
1006newToggle :: (Monoid a, PandocMonad m) => [Tok] -> LP m a
477newToggle name = do
1007newToggle name = do
478 updateState $ \st ->
1008 updateState $ \st ->
@@ -503,6 +1033,9 @@ ifToggle = do
503 report $ UndefinedToggle name' pos
1033 report $ UndefinedToggle name' pos
504 return ()
1034 return ()
1036+doTerm :: PandocMonad m => Translations.Term -> LP m Inlines
1037+doTerm term = str <$> translateTerm term
506ifstrequal :: (PandocMonad m, Monoid a) => LP m a
1039ifstrequal :: (PandocMonad m, Monoid a) => LP m a
507ifstrequal = do
1040ifstrequal = do
508 str1 <- tok
1041 str1 <- tok
@@ -523,6 +1056,13 @@ coloredInline stylename = do
523ttfamily :: PandocMonad m => LP m Inlines
1056ttfamily :: PandocMonad m => LP m Inlines
524ttfamily = code . stringify . toList <$> tok
1057ttfamily = code . stringify . toList <$> tok
1059+rawInlineOr :: PandocMonad m => Text -> LP m Inlines -> LP m Inlines
1060+rawInlineOr name' fallback = do
1061+ parseRaw <- extensionEnabled Ext_raw_tex <$> getOption readerExtensions
1063+ then rawInline "latex" <$> getRawCommand name' ("\\" <> name')
526processHBox :: Inlines -> Inlines
1066processHBox :: Inlines -> Inlines
527processHBox = walk convert
1067processHBox = walk convert
@@ -573,67 +1113,61 @@ treatAsInline = Set.fromList
573 , "pagebreak"
1113 , "pagebreak"
1116+dolabel :: PandocMonad m => LP m Inlines
1119+ let refstr = untokenize v
1120+ updateState $ \st ->
1121+ st{ sLastLabel = Just refstr }
1122+ return $ spanWith (refstr,[],[("label", refstr)])
1123+ $ inBrackets $ str $ untokenize v
1125+doref :: PandocMonad m => Text -> LP m Inlines
1128+ let refstr = untokenize v
1129+ return $ linkWith ("",[],[ ("reference-type", cls)
1130+ , ("reference", refstr)])
1133+ (inBrackets $ str refstr)
576lookupListDefault :: (Ord k) => v -> [k] -> M.Map k v -> v
1135lookupListDefault :: (Ord k) => v -> [k] -> M.Map k v -> v
577lookupListDefault d = (fromMaybe d .) . lookupList
1136lookupListDefault d = (fromMaybe d .) . lookupList
578 where lookupList l m = msum $ map (`M.lookup` m) l
1137 where lookupList l m = msum $ map (`M.lookup` m) l
580inline :: PandocMonad m => LP m Inlines
1139inline :: PandocMonad m => LP m Inlines
581−inline = do
1140+inline = (mempty <$ comment)
582− Tok pos toktype t <- lookAhead anyTok
1141+ <|> (space <$ whitespace)
583− let symbolAsString = str . untoken <$> anySymbol
1142+ <|> (softbreak <$ endline)
584− let unescapedSymbolAsString =
1143+ <|> word
585− do s <- untoken <$> anySymbol
1144+ <|> macroDef (rawInline "latex")
586− report $ ParsingUnescaped s pos
1145+ <|> inlineCommand'
587− return $ str s
1146+ <|> inlineEnvironment
588− case toktype of
1147+ <|> inlineGroup
589− Comment -> mempty <$ comment
1148+ <|> (symbol '-' *>
590− Spaces -> space <$ whitespace
1149+ option (str "-") (symbol '-' *>
591− Newline -> softbreak <$ endline
1150+ option (str "–") (str "—" <$ symbol '-')))
592− Word -> word
1151+ <|> doubleQuote
593− Esc1 -> str . T.singleton <$> primEscape
1152+ <|> singleQuote
594− Esc2 -> str . T.singleton <$> primEscape
1153+ <|> (str "”" <$ try (symbol '\'' >> symbol '\''))
595− Symbol ->
1154+ <|> (str "”" <$ symbol '”')
596− case t of
1155+ <|> (str "’" <$ symbol '\'')
597− "-" -> symbol '-' *>
1156+ <|> (str "’" <$ symbol '’')
598− option (str "-") (symbol '-' *>
1157+ <|> (str "\160" <$ symbol '~')
599− option (str "–") (str "—" <$ symbol '-'))
1158+ <|> dollarsMath
600− "'" -> symbol '\'' *>
1159+ <|> (guardEnabled Ext_literate_haskell *> symbol '|' *> doLHSverb)
601− option (str "’") (str "”" <$ symbol '\'')
1160+ <|> (str . T.singleton <$> primEscape)
602− "~" -> str "\160" <$ symbol '~'
1161+ <|> regularSymbol
603− "`" -> doubleQuote <|> singleQuote <|> symbolAsString
1162+ <|> (do res <- symbolIn "#^'`\"[]&"
604− "\"" -> doubleQuote <|> singleQuote <|> symbolAsString
1163+ pos <- getPosition
605− "“" -> doubleQuote <|> symbolAsString
1164+ let s = untoken res
606− "‘" -> singleQuote <|> symbolAsString
1165+ report $ ParsingUnescaped s pos
607− "$" -> dollarsMath <|> unescapedSymbolAsString
1166+ return $ str s)
608− "|" -> (guardEnabled Ext_literate_haskell *>
609− symbol '|' *> doLHSverb) <|> symbolAsString
611− "#" -> unescapedSymbolAsString
612− "&" -> unescapedSymbolAsString
613− "_" -> unescapedSymbolAsString
614− "^" -> unescapedSymbolAsString
618− CtrlSeq _ -> macroDef (rawInline "latex")
620− <|> inlineEnvironment
624inlines :: PandocMonad m => LP m Inlines
1168inlines :: PandocMonad m => LP m Inlines
625inlines = mconcat <$> many inline
1169inlines = mconcat <$> many inline
627−opt :: PandocMonad m => LP m Inlines
629− toks <- try (sp *> bracketedToks <* sp)
630− -- now parse the toks as inlines
632− parsed <- runParserT (mconcat <$> many inline) st "bracketed option" toks
634− Right result -> return result
635− Left e -> throwError $ PandocParsecError (toSources toks) e
637-- block elements:
1171-- block elements:
639preamble :: PandocMonad m => LP m Blocks
1173preamble :: PandocMonad m => LP m Blocks
@@ -727,6 +1261,10 @@ insertIncluded defaultExtension f' = do
727 getInput >>= setInput . (tokenize f contents ++)
1261 getInput >>= setInput . (tokenize f contents ++)
728 updateState dropLatestIncludeFile
1262 updateState dropLatestIncludeFile
1264+addMeta :: PandocMonad m => ToMetaValue a => Text -> a -> LP m ()
1265+addMeta field val = updateState $ \st ->
1266+ st{ sMeta = addMetaField field val $ sMeta st }
730authors :: PandocMonad m => LP m ()
1268authors :: PandocMonad m => LP m ()
731authors = try $ do
1269authors = try $ do
@@ -735,6 +1273,143 @@ authors = try $ do
736 addMeta "author" (map trimInlines auths)
1274 addMeta "author" (map trimInlines auths)
1276+macroDef :: (PandocMonad m, Monoid a) => (Text -> a) -> LP m a
1277+macroDef constructor = do
1278+ (_, s) <- withRaw (commandDef <|> environmentDef)
1279+ (constructor (untokenize s) <$
1280+ guardDisabled Ext_latex_macros)
1282+ where commandDef = do
1283+ (name, macro') <- newcommand <|> letmacro <|> defmacro
1284+ guardDisabled Ext_latex_macros <|>
1285+ updateState (\s -> s{ sMacros = M.insert name macro' (sMacros s) })
1286+ environmentDef = do
1287+ mbenv <- newenvironment
1289+ Nothing -> return ()
1290+ Just (name, macro1, macro2) ->
1291+ guardDisabled Ext_latex_macros <|>
1292+ do updateState $ \s -> s{ sMacros =
1293+ M.insert name macro1 (sMacros s) }
1294+ updateState $ \s -> s{ sMacros =
1295+ M.insert ("end" <> name) macro2 (sMacros s) }
1296+ -- @\newenvironment{envname}[n-args][default]{begin}{end}@
1297+ -- is equivalent to
1298+ -- @\newcommand{\envname}[n-args][default]{begin}@
1299+ -- @\newcommand{\endenvname}@
1301+letmacro :: PandocMonad m => LP m (Text, Macro)
1304+ (name, contents) <- withVerbatimMode $ do
1305+ Tok _ (CtrlSeq name) _ <- anyControlSeq
1306+ optional $ symbol '='
1308+ -- we first parse in verbatim mode, and then expand macros,
1309+ -- because we don't want \let\foo\bar to turn into
1310+ -- \let\foo hello if we have previously \def\bar{hello}
1311+ contents <- bracedOrToken
1312+ return (name, contents)
1313+ contents' <- doMacros' 0 contents
1314+ return (name, Macro ExpandWhenDefined [] Nothing contents')
1316+defmacro :: PandocMonad m => LP m (Text, Macro)
1318+ -- we use withVerbatimMode, because macros are to be expanded
1319+ -- at point of use, not point of definition
1320+ withVerbatimMode $ do
1322+ Tok _ (CtrlSeq name) _ <- anyControlSeq
1323+ argspecs <- many (argspecArg <|> argspecPattern)
1324+ contents <- bracedOrToken
1325+ return (name, Macro ExpandWhenUsed argspecs Nothing contents)
1327+argspecArg :: PandocMonad m => LP m ArgSpec
1329+ Tok _ (Arg i) _ <- satisfyTok isArgTok
1332+argspecPattern :: PandocMonad m => LP m ArgSpec
1334+ Pattern <$> many1 (satisfyTok (\(Tok _ toktype' txt) ->
1335+ (toktype' == Symbol || toktype' == Word) &&
1336+ (txt /= "{" && txt /= "\\" && txt /= "}")))
1338+newcommand :: PandocMonad m => LP m (Text, Macro)
1341+ Tok _ (CtrlSeq mtype) _ <- controlSeq "newcommand" <|>
1342+ controlSeq "renewcommand" <|>
1343+ controlSeq "providecommand" <|>
1344+ controlSeq "DeclareMathOperator" <|>
1345+ controlSeq "DeclareRobustCommand"
1346+ withVerbatimMode $ do
1347+ Tok _ (CtrlSeq name) txt <- do
1348+ optional (symbol '*')
1350+ (symbol '{' *> spaces *> anyControlSeq <* spaces <* symbol '}')
1352+ numargs <- option 0 $ try bracketedNum
1353+ let argspecs = map ArgNum [1..numargs]
1355+ optarg <- option Nothing $ Just <$> try bracketedToks
1357+ contents' <- bracedOrToken
1360+ "DeclareMathOperator" ->
1361+ Tok pos (CtrlSeq "mathop") "\\mathop"
1362+ : Tok pos Symbol "{"
1363+ : Tok pos (CtrlSeq "mathrm") "\\mathrm"
1364+ : Tok pos Symbol "{"
1366+ [ Tok pos Symbol "}", Tok pos Symbol "}" ])
1368+ macros <- sMacros <$> getState
1369+ case M.lookup name macros of
1371+ | mtype == "newcommand" -> do
1372+ report $ MacroAlreadyDefined txt pos
1373+ return (name, macro)
1374+ | mtype == "providecommand" -> return (name, macro)
1375+ _ -> return (name, Macro ExpandWhenUsed argspecs optarg contents)
1377+newenvironment :: PandocMonad m => LP m (Maybe (Text, Macro, Macro))
1380+ Tok _ (CtrlSeq mtype) _ <- controlSeq "newenvironment" <|>
1381+ controlSeq "renewenvironment" <|>
1382+ controlSeq "provideenvironment"
1383+ withVerbatimMode $ do
1384+ optional $ symbol '*'
1386+ name <- untokenize <$> braced
1388+ numargs <- option 0 $ try bracketedNum
1390+ optarg <- option Nothing $ Just <$> try bracketedToks
1391+ let argspecs = map (\i -> ArgNum i) [1..numargs]
1392+ startcontents <- spaces >> bracedOrToken
1393+ endcontents <- spaces >> bracedOrToken
1394+ macros <- sMacros <$> getState
1395+ case M.lookup name macros of
1397+ | mtype == "newenvironment" -> do
1398+ report $ MacroAlreadyDefined name pos
1400+ | mtype == "provideenvironment" ->
1402+ _ -> return $ Just (name,
1403+ Macro ExpandWhenUsed argspecs optarg startcontents,
1404+ Macro ExpandWhenUsed [] Nothing endcontents)
1406+bracketedNum :: PandocMonad m => LP m Int
1408+ ds <- untokenize <$> bracketedToks
1409+ case safeRead ds of
738looseItem :: PandocMonad m => LP m Blocks
1413looseItem :: PandocMonad m => LP m Blocks
739looseItem = do
1414looseItem = do
740 inListItem <- sInListItem <$> getState
1415 inListItem <- sInListItem <$> getState
@@ -840,7 +1515,7 @@ blockCommands = M.fromList
840 , ("address", mempty <$ (skipopts *> tok >>= addMeta "address"))
1515 , ("address", mempty <$ (skipopts *> tok >>= addMeta "address"))
841 , ("signature", mempty <$ (skipopts *> authors))
1516 , ("signature", mempty <$ (skipopts *> authors))
842 , ("date", mempty <$ (skipopts *> tok >>= addMeta "date"))
1517 , ("date", mempty <$ (skipopts *> tok >>= addMeta "date"))
843− , ("newtheorem", newtheorem inline)
1518+ , ("newtheorem", newtheorem)
844 , ("theoremstyle", theoremstyle)
1519 , ("theoremstyle", theoremstyle)
845 -- KOMA-Script metadata commands
1520 -- KOMA-Script metadata commands
846 , ("extratitle", mempty <$ (skipopts *> tok >>= addMeta "extratitle"))
1521 , ("extratitle", mempty <$ (skipopts *> tok >>= addMeta "extratitle"))
@@ -959,7 +1634,7 @@ environments = M.union (tableEnvironments blocks inline) $
959 , ("lilypond", rawVerbEnv "lilypond")
1634 , ("lilypond", rawVerbEnv "lilypond")
960 , ("ly", rawVerbEnv "ly")
1635 , ("ly", rawVerbEnv "ly")
961 -- amsthm
1636 -- amsthm
962− , ("proof", proof blocks opt)
1637+ , ("proof", proof)
963 -- etoolbox
1638 -- etoolbox
964 , ("ifstrequal", ifstrequal)
1639 , ("ifstrequal", ifstrequal)
965 , ("newtoggle", braced >>= newToggle)
1640 , ("newtoggle", braced >>= newToggle)
@@ -980,17 +1655,128 @@ filecontents = try $ do
980 st{ sFileContents = M.insert fp txt (sFileContents st) }
1655 st{ sFileContents = M.insert fp txt (sFileContents st) }
981 return mempty
1656 return mempty
1658+theoremstyle :: PandocMonad m => LP m Blocks
1660+ stylename <- untokenize <$> braced
1661+ let mbstyle = case stylename of
1662+ "plain" -> Just PlainStyle
1663+ "definition" -> Just DefinitionStyle
1664+ "remark" -> Just RemarkStyle
1667+ Nothing -> return ()
1668+ Just sty -> updateState $ \s -> s{ sLastTheoremStyle = sty }
1671+newtheorem :: PandocMonad m => LP m Blocks
1673+ number <- option True (False <$ symbol '*' <* sp)
1674+ name <- untokenize <$> braced
1676+ series <- option Nothing $ Just . untokenize <$> bracketedToks
1680+ syncTo <- option Nothing $ Just . untokenize <$> bracketedToks
1681+ sty <- sLastTheoremStyle <$> getState
1682+ let spec = TheoremSpec { theoremName = showName
1683+ , theoremStyle = sty
1684+ , theoremSeries = series
1685+ , theoremSyncTo = syncTo
1686+ , theoremNumber = number
1687+ , theoremLastNum = DottedNum [0] }
1688+ tmap <- sTheoremMap <$> getState
1689+ updateState $ \s -> s{ sTheoremMap =
1690+ M.insert name spec tmap }
1693+proof :: PandocMonad m => LP m Blocks
1695+ title <- option (B.text "Proof") opt
1696+ bs <- env "proof" blocks
1698+ B.divWith ("", ["proof"], []) $
1699+ addQed $ addTitle (B.emph (title <> ".")) bs
1701+addTitle :: Inlines -> Blocks -> Blocks
1703+ case B.toList bs of
1705+ -> B.fromList (Para (B.toList ils ++ (Space : xs)) : rest)
1706+ _ -> B.para ils <> bs
1708+addQed :: Blocks -> Blocks
1710+ case Seq.viewr (B.unMany bs) of
1712+ -> B.Many (s Seq.|> Para (ils ++ B.toList qedSign))
1713+ _ -> bs <> B.para qedSign
1715+ qedSign = B.str "\xa0\x25FB"
983environment :: PandocMonad m => LP m Blocks
1717environment :: PandocMonad m => LP m Blocks
984environment = try $ do
1718environment = try $ do
985 controlSeq "begin"
1719 controlSeq "begin"
986 name <- untokenize <$> braced
1720 name <- untokenize <$> braced
987 M.findWithDefault mzero name environments <|>
1721 M.findWithDefault mzero name environments <|>
988− theoremEnvironment blocks opt name <|>
1722+ theoremEnvironment name <|>
989 if M.member name (inlineEnvironments
1723 if M.member name (inlineEnvironments
990 :: M.Map Text (LP PandocPure Inlines))
1724 :: M.Map Text (LP PandocPure Inlines))
991 then mzero
1725 then mzero
992 else try (rawEnv name) <|> rawVerbEnv name
1726 else try (rawEnv name) <|> rawVerbEnv name
1728+theoremEnvironment :: PandocMonad m => Text -> LP m Blocks
1729+theoremEnvironment name = do
1730+ tmap <- sTheoremMap <$> getState
1731+ case M.lookup name tmap of
1734+ optTitle <- option mempty $ (\x -> space <> "(" <> x <> ")") <$> opt
1735+ mblabel <- option Nothing $ Just . untokenize <$>
1736+ try (spaces >> controlSeq "label" >> spaces >> braced)
1737+ bs <- env name blocks
1739+ if theoremNumber tspec
1741+ let name' = fromMaybe name $ theoremSeries tspec
1742+ num <- getNextNumber
1743+ (maybe (DottedNum [0]) theoremLastNum .
1744+ M.lookup name' . sTheoremMap)
1745+ updateState $ \s ->
1748+ (\spec -> spec{ theoremLastNum = num })
1755+ updateState $ \s ->
1756+ s{ sLabels = M.insert ident
1758+ theoremName tspec <> "\160" <>
1759+ str (renderDottedNum num)) (sLabels s) }
1760+ Nothing -> return ()
1761+ return $ space <> B.text (renderDottedNum num)
1763+ let titleEmph = case theoremStyle tspec of
1764+ PlainStyle -> B.strong
1765+ DefinitionStyle -> B.strong
1766+ RemarkStyle -> B.emph
1767+ let title = titleEmph (theoremName tspec <> number)
1768+ <> optTitle <> "." <> space
1769+ return $ divWith (fromMaybe "" mblabel, [name], []) $ addTitle title
1770+ $ case theoremStyle tspec of
1771+ PlainStyle -> walk italicize bs
1774+italicize :: Block -> Block
1775+italicize x@(Para [Image{}]) = x -- see #6925
1776+italicize (Para ils) = Para [Emph ils]
1777+italicize (Plain ils) = Plain [Emph ils]
994rawEnv :: PandocMonad m => Text -> LP m Blocks
1780rawEnv :: PandocMonad m => Text -> LP m Blocks
995rawEnv name = do
1781rawEnv name = do
996 exts <- getOption readerExtensions
1782 exts <- getOption readerExtensions
@@ -1162,8 +1948,7 @@ inputListing = do
1162 let (ident,classes,kvs) = parseListingsOptions options
1948 let (ident,classes,kvs) = parseListingsOptions options
1163 let classes' =
1949 let classes' =
1164 (case listingsLanguage options of
1950 (case listingsLanguage options of
1165− Nothing -> (take 1 (languagesByExtension defaultSyntaxMap
1951+ Nothing -> (take 1 (languagesByExtension (T.pack $ takeExtension $ T.unpack f)) <>)
1166− (T.pack $ takeExtension $ T.unpack f)) <>)
1167 Just _ -> id) classes
1952 Just _ -> id) classes
1168 let firstline = fromMaybe 1 $ lookup "firstline" options >>= safeRead
1953 let firstline = fromMaybe 1 $ lookup "firstline" options >>= safeRead
1169 let lastline = fromMaybe (length codeLines) $
1954 let lastline = fromMaybe (length codeLines) $
@@ -1231,21 +2016,27 @@ orderedList' = try $ do
1232block :: PandocMonad m => LP m Blocks
2017block :: PandocMonad m => LP m Blocks
1233block = do
2018block = do
1234− Tok _ toktype _ <- lookAhead anyTok
2019+ res <- (mempty <$ spaces1)
1235− res <- (case toktype of
2020+ <|> environment
1236− Newline -> mempty <$ spaces1
2021+ <|> macroDef (rawBlock "latex")
1237− Spaces -> mempty <$ spaces1
2022+ <|> blockCommand
1238− Comment -> mempty <$ spaces1
2023+ <|> paragraph
1239− Word -> paragraph
2024+ <|> grouped block
1240− CtrlSeq "begin" -> environment
1241− CtrlSeq _ -> macroDef (rawBlock "latex")
1246 trace (T.take 60 $ tshow $ B.toList res)
2025 trace (T.take 60 $ tshow $ B.toList res)
1247 return res
2026 return res
1249blocks :: PandocMonad m => LP m Blocks
2028blocks :: PandocMonad m => LP m Blocks
1250blocks = mconcat <$> many block
2029blocks = mconcat <$> many block
2031+setDefaultLanguage :: PandocMonad m => LP m Blocks
2032+setDefaultLanguage = do
2033+ o <- option "" $ T.filter (\c -> c /= '[' && c /= ']')
2035+ polylang <- untokenize <$> braced
2036+ case M.lookup polylang polyglossiaLangToBCP47 of
2037+ Nothing -> return mempty -- TODO mzero? warning?
2038+ Just langFunc -> do
2041+ updateState $ setMeta "lang" $ str (renderLang l)