html-parse 0.2.1.0 → 0.2.2.0
raw patch · 4 files changed
+41/−7 lines, 4 filesdep ~basedep ~containersPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: base, containers
API changes (from Hackage documentation)
Files
- changelog.md +5/−0
- html-parse.cabal +12/−5
- src/Text/HTML/Parser.hs +7/−2
- tests/Text/HTML/ParserSpec.hs +17/−0
changelog.md view
@@ -1,5 +1,10 @@ # Changelog for `html-parse` +## 0.2.2.0++- Fix dropping of attributes in some cases (#27)+- Fix parsing of unquoted attributes (#28)+ ## 0.2.1.0 - Added support for decoding of character references (#18)
html-parse.cabal view
@@ -1,5 +1,5 @@ name: html-parse-version: 0.2.1.0+version: 0.2.2.0 synopsis: A high-performance HTML tokenizer description: This package provides a fast and reasonably robust HTML5 tokenizer built@@ -52,13 +52,20 @@ category: Text build-type: Simple cabal-version: >=1.10-tested-with: GHC==8.4.*, GHC==8.6.*, GHC==8.8.*, GHC==8.10.*, GHC==9.0.*, GHC==9.2.*, GHC==9.4.*+tested-with: GHC==8.10.7,+ GHC==9.0.2,+ GHC==9.2.5,+ GHC==9.4.5,+ GHC==9.6.7,+ GHC==9.8.4,+ GHC==9.10.1,+ GHC==9.12.1 extra-source-files: changelog.md source-repository head type: git- location: git://github.com/bgamari/html-parse+ location: https://github.com/bgamari/html-parse library exposed-modules: Text.HTML.Parser, Text.HTML.Tree@@ -66,11 +73,11 @@ ghc-options: -Wall hs-source-dirs: src other-extensions: OverloadedStrings, DeriveGeneric- build-depends: base >=4.7 && <4.20,+ build-depends: base >=4.7 && <4.22, deepseq >=1.3 && <1.6, attoparsec >=0.13 && <0.15, text >=1.2 && <2.2,- containers >=0.5 && <0.8+ containers >=0.5 && <0.9 default-language: Haskell2010 benchmark bench
src/Text/HTML/Parser.hs view
@@ -3,6 +3,9 @@ {-# LANGUAGE LambdaCase #-} {-# OPTIONS_GHC -O2 #-}+{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-}+{-# HLINT ignore "Redundant id" #-}+{-# HLINT ignore "Redundant bracket" #-} -- | This is a performance-oriented HTML tokenizer aim at web-crawling -- applications. It follows the HTML5 parsing specification quite closely,@@ -200,6 +203,8 @@ name <- takeWhile $ not . (isWhitespace `orC` isC '/' `orC` isC '=' `orC` isC '>') id $ (endOfInput >> afterAttrName tag attrs name) <|> (char '=' >> beforeAttrValue tag attrs name)+ <|> (satisfy isWhitespace >> afterAttrName tag attrs name)+ -- N.B. '/' is handled by afterAttrName <|> try (do mc <- peekChar case mc of Just c | notNameChar c -> afterAttrName tag attrs name@@ -211,7 +216,7 @@ afterAttrName :: TagName -> [Attr] -> AttrName -> Parser Token afterAttrName tag attrs name = do skipWhile isWhitespace- id $ (char '/' >> selfClosingStartTag tag attrs)+ id $ (char '/' >> selfClosingStartTag tag (Attr name T.empty : attrs)) <|> (char '=' >> beforeAttrValue tag attrs name) <|> (char '>' >> return (TagOpen tag (Attr name T.empty : attrs))) <|> (endOfInput >> return endOfFileToken)@@ -244,7 +249,7 @@ attrValueUnquoted :: TagName -> [Attr] -> AttrName -> Parser Token attrValueUnquoted tag attrs name = do value <- takeTill $ isWhitespace `orC` isC '>'- id $ (satisfy isWhitespace >> beforeAttrName tag attrs) -- unsure: don't emit?+ id $ (satisfy isWhitespace >> beforeAttrName tag (Attr name value : attrs)) <|> (char '>' >> return (TagOpen tag (Attr name value : attrs))) <|> (endOfInput >> return endOfFileToken)
tests/Text/HTML/ParserSpec.hs view
@@ -85,6 +85,10 @@ maxListOf :: Int -> Gen a -> Gen [a] maxListOf n g = take n <$> listOf g +parsesTo :: String -> [Token] -> Spec+parsesTo str expected = do+ it ("parses " <> str) $ do+ parseTokens (T.pack str) `shouldBe` expected spec :: Spec spec = do@@ -110,3 +114,16 @@ parseTokens "<!-- img src=\"/www_images/NCEP_GFS.gif\"><!- -------------------------------------------------------- >" `shouldBe` [Comment " img src=\"/www_images/NCEP_GFS.gif\"><!- -------------------------------------------------------- >"] it "parses entity" $ do parseTokens "<" `shouldBe` [ContentText "<"]+ -- traling whitespace after attributes+ it "<foo .baz .bar>" $ do+ parseTokens "<foo .baz .bar>" `shouldBe` [TagOpen "foo" [Attr ".bar" "", Attr ".baz" ""]]+ it "<foo .baz .bar >" $ do+ parseTokens "<foo .baz .bar >" `shouldBe` [TagOpen "foo" [Attr ".bar" "", Attr ".baz" ""]]+ -- traling whitespace after attributes in self-closing tag (#27)+ "<foo .baz .bar/>" `parsesTo` [TagSelfClose "foo" [Attr ".bar" "", Attr ".baz" ""]]+ "<foo .baz .bar />" `parsesTo` [TagSelfClose "foo" [Attr ".bar" "", Attr ".baz" ""]]+ -- #28+ "<foo bar=\"baz\" foo='qux' a=b>" `parsesTo` [TagOpen "foo" [Attr "a" "b", Attr "foo" "qux", Attr "bar" "baz"]]+ "<foo bar=baz foo=qux a=b >" `parsesTo` [TagOpen "foo" [Attr "a" "b", Attr "foo" "qux", Attr "bar" "baz"]]+ "<foo bar=baz >" `parsesTo` [TagOpen "foo" [Attr "bar" "baz"]]+ "<foo bar=baz>" `parsesTo` [TagOpen "foo" [Attr "bar" "baz"]]