module HSX.XHTML where
import HSX.XMLGenerator
import Data.List (intersperse)
class (XMLGenerator m, EmbedAsChild m t, EmbedAsAttr m (Attr String t)) => StringType m t
class (XMLGenerator m, EmbedAsAttr m (Attr String t)) => IntType m t
class (XMLGenerator m, EmbedAsAttr m (Attr String t)) => BoolType m t
class (XMLGenerator m, EmbedAsAttr m (Attr String t)) => ShapeType m t
class (XMLGenerator m, EmbedAsAttr m (Attr String t)) => DirType m t
class (XMLGenerator m, EmbedAsChild m t ) => LegendType m t
class (XMLGenerator m, EmbedAsAttr m t ) => InputType m t
class (XMLGenerator m, EmbedAsAttr m t ) => CheckedType m t
class (XMLGenerator m, EmbedAsAttr m t ) => HTTPEquivType m t
class (XMLGenerator m, EmbedAsAttr m t ) => MetaNameType m t
class (XMLGenerator m, EmbedAsChild m t, EmbedAsAttr m t ) => ScriptType m t
class (XMLGenerator m, EmbedAsChild m t, EmbedAsAttr m t ) => OptionType m t
class (XMLGenerator m, EmbedAsChild m t ) => CaptionType m t
instance XMLGenerator m => StringType m String
instance XMLGenerator m => IntType m Int
instance XMLGenerator m => BoolType m Bool
page ::(StringType m title,
EmbedAsAttr m a,
EmbedAsChild m body)
=> title -> [a] -> body -> GenXML m
page title attrs html
= <html>
<head>
<title><% title %></title>
</head>
<body attrs><% html %></body>
</html>
link, anchor :: (StringType m s, EmbedAsChild m c) => s -> c -> GenXML m
link url conts = <a href=url><% conts %></a>
anchor name conts = <a id=name><% conts %></a>
abbr, acronym :: (StringType m s1, StringType m s2)
=> s1 -> s2 -> GenXML m
abbr full a = <abbr title=full><% a %></abbr>
acronym full a = <acronym title=full><% a %></acronym>
address :: (XMLGenerator m, EmbedAsChild m l) => [l] -> GenXML m
address ls = <address><% intersperse <% br %> $ map asChild ls %></address>
area :: (StringType m alt, StringType m url, ShapeType m sh)
=> alt -> sh -> url -> GenXML m
area altTxt sh url =
<area
alt=altTxt
shape=sh
coords=sh
href=url
/>
bdo :: (EmbedAsChild m a, DirType m d) => d -> a -> GenXML m
bdo dir a = <bdo dir=dir><% a %></bdo>
base :: (StringType m s) => s -> GenXML m
base url = <base href=url />
blockquote, q :: EmbedAsChild m a => a -> GenXML m
blockquote a = <blockquote><% a %></blockquote>
q a = <q><% a %></q>
br :: XMLGenerator m => GenXML m
br = <br/>
button :: EmbedAsChild m a => a -> GenXML m
button a = <button><% a %></button>
del, ins :: (StringType m s) => s -> GenXML m
del str = <del><% str %></del>
ins str = <ins><% str %></ins>
div, span, p :: EmbedAsChild m a => a -> GenXML m
div a = <div><% a %></div>
span a = <span><% a %></span>
p a = <p><% a %></p>
dl :: (EmbedAsChild m a, EmbedAsChild m b) => [(a,[b])] -> GenXML m
dl entries = <dl><% concatMap mkDef entries %></dl>
where mkDef (a, bs) = <dt><% a %></dt> : map (\b -> <dd><% b %></dd>) bs
fieldset :: (LegendType m l, EmbedAsChild m a) => l -> a -> GenXML m
fieldset lgd conts =
<fieldset>
<% lgd %>
<% conts %>
</fieldset>
form :: (StringType m s, EmbedAsChild m a) => s -> a -> GenXML m
form url conts = <form action=url><% conts %></form>
head :: (StringType m s, EmbedAsChild m a) => s -> a -> GenXML m
head ttl conts =
<head><title><% ttl %></title><% conts %></head>
h :: EmbedAsChild m a => Int -> a -> GenXML m
h n a = genElement (Nothing, ("h" ++ show n)) [] [asChild a]
h1,h2,h3,h4,h5,h6 :: EmbedAsChild m a => a -> GenXML m
h1 = h 1
h2 = h 2
h3 = h 3
h4 = h 4
h5 = h 5
h6 = h 6
hr :: XMLGenerator m => GenXML m
hr = <hr />
img :: (StringType m alt, StringType m url) => alt -> url -> GenXML m
img altTxt url = <img alt=altTxt src=url />
imgmap :: (StringType m alt, StringType m url, StringType m map,
StringType m aalt, StringType m aurl, ShapeType m sh)
=> alt -> url -> (map, [(aalt, sh, aurl)]) -> GenXMLList m
imgmap altTxt url (im,areas) =
do ix <- <img alt=altTxt src=url ismap=True usemap=im />
mp <- <map id=im name=im><% map (\(a,s,u) -> area a s u) areas %></map>
return $ [ix,mp]
label :: (StringType m s, EmbedAsChild m a) => s -> a -> GenXML m
label inp a = <label for=inp><% a %></label>
input :: (InputType m i, StringType m s) => i -> s -> GenXML m
input itype n = <input name=n [itype] />
data Input c s
= Checkbox c
| File
| Image s s
| Hidden
| Button s
| Password
| Text
| Radio c
| Submit s
| Reset s
type CInput c = Input c String
type SInput s = Input Checked s
data Checked = Checked | Unchecked
instance XMLGenerator m => EmbedAsAttr m Checked where
asAttr Checked = asAttr ("checked" := "checked")
asAttr Unchecked = return []
instance XMLGenerator m => CheckedType m Checked
instance (XMLGenerator m, CheckedType m c, StringType m s) => EmbedAsAttr m (Input c s) where
asAttr inp = do
t <- asAttr $ typeOf inp
es <- extras inp
return $ t ++ es
where typeOf i = let t = case i of
Checkbox _ -> "checkbox"
File -> "file"
Image _ _ -> "image"
Hidden -> "hidden"
Button _ -> "button"
Password -> "password"
Text -> "text"
Radio _ -> "radio"
Submit _ -> "submit"
Reset _ -> "reset"
in "type" := t
extras i = case i of
Checkbox b -> asAttr b
Radio b -> asAttr b
Image altText url -> asAttr ["alt" := altText, "src" := url]
Button val -> asAttr ["value" := val]
Submit val -> asAttr ["value" := val]
Reset val -> asAttr ["value" := val]
_ -> return []
instance (XMLGenerator m, CheckedType m c, StringType m s) => InputType m (Input c s)
submitButton, resetButton :: forall m n v . (StringType m n, StringType m v) => n -> v -> GenXML m
submitButton n val = input (Submit val :: SInput v) n
resetButton n val = input (Reset val :: SInput v) n
checkbox :: forall m c s1 s2 . (CheckedType m c, StringType m s1, StringType m s2) => c -> s1 -> s2 -> GenXMLList m
checkbox check n lbl =
sequence $ [input (Checkbox check :: CInput c) n, label lbl n]
data HTTPEquiv
= ContentType
| Expires
| Refresh
| SetCookie
instance XMLGenerator m => EmbedAsAttr m HTTPEquiv where
asAttr he = asAttr ("http-equiv" := toStr he)
where toStr ContentType = "content-type"
toStr Expires = "expires"
toStr Refresh = "refresh"
toStr SetCookie = "set-cookie"
instance XMLGenerator m => HTTPEquivType m HTTPEquiv
data MetaName
= Author
| Description
| Keywords
| Generator
| Revised
| Others String
instance XMLGenerator m => EmbedAsAttr m MetaName where
asAttr mn = asAttr ("name" := toStr mn)
where toStr Author = "author"
toStr Description = "description"
toStr Keywords = "keywords"
toStr Generator = "generator"
toStr Revised = "revised"
toStr (Others s) = s
instance XMLGenerator m => MetaNameType m MetaName
httpEquiv :: (HTTPEquivType m h, StringType m s) => h -> s -> GenXML m
httpEquiv equiv conts = <meta content=conts [equiv] />
meta :: (MetaNameType m mn, StringType m s) => mn -> s -> GenXML m
meta mn conts = <meta content=conts [mn] />
object :: (EmbedAsChild m a, StringType m s1, StringType m s2)
=> [(s1, s2)] -> a -> GenXML m
object pars alt = <object><% alt %><% mapM (uncurry param) pars %></object>
param :: (StringType m s1, StringType m s2) => s1 -> s2 -> GenXML m
param n v = <param name=n value=v />
ol, orderedList, ul, unorderedList :: (EmbedAsChild m a) => [a] -> GenXML m
ol items = <ol><% mapM listItem items %></ol>
orderedList = ol
ul items = <ul><% mapM listItem items %></ul>
unorderedList = ul
listItem :: EmbedAsChild m a => a -> GenXML m
listItem a = <li><% a %></li>
pre :: EmbedAsChild m a => a -> GenXML m
pre a = <pre><% a %></pre>
script :: (ScriptType m s, EmbedAsChild m a) => s -> a -> GenXMLList m
script sc alt = sequence [<script [sc]><% sc %></script>, <noscript><% alt %></noscript>]
data JavaScript s = JavaScript s
instance XMLGenerator m => EmbedAsAttr m (JavaScript s) where
asAttr _ = asAttr ("type" := "text/javascript")
instance EmbedAsChild m s => EmbedAsChild m (JavaScript s) where
asChild (JavaScript s) = asChild s
instance (XMLGenerator m, EmbedAsChild m s) => ScriptType m (JavaScript s)
data Option s
= Selected s s
| Unselected s s
mkOption :: StringType m s => s -> s -> Bool -> Option s
mkOption conts val sel = case sel of
True -> Selected conts val
_ -> Unselected conts val
instance StringType m s => EmbedAsAttr m (Option s) where
asAttr (Selected v _) = asAttr ("selected":="selected") >>=
\ss -> asAttr ("value":=v) >>=
\vs -> return $ ss ++ vs
asAttr (Unselected v _) = asAttr ("value":=v)
instance StringType m s => EmbedAsChild m (Option s) where
asChild (Selected _ c) = asChild c
asChild (Unselected _ c) = asChild c
instance StringType m s => OptionType m (Option s)
select' :: OptionType m o => [GenAttributeList m] -> [o] -> GenXML m
select' attrs opts = <select attrs><% mapM option opts %></select>
select :: forall m o . OptionType m o => [o] -> GenXML m
select = select' [return []]
multiSelect :: forall m o . OptionType m o => [o] -> GenXML m
multiSelect = select' [asAttr $ "multiple" := "multiple"]
sizedSelect :: (IntType m i, OptionType m o) => i -> [o] -> GenXML m
sizedSelect n = select' [asAttr $ "size" := n]
sizedMultiSelect :: (IntType m i, OptionType m o) => i -> [o] -> GenXML m
sizedMultiSelect n = select' [asAttr $ "multiple" := "multiple", asAttr $ "size" := n]
option :: OptionType m o => o -> GenXML m
option opt = <option [opt]><% opt %></option>
type OptGroup s o = (s, [o])
groupSelect :: (StringType m s, OptionType m o) => [OptGroup s o] -> GenXML m
groupSelect gs = <select><% mapM (uncurry optgroup) gs %></select>
optgroup :: (StringType m s, OptionType m o) => s -> [o] -> GenXML m
optgroup s opts = <optgroup label=s><% mapM option opts %></optgroup>
sub, sup :: EmbedAsChild m a => a -> GenXML m
sub a = <sub><% a %></sub>
sup a = <sup><% a %></sup>
data Caption a
= Caption a
| NoCaption
capt :: a -> Caption a
capt = Caption
noCapt :: Caption a
noCapt = NoCaption
instance EmbedAsChild m c => EmbedAsChild m (Caption c) where
asChild NoCaption = return []
asChild (Caption a) = asChild $ caption a
instance (XMLGenerator m, EmbedAsChild m c) => CaptionType m (Caption c)
caption :: EmbedAsChild m c => c -> GenXML m
caption a = <caption><% a %></caption>
colgroup :: (EmbedAsAttr m a, IntType m i) => i -> [[a]] -> GenXML m
colgroup spancols colattrs =
<colgroup span=spancols><% mapM col colattrs %></colgroup>
col :: EmbedAsAttr m a => [a] -> GenXML m
col ats = <col ats />
table :: (CaptionType m cap, EmbedAsChild m c) => cap -> [[c]] -> GenXML m
table cap rows = <table><% cap %><% mapM tableRow rows %></table>
tableRow :: EmbedAsChild m a => [a] -> GenXML m
tableRow cells = <tr><% mapM tableCell cells %></tr>
tableCell :: EmbedAsChild m a => a -> GenXML m
tableCell a = <td><% a %></td>
headFootTable :: (EmbedAsChild m h, EmbedAsChild m b, EmbedAsChild m f) => h -> [[b]] -> f -> GenXML m
headFootTable hs body fs =
<table>
<thead><% hs %></thead>
<tfoot><% fs %></tfoot>
<tbody><% mapM tableRow body %></tbody>
</table>