{-# LANGUAGE OverloadedStrings #-} module Text.HTML.Form (Form(..), Input(..), parseElement, parseDocument) where import Data.Text (Text) import qualified Data.Text as Txt import Text.XML.Cursor import Text.XML (Document) import Data.Maybe (fromMaybe) import Network.URI (parseURIReference, URI, nullURI) import Data.Char (isDigit) data Form = Form { action :: URI, enctype :: Text, method :: Text, validate :: Bool, target :: Text, acceptCharset :: [Text], autocomplete :: Bool, name :: Text, rel :: Text, inputs :: [Input] } data Input = Input attr :: Text -> Cursor -> Text -> Text attr n el def | [ret] <- n `laxAttribute` el = ret | otherwise = def attr' :: Text -> Cursor -> (Text -> a) -> Text -> a attr' n el cb def = cb $ attr n el def parseElement :: Cursor -> Maybe Form parseElement el | _:_ <- laxElement "form" el = Just Form { action = attr' "action" el (fromMaybe nullURI . parseURIReference . Txt.unpack) ".", enctype = attr "enctype" el "", method = attr "method" el "GET", validate = null $ hasAttribute "novalidate" el, target = attr "target" el "_self", acceptCharset = attr' "accept-charset" el Txt.words "utf-8", autocomplete = not $ null $ hasAttribute "autocomplete" el, name = attr "name" el "", rel = attr "rel" el "", inputs = [] } | otherwise = Nothing read' :: Read a => Text -> a read' = read . Txt.unpack parseDocument :: Document -> Text -> Maybe Form parseDocument doc n | Txt.all isDigit n = parseElement (forms doc' !! read' n) | el:_ <- (forms >=> attributeIs "name" n) doc' = parseElement el | otherwise = Nothing where forms = orSelf descendant >=> laxElement "form" doc' = fromDocument doc