{- |
We do not define a tag data type here,
since this is too much bound to the particular use
(e.g. list or tree structure).
However we define a tag name and several
-}
module Text.HTML.Basic.Tag (
   Tag.Name(..),
   Tag.doctype, Tag.doctypeName, Tag.doctypeString,
   Tag.cdata,   Tag.cdataName,   Tag.cdataString,
   isEmpty, isSloppy, isInnerOf, closes,
   maybeMetaHTTPHeader, maybeMetaEncoding, maybeMetaCharset,
   encodingFromContentType,
   ) where


import Text.XML.Basic.Tag (Name, )

import qualified Text.XML.Basic.Tag as Tag
import qualified Text.XML.Basic.Attribute as Attr
import qualified Text.XML.Basic.Name as Name

import qualified Data.Map as Map
import qualified Data.Set as Set

import qualified Data.List.Reverse.StrictElement as ListRev
import qualified Data.Char as Char
import           Data.Tuple.HT (mapFst, )
import           Control.Monad (guard, liftM2, )


{- |
Check whether a HTML tag is empty.
-}
isEmpty :: (Name.Tag name) =>
   Name name -> Bool
isEmpty :: forall name. Tag name => Name name -> Bool
isEmpty = (Name name -> Set (Name name) -> Bool)
-> Set (Name name) -> Name name -> Bool
forall a b c. (a -> b -> c) -> b -> a -> c
flip Name name -> Set (Name name) -> Bool
forall a. Ord a => a -> Set a -> Bool
Set.member Set (Name name)
forall name. Tag name => Set (Name name)
emptySet

{- |
Set of empty HTML tags.
-}
emptySet :: (Name.Tag name) =>
   Set.Set (Name name)
emptySet :: forall name. Tag name => Set (Name name)
emptySet =
   [String] -> Set (Name name)
forall name. Tag name => [String] -> Set (Name name)
nameSet ([String] -> Set (Name name)) -> [String] -> Set (Name name)
forall a b. (a -> b) -> a -> b
$
   String
"area" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
   String
"base" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
   String
"br" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
   String
"col" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
   String
"frame" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
   String
"hr" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
   String
"img" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
   String
"input" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
   String
"link" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
   String
"meta" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
   String
"param" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
   []


{- |
Some tags, namely those for text styles like FONT, B, I,
are used quite sloppily.
That is, they are not terminated or not terminated in the right order.
We close them implicitly, if another tag closes
and ignore non-matching closing tags.
-}
isSloppy ::  (Name.Tag name) =>
   Name name -> Bool
isSloppy :: forall name. Tag name => Name name -> Bool
isSloppy = (Name name -> Set (Name name) -> Bool)
-> Set (Name name) -> Name name -> Bool
forall a b c. (a -> b -> c) -> b -> a -> c
flip Name name -> Set (Name name) -> Bool
forall a. Ord a => a -> Set a -> Bool
Set.member Set (Name name)
forall name. Tag name => Set (Name name)
sloppySet

{-
Example page:
http://extremetracking.com/open;unique?login=crsucks
-}

sloppySet :: (Name.Tag name) =>
   Set.Set (Name name)
sloppySet :: forall name. Tag name => Set (Name name)
sloppySet =
   [String] -> Set (Name name)
forall name. Tag name => [String] -> Set (Name name)
nameSet ([String] -> Set (Name name)) -> [String] -> Set (Name name)
forall a b. (a -> b) -> a -> b
$
   String
"font" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
   String
"b" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
   String
"i" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
   String
"tt" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
   String
"u" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
   String
"strike" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
   String
"s" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
   String
"big" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
   String
"small" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
   []


isInnerOf :: (Name.Tag name) =>
   Name name -> Name name -> Bool
isInnerOf :: forall name. Tag name => Name name -> Name name -> Bool
isInnerOf Name name
outer Name name
inner =
   Bool
-> (Set (Name name) -> Bool) -> Maybe (Set (Name name)) -> Bool
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
False (Name name -> Set (Name name) -> Bool
forall a. Ord a => a -> Set a -> Bool
Set.member Name name
inner) (Maybe (Set (Name name)) -> Bool)
-> Maybe (Set (Name name)) -> Bool
forall a b. (a -> b) -> a -> b
$
   Name name
