packages feed

heist 0.11.0.1 → 0.11.1

raw patch · 4 files changed

+180/−61 lines, 4 filesdep ~blaze-htmldep ~xmlhtmlPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: blaze-html, xmlhtml

API changes (from Hackage documentation)

+ Heist.Compiled: namespaceSplices :: Text -> [(Text, a)] -> [(Text, a)]
+ Heist.Compiled: prefixSplices :: Text -> Text -> [(Text, a)] -> [(Text, a)]
+ Heist.Compiled: repromise :: Monad n => (a -> n b) -> [(d, Promise b -> Splice n)] -> [(d, Promise a -> Splice n)]
+ Heist.Compiled: repromise' :: Monad n => (a -> n b) -> (Promise b -> Splice n) -> Promise a -> Splice n
+ Heist.Compiled: repromiseMay :: Monad n => (a -> n (Maybe b)) -> [(d, Promise b -> Splice n)] -> [(d, Promise a -> Splice n)]
+ Heist.Compiled: repromiseMay' :: Monad n => (a -> n (Maybe b)) -> (Promise b -> Splice n) -> Promise a -> Splice n
+ Heist.Compiled: runAttributesRaw :: (Monad m, Monad n) => [(Text, Text)] -> HeistT n m (RuntimeSplice n [(Text, Text)])
- Heist.Compiled: adjustPromise :: Monad m => Promise a -> (a -> a) -> RuntimeSplice m ()
+ Heist.Compiled: adjustPromise :: Monad n => Promise a -> (a -> a) -> RuntimeSplice n ()
- Heist.Compiled: codeGen :: Monad m => DList (Chunk m) -> RuntimeSplice m Builder
+ Heist.Compiled: codeGen :: Monad n => DList (Chunk n) -> RuntimeSplice n Builder
- Heist.Compiled: getPromise :: Monad m => Promise a -> RuntimeSplice m a
+ Heist.Compiled: getPromise :: Monad n => Promise a -> RuntimeSplice n a
- Heist.Compiled: mapInputPromise :: Monad m => (a -> b) -> (Promise b -> Splice m) -> Promise a -> Splice m
+ Heist.Compiled: mapInputPromise :: Monad n => (a -> b) -> (Promise b -> Splice n) -> Promise a -> Splice n
- Heist.Compiled: promiseChildren :: Monad m => HeistT m IO (RuntimeSplice m Builder)
+ Heist.Compiled: promiseChildren :: Monad n => HeistT n IO (RuntimeSplice n Builder)
- Heist.Compiled: pureSplice :: Monad m => (a -> Builder) -> Promise a -> Splice m
+ Heist.Compiled: pureSplice :: Monad n => (a -> Builder) -> Promise a -> Splice n
- Heist.Compiled: pureSplices :: Monad m => [(d, a -> Builder)] -> [(d, Promise a -> Splice m)]
+ Heist.Compiled: pureSplices :: Monad n => [(d, a -> Builder)] -> [(d, Promise a -> Splice n)]
- Heist.Compiled: putPromise :: Monad m => Promise a -> a -> RuntimeSplice m ()
+ Heist.Compiled: putPromise :: Monad n => Promise a -> a -> RuntimeSplice n ()
- Heist.Compiled: yieldLater :: Monad m => m Builder -> DList (Chunk m)
+ Heist.Compiled: yieldLater :: Monad n => n Builder -> DList (Chunk n)
- Heist.Compiled: yieldPure :: Builder -> DList (Chunk m)
+ Heist.Compiled: yieldPure :: Builder -> DList (Chunk n)
- Heist.Compiled: yieldPureText :: Text -> DList (Chunk m)
+ Heist.Compiled: yieldPureText :: Text -> DList (Chunk n)
- Heist.Compiled: yieldRuntime :: RuntimeSplice m Builder -> DList (Chunk m)
+ Heist.Compiled: yieldRuntime :: RuntimeSplice n Builder -> DList (Chunk n)
- Heist.Compiled: yieldRuntimeEffect :: Monad m => RuntimeSplice m () -> DList (Chunk m)
+ Heist.Compiled: yieldRuntimeEffect :: Monad n => RuntimeSplice n () -> DList (Chunk n)
- Heist.Compiled: yieldRuntimeText :: Monad m => RuntimeSplice m Text -> DList (Chunk m)
+ Heist.Compiled: yieldRuntimeText :: Monad n => RuntimeSplice n Text -> DList (Chunk n)

Files

