packages feed

HandsomeSoup 0.2 → 0.3

raw patch · 4 files changed

+28/−9 lines, 4 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

Files

HandsomeSoup.cabal view
@@ -7,7 +7,7 @@ -- The package version. See the Haskell package versioning policy -- (http://www.haskell.org/haskellwiki/Package_versioning_policy) for -- standards guiding when and how versions should be incremented.-Version:             0.2+Version:             0.3  -- A short (one-line) description of the package. Synopsis:            Work with HTML more easily in HXT
README.markdown view
@@ -1,12 +1,12 @@ # HandsomeSoup -Current Status: Usable but untested (tests coming soon! See todo list).+Current Status: Usable. Please file bugs!  HandsomeSoup is the library I wish I had when I started parsing HTML in Haskell.  It is built on top of [HXT](http://www.fh-wedel.de/~si/HXmlToolbox/) and adds a few functions that make is easier to work with HTML. -Most importantly, it adds CSS selectors to HXT. The goal of HandsomeSoup is to be a complete CSS2 parser for HXT (it is very close to this right now).+Most importantly, it adds CSS selectors to HXT. The goal of HandsomeSoup is to be a complete CSS2 selector parser for HXT.  ## Install @@ -30,7 +30,7 @@ ### Or a local page using `parseHtml`      contents <- readFile [filename]-    doc <- parseHtml contents+    let doc = parseHtml contents  ### Easily extract elements using `css` @@ -41,10 +41,12 @@     doc <<< css "a#link1"     doc <<< css "a.foo"     doc <<< css "p > a"+    doc <<< css "p strong"     doc <<< css "#container h1"     doc <<< css "img[width]"     doc <<< css "img[width=400]"     doc <<< css "a[class~=bar]"+    doc <<< css "a:first-child"  ### Easily get attributes using `(!)` 
Text/CSS/Parser.hs view
@@ -4,14 +4,20 @@ import qualified Data.Functor.Identity as I import Data.List import Text.CSS.Utils- -- if no tag name was given, sName will be set to '*' -- attrs are (attr name, attr value). -- if attr value is the empty string, we just check to -- make sure that the element has that attribute.+-- -- if the attr value is prefixed with a '~', we treat -- that attribute as a list of words separated by a space -- and make sure that at least one of those words matches.+-- +-- if the attr value is prefixed with a `|`, the value must+-- be exactly val or start with val immediately followed by a '-'.+-- This is primarily intended to allow language subcode matches.+-- Example: [lang|="en"] matches "en", "en-US", etc.+-- From: http://www.w3.org/TR/CSS2/selector.html. data Selector = Selector { sName :: String, sAttrs :: [(String,String)], spseudoSelectores :: [String] } | Space | ChildOf | FollowedBy deriving (Show)  -- pretty printers for debugging@@ -52,12 +58,16 @@ -- | selects attributes, like @ [id] @ (element must have id) or @ [id=foo] @ (element must have id foo). attributeSelector :: ParsecT [Char] u I.Identity ([Char], [Char]) attributeSelector = do-      contents <- between (char '[') (char ']') (many1 (alphaNum <|> oneOf "~="))+      _contents <- between (char '[') (char ']') (many1 (alphaNum <|> oneOf "|~=\"'"))+      -- remove quotes+      let contents = filter (\c -> c /= '"' && c /= '\'') _contents       if "~=" `isInfixOf` contents            then return $ (\(a, b) -> (a, '~':b)) $ splitOn "~=" contents-          else if '=' `elem` contents-               then return $ splitOn "=" contents-               else return (contents, "")+          else if "|=" `isInfixOf` contents +              then return $ (\(a, b) -> (a, '|':b)) $ splitOn "|=" contents+              else if '=' `elem` contents+                   then return $ splitOn "=" contents+                   else return (contents, "")  -- | selector for everything after the type except pseudoSelectores secondarySelector = many1 (classSelector <|> idSelector <|> attributeSelector)
Text/HandsomeSoup.hs view
@@ -67,7 +67,14 @@         makeAttrs [] = this         makeAttr (name, "") = hasAttr name         makeAttr (name, '~':value) = hasAttrValue name (elem value . words)+        makeAttr (name, '|':value) = hasAttrValue name (headMatch value)         makeAttr (name, value) = hasAttrValue name (==value)         makePseudos (p:pseudos) = foldl (\acc pseudo -> acc >>> makePseudo pseudo) (makePseudo p) pseudos         makePseudos [] = id         makePseudo "first-child" = take 1++-- | Used internally to match attribute selectors like @ [att|=val] @.+-- From: http://www.w3.org/TR/CSS2/selector.html+-- "Represents an element with the att attribute, its value either being exactly "val" or beginning with "val" immediately followed by '-'".+headMatch value attrValue = value == attrValue || value `isPrefixOf` attrValue+    where first = head . words $ attrValue