-> Map (Name name) (Set (Name name)) -> Maybe (Set (Name name))
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Name name
outer Map (Name name) (Set (Name name))
forall name. Tag name => Map (Name name) (Set (Name name))
innerMap


innerMap :: (Name.Tag name) =>
   Map.Map (Name name) (Set.Set (Name name))
innerMap :: forall name. Tag name => Map (Name name) (Set (Name name))
innerMap =
   [(String, Set (Name name))] -> Map (Name name) (Set (Name name))
forall name a. Tag name => [(String, a)] -> Map (Name name) a
nameMap ([(String, Set (Name name))] -> Map (Name name) (Set (Name name)))
-> [(String, Set (Name name))] -> Map (Name name) (Set (Name name))
forall a b. (a -> b) -> a -> b
$
   (String
"body",    Set (Name name)
forall name. Tag name => Set (Name name)
pSet) (String, Set (Name name))
-> [(String, Set (Name name))] -> [(String, Set (Name name))]
forall a. a -> [a] -> [a]
:
   (String
"caption", Set (Name name)
forall name. Tag name => Set (Name name)
pSet) (String, Set (Name name))
-> [(String, Set (Name name))] -> [(String, Set (Name name))]
forall a. a -> [a] -> [a]
:
   (String
"dd",      Set (Name name)
forall name. Tag name => Set (Name name)
pSet) (String, Set (Name name))
-> [(String, Set (Name name))] -> [(String, Set (Name name))]
forall a. a -> [a] -> [a]
:
   (String
"div",     Set (Name name)
forall name. Tag name => Set (Name name)
pSet) (String, Set (Name name))
-> [(String, Set (Name name))] -> [(String, Set (Name name))]
forall a. a -> [a] -> [a]
:
   (String
"dl",      Set (Name name)
forall name. Tag name => Set (Name name)
dtdSet) (String, Set (Name name))
-> [(String, Set (Name name))] -> [(String, Set (Name name))]
forall a. a -> [a] -> [a]
:
   (String
"dt",      Set (Name name)
forall name. Tag name => Set (Name name)
pSet) (String, Set (Name name))
-> [(String, Set (Name name))] -> [(String, Set (Name name))]
forall a. a -> [a] -> [a]
:
   (String
"li",      Set (Name name)
forall name. Tag name => Set (Name name)
pSet) (String, Set (Name name))
-> [(String, Set (Name name))] -> [(String, Set (Name name))]
forall a. a -> [a] -> [a]
:
   (String
"map",     Set (Name name)
forall name. Tag name => Set (Name name)
pSet) (String, Set (Name name))
-> [(String, Set (Name name))] -> [(String, Set (Name name))]
forall a. a -> [a] -> [a]
:
   (String
"object",  Set (Name name)
forall name. Tag name => Set (Name name)
pSet) (String, Set (Name name))
-> [(String, Set (Name name))] -> [(String, Set (Name name))]
forall a. a -> [a] -> [a]
:
   (String
"ol",      Set (Name name)
forall name. Tag name => Set (Name name)
liSet) (String, Set (Name name))
-> [(String, Set (Name name))] -> [(String, Set (Name name))]
forall a. a -> [a] -> [a]
:
   (String
"table",   [String] -> Set (Name name)
forall name. Tag name => [String] -> Set (Name name)
nameSet [String
"th",String
"tr",String
"td",String
"thead",String
"tfoot",String
"tbody"]) (String, Set (Name name))
-> [(String, Set (Name name))] -> [(String, Set (Name name))]
forall a. a -> [a] -> [a]
:
   (String
"tbody",   Set (Name name)
forall name. Tag name => Set (Name name)
thdrSet) (String, Set (Name name))
-> [(String, Set (Name name))] -> [(String, Set (Name name))]
forall a. a -> [a] -> [a]
:
   (String
"td",      Set (Name name)
forall name. Tag name => Set (Name name)
pSet) (String, Set (Name name))
-> [(String, Set (Name name))] -> [(String, Set (Name name))]
forall a. a -> [a] -> [a]
:
   (String
"tfoot",   Set (Name name)
forall name. Tag name => Set (Name name)
thdrSet) (String, Set (Name name))
-> [(String, Set (Name name))] -> [(String, Set (Name name))]
forall a. a -> [a] -> [a]
:
   (String
"th",      Set (Name name)
forall name. Tag name => Set (Name name)
pSet) (String, Set (Name name))
-> [(String, Set (Name name))] -> [(String, Set (Name name))]
forall a. a -> [a] -> [a]
:
   (String
"thead",   Set (Name name)
forall name. Tag name => Set (Name name)
thdrSet) (String, Set (Name name))
-> [(String, Set (Name name))] -> [(String, Set (Name name))]
forall a. a -> [a] -> [a]
:
   (String
"tr",      Set (Name name)
forall name. Tag name => Set (Name name)
thdSet) (String, Set (Name name))
-> [(String, Set (Name name))] -> [(String, Set (Name name))]
forall a. a -> [a] -> [a]
:
   (String
"ul",      Set (Name name)
forall name. Tag name => Set (Name name)
liSet) (String, Set (Name name))
-> [(String, Set (Name name))] -> [(String, Set (Name name))]
forall a. a -> [a] -> [a]
:
   []


