{-# LANGUAGE DeriveDataTypeable #-}
-- | The central type in TagSoup

module Text.HTML.TagSoup.Type(
    -- * Data structures and parsing
    StringLike, Tag(..), Attribute, Row, Column,
    
    -- * Position manipulation
    Position(..), tagPosition, nullPosition, positionChar, positionString,

    -- * Tag identification
    isTagOpen, isTagClose, isTagText, isTagWarning, isTagPosition,
    isTagOpenName, isTagCloseName, isTagComment,

    -- * Extraction
    fromTagText, fromAttrib,
    maybeTagText, maybeTagWarning,
    innerText,
    ) where


import Data.List (foldl')
import Data.Maybe (fromMaybe, mapMaybe)
import Text.StringLike
import Data.Data(Data, Typeable)

-- | An HTML attribute @id=\"name\"@ generates @(\"id\",\"name\")@
type Attribute str = (str,str)

-- | The row/line of a position, starting at 1
type Row = Int

-- | The column of a position, starting at 1
type Column = Int


--- All positions are stored as a row and a column, with (1,1) being the
--- top-left position
data Position = Position !Row !Column deriving (Int -> Position -> ShowS
[Position] -> ShowS
Position -> String
(Int -> Position -> ShowS)
-> (Position -> String) -> ([Position] -> ShowS) -> Show Position
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Position] -> ShowS
$cshowList :: [Position] -> ShowS
show :: Position -> String
$cshow :: Position -> String
showsPrec :: Int -> Position -> ShowS
$cshowsPrec :: Int -> Position -> ShowS
Show,Position -> Position -> Bool
(Position -> Position -> Bool)
-> (Position -> Position -> Bool) -> Eq Position
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Position -> Position -> Bool
$c/= :: Position -> Position -> Bool
== :: Position -> Position -> Bool
$c== :: Position -> Position -> Bool
Eq,Eq Position
Eq Position =>
(Position -> Position -> Ordering)
-> (Position -> Position -> Bool)
-> (Position -> Position -> Bool)
-> (Position -> Position -> Bool)
-> (Position -> Position -> Bool)
-> (Position -> Position -> Position)
-> (Position -> Position -> Position)
-> Ord Position
Position -> Position -> Bool
Position -> Position -> Ordering
Position -> Position -> Position
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Position -> Position -> Position
$cmin :: Position -> Position -> Position
max :: Position -> Position -> Position
$cmax :: Position -> Position -> Position
>= :: Position -> Position -> Bool
$c>= :: Position -> Position -> Bool
> :: Position -> Position -> Bool
$c> :: Position -> Position -> Bool
<= :: Position -> Position -> Bool
$c<= :: Position -> Position -> Bool
< :: Position -> Position -> Bool
$c< :: Position -> Position -> Bool
compare :: Position -> Position -> Ordering
$ccompare :: Position -> Position -> Ordering
$cp1Ord :: Eq Position
Ord)

nullPosition :: Position
nullPosition :: Position
nullPosition = Int -> Int -> Position
Position 1 1

positionString :: Position -> String -> Position
positionString :: Position -> String -> Position
positionString = (Position -> Char -> Position) -> Position -> String -> Position
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' Position -> Char -> Position
positionChar

positionChar :: Position -> Char -> Position
positionChar :: Position -> Char -> Position
positionChar (Position r :: Int
r c :: Int
c) x :: Char
x = case Char
x of
    '\n' -> Int -> Int -> Position
Position (Int
rInt -> Int -> Int
forall a. Num a => a -> a -> a
+1) 1
    '\t' -> Int -> Int -> Position
Position Int
r (Int
c Int -> Int -> Int
forall a. Num a => a -> a -> a
+ 8 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int -> Int -> Int
forall a. Integral a => a -> a -> a
mod (Int
cInt -> Int -> Int
forall a. Num a => a -> a -> a
-1) 8)
    _    -> Int -> Int -> Position
Position Int
r (Int
cInt -> Int -> Int
forall a. Num a => a -> a -> a
+1)

tagPosition :: Position -> Tag str
tagPosition :: Position -> Tag str
tagPosition (Position r :: Int
r c :: Int
c) = Int -> Int -> Tag str
forall str. Int -> Int -> Tag str
TagPosition Int
r Int
c


-- | A single HTML element. A whole document is represented by a list of @Tag@.
--   There is no requirement for 'TagOpen' and 'TagClose' to match.
data Tag str =
     TagOpen str [Attribute str]  -- ^ An open tag with 'Attribute's in their original order
   | TagClose str                 -- ^ A closing tag
   | TagText str                  -- ^ A text node, guaranteed not to be the empty string
   | TagComment str               -- ^ A comment
   | TagWarning str               -- ^ Meta: A syntax error in the input file
   | TagPosition !Row !Column     -- ^ Meta: The position of a parsed element
     deriving (Int -> Tag str -> ShowS
[Tag str] -> ShowS
Tag str -> String
(Int -> Tag str -> ShowS)
-> (Tag str -> String) -> ([Tag str] -> ShowS) -> Show (Tag str)
forall str. Show str => Int -> Tag str -> ShowS
forall str. Show str => [Tag str] -> ShowS
forall str. Show str => Tag str -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Tag str] -> ShowS
$cshowList :: forall str. Show str => [Tag str] -> ShowS
show :: Tag str -> String
$cshow :: forall str. Show str => Tag str -> String
showsPrec :: Int -> Tag str -> ShowS
$cshowsPrec :: forall str. Show str => Int -> Tag str -> ShowS
Show, Tag str -> Tag str -> Bool
(Tag str -> Tag str -> Bool)
-> (Tag str -> Tag str -> Bool) -> Eq (Tag str)
forall str. Eq str => Tag str -> Tag str -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Tag str -> Tag str -> Bool
$c/= :: forall str. Eq str => Tag str -> Tag str -> Bool
== :: Tag str -> Tag str -> Bool
$c== :: forall str. Eq str => Tag str -> Tag str -> Bool
Eq, Eq (Tag str)
Eq (Tag str) =>
(Tag str -> Tag str -> Ordering)
-> (Tag str -> Tag str -> Bool)
-> (Tag str -> Tag str -> Bool)
-> (Tag str -> Tag str -> Bool)
-> (Tag str -> Tag str -> Bool)
-> (Tag str -> Tag str -> Tag str)
-> (Tag str -> Tag str -> Tag str)
-> Ord (Tag str)
Tag str -> Tag str -> Bool
Tag str -> Tag str -> Ordering
Tag str -> Tag str -> Tag str
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall str. Ord str => Eq (Tag str)
forall str. Ord str => Tag str -> Tag str -> Bool
forall str. Ord str => Tag str -> Tag str -> Ordering
forall str. Ord str => Tag str -> Tag str -> Tag str
min :: Tag str -> Tag str -> Tag str
$cmin :: forall str. Ord str => Tag str -> Tag str -> Tag str
max :: Tag str -> Tag str -> Tag str
$cmax :: forall str. Ord str => Tag str -> Tag str -> Tag str
>= :: Tag str -> Tag str -> Bool
$c>= :: forall str. Ord str => Tag str -> Tag str -> Bool
> :: Tag str -> Tag str -> Bool
$c> :: forall str. Ord str => Tag str -> Tag str -> Bool
<= :: Tag str -> Tag str -> Bool
$c<= :: forall str. Ord str => Tag str -> Tag str -> Bool
< :: Tag str -> Tag str -> Bool
$c< :: forall str. Ord str => Tag str -> Tag str -> Bool
compare :: Tag str -> Tag str -> Ordering
$ccompare :: forall str. Ord str => Tag str -> Tag str -> Ordering
$cp1Ord :: forall str. Ord str => Eq (Tag str)
Ord, Typeable (Tag str)
Constr
DataType
Typeable (Tag str) =>
(forall (c :: * -> *).
 (forall d b. Data d => c (d -> b) -> d -> c b)
 -> (forall g. g -> c g) -> Tag str -> c (Tag str))
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c (Tag str))
-> (Tag str -> Constr)
-> (Tag str -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c (Tag str)))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (Tag str)))
-> ((forall b. Data b => b -> b) -> Tag str -> Tag str)
-> (forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> Tag str -> r)
-> (forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> Tag str -> r)
-> (forall u. (forall d. Data d => d -> u) -> Tag str -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> Tag str -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> Tag str -> m (Tag str))
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Tag str -> m (Tag str))
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Tag str -> m (Tag str))
-> Data (Tag str)
Tag str -> Constr
Tag str -> DataType
(forall d. Data d => c (t d)) -> Maybe (c (Tag str))
(forall b. Data b => b -> b) -> Tag str -> Tag str
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Tag str -> c (Tag str)
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (Tag str)
forall str. Data str => Typeable (Tag str)
forall str. Data str => Tag str -> Constr
forall str. Data str => Tag str -> DataType
forall str.
Data str =>
(forall b. Data b => b -> b) -> Tag str -> Tag str
forall str u.
Data str =>
Int -> (forall d. Data d => d -> u) -> Tag str -> u
forall str u.
Data str =>
(forall d. Data d => d -> u) -> Tag str -> [u]
forall str r r'.
Data str =>
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> Tag str -> r
forall str r r'.
Data str =>
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> Tag str -> r
forall str (m :: * -> *).
(Data str, Monad m) =>
(forall d. Data d => d -> m d) -> Tag str -> m (Tag str)
forall str (m :: * -> *).
(Data str, MonadPlus m) =>
(forall d. Data d => d -> m d) -> Tag str -> m (Tag str)
forall str (c :: * -> *).
Data str =>
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (Tag str)
forall str (c :: * -> *).
Data str =>
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Tag str -> c (Tag str)
forall str (t :: * -> *) (c :: * -> *).
(Data str, Typeable t) =>
(forall d. Data d => c (t d)) -> Maybe (c (Tag str))
forall str (t :: * -> * -> *) (c :: * -> *).
(Data str, Typeable t) =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (Tag str))
forall a.
Typeable a =>
(forall (c :: * -> *).
 (forall d b. Data d => c (d -> b) -> d -> c b)
 -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> Tag str -> u
forall u. (forall d. Data d => d -> u) -> Tag str -> [u]
forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> Tag str -> r
forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> Tag str -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Tag str -> m (Tag str)
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Tag str -> m (Tag str)
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (Tag str)
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Tag str -> c (Tag str)
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c (Tag str))
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (Tag str))
$cTagPosition :: Constr
$cTagWarning :: Constr
$cTagComment :: Constr
$cTagText :: Constr
$cTagClose :: Constr
$cTagOpen :: Constr
$tTag :: DataType
gmapMo :: (forall d. Data d => d -> m d) -> Tag str -> m (Tag str)
$cgmapMo :: forall str (m :: * -> *).
(Data str, MonadPlus m) =>
(forall d. Data d => d -> m d) -> Tag str -> m (Tag str)
gmapMp :: (forall d. Data d => d -> m d) -> Tag str -> m (Tag str)
$cgmapMp :: forall str (m :: * -> *).
(Data str, MonadPlus m) =>
(forall d. Data d => d -> m d) -> Tag str -> m (Tag str)
gmapM :: (forall d. Data d => d -> m d) -> Tag str -> m (Tag str)
$cgmapM :: forall str (m :: * -> *).
(Data str, Monad m) =>
(forall d. Data d => d -> m d) -> Tag str -> m (Tag str)
gmapQi :: Int -> (forall d. Data d => d -> u) -> Tag str -> u
$cgmapQi :: forall str u.
Data str =>
Int -> (forall d. Data d => d -> u) -> Tag str -> u
gmapQ :: (forall d. Data d => d -> u) -> Tag str -> [u]
$cgmapQ :: forall str u.
Data str =>
(forall d. Data d => d -> u) -> Tag str -> [u]
gmapQr :: (r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> Tag str -> r
$cgmapQr :: forall str r r'.
Data str =>
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> Tag str -> r
gmapQl :: (r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> Tag str -> r
$cgmapQl :: forall str r r'.
Data str =>
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> Tag str -> r
gmapT :: (forall b. Data b => b -> b) -> Tag str -> Tag str
$cgmapT :: forall str.
Data str =>
(forall b. Data b => b -> b) -> Tag str -> Tag str
dataCast2 :: (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (Tag str))
$cdataCast2 :: forall str (t :: * -> * -> *) (c :: * -> *).
(Data str, Typeable t) =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (Tag str))
dataCast1 :: (forall d. Data d => c (t d)) -> Maybe (c (Tag str))
$cdataCast1 :: forall str (t :: * -> *) (c :: * -> *).
(Data str, Typeable t) =>
(forall d. Data d => c (t d)) -> Maybe (c (Tag str))
dataTypeOf :: Tag str -> DataType
$cdataTypeOf :: forall str. Data str => Tag str -> DataType
toConstr :: Tag str -> Constr
$ctoConstr :: forall str. Data str => Tag str -> Constr
gunfold :: (forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (Tag str)
$cgunfold :: forall str (c :: * -> *).
Data str =>
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (Tag str)
gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Tag str -> c (Tag str)
$cgfoldl :: forall str (c :: * -> *).
Data str =>
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Tag str -> c (Tag str)
$cp1Data :: forall str. Data str => Typeable (Tag str)
Data, Typeable)

instance Functor Tag where
    fmap :: (a -> b) -> Tag a -> Tag b
fmap f :: a -> b
f (TagOpen x :: a
x y :: [Attribute a]
y) = b -> [Attribute b] -> Tag b
forall str. str -> [Attribute str] -> Tag str
TagOpen (a -> b
f a
x) [(a -> b
f a
a, a -> b
f a
b) | (a :: a
a,b :: a
b) <- [Attribute a]
y]
    fmap f :: a -> b
f (TagClose x :: a
x) = b -> Tag b
forall str. str -> Tag str
TagClose (a -> b
f a
x)
    fmap f :: a -> b
f (TagText x :: a
x) = b -> Tag b
forall str. str -> Tag str
TagText (a -> b
f a
x)
    fmap f :: a -> b
f (TagComment x :: a
x) = b -> Tag b
forall str. str -> Tag str
TagComment (a -> b
f a
x)
    fmap f :: a -> b
f (TagWarning x :: a
x) = b -> Tag b
forall str. str -> Tag str
TagWarning (a -> b
f a
x)
    fmap f :: a -> b
f (TagPosition x :: Int
x y :: Int
y) = Int -> Int -> Tag b
forall str. Int -> Int -> Tag str
TagPosition Int
x Int
y


-- | Test if a 'Tag' is a 'TagOpen'
isTagOpen :: Tag str -> Bool
isTagOpen :: Tag str -> Bool
isTagOpen (TagOpen {})  = Bool
True; isTagOpen  _ = Bool
False

-- | Test if a 'Tag' is a 'TagClose'
isTagClose :: Tag str -> Bool
isTagClose :: Tag str -> Bool
isTagClose (TagClose {}) = Bool
True; isTagClose _ = Bool
False

-- | Test if a 'Tag' is a 'TagText'
isTagText :: Tag str -> Bool
isTagText :: Tag str -> Bool
isTagText (TagText {})  = Bool
True; isTagText  _ = Bool
False

-- | Extract the string from within 'TagText', otherwise 'Nothing'
maybeTagText :: Tag str -> Maybe str
maybeTagText :: Tag str -> Maybe str
maybeTagText (TagText x :: str
x) = str -> Maybe str
forall a. a -> Maybe a
Just str
x
maybeTagText _ = Maybe str
forall a. Maybe a
Nothing

-- | Extract the string from within 'TagText', crashes if not a 'TagText'
fromTagText :: Show str => Tag str -> str
fromTagText :: Tag str -> str
fromTagText (TagText x :: str
x) = str
x
fromTagText x :: Tag str
x = String -> str
forall a. HasCallStack => String -> a
error (String -> str) -> String -> str
forall a b. (a -> b) -> a -> b
$ "(" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Tag str -> String
forall a. Show a => a -> String
show Tag str
x String -> ShowS
forall a. [a] -> [a] -> [a]
++ ") is not a TagText"

-- | Extract all text content from tags (similar to Verbatim found in HaXml)
innerText :: StringLike str => [Tag str] -> str
innerText :: [Tag str] -> str
innerText = [str] -> str
forall a. StringLike a => [a] -> a
strConcat ([str] -> str) -> ([Tag str] -> [str]) -> [Tag str] -> str
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Tag str -> Maybe str) -> [Tag str] -> [str]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe Tag str -> Maybe str
forall str. Tag str -> Maybe str
maybeTagText

