packages feed

hsp 0.4.4 → 0.4.5

raw patch · 8 files changed

+158/−72 lines, 8 filesdep ~basePVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: base

API changes (from Hackage documentation)

- HSP: genEElement :: (XMLGen m) => Name -> [XMLGenT m [Attribute m]] -> XMLGenT m (XML m)
- HSP: genElement :: (XMLGen m) => Name -> [XMLGenT m [Attribute m]] -> [XMLGenT m [Child m]] -> XMLGenT m (XML m)
- HSP.XML: newtype AttrValue
+ HSP: setMetaData :: (Monad m) => (Maybe XMLMetaData) -> HSPT m ()
+ HSP: withMetaData :: (Monad m) => Maybe XMLMetaData -> HSPT m a -> HSPT m a
+ HSP.HTML: html4Strict :: Maybe XMLMetaData
+ HSP.HTML: html4StrictFrag :: Maybe XMLMetaData
+ HSP.HTML: htmlEscapeChars :: [(Char, String)]
+ HSP.XML: XMLMetaData :: (Bool, String) -> String -> (XML -> String) -> XMLMetaData
+ HSP.XML: contentType :: XMLMetaData -> String
+ HSP.XML: data AttrValue
+ HSP.XML: data XMLMetaData
+ HSP.XML: doctype :: XMLMetaData -> (Bool, String)
+ HSP.XML: preferredRenderer :: XMLMetaData -> XML -> String
+ HSP.XML.PCDATA: escaper :: [(Char, String)] -> String -> String
+ HSP.XML.PCDATA: unescaper :: [(Char, String)] -> String -> String
+ HSP.XML.PCDATA: xmlEscapeChars :: [(Char, String)]
- HSP: evalHSP :: HSP a -> IO a
+ HSP: evalHSP :: Maybe XMLMetaData -> HSP a -> IO (Maybe XMLMetaData, a)
- HSP: evalHSPT :: (MonadIO m) => HSPT m a -> m a
+ HSP: evalHSPT :: (MonadIO m) => Maybe XMLMetaData -> HSPT m a -> m (Maybe XMLMetaData, a)
- HSP: runHSP :: HSP a -> HSPEnv -> IO a
+ HSP: runHSP :: Maybe XMLMetaData -> HSP a -> HSPEnv -> IO (Maybe XMLMetaData, a)
- HSP: runHSPT :: HSPT m a -> HSPEnv -> m a
+ HSP: runHSPT :: (Monad m) => Maybe XMLMetaData -> HSPT m a -> HSPEnv -> m (Maybe XMLMetaData, a)
- HSP: type HSPT' m = ReaderT HSPEnv m
+ HSP: type HSPT' m = RWST HSPEnv () (Maybe XMLMetaData) m
- HSP.XML: CDATA :: String -> XML
+ HSP.XML: CDATA :: Bool -> String -> XML
- HSP.XML: Value :: String -> AttrValue
+ HSP.XML: Value :: Bool -> String -> AttrValue

Files