closes :: (Name.Tag name) =>
   Name name -> Name name -> Bool
closes :: forall name. Tag name => Name name -> Name name -> Bool
closes Name name
closing Name name
opening =
   (Bool -> Bool
not (String -> Name name -> Bool
forall name. C name => String -> name -> Bool
Name.match String
"option" Name name
closing) Bool -> Bool -> Bool
&& String -> Name name -> Bool
forall name. C name => String -> name -> Bool
Name.match String
"select" Name name
opening) Bool -> Bool -> Bool
||
   ([String] -> Name name -> Bool
forall name. C name => [String] -> name -> Bool
Name.matchAny [String
"option", String
"script", String
"style",String
"textarea",String
"title"] Name name
opening) Bool -> Bool -> Bool
||
   (Bool
-> (Set (Name name) -> Bool) -> Maybe (Set (Name name)) -> Bool
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
False (Name name -> Set (Name name) -> Bool
forall a. Ord a => a -> Set a -> Bool
Set.member Name name
opening) (Maybe (Set (Name name)) -> Bool)
-> Maybe (Set (Name name)) -> Bool
forall a b. (a -> b) -> a -> b
$
    Name name
-> Map (Name name) (Set (Name name)) -> Maybe (Set (Name name))
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Name name
closing Map (Name name) (Set (Name name))
forall name. Tag name => Map (Name name) (Set (Name name))
closesMap)


closesMap :: (Name.Tag name) =>
   Map.Map (Name name) (Set.Set (Name name))
closesMap :: forall name. Tag name => Map (Name name) (Set (Name name))
closesMap =
   [(String, Set (Name name))] -> Map (Name name) (Set (Name name))
