@@ -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,73 +573,74 @@ 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")
@@ -1272,6 +694,16 @@ include name = do
1272694 mapM_ (insertIncluded defaultExt) fs
1273695 return mempty
1274696
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+
1275707insertIncluded :: PandocMonad m
1276708 => FilePath
1277709 -> FilePath
@@ -1281,13 +713,12 @@ insertIncluded defaultExtension f' = do
1281713 ".tex" -> f'
1282714 ".sty" -> f'
1283715 _ -> addExtension f' defaultExtension
1284− dirs <- map T.unpack . splitTextBy (==':') . fromMaybe "." <$> lookupEnv "TEXINPUTS"
1285716 pos <- getPosition
1286717 containers <- getIncludeFiles <$> getState
1287718 when (T.pack f `elem` containers) $
1288719 throwError $ PandocParseError $ T.pack $ "Include file loop at " ++ show pos
1289720 updateState $ addIncludeFile $ T.pack f
1290− mbcontents <- readFileFromDirs dirs f
721+ mbcontents <- readFileFromTexinputs f
1291722 contents <- case mbcontents of
1292723 Just s -> return s
1293724 Nothing -> do
@@ -1296,10 +727,6 @@ insertIncluded defaultExtension f' = do
1296727 getInput >>= setInput . (tokenize f contents ++)
1297728 updateState dropLatestIncludeFile
1298729
1299−addMeta :: PandocMonad m => ToMetaValue a => Text -> a -> LP m ()
1300−addMeta field val = updateState $ \st ->
1301− st{ sMeta = addMetaField field val $ sMeta st }
1302−
1303730authors :: PandocMonad m => LP m ()
1304731authors = try $ do
1305732 bgroup
@@ -1308,150 +735,6 @@ authors = try $ do
1308735 egroup
1309736 addMeta "author" (map trimInlines auths)
1310737
1311−macroDef :: (PandocMonad m, Monoid a) => (Text -> a) -> LP m a
1312−macroDef constructor = do
1313− (_, s) <- withRaw (commandDef <|> environmentDef)
1314− (constructor (untokenize s) <$
1315− guardDisabled Ext_latex_macros)
1316− <|> return mempty
1317− where commandDef = do
1318− (name, macro') <- newcommand <|> letmacro <|> defmacro
1319− guardDisabled Ext_latex_macros <|>
1320− updateState (\s -> s{ sMacros = M.insert name macro' (sMacros s) })
1321− environmentDef = do
1322− mbenv <- newenvironment
1323− case mbenv of
1324− Nothing -> return ()
1325− Just (name, macro1, macro2) ->
1326− guardDisabled Ext_latex_macros <|>
1327− do updateState $ \s -> s{ sMacros =
1328− M.insert name macro1 (sMacros s) }
1329− updateState $ \s -> s{ sMacros =
1330− M.insert ("end" <> name) macro2 (sMacros s) }
1331− -- @\newenvironment{envname}[n-args][default]{begin}{end}@
1332− -- is equivalent to
1333− -- @\newcommand{\envname}[n-args][default]{begin}@
1334− -- @\newcommand{\endenvname}@
1335−
1336−letmacro :: PandocMonad m => LP m (Text, Macro)
1337−letmacro = do
1338− controlSeq "let"
1339− (name, contents) <- withVerbatimMode $ do
1340− Tok _ (CtrlSeq name) _ <- anyControlSeq
1341− optional $ symbol '='
1342− spaces
1343− -- we first parse in verbatim mode, and then expand macros,
1344− -- because we don't want \let\foo\bar to turn into
1345− -- \let\foo hello if we have previously \def\bar{hello}
1346− contents <- bracedOrToken
1347− return (name, contents)
1348− contents' <- doMacros' 0 contents
1349− return (name, Macro ExpandWhenDefined [] Nothing contents')
1350−
1351−defmacro :: PandocMonad m => LP m (Text, Macro)
1352−defmacro = try $
1353− -- we use withVerbatimMode, because macros are to be expanded
1354− -- at point of use, not point of definition
1355− withVerbatimMode $ do
1356− controlSeq "def"
1357− Tok _ (CtrlSeq name) _ <- anyControlSeq
1358− argspecs <- many (argspecArg <|> argspecPattern)
1359− contents <- bracedOrToken
1360− return (name, Macro ExpandWhenUsed argspecs Nothing contents)
1361−
1362−argspecArg :: PandocMonad m => LP m ArgSpec
1363−argspecArg = do
1364− Tok _ (Arg i) _ <- satisfyTok isArgTok
1365− return $ ArgNum i
1366−
1367−argspecPattern :: PandocMonad m => LP m ArgSpec
1368−argspecPattern =
1369− Pattern <$> many1 (satisfyTok (\(Tok _ toktype' txt) ->
1370− (toktype' == Symbol || toktype' == Word) &&
1371− (txt /= "{" && txt /= "\\" && txt /= "}")))
1372−
1373−newcommand :: PandocMonad m => LP m (Text, Macro)
1374−newcommand = do
1375− pos <- getPosition
1376− Tok _ (CtrlSeq mtype) _ <- controlSeq "newcommand" <|>
1377− controlSeq "renewcommand" <|>
1378− controlSeq "providecommand" <|>
1379− controlSeq "DeclareMathOperator" <|>
1380− controlSeq "DeclareRobustCommand"
1381− withVerbatimMode $ do
1382− Tok _ (CtrlSeq name) txt <- do
1383− optional (symbol '*')
1384− anyControlSeq <|>
1385− (symbol '{' *> spaces *> anyControlSeq <* spaces <* symbol '}')
1386− spaces
1387− numargs <- option 0 $ try bracketedNum
1388− let argspecs = map ArgNum [1..numargs]
1389− spaces
1390− optarg <- option Nothing $ Just <$> try bracketedToks
1391− spaces
1392− contents' <- bracedOrToken
1393− let contents =
1394− case mtype of
1395− "DeclareMathOperator" ->
1396− Tok pos (CtrlSeq "mathop") "\\mathop"
1397− : Tok pos Symbol "{"
1398− : Tok pos (CtrlSeq "mathrm") "\\mathrm"
1399− : Tok pos Symbol "{"
1400− : (contents' ++
1401− [ Tok pos Symbol "}", Tok pos Symbol "}" ])
1402− _ -> contents'
1403− macros <- sMacros <$> getState
1404− case M.lookup name macros of
1405− Just macro
1406− | mtype == "newcommand" -> do
1407− report $ MacroAlreadyDefined txt pos
1408− return (name, macro)
1409− | mtype == "providecommand" -> return (name, macro)
1410− _ -> return (name, Macro ExpandWhenUsed argspecs optarg contents)
1411−
1412−newenvironment :: PandocMonad m => LP m (Maybe (Text, Macro, Macro))
1413−newenvironment = do
1414− pos <- getPosition
1415− Tok _ (CtrlSeq mtype) _ <- controlSeq "newenvironment" <|>
1416− controlSeq "renewenvironment" <|>
1417− controlSeq "provideenvironment"
1418− withVerbatimMode $ do
1419− optional $ symbol '*'
1420− spaces
1421− name <- untokenize <$> braced
1422− spaces
1423− numargs <- option 0 $ try bracketedNum
1424− spaces
1425− optarg <- option Nothing $ Just <$> try bracketedToks
1426− let argspecs = map (\i -> ArgNum i) [1..numargs]
1427− startcontents <- spaces >> bracedOrToken
1428− endcontents <- spaces >> bracedOrToken
1429− macros <- sMacros <$> getState
1430− case M.lookup name macros of
1431− Just _
1432− | mtype == "newenvironment" -> do
1433− report $ MacroAlreadyDefined name pos
1434− return Nothing
1435− | mtype == "provideenvironment" ->
1436− return Nothing
1437− _ -> return $ Just (name,
1438− Macro ExpandWhenUsed argspecs optarg startcontents,
1439− Macro ExpandWhenUsed [] Nothing endcontents)
1440−
1441−bracketedNum :: PandocMonad m => LP m Int
1442−bracketedNum = do
1443− ds <- untokenize <$> bracketedToks
1444− case safeRead ds of
1445− Just i -> return i
1446− _ -> return 0
1447−
1448−setCaption :: PandocMonad m => LP m ()
1449−setCaption = try $ do
1450− skipopts
1451− ils <- tok
1452− optional $ try $ spaces *> label
1453− updateState $ \st -> st{ sCaption = Just ils }
1454−
1455738looseItem :: PandocMonad m => LP m Blocks
1456739looseItem = do
1457740 inListItem <- sInListItem <$> getState
@@ -1465,10 +748,6 @@ epigraph = do
1465748 p2 <- grouped block
1466749 return $ divWith ("", ["epigraph"], []) (p1 <> p2)
1467750
1468−resetCaption :: PandocMonad m => LP m ()
1469−resetCaption = updateState $ \st -> st{ sCaption = Nothing
1470− , sLastLabel = Nothing }
1471−
1472751section :: PandocMonad m => Attr -> Int -> LP m Blocks
1473752section (ident, classes, kvs) lvl = do
1474753 skipopts
@@ -1561,7 +840,7 @@ blockCommands = M.fromList
1561840 , ("address", mempty <$ (skipopts *> tok >>= addMeta "address"))
1562841 , ("signature", mempty <$ (skipopts *> authors))
1563842 , ("date", mempty <$ (skipopts *> tok >>= addMeta "date"))
1564− , ("newtheorem", newtheorem)
843+ , ("newtheorem", newtheorem inline)
1565844 , ("theoremstyle", theoremstyle)
1566845 -- KOMA-Script metadata commands
1567846 , ("extratitle", mempty <$ (skipopts *> tok >>= addMeta "extratitle"))
@@ -1609,7 +888,7 @@ blockCommands = M.fromList
1609888 , ("item", looseItem)
1610889 , ("documentclass", skipopts *> braced *> preamble)
1611890 , ("centerline", para . trimInlines <$> (skipopts *> tok))
1612− , ("caption", mempty <$ setCaption)
891+ , ("caption", mempty <$ setCaption inline)
1613892 , ("bibliography", mempty <$ (skipopts *> braced >>=
1614893 addMeta "bibliography" . splitBibs . untokenize))
1615894 , ("addbibresource", mempty <$ (skipopts *> braced >>=
@@ -1647,7 +926,8 @@ blockCommands = M.fromList
1647926
1648927
1649928environments :: PandocMonad m => M.Map Text (LP m Blocks)
1650−environments = M.fromList
929+environments = M.union (tableEnvironments blocks inline) $
930+ M.fromList
1651931 [ ("document", env "document" blocks <* skipMany anyTok)
1652932 , ("abstract", mempty <$ (env "abstract" blocks >>= addMeta "abstract"))
1653933 , ("sloppypar", env "sloppypar" blocks)
@@ -1657,13 +937,6 @@ environments = M.fromList
1657937 , ("figure", env "figure" $ skipopts *> figure)
1658938 , ("subfigure", env "subfigure" $ skipopts *> tok *> figure)
1659939 , ("center", divWith ("", ["center"], []) <$> env "center" blocks)
1660− , ("longtable", env "longtable" $
1661− resetCaption *> simpTable "longtable" False >>= addTableCaption)
1662− , ("table", env "table" $
1663− skipopts *> resetCaption *> blocks >>= addTableCaption)
1664− , ("tabular*", env "tabular*" $ simpTable "tabular*" True)
1665− , ("tabularx", env "tabularx" $ simpTable "tabularx" True)
1666− , ("tabular", env "tabular" $ simpTable "tabular" False)
1667940 , ("quote", blockQuote <$> env "quote" blocks)
1668941 , ("quotation", blockQuote <$> env "quotation" blocks)
1669942 , ("verse", blockQuote <$> env "verse" blocks)
@@ -1686,7 +959,7 @@ environments = M.fromList
1686959 , ("lilypond", rawVerbEnv "lilypond")
1687960 , ("ly", rawVerbEnv "ly")
1688961 -- amsthm
1689− , ("proof", proof)
962+ , ("proof", proof blocks opt)
1690963 -- etoolbox
1691964 , ("ifstrequal", ifstrequal)
1692965 , ("newtoggle", braced >>= newToggle)
@@ -1695,131 +968,29 @@ environments = M.fromList
1695968 , ("iftoggle", try $ ifToggle >> block)
1696969 ]
1697970
1698−theoremstyle :: PandocMonad m => LP m Blocks
1699−theoremstyle = do
1700− stylename <- untokenize <$> braced
1701− let mbstyle = case stylename of
1702− "plain" -> Just PlainStyle
1703− "definition" -> Just DefinitionStyle
1704− "remark" -> Just RemarkStyle
1705− _ -> Nothing
1706− case mbstyle of
1707− Nothing -> return ()
1708− Just sty -> updateState $ \s -> s{ sLastTheoremStyle = sty }
1709− return mempty
1710−
1711−newtheorem :: PandocMonad m => LP m Blocks
1712−newtheorem = do
1713− number <- option True (False <$ symbol '*' <* sp)
971+filecontents :: PandocMonad m => LP m Blocks
972+filecontents = try $ do
973+ controlSeq "begin"
1714974 name <- untokenize <$> braced
1715− sp
1716− series <- option Nothing $ Just . untokenize <$> bracketedToks
1717− sp
1718− showName <- tok
1719− sp
1720− syncTo <- option Nothing $ Just . untokenize <$> bracketedToks
1721− sty <- sLastTheoremStyle <$> getState
1722− let spec = TheoremSpec { theoremName = showName
1723− , theoremStyle = sty
1724− , theoremSeries = series
1725− , theoremSyncTo = syncTo
1726− , theoremNumber = number
1727− , theoremLastNum = DottedNum [0] }
1728− tmap <- sTheoremMap <$> getState
1729− updateState $ \s -> s{ sTheoremMap =
1730− 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) }
1731981 return mempty
1732982
1733−proof :: PandocMonad m => LP m Blocks
1734−proof = do
1735− title <- option (B.text "Proof") opt
1736− bs <- env "proof" blocks
1737− return $
1738− B.divWith ("", ["proof"], []) $
1739− addQed $ addTitle (B.emph (title <> ".")) bs
1740−
1741−addTitle :: Inlines -> Blocks -> Blocks
1742−addTitle ils bs =
1743− case B.toList bs of
1744− (Para xs : rest)
1745− -> B.fromList (Para (B.toList ils ++ (Space : xs)) : rest)
1746− _ -> B.para ils <> bs
1747−
1748−addQed :: Blocks -> Blocks
1749−addQed bs =
1750− case Seq.viewr (B.unMany bs) of
1751− s Seq.:> Para ils
1752− -> B.Many (s Seq.|> Para (ils ++ B.toList qedSign))
1753− _ -> bs <> B.para qedSign
1754− where
1755− qedSign = B.str "\xa0\x25FB"
1756−
1757983environment :: PandocMonad m => LP m Blocks
1758984environment = try $ do
1759985 controlSeq "begin"
1760986 name <- untokenize <$> braced
1761987 M.findWithDefault mzero name environments <|>
1762− theoremEnvironment name <|>
988+ theoremEnvironment blocks opt name <|>
1763989 if M.member name (inlineEnvironments
1764990 :: M.Map Text (LP PandocPure Inlines))
1765991 then mzero
1766992 else try (rawEnv name) <|> rawVerbEnv name
1767993
1768−theoremEnvironment :: PandocMonad m => Text -> LP m Blocks
1769−theoremEnvironment name = do
1770− tmap <- sTheoremMap <$> getState
1771− case M.lookup name tmap of
1772− Nothing -> mzero
1773− Just tspec -> do
1774− optTitle <- option mempty $ (\x -> space <> "(" <> x <> ")") <$> opt
1775− mblabel <- option Nothing $ Just . untokenize <$>
1776− try (spaces >> controlSeq "label" >> spaces >> braced)
1777− bs <- env name blocks
1778− number <-
1779− if theoremNumber tspec
1780− then do
1781− let name' = fromMaybe name $ theoremSeries tspec
1782− num <- getNextNumber
1783− (maybe (DottedNum [0]) theoremLastNum .
1784− M.lookup name' . sTheoremMap)
1785− updateState $ \s ->
1786− s{ sTheoremMap =
1787− M.adjust
1788− (\spec -> spec{ theoremLastNum = num })
1789− name'
1790− (sTheoremMap s)
1791− }
1792−
1793− case mblabel of
1794− Just ident ->
1795− updateState $ \s ->
1796− s{ sLabels = M.insert ident
1797− (B.toList $
1798− theoremName tspec <> "\160" <>
1799− str (renderDottedNum num)) (sLabels s) }
1800− Nothing -> return ()
1801− return $ space <> B.text (renderDottedNum num)
1802− else return mempty
1803− let titleEmph = case theoremStyle tspec of
1804− PlainStyle -> B.strong
1805− DefinitionStyle -> B.strong
1806− RemarkStyle -> B.emph
1807− let title = titleEmph (theoremName tspec <> number)
1808− <> optTitle <> "." <> space
1809− return $ divWith (fromMaybe "" mblabel, [name], []) $ addTitle title
1810− $ case theoremStyle tspec of
1811− PlainStyle -> walk italicize bs
1812− _ -> bs
1813−
1814−italicize :: Block -> Block
1815−italicize x@(Para [Image{}]) = x -- see #6925
1816−italicize (Para ils) = Para [Emph ils]
1817−italicize (Plain ils) = Plain [Emph ils]
1818−italicize x = x
1819−
1820−env :: PandocMonad m => Text -> LP m a -> LP m a
1821−env name p = p <* end_ name
1822−
1823994rawEnv :: PandocMonad m => Text -> LP m Blocks
1824995rawEnv name = do
1825996 exts <- getOption readerExtensions
@@ -1827,15 +998,17 @@ rawEnv name = do
1827998 rawOptions <- mconcat <$> many rawopt
1828999 let beginCommand = "\\begin{" <> name <> "}" <> rawOptions
18291000 pos1 <- getPosition
1830− (bs, raw) <- withRaw $ env name blocks
18311001 if parseRaw
1832− then return $ rawBlock "latex"
1002+ then do
1003+ (_, raw) <- withRaw $ env name blocks
1004+ return $ rawBlock "latex"
18331005 $ beginCommand <> untokenize raw
18341006 else do
1007+ bs <- env name blocks
18351008 report $ SkippedContent beginCommand pos1
18361009 pos2 <- getPosition
18371010 report $ SkippedContent ("\\end{" <> name <> "}") pos2
1838− return bs
1011+ return $ divWith ("",[name],[]) bs
18391012
18401013rawVerbEnv :: PandocMonad m => Text -> LP m Blocks
18411014rawVerbEnv name = do
@@ -1894,8 +1067,7 @@ inputMinted = do
18941067 pos <- getPosition
18951068 attr <- mintedAttr
18961069 f <- T.filter (/='"') . untokenize <$> braced
1897− dirs <- map T.unpack . splitTextBy (==':') . fromMaybe "." <$> lookupEnv "TEXINPUTS"
1898− mbCode <- readFileFromDirs dirs (T.unpack f)
1070+ mbCode <- readFileFromTexinputs (T.unpack f)
18991071 rawcode <- case mbCode of
19001072 Just s -> return s
19011073 Nothing -> do
@@ -1981,8 +1153,7 @@ inputListing = do
19811153 pos <- getPosition
19821154 options <- option [] keyvals
19831155 f <- T.filter (/='"') . untokenize <$> braced
1984− dirs <- map T.unpack . splitTextBy (==':') . fromMaybe "." <$> lookupEnv "TEXINPUTS"
1985− mbCode <- readFileFromDirs dirs (T.unpack f)
1156+ mbCode <- readFileFromTexinputs (T.unpack f)
19861157 codeLines <- case mbCode of
19871158 Just s -> return $ T.lines s
19881159 Nothing -> do
@@ -1991,7 +1162,8 @@ inputListing = do
19911162 let (ident,classes,kvs) = parseListingsOptions options
19921163 let classes' =
19931164 (case listingsLanguage options of
1994− Nothing -> (take 1 (languagesByExtension (T.pack $ takeExtension $ T.unpack f)) <>)
1165+ Nothing -> (take 1 (languagesByExtension defaultSyntaxMap
1166+ (T.pack $ takeExtension $ T.unpack f)) <>)
19951167 Just _ -> id) classes
19961168 let firstline = fromMaybe 1 $ lookup "firstline" options >>= safeRead
19971169 let lastline = fromMaybe (length codeLines) $
@@ -2057,358 +1229,23 @@ orderedList' = try $ do
20571229 bs <- listenv "enumerate" (many item)
20581230 return $ orderedListWith (start, style, delim) bs
20591231
2060−-- tables
2061−
2062−hline :: PandocMonad m => LP m ()
2063−hline = try $ do
2064− spaces
2065− controlSeq "hline" <|>
2066− -- booktabs rules:
2067− controlSeq "toprule" <|>
2068− controlSeq "bottomrule" <|>
2069− controlSeq "midrule" <|>
2070− controlSeq "endhead" <|>
2071− controlSeq "endfirsthead"
2072− spaces
2073− optional opt
2074− return ()
2075−
2076−lbreak :: PandocMonad m => LP m Tok
2077−lbreak = (controlSeq "\\" <|> controlSeq "tabularnewline")
2078− <* skipopts <* spaces
2079−
2080−amp :: PandocMonad m => LP m Tok
2081−amp = symbol '&'
2082−
2083−-- Split a Word into individual Symbols (for parseAligns)
2084−splitWordTok :: PandocMonad m => LP m ()
2085−splitWordTok = do
2086− inp <- getInput
2087− case inp of
2088− (Tok spos Word t : rest) ->
2089− setInput $ map (Tok spos Symbol . T.singleton) (T.unpack t) <> rest
2090− _ -> return ()
2091−
2092−parseAligns :: PandocMonad m => LP m [(Alignment, ColWidth, ([Tok], [Tok]))]
2093−parseAligns = try $ do
2094− let maybeBar = skipMany
2095− (try $ sp *> (() <$ symbol '|' <|> () <$ (symbol '@' >> braced)))
2096− let cAlign = AlignCenter <$ symbol 'c'
2097− let lAlign = AlignLeft <$ symbol 'l'
2098− let rAlign = AlignRight <$ symbol 'r'
2099− let parAlign = AlignLeft <$ symbol 'p'
2100− -- aligns from tabularx
2101− let xAlign = AlignLeft <$ symbol 'X'
2102− let mAlign = AlignLeft <$ symbol 'm'
2103− let bAlign = AlignLeft <$ symbol 'b'
2104− let alignChar = splitWordTok *> ( cAlign <|> lAlign <|> rAlign <|> parAlign
2105− <|> xAlign <|> mAlign <|> bAlign )
2106− let alignPrefix = symbol '>' >> braced
2107− let alignSuffix = symbol '<' >> braced
2108− let colWidth = try $ do
2109− symbol '{'
2110− ds <- trim . untokenize <$> manyTill anyTok (controlSeq "linewidth")
2111− spaces
2112− symbol '}'
2113− return $ safeRead ds
2114− let alignSpec = do
2115− pref <- option [] alignPrefix
2116− spaces
2117− al <- alignChar
2118− width <- colWidth <|> option Nothing (do s <- untokenize <$> braced
2119− pos <- getPosition
2120− report $ SkippedContent s pos
2121− return Nothing)
2122− spaces
2123− suff <- option [] alignSuffix
2124− return (al, width, (pref, suff))
2125− let starAlign = do -- '*{2}{r}' == 'rr', we just expand like a macro
2126− symbol '*'
2127− spaces
2128− ds <- trim . untokenize <$> braced
2129− spaces
2130− spec <- braced
2131− case safeRead ds of
2132− Just n ->
2133− getInput >>= setInput . (mconcat (replicate n spec) ++)
2134− Nothing -> Prelude.fail $ "Could not parse " <> T.unpack ds <> " as number"
2135− bgroup
2136− spaces
2137− maybeBar
2138− aligns' <- many $ try $ spaces >> optional starAlign >>
2139− (alignSpec <* maybeBar)
2140− spaces
2141− egroup
2142− spaces
2143− return $ map toSpec aligns'
2144− where
2145− toColWidth (Just w) | w > 0 = ColWidth w
2146− toColWidth _ = ColWidthDefault
2147− toSpec (x, y, z) = (x, toColWidth y, z)
2148−
2149−-- N.B. this parser returns a Row that may have erroneous empty cells
2150−-- in it. See the note above fixTableHead for details.
2151−parseTableRow :: PandocMonad m
2152− => Text -- ^ table environment name
2153− -> [([Tok], [Tok])] -- ^ pref/suffixes
2154− -> LP m Row
2155−parseTableRow envname prefsufs = do
2156− notFollowedBy (spaces *> end_ envname)
2157− -- add prefixes and suffixes in token stream:
2158− let celltoks (pref, suff) = do
2159− prefpos <- getPosition
2160− contents <- mconcat <$>
2161− many ( snd <$> withRaw (controlSeq "parbox" >> parbox) -- #5711
2162− <|>
2163− snd <$> withRaw (inlineEnvironment <|> dollarsMath)
2164− <|>
2165− (do notFollowedBy
2166− (() <$ amp <|> () <$ lbreak <|> end_ envname)
2167− count 1 anyTok) )
2168−
2169− suffpos <- getPosition
2170− option [] (count 1 amp)
2171− return $ map (setpos prefpos) pref ++ contents ++ map (setpos suffpos) suff
2172− rawcells <- mapM celltoks prefsufs
2173− oldInput <- getInput
2174− cells <- mapM (\ts -> setInput ts >> parseTableCell) rawcells
2175− setInput oldInput
2176− spaces
2177− return $ Row nullAttr cells
2178−
2179−parseTableCell :: PandocMonad m => LP m Cell
2180−parseTableCell = do
2181− spaces
2182− updateState $ \st -> st{ sInTableCell = True }
2183− cell' <- multicolumnCell
2184− <|> multirowCell
2185− <|> parseSimpleCell
2186− <|> parseEmptyCell
2187− updateState $ \st -> st{ sInTableCell = False }
2188− spaces
2189− return cell'
2190− where
2191− -- The parsing of empty cells is important in LaTeX, especially when dealing
2192− -- with multirow/multicolumn. See #6603.
2193− parseEmptyCell = spaces $> emptyCell
2194−
2195−cellAlignment :: PandocMonad m => LP m Alignment
2196−cellAlignment = skipMany (symbol '|') *> alignment <* skipMany (symbol '|')
2197− where
2198− alignment = do
2199− c <- untoken <$> singleChar
2200− return $ case c of
2201− "l" -> AlignLeft
2202− "r" -> AlignRight
2203− "c" -> AlignCenter
2204− "*" -> AlignDefault
2205− _ -> AlignDefault
2206−
2207−plainify :: Blocks -> Blocks
2208−plainify bs = case toList bs of
2209− [Para ils] -> plain (fromList ils)
2210− _ -> bs
2211−
2212−multirowCell :: PandocMonad m => LP m Cell
2213−multirowCell = controlSeq "multirow" >> do
2214− -- Full prototype for \multirow macro is:
2215− -- \multirow[vpos]{nrows}[bigstruts]{width}[vmove]{text}
2216− -- However, everything except `nrows` and `text` make
2217− -- sense in the context of the Pandoc AST
2218− _ <- optional $ symbol '[' *> cellAlignment <* symbol ']' -- vertical position
2219− nrows <- fmap (fromMaybe 1 . safeRead . untokenize) braced
2220− _ <- optional $ symbol '[' *> manyTill anyTok (symbol ']') -- bigstrut-related
2221− _ <- symbol '{' *> manyTill anyTok (symbol '}') -- Cell width
2222− _ <- optional $ symbol '[' *> manyTill anyTok (symbol ']') -- Length used for fine-tuning
2223− content <- symbol '{' *> (plainify <$> blocks) <* symbol '}'
2224− return $ cell AlignDefault (RowSpan nrows) (ColSpan 1) content
2225−
2226−multicolumnCell :: PandocMonad m => LP m Cell
2227−multicolumnCell = controlSeq "multicolumn" >> do
2228− span' <- fmap (fromMaybe 1 . safeRead . untokenize) braced
2229− alignment <- symbol '{' *> cellAlignment <* symbol '}'
2230−
2231− let singleCell = do
2232− content <- plainify <$> blocks
2233− return $ cell alignment (RowSpan 1) (ColSpan span') content
2234−
2235− -- Two possible contents: either a \multirow cell, or content.
2236− -- E.g. \multicol{1}{c}{\multirow{2}{1em}{content}}
2237− -- Note that a \multirow cell can be nested in a \multicolumn,
2238− -- but not the other way around. See #6603
2239− let nestedCell = do
2240− (Cell _ _ (RowSpan rs) _ bs) <- multirowCell
2241− return $ cell
2242− alignment
2243− (RowSpan rs)
2244− (ColSpan span')
2245− (fromList bs)
2246−
2247− symbol '{' *> (nestedCell <|> singleCell) <* symbol '}'
2248−
2249−-- Parse a simple cell, i.e. not multirow/multicol
2250−parseSimpleCell :: PandocMonad m => LP m Cell
2251−parseSimpleCell = simpleCell <$> (plainify <$> blocks)
2252−
2253−-- LaTeX tables are stored with empty cells underneath multirow cells
2254−-- denoting the grid spaces taken up by them. More specifically, if a
2255−-- cell spans m rows, then it will overwrite all the cells in the
2256−-- columns it spans for (m-1) rows underneath it, requiring padding
2257−-- cells in these places. These padding cells need to be removed for
2258−-- proper table reading. See #6603.
2259−--
2260−-- These fixTable functions do not otherwise fix up malformed
2261−-- input tables: that is left to the table builder.
2262−fixTableHead :: TableHead -> TableHead
2263−fixTableHead (TableHead attr rows) = TableHead attr rows'
2264− where
2265− rows' = fixTableRows rows
2266−
2267−fixTableBody :: TableBody -> TableBody
2268−fixTableBody (TableBody attr rhc th tb)
2269− = TableBody attr rhc th' tb'
2270− where
2271− th' = fixTableRows th
2272− tb' = fixTableRows tb
2273−
2274−fixTableRows :: [Row] -> [Row]
2275−fixTableRows = fixTableRows' $ repeat Nothing
2276− where
2277− fixTableRows' oldHang (Row attr cells : rs)
2278− = let (newHang, cells') = fixTableRow oldHang cells
2279− rs' = fixTableRows' newHang rs
2280− in Row attr cells' : rs'
2281− fixTableRows' _ [] = []
2282−
2283−-- The overhang is represented as Just (relative cell dimensions) or
2284−-- Nothing for an empty grid space.
2285−fixTableRow :: [Maybe (ColSpan, RowSpan)] -> [Cell] -> ([Maybe (ColSpan, RowSpan)], [Cell])
2286−fixTableRow oldHang cells
2287− -- If there's overhang, drop cells until their total width meets the
2288− -- width of the occupied grid spaces (or we run out)
2289− | (n, prefHang, restHang) <- splitHang oldHang
2290− , n > 0
2291− = let cells' = dropToWidth getCellW n cells
2292− (restHang', cells'') = fixTableRow restHang cells'
2293− in (prefHang restHang', cells'')
2294− -- Otherwise record the overhang of a pending cell and fix the rest
2295− -- of the row
2296− | c@(Cell _ _ h w _):cells' <- cells
2297− = let h' = max 1 h
2298− w' = max 1 w
2299− oldHang' = dropToWidth getHangW w' oldHang
2300− (newHang, cells'') = fixTableRow oldHang' cells'
2301− in (toHang w' h' <> newHang, c : cells'')
2302− | otherwise
2303− = (oldHang, [])
2304− where
2305− getCellW (Cell _ _ _ w _) = w
2306− getHangW = maybe 1 fst
2307− getCS (ColSpan n) = n
2308−
2309− toHang c r
2310− | r > 1 = [Just (c, r)]
2311− | otherwise = replicate (getCS c) Nothing
2312−
2313− -- Take the prefix of the overhang list representing filled grid
2314− -- spaces. Also return the remainder and the length of this prefix.
2315− splitHang = splitHang' 0 id
2316−
2317− splitHang' !n l (Just (c, r):xs)
2318− = splitHang' (n + c) (l . (toHang c (r-1) ++)) xs
2319− splitHang' n l xs = (n, l, xs)
2320−
2321− -- Drop list items until the total width of the dropped items
2322− -- exceeds the passed width.
2323− dropToWidth _ n l | n < 1 = l
2324− dropToWidth wproj n (c:cs) = dropToWidth wproj (n - wproj c) cs
2325− dropToWidth _ _ [] = []
2326−
2327−simpTable :: PandocMonad m => Text -> Bool -> LP m Blocks
2328−simpTable envname hasWidthParameter = try $ do
2329− when hasWidthParameter $ () <$ (spaces >> tok)
2330− skipopts
2331− colspecs <- parseAligns
2332− let (aligns, widths, prefsufs) = unzip3 colspecs
2333− optional $ controlSeq "caption" *> setCaption
2334− spaces
2335− optional label
2336− spaces
2337− optional lbreak
2338− spaces
2339− skipMany hline
2340− spaces
2341− header' <- option [] . try . fmap (:[]) $
2342− parseTableRow envname prefsufs <* lbreak <* many1 hline
2343− spaces
2344− rows <- sepEndBy (parseTableRow envname prefsufs)
2345− (lbreak <* optional (skipMany hline))
2346− spaces
2347− optional $ controlSeq "caption" *> setCaption
2348− spaces
2349− optional label
2350− spaces
2351− optional lbreak
2352− spaces
2353− lookAhead $ controlSeq "end" -- make sure we're at end
2354− let th = fixTableHead $ TableHead nullAttr header'
2355− let tbs = [fixTableBody $ TableBody nullAttr 0 [] rows]
2356− let tf = TableFoot nullAttr []
2357− return $ table emptyCaption (zip aligns widths) th tbs tf
2358−
2359−addTableCaption :: PandocMonad m => Blocks -> LP m Blocks
2360−addTableCaption = walkM go
2361− where go (Table attr c spec th tb tf) = do
2362− st <- getState
2363− let mblabel = sLastLabel st
2364− capt <- case (sCaption st, mblabel) of
2365− (Just ils, Nothing) -> return $ caption Nothing (plain ils)
2366− (Just ils, Just lab) -> do
2367− num <- getNextNumber sLastTableNum
2368− setState
2369− st{ sLastTableNum = num
2370− , sLabels = M.insert lab
2371− [Str (renderDottedNum num)]
2372− (sLabels st) }
2373− return $ caption Nothing (plain ils) -- add number??
2374− (Nothing, _) -> return c
2375− let attr' = case (attr, mblabel) of
2376− ((_,classes,kvs), Just ident) ->
2377− (ident,classes,kvs)
2378− _ -> attr
2379− return $ addAttrDiv attr' $ Table nullAttr capt spec th tb tf
2380− go x = return x
2381−
2382−-- TODO: For now we add a Div to contain table attributes, since
2383−-- most writers don't do anything yet with attributes on Table.
2384−-- This can be removed when that changes.
2385−addAttrDiv :: Attr -> Block -> Block
2386−addAttrDiv ("",[],[]) b = b
2387−addAttrDiv attr b = Div attr [b]
2388−
23891232block :: PandocMonad m => LP m Blocks
23901233block = do
2391− res <- (mempty <$ spaces1)
2392− <|> environment
2393− <|> macroDef (rawBlock "latex")
2394− <|> blockCommand
2395− <|> paragraph
2396− <|> 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
23971246 trace (T.take 60 $ tshow $ B.toList res)
23981247 return res
23991248
24001249blocks :: PandocMonad m => LP m Blocks
24011250blocks = mconcat <$> many block
24021251
2403−setDefaultLanguage :: PandocMonad m => LP m Blocks
2404−setDefaultLanguage = do
2405− o <- option "" $ T.filter (\c -> c /= '[' && c /= ']')
2406− <$> rawopt
2407− polylang <- untokenize <$> braced
2408− case M.lookup polylang polyglossiaLangToBCP47 of
2409− Nothing -> return mempty -- TODO mzero? warning?
2410− Just langFunc -> do
2411− let l = langFunc o
2412− setTranslations l
2413− updateState $ setMeta "lang" $ str (renderLang l)
2414− return mempty