hsp.cabal view
@@ -1,5 +1,5 @@ Name:                   hsp-Version:                0.4.4+Version:                0.4.5 License:                BSD3 License-File:           LICENSE Author:                 Niklas Broberg, Joel Bjornson@@ -20,15 +20,16 @@                         For details on usage, please see the website, and the author's thesis. Homepage:               http://code.google.com/p/hsp -Build-Depends:          base>3, mtl, harp, hsx>=0.4.4, HJScript>=0.4.4+Build-Depends:          base >3 && < 4, mtl, harp, hsx>=0.4.4, HJScript>=0.4.4 Build-Type:             Simple+Cabal-Version:          >= 1.2.3 Tested-With:            GHC==6.8.3  Hs-Source-Dirs:         src Exposed-Modules:        HSP.XML, HSP.XML.PCDATA, HSP.HTML, HSP.Env, HSP.Env.Request, HSP.Env.NumberGen, HSP.HJScript, HSP Other-Modules:          HSP.Exception, HSP.Monad, HSP.XMLGenerator -GHC-Options:            -F -pgmFtrhsx -Wall -fno-warn-orphans+GHC-Options:            -Wall -fno-warn-orphans Extensions:             MultiParamTypeClasses,                         FunctionalDependencies,                         TypeFamilies,
src/HSP.hs view
@@ -1,7 +1,7 @@ module HSP (
         -- module HSP.Monad
         HSP, HSPT, HSPT', runHSP, evalHSP, runHSPT, evalHSPT, getEnv,
-        getParam, getIncNumber, doIO, catch,
+        getParam, getIncNumber, doIO, catch, setMetaData, withMetaData,
         
         -- module HSP.Env
         module HSP.Env,
src/HSP/HJScript.hs view
@@ -1,3 +1,4 @@+{-# OPTIONS_GHC -F -pgmFtrhsx #-}
 module HSP.HJScript where
 
 import HSP.Monad
@@ -17,7 +18,7 @@   asChild script = asChild . snd $ evalHJScript script
 
 instance Monad m => IsAttrValue m (Block t) where
-  toAttrValue block = return . Value $ "javascript:" ++ show block
+  toAttrValue block = return . attrVal $ "javascript:" ++ show block
 
 instance Monad m => IsAttrValue m (HJScript ()) where
   toAttrValue script = toAttrValue . snd $ evalHJScript script
src/HSP/HTML.hs view
@@ -8,27 +8,34 @@ -- Stability   :  experimental -- Portability :  Haskell 98 ----- Attempt to render XML as well-formed HTML 4.01:---  * no short tags are used, e.g., <script></script> instead of <script />---  * the end tag is forbidden for some elements, for these we:---    * render only the open tag, e.g., <br>+-- Attempt to render XHTML as well-formed HTML 4.01:+--+--  1. no short tags are used, e.g., \<script\>\<\/script\> instead of \<script \/\>+--+--  2. the end tag is forbidden for some elements, for these we:+--+--    * render only the open tag, e.g., \<br\>+-- --    * throw an error if the tag contains children---  * optional end tags are always rendered --+--  3. optional end tags are always rendered+-- -- Currently no validation is performed. ----------------------------------------------------------------------------- module HSP.HTML (                  -- * Functions-                 renderAsHTML+                  renderAsHTML+                , htmlEscapeChars+                 -- * Predefined XMLMetaData+                , html4Strict+                , html4StrictFrag                 ) where  import Data.List import HSP.XML-import HSP.XML.PCDATA(unescape)+import HSP.XML.PCDATA(escaper)  -- | Pretty-prints HTML values.--- FIXME: also verify that the domain is correct--- FIXME: what to do if a namespace is encountered -- -- Error Handling: --@@ -38,7 +45,9 @@ -- handle this: -- --  1. drop the bogus children silently---  2. call 'error' / raise an exception+--+--  2. call 'error' \/ raise an exception+-- --  3. render the img tag with children -- even though it is invalid -- -- Currently we are taking approach #3, since no other attempts to@@ -58,13 +67,17 @@ -- -- Another solution would be a compile time error if an empty-only -- tag contained children.+--+-- FIXME: also verify that the domain is correct+--+-- FIXME: what to do if a namespace is encountered renderAsHTML :: XML -> String renderAsHTML xml = renderAsHTML' 0 xml ""  data TagType = Open | Close  renderAsHTML' :: Int -> XML -> ShowS-renderAsHTML' _ (CDATA cd) = showString cd+renderAsHTML' _ (CDATA needsEscape cd) = showString (if needsEscape then (escaper htmlEscapeChars cd) else cd) renderAsHTML' n elm@(Element name@(Nothing,nm) attrs children)      | nm == "area"	= renderTagEmpty children     | nm == "base"	= renderTagEmpty children@@ -76,24 +89,18 @@     | nm == "link"      = renderTagEmpty children     | nm == "meta"      = renderTagEmpty children     | nm == "param"     = renderTagEmpty children-    | nm == "script"    = renderTagCDATA children-    | nm == "style"     = renderTagCDATA children+    | nm == "script"    = renderElement n (Element name attrs (map asCDATA children))+    | nm == "style"     = renderElement n (Element name attrs (map asCDATA children))     where       renderTagEmpty [] = renderTag Open n name attrs-      renderTagEmpty _ = renderElement n elm -- ^ this case should not happen in valid HTML-      renderTagCDATA :: Children -> ShowS-      renderTagCDATA children =-        let open  = renderTag Open n name attrs -            cs    = renderChildrenCDATA 0 children -            close = renderTag Close n name []-        in-          open . cs .close-      renderChildrenCDATA :: Int -> Children -> ShowS-      renderChildrenCDATA n' cs = foldl (.) id $ map (renderChildCDATA (n'+2)) cs-      renderChildCDATA n (CDATA cd) = showString (unescape cd)-      renderChildCDATA n e = renderElement n e  -- ^ this case should not happen in valid HTML+      renderTagEmpty _ = renderElement n elm -- this case should not happen in valid HTML+      -- for and script\/style, render text in element as CDATA not PCDATA+      asCDATA :: XML -> XML+      asCDATA (CDATA _ cd) = (CDATA False cd)+      asCDATA o = o -- this case should not happen in valid HTML renderAsHTML' n e = renderElement n e +renderElement :: Int -> XML -> String -> String renderElement n (Element name attrs children) =         let open  = renderTag Open n name attrs              cs    = renderChildren n children @@ -118,7 +125,7 @@           renderAttr :: Attribute -> ShowS-        renderAttr (MkAttr (nam, (Value val))) = showName nam . showChar '=' . renderAttrVal val+        renderAttr (MkAttr (nam, (Value needsEscape val))) = showName nam . showChar '=' . renderAttrVal (if needsEscape then (escaper htmlEscapeChars val) else val)          renderAttrVal :: String -> ShowS         renderAttrVal s = showChar '\"' . showString s . showChar '\"'@@ -127,3 +134,28 @@         showName (Just d, s)  = showString d . showChar ':' . showString s          nl = showChar '\n' . showString (replicate n ' ')++-- This list should be extended.+htmlEscapeChars :: [(Char, String)]+htmlEscapeChars = [+	('&',	"amp"	),+	('\"',	"quot"	),+	('<',	"lt"	),+	('>',	"gt"	)+	]++-- * Pre-defined XMLMetaData++html4Strict :: Maybe XMLMetaData+html4Strict = Just $+    XMLMetaData { doctype = (True, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n")+                , contentType = "text/html;charset=utf-8"+                , preferredRenderer = renderAsHTML+                }++html4StrictFrag :: Maybe XMLMetaData+html4StrictFrag = Just $+    XMLMetaData { doctype = (False, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n")+                , contentType = "text/html;charset=utf-8"+                , preferredRenderer = renderAsHTML+                }
src/HSP/Monad.hs view
@@ -21,11 +21,14 @@         runHSP, evalHSP, runHSPT, evalHSPT, getEnv,         unsafeRunHSP,  -- dangerous!!         -- * Functions-        getParam, getIncNumber, doIO, catch+        getParam, getIncNumber, doIO, catch,+        setMetaData, withMetaData         ) where  -- Monad imports-import Control.Monad.Reader (ReaderT(..), ask, lift)+-- import Control.Monad.Reader (ReaderT(..), ask, lift)+import Control.Monad.RWS (RWST(..), ask, lift, put)+import Control.Monad.State import Control.Monad.Trans (MonadIO(..))  import Prelude hiding (catch)@@ -36,6 +39,7 @@  import HSP.Env +import HSP.XML import HSX.XMLGenerator (XMLGenT(..), unXMLGenT)  --------------------------------------------------------------@@ -48,7 +52,7 @@  type HSP =  HSPT IO -type HSPT' m = ReaderT HSPEnv m+type HSPT' m = RWST HSPEnv () (Maybe XMLMetaData) m type HSPT  m = XMLGenT (HSPT' m)  -- do NOT export this in the final version@@ -57,27 +61,36 @@  -- | Runs a HSP computation in a particular environment. Since HSP wraps the IO monad, -- the result of running it will be an IO computation.-runHSP :: HSP a -> HSPEnv -> IO a-runHSP = runReaderT . unXMLGenT+runHSP :: Maybe XMLMetaData -> HSP a -> HSPEnv -> IO (Maybe XMLMetaData, a)+runHSP xmd hsp hspEnv = runRWST (unXMLGenT hsp) hspEnv xmd >>= \(a,md,()) -> return (md, a) -runHSPT :: HSPT m a -> HSPEnv -> m a-runHSPT = runReaderT . unXMLGenT+runHSPT :: (Monad m) => Maybe XMLMetaData -> HSPT m a -> HSPEnv -> m (Maybe XMLMetaData, a)+runHSPT xmd hsp hspEnv = runRWST (unXMLGenT hsp) hspEnv xmd >>= \(a,md,()) -> return (md, a) -evalHSPT :: MonadIO m => HSPT m a -> m a-evalHSPT hsp = liftIO mkSimpleEnv >>= runHSPT hsp+evalHSPT :: MonadIO m => Maybe XMLMetaData -> HSPT m a -> m (Maybe XMLMetaData, a)+evalHSPT xmd hsp = liftIO mkSimpleEnv >>= \env -> runHSPT xmd hsp env  -evalHSP :: HSP a -> IO a-evalHSP hsp = mkSimpleEnv >>= runHSP hsp +evalHSP :: Maybe XMLMetaData -> HSP a -> IO (Maybe XMLMetaData, a)+evalHSP xmd hsp = mkSimpleEnv >>= \env -> runHSP xmd hsp env  -- | Runs a HSP computation without an environment. Will work if the page in question does -- not touch the environment. Not sure about the usefulness at this stage though...-unsafeRunHSP :: HSP a -> IO a-unsafeRunHSP hspf = runHSP hspf dummyEnv+unsafeRunHSP :: HSP a -> IO (Maybe XMLMetaData, a)+unsafeRunHSP hspf = runHSP Nothing hspf dummyEnv  -- | Execute an IO computation within the HSP monad. doIO :: IO a -> HSP a doIO = liftIO +setMetaData :: (Monad m) => (Maybe XMLMetaData) -> HSPT m ()+setMetaData xmd = lift (put xmd)++withMetaData :: (Monad m) => Maybe XMLMetaData -> HSPT m a -> HSPT m a+withMetaData xmd h = do+  x <- h+  setMetaData xmd+  return x+ ---------------------------------------------------------------- -- Environment stuff @@ -101,6 +114,6 @@  -- | Catch a user-caused exception. catch :: HSP a -> (Exception -> HSP a) -> HSP a-catch (XMLGenT (ReaderT f)) handler = XMLGenT $ ReaderT $ \e ->-        f e `catchDyn` (\ex -> (let (XMLGenT (ReaderT g)) = handler ex-                                 in g e))+catch (XMLGenT (RWST f)) handler = XMLGenT $ RWST $ \e s ->+        f e s `catchDyn` (\ex -> (let (XMLGenT (RWST g)) = handler ex+                                 in g e s))
src/HSP/XML.hs view
@@ -14,6 +14,7 @@ module HSP.XML (         -- * The 'XML' datatype         XML(..), +        XMLMetaData(..),         Domain,          Name,          Attributes, @@ -42,9 +43,20 @@  -- | The XML datatype representation. Is either an Element or CDATA. data XML = Element Name Attributes Children-         | CDATA String+         | CDATA Bool String   deriving Show +-- |The XMLMetaData datatype+-- +-- Specify the DOCTYPE, content-type, and preferred render for XML data.+--+-- See also: 'HSP.Monad.setMetaData' and 'HSP.Monad.withMetaData'+data XMLMetaData = XMLMetaData+  {  doctype :: (Bool, String) -- ^ (show doctype when rendering, DOCTYPE string)+  ,  contentType :: String+  ,  preferredRenderer :: XML -> String+  } + {- instance Show XML where  show = renderXML -} @@ -56,8 +68,8 @@  -- | Embeds a string as a CDATA XML value. cdata , pcdata :: String -> XML-cdata  = CDATA-pcdata = cdata . escape+cdata  = CDATA False+pcdata = CDATA True  --------------------------------------------------------------- -- Attributes@@ -66,15 +78,15 @@   deriving Show  -- | Represents an attribue value.-newtype AttrValue = Value String+data AttrValue = Value Bool String  -- | Create an attribue value from a string. attrVal, pAttrVal :: String -> AttrValue-attrVal  = Value-pAttrVal = attrVal . escape+attrVal  = Value False+pAttrVal = Value True  instance Show AttrValue where- show (Value str) = str+ show (Value _ str) = str  ------------------------------------------------------------------ -- Rendering@@ -88,7 +100,7 @@ data TagType = Open | Close | Single  renderXML' :: Int -> XML -> ShowS-renderXML' _ (CDATA cd) = showString cd+renderXML' _ (CDATA needsEscape cd) = showString (if needsEscape then escape cd else cd) renderXML' n (Element name attrs []) = renderTag Single n name attrs renderXML' n (Element name attrs children) =         let open  = renderTag Open n name attrs @@ -117,7 +129,7 @@           renderAttr :: Attribute -> ShowS-        renderAttr (MkAttr (nam, (Value val))) = showName nam . showChar '=' . renderAttrVal val+        renderAttr (MkAttr (nam, (Value needsEscape val))) = showName nam . showChar '=' . renderAttrVal  (if needsEscape then escape val else val)          renderAttrVal :: String -> ShowS         renderAttrVal s = showChar '\"' . showString s . showChar '\"'
src/HSP/XML/PCDATA.hs view
@@ -13,22 +13,37 @@ module HSP.XML.PCDATA ( 	  escape	-- :: String -> String 	, unescape	-- :: String -> String+        , escaper+        , unescaper+        , xmlEscapeChars 	) where   -- | Take a normal string and transform it to PCDATA by escaping special characters.+-- calls 'escaper' with 'xmlEscapeChars'+-- See also: 'escaper' escape :: String -> String-escape [] = ""-escape (c:cs) = pChar c ++ escape cs+escape = escaper xmlEscapeChars -pChar :: Char -> String-pChar c = case lookup c escapeChars of-	   Nothing -> [c]-	   Just s  -> '&' : s ++ ";"+-- | Take a normal string and transform it to PCDATA by escaping special characters.+-- See also: 'escape', 'xmlEscapeChars'+escaper :: [(Char, String)] -- ^ table of escape characters+        -> String -- ^ String to escape+        -> String -- ^ Escaped String+escaper _ [] = ""+escaper escapeChars (c:cs) = pChar escapeChars c ++ escaper escapeChars cs +pChar :: [(Char, String)] -- ^ table of escape characters+      -> Char -- ^ character to escape+      -> String -- ^ escaped character+pChar escapeChars c = +    case lookup c escapeChars of+      Nothing -> [c]+      Just s  -> '&' : s ++ ";"+ -- This list should be extended.-escapeChars :: [(Char, String)]-escapeChars = [+xmlEscapeChars :: [(Char, String)]+xmlEscapeChars = [ 	('&',	"amp"	), 	('\"',	"quot"	), 	('\'',	"apos"	),@@ -39,8 +54,19 @@ -- | Take a PCDATA string and translate all escaped characters in it to the normal -- characters they represent. -- Does no error checking of input string, will fail if input is not valid PCDATA.+-- calls 'unescaper' with 'xmlEscapeChars'+-- See also: 'unescaper' unescape :: String -> String-unescape = reverse . unE ""+unescape = unescaper xmlEscapeChars++-- | Take a PCDATA string and translate all escaped characters in it to the normal+-- characters they represent.+-- Does no error checking of input string, will fail if input is not valid PCDATA.+-- See also: 'unescape', 'xmlEscapeChars'+unescaper :: [(Char, String)] -- ^ table of escape characters+          -> String -- ^ String to unescape+          -> String -- ^ unescaped String+unescaper escapeChars = reverse . unE ""   where unE acc "" = acc   	unE acc (c:cs) =    	  case c of
src/HSP/XMLGenerator.hs view
@@ -1,3 +1,4 @@+{-# OPTIONS_GHC -F -pgmFtrhsx #-}
 module HSP.XMLGenerator (
         -- * Type classes
 --        IsXML(..), 
@@ -267,7 +268,7 @@  setAll xml hats = do
         attrs <- hats
         case xml of
-         CDATA _         -> return xml
+         CDATA _ _       -> return xml
          Element n as cs -> return $ Element n (foldr insert as (map stripAttr attrs)) cs
 
 {-
@@ -281,7 +282,7 @@  appAll xml children = do
         chs <- children
         case xml of
-         CDATA _         -> return xml
+         CDATA _ _       -> return xml
          Element n as cs -> return $ Element n as (cs ++ (map stripChild chs))
 
 {-
@@ -303,7 +304,7 @@ 
 -- | Strings can be directly taken from values.
 instance GetAttrValue String where
- fromAttrValue (Value s) = s
+ fromAttrValue (Value _ s) = s
  
 -- | Anything that can be read can always fall back on
 -- that as a default behavior.
@@ -318,9 +319,9 @@ -- | The common way to present list data in attributes is as
 -- a comma separated, unbracketed sequence
 instance (GetAttrValue a) => GetAttrValue [a] where
- fromAttrValue v@(Value str) = case str of
+ fromAttrValue v@(Value needsEscape str) = case str of
         [ v1+, (| ',', vs@:(_+) |)+ ] -> 
-                map (fromAttrValue . Value) (v1:vs)
+                map (fromAttrValue . Value needsEscape) (v1:vs)
         _ -> [fromAttrValue v]
 
 -- All that for these two functions
@@ -351,13 +352,13 @@         flattenCDATA cxml = 
                 case flP cxml [] of
                  [] -> []
-                 [CDATA ""] -> []
+                 [CDATA _ ""] -> []
                  xs -> xs                       
         flP :: [XML] -> [XML] -> [XML]
         flP [] bs = reverse bs
         flP [x] bs = reverse (x:bs)
         flP (x:y:xs) bs = case (x,y) of
-                           (CDATA s1, CDATA s2) -> flP (CDATA (s1++s2) : xs) bs
+                           (CDATA e1 s1, CDATA e2 s2) | e1 == e2 -> flP (CDATA e1 (s1++s2) : xs) bs
                            _ -> flP (y:xs) (x:bs)
 
 stripAttr :: HSX.Attribute (HSPT' m) -> Attribute