yuiGrid-0.1: Text/CxML/HTML.hs
{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-}
module Text.CxML.HTML where
import Text.CxML.Types
import Text.CxML.Tags(input)
-- | escape HTML
--newtype HtmlSafeString = HtSfString String -- this is a type safe way to prevent XSS. We may do that in the future
-- see http://blog.moertel.com/articles/2006/10/18/a-type-based-solution-to-the-strings-problem
hText = HText . escapeBrackets -- poor man's solution to the "strings problem" (see link above)
escapeBrackets :: String -> String
escapeBrackets [] = []
escapeBrackets ('<':t) = "<"++escapeBrackets t
escapeBrackets ('>':t) = ">"++escapeBrackets t
escapeBrackets ('&':t) = "&"++escapeBrackets t
escapeBrackets ('\'':t) = "'"++escapeBrackets t
escapeBrackets ('"':t) = "&qout;"++escapeBrackets t
escapeBrackets ('(':'C':')':t) = "©"++escapeBrackets t --copyright
escapeBrackets (h:t) = h:(escapeBrackets t)
-- | create a text node. Automatically escape HTML to protect against XSS
t :: String-> CxML a
t str = CxML (\_->[hText str],[],[],[])
-- modify HTML part of CxML - used in navList?
modHElems :: (HElem->HElem)->CxML a->CxML a
modHElems f (CxML (h,ts,c,j)) = CxML (\ctx->map f $ h ctx, ts, c, j)
class CxMLChild a b where
(//) :: CxML a -> b -> CxML a
instance CxMLChild a (CxML a)where
p//c= withChildren p [c]
instance CxMLChild a [CxML a]where
p//c= withChildren p c
instance CxMLChild a [Char]where
p//c= withChildren p [t c]
instance CxMLChild a [[Char]] where
p//c= withChildren p $ map t c
infixl 5 //
-- | create an operator to set an attribute of HTML elements
setAttrOp :: String -> (CxML a) -> String -> (CxML a)
setAttrOp at= \tag-> \val->
CxML (\ctx-> map (add_attr at val) $ htm tag ctx, titleParts tag, css tag,js tag )
-- | helper function for setAttrOp
add_attr :: String->String->HElem->HElem
add_attr _ _ s@(HText str)= s
add_attr nm vl (HTag tn ats chs) = HTag tn (add_attr' nm vl ats) chs
where
add_attr' nm vl [] = [(nm,vl)]
add_attr' nm vl ((nm',vl'):ats)
= if (nm==nm')
then (nm,vl' ++ " " ++ vl):ats
else (nm',vl'): add_attr' nm vl ats
--FIXME: a Map could be used for the attributes, although there should be just a few per tag
infixl 8 ^#
(^#)=setAttrOp "id"
infixl 8 ^.
(^.)=setAttrOp "class"
infixl 7 ^>
(^>)=setAttrOp "href"
{-
maybe one day I would like ^> to set href for <a> but src for <img>
(^>) = \tag-> \val->
CxML (\ctx-> map (add_attr at val) $ (htm tag) ctx, css tag,js tag )
where tagAtAssoc = [("img", "src"),
("a", "href")
]-}
-- | set any attribute of HTML element
infixl 8 !
(!) :: (CxML a)->(String, String)->(CxML a)
tag ! (at,vl) = CxML (\ctx-> map (add_attr at vl) $ htm tag ctx, titleParts tag, css tag, js tag)
--------------------------------------------------
-----Modified from module Text.XHtml.Extras -----
--------------------------------------------------
{-widget :: String -> String -> [HtmlAttr] -> Html
widget w n markupAttrs = input ! ([thetype w,name n,identifier n] ++ markupAttrs)
checkbox :: String -> String -> Html
hidden :: String -> String -> Html
radio :: String -> String -> Html
reset :: String -> String -> Html
submit :: String -> String -> Html
password :: String -> Html
textfield :: String -> Html
afile :: String -> Html
clickmap :: String -> Html
checkbox n v = widget "checkbox" n [value v]
hidden n v = widget "hidden" n [value v]
radio n v = widget "radio" n [value v]
reset n v = widget "reset" n [value v]
submit n v = widget "submit" n [value v]
password n = widget "password" n []
textfield n = widget "text" n []
afile n = widget "file" n []
clickmap n = widget "image" n []
-}
widget :: String -> String -> [(String,String)] -> CxML a
widget w n markupAttrs = foldl (!) input (("type",w):("name",n):("id",n):markupAttrs)
textfield n = widget "text" n []
hidden n v = widget "hidden" n [("value",v)]
afile n = widget "file" n []