{-# OPTIONS_GHC -Wall #-} {-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE FlexibleInstances #-} module Text.HTML.TagSoup.Navigate.Types.Tag( Tag(..) , HasTag(..) , AsTag(..) , tagOpen , tagAttributes , tagAttributeNames , tagAttributeValues , tagRows , tagColumns , tagsoupTag ) where import Control.Applicative((<*>), pure) import Control.Category(id, (.)) import Control.Lens(Lens', Prism', Traversal', Each(each), Iso, iso, prism', view, from, _1, _2, (^.), ( # )) import Data.Eq(Eq) import Data.Eq.Deriving(deriveEq1) import Data.Maybe(Maybe(Nothing, Just)) import Data.Ord(Ord) import Data.Ord.Deriving(deriveOrd1) import Data.Foldable(Foldable(foldMap)) import Data.Functor(Functor(fmap), (<$>)) import Data.Monoid(mappend, mempty) import Data.Traversable(Traversable(traverse)) import Prelude(Show) import Text.HTML.TagSoup.Navigate.Types.Attribute(Attribute, Row, Column, attributeName, attributeValue, tagsoupAttribute) import qualified Text.HTML.TagSoup as TagSoup(Tag(TagOpen, TagClose, TagText, TagComment, TagWarning, TagPosition)) import qualified Text.HTML.TagSoup.Tree as TagSoup(TagTree(TagBranch, TagLeaf)) import Text.Show.Deriving(deriveShow1) data Tag str = TagOpen str [Attribute str] | TagClose str | TagText str | TagComment str | TagWarning str | TagPosition Row Column deriving (Eq, Ord, Show) instance Functor Tag where fmap f (TagOpen s as) = TagOpen (f s) (fmap (fmap f) as) fmap f (TagClose s) = TagClose (f s) fmap f (TagText s) = TagText (f s) fmap f (TagComment s) = TagComment (f s) fmap f (TagWarning s) = TagWarning (f s) fmap _ (TagPosition r c) = TagPosition r c instance Foldable Tag where foldMap f (TagOpen s as) = f s `mappend` foldMap (foldMap f) as foldMap f (TagClose s) = f s foldMap f (TagText s) = f s foldMap f (TagComment s) = f s foldMap f (TagWarning s) = f s foldMap _ (TagPosition _ _) = mempty instance Traversable Tag where traverse f (TagOpen s as) = TagOpen <$> f s <*> traverse (traverse f) as traverse f (TagClose s) = TagClose <$> f s traverse f (TagText s) = TagText <$> f s traverse f (TagComment s) = TagComment <$> f s traverse f (TagWarning s) = TagWarning <$> f s traverse _ (TagPosition r c) = pure (TagPosition r c) deriveEq1 ''Tag deriveOrd1 ''Tag deriveShow1 ''Tag instance Each (Tag str) (Tag str') str str' where each f (TagOpen a as) = TagOpen <$> f a <*> traverse (traverse f) as each f (TagClose s) = TagClose <$> f s each f (TagText s) = TagClose <$> f s each f (TagComment s) = TagClose <$> f s each f (TagWarning s) = TagClose <$> f s each _ (TagPosition r c) = pure (TagPosition r c) class HasTag a str | a -> str where tag :: Lens' a (Tag str) instance HasTag (Tag str) str where tag = id instance HasTag (TagSoup.Tag str) str where tag = from tagsoupTag . tag class AsTag a str | a -> str where _Tag :: Prism' a (Tag str) _TagOpen :: Prism' a (str, [Attribute str]) _TagOpen = _Tag . _TagOpen _TagClose :: Prism' a str _TagClose = _Tag . _TagClose _TagText :: Prism' a str _TagText = _Tag . _TagText _TagComment :: Prism' a str _TagComment = _Tag . _TagComment _TagWarning :: Prism' a str _TagWarning = _Tag . _TagWarning _TagPosition :: Prism' a (Row, Column) _TagPosition = _Tag . _TagPosition instance AsTag (Tag str) str where _Tag = id _TagOpen = prism' (\(s, as) -> TagOpen s as) (\case TagOpen s as -> Just (s, as) _ -> Nothing ) _TagClose = prism' TagClose (\case TagClose s -> Just s _ -> Nothing ) _TagText = prism' TagText (\case TagText s -> Just s _ -> Nothing ) _TagComment = prism' TagComment (\case TagComment s -> Just s _ -> Nothing ) _TagWarning = prism' TagWarning (\case TagWarning s -> Just s _ -> Nothing ) _TagPosition = prism' (\(r, c) -> TagPosition r c) (\case TagPosition r c -> Just (r, c) _ -> Nothing ) instance AsTag (TagSoup.Tag str) str where _Tag = from tagsoupTag . _Tag instance AsTag (TagSoup.TagTree str) str where _Tag = prism' (\t -> TagSoup.TagLeaf (view tagsoupTag t)) (\case TagSoup.TagLeaf x -> Just (view (from tagsoupTag) x) TagSoup.TagBranch _ _ _ -> Nothing ) tagOpen :: AsTag a str => Traversal' a str tagOpen = _TagOpen . _1 tagAttributes :: AsTag a str => Traversal' a (Attribute str) tagAttributes = _TagOpen . _2 . traverse tagAttributeNames :: AsTag a str => Traversal' a str tagAttributeNames = tagAttributes . attributeName tagAttributeValues :: AsTag a str => Traversal' a str tagAttributeValues = tagAttributes . attributeValue tagRows :: AsTag a str => Traversal' a Row tagRows = _TagPosition . _1 tagColumns :: AsTag a str => Traversal' a Column tagColumns = _TagPosition . _2 tagsoupTag :: Iso (Tag str) (Tag str') (TagSoup.Tag str) (TagSoup.Tag str') tagsoupTag = iso (\t -> case t of TagOpen s as -> TagSoup.TagOpen s (fmap (^. tagsoupAttribute) as) TagClose s -> TagSoup.TagClose s TagText s -> TagSoup.TagText s TagComment s -> TagSoup.TagComment s TagWarning s -> TagSoup.TagWarning s TagPosition r c -> TagSoup.TagPosition r c) (\t -> case t of TagSoup.TagOpen s as -> TagOpen s (fmap (tagsoupAttribute #) as) TagSoup.TagClose s -> TagClose s TagSoup.TagText s -> TagText s TagSoup.TagComment s -> TagComment s TagSoup.TagWarning s -> TagWarning s TagSoup.TagPosition r c -> TagPosition r c)