From 83c1ce1d77d3ef058e4e5c645a8eb0379fab780f Mon Sep 17 00:00:00 2001 From: Nikolay Yakimov Date: Thu, 16 Apr 2020 02:20:01 +0300 Subject: Markdown Reader: Fix inline code in lists (#6284) Closes #6284. Previously inline code containing list markers was sometimes parsed incorrectly. --- src/Text/Pandoc/Readers/Markdown.hs | 17 +++++++++----- test/Tests/Readers/Markdown.hs | 47 +++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 6 deletions(-) diff --git a/src/Text/Pandoc/Readers/Markdown.hs b/src/Text/Pandoc/Readers/Markdown.hs index c9643f1b0..66f4df341 100644 --- a/src/Text/Pandoc/Readers/Markdown.hs +++ b/src/Text/Pandoc/Readers/Markdown.hs @@ -1517,12 +1517,17 @@ code :: PandocMonad m => MarkdownParser m (F Inlines) code = try $ do starts <- many1 (char '`') skipSpaces - result <- (trim . T.concat) <$> - manyTill (notFollowedBy (inList >> listStart) >> - (many1Char (noneOf "`\n") <|> many1Char (char '`') <|> - (char '\n' >> notFollowedBy' blankline >> return " "))) - (try (skipSpaces >> count (length starts) (char '`') >> - notFollowedBy (char '`'))) + result <- trim . T.concat + <$> manyTill + ( many1Char (noneOf "`\n") + <|> many1Char (char '`') + <|> (char '\n' + >> notFollowedBy (inList >> listStart) + >> notFollowedBy' blankline + >> return " ")) + (try $ skipSpaces + >> count (length starts) (char '`') + >> notFollowedBy (char '`')) rawattr <- (Left <$> try (guardEnabled Ext_raw_attribute >> rawAttribute)) <|> diff --git a/test/Tests/Readers/Markdown.hs b/test/Tests/Readers/Markdown.hs index d33c0e64a..228777496 100644 --- a/test/Tests/Readers/Markdown.hs +++ b/test/Tests/Readers/Markdown.hs @@ -171,6 +171,53 @@ tests = [ testGroup "inline code" =?> para (code "*" <> space <> str "{.haskell" <> space <> str ".special" <> space <> str "x=\"7\"}") ] + , testGroup "inline code in lists (regression tests for #6284)" $ + let lists = [("ordered", "1. ", ol), ("bullet", "- ", ul)] + ol = orderedListWith (1, Decimal, Period) + ul = bulletList + items = + [ ("in text" , ["If `(1) x`, then `2`"], [text "If " <> code "(1) x" <> text ", then " <> code "2"]) + , ("at start" , ["`#. x`" ], [code "#. x" ]) + , ("at start" , ["`- x`" ], [code "- x" ]) + , ("after literal backticks", ["`x``#. x`" ], [code "x``#. x" ]) + , ("after literal backticks", ["`x``- x`" ], [code "x``- x" ]) + ] + lis = ["`text","y","x`"] + lis' = ["text","y","x"] + bldLsts w lsts txts + = let (res, res', f) = + foldr (\((_, _, lt), lc) (acc, tacc, t) -> + if lt [] == t [] + then (acc, lc : tacc, lt) + else (join t tacc acc, [lc], lt)) + (mempty, [], mconcat) + (zip lsts (map text txts)) + join t tacc acc = case tacc of + [] -> acc + [x] -> t [plain x] <> acc + xs -> t (map w xs) <> acc + in join f res' res + in ["code with list marker "<>mp<>" in " <> ln <> " list" =: + T.intercalate "\n" (map (lstr <>) istrs) =?> lbld (map plain iblds) + | (ln, lstr, lbld) <- lists, (mp, istrs, iblds) <- items] + <> [ "lists with newlines in backticks" =: + T.intercalate "\n" (zipWith (\i (_, lt, _) -> lt <> i) lis lsts) + =?> bldLsts plain lsts lis + | lsts <- [ [i, j, k] | i <- lists, j <- lists, k <- lists] + ] + <> [ "lists with newlines and indent in backticks" =: + T.intercalate ("\n" <> T.replicate 4 " ") (zipWith (\i (_, lt, _) -> lt <> i) lis lsts) + =?> let (_, _, f) = head lsts + in f [plain $ code $ T.intercalate (T.replicate 5 " ") $ head lis' : zipWith (\i (_, lt, _) -> lt <> i) (tail lis') (tail lsts)] + | lsts <- [ [i, j, k] | i <- lists, j <- lists, k <- lists] + ] + <> [ "lists with blank lines and indent in backticks" =: + T.intercalate ("\n\n" <> T.replicate 4 " ") (zipWith (\i (_, lt, _) -> lt <> i) lis lsts) + <> "\n" + =?> let (_, _, f) = head lsts + in f . pure $ (para . text $ head lis) <> bldLsts para (tail lsts) (tail lis) + | lsts <- [ [i, j, k] | i <- lists, j <- lists, k <- lists] + ] , testGroup "emph and strong" [ "two strongs in emph" =: "***a**b **c**d*" =?> para (emph (strong (str "a") <> str "b" <> space -- cgit v1.2.3