-- | Test if a 'Tag' is a 'TagWarning'
isTagWarning :: Tag str -> Bool
isTagWarning :: Tag str -> Bool
isTagWarning (TagWarning {})  = Bool
True; isTagWarning _ = Bool
False

-- | Extract the string from within 'TagWarning', otherwise 'Nothing'
maybeTagWarning :: Tag str -> Maybe str
maybeTagWarning :: Tag str -> Maybe str
maybeTagWarning (TagWarning x :: str
x) = str -> Maybe str
forall a. a -> Maybe a
Just str
x
maybeTagWarning _ = Maybe str
forall a. Maybe a
Nothing

-- | Test if a 'Tag' is a 'TagPosition'
isTagPosition :: Tag str -> Bool
isTagPosition :: Tag str -> Bool
isTagPosition TagPosition{} = Bool
True; isTagPosition _ = Bool
False

-- | Extract an attribute, crashes if not a 'TagOpen'.
--   Returns @\"\"@ if no attribute present.
--
-- Warning: does not distinquish between missing attribute
-- and present attribute with value @\"\"@.
fromAttrib :: (Show str, Eq str, StringLike str) => str -> Tag str -> str
fromAttrib :: str -> Tag str -> str
fromAttrib att :: str
att tag :: Tag str
tag = str -> Maybe str -> str
forall a. a -> Maybe a -> a
fromMaybe str
forall a. StringLike a => a
empty (Maybe str -> str) -> Maybe str -> str
forall a b. (a -> b) -> a -> b
$ str -> Tag str -> Maybe str
forall str. (Show str, Eq str) => str -> Tag str -> Maybe str
maybeAttrib str
att Tag str
tag

