haddock-library 1.2.0 → 1.2.1
raw patch · 3 files changed
+79/−39 lines, 3 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- haddock-library.cabal +2/−2
- src/Documentation/Haddock/Parser.hs +55/−35
- test/Documentation/Haddock/ParserSpec.hs +22/−2
haddock-library.cabal view
@@ -1,5 +1,5 @@ name: haddock-library-version: 1.2.0+version: 1.2.1 synopsis: Library exposing some functionality of Haddock. description: Haddock is a documentation-generation tool for Haskell libraries. These modules expose some functionality of it@@ -21,7 +21,7 @@ default-language: Haskell2010 build-depends:- base >= 4.3 && < 4.9+ base >= 4.5 && < 4.9 , bytestring , transformers , deepseq
src/Documentation/Haddock/Parser.hs view
@@ -231,18 +231,20 @@ -- | Paragraph parser, called by 'parseParas'. paragraph :: Parser (DocH mod Identifier)-paragraph = examples <|> skipSpace *> (- since- <|> unorderedList- <|> orderedList- <|> birdtracks- <|> codeblock- <|> property- <|> header- <|> textParagraphThatStartsWithMarkdownLink- <|> definitionList- <|> docParagraph <$> textParagraph- )+paragraph = examples <|> do+ indent <- takeIndent+ choice+ [ since+ , unorderedList indent+ , orderedList indent+ , birdtracks+ , codeblock+ , property+ , header+ , textParagraphThatStartsWithMarkdownLink+ , definitionList indent+ , docParagraph <$> textParagraph+ ] since :: Parser (DocH mod a) since = ("@since " *> version <* skipHorizontalSpace <* endOfLine) >>= setSince >> return DocEmpty@@ -283,16 +285,16 @@ | otherwise = " " -- | Parses unordered (bullet) lists.-unorderedList :: Parser (DocH mod Identifier)-unorderedList = DocUnorderedList <$> p+unorderedList :: BS.ByteString -> Parser (DocH mod Identifier)+unorderedList indent = DocUnorderedList <$> p where- p = ("*" <|> "-") *> innerList p+ p = ("*" <|> "-") *> innerList indent p -- | Parses ordered lists (numbered or dashed).-orderedList :: Parser (DocH mod Identifier)-orderedList = DocOrderedList <$> p+orderedList :: BS.ByteString -> Parser (DocH mod Identifier)+orderedList indent = DocOrderedList <$> p where- p = (paren <|> dot) *> innerList p+ p = (paren <|> dot) *> innerList indent p dot = (decimal :: Parser Int) <* "." paren = "(" *> decimal <* ")" @@ -301,23 +303,24 @@ -- same paragraph. Usually used as -- -- > someListFunction = listBeginning *> innerList someListFunction-innerList :: Parser [DocH mod Identifier] -> Parser [DocH mod Identifier]-innerList item = do+innerList :: BS.ByteString -> Parser [DocH mod Identifier]+ -> Parser [DocH mod Identifier]+innerList indent item = do c <- takeLine- (cs, items) <- more item+ (cs, items) <- more indent item let contents = docParagraph . parseString . dropNLs . unlines $ c : cs return $ case items of Left p -> [contents `docAppend` p] Right i -> contents : i -- | Parses definition lists.-definitionList :: Parser (DocH mod Identifier)-definitionList = DocDefList <$> p+definitionList :: BS.ByteString -> Parser (DocH mod Identifier)+definitionList indent = DocDefList <$> p where p = do label <- "[" *> (parseStringBS <$> takeWhile1 (`notElem` ("]\n" :: String))) <* ("]" <* optional ":") c <- takeLine- (cs, items) <- more p+ (cs, items) <- more indent p let contents = parseString . dropNLs . unlines $ c : cs return $ case items of Left x -> [(label, contents `docAppend` x)]@@ -330,32 +333,40 @@ -- | Main worker for 'innerList' and 'definitionList'. -- We need the 'Either' here to be able to tell in the respective functions -- whether we're dealing with the next list or a nested paragraph.-more :: Monoid a => Parser a+more :: Monoid a => BS.ByteString -> Parser a -> Parser ([String], Either (DocH mod Identifier) a)-more item = innerParagraphs <|> moreListItems item- <|> moreContent item <|> pure ([], Right mempty)+more indent item = innerParagraphs indent+ <|> moreListItems indent item+ <|> moreContent indent item+ <|> pure ([], Right mempty) -- | Used by 'innerList' and 'definitionList' to parse any nested paragraphs.-innerParagraphs :: Parser ([String], Either (DocH mod Identifier) a)-innerParagraphs = (,) [] . Left <$> ("\n" *> indentedParagraphs)+innerParagraphs :: BS.ByteString+ -> Parser ([String], Either (DocH mod Identifier) a)+innerParagraphs indent = (,) [] . Left <$> ("\n" *> indentedParagraphs indent) -- | Attempts to fetch the next list if possibly. Used by 'innerList' and -- 'definitionList' to recursively grab lists that aren't separated by a whole -- paragraph.-moreListItems :: Parser a+moreListItems :: BS.ByteString -> Parser a -> Parser ([String], Either (DocH mod Identifier) a)-moreListItems item = (,) [] . Right <$> (skipSpace *> item)+moreListItems indent item = (,) [] . Right <$> indentedItem+ where+ indentedItem = string indent *> skipSpace *> item -- | Helper for 'innerList' and 'definitionList' which simply takes -- a line of text and attempts to parse more list content with 'more'.-moreContent :: Monoid a => Parser a+moreContent :: Monoid a => BS.ByteString -> Parser a -> Parser ([String], Either (DocH mod Identifier) a)-moreContent item = first . (:) <$> nonEmptyLine <*> more item+moreContent indent item = first . (:) <$> nonEmptyLine <*> more indent item -- | Parses an indented paragraph. -- The indentation is 4 spaces.-indentedParagraphs :: Parser (DocH mod Identifier)-indentedParagraphs = (concat <$> dropFrontOfPara " ") >>= parseParagraphs+indentedParagraphs :: BS.ByteString -> Parser (DocH mod Identifier)+indentedParagraphs indent =+ (concat <$> dropFrontOfPara indent') >>= parseParagraphs+ where+ indent' = string $ BS.append indent " " -- | Grab as many fully indented paragraphs as we can. dropFrontOfPara :: Parser BS.ByteString -> Parser [String]@@ -381,6 +392,15 @@ takeNonEmptyLine :: Parser String takeNonEmptyLine = do (++ "\n") . decodeUtf8 <$> (takeWhile1 (/= '\n') >>= nonSpace) <* "\n"++-- | Takes indentation of first non-empty line.+--+-- More precisely: skips all whitespace-only lines and returns indentation+-- (horizontal space, might be empty) of that non-empty line.+takeIndent :: Parser BS.ByteString+takeIndent = do+ indent <- takeHorizontalSpace+ "\n" *> takeIndent <|> return indent -- | Blocks of text of the form: --
test/Documentation/Haddock/ParserSpec.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE OverloadedStrings, FlexibleInstances #-}+{-# LANGUAGE LambdaCase #-} {-# OPTIONS_GHC -fno-warn-orphans #-} module Documentation.Haddock.ParserSpec (main, spec) where@@ -55,8 +56,10 @@ it "accepts hexadecimal character references" $ do "e" `shouldParseTo` "e" - it "allows to backslash-escape characters" $ do- property $ \x -> ['\\', x] `shouldParseTo` DocString [x]+ it "allows to backslash-escape characters except \\r" $ do+ property $ \case+ '\r' -> "\\\r" `shouldParseTo` DocString "\\"+ x -> ['\\', x] `shouldParseTo` DocString [x] context "when parsing strings contaning numeric character references" $ do it "will implicitly convert digits to characters" $ do@@ -692,6 +695,23 @@ <> DocUnorderedList [ DocParagraph "bar" ] ] <> DocOrderedList [ DocParagraph "baz" ]++ it "allows arbitrary initial indent of a list" $ do+ unlines+ [ " * foo"+ , " * bar"+ , ""+ , " * quux"+ , ""+ , " * baz"+ ]+ `shouldParseTo`+ DocUnorderedList+ [ DocParagraph "foo"+ , DocParagraph "bar"+ <> DocUnorderedList [ DocParagraph "quux" ]+ , DocParagraph "baz"+ ] it "definition lists can come back to top level with a different list" $ do "[foo]: foov\n\n [bar]: barv\n\n1. baz" `shouldParseTo`