{-# OPTIONS_HADDOCK hide #-} module Text.HTML.Scalpel.Internal.Select.Combinators ( (//) , (@:) , (@=) , (@=~) , hasClass ) where import Text.HTML.Scalpel.Internal.Select.Types import qualified Data.Text as T import qualified Text.Regex.Base.RegexLike as RE import qualified Text.StringLike as TagSoup -- | The '@:' operator creates a 'Selector' by combining a 'TagName' with a list -- of 'AttributePredicate's. (@:) :: (TagSoup.StringLike str, TagName str tag) => tag -> [AttributePredicate str] -> Selector str (@:) tag attrs = MkSelector [toSelectNode tag attrs] infixl 9 @: -- | The '@=' operator creates an 'AttributePredicate' that will match -- attributes with the given name and value. -- -- If you are attempting to match a specific class of a tag with potentially -- multiple classes, you should use the 'hasClass' utility function. (@=) :: (TagSoup.StringLike str, AttributeName str key) => key -> str -> AttributePredicate str (@=) key value (attrKey, attrValue) = matchKey key attrKey && value == attrValue infixl 6 @= -- | The '@=~' operator creates an 'AttributePredicate' that will match -- attributes with the given name and whose value matches the given regular -- expression. (@=~) :: (TagSoup.StringLike str, AttributeName str key, RE.RegexLike re str) => key -> re -> AttributePredicate str (@=~) key re (attrKey, attrValue) = matchKey key attrKey && RE.matchTest re attrValue infixl 6 @=~ -- | The '//' operator creates an 'Selector' by nesting one 'Selector' in -- another. For example, @"div" // "a"@ will create a 'Selector' that matches -- anchor tags that are nested arbitrarily deep within a div tag. (//) :: (TagSoup.StringLike str, Selectable str a, Selectable str b) => a -> b -> Selector str (//) a b = MkSelector (as ++ bs) where (MkSelector as) = toSelector a (MkSelector bs) = toSelector b infixl 5 // -- | The classes of a tag are defined in HTML as a space separated list given by -- the @class@ attribute. The 'hasClass' function will match a @class@ attribute -- if the given class appears anywhere in the space separated list of classes. hasClass :: TagSoup.StringLike str => str -> AttributePredicate str hasClass clazz (attrName, classes) | "class" == TagSoup.toString attrName = any (== textClass) classList | otherwise = False where textClass = TagSoup.castString clazz textClasses = TagSoup.castString classes classList = T.split (== ' ') textClasses