@@ -1,14 +1,10 @@
1−{-# LANGUAGE BangPatterns #-}
2−{-# LANGUAGE CPP #-}
3−{-# LANGUAGE FlexibleInstances #-}
4−{-# LANGUAGE MultiParamTypeClasses #-}
51{-# LANGUAGE OverloadedStrings #-}
62{-# LANGUAGE PatternGuards #-}
73{-# LANGUAGE ScopedTypeVariables #-}
84{-# LANGUAGE ViewPatterns #-}
95{- |
106 Module : Text.Pandoc.Readers.LaTeX
11− Copyright : Copyright (C) 2006-2020 John MacFarlane
7+ Copyright : Copyright (C) 2006-2021 John MacFarlane
128 License : GNU GPL, version 2 or above
139
1410 Maintainer : John MacFarlane <jgm@berkeley.edu>
@@ -22,50 +18,58 @@ module Text.Pandoc.Readers.LaTeX ( readLaTeX,
2218 applyMacros,
2319 rawLaTeXInline,
2420 rawLaTeXBlock,
25− inlineCommand,
26− tokenize,
27− untokenize
21+ inlineCommand
2822 ) where
2923
3024import Control.Applicative (many, optional, (<|>))
3125import Control.Monad
3226import Control.Monad.Except (throwError)
33−import Data.Char (isDigit, isLetter, toUpper, chr)
27+import Data.Char (isDigit, isLetter, isAlphaNum, toUpper, chr)
3428import Data.Default
35−import Data.Functor (($>))
3629import Data.List (intercalate)
3730import qualified Data.Map as M
3831import Data.Maybe (fromMaybe, maybeToList)
3932import qualified Data.Set as Set
40−import qualified Data.Sequence as Seq
4133import Data.Text (Text)
4234import qualified Data.Text as T
35+import Skylighting (defaultSyntaxMap)
4336import System.FilePath (addExtension, replaceExtension, takeExtension)
44−import Text.Pandoc.BCP47 (Lang (..), renderLang)
45−import Text.Pandoc.Builder
37+import Text.Collate.Lang (renderLang)
38+import Text.Pandoc.Builder as B
4639import Text.Pandoc.Class.PandocPure (PandocPure)
4740import Text.Pandoc.Class.PandocMonad (PandocMonad (..), getResourcePath,
48− readFileFromDirs, report, setResourcePath,
49− setTranslations, translateTerm)
41+ readFileFromDirs, report,
42+ setResourcePath)
5043import Text.Pandoc.Error (PandocError (PandocParseError, PandocParsecError))
51−import Text.Pandoc.Highlighting (fromListingsLanguage, languagesByExtension)
44+import Text.Pandoc.Highlighting (languagesByExtension)
5245import Text.Pandoc.ImageSize (numUnit, showFl)
5346import Text.Pandoc.Logging
5447import Text.Pandoc.Options
5548import Text.Pandoc.Parsing hiding (blankline, many, mathDisplay, mathInline,
5649 optional, space, spaces, withRaw, (<|>))
57−import Text.Pandoc.Readers.LaTeX.Types (ExpansionPoint (..), Macro (..),
58− ArgSpec (..), Tok (..), TokType (..))
50+import Text.Pandoc.Readers.LaTeX.Types (Tok (..), TokType (..))
5951import Text.Pandoc.Readers.LaTeX.Parsing
60−import Text.Pandoc.Readers.LaTeX.Lang (polyglossiaLangToBCP47,
61− babelLangToBCP47)
62−import Text.Pandoc.Readers.LaTeX.SIunitx
52+import Text.Pandoc.Readers.LaTeX.Citation (citationCommands, cites)
53+import Text.Pandoc.Readers.LaTeX.Math (dollarsMath, inlineEnvironments,
54+ inlineEnvironment,
55+ mathDisplay, mathInline,
56+ newtheorem, theoremstyle, proof,
57+ theoremEnvironment)
58+import Text.Pandoc.Readers.LaTeX.Table (tableEnvironments)
59+import Text.Pandoc.Readers.LaTeX.Macro (macroDef)
60+import Text.Pandoc.Readers.LaTeX.Lang (inlineLanguageCommands,
61+ enquoteCommands,
62+ babelLangToBCP47, setDefaultLanguage)
63+import Text.Pandoc.Readers.LaTeX.SIunitx (siunitxCommands)
64+import Text.Pandoc.Readers.LaTeX.Inline (acronymCommands, refCommands,
65+ nameCommands, charCommands,
66+ accentCommands,
67+ biblatexInlineCommands,
68+ verbCommands, rawInlineOr,
69+ listingsLanguage)
6370import Text.Pandoc.Shared
64−import qualified Text.Pandoc.Translations as Translations
6571import Text.Pandoc.Walk
66−import qualified Text.Pandoc.Builder as B
67−import qualified Data.Text.Normalize as Normalize
68−import Safe
72+import Data.List.NonEmpty (nonEmpty)
6973
7074-- for debugging:
7175-- import Text.Pandoc.Extensions (getDefaultExtensions)
@@ -73,16 +77,17 @@ import Safe
7377-- import Debug.Trace (traceShowId)
7478
7579-- | Parse LaTeX from string and return 'Pandoc' document.
76−readLaTeX :: PandocMonad m
80+readLaTeX :: (PandocMonad m, ToSources a)
7781 => ReaderOptions -- ^ Reader options
78− -> Text -- ^ String to parse (assumes @'\n'@ line endings)
82+ -> a -- ^ Input to parse
7983 -> m Pandoc
8084readLaTeX opts ltx = do
85+ let sources = toSources ltx
8186 parsed <- runParserT parseLaTeX def{ sOptions = opts } "source"
82− (tokenize "source" (crFilter ltx))
87+ (tokenizeSources sources)
8388 case parsed of
8489 Right result -> return result
85− Left e -> throwError $ PandocParsecError ltx e
90+ Left e -> throwError $ PandocParsecError sources e
8691
8792parseLaTeX :: PandocMonad m => LP m Pandoc
8893parseLaTeX = do
@@ -93,11 +98,7 @@ parseLaTeX = do
9398 let doc' = doc bs
9499 let headerLevel (Header n _ _) = [n]
95100 headerLevel _ = []
96−#if MIN_VERSION_safe(0,3,18)
97− let bottomLevel = minimumBound 1 $ query headerLevel doc'
98−#else
99− let bottomLevel = minimumDef 1 $ query headerLevel doc'
100−#endif
101+ let bottomLevel = maybe 1 minimum $ nonEmpty $ query headerLevel doc'
101102 let adjustHeaders m (Header n attr ils) = Header (n+m) attr ils
102103 adjustHeaders _ x = x
103104 let (Pandoc _ bs') =
@@ -132,11 +133,11 @@ resolveRefs _ x = x
132133
133134
134135rawLaTeXBlock :: (PandocMonad m, HasMacros s, HasReaderOptions s)
135− => ParserT Text s m Text
136+ => ParserT Sources s m Text
136137rawLaTeXBlock = do
137138 lookAhead (try (char '\\' >> letter))
138139 inp <- getInput
139− let toks = tokenize "source" inp
140+ let toks = tokenizeSources inp
140141 snd <$> (rawLaTeXParser toks False (macroDef (const mempty)) blocks
141142 <|> rawLaTeXParser toks True
142143 (do choice (map controlSeq
@@ -163,14 +164,14 @@ beginOrEndCommand = try $ do
163164 (txt <> untokenize rawargs)
164165
165166rawLaTeXInline :: (PandocMonad m, HasMacros s, HasReaderOptions s)
166− => ParserT Text s m Text
167+ => ParserT Sources s m Text
167168rawLaTeXInline = do
168169 lookAhead (try (char '\\' >> letter))
169170 inp <- getInput
170− let toks = tokenize "source" inp
171+ let toks = tokenizeSources inp
171172 raw <- snd <$>
172173 ( rawLaTeXParser toks True
173− (mempty <$ (controlSeq "input" >> skipMany opt >> braced))
174+ (mempty <$ (controlSeq "input" >> skipMany rawopt >> braced))
174175 inlines
175176 <|> rawLaTeXParser toks True (inlineEnvironment <|> inlineCommand')
176177 inlines
@@ -178,11 +179,11 @@ rawLaTeXInline = do
178179 finalbraces <- mconcat <$> many (try (string "{}")) -- see #5439
179180 return $ raw <> T.pack finalbraces
180181
181−inlineCommand :: PandocMonad m => ParserT Text ParserState m Inlines
182+inlineCommand :: PandocMonad m => ParserT Sources ParserState m Inlines
182183inlineCommand = do
183184 lookAhead (try (char '\\' >> letter))
184185 inp <- getInput
185− let toks = tokenize "source" inp
186+ let toks = tokenizeSources inp
186187 fst <$> rawLaTeXParser toks True (inlineEnvironment <|> inlineCommand')
187188 inlines
188189
@@ -191,12 +192,6 @@ inlineCommand = do
191192word :: PandocMonad m => LP m Inlines
192193word = str . untoken <$> satisfyTok isWordTok
193194
194−regularSymbol :: PandocMonad m => LP m Inlines
195−regularSymbol = str . untoken <$> satisfyTok isRegularSymbol
196− where isRegularSymbol (Tok _ Symbol t) = not $ T.any isSpecial t
197− isRegularSymbol _ = False
198− isSpecial c = c `Set.member` specialChars
199−
200195inlineGroup :: PandocMonad m => LP m Inlines
201196inlineGroup = do
202197 ils <- grouped inline
@@ -237,19 +232,6 @@ mkImage options (T.unpack -> src) = do
237232 _ -> return src
238233 return $ imageWith attr (T.pack src') "" alt
239234
240−doxspace :: PandocMonad m => LP m Inlines
241−doxspace =
242− (space <$ lookAhead (satisfyTok startsWithLetter)) <|> return mempty
243− where startsWithLetter (Tok _ Word t) =
244− case T.uncons t of
245− Just (c, _) | isLetter c -> True
246− _ -> False
247− startsWithLetter _ = False
248−
249−
250−lit :: Text -> LP m Inlines
251−lit = pure . str
252−
253235removeDoubleQuotes :: Text -> Text
254236removeDoubleQuotes t =
255237 Data.Maybe.fromMaybe t $ T.stripPrefix "\"" t >>= T.stripSuffix "\""
@@ -296,23 +278,14 @@ quoted' f starter ender = do
296278 cs -> cs)
297279 else lit startchs
298280
299−enquote :: PandocMonad m => Bool -> Maybe Text -> LP m Inlines
300−enquote starred mblang = do
301− skipopts
302− let lang = mblang >>= babelLangToBCP47
303− let langspan = case lang of
304− Nothing -> id
305− Just l -> spanWith ("",[],[("lang", renderLang l)])
306− quoteContext <- sQuoteContext <$> getState
307− if starred || quoteContext == InDoubleQuote
308− then singleQuoted . langspan <$> withQuoteContext InSingleQuote tok
309− else doubleQuoted . langspan <$> withQuoteContext InDoubleQuote tok
281+lit :: Text -> LP m Inlines
282+lit = pure . str
310283
311284blockquote :: PandocMonad m => Bool -> Maybe Text -> LP m Blocks
312285blockquote cvariant mblang = do
313286 citepar <- if cvariant
314287 then (\xs -> para (cite xs mempty))
315− <$> cites NormalCitation False
288+ <$> cites inline NormalCitation False
316289 else option mempty $ para <$> bracketed inline
317290 let lang = mblang >>= babelLangToBCP47
318291 let langdiv = case lang of
@@ -323,224 +296,13 @@ blockquote cvariant mblang = do
323296 optional $ symbolIn (".:;?!" :: [Char]) -- currently ignored
324297 return $ blockQuote . langdiv $ (bs <> citepar)
325298
326−doAcronym :: PandocMonad m => Text -> LP m Inlines
327−doAcronym form = do
328− acro <- braced
329− return . mconcat $ [spanWith ("",[],[("acronym-label", untokenize acro),
330− ("acronym-form", "singular+" <> form)])
331− $ str $ untokenize acro]
332−
333−doAcronymPlural :: PandocMonad m => Text -> LP m Inlines
334−doAcronymPlural form = do
335− acro <- braced
336− plural <- lit "s"
337− return . mconcat $ [spanWith ("",[],[("acronym-label", untokenize acro),
338− ("acronym-form", "plural+" <> form)]) $
339− mconcat [str $ untokenize acro, plural]]
340−
341−doverb :: PandocMonad m => LP m Inlines
342−doverb = do
343− Tok _ Symbol t <- anySymbol
344− marker <- case T.uncons t of
345− Just (c, ts) | T.null ts -> return c
346− _ -> mzero
347− withVerbatimMode $
348− code . untokenize <$>
349− manyTill (notFollowedBy newlineTok >> verbTok marker) (symbol marker)
350−
351−verbTok :: PandocMonad m => Char -> LP m Tok
352−verbTok stopchar = do
353− t@(Tok pos toktype txt) <- anyTok
354− case T.findIndex (== stopchar) txt of
355− Nothing -> return t
356− Just i -> do
357− let (t1, t2) = T.splitAt i txt
358− inp <- getInput
359− setInput $ Tok (incSourceColumn pos i) Symbol (T.singleton stopchar)
360− : totoks (incSourceColumn pos (i + 1)) (T.drop 1 t2) ++ inp
361− return $ Tok pos toktype t1
362−
363−listingsLanguage :: [(Text, Text)] -> Maybe Text
364−listingsLanguage opts =
365− case lookup "language" opts of
366− Nothing -> Nothing
367− Just l -> fromListingsLanguage l `mplus` Just l
368−
369−dolstinline :: PandocMonad m => LP m Inlines
370−dolstinline = do
371− options <- option [] keyvals
372− let classes = maybeToList $ listingsLanguage options
373− doinlinecode classes
374−
375−domintinline :: PandocMonad m => LP m Inlines
376−domintinline = do
377− skipopts
378− cls <- untokenize <$> braced
379− doinlinecode [cls]
380−
381−doinlinecode :: PandocMonad m => [Text] -> LP m Inlines
382−doinlinecode classes = do
383− Tok _ Symbol t <- anySymbol
384− marker <- case T.uncons t of
385− Just (c, ts) | T.null ts -> return c
386− _ -> mzero
387− let stopchar = if marker == '{' then '}' else marker
388− withVerbatimMode $
389− codeWith ("",classes,[]) . T.map nlToSpace . untokenize <$>
390− manyTill (verbTok stopchar) (symbol stopchar)
391−
392−nlToSpace :: Char -> Char
393−nlToSpace '\n' = ' '
394−nlToSpace x = x
395−
396−mathDisplay :: Text -> Inlines
397−mathDisplay = displayMath . trimMath
398−
399−mathInline :: Text -> Inlines
400−mathInline = math . trimMath
401−
402−dollarsMath :: PandocMonad m => LP m Inlines
403−dollarsMath = do
404− symbol '$'
405− display <- option False (True <$ symbol '$')
406− (do contents <- try $ untokenize <$> pDollarsMath 0
407− if display
408− then mathDisplay contents <$ symbol '$'
409− else return $ mathInline contents)
410− <|> (guard display >> return (mathInline ""))
411−
412−-- Int is number of embedded groupings
413−pDollarsMath :: PandocMonad m => Int -> LP m [Tok]
414−pDollarsMath n = do
415− tk@(Tok _ toktype t) <- anyTok
416− case toktype of
417− Symbol | t == "$"
418− , n == 0 -> return []
419− | t == "\\" -> do
420− tk' <- anyTok
421− (tk :) . (tk' :) <$> pDollarsMath n
422− | t == "{" -> (tk :) <$> pDollarsMath (n+1)
423− | t == "}" ->
424− if n > 0
425− then (tk :) <$> pDollarsMath (n-1)
426− else mzero
427− _ -> (tk :) <$> pDollarsMath n
428−
429−-- citations
430−
431−addPrefix :: [Inline] -> [Citation] -> [Citation]
432−addPrefix p (k:ks) = k {citationPrefix = p ++ citationPrefix k} : ks
433−addPrefix _ _ = []
434−
435−addSuffix :: [Inline] -> [Citation] -> [Citation]
436−addSuffix s ks@(_:_) =
437− let k = last ks
438− in init ks ++ [k {citationSuffix = citationSuffix k ++ s}]
439−addSuffix _ _ = []
440−
441−simpleCiteArgs :: PandocMonad m => LP m [Citation]
442−simpleCiteArgs = try $ do
443− first <- optionMaybe $ toList <$> opt
444− second <- optionMaybe $ toList <$> opt
445− keys <- try $ bgroup *> manyTill citationLabel egroup
446− let (pre, suf) = case (first , second ) of
447− (Just s , Nothing) -> (mempty, s )
448− (Just s , Just t ) -> (s , t )
449− _ -> (mempty, mempty)
450− conv k = Citation { citationId = k
451− , citationPrefix = []
452− , citationSuffix = []
453− , citationMode = NormalCitation
454− , citationHash = 0
455− , citationNoteNum = 0
456− }
457− return $ addPrefix pre $ addSuffix suf $ map conv keys
458−
459−citationLabel :: PandocMonad m => LP m Text
460−citationLabel = do
461− sp
462− untokenize <$>
463− (many1 (satisfyTok isWordTok <|> symbolIn bibtexKeyChar)
464− <* sp
465− <* optional (symbol ',')
466− <* sp)
467− where bibtexKeyChar = ".:;?!`'()/*@_+=-&[]" :: [Char]
468−
469−cites :: PandocMonad m => CitationMode -> Bool -> LP m [Citation]
470−cites mode multi = try $ do
471− cits <- if multi
472− then do
473− multiprenote <- optionMaybe $ toList <$> paropt
474− multipostnote <- optionMaybe $ toList <$> paropt
475− let (pre, suf) = case (multiprenote, multipostnote) of
476− (Just s , Nothing) -> (mempty, s)
477− (Nothing , Just t) -> (mempty, t)
478− (Just s , Just t ) -> (s, t)
479− _ -> (mempty, mempty)
480− tempCits <- many1 simpleCiteArgs
481− case tempCits of
482− (k:ks) -> case ks of
483− (_:_) -> return $ (addMprenote pre k : init ks) ++
484− [addMpostnote suf (last ks)]
485− _ -> return [addMprenote pre (addMpostnote suf k)]
486− _ -> return [[]]
487− else count 1 simpleCiteArgs
488− let cs = concat cits
489− return $ case mode of
490− AuthorInText -> case cs of
491− (c:rest) -> c {citationMode = mode} : rest
492− [] -> []
493− _ -> map (\a -> a {citationMode = mode}) cs
494− where mprenote (k:ks) = (k:ks) ++ [Space]
495− mprenote _ = mempty
496− mpostnote (k:ks) = [Str ",", Space] ++ (k:ks)
497− mpostnote _ = mempty
498− addMprenote mpn (k:ks) =
499− let mpnfinal = case citationPrefix k of
500− (_:_) -> mprenote mpn
501− _ -> mpn
502− in addPrefix mpnfinal (k:ks)
503− addMprenote _ _ = []
504− addMpostnote = addSuffix . mpostnote
505−
506−citation :: PandocMonad m => Text -> CitationMode -> Bool -> LP m Inlines
507−citation name mode multi = do
508− (c,raw) <- withRaw $ cites mode multi
509− return $ cite c (rawInline "latex" $ "\\" <> name <> untokenize raw)
510−
511−handleCitationPart :: Inlines -> [Citation]
512−handleCitationPart ils =
513− let isCite Cite{} = True
514− isCite _ = False
515− (pref, rest) = break isCite (toList ils)
516− in case rest of
517− (Cite cs _:suff) -> addPrefix pref $ addSuffix suff cs
518− _ -> []
519−
520−complexNatbibCitation :: PandocMonad m => CitationMode -> LP m Inlines
521−complexNatbibCitation mode = try $ do
522− (cs, raw) <-
523− withRaw $ concat <$> do
524− bgroup
525− items <- mconcat <$>
526− many1 (notFollowedBy (symbol ';') >> inline)
527− `sepBy1` symbol ';'
528− egroup
529− return $ map handleCitationPart items
530− case cs of
531− [] -> mzero
532− (c:cits) -> return $ cite (c{ citationMode = mode }:cits)
533− (rawInline "latex" $ "\\citetext" <> untokenize raw)
534−
535−inNote :: Inlines -> Inlines
536−inNote ils =
537− note $ para $ ils <> str "."
538−
539299inlineCommand' :: PandocMonad m => LP m Inlines
540300inlineCommand' = try $ do
541301 Tok _ (CtrlSeq name) cmd <- anyControlSeq
542302 guard $ name /= "begin" && name /= "end" && name /= "and"
543− star <- option "" ("*" <$ symbol '*' <* sp)
303+ star <- if T.all isAlphaNum name
304+ then option "" ("*" <$ symbol '*' <* sp)
305+ else pure ""
544306 overlay <- option "" overlaySpecification
545307 let name' = name <> star <> overlay
546308 let names = ordNub [name', name] -- check non-starred as fallback
@@ -551,28 +313,8 @@ inlineCommand' = try $ do
551313 <|> ignore rawcommand
552314 lookupListDefault raw names inlineCommands
553315
554−
555316tok :: PandocMonad m => LP m Inlines
556−tok = try $ spaces >> grouped inline <|> inlineCommand' <|> singleChar'
557− where singleChar' = do
558− Tok _ _ t <- singleChar
559− return $ str t
560−
561−opt :: PandocMonad m => LP m Inlines
562−opt = do
563− toks <- try (sp *> bracketedToks <* sp)
564− -- now parse the toks as inlines
565− st <- getState
566− parsed <- runParserT (mconcat <$> many inline) st "bracketed option" toks
567− case parsed of
568− Right result -> return result
569− Left e -> throwError $ PandocParsecError (untokenize toks) e
570−
571−paropt :: PandocMonad m => LP m Inlines
572−paropt = parenWrapped inline
573−
574−inBrackets :: Inlines -> Inlines
575−inBrackets x = str "[" <> x <> str "]"
317+tok = tokWith inline
576318
577319unescapeURL :: Text -> Text
578320unescapeURL = T.concat . go . T.splitOn "\\"
@@ -585,379 +327,107 @@ unescapeURL = T.concat . go . T.splitOn "\\"
585327 , isEscapable c = t
586328 | otherwise = "\\" <> t
587329
588−mathEnvWith :: PandocMonad m
589− => (Inlines -> a) -> Maybe Text -> Text -> LP m a
590−mathEnvWith f innerEnv name = f . mathDisplay . inner <$> mathEnv name
591− where inner x = case innerEnv of
592− Nothing -> x
593− Just y -> "\\begin{" <> y <> "}\n" <> x <>
594− "\\end{" <> y <> "}"
595−
596−mathEnv :: PandocMonad m => Text -> LP m Text
597−mathEnv name = do
598− skipopts
599− optional blankline
600− res <- manyTill anyTok (end_ name)
601− return $ stripTrailingNewlines $ untokenize res
602−
603−inlineEnvironment :: PandocMonad m => LP m Inlines
604−inlineEnvironment = try $ do
605− controlSeq "begin"
606− name <- untokenize <$> braced
607− M.findWithDefault mzero name inlineEnvironments
608−
609−inlineEnvironments :: PandocMonad m => M.Map Text (LP m Inlines)
610−inlineEnvironments = M.fromList [
611− ("displaymath", mathEnvWith id Nothing "displaymath")
612− , ("math", math <$> mathEnv "math")
613− , ("equation", mathEnvWith id Nothing "equation")
614− , ("equation*", mathEnvWith id Nothing "equation*")
615− , ("gather", mathEnvWith id (Just "gathered") "gather")
616− , ("gather*", mathEnvWith id (Just "gathered") "gather*")
617− , ("multline", mathEnvWith id (Just "gathered") "multline")
618− , ("multline*", mathEnvWith id (Just "gathered") "multline*")
619− , ("eqnarray", mathEnvWith id (Just "aligned") "eqnarray")
620− , ("eqnarray*", mathEnvWith id (Just "aligned") "eqnarray*")
621− , ("align", mathEnvWith id (Just "aligned") "align")
622− , ("align*", mathEnvWith id (Just "aligned") "align*")
623− , ("alignat", mathEnvWith id (Just "aligned") "alignat")
624− , ("alignat*", mathEnvWith id (Just "aligned") "alignat*")
625− , ("dmath", mathEnvWith id Nothing "dmath")
626− , ("dmath*", mathEnvWith id Nothing "dmath*")
627− , ("dgroup", mathEnvWith id (Just "aligned") "dgroup")
628− , ("dgroup*", mathEnvWith id (Just "aligned") "dgroup*")
629− , ("darray", mathEnvWith id (Just "aligned") "darray")
630− , ("darray*", mathEnvWith id (Just "aligned") "darray*")
631− ]
632−
633330inlineCommands :: PandocMonad m => M.Map Text (LP m Inlines)
634−inlineCommands = M.union inlineLanguageCommands $ M.fromList
635− [ ("emph", extractSpaces emph <$> tok)
636− , ("textit", extractSpaces emph <$> tok)
637− , ("textsl", extractSpaces emph <$> tok)
638− , ("textsc", extractSpaces smallcaps <$> tok)
639− , ("textsf", extractSpaces (spanWith ("",["sans-serif"],[])) <$> tok)
640− , ("textmd", extractSpaces (spanWith ("",["medium"],[])) <$> tok)
641− , ("textrm", extractSpaces (spanWith ("",["roman"],[])) <$> tok)
642− , ("textup", extractSpaces (spanWith ("",["upright"],[])) <$> tok)
643− , ("texttt", ttfamily)
644− , ("sout", extractSpaces strikeout <$> tok)
645− , ("alert", skipopts >> spanWith ("",["alert"],[]) <$> tok) -- beamer
646− , ("lq", return (str "‘"))
647− , ("rq", return (str "’"))
648− , ("textquoteleft", return (str "‘"))
649− , ("textquoteright", return (str "’"))
650− , ("textquotedblleft", return (str "“"))
651− , ("textquotedblright", return (str "”"))
652− , ("textsuperscript", extractSpaces superscript <$> tok)
653− , ("textsubscript", extractSpaces subscript <$> tok)
654− , ("textbackslash", lit "\\")
655− , ("backslash", lit "\\")
656− , ("slash", lit "/")
657− , ("textbf", extractSpaces strong <$> tok)
658− , ("textnormal", extractSpaces (spanWith ("",["nodecor"],[])) <$> tok)
659− , ("underline", underline <$> tok)
660− , ("ldots", lit "…")
661− , ("vdots", lit "\8942")
662− , ("dots", lit "…")
663− , ("mdots", lit "…")
664− , ("sim", lit "~")
665− , ("sep", lit ",")
666− , ("label", rawInlineOr "label" dolabel)
667− , ("ref", rawInlineOr "ref" $ doref "ref")
668− , ("cref", rawInlineOr "cref" $ doref "ref") -- from cleveref.sty
669− , ("vref", rawInlineOr "vref" $ doref "ref+page") -- from varioref.sty
670− , ("eqref", rawInlineOr "eqref" $ doref "eqref") -- from amsmath.sty
671− , ("mbox", rawInlineOr "mbox" $ processHBox <$> tok)
672− , ("hbox", rawInlineOr "hbox" $ processHBox <$> tok)
673− , ("lettrine", rawInlineOr "lettrine" lettrine)
674− , ("(", mathInline . untokenize <$> manyTill anyTok (controlSeq ")"))
675− , ("[", mathDisplay . untokenize <$> manyTill anyTok (controlSeq "]"))
676− , ("ensuremath", mathInline . untokenize <$> braced)
677− , ("texorpdfstring", const <$> tok <*> tok)
678− , ("P", lit "¶")
679− , ("S", lit "§")
680− , ("$", lit "$")
681− , ("%", lit "%")
682− , ("&", lit "&")
683− , ("#", lit "#")
684− , ("_", lit "_")
685− , ("{", lit "{")
686− , ("}", lit "}")
687− , ("qed", lit "\a0\x25FB")
688− -- old TeX commands
689− , ("em", extractSpaces emph <$> inlines)
690− , ("it", extractSpaces emph <$> inlines)
691− , ("sl", extractSpaces emph <$> inlines)
692− , ("bf", extractSpaces strong <$> inlines)
693− , ("tt", code . stringify . toList <$> inlines)
694− , ("rm", inlines)
695− , ("itshape", extractSpaces emph <$> inlines)
696− , ("slshape", extractSpaces emph <$> inlines)
697− , ("scshape", extractSpaces smallcaps <$> inlines)
698− , ("bfseries", extractSpaces strong <$> inlines)
699− , ("MakeUppercase", makeUppercase <$> tok)
700− , ("MakeTextUppercase", makeUppercase <$> tok) -- textcase
701− , ("uppercase", makeUppercase <$> tok)
702− , ("MakeLowercase", makeLowercase <$> tok)
703− , ("MakeTextLowercase", makeLowercase <$> tok)
704− , ("lowercase", makeLowercase <$> tok)
705− , ("/", pure mempty) -- italic correction
706− , ("aa", lit "å")
707− , ("AA", lit "Å")
708− , ("ss", lit "ß")
709− , ("o", lit "ø")
710− , ("O", lit "Ø")
711− , ("L", lit "Ł")
712− , ("l", lit "ł")
713− , ("ae", lit "æ")
714− , ("AE", lit "Æ")
715− , ("oe", lit "œ")
716− , ("OE", lit "Œ")
717− , ("pounds", lit "£")
718− , ("euro", lit "€")
719− , ("copyright", lit "©")
720− , ("textasciicircum", lit "^")
721− , ("textasciitilde", lit "~")
722− , ("H", accent '\779' Nothing) -- hungarumlaut
723− , ("`", accent '\768' (Just '`')) -- grave
724− , ("'", accent '\769' (Just '\'')) -- acute
725− , ("^", accent '\770' (Just '^')) -- circ
726− , ("~", accent '\771' (Just '~')) -- tilde
727− , ("\"", accent '\776' Nothing) -- umlaut
728− , (".", accent '\775' Nothing) -- dot
729− , ("=", accent '\772' Nothing) -- macron
730− , ("|", accent '\781' Nothing) -- vertical line above
731− , ("b", accent '\817' Nothing) -- macron below
732− , ("c", accent '\807' Nothing) -- cedilla
733− , ("G", accent '\783' Nothing) -- doublegrave
734− , ("h", accent '\777' Nothing) -- hookabove
735− , ("d", accent '\803' Nothing) -- dotbelow
736− , ("f", accent '\785' Nothing) -- inverted breve
737− , ("r", accent '\778' Nothing) -- ringabove
738− , ("t", accent '\865' Nothing) -- double inverted breve
739− , ("U", accent '\782' Nothing) -- double vertical line above
740− , ("v", accent '\780' Nothing) -- hacek
741− , ("u", accent '\774' Nothing) -- breve
742− , ("k", accent '\808' Nothing) -- ogonek
743− , ("textogonekcentered", accent '\808' Nothing) -- ogonek
744− , ("i", lit "ı") -- dotless i
745− , ("j", lit "ȷ") -- dotless j
746− , ("newtie", accent '\785' Nothing) -- inverted breve
747− , ("textcircled", accent '\8413' Nothing) -- combining circle
748− , ("\\", linebreak <$ (do inTableCell <- sInTableCell <$> getState
749− guard $ not inTableCell
750− optional opt
751− spaces))
752− , (",", lit "\8198")
753− , ("@", pure mempty)
754− , (" ", lit "\160")
755− , ("ps", pure $ str "PS." <> space)
756− , ("TeX", lit "TeX")
757− , ("LaTeX", lit "LaTeX")
758− , ("bar", lit "|")
759− , ("textless", lit "<")
760− , ("textgreater", lit ">")
761− , ("thanks", skipopts >> note <$> grouped block)
762− , ("footnote", skipopts >> note <$> grouped block)
763− , ("passthrough", tok) -- \passthrough macro used by latex writer
764− -- for listings
765− , ("verb", doverb)
766− , ("lstinline", dolstinline)
767− , ("mintinline", domintinline)
768− , ("Verb", doverb)
769− , ("url", (\url -> link url "" (str url)) . unescapeURL . untokenize <$>
770− bracedUrl)
771− , ("nolinkurl", code . unescapeURL . untokenize <$> bracedUrl)
772− , ("href", do url <- bracedUrl
773− sp
774− link (unescapeURL $ untokenize url) "" <$> tok)
775− , ("includegraphics", do options <- option [] keyvals
776− src <- braced
777− mkImage options . unescapeURL . removeDoubleQuotes $
778− untokenize src)
779− , ("enquote*", enquote True Nothing)
780− , ("enquote", enquote False Nothing)
781− -- foreignquote is supposed to use native quote marks
782− , ("foreignquote*", braced >>= enquote True . Just . untokenize)
783− , ("foreignquote", braced >>= enquote False . Just . untokenize)
784− -- hypehnquote uses regular quotes
785− , ("hyphenquote*", braced >>= enquote True . Just . untokenize)
786− , ("hyphenquote", braced >>= enquote False . Just . untokenize)
787− , ("figurename", doTerm Translations.Figure)
788− , ("prefacename", doTerm Translations.Preface)
789− , ("refname", doTerm Translations.References)
790− , ("bibname", doTerm Translations.Bibliography)
791− , ("chaptername", doTerm Translations.Chapter)
792− , ("partname", doTerm Translations.Part)
793− , ("contentsname", doTerm Translations.Contents)
794− , ("listfigurename", doTerm Translations.ListOfFigures)
795− , ("listtablename", doTerm Translations.ListOfTables)
796− , ("indexname", doTerm Translations.Index)
797− , ("abstractname", doTerm Translations.Abstract)
798− , ("tablename", doTerm Translations.Table)
799− , ("enclname", doTerm Translations.Encl)
800− , ("ccname", doTerm Translations.Cc)
801− , ("headtoname", doTerm Translations.To)
802− , ("pagename", doTerm Translations.Page)
803− , ("seename", doTerm Translations.See)
804− , ("seealsoname", doTerm Translations.SeeAlso)
805− , ("proofname", doTerm Translations.Proof)
806− , ("glossaryname", doTerm Translations.Glossary)
807− , ("lstlistingname", doTerm Translations.Listing)
808− , ("cite", citation "cite" NormalCitation False)
809− , ("Cite", citation "Cite" NormalCitation False)
810− , ("citep", citation "citep" NormalCitation False)
811− , ("citep*", citation "citep*" NormalCitation False)
812− , ("citeal", citation "citeal" NormalCitation False)
813− , ("citealp", citation "citealp" NormalCitation False)
814− , ("citealp*", citation "citealp*" NormalCitation False)
815− , ("autocite", citation "autocite" NormalCitation False)
816− , ("smartcite", citation "smartcite" NormalCitation False)
817− , ("footcite", inNote <$> citation "footcite" NormalCitation False)
818− , ("parencite", citation "parencite" NormalCitation False)
819− , ("supercite", citation "supercite" NormalCitation False)
820− , ("footcitetext", inNote <$> citation "footcitetext" NormalCitation False)
821− , ("citeyearpar", citation "citeyearpar" SuppressAuthor False)
822− , ("citeyear", citation "citeyear" SuppressAuthor False)
823− , ("autocite*", citation "autocite*" SuppressAuthor False)
824− , ("cite*", citation "cite*" SuppressAuthor False)
825− , ("parencite*", citation "parencite*" SuppressAuthor False)
826− , ("textcite", citation "textcite" AuthorInText False)
827− , ("citet", citation "citet" AuthorInText False)
828− , ("citet*", citation "citet*" AuthorInText False)
829− , ("citealt", citation "citealt" AuthorInText False)
830− , ("citealt*", citation "citealt*" AuthorInText False)
831− , ("textcites", citation "textcites" AuthorInText True)
832− , ("cites", citation "cites" NormalCitation True)
833− , ("autocites", citation "autocites" NormalCitation True)
834− , ("footcites", inNote <$> citation "footcites" NormalCitation True)
835− , ("parencites", citation "parencites" NormalCitation True)
836− , ("supercites", citation "supercites" NormalCitation True)
837− , ("footcitetexts", inNote <$> citation "footcitetexts" NormalCitation True)
838− , ("Autocite", citation "Autocite" NormalCitation False)
839− , ("Smartcite", citation "Smartcite" NormalCitation False)
840− , ("Footcite", inNote <$> citation "Footcite" NormalCitation False)
841− , ("Parencite", citation "Parencite" NormalCitation False)
842− , ("Supercite", citation "Supercite" NormalCitation False)
843− , ("Footcitetext", inNote <$> citation "Footcitetext" NormalCitation False)
844− , ("Citeyearpar", citation "Citeyearpar" SuppressAuthor False)
845− , ("Citeyear", citation "Citeyear" SuppressAuthor False)
846− , ("Autocite*", citation "Autocite*" SuppressAuthor False)
847− , ("Cite*", citation "Cite*" SuppressAuthor False)
848− , ("Parencite*", citation "Parencite*" SuppressAuthor False)
849− , ("Textcite", citation "Textcite" AuthorInText False)
850− , ("Textcites", citation "Textcites" AuthorInText True)
851− , ("Cites", citation "Cites" NormalCitation True)
852− , ("Autocites", citation "Autocites" NormalCitation True)
853− , ("Footcites", inNote <$> citation "Footcites" NormalCitation True)
854− , ("Parencites", citation "Parencites" NormalCitation True)
855− , ("Supercites", citation "Supercites" NormalCitation True)
856− , ("Footcitetexts", inNote <$> citation "Footcitetexts" NormalCitation True)
857− , ("citetext", complexNatbibCitation NormalCitation)
858− , ("citeauthor", (try (tok *> sp *> controlSeq "citetext") *>
859− complexNatbibCitation AuthorInText)
860− <|> citation "citeauthor" AuthorInText False)
861− , ("nocite", mempty <$ (citation "nocite" NormalCitation False >>=
862− addMeta "nocite"))
863− , ("hyperlink", hyperlink)
864− , ("hypertarget", hypertargetInline)
865− -- glossaries package
866− , ("gls", doAcronym "short")
867− , ("Gls", doAcronym "short")
868− , ("glsdesc", doAcronym "long")
869− , ("Glsdesc", doAcronym "long")
870− , ("GLSdesc", doAcronym "long")
871− , ("acrlong", doAcronym "long")
872− , ("Acrlong", doAcronym "long")
873− , ("acrfull", doAcronym "full")
874− , ("Acrfull", doAcronym "full")
875− , ("acrshort", doAcronym "abbrv")
876− , ("Acrshort", doAcronym "abbrv")
877− , ("glspl", doAcronymPlural "short")
878− , ("Glspl", doAcronymPlural "short")
879− , ("glsdescplural", doAcronymPlural "long")
880− , ("Glsdescplural", doAcronymPlural "long")
881− , ("GLSdescplural", doAcronymPlural "long")
882− -- acronyms package
883− , ("ac", doAcronym "short")
884− , ("acf", doAcronym "full")
885− , ("acs", doAcronym "abbrv")
886− , ("acl", doAcronym "long")
887− , ("acp", doAcronymPlural "short")
888− , ("acfp", doAcronymPlural "full")
889− , ("acsp", doAcronymPlural "abbrv")
890− , ("aclp", doAcronymPlural "long")
891− , ("Ac", doAcronym "short")
892− , ("Acf", doAcronym "full")
893− , ("Acs", doAcronym "abbrv")
894− , ("Acl", doAcronym "long")
895− , ("Acp", doAcronymPlural "short")
896− , ("Acfp", doAcronymPlural "full")
897− , ("Acsp", doAcronymPlural "abbrv")
898− , ("Aclp", doAcronymPlural "long")
899− -- siuntix
900− , ("si", skipopts *> dosi tok)
901− , ("SI", doSI tok)
902− , ("SIrange", doSIrange True tok)
903− , ("numrange", doSIrange False tok)
904− , ("numlist", doSInumlist)
905− , ("num", doSInum)
906− , ("ang", doSIang)
907− -- hyphenat
908− , ("bshyp", lit "\\\173")
909− , ("fshyp", lit "/\173")
910− , ("dothyp", lit ".\173")
911− , ("colonhyp", lit ":\173")
912− , ("hyp", lit "-")
913− , ("nohyphens", tok)
914− , ("textnhtt", ttfamily)
915− , ("nhttfamily", ttfamily)
916− -- LaTeX colors
917− , ("textcolor", coloredInline "color")
918− , ("colorbox", coloredInline "background-color")
919− -- fontawesome
920− , ("faCheck", lit "\10003")
921− , ("faClose", lit "\10007")
922− -- xspace
923− , ("xspace", doxspace)
924− -- etoolbox
925− , ("ifstrequal", ifstrequal)
926− , ("newtoggle", braced >>= newToggle)
927− , ("toggletrue", braced >>= setToggle True)
928− , ("togglefalse", braced >>= setToggle False)
929− , ("iftoggle", try $ ifToggle >> inline)
930− -- biblatex misc
931− , ("RN", romanNumeralUpper)
932− , ("Rn", romanNumeralLower)
933− -- babel
934− , ("foreignlanguage", foreignlanguage)
935− -- include
936− , ("input", rawInlineOr "input" $ include "input")
937− -- soul package
938− , ("ul", underline <$> tok)
939− -- ulem package
940− , ("uline", underline <$> tok)
941− -- plain tex stuff that should just be passed through as raw tex
942− , ("ifdim", ifdim)
943− ]
944−
945−accent :: PandocMonad m => Char -> Maybe Char -> LP m Inlines
946−accent combiningAccent fallBack = try $ do
947− ils <- tok
948− case toList ils of
949− (Str (T.uncons -> Just (x, xs)) : ys) -> return $ fromList $
950− -- try to normalize to the combined character:
951− Str (Normalize.normalize Normalize.NFC
952− (T.pack [x, combiningAccent]) <> xs) : ys
953− [Space] -> return $ str $ T.singleton $ fromMaybe combiningAccent fallBack
954− [] -> return $ str $ T.singleton $ fromMaybe combiningAccent fallBack
955− _ -> return ils
956−
331+inlineCommands = M.unions
332+ [ accentCommands tok
333+ , citationCommands inline
334+ , siunitxCommands tok
335+ , acronymCommands
336+ , refCommands
337+ , nameCommands
338+ , verbCommands
339+ , charCommands
340+ , enquoteCommands tok
341+ , inlineLanguageCommands tok
342+ , biblatexInlineCommands tok
343+ , rest ]
344+ where
345+ rest = M.fromList
346+ [ ("emph", extractSpaces emph <$> tok)
347+ , ("textit", extractSpaces emph <$> tok)
348+ , ("textsl", extractSpaces emph <$> tok)
349+ , ("textsc", extractSpaces smallcaps <$> tok)
350+ , ("textsf", extractSpaces (spanWith ("",["sans-serif"],[])) <$> tok)
351+ , ("textmd", extractSpaces (spanWith ("",["medium"],[])) <$> tok)
352+ , ("textrm", extractSpaces (spanWith ("",["roman"],[])) <$> tok)
353+ , ("textup", extractSpaces (spanWith ("",["upright"],[])) <$> tok)
354+ , ("texttt", ttfamily)
355+ , ("sout", extractSpaces strikeout <$> tok)
356+ , ("alert", skipopts >> spanWith ("",["alert"],[]) <$> tok) -- beamer
357+ , ("textsuperscript", extractSpaces superscript <$> tok)
358+ , ("textsubscript", extractSpaces subscript <$> tok)
359+ , ("textbf", extractSpaces strong <$> tok)
360+ , ("textnormal", extractSpaces (spanWith ("",["nodecor"],[])) <$> tok)
361+ , ("underline", underline <$> tok)
362+ , ("mbox", rawInlineOr "mbox" $ processHBox <$> tok)
363+ , ("hbox", rawInlineOr "hbox" $ processHBox <$> tok)
364+ , ("lettrine", rawInlineOr "lettrine" lettrine)
365+ , ("(", mathInline . untokenize <$> manyTill anyTok (controlSeq ")"))
366+ , ("[", mathDisplay . untokenize <$> manyTill anyTok (controlSeq "]"))
367+ , ("ensuremath", mathInline . untokenize <$> braced)
368+ , ("texorpdfstring", const <$> tok <*> tok)
369+ -- old TeX commands
370+ , ("em", extractSpaces emph <$> inlines)
371+ , ("it", extractSpaces emph <$> inlines)
372+ , ("sl", extractSpaces emph <$> inlines)
373+ , ("bf", extractSpaces strong <$> inlines)
374+ , ("tt", code . stringify . toList <$> inlines)
375+ , ("rm", inlines)
376+ , ("itshape", extractSpaces emph <$> inlines)
377+ , ("slshape", extractSpaces emph <$> inlines)
378+ , ("scshape", extractSpaces smallcaps <$> inlines)
379+ , ("bfseries", extractSpaces strong <$> inlines)
380+ , ("MakeUppercase", makeUppercase <$> tok)
381+ , ("MakeTextUppercase", makeUppercase <$> tok) -- textcase
382+ , ("uppercase", makeUppercase <$> tok)
383+ , ("MakeLowercase", makeLowercase <$> tok)
384+ , ("MakeTextLowercase", makeLowercase <$> tok)
385+ , ("lowercase", makeLowercase <$> tok)
386+ , ("thanks", skipopts >> note <$> grouped block)
387+ , ("footnote", skipopts >> note <$> grouped block)
388+ , ("passthrough", tok) -- \passthrough macro used by latex writer
389+ -- for listings
390+ , ("includegraphics", do options <- option [] keyvals
391+ src <- braced
392+ mkImage options .
393+ unescapeURL .
394+ removeDoubleQuotes $ untokenize src)
395+ -- hyperref
396+ , ("url", (\url -> link url "" (str url)) . unescapeURL . untokenize <$>
397+ bracedUrl)
398+ , ("nolinkurl", code . unescapeURL . untokenize <$> bracedUrl)
399+ , ("href", do url <- bracedUrl
400+ sp
401+ link (unescapeURL $ untokenize url) "" <$> tok)
402+ , ("hyperlink", hyperlink)
403+ , ("hyperref", hyperref)
404+ , ("hypertarget", hypertargetInline)
405+ -- hyphenat
406+ , ("nohyphens", tok)
407+ , ("textnhtt", ttfamily)
408+ , ("nhttfamily", ttfamily)
409+ -- LaTeX colors
410+ , ("textcolor", coloredInline "color")
411+ , ("colorbox", coloredInline "background-color")
412+ -- etoolbox
413+ , ("ifstrequal", ifstrequal)
414+ , ("newtoggle", braced >>= newToggle)
415+ , ("toggletrue", braced >>= setToggle True)
416+ , ("togglefalse", braced >>= setToggle False)
417+ , ("iftoggle", try $ ifToggle >> inline)
418+ -- include
419+ , ("input", rawInlineOr "input" $ include "input")
420+ -- soul package
421+ , ("ul", underline <$> tok)
422+ -- ulem package
423+ , ("uline", underline <$> tok)
424+ -- plain tex stuff that should just be passed through as raw tex
425+ , ("ifdim", ifdim)
426+ ]
957427
958428lettrine :: PandocMonad m => LP m Inlines
959429lettrine = do
960− optional opt
430+ optional rawopt
961431 x <- tok
962432 y <- tok
963433 return $ extractSpaces (spanWith ("",["lettrine"],[])) x <> smallcaps y
@@ -977,32 +447,18 @@ alterStr :: (Text -> Text) -> Inline -> Inline
977447alterStr f (Str xs) = Str (f xs)
978448alterStr _ x = x
979449
980−foreignlanguage :: PandocMonad m => LP m Inlines
981−foreignlanguage = do
982− babelLang <- untokenize <$> braced
983− case babelLangToBCP47 babelLang of
984− Just lang -> spanWith ("", [], [("lang", renderLang lang)]) <$> tok
985− _ -> tok
986−
987−inlineLanguageCommands :: PandocMonad m => M.Map Text (LP m Inlines)
988−inlineLanguageCommands = M.fromList $ mk <$> M.toList polyglossiaLangToBCP47
989− where
990− mk (polyglossia, bcp47Func) =
991− ("text" <> polyglossia, inlineLanguage bcp47Func)
992−
993−inlineLanguage :: PandocMonad m => (Text -> Lang) -> LP m Inlines
994−inlineLanguage bcp47Func = do
995− o <- option "" $ T.filter (\c -> c /= '[' && c /= ']')
996− <$> rawopt
997− let lang = renderLang $ bcp47Func o
998− extractSpaces (spanWith ("", [], [("lang", lang)])) <$> tok
999−
1000450hyperlink :: PandocMonad m => LP m Inlines
1001451hyperlink = try $ do
1002452 src <- untokenize <$> braced
1003453 lab <- tok
1004454 return $ link ("#" <> src) "" lab
1005455
456+hyperref :: PandocMonad m => LP m Inlines
457+hyperref = try $ do
458+ url <- (("#" <>) . untokenize <$> try (sp *> bracketedToks <* sp))
459+ <|> untokenize <$> (bracedUrl <* bracedUrl <* bracedUrl)
460+ link url "" <$> tok
461+
1006462hypertargetBlock :: PandocMonad m => LP m Blocks
1007463hypertargetBlock = try $ do
1008464 ref <- untokenize <$> braced
@@ -1017,31 +473,6 @@ hypertargetInline = try $ do
1017473 ils <- grouped inline
1018474 return $ spanWith (ref, [], []) ils
1019475
1020−romanNumeralUpper :: (PandocMonad m) => LP m Inlines
1021−romanNumeralUpper =
1022− str . toRomanNumeral <$> romanNumeralArg
1023−
1024−romanNumeralLower :: (PandocMonad m) => LP m Inlines
1025−romanNumeralLower =
1026− str . T.toLower . toRomanNumeral <$> romanNumeralArg
1027−
1028−romanNumeralArg :: (PandocMonad m) => LP m Int
1029−romanNumeralArg = spaces *> (parser <|> inBraces)
1030− where
1031− inBraces = do
1032− symbol '{'
1033− spaces
1034− res <- parser
1035− spaces
1036− symbol '}'
1037− return res
1038− parser = do
1039− Tok _ Word s <- satisfyTok isWordTok
1040− let (digits, rest) = T.span isDigit s
1041− unless (T.null rest) $
1042− Prelude.fail "Non-digits in argument to \\Rn or \\RN"
1043− safeRead digits
1044−
1045476newToggle :: (Monoid a, PandocMonad m) => [Tok] -> LP m a
1046477newToggle name = do
1047478 updateState $ \st ->
@@ -1072,9 +503,6 @@ ifToggle = do
1072503 report $ UndefinedToggle name' pos
1073504 return ()
1074505
1075−doTerm :: PandocMonad m => Translations.Term -> LP m Inlines
1076−doTerm term = str <$> translateTerm term
1077−
1078506ifstrequal :: (PandocMonad m, Monoid a) => LP m a
1079507ifstrequal = do
1080508 str1 <- tok
@@ -1095,13 +523,6 @@ coloredInline stylename = do
1095523ttfamily :: PandocMonad m => LP m Inlines
1096524ttfamily = code . stringify . toList <$> tok
1097525
1098−rawInlineOr :: PandocMonad m => Text -> LP m Inlines -> LP m Inlines
1099−rawInlineOr name' fallback = do
1100− parseRaw <- extensionEnabled Ext_raw_tex <$> getOption readerExtensions
1101− if parseRaw
1102− then rawInline "latex" <$> getRawCommand name' ("\\" <> name')
1103− else fallback
1104−
1105526processHBox :: Inlines -> Inlines
1106527processHBox = walk convert
1107528 where
@@ -1152,79 +573,90 @@ treatAsInline = Set.fromList
1152573 , "pagebreak"
1153574 ]
1154575
1155−label :: PandocMonad m => LP m ()
1156−label = do
1157− controlSeq "label"
1158− t <- braced
1159− updateState $ \st -> st{ sLastLabel = Just $ untokenize t }
1160−
1161−dolabel :: PandocMonad m => LP m Inlines
1162−dolabel = do
1163− v <- braced
1164− let refstr = untokenize v
1165− updateState $ \st ->
1166− st{ sLastLabel = Just refstr }
1167− return $ spanWith (refstr,[],[("label", refstr)])
1168− $ inBrackets $ str $ untokenize v
1169−
1170−doref :: PandocMonad m => Text -> LP m Inlines
1171−doref cls = do
1172− v <- braced
1173− let refstr = untokenize v
1174− return $ linkWith ("",[],[ ("reference-type", cls)
1175− , ("reference", refstr)])
1176− ("#" <> refstr)
1177− ""
1178− (inBrackets $ str refstr)
1179−
1180576lookupListDefault :: (Ord k) => v -> [k] -> M.Map k v -> v
1181577lookupListDefault d = (fromMaybe d .) . lookupList
1182578 where lookupList l m = msum $ map (`M.lookup` m) l
1183579
1184580inline :: PandocMonad m => LP m Inlines
1185−inline = (mempty <$ comment)
1186− <|> (space <$ whitespace)
1187− <|> (softbreak <$ endline)
1188− <|> word
1189− <|> macroDef (rawInline "latex")
1190− <|> inlineCommand'
1191− <|> inlineEnvironment
1192− <|> inlineGroup
1193− <|> (symbol '-' *>
1194− option (str "-") (symbol '-' *>
1195− option (str "–") (str "—" <$ symbol '-')))
1196− <|> doubleQuote
1197− <|> singleQuote
1198− <|> (str "”" <$ try (symbol '\'' >> symbol '\''))
1199− <|> (str "”" <$ symbol '”')
1200− <|> (str "’" <$ symbol '\'')
1201− <|> (str "’" <$ symbol '’')
1202− <|> (str "\160" <$ symbol '~')
1203− <|> dollarsMath
1204− <|> (guardEnabled Ext_literate_haskell *> symbol '|' *> doLHSverb)
1205− <|> (str . T.singleton <$> primEscape)
1206− <|> regularSymbol
1207− <|> (do res <- symbolIn "#^'`\"[]&"
1208− pos <- getPosition
1209− let s = untoken res
1210− report $ ParsingUnescaped s pos
1211− return $ str s)
581+inline = do
582+ Tok pos toktype t <- lookAhead anyTok
583+ let symbolAsString = str . untoken <$> anySymbol
584+ let unescapedSymbolAsString =
585+ do s <- untoken <$> anySymbol
586+ report $ ParsingUnescaped s pos
587+ return $ str s
588+ case toktype of
589+ Comment -> mempty <$ comment
590+ Spaces -> space <$ whitespace
591+ Newline -> softbreak <$ endline
592+ Word -> word
593+ Esc1 -> str . T.singleton <$> primEscape
594+ Esc2 -> str . T.singleton <$> primEscape
595+ Symbol ->
596+ case t of
597+ "-" -> symbol '-' *>
598+ option (str "-") (symbol '-' *>
599+ option (str "–") (str "—" <$ symbol '-'))
600+ "'" -> symbol '\'' *>
601+ option (str "’") (str "”" <$ symbol '\'')
602+ "~" -> str "\160" <$ symbol '~'
603+ "`" -> doubleQuote <|> singleQuote <|> symbolAsString
604+ "\"" -> doubleQuote <|> singleQuote <|> symbolAsString
605+ "“" -> doubleQuote <|> symbolAsString
606+ "‘" -> singleQuote <|> symbolAsString
607+ "$" -> dollarsMath <|> unescapedSymbolAsString
608+ "|" -> (guardEnabled Ext_literate_haskell *>
609+ symbol '|' *> doLHSverb) <|> symbolAsString
610+ "{" -> inlineGroup
611+ "#" -> unescapedSymbolAsString
612+ "&" -> unescapedSymbolAsString
613+ "_" -> unescapedSymbolAsString
614+ "^" -> unescapedSymbolAsString
615+ "\\" -> mzero
616+ "}" -> mzero
617+ _ -> symbolAsString
618+ CtrlSeq _ -> macroDef (rawInline "latex")
619+ <|> inlineCommand'
620+ <|> inlineEnvironment
621+ <|> inlineGroup
622+ _ -> mzero
1212623
1213624inlines :: PandocMonad m => LP m Inlines
1214625inlines = mconcat <$> many inline
1215626
627+opt :: PandocMonad m => LP m Inlines
628+opt = do
629+ toks <- try (sp *> bracketedToks <* sp)
630+ -- now parse the toks as inlines
631+ st <- getState
632+ parsed <- runParserT (mconcat <$> many inline) st "bracketed option" toks
633+ case parsed of
634+ Right result -> return result
635+ Left e -> throwError $ PandocParsecError (toSources toks) e
636+
1216637-- block elements:
1217638
1218639preamble :: PandocMonad m => LP m Blocks
1219640preamble = mconcat <$> many preambleBlock
1220641 where preambleBlock = (mempty <$ spaces1)
1221642 <|> macroDef (rawBlock "latex")
643+ <|> filecontents
1222644 <|> (mempty <$ blockCommand)
1223645 <|> (mempty <$ braced)
1224646 <|> (do notFollowedBy (begin_ "document")
1225647 anyTok
1226648 return mempty)
1227649
650+rule :: PandocMonad m => LP m Blocks
651+rule = do
652+ skipopts
653+ width <- T.takeWhile (\c -> isDigit c || c == '.') . stringify <$> tok
654+ _thickness <- tok
655+ -- 0-width rules are used to fix spacing issues:
656+ case safeRead width of
657+ Just (0 :: Double) -> return mempty
658+ _ -> return horizontalRule
659+
1228660paragraph :: PandocMonad m => LP m Blocks
1229661paragraph = do
1230662 x <- trimInlines . mconcat <$> many1 inline
@@ -1262,6 +694,16 @@ include name = do
1262694 mapM_ (insertIncluded defaultExt) fs
1263695 return mempty
1264696
697+readFileFromTexinputs :: PandocMonad m => FilePath -> LP m (Maybe Text)
698+readFileFromTexinputs fp = do
699+ fileContentsMap <- sFileContents <$> getState
700+ case M.lookup (T.pack fp) fileContentsMap of
701+ Just t -> return (Just t)
702+ Nothing -> do
703+ dirs <- map T.unpack . splitTextBy (==':') . fromMaybe "."
704+ <$> lookupEnv "TEXINPUTS"
705+ readFileFromDirs dirs fp
706+
1265707insertIncluded :: PandocMonad m
1266708 => FilePath
1267709 -> FilePath
@@ -1271,13 +713,12 @@ insertIncluded defaultExtension f' = do
1271713 ".tex" -> f'
1272714 ".sty" -> f'
1273715 _ -> addExtension f' defaultExtension
1274− dirs <- map T.unpack . splitTextBy (==':') . fromMaybe "." <$> lookupEnv "TEXINPUTS"
1275716 pos <- getPosition
1276717 containers <- getIncludeFiles <$> getState
1277718 when (T.pack f `elem` containers) $
1278719 throwError $ PandocParseError $ T.pack $ "Include file loop at " ++ show pos
1279720 updateState $ addIncludeFile $ T.pack f
1280− mbcontents <- readFileFromDirs dirs f
721+ mbcontents <- readFileFromTexinputs f
1281722 contents <- case mbcontents of
1282723 Just s -> return s
1283724 Nothing -> do
@@ -1286,10 +727,6 @@ insertIncluded defaultExtension f' = do
1286727 getInput >>= setInput . (tokenize f contents ++)
1287728 updateState dropLatestIncludeFile
1288729
1289−addMeta :: PandocMonad m => ToMetaValue a => Text -> a -> LP m ()
1290−addMeta field val = updateState $ \st ->
1291− st{ sMeta = addMetaField field val $ sMeta st }
1292−
1293730authors :: PandocMonad m => LP m ()
1294731authors = try $ do
1295732 bgroup
@@ -1298,150 +735,6 @@ authors = try $ do
1298735 egroup
1299736 addMeta "author" (map trimInlines auths)
1300737
1301−macroDef :: (PandocMonad m, Monoid a) => (Text -> a) -> LP m a
1302−macroDef constructor = do
1303− (_, s) <- withRaw (commandDef <|> environmentDef)
1304− (constructor (untokenize s) <$
1305− guardDisabled Ext_latex_macros)
1306− <|> return mempty
1307− where commandDef = do
1308− (name, macro') <- newcommand <|> letmacro <|> defmacro
1309− guardDisabled Ext_latex_macros <|>
1310− updateState (\s -> s{ sMacros = M.insert name macro' (sMacros s) })
1311− environmentDef = do
1312− mbenv <- newenvironment
1313− case mbenv of
1314− Nothing -> return ()
1315− Just (name, macro1, macro2) ->
1316− guardDisabled Ext_latex_macros <|>
1317− do updateState $ \s -> s{ sMacros =
1318− M.insert name macro1 (sMacros s) }
1319− updateState $ \s -> s{ sMacros =
1320− M.insert ("end" <> name) macro2 (sMacros s) }
1321− -- @\newenvironment{envname}[n-args][default]{begin}{end}@
1322− -- is equivalent to
1323− -- @\newcommand{\envname}[n-args][default]{begin}@
1324− -- @\newcommand{\endenvname}@
1325−
1326−letmacro :: PandocMonad m => LP m (Text, Macro)
1327−letmacro = do
1328− controlSeq "let"
1329− (name, contents) <- withVerbatimMode $ do
1330− Tok _ (CtrlSeq name) _ <- anyControlSeq
1331− optional $ symbol '='
1332− spaces
1333− -- we first parse in verbatim mode, and then expand macros,
1334− -- because we don't want \let\foo\bar to turn into
1335− -- \let\foo hello if we have previously \def\bar{hello}
1336− contents <- bracedOrToken
1337− return (name, contents)
1338− contents' <- doMacros' 0 contents
1339− return (name, Macro ExpandWhenDefined [] Nothing contents')
1340−
1341−defmacro :: PandocMonad m => LP m (Text, Macro)
1342−defmacro = try $
1343− -- we use withVerbatimMode, because macros are to be expanded
1344− -- at point of use, not point of definition
1345− withVerbatimMode $ do
1346− controlSeq "def"
1347− Tok _ (CtrlSeq name) _ <- anyControlSeq
1348− argspecs <- many (argspecArg <|> argspecPattern)
1349− contents <- bracedOrToken
1350− return (name, Macro ExpandWhenUsed argspecs Nothing contents)
1351−
1352−argspecArg :: PandocMonad m => LP m ArgSpec
1353−argspecArg = do
1354− Tok _ (Arg i) _ <- satisfyTok isArgTok
1355− return $ ArgNum i
1356−
1357−argspecPattern :: PandocMonad m => LP m ArgSpec
1358−argspecPattern =
1359− Pattern <$> many1 (satisfyTok (\(Tok _ toktype' txt) ->
1360− (toktype' == Symbol || toktype' == Word) &&
1361− (txt /= "{" && txt /= "\\" && txt /= "}")))
1362−
1363−newcommand :: PandocMonad m => LP m (Text, Macro)
1364−newcommand = do
1365− pos <- getPosition
1366− Tok _ (CtrlSeq mtype) _ <- controlSeq "newcommand" <|>
1367− controlSeq "renewcommand" <|>
1368− controlSeq "providecommand" <|>
1369− controlSeq "DeclareMathOperator" <|>
1370− controlSeq "DeclareRobustCommand"
1371− withVerbatimMode $ do
1372− Tok _ (CtrlSeq name) txt <- do
1373− optional (symbol '*')
1374− anyControlSeq <|>
1375− (symbol '{' *> spaces *> anyControlSeq <* spaces <* symbol '}')
1376− spaces
1377− numargs <- option 0 $ try bracketedNum
1378− let argspecs = map ArgNum [1..numargs]
1379− spaces
1380− optarg <- option Nothing $ Just <$> try bracketedToks
1381− spaces
1382− contents' <- bracedOrToken
1383− let contents =
1384− case mtype of
1385− "DeclareMathOperator" ->
1386− Tok pos (CtrlSeq "mathop") "\\mathop"
1387− : Tok pos Symbol "{"
1388− : Tok pos (CtrlSeq "mathrm") "\\mathrm"
1389− : Tok pos Symbol "{"
1390− : (contents' ++
1391− [ Tok pos Symbol "}", Tok pos Symbol "}" ])
1392− _ -> contents'
1393− macros <- sMacros <$> getState
1394− case M.lookup name macros of
1395− Just macro
1396− | mtype == "newcommand" -> do
1397− report $ MacroAlreadyDefined txt pos
1398− return (name, macro)
1399− | mtype == "providecommand" -> return (name, macro)
1400− _ -> return (name, Macro ExpandWhenUsed argspecs optarg contents)
1401−
1402−newenvironment :: PandocMonad m => LP m (Maybe (Text, Macro, Macro))
1403−newenvironment = do
1404− pos <- getPosition
1405− Tok _ (CtrlSeq mtype) _ <- controlSeq "newenvironment" <|>
1406− controlSeq "renewenvironment" <|>
1407− controlSeq "provideenvironment"
1408− withVerbatimMode $ do
1409− optional $ symbol '*'
1410− spaces
1411− name <- untokenize <$> braced
1412− spaces
1413− numargs <- option 0 $ try bracketedNum
1414− spaces
1415− optarg <- option Nothing $ Just <$> try bracketedToks
1416− let argspecs = map (\i -> ArgNum i) [1..numargs]
1417− startcontents <- spaces >> bracedOrToken
1418− endcontents <- spaces >> bracedOrToken
1419− macros <- sMacros <$> getState
1420− case M.lookup name macros of
1421− Just _
1422− | mtype == "newenvironment" -> do
1423− report $ MacroAlreadyDefined name pos
1424− return Nothing
1425− | mtype == "provideenvironment" ->
1426− return Nothing
1427− _ -> return $ Just (name,
1428− Macro ExpandWhenUsed argspecs optarg startcontents,
1429− Macro ExpandWhenUsed [] Nothing endcontents)
1430−
1431−bracketedNum :: PandocMonad m => LP m Int
1432−bracketedNum = do
1433− ds <- untokenize <$> bracketedToks
1434− case safeRead ds of
1435− Just i -> return i
1436− _ -> return 0
1437−
1438−setCaption :: PandocMonad m => LP m ()
1439−setCaption = try $ do
1440− skipopts
1441− ils <- tok
1442− optional $ try $ spaces *> label
1443− updateState $ \st -> st{ sCaption = Just ils }
1444−
1445738looseItem :: PandocMonad m => LP m Blocks
1446739looseItem = do
1447740 inListItem <- sInListItem <$> getState
@@ -1455,10 +748,6 @@ epigraph = do
1455748 p2 <- grouped block
1456749 return $ divWith ("", ["epigraph"], []) (p1 <> p2)
1457750
1458−resetCaption :: PandocMonad m => LP m ()
1459−resetCaption = updateState $ \st -> st{ sCaption = Nothing
1460− , sLastLabel = Nothing }
1461−
1462751section :: PandocMonad m => Attr -> Int -> LP m Blocks
1463752section (ident, classes, kvs) lvl = do
1464753 skipopts
@@ -1551,7 +840,7 @@ blockCommands = M.fromList
1551840 , ("address", mempty <$ (skipopts *> tok >>= addMeta "address"))
1552841 , ("signature", mempty <$ (skipopts *> authors))
1553842 , ("date", mempty <$ (skipopts *> tok >>= addMeta "date"))
1554− , ("newtheorem", newtheorem)
843+ , ("newtheorem", newtheorem inline)
1555844 , ("theoremstyle", theoremstyle)
1556845 -- KOMA-Script metadata commands
1557846 , ("extratitle", mempty <$ (skipopts *> tok >>= addMeta "extratitle"))
@@ -1595,11 +884,11 @@ blockCommands = M.fromList
1595884 --
1596885 , ("hrule", pure horizontalRule)
1597886 , ("strut", pure mempty)
1598− , ("rule", skipopts *> tok *> tok $> horizontalRule)
887+ , ("rule", rule)
1599888 , ("item", looseItem)
1600889 , ("documentclass", skipopts *> braced *> preamble)
1601890 , ("centerline", para . trimInlines <$> (skipopts *> tok))
1602− , ("caption", mempty <$ setCaption)
891+ , ("caption", mempty <$ setCaption inline)
1603892 , ("bibliography", mempty <$ (skipopts *> braced >>=
1604893 addMeta "bibliography" . splitBibs . untokenize))
1605894 , ("addbibresource", mempty <$ (skipopts *> braced >>=
@@ -1637,7 +926,8 @@ blockCommands = M.fromList
1637926
1638927
1639928environments :: PandocMonad m => M.Map Text (LP m Blocks)
1640−environments = M.fromList
929+environments = M.union (tableEnvironments blocks inline) $
930+ M.fromList
1641931 [ ("document", env "document" blocks <* skipMany anyTok)
1642932 , ("abstract", mempty <$ (env "abstract" blocks >>= addMeta "abstract"))
1643933 , ("sloppypar", env "sloppypar" blocks)
@@ -1646,14 +936,7 @@ environments = M.fromList
1646936 skipopts *> spaces *> optional braced *> spaces *> blocks)
1647937 , ("figure", env "figure" $ skipopts *> figure)
1648938 , ("subfigure", env "subfigure" $ skipopts *> tok *> figure)
1649− , ("center", env "center" blocks)
1650− , ("longtable", env "longtable" $
1651− resetCaption *> simpTable "longtable" False >>= addTableCaption)
1652− , ("table", env "table" $
1653− skipopts *> resetCaption *> blocks >>= addTableCaption)
1654− , ("tabular*", env "tabular*" $ simpTable "tabular*" True)
1655− , ("tabularx", env "tabularx" $ simpTable "tabularx" True)
1656− , ("tabular", env "tabular" $ simpTable "tabular" False)
939+ , ("center", divWith ("", ["center"], []) <$> env "center" blocks)
1657940 , ("quote", blockQuote <$> env "quote" blocks)
1658941 , ("quotation", blockQuote <$> env "quotation" blocks)
1659942 , ("verse", blockQuote <$> env "verse" blocks)
@@ -1676,7 +959,7 @@ environments = M.fromList
1676959 , ("lilypond", rawVerbEnv "lilypond")
1677960 , ("ly", rawVerbEnv "ly")
1678961 -- amsthm
1679− , ("proof", proof)
962+ , ("proof", proof blocks opt)
1680963 -- etoolbox
1681964 , ("ifstrequal", ifstrequal)
1682965 , ("newtoggle", braced >>= newToggle)
@@ -1685,130 +968,29 @@ environments = M.fromList
1685968 , ("iftoggle", try $ ifToggle >> block)
1686969 ]
1687970
1688−theoremstyle :: PandocMonad m => LP m Blocks
1689−theoremstyle = do
1690− stylename <- untokenize <$> braced
1691− let mbstyle = case stylename of
1692− "plain" -> Just PlainStyle
1693− "definition" -> Just DefinitionStyle
1694− "remark" -> Just RemarkStyle
1695− _ -> Nothing
1696− case mbstyle of
1697− Nothing -> return ()
1698− Just sty -> updateState $ \s -> s{ sLastTheoremStyle = sty }
1699− return mempty
1700−
1701−newtheorem :: PandocMonad m => LP m Blocks
1702−newtheorem = do
1703− number <- option True (False <$ symbol '*' <* sp)
971+filecontents :: PandocMonad m => LP m Blocks
972+filecontents = try $ do
973+ controlSeq "begin"
1704974 name <- untokenize <$> braced
1705− sp
1706− series <- option Nothing $ Just . untokenize <$> bracketedToks
1707− sp
1708− showName <- tok
1709− sp
1710− syncTo <- option Nothing $ Just . untokenize <$> bracketedToks
1711− sty <- sLastTheoremStyle <$> getState
1712− let spec = TheoremSpec { theoremName = showName
1713− , theoremStyle = sty
1714− , theoremSeries = series
1715− , theoremSyncTo = syncTo
1716− , theoremNumber = number
1717− , theoremLastNum = DottedNum [0] }
1718− tmap <- sTheoremMap <$> getState
1719− updateState $ \s -> s{ sTheoremMap =
1720− M.insert name spec tmap }
975+ guard $ name == "filecontents" || name == "filecontents*"
976+ skipopts
977+ fp <- untokenize <$> braced
978+ txt <- verbEnv name
979+ updateState $ \st ->
980+ st{ sFileContents = M.insert fp txt (sFileContents st) }
1721981 return mempty
1722982
1723−proof :: PandocMonad m => LP m Blocks
1724−proof = do
1725− title <- option (B.text "Proof") opt
1726− bs <- env "proof" blocks
1727− return $
1728− B.divWith ("", ["proof"], []) $
1729− addQed $ addTitle (B.emph (title <> ".")) bs
1730−
1731−addTitle :: Inlines -> Blocks -> Blocks
1732−addTitle ils bs =
1733− case B.toList bs of
1734− (Para xs : rest)
1735− -> B.fromList (Para (B.toList ils ++ (Space : xs)) : rest)
1736− _ -> B.para ils <> bs
1737−
1738−addQed :: Blocks -> Blocks
1739−addQed bs =
1740− case Seq.viewr (B.unMany bs) of
1741− s Seq.:> Para ils
1742− -> B.Many (s Seq.|> Para (ils ++ B.toList qedSign))
1743− _ -> bs <> B.para qedSign
1744− where
1745− qedSign = B.str "\xa0\x25FB"
1746−
1747983environment :: PandocMonad m => LP m Blocks
1748984environment = try $ do
1749985 controlSeq "begin"
1750986 name <- untokenize <$> braced
1751987 M.findWithDefault mzero name environments <|>
1752− theoremEnvironment name <|>
988+ theoremEnvironment blocks opt name <|>
1753989 if M.member name (inlineEnvironments
1754990 :: M.Map Text (LP PandocPure Inlines))
1755991 then mzero
1756992 else try (rawEnv name) <|> rawVerbEnv name
1757993
1758−theoremEnvironment :: PandocMonad m => Text -> LP m Blocks
1759−theoremEnvironment name = do
1760− tmap <- sTheoremMap <$> getState
1761− case M.lookup name tmap of
1762− Nothing -> mzero
1763− Just tspec -> do
1764− optTitle <- option mempty $ (\x -> space <> "(" <> x <> ")") <$> opt
1765− mblabel <- option Nothing $ Just . untokenize <$>
1766− try (spaces >> controlSeq "label" >> spaces >> braced)
1767− bs <- env name blocks
1768− number <-
1769− if theoremNumber tspec
1770− then do
1771− let name' = fromMaybe name $ theoremSeries tspec
1772− num <- getNextNumber
1773− (maybe (DottedNum [0]) theoremLastNum .
1774− M.lookup name' . sTheoremMap)
1775− updateState $ \s ->
1776− s{ sTheoremMap =
1777− M.adjust
1778− (\spec -> spec{ theoremLastNum = num })
1779− name'
1780− (sTheoremMap s)
1781− }
1782−
1783− case mblabel of
1784− Just ident ->
1785− updateState $ \s ->
1786− s{ sLabels = M.insert ident
1787− (B.toList $
1788− theoremName tspec <> "\160" <>
1789− str (renderDottedNum num)) (sLabels s) }
1790− Nothing -> return ()
1791− return $ space <> B.text (renderDottedNum num)
1792− else return mempty
1793− let titleEmph = case theoremStyle tspec of
1794− PlainStyle -> B.strong
1795− DefinitionStyle -> B.strong
1796− RemarkStyle -> B.emph
1797− let title = titleEmph (theoremName tspec <> number)
1798− <> optTitle <> "." <> space
1799− return $ divWith (fromMaybe "" mblabel, [name], []) $ addTitle title
1800− $ case theoremStyle tspec of
1801− PlainStyle -> walk italicize bs
1802− _ -> bs
1803−
1804−italicize :: Block -> Block
1805−italicize (Para ils) = Para [Emph ils]
1806−italicize (Plain ils) = Plain [Emph ils]
1807−italicize x = x
1808−
1809−env :: PandocMonad m => Text -> LP m a -> LP m a
1810−env name p = p <* end_ name
1811−
1812994rawEnv :: PandocMonad m => Text -> LP m Blocks
1813995rawEnv name = do
1814996 exts <- getOption readerExtensions
@@ -1816,15 +998,17 @@ rawEnv name = do
1816998 rawOptions <- mconcat <$> many rawopt
1817999 let beginCommand = "\\begin{" <> name <> "}" <> rawOptions
18181000 pos1 <- getPosition
1819− (bs, raw) <- withRaw $ env name blocks
18201001 if parseRaw
1821− then return $ rawBlock "latex"
1002+ then do
1003+ (_, raw) <- withRaw $ env name blocks
1004+ return $ rawBlock "latex"
18221005 $ beginCommand <> untokenize raw
18231006 else do
1007+ bs <- env name blocks
18241008 report $ SkippedContent beginCommand pos1
18251009 pos2 <- getPosition
18261010 report $ SkippedContent ("\\end{" <> name <> "}") pos2
1827− return bs
1011+ return $ divWith ("",[name],[]) bs
18281012
18291013rawVerbEnv :: PandocMonad m => Text -> LP m Blocks
18301014rawVerbEnv name = do
@@ -1883,8 +1067,7 @@ inputMinted = do
18831067 pos <- getPosition
18841068 attr <- mintedAttr
18851069 f <- T.filter (/='"') . untokenize <$> braced
1886− dirs <- map T.unpack . splitTextBy (==':') . fromMaybe "." <$> lookupEnv "TEXINPUTS"
1887− mbCode <- readFileFromDirs dirs (T.unpack f)
1070+ mbCode <- readFileFromTexinputs (T.unpack f)
18881071 rawcode <- case mbCode of
18891072 Just s -> return s
18901073 Nothing -> do
@@ -1970,8 +1153,7 @@ inputListing = do
19701153 pos <- getPosition
19711154 options <- option [] keyvals
19721155 f <- T.filter (/='"') . untokenize <$> braced
1973− dirs <- map T.unpack . splitTextBy (==':') . fromMaybe "." <$> lookupEnv "TEXINPUTS"
1974− mbCode <- readFileFromDirs dirs (T.unpack f)
1156+ mbCode <- readFileFromTexinputs (T.unpack f)
19751157 codeLines <- case mbCode of
19761158 Just s -> return $ T.lines s
19771159 Nothing -> do
@@ -1980,7 +1162,8 @@ inputListing = do
19801162 let (ident,classes,kvs) = parseListingsOptions options
19811163 let classes' =
19821164 (case listingsLanguage options of
1983− Nothing -> (take 1 (languagesByExtension (T.pack $ takeExtension $ T.unpack f)) <>)
1165+ Nothing -> (take 1 (languagesByExtension defaultSyntaxMap
1166+ (T.pack $ takeExtension $ T.unpack f)) <>)
19841167 Just _ -> id) classes
19851168 let firstline = fromMaybe 1 $ lookup "firstline" options >>= safeRead
19861169 let lastline = fromMaybe (length codeLines) $
@@ -2046,358 +1229,23 @@ orderedList' = try $ do
20461229 bs <- listenv "enumerate" (many item)
20471230 return $ orderedListWith (start, style, delim) bs
20481231
2049−-- tables
2050−
2051−hline :: PandocMonad m => LP m ()
2052−hline = try $ do
2053− spaces
2054− controlSeq "hline" <|>
2055− -- booktabs rules:
2056− controlSeq "toprule" <|>
2057− controlSeq "bottomrule" <|>
2058− controlSeq "midrule" <|>
2059− controlSeq "endhead" <|>
2060− controlSeq "endfirsthead"
2061− spaces
2062− optional opt
2063− return ()
2064−
2065−lbreak :: PandocMonad m => LP m Tok
2066−lbreak = (controlSeq "\\" <|> controlSeq "tabularnewline")
2067− <* skipopts <* spaces
2068−
2069−amp :: PandocMonad m => LP m Tok
2070−amp = symbol '&'
2071−
2072−-- Split a Word into individual Symbols (for parseAligns)
2073−splitWordTok :: PandocMonad m => LP m ()
2074−splitWordTok = do
2075− inp <- getInput
2076− case inp of
2077− (Tok spos Word t : rest) ->
2078− setInput $ map (Tok spos Symbol . T.singleton) (T.unpack t) <> rest
2079− _ -> return ()
2080−
2081−parseAligns :: PandocMonad m => LP m [(Alignment, ColWidth, ([Tok], [Tok]))]
2082−parseAligns = try $ do
2083− let maybeBar = skipMany
2084− (try $ sp *> (() <$ symbol '|' <|> () <$ (symbol '@' >> braced)))
2085− let cAlign = AlignCenter <$ symbol 'c'
2086− let lAlign = AlignLeft <$ symbol 'l'
2087− let rAlign = AlignRight <$ symbol 'r'
2088− let parAlign = AlignLeft <$ symbol 'p'
2089− -- aligns from tabularx
2090− let xAlign = AlignLeft <$ symbol 'X'
2091− let mAlign = AlignLeft <$ symbol 'm'
2092− let bAlign = AlignLeft <$ symbol 'b'
2093− let alignChar = splitWordTok *> ( cAlign <|> lAlign <|> rAlign <|> parAlign
2094− <|> xAlign <|> mAlign <|> bAlign )
2095− let alignPrefix = symbol '>' >> braced
2096− let alignSuffix = symbol '<' >> braced
2097− let colWidth = try $ do
2098− symbol '{'
2099− ds <- trim . untokenize <$> manyTill anyTok (controlSeq "linewidth")
2100− spaces
2101− symbol '}'
2102− return $ safeRead ds
2103− let alignSpec = do
2104− pref <- option [] alignPrefix
2105− spaces
2106− al <- alignChar
2107− width <- colWidth <|> option Nothing (do s <- untokenize <$> braced
2108− pos <- getPosition
2109− report $ SkippedContent s pos
2110− return Nothing)
2111− spaces
2112− suff <- option [] alignSuffix
2113− return (al, width, (pref, suff))
2114− let starAlign = do -- '*{2}{r}' == 'rr', we just expand like a macro
2115− symbol '*'
2116− spaces
2117− ds <- trim . untokenize <$> braced
2118− spaces
2119− spec <- braced
2120− case safeRead ds of
2121− Just n ->
2122− getInput >>= setInput . (mconcat (replicate n spec) ++)
2123− Nothing -> Prelude.fail $ "Could not parse " <> T.unpack ds <> " as number"
2124− bgroup
2125− spaces
2126− maybeBar
2127− aligns' <- many $ try $ spaces >> optional starAlign >>
2128− (alignSpec <* maybeBar)
2129− spaces
2130− egroup
2131− spaces
2132− return $ map toSpec aligns'
2133− where
2134− toColWidth (Just w) | w > 0 = ColWidth w
2135− toColWidth _ = ColWidthDefault
2136− toSpec (x, y, z) = (x, toColWidth y, z)
2137−
2138−-- N.B. this parser returns a Row that may have erroneous empty cells
2139−-- in it. See the note above fixTableHead for details.
2140−parseTableRow :: PandocMonad m
2141− => Text -- ^ table environment name
2142− -> [([Tok], [Tok])] -- ^ pref/suffixes
2143− -> LP m Row
2144−parseTableRow envname prefsufs = do
2145− notFollowedBy (spaces *> end_ envname)
2146− -- add prefixes and suffixes in token stream:
2147− let celltoks (pref, suff) = do
2148− prefpos <- getPosition
2149− contents <- mconcat <$>
2150− many ( snd <$> withRaw (controlSeq "parbox" >> parbox) -- #5711
2151− <|>
2152− snd <$> withRaw (inlineEnvironment <|> dollarsMath)
2153− <|>
2154− (do notFollowedBy
2155− (() <$ amp <|> () <$ lbreak <|> end_ envname)
2156− count 1 anyTok) )
2157−
2158− suffpos <- getPosition
2159− option [] (count 1 amp)
2160− return $ map (setpos prefpos) pref ++ contents ++ map (setpos suffpos) suff
2161− rawcells <- mapM celltoks prefsufs
2162− oldInput <- getInput
2163− cells <- mapM (\ts -> setInput ts >> parseTableCell) rawcells
2164− setInput oldInput
2165− spaces
2166− return $ Row nullAttr cells
2167−
2168−parseTableCell :: PandocMonad m => LP m Cell
2169−parseTableCell = do
2170− spaces
2171− updateState $ \st -> st{ sInTableCell = True }
2172− cell' <- multicolumnCell
2173− <|> multirowCell
2174− <|> parseSimpleCell
2175− <|> parseEmptyCell
2176− updateState $ \st -> st{ sInTableCell = False }
2177− spaces
2178− return cell'
2179− where
2180− -- The parsing of empty cells is important in LaTeX, especially when dealing
2181− -- with multirow/multicolumn. See #6603.
2182− parseEmptyCell = spaces $> emptyCell
2183−
2184−cellAlignment :: PandocMonad m => LP m Alignment
2185−cellAlignment = skipMany (symbol '|') *> alignment <* skipMany (symbol '|')
2186− where
2187− alignment = do
2188− c <- untoken <$> singleChar
2189− return $ case c of
2190− "l" -> AlignLeft
2191− "r" -> AlignRight
2192− "c" -> AlignCenter
2193− "*" -> AlignDefault
2194− _ -> AlignDefault
2195−
2196−plainify :: Blocks -> Blocks
2197−plainify bs = case toList bs of
2198− [Para ils] -> plain (fromList ils)
2199− _ -> bs
2200−
2201−multirowCell :: PandocMonad m => LP m Cell
2202−multirowCell = controlSeq "multirow" >> do
2203− -- Full prototype for \multirow macro is:
2204− -- \multirow[vpos]{nrows}[bigstruts]{width}[vmove]{text}
2205− -- However, everything except `nrows` and `text` make
2206− -- sense in the context of the Pandoc AST
2207− _ <- optional $ symbol '[' *> cellAlignment <* symbol ']' -- vertical position
2208− nrows <- fmap (fromMaybe 1 . safeRead . untokenize) braced
2209− _ <- optional $ symbol '[' *> manyTill anyTok (symbol ']') -- bigstrut-related
2210− _ <- symbol '{' *> manyTill anyTok (symbol '}') -- Cell width
2211− _ <- optional $ symbol '[' *> manyTill anyTok (symbol ']') -- Length used for fine-tuning
2212− content <- symbol '{' *> (plainify <$> blocks) <* symbol '}'
2213− return $ cell AlignDefault (RowSpan nrows) (ColSpan 1) content
2214−
2215−multicolumnCell :: PandocMonad m => LP m Cell
2216−multicolumnCell = controlSeq "multicolumn" >> do
2217− span' <- fmap (fromMaybe 1 . safeRead . untokenize) braced
2218− alignment <- symbol '{' *> cellAlignment <* symbol '}'
2219−
2220− let singleCell = do
2221− content <- plainify <$> blocks
2222− return $ cell alignment (RowSpan 1) (ColSpan span') content
2223−
2224− -- Two possible contents: either a \multirow cell, or content.
2225− -- E.g. \multicol{1}{c}{\multirow{2}{1em}{content}}
2226− -- Note that a \multirow cell can be nested in a \multicolumn,
2227− -- but not the other way around. See #6603
2228− let nestedCell = do
2229− (Cell _ _ (RowSpan rs) _ bs) <- multirowCell
2230− return $ cell
2231− alignment
2232− (RowSpan rs)
2233− (ColSpan span')
2234− (fromList bs)
2235−
2236− symbol '{' *> (nestedCell <|> singleCell) <* symbol '}'
2237−
2238−-- Parse a simple cell, i.e. not multirow/multicol
2239−parseSimpleCell :: PandocMonad m => LP m Cell
2240−parseSimpleCell = simpleCell <$> (plainify <$> blocks)
2241−
2242−-- LaTeX tables are stored with empty cells underneath multirow cells
2243−-- denoting the grid spaces taken up by them. More specifically, if a
2244−-- cell spans m rows, then it will overwrite all the cells in the
2245−-- columns it spans for (m-1) rows underneath it, requiring padding
2246−-- cells in these places. These padding cells need to be removed for
2247−-- proper table reading. See #6603.
2248−--
2249−-- These fixTable functions do not otherwise fix up malformed
2250−-- input tables: that is left to the table builder.
2251−fixTableHead :: TableHead -> TableHead
2252−fixTableHead (TableHead attr rows) = TableHead attr rows'
2253− where
2254− rows' = fixTableRows rows
2255−
2256−fixTableBody :: TableBody -> TableBody
2257−fixTableBody (TableBody attr rhc th tb)
2258− = TableBody attr rhc th' tb'
2259− where
2260− th' = fixTableRows th
2261− tb' = fixTableRows tb
2262−
2263−fixTableRows :: [Row] -> [Row]
2264−fixTableRows = fixTableRows' $ repeat Nothing
2265− where
2266− fixTableRows' oldHang (Row attr cells : rs)
2267− = let (newHang, cells') = fixTableRow oldHang cells
2268− rs' = fixTableRows' newHang rs
2269− in Row attr cells' : rs'
2270− fixTableRows' _ [] = []
2271−
2272−-- The overhang is represented as Just (relative cell dimensions) or
2273−-- Nothing for an empty grid space.
2274−fixTableRow :: [Maybe (ColSpan, RowSpan)] -> [Cell] -> ([Maybe (ColSpan, RowSpan)], [Cell])
2275−fixTableRow oldHang cells
2276− -- If there's overhang, drop cells until their total width meets the
2277− -- width of the occupied grid spaces (or we run out)
2278− | (n, prefHang, restHang) <- splitHang oldHang
2279− , n > 0
2280− = let cells' = dropToWidth getCellW n cells
2281− (restHang', cells'') = fixTableRow restHang cells'
2282− in (prefHang restHang', cells'')
2283− -- Otherwise record the overhang of a pending cell and fix the rest
2284− -- of the row
2285− | c@(Cell _ _ h w _):cells' <- cells
2286− = let h' = max 1 h
2287− w' = max 1 w
2288− oldHang' = dropToWidth getHangW w' oldHang
2289− (newHang, cells'') = fixTableRow oldHang' cells'
2290− in (toHang w' h' <> newHang, c : cells'')
2291− | otherwise
2292− = (oldHang, [])
2293− where
2294− getCellW (Cell _ _ _ w _) = w
2295− getHangW = maybe 1 fst
2296− getCS (ColSpan n) = n
2297−
2298− toHang c r
2299− | r > 1 = [Just (c, r)]
2300− | otherwise = replicate (getCS c) Nothing
2301−
2302− -- Take the prefix of the overhang list representing filled grid
2303− -- spaces. Also return the remainder and the length of this prefix.
2304− splitHang = splitHang' 0 id
2305−
2306− splitHang' !n l (Just (c, r):xs)
2307− = splitHang' (n + c) (l . (toHang c (r-1) ++)) xs
2308− splitHang' n l xs = (n, l, xs)
2309−
2310− -- Drop list items until the total width of the dropped items
2311− -- exceeds the passed width.
2312− dropToWidth _ n l | n < 1 = l
2313− dropToWidth wproj n (c:cs) = dropToWidth wproj (n - wproj c) cs
2314− dropToWidth _ _ [] = []
2315−
2316−simpTable :: PandocMonad m => Text -> Bool -> LP m Blocks
2317−simpTable envname hasWidthParameter = try $ do
2318− when hasWidthParameter $ () <$ (spaces >> tok)
2319− skipopts
2320− colspecs <- parseAligns
2321− let (aligns, widths, prefsufs) = unzip3 colspecs
2322− optional $ controlSeq "caption" *> setCaption
2323− spaces
2324− optional label
2325− spaces
2326− optional lbreak
2327− spaces
2328− skipMany hline
2329− spaces
2330− header' <- option [] . try . fmap (:[]) $
2331− parseTableRow envname prefsufs <* lbreak <* many1 hline
2332− spaces
2333− rows <- sepEndBy (parseTableRow envname prefsufs)
2334− (lbreak <* optional (skipMany hline))
2335− spaces
2336− optional $ controlSeq "caption" *> setCaption
2337− spaces
2338− optional label
2339− spaces
2340− optional lbreak
2341− spaces
2342− lookAhead $ controlSeq "end" -- make sure we're at end
2343− let th = fixTableHead $ TableHead nullAttr header'
2344− let tbs = [fixTableBody $ TableBody nullAttr 0 [] rows]
2345− let tf = TableFoot nullAttr []
2346− return $ table emptyCaption (zip aligns widths) th tbs tf
2347−
2348−addTableCaption :: PandocMonad m => Blocks -> LP m Blocks
2349−addTableCaption = walkM go
2350− where go (Table attr c spec th tb tf) = do
2351− st <- getState
2352− let mblabel = sLastLabel st
2353− capt <- case (sCaption st, mblabel) of
2354− (Just ils, Nothing) -> return $ caption Nothing (plain ils)
2355− (Just ils, Just lab) -> do
2356− num <- getNextNumber sLastTableNum
2357− setState
2358− st{ sLastTableNum = num
2359− , sLabels = M.insert lab
2360− [Str (renderDottedNum num)]
2361− (sLabels st) }
2362− return $ caption Nothing (plain ils) -- add number??
2363− (Nothing, _) -> return c
2364− let attr' = case (attr, mblabel) of
2365− ((_,classes,kvs), Just ident) ->
2366− (ident,classes,kvs)
2367− _ -> attr
2368− return $ addAttrDiv attr' $ Table nullAttr capt spec th tb tf
2369− go x = return x
2370−
2371−-- TODO: For now we add a Div to contain table attributes, since
2372−-- most writers don't do anything yet with attributes on Table.
2373−-- This can be removed when that changes.
2374−addAttrDiv :: Attr -> Block -> Block
2375−addAttrDiv ("",[],[]) b = b
2376−addAttrDiv attr b = Div attr [b]
2377−
23781232block :: PandocMonad m => LP m Blocks
23791233block = do
2380− res <- (mempty <$ spaces1)
2381− <|> environment
2382− <|> macroDef (rawBlock "latex")
2383− <|> blockCommand
2384− <|> paragraph
2385− <|> grouped block
1234+ Tok _ toktype _ <- lookAhead anyTok
1235+ res <- (case toktype of
1236+ Newline -> mempty <$ spaces1
1237+ Spaces -> mempty <$ spaces1
1238+ Comment -> mempty <$ spaces1
1239+ Word -> paragraph
1240+ CtrlSeq "begin" -> environment
1241+ CtrlSeq _ -> macroDef (rawBlock "latex")
1242+ <|> blockCommand
1243+ _ -> mzero)
1244+ <|> paragraph
1245+ <|> grouped block
23861246 trace (T.take 60 $ tshow $ B.toList res)
23871247 return res
23881248
23891249blocks :: PandocMonad m => LP m Blocks
23901250blocks = mconcat <$> many block
23911251
2392−setDefaultLanguage :: PandocMonad m => LP m Blocks
2393−setDefaultLanguage = do
2394− o <- option "" $ T.filter (\c -> c /= '[' && c /= ']')
2395− <$> rawopt
2396− polylang <- untokenize <$> braced
2397− case M.lookup polylang polyglossiaLangToBCP47 of
2398− Nothing -> return mempty -- TODO mzero? warning?
2399− Just langFunc -> do
2400− let l = langFunc o
2401− setTranslations l
2402− updateState $ setMeta "lang" $ str (renderLang l)
2403− return mempty