heist.cabal view
@@ -1,5 +1,5 @@ name:           heist-version:        0.11.0.1+version:        0.11.1 synopsis:       An Haskell template system supporting both HTML5 and XML. description:     Heist is a powerful template system that supports both HTML5 and XML.@@ -141,7 +141,7 @@     attoparsec                 >= 0.10    && < 0.11,     base                       >= 4       && < 5,     blaze-builder              >= 0.2     && < 0.4,-    blaze-html                 >= 0.4     && < 0.6,+    blaze-html                 >= 0.4     && < 0.7,     bytestring                 >= 0.9     && < 0.11,     containers                 >= 0.2     && < 0.6,     directory                  >= 1.1     && < 1.3,@@ -157,7 +157,7 @@     time                       >= 1.1     && < 1.5,     unordered-containers       >= 0.1.4   && < 0.3,     vector                     >= 0.9     && < 0.11,-    xmlhtml                    >= 0.1.6   && < 0.3+    xmlhtml                    >= 0.2.1   && < 0.3    if impl(ghc >= 6.12.0)     ghc-options: -Wall -fwarn-tabs -funbox-strict-fields -O2
src/Heist/Compiled.hs view
@@ -23,6 +23,8 @@   -- * Functions for manipulating lists of compiled splices   , mapSnd   , applySnd+  , prefixSplices+  , namespaceSplices   , textSplices   , nodeSplices   , pureSplices@@ -30,6 +32,10 @@   , nodeSplice   , pureSplice   , mapInputPromise+  , repromise+  , repromiseMay+  , repromise'+  , repromiseMay'   , defer   , deferMany   , withSplices@@ -66,6 +72,7 @@   , runNodeList   , runNode   , runAttributes+  , runAttributesRaw   , callTemplate    ) where
src/Heist/Compiled/Internal.hs view
@@ -21,6 +21,7 @@ import           Data.DList                      (DList) import qualified Data.DList                      as DL import qualified Data.HashMap.Strict             as H+import qualified Data.HashSet                    as S import qualified Data.HeterogeneousEnvironment   as HE import           Data.Maybe import           Data.Text                       (Text)@@ -29,6 +30,7 @@ import qualified Data.Vector                     as V import           Prelude                         hiding (catch) import qualified Text.XmlHtml                    as X+import qualified Text.XmlHtml.HTML.Meta          as X ------------------------------------------------------------------------------ import           Heist.Common import           Heist.Types@@ -86,7 +88,7 @@  ------------------------------------------------------------------------------ -- | Returns a runtime computation that simply renders the node's children.-promiseChildren :: Monad m => HeistT m IO (RuntimeSplice m Builder)+promiseChildren :: Monad n => HeistT n IO (RuntimeSplice n Builder) promiseChildren = liftM codeGen runChildren {-# INLINE promiseChildren #-} @@ -150,14 +152,14 @@ -- | Yields a pure Builder known at load time.  You should use this and -- 'yieldPureText' as much as possible to maximize the parts of your page that -- can be compiled to static ByteStrings.-yieldPure :: Builder -> DList (Chunk m)+yieldPure :: Builder -> DList (Chunk n) yieldPure = DL.singleton . Pure . toByteString {-# INLINE yieldPure #-}   ------------------------------------------------------------------------------ -- | Yields a runtime action that returns a builder.-yieldRuntime :: RuntimeSplice m Builder -> DList (Chunk m)+yieldRuntime :: RuntimeSplice n Builder -> DList (Chunk n) yieldRuntime = DL.singleton . RuntimeHtml {-# INLINE yieldRuntime #-} @@ -165,7 +167,7 @@ ------------------------------------------------------------------------------ -- | Yields a runtime action that returns no value and is only needed for its -- side effect.-yieldRuntimeEffect :: Monad m => RuntimeSplice m () -> DList (Chunk m)+yieldRuntimeEffect :: Monad n => RuntimeSplice n () -> DList (Chunk n) yieldRuntimeEffect = DL.singleton . RuntimeAction {-# INLINE yieldRuntimeEffect #-} @@ -173,14 +175,14 @@ ------------------------------------------------------------------------------ -- | A convenience wrapper around yieldPure for working with Text.  Roughly -- equivalent to 'textSplice' from Heist.Interpreted.-yieldPureText :: Text -> DList (Chunk m)+yieldPureText :: Text -> DList (Chunk n) yieldPureText = DL.singleton . pureTextChunk {-# INLINE yieldPureText #-}   ------------------------------------------------------------------------------ -- | Convenience wrapper around yieldRuntime allowing you to work with Text.-yieldRuntimeText :: Monad m => RuntimeSplice m Text -> DList (Chunk m)+yieldRuntimeText :: Monad n => RuntimeSplice n Text -> DList (Chunk n) yieldRuntimeText = yieldRuntime .  liftM fromText {-# INLINE yieldRuntimeText #-} @@ -188,7 +190,7 @@ ------------------------------------------------------------------------------ -- | This lets you turn a plain runtime monad function returning a Builder -- into a compiled splice.-yieldLater :: Monad m => m Builder -> DList (Chunk m)+yieldLater :: Monad n => n Builder -> DList (Chunk n) yieldLater = yieldRuntime . RuntimeSplice . lift {-# INLINE yieldLater #-} @@ -250,9 +252,9 @@   -------------------------------------------------------------------------------compileTemplates' :: Monad m-                  => HeistState m-                  -> IO (H.HashMap TPath ([Chunk m], MIMEType))+compileTemplates' :: Monad n+                  => HeistState n+                  -> IO (H.HashMap TPath ([Chunk n], MIMEType)) compileTemplates' hs = do     ctm <- foldM runOne H.empty tpathDocfiles     return $! ctm@@ -268,7 +270,7 @@  ------------------------------------------------------------------------------ -- | Consolidate consecutive Pure Chunks.-consolidate :: (Monad m) => DList (Chunk m) -> [Chunk m]+consolidate :: (Monad n) => DList (Chunk n) -> [Chunk n] consolidate = consolidateL . DL.toList   where     consolidateL []     = []@@ -306,7 +308,7 @@ -- | Given a list of output chunks, consolidate turns consecutive runs of -- @Pure Html@ values into maximally-efficient pre-rendered strict -- 'ByteString' chunks.-codeGen :: Monad m => DList (Chunk m) -> RuntimeSplice m Builder+codeGen :: Monad n => DList (Chunk n) -> RuntimeSplice n Builder codeGen l = V.foldr mappend mempty $!             V.map toAct $! V.fromList $! consolidate l   where@@ -385,34 +387,6 @@   --------------------------------------------------------------------------------- |-parseAtt :: Monad n => (Text, Text) -> HeistT n IO (DList (Chunk n))-parseAtt (k,v) = do-    mas <- getsHS (H.lookup k . _attrSpliceMap)-    maybe doInline (return . doAttrSplice) mas--  where-    cvt (Literal x) = return $ yieldPureText x-    cvt (Ident x) =-        localParamNode (const $ X.Element x [] []) $ getAttributeSplice x--    -- Handles inline parsing of $() splice syntax in attributes-    doInline = do-        let ast = case AP.feed (AP.parse attParser v) "" of-                    (AP.Done _ res) -> res-                    (AP.Fail _ _ _) -> []-                    (AP.Partial _ ) -> []-        chunks <- mapM cvt ast-        let value = DL.concat chunks-        return $ attrToChunk k value--    -- Handles attribute splices-    doAttrSplice splice = DL.singleton $ RuntimeHtml $ do-        res <- splice v-        return $ mconcat $ map attrToBuilder res--    ------------------------------------------------------------------------------- -- | Given a 'X.Node' in the DOM tree, produces a \"runtime splice\" that will -- generate html at runtime. compileNode :: Monad n => X.Node -> Splice n@@ -429,7 +403,7 @@          childHtml <- runNodeList ch -        return $! if null (DL.toList childHtml)+        return $! if null (DL.toList childHtml) && nm `S.member` X.voidTags           then DL.concat [ DL.singleton $! pureTextChunk $! tag0                          , DL.concat compiledAttrs                          , DL.singleton $! pureTextChunk " />"@@ -444,6 +418,34 @@   ------------------------------------------------------------------------------+-- |+parseAtt :: Monad n => (Text, Text) -> HeistT n IO (DList (Chunk n))+parseAtt (k,v) = do+    mas <- getsHS (H.lookup k . _attrSpliceMap)+    maybe doInline (return . doAttrSplice) mas++  where+    cvt (Literal x) = return $ yieldPureText x+    cvt (Ident x) =+        localParamNode (const $ X.Element x [] []) $ getAttributeSplice x++    -- Handles inline parsing of $() splice syntax in attributes+    doInline = do+        let ast = case AP.feed (AP.parse attParser v) "" of+                    (AP.Done _ res) -> res+                    (AP.Fail _ _ _) -> []+                    (AP.Partial _ ) -> []+        chunks <- mapM cvt ast+        let value = DL.concat chunks+        return $ attrToChunk k value++    -- Handles attribute splices+    doAttrSplice splice = DL.singleton $ RuntimeHtml $ do+        res <- splice v+        return $ mconcat $ map attrToBuilder res+++------------------------------------------------------------------------------ -- | Performs splice processing on a list of attributes.  This is useful in -- situations where you need to stop recursion, but still run splice -- processing on the node's attributes.@@ -451,6 +453,22 @@ runAttributes = mapM parseAtt  +------------------------------------------------------------------------------+-- | Performs splice processing on a list of attributes.  This is useful in+-- situations where you need to stop recursion, but still run splice+-- processing on the node's attributes.+runAttributesRaw :: (Monad m, Monad n)+                 => [(Text, Text)]+                 -> HeistT n m (RuntimeSplice n [(Text, Text)])+runAttributesRaw attrs = do+    arrs <- mapM runSingle attrs+    return $ liftM concat $ sequence arrs+  where+    runSingle p@(k,v) = do+        mas <- getsHS (H.lookup k . _attrSpliceMap)+        return $ maybe (return [p]) ($v) mas++ attrToChunk :: Text -> DList (Chunk n) -> DList (Chunk n) attrToChunk !k !v = do     DL.concat@@ -490,7 +508,7 @@  ------------------------------------------------------------------------------ -- | Gets the result of a promised runtime computation.-getPromise :: (Monad m) => Promise a -> RuntimeSplice m a+getPromise :: (Monad n) => Promise a -> RuntimeSplice n a getPromise (Promise k) = do     mb <- gets (HE.lookup k)     return $ fromMaybe e mb@@ -503,14 +521,14 @@  ------------------------------------------------------------------------------ -- | Adds a promise to the runtime splice context.-putPromise :: (Monad m) => Promise a -> a -> RuntimeSplice m ()+putPromise :: (Monad n) => Promise a -> a -> RuntimeSplice n () putPromise (Promise k) x = modify (HE.insert k x) {-# INLINE putPromise #-}   ------------------------------------------------------------------------------ -- | Modifies a promise.-adjustPromise :: Monad m => Promise a -> (a -> a) -> RuntimeSplice m ()+adjustPromise :: Monad n => Promise a -> (a -> a) -> RuntimeSplice n () adjustPromise (Promise k) f = modify (HE.adjust f k) {-# INLINE adjustPromise #-} @@ -647,7 +665,7 @@     err = "callTemplate: "++(T.unpack $ T.decodeUtf8 nm)++(" does not exist")  -interpret :: Monad m => DList (Chunk m) -> m Builder+interpret :: Monad n => DList (Chunk n) -> n Builder interpret = flip evalStateT HE.empty . unRT . codeGen  @@ -656,44 +674,138 @@ ------------------------------------------------------------------------------  +------------------------------------------------------------------------------+-- | Helper function for transforming the second element of each of a list of+-- tuples. mapSnd :: (b -> c) -> [(d, b)] -> [(d, c)] mapSnd = map . second ++------------------------------------------------------------------------------+-- | The type signature says it all. applySnd :: a -> [(d, a -> b)] -> [(d, b)] applySnd a = mapSnd ($a) ++------------------------------------------------------------------------------+-- | Adds a prefix to the tag names for a list of splices.  If the existing+-- tag name is empty, then the new tag name is just the prefix.  Otherwise the+-- new tag name is the prefix followed by the separator followed by the+-- existing name.+prefixSplices :: Text -> Text -> [(Text, a)] -> [(Text, a)]+prefixSplices sep pre = map f+  where+    f (t,v) = if T.null t then (pre,v) else (T.concat [pre,sep,t], v)+++------------------------------------------------------------------------------+-- | 'prefixSplices' specialized to use a colon as separator in the style of+-- XML namespaces.+namespaceSplices :: Text -> [(Text, a)] -> [(Text, a)]+namespaceSplices = prefixSplices ":"+++------------------------------------------------------------------------------+-- | Converts pure text splices to pure Builder splices. textSplices :: [(Text, a -> Text)] -> [(Text, a -> Builder)] textSplices = mapSnd textSplice ++------------------------------------------------------------------------------+-- | Converts a pure text splice function to a pure Builder splice function. textSplice :: (a -> Text) -> a -> Builder textSplice f = fromText . f ++------------------------------------------------------------------------------+-- | Converts pure Node splices to pure Builder splices. nodeSplices :: [(Text, a -> [X.Node])] -> [(Text, a -> Builder)] nodeSplices = mapSnd nodeSplice ++------------------------------------------------------------------------------+-- | Converts a pure Node splice function to a pure Builder splice function. nodeSplice :: (a -> [X.Node]) -> a -> Builder nodeSplice f = X.renderHtmlFragment X.UTF8 . f -pureSplices :: Monad m => [(d, a -> Builder)] -> [(d, Promise a -> Splice m)]++------------------------------------------------------------------------------+-- | Converts pure Builder splices into monadic splice functions of a+-- 'Promise'.+pureSplices :: Monad n => [(d, a -> Builder)] -> [(d, Promise a -> Splice n)] pureSplices = mapSnd pureSplice -pureSplice :: Monad m => (a -> Builder) -> Promise a -> Splice m++------------------------------------------------------------------------------+-- | Converts a pure Builder splice function into a monadic splice function+-- that takes a 'Promise'.+pureSplice :: Monad n => (a -> Builder) -> Promise a -> Splice n pureSplice f p = do     return $ yieldRuntime $ do         a <- getPromise p         return $ f a -mapInputPromise :: Monad m++mapInputPromise :: Monad n                 => (a -> b)-                -> (Promise b -> Splice m)-                -> Promise a -> Splice m-mapInputPromise f g p1 = do+                -> (Promise b -> Splice n)+                -> Promise a -> Splice n+mapInputPromise f = repromise' (return . f)+{-# DEPRECATED mapInputPromise "Use repromise' instead."#-}+++------------------------------------------------------------------------------+-- | Change the promise type of a splice function.+repromise' :: Monad n+           => (a -> n b)+           -> (Promise b -> Splice n)+           -> Promise a -> Splice n+repromise' f pf p = do     p2 <- newEmptyPromise     let action = yieldRuntimeEffect $ do-        a <- getPromise p1-        putPromise p2 (f a)-    res <- g p2+            a <- getPromise p+            putPromise p2 =<< lift (f a)+    res <- pf p2     return $ action `mappend` res+++------------------------------------------------------------------------------+-- | Repromise a list of splices.+repromise :: Monad n+          => (a -> n b)+          -> [(d, Promise b -> Splice n)]+          -> [(d, Promise a -> Splice n)]+repromise f = mapSnd (repromise' f)+++------------------------------------------------------------------------------+-- | Change the promise type of a splice function with a function that might+-- fail.  If a Nothing is encountered, then the splice will generate no+-- output.+repromiseMay' :: Monad n+              => (a -> n (Maybe b))+              -> (Promise b -> Splice n)+              -> Promise a -> Splice n+repromiseMay' f pf p = do+    p2 <- newEmptyPromise+    action <- pf p2+    return $ yieldRuntime $ do+        a <- getPromise p+        mb <- lift (f a)+        case mb of+          Nothing -> return mempty+          Just b -> do+            putPromise p2 b+            codeGen action+++------------------------------------------------------------------------------+-- | repromiseMay' for a list of splices.+repromiseMay :: Monad n+             => (a -> n (Maybe b))+             -> [(d, Promise b -> Splice n)]+             -> [(d, Promise a -> Splice n)]+repromiseMay f = mapSnd (repromiseMay' f)   ------------------------------------------------------------------------------
test/heist-testsuite.cabal view
@@ -18,7 +18,7 @@     attoparsec                 >= 0.10    && < 0.11,     base                       >= 4       && < 5,     blaze-builder              >= 0.2     && < 0.4,-    blaze-html                 >= 0.4     && < 0.6,+    blaze-html                 >= 0.4     && < 0.7,     bytestring                 >= 0.9     && < 0.11,     containers                 >= 0.2     && < 0.6,     directory                  >= 1.1     && < 1.3,@@ -35,7 +35,7 @@     transformers               >= 0.2     && < 0.4,     unordered-containers       >= 0.1.4   && < 0.3,     vector                     >= 0.9     && < 0.11,-    xmlhtml                    >= 0.1.6   && < 0.3+    xmlhtml                    >= 0.2.1   && < 0.3     ghc-options: -O2 -Wall -fhpc -fwarn-tabs -funbox-strict-fields -threaded@@ -58,7 +58,7 @@     attoparsec                 >= 0.10    && < 0.11,     base                       >= 4       && < 5,     blaze-builder              >= 0.2     && < 0.4,-    blaze-html                 >= 0.4     && < 0.6,+    blaze-html                 >= 0.4     && < 0.7,     bytestring                 >= 0.9     && < 0.11,     containers                 >= 0.2     && < 0.6,     directory                  >= 1.1     && < 1.3,@@ -75,7 +75,7 @@     transformers               >= 0.2     && < 0.4,     unordered-containers       >= 0.1.4   && < 0.3,     vector                     >= 0.9     && < 0.11,-    xmlhtml                    >= 0.1.6   && < 0.3+    xmlhtml                    >= 0.2.1   && < 0.3    ghc-options: -O2 -Wall -fwarn-tabs -funbox-strict-fields -threaded                -fno-warn-unused-do-bind -rtsopts