{-# 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 (Row -> Position -> ShowS
[Position] -> ShowS
Position -> String
(Row -> Position -> ShowS)
-> (Position -> String) -> ([Position] -> ShowS) -> Show Position
forall a.
(Row -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Row -> Position -> ShowS
showsPrec :: Row -> Position -> ShowS
$cshow :: Position -> String
show :: Position -> String
$cshowList :: [Position] -> ShowS
showList :: [Position] -> ShowS
Show,Position -> Position -> Bool
(Position -> Position -> Bool)
-> (Position -> Position -> Bool) -> Eq Position
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Position -> Position -> Bool
== :: Position -> Position -> Bool
$c/= :: Position -> Position -> Bool
/= :: 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
$ccompare :: Position -> Position -> Ordering
compare :: Position -> Position -> Ordering
$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
>= :: Position -> Position -> Bool
$cmax :: Position -> Position -> Position
max :: Position -> Position -> Position
$cmin :: Position -> Position -> Position
min :: Position -> Position -> Position
Ord)

nullPosition :: Position
nullPosition :: Position
nullPosition = Row -> Row -> Position
Position Row
1 Row
1

positionString :: Position -> String -> Position
positionString :: Position -> String -> Position
positionString = (Position -> Char -> Position) -> Position -> String -> Position
forall b a. (b -> a -> b) -> b -> [a] -> b
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 Row
r Row
c) Char
x = case Char
x of
    Char
'\n' -> Row -> Row -> Position
Position (Row
rRow -> Row -> Row
forall a. Num a => a -> a -> a
+Row
1) Row
1
    Char
'\t' -> Row -> Row -> Position
Position Row
r (Row
c Row -> Row -> Row
forall a. Num a => a -> a -> a
+ Row
8 Row -> Row -> Row
forall a. Num a => a -> a -> a
- Row -> Row -> Row
forall a. Integral a => a -> a -> a
mod (Row
cRow -> Row -> Row
forall a. Num a => a -> a -> a
-Row
1) Row
8)
    Char
_    -> Row -> Row -> Position
Position Row
r (Row
cRow -> Row -> Row
forall a. Num a => a -> a -> a
+Row
1)

tagPosition :: Position -> Tag str
tagPosition :: forall str. Position -> Tag str
tagPosition (Position Row
r Row
c) = Row -> Row -> Tag str
forall str. Row -> Row -> Tag str
TagPosition Row
r Row
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 (Row -> Tag str -> ShowS
[Tag str] -> ShowS
Tag str -> String
(Row -> Tag str -> ShowS)
-> (Tag str -> String) -> ([Tag str] -> ShowS) -> Show (Tag str)
forall str. Show str => Row -> Tag str -> ShowS
forall str. Show str => [Tag str] -> ShowS
forall str. Show str => Tag str -> String
forall a.
(Row -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall str. Show str => Row -> Tag str -> ShowS
showsPrec :: Row -> Tag str -> ShowS
$cshow :: forall str. Show str => Tag str -> String
show :: Tag str -> String
$cshowList :: forall str. Show str => [Tag str] -> ShowS
showList :: [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
$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
/= :: 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
$ccompare :: forall str. Ord str => Tag str -> Tag str -> Ordering
compare :: Tag str -> Tag str -> Ordering
$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
>= :: Tag str -> Tag str -> Bool
$cmax :: forall str. Ord str => Tag str -> Tag str -> Tag str
max :: Tag str -> Tag str -> Tag str
$cmin :: forall str. Ord str => Tag str -> Tag str -> Tag str
min :: Tag str -> Tag str -> Tag str
Ord, Typeable (Tag str)
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. Row -> (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 b. Data b => b -> b) -> Tag str -> 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 =>
Row -> (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. Row -> (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. Row -> (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))
$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)
gfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Tag str -> 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)
gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (Tag str)
$ctoConstr :: forall str. Data str => Tag str -> Constr
toConstr :: Tag str -> Constr
$cdataTypeOf :: forall str. Data str => Tag str -> DataType
dataTypeOf :: Tag str -> DataType
$cdataCast1 :: forall str (t :: * -> *) (c :: * -> *).
(Data str, Typeable t) =>
(forall d. Data d => c (t d)) -> Maybe (c (Tag str))
dataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> 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))
dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (Tag str))
$cgmapT :: forall str.
Data str =>
(forall b. Data b => b -> b) -> Tag str -> Tag str
gmapT :: (forall b. Data b => b -> b) -> Tag str -> Tag str
$cgmapQl :: forall str r r'.
Data str =>
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> Tag str -> r
gmapQl :: forall r r'.
(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
gmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> Tag str -> r
$cgmapQ :: forall str u.
Data str =>
(forall d. Data d => d -> u) -> Tag str -> [u]
gmapQ :: forall u. (forall d. Data d => d -> u) -> Tag str -> [u]
$cgmapQi :: forall str u.
Data str =>
Row -> (forall d. Data d => d -> u) -> Tag str -> u
gmapQi :: forall u. Row -> (forall d. Data d => d -> u) -> Tag str -> u
$cgmapM :: forall str (m :: * -> *).
(Data str, Monad m) =>
(forall d. Data d => d -> m d) -> Tag str -> m (Tag str)
gmapM :: forall (m :: * -> *).
Monad m =>
(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)
gmapMp :: forall (m :: * -> *).
MonadPlus m =>
(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)
gmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Tag str -> m (Tag str)
Data, Typeable)

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


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

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

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

-- | Extract the string from within 'TagText', otherwise 'Nothing'
maybeTagText :: Tag str -> Maybe str
maybeTagText :: forall str. Tag str -> Maybe str
maybeTagText (TagText str
x) = str -> Maybe str
forall a. a -> Maybe a
Just str
x
maybeTagText Tag str
_ = 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 :: forall str. Show str => Tag str -> str
fromTagText (TagText str
x) = str
x
fromTagText Tag str
x = String -> str
forall a. HasCallStack => String -> a
error (String -> str) -> String -> str
forall a b. (a -> b) -> a -> b
$ String
"(" 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]
++ String
") is not a TagText"

-- | Extract all text content from tags (similar to Verbatim found in HaXml)
innerText :: StringLike str => [Tag str] -> str
innerText :: forall str. StringLike str => [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 :: forall str. Tag str -> Bool
isTagWarning (TagWarning {})  = Bool
True; isTagWarning Tag str
_ = Bool
False

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

-- | Test if a 'Tag' is a 'TagPosition'
isTagPosition :: Tag str -> Bool
isTagPosition :: forall str. Tag str -> Bool
isTagPosition TagPosition{} = Bool
True; isTagPosition Tag str
_ = 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 :: forall str.
(Show str, Eq str, StringLike str) =>
str -> Tag str -> str
fromAttrib str
att 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 :: forall str. (Show str, Eq str) => str -> Tag str -> Maybe str
maybeAttrib str
att (TagOpen str
_ [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 str
_ Tag str
x = String -> Maybe str
forall a. HasCallStack => String -> a
error (String
"(" 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]
++ String
") is not a TagOpen")

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

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

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