forall name a. Tag name => [(String, a)] -> Map (Name name) a
nameMap ([(String, Set (Name name))] -> Map (Name name) (Set (Name name)))
-> [(String, Set (Name name))] -> Map (Name name) (Set (Name name))
forall a b. (a -> b) -> a -> b
$
   (String
"a"        , String -> Set (Name name)
forall name. Tag name => String -> Set (Name name)
nameSingle String
"a") (String, Set (Name name))
-> [(String, Set (Name name))] -> [(String, Set (Name name))]
forall a. a -> [a] -> [a]
:
   (String
"li"       , Set (Name name)
forall name. Tag name => Set (Name name)
liSet) (String, Set (Name name))
-> [(String, Set (Name name))] -> [(String, Set (Name name))]
forall a. a -> [a] -> [a]
:
   (String
"th"       , Set (Name name)
forall name. Tag name => Set (Name name)
thdSet) (String, Set (Name name))
-> [(String, Set (Name name))] -> [(String, Set (Name name))]
forall a. a -> [a] -> [a]
:
   (String
"td"       , Set (Name name)
forall name. Tag name => Set (Name name)
thdSet) (String, Set (Name name))
-> [(String, Set (Name name))] -> [(String, Set (Name name))]
forall a. a -> [a] -> [a]
:
   (String
"tr"       , Set (Name name)
forall name. Tag name => Set (Name name)
thdrSet) (String, Set (Name name))
-> [(String, Set (Name name))] -> [(String, Set (Name name))]
forall a. a -> [a] -> [a]
:
   (String
"dt"       , Set (Name name)
forall name. Tag name => Set (Name name)
dtdSet) (String, Set (Name name))
-> [(String, Set (Name name))] -> [(String, Set (Name name))]
forall a. a -> [a] -> [a]
:
   (String
"dd"       , Set (Name name)
forall name. Tag name => Set (Name name)
dtdSet) (String, Set (Name name))
-> [(String, Set (Name name))] -> [(String, Set (Name name))]
forall a. a -> [a] -> [a]
:
   (String
"hr"       , Set (Name name)
forall name. Tag name => Set (Name name)
pSet) (String, Set (Name name))
-> [(String, Set (Name name))] -> [(String, Set (Name name))]
forall a. a -> [a] -> [a]
:
   (String
"colgroup" , String -> Set (Name name)
forall name. Tag name => String -> Set (Name name)
nameSingle String
"colgroup") (String, Set (Name name))
-> [(String, Set (Name name))] -> [(String, Set (Name name))]
forall a. a -> [a] -> [a]
:
   (String
"form"     , String -> Set (Name name)
forall name. Tag name => String -> Set (Name name)
nameSingle String
"form") (String, Set (Name name))
-> [(String, Set (Name name))] -> [(String, Set (Name name))]
forall a. a -> [a] -> [a]
:
   (String
"label"    , String -> Set (Name name)
forall name. Tag name => String -> Set (Name name)
nameSingle String
"label") (String, Set (Name name))
-> [(String, Set (Name name))] -> [(String, Set (Name name))]
forall a. a -> [a] -> [a]
:
   (String
"map"      , String -> Set (Name name)
forall name. Tag name => String -> Set (Name name)
nameSingle String
"map") (String, Set (Name name))
-> [(String, Set (Name name))] -> [(String, Set (Name name))]
forall a. a -> [a] -> [a]
:
   (String
"object"   , String -> Set (Name name)
forall name. Tag name => String -> Set (Name name)
nameSingle String
"object") (String, Set (Name name))
-> [(String, Set (Name name))] -> [(String, Set (Name name))]
forall a. a -> [a] -> [a]
:
   (String
"thead"    , [String] -> Set (Name name)
forall name. Tag name => [String] -> Set (Name name)
nameSet [String
"colgroup"]) (String, Set (Name name))
-> [(String, Set (Name name))] -> [(String, Set (Name name))]
forall a. a -> [a] -> [a]
:
   (String
"tfoot"    , [String] -> Set (Name name)
forall name. Tag name => [String] -> Set (Name name)
nameSet [String
"thead", String
"colgroup"]) (String, Set (Name name))
-> [(String, Set (Name name))] -> [(String, Set (Name name))]
forall a. a -> [a] -> [a]
:
   (String
"tbody"    , [String] -> Set (Name name)
forall name. Tag name => [String] -> Set (Name name)
nameSet [String
"tbody", String
"tfoot", String
"thead", String
"colgroup"]) (String, Set (Name name))
-> [(String, Set (Name name))] -> [(String, Set (Name name))]
forall a. a -> [a] -> [a]
:
   (String
"h1"       , Set (Name name)
forall name. Tag name => Set (Name name)
headingSet) (String, Set (Name name))
-> [(String, Set (Name name))] -> [(String, Set (Name name))]
forall a. a -> [a] -> [a]
:
   (String
"h2"       , Set (Name name)
forall name. Tag name => Set (Name name)
headingSet) (String, Set (Name name))
-> [(String, Set (Name name))] -> [(String, Set (Name name))]
forall a. a -> [a] -> [a]
:
   (String
"h3"       , Set (Name name)
forall name. Tag name => Set (Name name)
headingSet) (String, Set (Name name))
-> [(String, Set (Name name))] -> [(String, Set (Name name))]
forall a. a -> [a] -> [a]
:
   (String
"h4"       , Set (Name name)
forall name. Tag name => Set (Name name)
headingSet) (String, Set (Name name))
-> [(String, Set (Name name))] -> [(String, Set (Name name))]
forall a. a -> [a] -> [a]
:
   (String
"h5"       , Set (Name name)
forall name. Tag name => Set (Name name)
headingSet) (String, Set (Name name))
-> [(String, Set (Name name))] -> [(String, Set (Name name))]
forall a. a -> [a] -> [a]
:
   (String
"h6"       , Set (Name name)
forall name. Tag name => Set (Name name)
headingSet) (String, Set (Name name))
-> [(String, Set (Name name))] -> [(String, Set (Name name))]
forall a. a -> [a] -> [a]
:
   (String
"dl"       , Set (Name name)
forall name. Tag name => Set (Name name)
headingSet) (String, Set (Name name))
-> [(String, Set (Name name))] -> [(String, Set (Name name))]
forall a. a -> [a] -> [a]
:
   (String
"ol"       , Set (Name name)
forall name. Tag name => Set (Name name)
headingSet) (String, Set (Name name))
-> [(String, Set (Name name))] -> [(String, Set (Name name))]
forall a. a -> [a] -> [a]
:
   (String
"ul"       , Set (Name name)
forall name. Tag name => Set (Name name)
headingSet) (String, Set (Name name))
-> [(String, Set (Name name))] -> [(String, Set (Name name))]
forall a. a -> [a] -> [a]
:
   (String
"table"    , Set (Name name)
forall name. Tag name => Set (Name name)
headingSet) (String, Set (Name name))
-> [(String, Set (Name name))] -> [(String, Set (Name name))]
forall a. a -> [a] -> [a]
:
   (String
"div"      , Set (Name name)
forall name. Tag name => Set (Name name)
headingSet) (String, Set (Name name))
-> [(String, Set (Name name))] -> [(String, Set (Name name))]
forall a. a -> [a] -> [a]
:
   (String
"p"        , Set (Name name)
forall name. Tag name => Set (Name name)
headingSet) (String, Set (Name name))
-> [(String, Set (Name name))] -> [(String, Set (Name name))]
forall a. a -> [a] -> [a]
:
   []


