diff --git a/src/MdToHTML.hs b/src/MdToHTML.hs index 0e05836..dd863f8 100644 --- a/src/MdToHTML.hs +++ b/src/MdToHTML.hs @@ -120,6 +120,16 @@ fallthroughParser :: [ReadP a] -> ReadP a fallthroughParser [x] = x fallthroughParser (x : xs) = x <++ fallthroughParser xs +myMany :: (Monoid a) => ReadP a -> ReadP [a] +myMany p = do + remaining <- look + case remaining of + [] -> return [] + _ -> return [] +++ myMany1 p + +myMany1 :: (Monoid a) => ReadP a -> ReadP [a] +myMany1 p = liftM2 (:) p (myMany p) + -- --------------- -- Parse a markdown header, denoted by 1-6 #'s followed by some text, followed by EOL. @@ -143,19 +153,25 @@ parseBold = parseBoldWith "**" <|> parseBoldWith "__" where parseBoldWith delim = do string delim - inside <- many1 parseLineToken + inside <- myMany1 parseLineToken string delim return (Bold (Line inside)) -- Parse italic text parseItalic :: ReadP MdToken -parseItalic = parseItalicWith "*" <|> parseItalicWith "_" +parseItalic = parseItalicWith '*' <|> parseItalicWith '_' where parseItalicWith delim = do - string delim - inside <- many1 parseLineToken - string delim + exactlyOnce delim + inside <- myMany1 parseLineToken + exactlyOnce delim return (Italic (Line inside)) + exactlyOnce ch = do + char ch + remaining <- look + case remaining of + [] -> return ch + x : xs -> if x == ch then pfail else return ch -- Parse strikethrough text parseStrikethrough :: ReadP MdToken @@ -250,7 +266,7 @@ parseLine :: ReadP MdToken parseLine = do skipSpaces -- Fail if we have reached the end of the document. - parsed <- manyTill parseLineToken eof + parsed <- myMany1 parseLineToken return (Line parsed) -- Parse a paragraph, which is a 'Line' (can span multiple actual lines), separated by double-newlines. diff --git a/src/MdToHtmlTest.hs b/src/MdToHtmlTest.hs index f36c6d8..9885853 100644 --- a/src/MdToHtmlTest.hs +++ b/src/MdToHtmlTest.hs @@ -22,6 +22,7 @@ headerTests = boldTests = TestList [ check_equal "Should convert bold" "

Hello

" (convert "__Hello__"), + check_equal " Should not convert incomplete bold" "

**Hello

" (convert "**Hello"), check_equal "Should convert italic" "

Hello

" (convert "_Hello_"), check_equal "Should convert bold and italic in a sentence" "

It is a wonderful day

" (convert "It _is_ a __wonderful__ day"), check_equal "Should convert nested bold and italic" "

Bold then Italic

" (convert "**Bold then *Italic***"),