@@ -1,4 +1,3 @@
1−{-# LANGUAGE BangPatterns #-}
2{-# LANGUAGE CPP #-}
1{-# LANGUAGE CPP #-}
3{-# LANGUAGE FlexibleInstances #-}
2{-# LANGUAGE FlexibleInstances #-}
4{-# LANGUAGE MultiParamTypeClasses #-}
3{-# LANGUAGE MultiParamTypeClasses #-}
@@ -32,7 +31,6 @@ import Control.Monad
32import Control.Monad.Except (throwError)
31import Control.Monad.Except (throwError)
33import Data.Char (isDigit, isLetter, toUpper, chr)
32import Data.Char (isDigit, isLetter, toUpper, chr)
34import Data.Default
33import Data.Default
35−import Data.Functor (($>))
36import Data.List (intercalate)
34import Data.List (intercalate)
37import qualified Data.Map as M
35import qualified Data.Map as M
38import Data.Maybe (fromMaybe, maybeToList)
36import Data.Maybe (fromMaybe, maybeToList)
@@ -58,6 +56,7 @@ import Text.Pandoc.Readers.LaTeX.Types (ExpansionPoint (..), Macro (..),
58 ArgSpec (..), Tok (..), TokType (..))
56 ArgSpec (..), Tok (..), TokType (..))
59import Text.Pandoc.Readers.LaTeX.Parsing
57import Text.Pandoc.Readers.LaTeX.Parsing
60import Text.Pandoc.Readers.LaTeX.Accent (accentCommands)
58import Text.Pandoc.Readers.LaTeX.Accent (accentCommands)
59+import Text.Pandoc.Readers.LaTeX.Table (tableEnvironments)
61import Text.Pandoc.Readers.LaTeX.Lang (polyglossiaLangToBCP47,
60import Text.Pandoc.Readers.LaTeX.Lang (polyglossiaLangToBCP47,
62 babelLangToBCP47)
61 babelLangToBCP47)
63import Text.Pandoc.Readers.LaTeX.SIunitx
62import Text.Pandoc.Readers.LaTeX.SIunitx
@@ -551,12 +550,8 @@ inlineCommand' = try $ do
551 <|> ignore rawcommand
550 <|> ignore rawcommand
552 lookupListDefault raw names inlineCommands
551 lookupListDefault raw names inlineCommands
555tok :: PandocMonad m => LP m Inlines
553tok :: PandocMonad m => LP m Inlines
556−tok = try $ spaces >> grouped inline <|> inlineCommand' <|> singleChar'
554+tok = tokWith inline
557− where singleChar' = do
558− Tok _ _ t <- singleChar
561opt :: PandocMonad m => LP m Inlines
556opt :: PandocMonad m => LP m Inlines
@@ -1118,12 +1113,6 @@ treatAsInline = Set.fromList
1118 , "pagebreak"
1113 , "pagebreak"
1121−label :: PandocMonad m => LP m ()
1125− updateState $ \st -> st{ sLastLabel = Just $ untokenize t }
1127dolabel :: PandocMonad m => LP m Inlines
1116dolabel :: PandocMonad m => LP m Inlines
1128dolabel = do
1117dolabel = do
1129 v <- braced
1118 v <- braced
@@ -1421,13 +1410,6 @@ bracketedNum = do
1421 Just i -> return i
1410 Just i -> return i
1422 _ -> return 0
1411 _ -> return 0
1424−setCaption :: PandocMonad m => LP m ()
1425−setCaption = try $ do
1428− optional $ try $ spaces *> label
1429− updateState $ \st -> st{ sCaption = Just ils }
1431looseItem :: PandocMonad m => LP m Blocks
1413looseItem :: PandocMonad m => LP m Blocks
1432looseItem = do
1414looseItem = do
1433 inListItem <- sInListItem <$> getState
1415 inListItem <- sInListItem <$> getState
@@ -1441,10 +1423,6 @@ epigraph = do
1441 p2 <- grouped block
1423 p2 <- grouped block
1442 return $ divWith ("", ["epigraph"], []) (p1 <> p2)
1424 return $ divWith ("", ["epigraph"], []) (p1 <> p2)
1444−resetCaption :: PandocMonad m => LP m ()
1445−resetCaption = updateState $ \st -> st{ sCaption = Nothing
1446− , sLastLabel = Nothing }
1448section :: PandocMonad m => Attr -> Int -> LP m Blocks
1426section :: PandocMonad m => Attr -> Int -> LP m Blocks
1449section (ident, classes, kvs) lvl = do
1427section (ident, classes, kvs) lvl = do
1450 skipopts
1428 skipopts
@@ -1585,7 +1563,7 @@ blockCommands = M.fromList
1585 , ("item", looseItem)
1563 , ("item", looseItem)
1586 , ("documentclass", skipopts *> braced *> preamble)
1564 , ("documentclass", skipopts *> braced *> preamble)
1587 , ("centerline", para . trimInlines <$> (skipopts *> tok))
1565 , ("centerline", para . trimInlines <$> (skipopts *> tok))
1588− , ("caption", mempty <$ setCaption)
1566+ , ("caption", mempty <$ setCaption inline)
1589 , ("bibliography", mempty <$ (skipopts *> braced >>=
1567 , ("bibliography", mempty <$ (skipopts *> braced >>=
1590 addMeta "bibliography" . splitBibs . untokenize))
1568 addMeta "bibliography" . splitBibs . untokenize))
1591 , ("addbibresource", mempty <$ (skipopts *> braced >>=
1569 , ("addbibresource", mempty <$ (skipopts *> braced >>=
@@ -1623,7 +1601,8 @@ blockCommands = M.fromList
1625environments :: PandocMonad m => M.Map Text (LP m Blocks)
1603environments :: PandocMonad m => M.Map Text (LP m Blocks)
1604+environments = M.union (tableEnvironments blocks inline) $
1626−environments = M.fromList
1605+ M.fromList
1627 [ ("document", env "document" blocks <* skipMany anyTok)
1606 [ ("document", env "document" blocks <* skipMany anyTok)
1628 , ("abstract", mempty <$ (env "abstract" blocks >>= addMeta "abstract"))
1607 , ("abstract", mempty <$ (env "abstract" blocks >>= addMeta "abstract"))
1629 , ("sloppypar", env "sloppypar" blocks)
1608 , ("sloppypar", env "sloppypar" blocks)
@@ -1633,13 +1612,6 @@ environments = M.fromList
1633 , ("figure", env "figure" $ skipopts *> figure)
1612 , ("figure", env "figure" $ skipopts *> figure)
1634 , ("subfigure", env "subfigure" $ skipopts *> tok *> figure)
1613 , ("subfigure", env "subfigure" $ skipopts *> tok *> figure)
1635 , ("center", divWith ("", ["center"], []) <$> env "center" blocks)
1614 , ("center", divWith ("", ["center"], []) <$> env "center" blocks)
1636− , ("longtable", env "longtable" $
1637− resetCaption *> simpTable "longtable" False >>= addTableCaption)
1638− , ("table", env "table" $
1639− skipopts *> resetCaption *> blocks >>= addTableCaption)
1640− , ("tabular*", env "tabular*" $ simpTable "tabular*" True)
1641− , ("tabularx", env "tabularx" $ simpTable "tabularx" True)
1642− , ("tabular", env "tabular" $ simpTable "tabular" False)
1643 , ("quote", blockQuote <$> env "quote" blocks)
1615 , ("quote", blockQuote <$> env "quote" blocks)
1644 , ("quotation", blockQuote <$> env "quotation" blocks)
1616 , ("quotation", blockQuote <$> env "quotation" blocks)
1645 , ("verse", blockQuote <$> env "verse" blocks)
1617 , ("verse", blockQuote <$> env "verse" blocks)
@@ -1805,9 +1777,6 @@ italicize (Para ils) = Para [Emph ils]
1805italicize (Plain ils) = Plain [Emph ils]
1777italicize (Plain ils) = Plain [Emph ils]
1806italicize x = x
1778italicize x = x
1808−env :: PandocMonad m => Text -> LP m a -> LP m a
1809−env name p = p <* end_ name
1811rawEnv :: PandocMonad m => Text -> LP m Blocks
1780rawEnv :: PandocMonad m => Text -> LP m Blocks
1812rawEnv name = do
1781rawEnv name = do
1813 exts <- getOption readerExtensions
1782 exts <- getOption readerExtensions
@@ -2045,333 +2014,6 @@ orderedList' = try $ do
2045 bs <- listenv "enumerate" (many item)
2014 bs <- listenv "enumerate" (many item)
2046 return $ orderedListWith (start, style, delim) bs
2015 return $ orderedListWith (start, style, delim) bs
2050−hline :: PandocMonad m => LP m ()
2053− controlSeq "hline" <|>
2055− controlSeq "toprule" <|>
2056− controlSeq "bottomrule" <|>
2057− controlSeq "midrule" <|>
2058− controlSeq "endhead" <|>
2059− controlSeq "endfirsthead"
2064−lbreak :: PandocMonad m => LP m Tok
2065−lbreak = (controlSeq "\\" <|> controlSeq "tabularnewline")
2066− <* skipopts <* spaces
2068−amp :: PandocMonad m => LP m Tok
2071−-- Split a Word into individual Symbols (for parseAligns)
2072−splitWordTok :: PandocMonad m => LP m ()
2076− (Tok spos Word t : rest) ->
2077− setInput $ map (Tok spos Symbol . T.singleton) (T.unpack t) <> rest
2080−parseAligns :: PandocMonad m => LP m [(Alignment, ColWidth, ([Tok], [Tok]))]
2081−parseAligns = try $ do
2082− let maybeBar = skipMany
2083− (try $ sp *> (() <$ symbol '|' <|> () <$ (symbol '@' >> braced)))
2084− let cAlign = AlignCenter <$ symbol 'c'
2085− let lAlign = AlignLeft <$ symbol 'l'
2086− let rAlign = AlignRight <$ symbol 'r'
2087− let parAlign = AlignLeft <$ symbol 'p'
2088− -- aligns from tabularx
2089− let xAlign = AlignLeft <$ symbol 'X'
2090− let mAlign = AlignLeft <$ symbol 'm'
2091− let bAlign = AlignLeft <$ symbol 'b'
2092− let alignChar = splitWordTok *> ( cAlign <|> lAlign <|> rAlign <|> parAlign
2093− <|> xAlign <|> mAlign <|> bAlign )
2094− let alignPrefix = symbol '>' >> braced
2095− let alignSuffix = symbol '<' >> braced
2096− let colWidth = try $ do
2098− ds <- trim . untokenize <$> manyTill anyTok (controlSeq "linewidth")
2101− return $ safeRead ds
2103− pref <- option [] alignPrefix
2106− width <- colWidth <|> option Nothing (do s <- untokenize <$> braced
2108− report $ SkippedContent s pos
2111− suff <- option [] alignSuffix
2112− return (al, width, (pref, suff))
2113− let starAlign = do -- '*{2}{r}' == 'rr', we just expand like a macro
2116− ds <- trim . untokenize <$> braced
2119− case safeRead ds of
2121− getInput >>= setInput . (mconcat (replicate n spec) ++)
2122− Nothing -> Prelude.fail $ "Could not parse " <> T.unpack ds <> " as number"
2126− aligns' <- many $ try $ spaces >> optional starAlign >>
2127− (alignSpec <* maybeBar)
2131− return $ map toSpec aligns'
2133− toColWidth (Just w) | w > 0 = ColWidth w
2134− toColWidth _ = ColWidthDefault
2135− toSpec (x, y, z) = (x, toColWidth y, z)
2137−-- N.B. this parser returns a Row that may have erroneous empty cells
2138−-- in it. See the note above fixTableHead for details.
2139−parseTableRow :: PandocMonad m
2140− => Text -- ^ table environment name
2141− -> [([Tok], [Tok])] -- ^ pref/suffixes
2143−parseTableRow envname prefsufs = do
2144− notFollowedBy (spaces *> end_ envname)
2145− -- add prefixes and suffixes in token stream:
2146− let celltoks (pref, suff) = do
2147− prefpos <- getPosition
2148− contents <- mconcat <$>
2149− many ( snd <$> withRaw (controlSeq "parbox" >> parbox) -- #5711
2151− snd <$> withRaw (inlineEnvironment <|> dollarsMath)
2154− (() <$ amp <|> () <$ lbreak <|> end_ envname)
2157− suffpos <- getPosition
2158− option [] (count 1 amp)
2159− return $ map (setpos prefpos) pref ++ contents ++ map (setpos suffpos) suff
2160− rawcells <- mapM celltoks prefsufs
2161− cells <- mapM (parseFromToks parseTableCell) rawcells
2163− return $ Row nullAttr cells
2165−parseTableCell :: PandocMonad m => LP m Cell
2168− updateState $ \st -> st{ sInTableCell = True }
2169− cell' <- multicolumnCell
2171− <|> parseSimpleCell
2173− updateState $ \st -> st{ sInTableCell = False }
2177− -- The parsing of empty cells is important in LaTeX, especially when dealing
2178− -- with multirow/multicolumn. See #6603.
2179− parseEmptyCell = spaces $> emptyCell
2181−cellAlignment :: PandocMonad m => LP m Alignment
2182−cellAlignment = skipMany (symbol '|') *> alignment <* skipMany (symbol '|')
2185− c <- untoken <$> singleChar
2190− "*" -> AlignDefault
2193−plainify :: Blocks -> Blocks
2194−plainify bs = case toList bs of
2195− [Para ils] -> plain (fromList ils)
2198−multirowCell :: PandocMonad m => LP m Cell
2199−multirowCell = controlSeq "multirow" >> do
2200− -- Full prototype for \multirow macro is:
2201− -- \multirow[vpos]{nrows}[bigstruts]{width}[vmove]{text}
2202− -- However, everything except `nrows` and `text` make
2203− -- sense in the context of the Pandoc AST
2204− _ <- optional $ symbol '[' *> cellAlignment <* symbol ']' -- vertical position
2205− nrows <- fmap (fromMaybe 1 . safeRead . untokenize) braced
2206− _ <- optional $ symbol '[' *> manyTill anyTok (symbol ']') -- bigstrut-related
2207− _ <- symbol '{' *> manyTill anyTok (symbol '}') -- Cell width
2208− _ <- optional $ symbol '[' *> manyTill anyTok (symbol ']') -- Length used for fine-tuning
2209− content <- symbol '{' *> (plainify <$> blocks) <* symbol '}'
2210− return $ cell AlignDefault (RowSpan nrows) (ColSpan 1) content
2212−multicolumnCell :: PandocMonad m => LP m Cell
2213−multicolumnCell = controlSeq "multicolumn" >> do
2214− span' <- fmap (fromMaybe 1 . safeRead . untokenize) braced
2215− alignment <- symbol '{' *> cellAlignment <* symbol '}'
2217− let singleCell = do
2218− content <- plainify <$> blocks
2219− return $ cell alignment (RowSpan 1) (ColSpan span') content
2221− -- Two possible contents: either a \multirow cell, or content.
2222− -- E.g. \multicol{1}{c}{\multirow{2}{1em}{content}}
2223− -- Note that a \multirow cell can be nested in a \multicolumn,
2224− -- but not the other way around. See #6603
2225− let nestedCell = do
2226− (Cell _ _ (RowSpan rs) _ bs) <- multirowCell
2233− symbol '{' *> (nestedCell <|> singleCell) <* symbol '}'
2235−-- Parse a simple cell, i.e. not multirow/multicol
2236−parseSimpleCell :: PandocMonad m => LP m Cell
2237−parseSimpleCell = simpleCell <$> (plainify <$> blocks)
2239−-- LaTeX tables are stored with empty cells underneath multirow cells
2240−-- denoting the grid spaces taken up by them. More specifically, if a
2241−-- cell spans m rows, then it will overwrite all the cells in the
2242−-- columns it spans for (m-1) rows underneath it, requiring padding
2243−-- cells in these places. These padding cells need to be removed for
2244−-- proper table reading. See #6603.
2246−-- These fixTable functions do not otherwise fix up malformed
2247−-- input tables: that is left to the table builder.
2248−fixTableHead :: TableHead -> TableHead
2249−fixTableHead (TableHead attr rows) = TableHead attr rows'
2251− rows' = fixTableRows rows
2253−fixTableBody :: TableBody -> TableBody
2254−fixTableBody (TableBody attr rhc th tb)
2255− = TableBody attr rhc th' tb'
2257− th' = fixTableRows th
2258− tb' = fixTableRows tb
2260−fixTableRows :: [Row] -> [Row]
2261−fixTableRows = fixTableRows' $ repeat Nothing
2263− fixTableRows' oldHang (Row attr cells : rs)
2264− = let (newHang, cells') = fixTableRow oldHang cells
2265− rs' = fixTableRows' newHang rs
2266− in Row attr cells' : rs'
2267− fixTableRows' _ [] = []
2269−-- The overhang is represented as Just (relative cell dimensions) or
2270−-- Nothing for an empty grid space.
2271−fixTableRow :: [Maybe (ColSpan, RowSpan)] -> [Cell] -> ([Maybe (ColSpan, RowSpan)], [Cell])
2272−fixTableRow oldHang cells
2273− -- If there's overhang, drop cells until their total width meets the
2274− -- width of the occupied grid spaces (or we run out)
2275− | (n, prefHang, restHang) <- splitHang oldHang
2277− = let cells' = dropToWidth getCellW n cells
2278− (restHang', cells'') = fixTableRow restHang cells'
2279− in (prefHang restHang', cells'')
2280− -- Otherwise record the overhang of a pending cell and fix the rest
2282− | c@(Cell _ _ h w _):cells' <- cells
2285− oldHang' = dropToWidth getHangW w' oldHang
2286− (newHang, cells'') = fixTableRow oldHang' cells'
2287− in (toHang w' h' <> newHang, c : cells'')
2291− getCellW (Cell _ _ _ w _) = w
2292− getHangW = maybe 1 fst
2293− getCS (ColSpan n) = n
2296− | r > 1 = [Just (c, r)]
2297− | otherwise = replicate (getCS c) Nothing
2299− -- Take the prefix of the overhang list representing filled grid
2300− -- spaces. Also return the remainder and the length of this prefix.
2301− splitHang = splitHang' 0 id
2303− splitHang' !n l (Just (c, r):xs)
2304− = splitHang' (n + c) (l . (toHang c (r-1) ++)) xs
2305− splitHang' n l xs = (n, l, xs)
2307− -- Drop list items until the total width of the dropped items
2308− -- exceeds the passed width.
2309− dropToWidth _ n l | n < 1 = l
2310− dropToWidth wproj n (c:cs) = dropToWidth wproj (n - wproj c) cs
2311− dropToWidth _ _ [] = []
2313−simpTable :: PandocMonad m => Text -> Bool -> LP m Blocks
2314−simpTable envname hasWidthParameter = try $ do
2315− when hasWidthParameter $ () <$ (spaces >> tok)
2317− colspecs <- parseAligns
2318− let (aligns, widths, prefsufs) = unzip3 colspecs
2319− optional $ controlSeq "caption" *> setCaption
2327− header' <- option [] . try . fmap (:[]) $
2328− parseTableRow envname prefsufs <* lbreak <* many1 hline
2330− rows <- sepEndBy (parseTableRow envname prefsufs)
2331− (lbreak <* optional (skipMany hline))
2333− optional $ controlSeq "caption" *> setCaption
2339− lookAhead $ controlSeq "end" -- make sure we're at end
2340− let th = fixTableHead $ TableHead nullAttr header'
2341− let tbs = [fixTableBody $ TableBody nullAttr 0 [] rows]
2342− let tf = TableFoot nullAttr []
2343− return $ table emptyCaption (zip aligns widths) th tbs tf
2345−addTableCaption :: PandocMonad m => Blocks -> LP m Blocks
2346−addTableCaption = walkM go
2347− where go (Table attr c spec th tb tf) = do
2349− let mblabel = sLastLabel st
2350− capt <- case (sCaption st, mblabel) of
2351− (Just ils, Nothing) -> return $ caption Nothing (plain ils)
2352− (Just ils, Just lab) -> do
2353− num <- getNextNumber sLastTableNum
2355− st{ sLastTableNum = num
2356− , sLabels = M.insert lab
2357− [Str (renderDottedNum num)]
2359− return $ caption Nothing (plain ils) -- add number??
2360− (Nothing, _) -> return c
2361− let attr' = case (attr, mblabel) of
2362− ((_,classes,kvs), Just ident) ->
2363− (ident,classes,kvs)
2365− return $ addAttrDiv attr' $ Table nullAttr capt spec th tb tf
2368−-- TODO: For now we add a Div to contain table attributes, since
2369−-- most writers don't do anything yet with attributes on Table.
2370−-- This can be removed when that changes.
2371−addAttrDiv :: Attr -> Block -> Block
2372−addAttrDiv ("",[],[]) b = b
2373−addAttrDiv attr b = Div attr [b]
2375block :: PandocMonad m => LP m Blocks
2017block :: PandocMonad m => LP m Blocks
2376block = do
2018block = do
2377 res <- (mempty <$ spaces1)
2019 res <- (mempty <$ spaces1)