nameMap :: (Name.Tag name) => [(String,a)] -> Map.Map (Name name) a
nameMap :: forall name a. Tag name => [(String, a)] -> Map (Name name) a
nameMap = [(Name name, a)] -> Map (Name name) a
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList ([(Name name, a)] -> Map (Name name) a)
-> ([(String, a)] -> [(Name name, a)])
-> [(String, a)]
-> Map (Name name) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((String, a) -> (Name name, a))
-> [(String, a)] -> [(Name name, a)]
forall a b. (a -> b) -> [a] -> [b]
map ((String -> Name name) -> (String, a) -> (Name name, a)
forall a c b. (a -> c) -> (a, b) -> (c, b)
mapFst String -> Name name
forall name. C name => String -> name
Name.fromString)

nameSet :: (Name.Tag name) => [String] -> Set.Set (Name name)
nameSet :: forall name. Tag name => [String] -> Set (Name name)
nameSet = [Name name] -> Set (Name name)
forall a. Ord a => [a] -> Set a
Set.fromList ([Name name] -> Set (Name name))
-> ([String] -> [Name name]) -> [String] -> Set (Name name)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String -> Name name) -> [String] -> [Name name]
forall a b. (a -> b) -> [a] -> [b]
map String -> Name name
forall name. C name => String -> name
Name.fromString

nameSingle :: (Name.Tag name) => String -> Set.Set (Name name)
nameSingle :: forall name. Tag name => String -> Set (Name name)
nameSingle = Name name -> Set (Name name)
forall a. a -> Set a
Set.singleton (Name name -> Set (Name name))
-> (String -> Name name) -> String -> Set (Name name)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Name name
forall name. C name => String -> name
Name.fromString

pSet, dtdSet, thdSet, thdrSet, liSet, headingSet ::
   (Name.Tag name) => Set.Set (Name name)