-- | Extract an attribute, crashes if not a 'TagOpen'.
--   Returns @Nothing@ if no attribute present.
maybeAttrib :: (Show str, Eq str) => str -> Tag str -> Maybe str
maybeAttrib :: str -> Tag str -> Maybe str
maybeAttrib att :: str
att (TagOpen _ atts :: [Attribute str]
atts) = str -> [Attribute str] -> Maybe str
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup str
att [Attribute str]
atts
maybeAttrib _ x :: Tag str
x = String -> Maybe str
forall a. HasCallStack => String -> a
error ("(" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Tag str -> String
forall a. Show a => a -> String
show Tag str
x String -> ShowS
forall a. [a] -> [a] -> [a]
++ ") is not a TagOpen")

-- | Returns True if the 'Tag' is 'TagOpen' and matches the given name
isTagOpenName :: Eq str => str -> Tag str -> Bool
isTagOpenName :: str -> Tag str -> Bool
isTagOpenName name :: str
name (TagOpen n :: str
n _) = str
n str -> str -> Bool
forall a. Eq a => a -> a -> Bool
== str
name
isTagOpenName _ _ = Bool
False

-- | Returns True if the 'Tag' is 'TagClose' and matches the given name
isTagCloseName :: Eq str => str -> Tag str -> Bool
isTagCloseName :: str -> Tag str -> Bool
isTagCloseName name :: str
name (TagClose n :: str
n) = str
n str -> str -> Bool
forall a. Eq a => a -> a -> Bool
== str
name
isTagCloseName _ _ = Bool
False

-- | Test if a 'Tag' is a 'TagComment'
isTagComment :: Tag str -> Bool
isTagComment :: Tag str -> Bool
isTagComment TagComment {} = Bool
True; isTagComment _ = Bool
False