hsp-0.10.0/0000755000000000000000000000000012240516336010552 5ustar0000000000000000hsp-0.10.0/LICENSE0000644000000000000000000000261612240516336011564 0ustar0000000000000000All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the author nor the names of his contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. hsp-0.10.0/hsp.cabal0000644000000000000000000000455312240516336012337 0ustar0000000000000000Name: hsp Version: 0.10.0 License: BSD3 License-File: LICENSE Author: Niklas Broberg, Joel Bjornson Maintainer: Niklas Broberg Stability: Experimental Category: Web, Language Synopsis: Haskell Server Pages is a library for writing dynamic server-side web pages. Description: Haskell Server Pages (HSP) is an extension of vanilla Haskell, targetted at the task of writing dynamic server-side web pages. Features include: . * Embedded XML syntax . * A (low-to-mid-level) programming model for writing dynamic web pages . * A cgi-handler utility (as a separate package, hsp-cgi) . For details on usage, please see the website, and the author's thesis. Homepage: http://hub.darcs.net/nibro/hsp Build-Type: Simple Cabal-Version: >= 1.6 Tested-With: GHC==7.6.3 source-repository head type: darcs location: http://hub.darcs.net/nibro/hsp Flag base4 Library Build-Depends: base >3 && < 5, mtl, text if flag(base4) Build-depends: base >= 4 && < 5 cpp-options: -DBASE4 else Build-depends: base >= 3 && < 4 Hs-Source-Dirs: src Exposed-Modules: HSP HSP.HTML4 HSP.Monad HSP.XML HSP.XML.PCDATA HSP.XMLGenerator GHC-Options: -Wall -fno-warn-orphans Extensions: MultiParamTypeClasses, FunctionalDependencies, TypeFamilies, RankNTypes, PolymorphicComponents, ExistentialQuantification, FlexibleContexts, FlexibleInstances, EmptyDataDecls, CPP, TypeSynonymInstances, OverlappingInstances, UndecidableInstances, PatternGuards hsp-0.10.0/Setup.hs0000644000000000000000000000005612240516336012207 0ustar0000000000000000import Distribution.Simple main = defaultMain hsp-0.10.0/src/0000755000000000000000000000000012240516336011341 5ustar0000000000000000hsp-0.10.0/src/HSP.hs0000644000000000000000000000016212240516336012326 0ustar0000000000000000module HSP ( module HSP.XMLGenerator , module HSP.XML ) where import HSP.XMLGenerator import HSP.XML hsp-0.10.0/src/HSP/0000755000000000000000000000000012240516336011773 5ustar0000000000000000hsp-0.10.0/src/HSP/Monad.hs0000644000000000000000000001247712240516336013400 0ustar0000000000000000{-# LANGUAGE FlexibleInstances, GeneralizedNewtypeDeriving, OverlappingInstances, MultiParamTypeClasses, TypeFamilies #-} module HSP.Monad where import Control.Applicative (Applicative, Alternative, (<$>)) import Control.Monad (MonadPlus) import Control.Monad.Cont (MonadCont) import Control.Monad.Error (MonadError) import Control.Monad.Fix (MonadFix) import Control.Monad.Reader (MonadReader) import Control.Monad.Writer (MonadWriter) import Control.Monad.State (MonadState) import Control.Monad.Trans (MonadIO, MonadTrans(lift)) import Data.String (fromString) import qualified Data.Text as Strict import Data.Text.Lazy (Text) import qualified Data.Text.Lazy as Lazy import HSP.XMLGenerator (AppendChild(..), Attr(..), EmbedAsAttr(..), EmbedAsChild(..), IsName(..), SetAttr(..), XMLGen(..), XMLGenerator) import HSP.XML (Attribute(..), XML(..), AttrValue(..), pAttrVal, pcdata) newtype HSPT xml m a = HSPT { unHSPT :: m a } deriving (Functor, Applicative, Alternative, Monad, MonadPlus, MonadIO, MonadReader r, MonadWriter w, MonadState s, MonadCont, MonadError e, MonadFix) instance MonadTrans (HSPT xml) where lift = HSPT instance (Functor m, Monad m) => (XMLGen (HSPT XML m)) where type XMLType (HSPT XML m) = XML type StringType (HSPT XML m) = Text newtype ChildType (HSPT XML m) = HSPChild { unHSPChild :: XML } newtype AttributeType (HSPT XML m) = HSPAttr { unHSPAttr :: Attribute } genElement n attrs childr = do as <- (map unHSPAttr . concat) <$> sequence attrs cs <- (map unHSPChild . concat) <$> sequence childr return (Element n as cs) xmlToChild = HSPChild pcdataToChild str = HSPChild (pcdata str) instance (Functor m, Monad m) => SetAttr (HSPT XML m) XML where setAll xml hats = do attrs <- hats case xml of CDATA _ _ -> return xml Element n as cs -> return $ Element n (foldr (:) as (map unHSPAttr attrs)) cs instance (Functor m, Monad m) => AppendChild (HSPT XML m) XML where appAll xml children = do chs <- children case xml of CDATA _ _ -> return xml Element n as cs -> return $ Element n as (cs ++ (map unHSPChild chs)) instance (Functor m, Monad m) => EmbedAsChild (HSPT XML m) XML where asChild = return . (:[]) . HSPChild instance (Functor m, Monad m) => EmbedAsChild (HSPT XML m) [XML] where asChild = return . map HSPChild instance (Functor m, Monad m) => EmbedAsChild (HSPT XML m) String where asChild = return . (:[]) . HSPChild . pcdata . Lazy.pack instance (Functor m, Monad m) => EmbedAsChild (HSPT XML m) Text where asChild = return . (:[]) . HSPChild . pcdata instance (Functor m, Monad m) => EmbedAsChild (HSPT XML m) Strict.Text where asChild = return . (:[]) . HSPChild . pcdata . Lazy.fromStrict instance (Functor m, Monad m) => EmbedAsChild (HSPT XML m) Char where asChild = return . (:[]) . pcdataToChild . Lazy.singleton instance (Functor m, Monad m) => EmbedAsChild (HSPT XML m) () where asChild = return . const [] instance (Monad m, Functor m) => EmbedAsAttr (HSPT XML m) Attribute where asAttr = return . (:[]) . HSPAttr instance (Functor m, Monad m) => EmbedAsAttr (HSPT XML m) (Attr Text Text) where asAttr (n := v) = asAttr $ MkAttr (toName n, (pAttrVal v)) instance (Functor m, Monad m) => EmbedAsAttr (HSPT XML m) (Attr Strict.Text Text) where asAttr (n := v) = asAttr $ MkAttr (toName n, (pAttrVal v)) instance (Functor m, Monad m) => EmbedAsAttr (HSPT XML m) (Attr Strict.Text Strict.Text) where asAttr (n := v) = asAttr $ MkAttr (toName n, (pAttrVal $ Lazy.fromStrict v)) instance (Functor m, Monad m) => EmbedAsAttr (HSPT XML m) (Attr Text Strict.Text) where asAttr (n := v) = asAttr $ MkAttr (toName n, (pAttrVal $ Lazy.fromStrict v)) instance (Monad m, Functor m) => EmbedAsAttr (HSPT XML m) (Attr Text Char) where asAttr (n := c) = asAttr (n := Lazy.singleton c) instance (Monad m, Functor m) => EmbedAsAttr (HSPT XML m) (Attr Strict.Text Char) where asAttr (n := c) = asAttr $ MkAttr (toName n, pAttrVal $ Lazy.singleton c) instance (Functor m, Monad m) => EmbedAsAttr (HSPT XML m) (Attr Text Bool) where asAttr (n := True) = asAttr $ MkAttr (toName n, pAttrVal $ fromString "true") asAttr (n := False) = asAttr $ MkAttr (toName n, pAttrVal $ fromString "false") instance (Functor m, Monad m) => EmbedAsAttr (HSPT XML m) (Attr Strict.Text Bool) where asAttr (n := True) = asAttr $ MkAttr (toName n, pAttrVal $ fromString "true") asAttr (n := False) = asAttr $ MkAttr (toName n, pAttrVal $ fromString "false") instance (Functor m, Monad m) => EmbedAsAttr (HSPT XML m) (Attr Text Int) where asAttr (n := i) = asAttr $ MkAttr (toName n, pAttrVal $ fromString (show i)) instance (Functor m, Monad m) => EmbedAsAttr (HSPT XML m) (Attr Strict.Text Int) where asAttr (n := i) = asAttr $ MkAttr (toName n, pAttrVal $ fromString (show i)) instance (Functor m, Monad m) => EmbedAsAttr (HSPT XML m) (Attr Text ()) where asAttr (n := ()) = asAttr $ MkAttr (toName n, NoValue) instance (Functor m, Monad m) => EmbedAsAttr (HSPT XML m) (Attr Strict.Text ()) where asAttr (n := ()) = asAttr $ MkAttr (toName n, NoValue) instance (Functor m, Monad m) => XMLGenerator (HSPT XML m) hsp-0.10.0/src/HSP/XMLGenerator.hs0000644000000000000000000002247712240516336014652 0ustar0000000000000000{-# LANGUAGE CPP, TypeFamilies, MultiParamTypeClasses, FunctionalDependencies, FlexibleContexts, FlexibleInstances, UndecidableInstances, TypeSynonymInstances, GeneralizedNewtypeDeriving #-} ----------------------------------------------------------------------------- -- | -- Module : HSX.XMLGenerator -- Copyright : (c) Niklas Broberg 2008-2013 -- License : BSD-style (see the file LICENSE.txt) -- -- Maintainer : Niklas Broberg -- Stability : experimental -- Portability : requires newtype deriving and MPTCs with fundeps and type families -- -- The class and monad transformer that forms the basis of the literal XML -- syntax translation. Literal tags will be translated into functions of -- the GenerateXML class, and any instantiating monads with associated XML -- types can benefit from that syntax. ----------------------------------------------------------------------------- module HSP.XMLGenerator where import Control.Applicative (Applicative, Alternative) import Control.Monad.Trans (MonadTrans(lift), MonadIO) import Control.Monad.Cont (MonadCont) import Control.Monad.Error (MonadError) import Control.Monad.Reader(MonadReader) import Control.Monad.Writer(MonadWriter) import Control.Monad.State (MonadState) import Control.Monad.RWS (MonadRWS) import Control.Monad (MonadPlus(..),liftM) import Data.Text.Lazy (Text) import qualified Data.Text.Lazy as Text import qualified Data.Text as Strict ---------------------------------------------- -- General XML Generation -- | The monad transformer that allows a monad to generate XML values. newtype XMLGenT m a = XMLGenT (m a) deriving (Applicative, Alternative, Monad, Functor, MonadIO, MonadPlus, MonadWriter w, MonadReader r, MonadState s, MonadRWS r w s, MonadCont, MonadError e) -- | un-lift. unXMLGenT :: XMLGenT m a -> m a unXMLGenT (XMLGenT ma) = ma -- | map the inner monad mapXMLGenT :: (m a -> n b) -> XMLGenT m a -> XMLGenT n b mapXMLGenT f (XMLGenT m) = XMLGenT (f m) instance MonadTrans XMLGenT where lift = XMLGenT type Name a = (Maybe a, a) -- | Generate XML values in some XMLGenerator monad. class Monad m => XMLGen m where type XMLType m type StringType m data ChildType m data AttributeType m genElement :: Name (StringType m) -> [XMLGenT m [AttributeType m]] -> [XMLGenT m [ChildType m]] -> XMLGenT m (XMLType m) genEElement :: Name (StringType m) -> [XMLGenT m [AttributeType m]] -> XMLGenT m (XMLType m) genEElement n ats = genElement n ats [] xmlToChild :: XMLType m -> ChildType m pcdataToChild :: StringType m -> ChildType m -- | Type synonyms to avoid writing out the XMLnGenT all the time type GenXML m = XMLGenT m (XMLType m) type GenXMLList m = XMLGenT m [XMLType m] type GenChild m = XMLGenT m (ChildType m) type GenChildList m = XMLGenT m [ChildType m] type GenAttribute m = XMLGenT m (AttributeType m) type GenAttributeList m = XMLGenT m [AttributeType m] -- | Embed values as child nodes of an XML element. The parent type will be clear -- from the context so it is not mentioned. class XMLGen m => EmbedAsChild m c where asChild :: c -> GenChildList m #if __GLASGOW_HASKELL__ >= 610 instance (EmbedAsChild m c, m ~ n) => EmbedAsChild m (XMLGenT n c) where asChild m = asChild =<< m #else instance (EmbedAsChild m c, TypeCastM m1 m) => EmbedAsChild m (XMLGenT m1 c) where asChild (XMLGenT m1a) = do a <- XMLGenT $ typeCastM m1a asChild a #endif instance EmbedAsChild m c => EmbedAsChild m [c] where asChild = liftM concat . mapM asChild instance XMLGen m => EmbedAsChild m (ChildType m) where asChild = return . return #if __GLASGOW_HASKELL__ >= 610 instance (XMLGen m, XMLType m ~ x) => EmbedAsChild m x where #else instance (XMLGen m) => EmbedAsChild m (XMLType m) where #endif asChild = return . return . xmlToChild instance XMLGen m => EmbedAsChild m () where asChild _ = return [] data Attr n a = n := a deriving Show -- | Similarly embed values as attributes of an XML element. class XMLGen m => EmbedAsAttr m a where asAttr :: a -> GenAttributeList m instance (XMLGen m, EmbedAsAttr m a) => EmbedAsAttr m (XMLGenT m a) where asAttr ma = ma >>= asAttr instance (EmbedAsAttr m (Attr a v), TypeCastM m1 m) => EmbedAsAttr m (Attr a (XMLGenT m1 v)) where asAttr (a := (XMLGenT m1a)) = do v <- XMLGenT $ typeCastM m1a asAttr (a := v) instance XMLGen m => EmbedAsAttr m (AttributeType m) where asAttr = return . return instance EmbedAsAttr m a => EmbedAsAttr m [a] where asAttr = liftM concat . mapM asAttr -- This is certainly true, but we want the various generators to explicitly state it, -- in order to get the error messages right. class ( XMLGen m , SetAttr m (XMLType m) , AppendChild m (XMLType m) , EmbedAsChild m (XMLType m) , EmbedAsChild m [XMLType m] , EmbedAsChild m Text , EmbedAsChild m Char -- for overlap purposes , EmbedAsChild m () , EmbedAsAttr m (Attr Text Text) , EmbedAsAttr m (Attr Text Int) , EmbedAsAttr m (Attr Text Bool) ) => XMLGenerator m ------------------------------------- -- Setting attributes -- | Set attributes on XML elements class XMLGen m => SetAttr m elem where setAttr :: elem -> GenAttribute m -> GenXML m setAll :: elem -> GenAttributeList m -> GenXML m setAttr e a = setAll e $ liftM return a -- | prepend @attr@ to the list of attributes for the @elem@ (<@), set :: (SetAttr m elem, EmbedAsAttr m attr) => elem -> attr -> GenXML m set xml attr = setAll xml (asAttr attr) (<@) = set -- | prepend the list of @attr@ to the attributes for the @elem@ (<<@) :: (SetAttr m elem, EmbedAsAttr m attr) => elem -> [attr] -> GenXML m xml <<@ ats = setAll xml (liftM concat $ mapM asAttr ats) instance (TypeCastM m1 m, SetAttr m x) => SetAttr m (XMLGenT m1 x) where setAll (XMLGenT m1x) ats = (XMLGenT $ typeCastM m1x) >>= (flip setAll) ats ------------------------------------- -- Appending children class XMLGen m => AppendChild m elem where appChild :: elem -> GenChild m -> GenXML m appAll :: elem -> GenChildList m -> GenXML m appChild e c = appAll e $ liftM return c -- | append child to the children of @elem@ (<:), app :: (AppendChild m elem, EmbedAsChild m c) => elem -> c -> GenXML m app xml c = appAll xml $ asChild c (<:) = app -- | append children to the children of @elem@ (<<:) :: (AppendChild m elem, EmbedAsChild m c) => elem -> [c] -> GenXML m xml <<: chs = appAll xml (liftM concat $ mapM asChild chs) instance (AppendChild m x, TypeCastM m1 m) => AppendChild m (XMLGenT m1 x) where appAll (XMLGenT m1x) chs = (XMLGenT $ typeCastM m1x) >>= (flip appAll) chs ------------------------------------- -- Names -- | Names can be simple or qualified with a domain. We want to conveniently -- use both simple strings or pairs wherever a 'Name' is expected. class Show n => IsName n s where toName :: n -> Name s -- | Strings can represent names, meaning a simple name with no domain. instance IsName String String where toName s = (Nothing, s) -- | Strings can represent names, meaning a simple name with no domain. instance IsName String Text where toName s = (Nothing, Text.pack s) -- | Names can represent names, of course. instance (Show a) => IsName (Name a) a where toName = id -- | Pairs of strings can represent names, meaning a name qualified with a domain. instance IsName (String, String) Text where toName (ns, s) = (Just $ Text.pack ns, Text.pack s) -- | Strings can represent names, meaning a simple name with no domain. instance IsName Text Text where toName s = (Nothing, s) -- | strings can represent names, meaning a simple name with no domain. instance IsName Strict.Text Text where toName s = (Nothing, Text.fromStrict s) -- | Pairs of strings can represent names, meaning a name qualified with a domain. instance IsName (Text, Text) Text where toName (ns, s) = (Just $ ns, s) -- | Pairs of strings can represent names, meaning a name qualified with a domain. instance IsName (Strict.Text, Strict.Text) Text where toName (ns, s) = (Just $ Text.fromStrict ns, Text.fromStrict s) --------------------------------------- -- TypeCast, in lieu of ~ constraints -- literally lifted from the HList library class TypeCast a b | a -> b, b -> a where typeCast :: a -> b class TypeCast' t a b | t a -> b, t b -> a where typeCast' :: t->a->b class TypeCast'' t a b | t a -> b, t b -> a where typeCast'' :: t->a->b instance TypeCast' () a b => TypeCast a b where typeCast x = typeCast' () x instance TypeCast'' t a b => TypeCast' t a b where typeCast' = typeCast'' instance TypeCast'' () a a where typeCast'' _ x = x class TypeCastM ma mb | ma -> mb, mb -> ma where typeCastM :: ma x -> mb x class TypeCastM' t ma mb | t ma -> mb, t mb -> ma where typeCastM' :: t -> ma x -> mb x class TypeCastM'' t ma mb | t ma -> mb, t mb -> ma where typeCastM'' :: t -> ma x -> mb x instance TypeCastM' () ma mb => TypeCastM ma mb where typeCastM mx = typeCastM' () mx instance TypeCastM'' t ma mb => TypeCastM' t ma mb where typeCastM' = typeCastM'' instance TypeCastM'' () ma ma where typeCastM'' _ x = x hsp-0.10.0/src/HSP/XML.hs0000644000000000000000000001220112240516336012763 0ustar0000000000000000----------------------------------------------------------------------------- -- | -- Module : HSP.XML -- Copyright : (c) Niklas Broberg 2008-2013 -- License : BSD-style (see the file LICENSE.txt) -- -- Maintainer : Niklas Broberg, niklas.broberg@gmail.com -- Stability : experimental -- Portability : Haskell 98 -- -- Datatypes and type classes comprising the basic model behind -- the scenes of Haskell Server Pages tags. ----------------------------------------------------------------------------- module HSP.XML ( -- * The 'XML' datatype XML(..), XMLMetaData(..), Namespace, NSName, Attributes, Children, pcdata, cdata, -- * The Attribute type Attribute(..), AttrValue(..), attrVal, pAttrVal, -- * Functions renderXML, isElement, isCDATA, fromStringLit ) where import Data.List (intersperse) import Data.Monoid ((<>), mconcat) import Data.String (fromString) import Data.Text.Lazy.Builder (Builder, fromLazyText, singleton, toLazyText) import Data.Text.Lazy (Text) import qualified Data.Text.Lazy as Text import HSP.XML.PCDATA (escape) --------------------------------------------------------------- -- fromStringLit fromStringLit :: String -> Text fromStringLit = Text.pack --------------------------------------------------------------- -- Namespace/NSName type Namespace = Maybe Text type NSName = (Namespace, Text) --------------------------------------------------------------- -- Attributes newtype Attribute = MkAttr (NSName, AttrValue) deriving Show -- | Represents an attribue value. data AttrValue = Value Bool Text | NoValue -- fromStringLit :: String -> Text -- fromStringLit = Text.pack -- | Create an attribue value from a string. attrVal, pAttrVal :: Text -> AttrValue attrVal = Value False pAttrVal = Value True instance Show AttrValue where show (Value _ txt) = Text.unpack txt show NoValue = "" type Attributes = [Attribute] --------------------------------------------------------------- -- XML -- | The XML datatype representation. Is either an Element or CDATA. data XML = Element NSName Attributes Children | CDATA Bool Text deriving Show type Children = [XML] -- | Embeds a string as a CDATA XML value. cdata , pcdata :: Text -> XML cdata = CDATA False pcdata = CDATA True -- | Test whether an XML value is an Element or CDATA isElement, isCDATA :: XML -> Bool isElement (Element {}) = True isElement _ = False isCDATA = not . isElement --------------------------------------------------------------- -- XMLMetaData -- |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, Text) -- ^ (show doctype when rendering, DOCTYPE string) , contentType :: Text , preferredRenderer :: XML -> Builder } ------------------------------------------------------------------ -- Rendering data TagType = Open | Close | Single renderTag :: TagType -> Int -> NSName -> Attributes -> Builder renderTag typ n name attrs = let (start,end) = case typ of Open -> (singleton '<', singleton '>') Close -> (fromString "') Single -> (singleton '<', fromString "/>") nam = showNSName name as = renderAttrs attrs in mconcat [start, nam, as, end] where renderAttrs :: Attributes -> Builder renderAttrs [] = nl renderAttrs attrs' = singleton ' ' <> mconcat ats <> nl where ats = intersperse (singleton ' ') $ fmap renderAttr attrs' renderAttr :: Attribute -> Builder renderAttr (MkAttr (nam, (Value needsEscape val))) = showNSName nam <> singleton '=' <> renderAttrVal (if needsEscape then escape val else fromLazyText val) renderAttr (MkAttr (nam, NoValue)) = showNSName nam <> singleton '=' <> renderAttrVal (fromString "") renderAttrVal :: Builder -> Builder renderAttrVal txt = singleton '\"' <> txt <> singleton '\"' showNSName (Nothing, s) = fromLazyText s showNSName (Just d, s) = fromLazyText d <> singleton ':' <> fromLazyText s nl = singleton '\n' <> fromString (replicate n ' ') renderXML' :: Int -> XML -> Builder renderXML' _ (CDATA needsEscape cd) = if needsEscape then escape cd else fromLazyText cd renderXML' n (Element name attrs []) = renderTag Single n name attrs renderXML' n (Element name attrs children) = let open = renderTag Open n name attrs cs = renderChildren n children close = renderTag Close n name [] in open <> cs <> close where renderChildren :: Int -> Children -> Builder renderChildren n' cs = mconcat $ map (renderXML' (n'+2)) cs -- TODO: indents are incorrectly calculated -- | Pretty-prints XML values. renderXML :: XML -> Text renderXML xml = toLazyText $ renderXML' 0 xml hsp-0.10.0/src/HSP/HTML4.hs0000644000000000000000000001531312240516336013162 0ustar0000000000000000{-# LANGUAGE OverloadedStrings #-} ----------------------------------------------------------------------------- -- | -- Module : HSP.HTML4 -- Copyright : (c) Niklas Broberg, Jeremy Shaw 2008-2012 -- License : BSD-style (see the file LICENSE.txt) -- -- Maintainer : Niklas Broberg, niklas.broberg@gmail.com -- Stability : experimental -- Portability : Haskell 98 -- -- Attempt to render XHTML as well-formed HTML 4.01: -- -- 1. no short tags are used, e.g., \\<\/script\> instead of \