pSet :: forall name. Tag name => Set (Name name)
pSet       = [String] -> Set (Name name)
forall name. Tag name => [String] -> Set (Name name)
nameSet [String
"p"]
dtdSet :: forall name. Tag name => Set (Name name)
dtdSet     = [String] -> Set (Name name)
forall name. Tag name => [String] -> Set (Name name)
nameSet [String
"dt",String
"dd"]
thdSet :: forall name. Tag name => Set (Name name)
thdSet     = [String] -> Set (Name name)
forall name. Tag name => [String] -> Set (Name name)
nameSet [String
"th",String
"td"]
thdrSet :: forall name. Tag name => Set (Name name)
thdrSet    = [String] -> Set (Name name)
forall name. Tag name => [String] -> Set (Name name)
nameSet [String
"th",String
"td",String
"tr"]
liSet :: forall name. Tag name => Set (Name name)
liSet      = [String] -> Set (Name name)
forall name. Tag name => [String] -> Set (Name name)
nameSet [String
"li"]
headingSet :: forall name. Tag name => Set (Name name)
headingSet = [String] -> Set (Name name)
forall name. Tag name => [String] -> Set (Name name)
nameSet [String
"h1",String
"h2",String
"h3",String
"h4",String
"h5",String
"h6",String
"p" {- not "div" -}]




maybeMetaHTTPHeader ::
   (Name.Tag name, Name.Attribute name) =>
   Tag.Name name -> [Attr.T name string] -> Maybe (string, string)
maybeMetaHTTPHeader :: forall name string.
(Tag name, Attribute name) =>
Name name -> [T name string] -> Maybe (string, string)
maybeMetaHTTPHeader Name name
name [T name string]
attrs =
   do Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (String -> Name name -> Bool
forall name. C name => String -> name -> Bool
Name.match String
"meta" Name name
name)
      (string -> string -> (string, string))
-> Maybe string -> Maybe string -> Maybe (string, string)
forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 (,)
         (String -> [T name string] -> Maybe string
forall name string.
Attribute name =>
String -> [T name string] -> Maybe string
Attr.lookupLit String
"http-equiv" [T name string]
attrs)
         (String -> [T name string] -> Maybe string
forall name string.
Attribute name =>
String -> [T name string] -> Maybe string
Attr.lookupLit String
"content" [T name string]
attrs)


{- |
Extract charset from Content-Type declaration.

> encodingFromContentType "text/html; charset=UTF-8" == "utf-8"

The routine does not perform any syntax check.
-}
encodingFromContentType :: String -> String
encodingFromContentType :: String -> String
encodingFromContentType = (Char -> Char) -> String -> String
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
Char.toLower (String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Bool) -> String -> String
forall a. (a -> Bool) -> [a] -> [a]
ListRev.takeWhile (Char
'='Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/=)

{- |
A simple routine that does not check for valid syntax
of the Content-Type specification.

In future we might use a distinct @Encoding@ type instead of plain String.
-}
maybeMetaEncoding ::
   (Name.Tag name, Name.Attribute name) =>
   Tag.Name name -> [Attr.T name String] -> Maybe String
maybeMetaEncoding :: forall name.
(Tag name, Attribute name) =>
Name name -> [T name String] -> Maybe String
maybeMetaEncoding Name name
name [T name String]
attrs =
   do (String
headerName, String
content) <- Name name -> [T name String] -> Maybe (String, String)
forall name string.
(Tag name, Attribute name) =>
Name name -> [T name string] -> Maybe (string, string)
maybeMetaHTTPHeader Name name
name [T name String]
attrs
      Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard ((String
"content-type"String -> String -> Bool
forall a. Eq a => a -> a -> Bool
==) (String -> Bool) -> (String -> String) -> String -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Char) -> String -> String
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
Char.toLower (String -> Bool) -> String -> Bool
forall a b. (a -> b) -> a -> b
$ String
headerName)
      String -> Maybe String
forall a. a -> Maybe a
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> Maybe String) -> String -> Maybe String
forall a b. (a -> b) -> a -> b
$ String -> String
encodingFromContentType String
content

maybeMetaCharset ::
   (Name.Tag name, Name.Attribute name) =>
   Tag.Name name -> [Attr.T name string] -> Maybe string
maybeMetaCharset :: forall name string.
(Tag name, Attribute name) =>
Name name -> [T name string] -> Maybe string
maybeMetaCharset Name name
name [T name string]
attrs =
   do Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (String -> Name name -> Bool
forall name. C name => String -> name -> Bool
Name.match String
"meta" Name name
name)
      String -> [T name string] -> Maybe string
forall name string.
Attribute name =>
String -> [T name string] -> Maybe string
Attr.lookupLit String
"charset" [T name string]
attrs