{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE NoMonomorphismRestriction #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeSynonymInstances #-}
module Heist.Compiled.Internal where
import Blaze.ByteString.Builder
import Blaze.ByteString.Builder.Char.Utf8
import Control.Arrow
import Control.Exception
import Control.Monad
import Control.Monad.RWS.Strict
import Control.Monad.State.Strict
import qualified Data.Attoparsec.Text as AP
import Data.ByteString (ByteString)
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.Map.Syntax
import Data.Maybe
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
import qualified Data.Vector as V
import Text.Printf
import qualified Text.XmlHtml as X
import qualified Text.XmlHtml.HTML.Meta as X
#if !MIN_VERSION_base(4,8,0)
import Data.Foldable (Foldable)
#endif
import qualified Data.Foldable as Foldable
import Heist.Common
import Heist.Internal.Types.HeistState
type Splice n = HeistT n IO (DList (Chunk n))
runChildren :: Monad n => Splice n
runChildren :: forall (n :: * -> *). Monad n => Splice n
runChildren = [Node] -> Splice n
forall (n :: * -> *). Monad n => [Node] -> Splice n
runNodeList ([Node] -> Splice n) -> (Node -> [Node]) -> Node -> Splice n
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Node -> [Node]
X.childNodes (Node -> Splice n) -> HeistT n IO Node -> Splice n
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< HeistT n IO Node
forall (m :: * -> *) (n :: * -> *). Monad m => HeistT n m Node
getParamNode
{-# INLINE runChildren #-}
renderFragment :: Markup -> [X.Node] -> Builder
renderFragment :: Markup -> [Node] -> Builder
renderFragment Markup
markup [Node]
ns =
case Markup
markup of
Markup
Html -> Encoding -> [Node] -> Builder
X.renderHtmlFragment Encoding
X.UTF8 [Node]
ns
Markup
Xml -> Encoding -> [Node] -> Builder
X.renderXmlFragment Encoding
X.UTF8 [Node]
ns
pureTextChunk :: Text -> Chunk n
pureTextChunk :: forall (n :: * -> *). Text -> Chunk n
pureTextChunk Text
t = ByteString -> Chunk n
forall (m :: * -> *). ByteString -> Chunk m
Pure (ByteString -> Chunk n) -> ByteString -> Chunk n
forall a b. (a -> b) -> a -> b
$ Text -> ByteString
T.encodeUtf8 Text
t
{-# INLINE pureTextChunk #-}
yieldPure :: Builder -> DList (Chunk n)
yieldPure :: forall (n :: * -> *). Builder -> DList (Chunk n)
yieldPure = Chunk n -> DList (Chunk n)
forall a. a -> DList a
DL.singleton (Chunk n -> DList (Chunk n))
-> (Builder -> Chunk n) -> Builder -> DList (Chunk n)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Chunk n
forall (m :: * -> *). ByteString -> Chunk m
Pure (ByteString -> Chunk n)
-> (Builder -> ByteString) -> Builder -> Chunk n
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> ByteString
toByteString
{-# INLINE yieldPure #-}
yieldRuntime :: RuntimeSplice n Builder -> DList (Chunk n)
yieldRuntime :: forall (n :: * -> *). RuntimeSplice n Builder -> DList (Chunk n)
yieldRuntime = Chunk n -> DList (Chunk n)
forall a. a -> DList a
DL.singleton (Chunk n -> DList (Chunk n))
-> (RuntimeSplice n Builder -> Chunk n)
-> RuntimeSplice n Builder
-> DList (Chunk n)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RuntimeSplice n Builder -> Chunk n
forall (m :: * -> *). RuntimeSplice m Builder -> Chunk m
RuntimeHtml
{-# INLINE yieldRuntime #-}
yieldRuntimeEffect :: Monad n => RuntimeSplice n () -> DList (Chunk n)
yieldRuntimeEffect :: forall (n :: * -> *).
Monad n =>
RuntimeSplice n () -> DList (Chunk n)
yieldRuntimeEffect = Chunk n -> DList (Chunk n)
forall a. a -> DList a
DL.singleton (Chunk n -> DList (Chunk n))
-> (RuntimeSplice n () -> Chunk n)
-> RuntimeSplice n ()
-> DList (Chunk n)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RuntimeSplice n () -> Chunk n
forall (m :: * -> *). RuntimeSplice m () -> Chunk m
RuntimeAction
{-# INLINE yieldRuntimeEffect #-}
yieldPureText :: Text -> DList (Chunk n)
yieldPureText :: forall (n :: * -> *). Text -> DList (Chunk n)
yieldPureText = Chunk n -> DList (Chunk n)
forall a. a -> DList a
DL.singleton (Chunk n -> DList (Chunk n))
-> (Text -> Chunk n) -> Text -> DList (Chunk n)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Chunk n
forall (n :: * -> *). Text -> Chunk n
pureTextChunk
{-# INLINE yieldPureText #-}
yieldRuntimeText :: Monad n => RuntimeSplice n Text -> DList (Chunk n)
yieldRuntimeText :: forall (n :: * -> *).
Monad n =>
RuntimeSplice n Text -> DList (Chunk n)
yieldRuntimeText = RuntimeSplice n Builder -> DList (Chunk n)
forall (n :: * -> *). RuntimeSplice n Builder -> DList (Chunk n)
yieldRuntime (RuntimeSplice n Builder -> DList (Chunk n))
-> (RuntimeSplice n Text -> RuntimeSplice n Builder)
-> RuntimeSplice n Text
-> DList (Chunk n)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text -> Builder)
-> RuntimeSplice n Text -> RuntimeSplice n Builder
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM Text -> Builder
fromText
{-# INLINE yieldRuntimeText #-}
runNodeList :: Monad n => [X.Node] -> Splice n
runNodeList :: forall (n :: * -> *). Monad n => [Node] -> Splice n
runNodeList = (Node -> HeistT n IO (DList (Chunk n)))
-> [Node] -> HeistT n IO (DList (Chunk n))
forall (m :: * -> *) b a.
(Monad m, Monoid b) =>
(a -> m b) -> [a] -> m b
mapSplices Node -> HeistT n IO (DList (Chunk n))
forall (n :: * -> *). Monad n => Node -> Splice n
runNode
runDocumentFile :: Monad n
=> TPath
-> DocumentFile
-> Splice n
runDocumentFile :: forall (n :: * -> *). Monad n => TPath -> DocumentFile -> Splice n
runDocumentFile TPath
tpath DocumentFile
df = do
let markup :: Markup
markup = case DocumentFile -> Document
dfDoc DocumentFile
df of
X.XmlDocument Encoding
_ Maybe DocType
_ [Node]
_ -> Markup
Xml
X.HtmlDocument Encoding
_ Maybe DocType
_ [Node]
_ -> Markup
Html
(HeistState n -> HeistState n) -> HeistT n IO ()
forall (m :: * -> *) (n :: * -> *).
Monad m =>
(HeistState n -> HeistState n) -> HeistT n m ()
modifyHS (\HeistState n
hs -> HeistState n
hs { _curMarkup = markup })
let inDoctype :: Maybe DocType
inDoctype = Document -> Maybe DocType
X.docType (Document -> Maybe DocType) -> Document -> Maybe DocType
forall a b. (a -> b) -> a -> b
$ DocumentFile -> Document
dfDoc DocumentFile
df
[DocType] -> HeistT n IO ()
forall (m :: * -> *) (n :: * -> *).
Monad m =>
[DocType] -> HeistT n m ()
addDoctype ([DocType] -> HeistT n IO ()) -> [DocType] -> HeistT n IO ()
forall a b. (a -> b) -> a -> b
$ Maybe DocType -> [DocType]
forall a. Maybe a -> [a]
maybeToList Maybe DocType
inDoctype
(HeistState n -> HeistState n) -> HeistT n IO ()
forall (m :: * -> *) (n :: * -> *).
Monad m =>
(HeistState n -> HeistState n) -> HeistT n m ()
modifyHS (Maybe [Char] -> HeistState n -> HeistState n
forall (n :: * -> *). Maybe [Char] -> HeistState n -> HeistState n
setCurTemplateFile Maybe [Char]
curPath (HeistState n -> HeistState n)
-> (HeistState n -> HeistState n) -> HeistState n -> HeistState n
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TPath -> HeistState n -> HeistState n
forall (n :: * -> *). TPath -> HeistState n -> HeistState n
setCurContext TPath
tpath)
res <- [Node] -> Splice n
forall (n :: * -> *). Monad n => [Node] -> Splice n
runNodeList [Node]
nodes
dt <- getsHS (listToMaybe . _doctypes)
let enc = Document -> Encoding
X.docEncoding (Document -> Encoding) -> Document -> Encoding
forall a b. (a -> b) -> a -> b
$ DocumentFile -> Document
dfDoc DocumentFile
df
return $! (yieldPure (X.renderDocType enc dt) `mappend` res)
where
curPath :: Maybe [Char]
curPath = DocumentFile -> Maybe [Char]
dfFile DocumentFile
df
nodes :: [Node]
nodes = Document -> [Node]
X.docContent (Document -> [Node]) -> Document -> [Node]
forall a b. (a -> b) -> a -> b
$! DocumentFile -> Document
dfDoc DocumentFile
df
compileTemplate
:: Monad n
=> TPath
-> DocumentFile
-> HeistT n IO [Chunk n]
compileTemplate :: forall (n :: * -> *).
Monad n =>
TPath -> DocumentFile -> HeistT n IO [Chunk n]
compileTemplate TPath
tpath DocumentFile
df = do
!chunks <- TPath -> DocumentFile -> Splice n
forall (n :: * -> *). Monad n => TPath -> DocumentFile -> Splice n
runDocumentFile TPath
tpath DocumentFile
df
return $! consolidate chunks
compileTemplates
:: Monad n
=> (TPath -> Bool)
-> HeistState n
-> IO (Either [String] (HeistState n))
compileTemplates :: forall (n :: * -> *).
Monad n =>
(TPath -> Bool)
-> HeistState n -> IO (Either [[Char]] (HeistState n))
compileTemplates TPath -> Bool
f HeistState n
hs = do
(tmap, hs') <- HeistT n IO (HashMap TPath ([Chunk n], ByteString))
-> Node
-> HeistState n
-> IO (HashMap TPath ([Chunk n], ByteString), HeistState n)
forall (n :: * -> *) (m :: * -> *) a.
HeistT n m a -> Node -> HeistState n -> m (a, HeistState n)
runHeistT ((TPath -> Bool)
-> HeistT n IO (HashMap TPath ([Chunk n], ByteString))
forall (n :: * -> *).
Monad n =>
(TPath -> Bool)
-> HeistT n IO (HashMap TPath ([Chunk n], ByteString))
compileTemplates' TPath -> Bool
f) (Text -> Node
X.TextNode Text
"") HeistState n
hs
let pre = HeistState n -> Text
forall (m :: * -> *). HeistState m -> Text
_splicePrefix HeistState n
hs'
let canError = HeistState n -> Bool
forall (m :: * -> *). HeistState m -> Bool
_errorNotBound HeistState n
hs'
let errs = HeistState n -> [SpliceError]
forall (m :: * -> *). HeistState m -> [SpliceError]
_spliceErrors HeistState n
hs'
let nsErr = if Bool -> Bool
not (Text -> Bool
T.null Text
pre) Bool -> Bool -> Bool
&& (HeistState n -> Int
forall (m :: * -> *). HeistState m -> Int
_numNamespacedTags HeistState n
hs' Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0)
then [[Char]] -> Either [[Char]] ()
forall a b. a -> Either a b
Left [[Char] -> [Char]
noNamespaceSplicesMsg ([Char] -> [Char]) -> [Char] -> [Char]
forall a b. (a -> b) -> a -> b
$ Text -> [Char]
T.unpack Text
pre]
else () -> Either [[Char]] ()
forall a b. b -> Either a b
Right ()
return $ if canError
then case errs of
[] -> Either [[Char]] ()
nsErr Either [[Char]] ()
-> Either [[Char]] (HeistState n) -> Either [[Char]] (HeistState n)
forall a b.
Either [[Char]] a -> Either [[Char]] b -> Either [[Char]] b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>>
(HeistState n -> Either [[Char]] (HeistState n)
forall a b. b -> Either a b
Right (HeistState n -> Either [[Char]] (HeistState n))
-> HeistState n -> Either [[Char]] (HeistState n)
forall a b. (a -> b) -> a -> b
$! HeistState n
hs { _compiledTemplateMap = tmap })
[SpliceError]
es -> [[Char]] -> Either [[Char]] (HeistState n)
forall a b. a -> Either a b
Left ([[Char]] -> Either [[Char]] (HeistState n))
-> [[Char]] -> Either [[Char]] (HeistState n)
forall a b. (a -> b) -> a -> b
$ ([[Char]] -> [[Char]] -> [[Char]])
-> (() -> [[Char]] -> [[Char]])
-> Either [[Char]] ()
-> [[Char]]
-> [[Char]]
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either [[Char]] -> [[Char]] -> [[Char]]
forall a. [a] -> [a] -> [a]
(++) (([[Char]] -> [[Char]]) -> () -> [[Char]] -> [[Char]]
forall a b. a -> b -> a
const [[Char]] -> [[Char]]
forall a. a -> a
id) Either [[Char]] ()
nsErr ([[Char]] -> [[Char]]) -> [[Char]] -> [[Char]]
forall a b. (a -> b) -> a -> b
$
(SpliceError -> [Char]) -> [SpliceError] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map (Text -> [Char]
T.unpack (Text -> [Char]) -> (SpliceError -> Text) -> SpliceError -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SpliceError -> Text
spliceErrorText) [SpliceError]
es
else nsErr >> (Right $! hs { _compiledTemplateMap = tmap
, _spliceErrors = errs
})
noNamespaceSplicesMsg :: String -> String
noNamespaceSplicesMsg :: [Char] -> [Char]
noNamespaceSplicesMsg [Char]
pre = [[Char]] -> [Char]
unwords
[ [Char] -> [Char] -> [Char]
forall r. PrintfType r => [Char] -> r
printf [Char]
"You are using a namespace of '%s', but you don't have any" [Char]
ns
, [Char] -> [Char] -> [Char]
forall r. PrintfType r => [Char] -> r
printf [Char]
"tags starting with '%s'. If you have not defined any" [Char]
pre
, [Char]
"splices, then change your namespace to the empty string to get rid"
, [Char]
"of this message."
]
where
ns :: [Char]
ns = [Char] -> [Char]
forall a. [a] -> [a]
reverse ([Char] -> [Char]) -> [Char] -> [Char]
forall a b. (a -> b) -> a -> b
$ Int -> [Char] -> [Char]
forall a. Int -> [a] -> [a]
drop Int
1 ([Char] -> [Char]) -> [Char] -> [Char]
forall a b. (a -> b) -> a -> b
$ [Char] -> [Char]
forall a. [a] -> [a]
reverse [Char]
pre
compileTemplates'
:: Monad n
=> (TPath -> Bool)
-> HeistT n IO (H.HashMap TPath ([Chunk n], MIMEType))
compileTemplates' :: forall (n :: * -> *).
Monad n =>
(TPath -> Bool)
-> HeistT n IO (HashMap TPath ([Chunk n], ByteString))
compileTemplates' TPath -> Bool
f = do
hs <- HeistT n IO (HeistState n)
forall (m :: * -> *) (n :: * -> *).
Monad m =>
HeistT n m (HeistState n)
getHS
let tpathDocfiles :: [(TPath, DocumentFile)]
tpathDocfiles = ((TPath, DocumentFile) -> Bool)
-> [(TPath, DocumentFile)] -> [(TPath, DocumentFile)]
forall a. (a -> Bool) -> [a] -> [a]
filter (TPath -> Bool
f (TPath -> Bool)
-> ((TPath, DocumentFile) -> TPath)
-> (TPath, DocumentFile)
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (TPath, DocumentFile) -> TPath
forall a b. (a, b) -> a
fst)
(HashMap TPath DocumentFile -> [(TPath, DocumentFile)]
forall k v. HashMap k v -> [(k, v)]
H.toList (HashMap TPath DocumentFile -> [(TPath, DocumentFile)])
-> HashMap TPath DocumentFile -> [(TPath, DocumentFile)]
forall a b. (a -> b) -> a -> b
$ HeistState n -> HashMap TPath DocumentFile
forall (m :: * -> *). HeistState m -> HashMap TPath DocumentFile
_templateMap HeistState n
hs)
foldM runOne H.empty tpathDocfiles
where
runOne :: HashMap TPath ([Chunk m], ByteString)
-> (TPath, DocumentFile)
-> HeistT m IO (HashMap TPath ([Chunk m], ByteString))
runOne HashMap TPath ([Chunk m], ByteString)
tmap (TPath
tpath, DocumentFile
df) = do
(HeistState m -> HeistState m) -> HeistT m IO ()
forall (m :: * -> *) (n :: * -> *).
Monad m =>
(HeistState n -> HeistState n) -> HeistT n m ()
modifyHS (\HeistState m
hs -> HeistState m
hs { _doctypes = []})
!mHtml <- TPath -> DocumentFile -> HeistT m IO [Chunk m]
forall (n :: * -> *).
Monad n =>
TPath -> DocumentFile -> HeistT n IO [Chunk n]
compileTemplate TPath
tpath DocumentFile
df
return $! H.insert tpath (mHtml, mimeType $! dfDoc df) tmap
consolidate :: (Monad n) => DList (Chunk n) -> [Chunk n]
consolidate :: forall (n :: * -> *). Monad n => DList (Chunk n) -> [Chunk n]
consolidate = [Chunk n] -> [Chunk n]
forall {m :: * -> *}. Monad m => [Chunk m] -> [Chunk m]
consolidateL ([Chunk n] -> [Chunk n])
-> (DList (Chunk n) -> [Chunk n]) -> DList (Chunk n) -> [Chunk n]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DList (Chunk n) -> [Chunk n]
forall a. DList a -> [a]
DL.toList
where
consolidateL :: [Chunk m] -> [Chunk m]
consolidateL [] = []
consolidateL (Chunk m
y:[Chunk m]
ys) = [Chunk m] -> [Chunk m] -> [Chunk m]
forall {m :: * -> *}. [Chunk m] -> [Chunk m] -> [Chunk m]
boilDown [] ([Chunk m] -> [Chunk m]) -> [Chunk m] -> [Chunk m]
forall a b. (a -> b) -> a -> b
$! [Chunk m] -> Chunk m -> [Chunk m] -> [Chunk m]
forall {m :: * -> *}.
Monad m =>
[Chunk m] -> Chunk m -> [Chunk m] -> [Chunk m]
go [] Chunk m
y [Chunk m]
ys
where
go :: [Chunk m] -> Chunk m -> [Chunk m] -> [Chunk m]
go [Chunk m]
soFar Chunk m
x [] = Chunk m
x Chunk m -> [Chunk m] -> [Chunk m]
forall a. a -> [a] -> [a]
: [Chunk m]
soFar
go [Chunk m]
soFar (Pure ByteString
a) ((Pure ByteString
b) : [Chunk m]
xs) =
[Chunk m] -> Chunk m -> [Chunk m] -> [Chunk m]
go [Chunk m]
soFar (ByteString -> Chunk m
forall (m :: * -> *). ByteString -> Chunk m
Pure (ByteString -> Chunk m) -> ByteString -> Chunk m
forall a b. (a -> b) -> a -> b
$! ByteString
a ByteString -> ByteString -> ByteString
forall a. Monoid a => a -> a -> a
`mappend` ByteString
b) [Chunk m]
xs
go [Chunk m]
soFar (RuntimeHtml RuntimeSplice m Builder
a) ((RuntimeHtml RuntimeSplice m Builder
b) : [Chunk m]
xs) =
[Chunk m] -> Chunk m -> [Chunk m] -> [Chunk m]
go [Chunk m]
soFar (RuntimeSplice m Builder -> Chunk m
forall (m :: * -> *). RuntimeSplice m Builder -> Chunk m
RuntimeHtml (RuntimeSplice m Builder -> Chunk m)
-> RuntimeSplice m Builder -> Chunk m
forall a b. (a -> b) -> a -> b
$! RuntimeSplice m Builder
a RuntimeSplice m Builder
-> RuntimeSplice m Builder -> RuntimeSplice m Builder
forall a. Monoid a => a -> a -> a
`mappend` RuntimeSplice m Builder
b) [Chunk m]
xs
go [Chunk m]
soFar (RuntimeHtml RuntimeSplice m Builder
a) ((RuntimeAction RuntimeSplice m ()
b) : [Chunk m]
xs) =
[Chunk m] -> Chunk m -> [Chunk m] -> [Chunk m]
go [Chunk m]
soFar (RuntimeSplice m Builder -> Chunk m
forall (m :: * -> *). RuntimeSplice m Builder -> Chunk m
RuntimeHtml (RuntimeSplice m Builder -> Chunk m)
-> RuntimeSplice m Builder -> Chunk m
forall a b. (a -> b) -> a -> b
$! RuntimeSplice m Builder
a RuntimeSplice m Builder
-> (Builder -> RuntimeSplice m Builder) -> RuntimeSplice m Builder
forall a b.
RuntimeSplice m a -> (a -> RuntimeSplice m b) -> RuntimeSplice m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Builder
x -> RuntimeSplice m ()
b RuntimeSplice m ()
-> RuntimeSplice m Builder -> RuntimeSplice m Builder
forall a b.
RuntimeSplice m a -> RuntimeSplice m b -> RuntimeSplice m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Builder -> RuntimeSplice m Builder
forall a. a -> RuntimeSplice m a
forall (m :: * -> *) a. Monad m => a -> m a
return Builder
x) [Chunk m]
xs
go [Chunk m]
soFar (RuntimeAction RuntimeSplice m ()
a) ((RuntimeHtml RuntimeSplice m Builder
b) : [Chunk m]
xs) =
[Chunk m] -> Chunk m -> [Chunk m] -> [Chunk m]
go [Chunk m]
soFar (RuntimeSplice m Builder -> Chunk m
forall (m :: * -> *). RuntimeSplice m Builder -> Chunk m
RuntimeHtml (RuntimeSplice m Builder -> Chunk m)
-> RuntimeSplice m Builder -> Chunk m
forall a b. (a -> b) -> a -> b
$! RuntimeSplice m ()
a RuntimeSplice m ()
-> RuntimeSplice m Builder -> RuntimeSplice m Builder
forall a b.
RuntimeSplice m a -> RuntimeSplice m b -> RuntimeSplice m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> RuntimeSplice m Builder
b) [Chunk m]
xs
go [Chunk m]
soFar (RuntimeAction RuntimeSplice m ()
a) ((RuntimeAction RuntimeSplice m ()
b) : [Chunk m]
xs) =
[Chunk m] -> Chunk m -> [Chunk m] -> [Chunk m]
go [Chunk m]
soFar (RuntimeSplice m () -> Chunk m
forall (m :: * -> *). RuntimeSplice m () -> Chunk m
RuntimeAction (RuntimeSplice m () -> Chunk m) -> RuntimeSplice m () -> Chunk m
forall a b. (a -> b) -> a -> b
$! RuntimeSplice m ()
a RuntimeSplice m () -> RuntimeSplice m () -> RuntimeSplice m ()
forall a b.
RuntimeSplice m a -> RuntimeSplice m b -> RuntimeSplice m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> RuntimeSplice m ()
b) [Chunk m]
xs
go [Chunk m]
soFar Chunk m
a (Chunk m
b : [Chunk m]
xs) = [Chunk m] -> Chunk m -> [Chunk m] -> [Chunk m]
go (Chunk m
a Chunk m -> [Chunk m] -> [Chunk m]
forall a. a -> [a] -> [a]
: [Chunk m]
soFar) Chunk m
b [Chunk m]
xs
boilDown :: [Chunk m] -> [Chunk m] -> [Chunk m]
boilDown [Chunk m]
soFar [] = [Chunk m]
soFar
boilDown [Chunk m]
soFar ((Pure ByteString
h) : [Chunk m]
xs) = [Chunk m] -> [Chunk m] -> [Chunk m]
boilDown ((ByteString -> Chunk m
forall (m :: * -> *). ByteString -> Chunk m
Pure (ByteString -> Chunk m) -> ByteString -> Chunk m
forall a b. (a -> b) -> a -> b
$! ByteString
h) Chunk m -> [Chunk m] -> [Chunk m]
forall a. a -> [a] -> [a]
: [Chunk m]
soFar) [Chunk m]
xs
boilDown [Chunk m]
soFar (Chunk m
x : [Chunk m]
xs) = [Chunk m] -> [Chunk m] -> [Chunk m]
boilDown (Chunk m
x Chunk m -> [Chunk m] -> [Chunk m]
forall a. a -> [a] -> [a]
: [Chunk m]
soFar) [Chunk m]
xs
codeGen :: Monad n => DList (Chunk n) -> RuntimeSplice n Builder
codeGen :: forall (n :: * -> *).
Monad n =>
DList (Chunk n) -> RuntimeSplice n Builder
codeGen DList (Chunk n)
l = (RuntimeSplice n Builder
-> RuntimeSplice n Builder -> RuntimeSplice n Builder)
-> RuntimeSplice n Builder
-> Vector (RuntimeSplice n Builder)
-> RuntimeSplice n Builder
forall a b. (a -> b -> b) -> b -> Vector a -> b
V.foldr RuntimeSplice n Builder
-> RuntimeSplice n Builder -> RuntimeSplice n Builder
forall a. Monoid a => a -> a -> a
mappend RuntimeSplice n Builder
forall a. Monoid a => a
mempty (Vector (RuntimeSplice n Builder) -> RuntimeSplice n Builder)
-> Vector (RuntimeSplice n Builder) -> RuntimeSplice n Builder
forall a b. (a -> b) -> a -> b
$!
(Chunk n -> RuntimeSplice n Builder)
-> Vector (Chunk n) -> Vector (RuntimeSplice n Builder)
forall a b. (a -> b) -> Vector a -> Vector b
V.map Chunk n -> RuntimeSplice n Builder
forall {m :: * -> *}. Monad m => Chunk m -> RuntimeSplice m Builder
toAct (Vector (Chunk n) -> Vector (RuntimeSplice n Builder))
-> Vector (Chunk n) -> Vector (RuntimeSplice n Builder)
forall a b. (a -> b) -> a -> b
$! [Chunk n] -> Vector (Chunk n)
forall a. [a] -> Vector a
V.fromList ([Chunk n] -> Vector (Chunk n)) -> [Chunk n] -> Vector (Chunk n)
forall a b. (a -> b) -> a -> b
$! DList (Chunk n) -> [Chunk n]
forall (n :: * -> *). Monad n => DList (Chunk n) -> [Chunk n]
consolidate DList (Chunk n)
l
where
toAct :: Chunk m -> RuntimeSplice m Builder
toAct !(RuntimeHtml !RuntimeSplice m Builder
m) = RuntimeSplice m Builder
m
toAct !(Pure !ByteString
h) = Builder -> RuntimeSplice m Builder
forall a. a -> RuntimeSplice m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Builder -> RuntimeSplice m Builder)
-> Builder -> RuntimeSplice m Builder
forall a b. (a -> b) -> a -> b
$! ByteString -> Builder
fromByteString ByteString
h
toAct !(RuntimeAction !RuntimeSplice m ()
m) = RuntimeSplice m ()
m RuntimeSplice m ()
-> RuntimeSplice m Builder -> RuntimeSplice m Builder
forall a b.
RuntimeSplice m a -> RuntimeSplice m b -> RuntimeSplice m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Builder -> RuntimeSplice m Builder
forall a. a -> RuntimeSplice m a
forall (m :: * -> *) a. Monad m => a -> m a
return Builder
forall a. Monoid a => a
mempty
{-# INLINE codeGen #-}
lookupSplice :: Text -> HeistT n IO (Maybe (Splice n))
lookupSplice :: forall (n :: * -> *). Text -> HeistT n IO (Maybe (Splice n))
lookupSplice Text
nm = do
pre <- (HeistState n -> Text) -> HeistT n IO Text
forall (m :: * -> *) (n :: * -> *) r.
Monad m =>
(HeistState n -> r) -> HeistT n m r
getsHS HeistState n -> Text
forall (m :: * -> *). HeistState m -> Text
_splicePrefix
res <- getsHS (H.lookup nm . _compiledSpliceMap)
if isNothing res && T.isPrefixOf pre nm && not (T.null pre)
then do
tellSpliceError $ "No splice bound for " `mappend` nm
return Nothing
else return res
runNode :: Monad n => X.Node -> Splice n
runNode :: forall (n :: * -> *). Monad n => Node -> Splice n
runNode Node
node = (Node -> Node)
-> HeistT n IO (DList (Chunk n)) -> HeistT n IO (DList (Chunk n))
forall (m :: * -> *) (n :: * -> *) a.
Monad m =>
(Node -> Node) -> HeistT n m a -> HeistT n m a
localParamNode (Node -> Node -> Node
forall a b. a -> b -> a
const Node
node) (HeistT n IO (DList (Chunk n)) -> HeistT n IO (DList (Chunk n)))
-> HeistT n IO (DList (Chunk n)) -> HeistT n IO (DList (Chunk n))
forall a b. (a -> b) -> a -> b
$ do
hs <- HeistT n IO (HeistState n)
forall (m :: * -> *) (n :: * -> *).
Monad m =>
HeistT n m (HeistState n)
getHS
let pre = HeistState n -> Text
forall (m :: * -> *). HeistState m -> Text
_splicePrefix HeistState n
hs
let hasPrefix = (Text -> Text -> Bool
T.isPrefixOf Text
pre (Text -> Bool) -> Maybe Text -> Maybe Bool
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
`fmap` Node -> Maybe Text
X.tagName Node
node) Maybe Bool -> Maybe Bool -> Bool
forall a. Eq a => a -> a -> Bool
== Bool -> Maybe Bool
forall a. a -> Maybe a
Just Bool
True
when (not (T.null pre) && hasPrefix) incNamespacedTags
hs' <- getHS
(res, hs'') <- liftIO $ catches (compileIO hs')
[ Handler (\(CompileException
ex :: CompileException) -> CompileException -> IO (DList (Chunk n), HeistState n)
forall e a. (HasCallStack, Exception e) => e -> IO a
throwIO CompileException
ex)
, Handler (\(SomeException
ex :: SomeException) -> SomeException -> HeistState n -> IO (DList (Chunk n), HeistState n)
forall {e} {n :: * -> *} {b}.
Exception e =>
e -> HeistState n -> IO b
handleError SomeException
ex HeistState n
hs')]
putHS hs''
return res
where
localSplicePath :: HeistT m m a -> HeistT m m a
localSplicePath =
(HeistState m -> HeistState m) -> HeistT m m a -> HeistT m m a
forall (m :: * -> *) (n :: * -> *) a.
Monad m =>
(HeistState n -> HeistState n) -> HeistT n m a -> HeistT n m a
localHS (\HeistState m
hs -> HeistState m
hs {_splicePath = (_curContext hs,
_curTemplateFile hs,
X.elementTag node):
(_splicePath hs)})
compileIO :: HeistState n -> IO (DList (Chunk n), HeistState n)
compileIO HeistState n
hs = HeistT n IO (DList (Chunk n))
-> Node -> HeistState n -> IO (DList (Chunk n), HeistState n)
forall (n :: * -> *) (m :: * -> *) a.
HeistT n m a -> Node -> HeistState n -> m (a, HeistState n)
runHeistT HeistT n IO (DList (Chunk n))
forall (n :: * -> *). Monad n => Splice n
compile Node
node HeistState n
hs
compile :: HeistT n IO (DList (Chunk n))
compile = do
isStatic <- Node -> HeistT n IO Bool
forall (n :: * -> *). Node -> HeistT n IO Bool
subtreeIsStatic Node
node
dl <- compile' isStatic
liftIO $ evaluate $ DL.fromList $! consolidate dl
compile' :: Bool -> HeistT n IO (DList (Chunk n))
compile' Bool
True = do
markup <- (HeistState n -> Markup) -> HeistT n IO Markup
forall (m :: * -> *) (n :: * -> *) r.
Monad m =>
(HeistState n -> r) -> HeistT n m r
getsHS HeistState n -> Markup
forall (m :: * -> *). HeistState m -> Markup
_curMarkup
return $! yieldPure $! renderFragment markup [parseAttrs node]
compile' Bool
False = HeistT n IO (DList (Chunk n)) -> HeistT n IO (DList (Chunk n))
forall {m :: * -> *} {m :: * -> *} {a}.
Monad m =>
HeistT m m a -> HeistT m m a
localSplicePath (HeistT n IO (DList (Chunk n)) -> HeistT n IO (DList (Chunk n)))
-> HeistT n IO (DList (Chunk n)) -> HeistT n IO (DList (Chunk n))
forall a b. (a -> b) -> a -> b
$ Node -> HeistT n IO (DList (Chunk n))
forall (n :: * -> *). Monad n => Node -> Splice n
compileNode Node
node
handleError :: e -> HeistState n -> IO b
handleError e
ex HeistState n
hs = do
errs <- HeistT n IO [SpliceError]
-> Node -> HeistState n -> IO [SpliceError]
forall (m :: * -> *) (n :: * -> *) a.
Monad m =>
HeistT n m a -> Node -> HeistState n -> m a
evalHeistT (do HeistT n IO () -> HeistT n IO ()
forall {m :: * -> *} {m :: * -> *} {a}.
Monad m =>
HeistT m m a -> HeistT m m a
localSplicePath (HeistT n IO () -> HeistT n IO ())
-> HeistT n IO () -> HeistT n IO ()
forall a b. (a -> b) -> a -> b
$ Text -> HeistT n IO ()
forall (m :: * -> *) (n :: * -> *).
Monad m =>
Text -> HeistT n m ()
tellSpliceError (Text -> HeistT n IO ()) -> Text -> HeistT n IO ()
forall a b. (a -> b) -> a -> b
$ [Char] -> Text
T.pack ([Char] -> Text) -> [Char] -> Text
forall a b. (a -> b) -> a -> b
$
[Char]
"Exception in splice compile: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ e -> [Char]
forall a. Show a => a -> [Char]
show e
ex
(HeistState n -> [SpliceError]) -> HeistT n IO [SpliceError]
forall (m :: * -> *) (n :: * -> *) r.
Monad m =>
(HeistState n -> r) -> HeistT n m r
getsHS HeistState n -> [SpliceError]
forall (m :: * -> *). HeistState m -> [SpliceError]
_spliceErrors) Node
node HeistState n
hs
throwIO $ CompileException ex errs
parseAttrs :: X.Node -> X.Node
parseAttrs :: Node -> Node
parseAttrs (X.Element Text
nm [(Text, Text)]
attrs [Node]
ch) = [(Text, Text)]
newAttrs [(Text, Text)] -> Node -> Node
forall a b. a -> b -> b
`seq` Text -> [(Text, Text)] -> [Node] -> Node
X.Element Text
nm [(Text, Text)]
newAttrs [Node]
ch
where
newAttrs :: [(Text, Text)]
newAttrs = ((Text, Text) -> (Text, Text)) -> [(Text, Text)] -> [(Text, Text)]
forall a b. (a -> b) -> [a] -> [b]
map (Text, Text) -> (Text, Text)
parseAttr [(Text, Text)]
attrs
parseAttrs !Node
n = Node
n
parseAttr :: (Text, Text) -> (Text, Text)
parseAttr :: (Text, Text) -> (Text, Text)
parseAttr (Text
k,Text
v) = (Text
k, [Text] -> Text
T.concat ([Text] -> Text) -> [Text] -> Text
forall a b. (a -> b) -> a -> b
$! (AttAST -> Text) -> [AttAST] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map AttAST -> Text
cvt [AttAST]
ast)
where
!ast :: [AttAST]
ast = case IResult Text [AttAST] -> Text -> IResult Text [AttAST]
forall i r. Monoid i => IResult i r -> i -> IResult i r
AP.feed (Parser [AttAST] -> Text -> IResult Text [AttAST]
forall a. Parser a -> Text -> Result a
AP.parse Parser [AttAST]
attParser Text
v) Text
"" of
(AP.Done Text
_ [AttAST]
res) -> [AttAST]
res
(AP.Fail Text
_ [[Char]]
_ [Char]
_) -> []
(AP.Partial Text -> IResult Text [AttAST]
_ ) -> []
cvt :: AttAST -> Text
cvt (Literal Text
x) = Text
x
cvt (Ident Text
i) = [Text] -> Text
T.concat [Text
"${", Text
i, Text
"}"]
subtreeIsStatic :: X.Node -> HeistT n IO Bool
subtreeIsStatic :: forall (n :: * -> *). Node -> HeistT n IO Bool
subtreeIsStatic (X.Element Text
nm [(Text, Text)]
attrs [Node]
ch) = do
isNodeDynamic <- (Maybe (Splice n) -> Bool)
-> HeistT n IO (Maybe (Splice n)) -> HeistT n IO Bool
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM Maybe (Splice n) -> Bool
forall a. Maybe a -> Bool
isJust (HeistT n IO (Maybe (Splice n)) -> HeistT n IO Bool)
-> HeistT n IO (Maybe (Splice n)) -> HeistT n IO Bool
forall a b. (a -> b) -> a -> b
$ Text -> HeistT n IO (Maybe (Splice n))
forall (n :: * -> *). Text -> HeistT n IO (Maybe (Splice n))
lookupSplice Text
nm
attrSplices <- getsHS _attrSpliceMap
let hasSubstitutions (Text
k,Text
v) = Text -> Bool
hasAttributeSubstitutions Text
v Bool -> Bool -> Bool
||
Text -> HashMap Text (AttrSplice n) -> Bool
forall k a. (Eq k, Hashable k) => k -> HashMap k a -> Bool
H.member Text
k HashMap Text (AttrSplice n)
attrSplices
if isNodeDynamic
then return False
else do
let hasDynamicAttrs = ((Text, Text) -> Bool) -> [(Text, Text)] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (Text, Text) -> Bool
hasSubstitutions [(Text, Text)]
attrs
if hasDynamicAttrs
then return False
else do
staticSubtrees <- mapM subtreeIsStatic ch
return $ and staticSubtrees
subtreeIsStatic Node
_ = Bool -> HeistT n IO Bool
forall a. a -> HeistT n IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
hasAttributeSubstitutions :: Text -> Bool
hasAttributeSubstitutions :: Text -> Bool
hasAttributeSubstitutions Text
txt = (AttAST -> Bool) -> [AttAST] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any AttAST -> Bool
isIdent [AttAST]
ast
where
ast :: [AttAST]
ast = case IResult Text [AttAST] -> Text -> IResult Text [AttAST]
forall i r. Monoid i => IResult i r -> i -> IResult i r
AP.feed (Parser [AttAST] -> Text -> IResult Text [AttAST]
forall a. Parser a -> Text -> Result a
AP.parse Parser [AttAST]
attParser Text
txt) Text
"" of
(AP.Done Text
_ [AttAST]
res) -> [AttAST]
res
(AP.Fail Text
_ [[Char]]
_ [Char]
_) -> []
(AP.Partial Text -> IResult Text [AttAST]
_ ) -> []
compileNode :: Monad n => X.Node -> Splice n
compileNode :: forall (n :: * -> *). Monad n => Node -> Splice n
compileNode (X.Element Text
nm [(Text, Text)]
attrs [Node]
ch) = do
msplice <- Text -> HeistT n IO (Maybe (Splice n))
forall (n :: * -> *). Text -> HeistT n IO (Maybe (Splice n))
lookupSplice Text
nm
fromMaybe compileStaticElement msplice
where
tag0 :: Text
tag0 = Text -> Text -> Text
T.append Text
"<" Text
nm
end :: Text
end = [Text] -> Text
T.concat [ Text
"</" , Text
nm , Text
">"]
compileStaticElement :: HeistT n IO (DList (Chunk n))
compileStaticElement = do
compiledAttrs <- [(Text, Text)] -> HeistT n IO [DList (Chunk n)]
forall (n :: * -> *).
Monad n =>
[(Text, Text)] -> HeistT n IO [DList (Chunk n)]
runAttributes [(Text, Text)]
attrs
childHtml <- runNodeList ch
return $! if null (DL.toList childHtml) && nm `S.member` X.voidTags
then DL.concat [ DL.singleton $! pureTextChunk $! tag0
, DL.concat compiledAttrs
, DL.singleton $! pureTextChunk " />"
]
else DL.concat [ DL.singleton $! pureTextChunk $! tag0
, DL.concat compiledAttrs
, DL.singleton $! pureTextChunk ">"
, childHtml
, DL.singleton $! pureTextChunk $! end
]
compileNode Node
_ = [Char] -> Splice n
forall a. HasCallStack => [Char] -> a
error [Char]
"impossible"
parseAtt :: Monad n => (Text, Text) -> HeistT n IO (DList (Chunk n))
parseAtt :: forall (n :: * -> *).
Monad n =>
(Text, Text) -> HeistT n IO (DList (Chunk n))
parseAtt (Text
k,Text
v) = do
mas <- (HeistState n -> Maybe (AttrSplice n))
-> HeistT n IO (Maybe (AttrSplice n))
forall (m :: * -> *) (n :: * -> *) r.
Monad m =>
(HeistState n -> r) -> HeistT n m r
getsHS (Text -> HashMap Text (AttrSplice n) -> Maybe (AttrSplice n)
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
H.lookup Text
k (HashMap Text (AttrSplice n) -> Maybe (AttrSplice n))
-> (HeistState n -> HashMap Text (AttrSplice n))
-> HeistState n
-> Maybe (AttrSplice n)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HeistState n -> HashMap Text (AttrSplice n)
forall (m :: * -> *). HeistState m -> HashMap Text (AttrSplice m)
_attrSpliceMap)
maybe doInline (return . doAttrSplice) mas
where
cvt :: AttAST -> HeistT n IO (DList (Chunk n))
cvt (Literal Text
x) = DList (Chunk n) -> HeistT n IO (DList (Chunk n))
forall a. a -> HeistT n IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (DList (Chunk n) -> HeistT n IO (DList (Chunk n)))
-> DList (Chunk n) -> HeistT n IO (DList (Chunk n))
forall a b. (a -> b) -> a -> b
$ Text -> DList (Chunk n)
forall (n :: * -> *). Text -> DList (Chunk n)
yieldPureText Text
x
cvt (Ident Text
x) =
(Node -> Node)
-> HeistT n IO (DList (Chunk n)) -> HeistT n IO (DList (Chunk n))
forall (m :: * -> *) (n :: * -> *) a.
Monad m =>
(Node -> Node) -> HeistT n m a -> HeistT n m a
localParamNode (Node -> Node -> Node
forall a b. a -> b -> a
const (Node -> Node -> Node) -> Node -> Node -> Node
forall a b. (a -> b) -> a -> b
$ Text -> [(Text, Text)] -> [Node] -> Node
X.Element Text
x [] []) (HeistT n IO (DList (Chunk n)) -> HeistT n IO (DList (Chunk n)))
-> HeistT n IO (DList (Chunk n)) -> HeistT n IO (DList (Chunk n))
forall a b. (a -> b) -> a -> b
$ Text -> HeistT n IO (DList (Chunk n))
forall (n :: * -> *). Text -> HeistT n IO (DList (Chunk n))
getAttributeSplice Text
x
doInline :: HeistT n IO (DList (Chunk n))
doInline = do
let ast :: [AttAST]
ast = case IResult Text [AttAST] -> Text -> IResult Text [AttAST]
forall i r. Monoid i => IResult i r -> i -> IResult i r
AP.feed (Parser [AttAST] -> Text -> IResult Text [AttAST]
forall a. Parser a -> Text -> Result a
AP.parse Parser [AttAST]
attParser Text
v) Text
"" of
(AP.Done Text
_ [AttAST]
res) -> [AttAST]
res
(AP.Fail Text
_ [[Char]]
_ [Char]
_) -> []
(AP.Partial Text -> IResult Text [AttAST]
_ ) -> []
chunks <- (AttAST -> HeistT n IO (DList (Chunk n)))
-> [AttAST] -> HeistT n IO [DList (Chunk n)]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM AttAST -> HeistT n IO (DList (Chunk n))
forall {n :: * -> *}. AttAST -> HeistT n IO (DList (Chunk n))
cvt [AttAST]
ast
let value = [DList (Chunk n)] -> DList (Chunk n)
forall a. [DList a] -> DList a
DL.concat [DList (Chunk n)]
chunks
return $ attrToChunk k value
doAttrSplice :: (Text -> RuntimeSplice m [(Text, Text)]) -> DList (Chunk m)
doAttrSplice Text -> RuntimeSplice m [(Text, Text)]
splice = Chunk m -> DList (Chunk m)
forall a. a -> DList a
DL.singleton (Chunk m -> DList (Chunk m)) -> Chunk m -> DList (Chunk m)
forall a b. (a -> b) -> a -> b
$ RuntimeSplice m Builder -> Chunk m
forall (m :: * -> *). RuntimeSplice m Builder -> Chunk m
RuntimeHtml (RuntimeSplice m Builder -> Chunk m)
-> RuntimeSplice m Builder -> Chunk m
forall a b. (a -> b) -> a -> b
$ do
res <- Text -> RuntimeSplice m [(Text, Text)]
splice Text
v
return $ mconcat $ map attrToBuilder res
parseAtt2 :: Monad n
=> (Text, Text)
-> HeistT n IO (RuntimeSplice n [(Text, Text)])
parseAtt2 :: forall (n :: * -> *).
Monad n =>
(Text, Text) -> HeistT n IO (RuntimeSplice n [(Text, Text)])
parseAtt2 (Text
k,Text
v) = do
mas <- (HeistState n -> Maybe (AttrSplice n))
-> HeistT n IO (Maybe (AttrSplice n))
forall (m :: * -> *) (n :: * -> *) r.
Monad m =>
(HeistState n -> r) -> HeistT n m r
getsHS (Text -> HashMap Text (AttrSplice n) -> Maybe (AttrSplice n)
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
H.lookup Text
k (HashMap Text (AttrSplice n) -> Maybe (AttrSplice n))
-> (HeistState n -> HashMap Text (AttrSplice n))
-> HeistState n
-> Maybe (AttrSplice n)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HeistState n -> HashMap Text (AttrSplice n)
forall (m :: * -> *). HeistState m -> HashMap Text (AttrSplice m)
_attrSpliceMap)
maybe doInline (return . doAttrSplice) mas
where
cvt :: AttAST -> HeistT n IO (RuntimeSplice n Text)
cvt (Literal Text
x) = RuntimeSplice n Text -> HeistT n IO (RuntimeSplice n Text)
forall a. a -> HeistT n IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (RuntimeSplice n Text -> HeistT n IO (RuntimeSplice n Text))
-> RuntimeSplice n Text -> HeistT n IO (RuntimeSplice n Text)
forall a b. (a -> b) -> a -> b
$ Text -> RuntimeSplice n Text
forall a. a -> RuntimeSplice n a
forall (m :: * -> *) a. Monad m => a -> m a
return Text
x
cvt (Ident Text
x) =
(Node -> Node)
-> HeistT n IO (RuntimeSplice n Text)
-> HeistT n IO (RuntimeSplice n Text)
forall (m :: * -> *) (n :: * -> *) a.
Monad m =>
(Node -> Node) -> HeistT n m a -> HeistT n m a
localParamNode (Node -> Node -> Node
forall a b. a -> b -> a
const (Node -> Node -> Node) -> Node -> Node -> Node
forall a b. (a -> b) -> a -> b
$ Text -> [(Text, Text)] -> [Node] -> Node
X.Element Text
x [] []) (HeistT n IO (RuntimeSplice n Text)
-> HeistT n IO (RuntimeSplice n Text))
-> HeistT n IO (RuntimeSplice n Text)
-> HeistT n IO (RuntimeSplice n Text)
forall a b. (a -> b) -> a -> b
$ Text -> HeistT n IO (RuntimeSplice n Text)
forall (n :: * -> *).
Monad n =>
Text -> HeistT n IO (RuntimeSplice n Text)
getAttributeSplice2 Text
x
doInline :: HeistT n IO (RuntimeSplice n [(Text, Text)])
doInline = do
let ast :: [AttAST]
ast = case IResult Text [AttAST] -> Text -> IResult Text [AttAST]
forall i r. Monoid i => IResult i r -> i -> IResult i r
AP.feed (Parser [AttAST] -> Text -> IResult Text [AttAST]
forall a. Parser a -> Text -> Result a
AP.parse Parser [AttAST]
attParser Text
v) Text
"" of
(AP.Done Text
_ [AttAST]
res) -> [AttAST]
res
(AP.Fail Text
_ [[Char]]
_ [Char]
_) -> []
(AP.Partial Text -> IResult Text [AttAST]
_ ) -> []
chunks <- (AttAST -> HeistT n IO (RuntimeSplice n Text))
-> [AttAST] -> HeistT n IO [RuntimeSplice n Text]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM AttAST -> HeistT n IO (RuntimeSplice n Text)
forall {n :: * -> *}.
Monad n =>
AttAST -> HeistT n IO (RuntimeSplice n Text)
cvt [AttAST]
ast
return $ do
list <- sequence chunks
return [(k, T.concat list)]
doAttrSplice :: (Text -> t) -> t
doAttrSplice Text -> t
splice = Text -> t
splice Text
v
runAttributes :: Monad n
=> [(Text, Text)]
-> HeistT n IO [DList (Chunk n)]
runAttributes :: forall (n :: * -> *).
Monad n =>
[(Text, Text)] -> HeistT n IO [DList (Chunk n)]
runAttributes = ((Text, Text) -> HeistT n IO (DList (Chunk n)))
-> [(Text, Text)] -> HeistT n IO [DList (Chunk n)]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM (Text, Text) -> HeistT n IO (DList (Chunk n))
forall (n :: * -> *).
Monad n =>
(Text, Text) -> HeistT n IO (DList (Chunk n))
parseAtt
runAttributesRaw :: Monad n
=> [(Text, Text)]
-> HeistT n IO (RuntimeSplice n [(Text, Text)])
runAttributesRaw :: forall (n :: * -> *).
Monad n =>
[(Text, Text)] -> HeistT n IO (RuntimeSplice n [(Text, Text)])
runAttributesRaw [(Text, Text)]
attrs = do
arrs <- ((Text, Text) -> HeistT n IO (RuntimeSplice n [(Text, Text)]))
-> [(Text, Text)] -> HeistT n IO [RuntimeSplice n [(Text, Text)]]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM (Text, Text) -> HeistT n IO (RuntimeSplice n [(Text, Text)])
forall (n :: * -> *).
Monad n =>
(Text, Text) -> HeistT n IO (RuntimeSplice n [(Text, Text)])
parseAtt2 [(Text, Text)]
attrs
return $ liftM concat $ sequence arrs
attrToChunk :: Text -> DList (Chunk n) -> DList (Chunk n)
attrToChunk :: forall (n :: * -> *). Text -> DList (Chunk n) -> DList (Chunk n)
attrToChunk !Text
k !DList (Chunk n)
v = do
[DList (Chunk n)] -> DList (Chunk n)
forall a. [DList a] -> DList a
DL.concat
[ Chunk n -> DList (Chunk n)
forall a. a -> DList a
DL.singleton (Chunk n -> DList (Chunk n)) -> Chunk n -> DList (Chunk n)
forall a b. (a -> b) -> a -> b
$! Text -> Chunk n
forall (n :: * -> *). Text -> Chunk n
pureTextChunk (Text -> Chunk n) -> Text -> Chunk n
forall a b. (a -> b) -> a -> b
$! [Text] -> Text
T.concat [Text
" ", Text
k, Text
"=\""]
, DList (Chunk n)
v, Chunk n -> DList (Chunk n)
forall a. a -> DList a
DL.singleton (Chunk n -> DList (Chunk n)) -> Chunk n -> DList (Chunk n)
forall a b. (a -> b) -> a -> b
$! Text -> Chunk n
forall (n :: * -> *). Text -> Chunk n
pureTextChunk Text
"\"" ]
attrToBuilder :: (Text, Text) -> Builder
attrToBuilder :: (Text, Text) -> Builder
attrToBuilder (Text
k,Text
v)
| Text -> Bool
T.null Text
v = [Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat
[ Text -> Builder
fromText Text
" "
, Text -> Builder
fromText Text
k
]
| Bool
otherwise = [Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat
[ Text -> Builder
fromText Text
" "
, Text -> Builder
fromText Text
k
, Text -> Builder
fromText Text
"=\""
, Text -> Builder
fromText Text
v
, Text -> Builder
fromText Text
"\""
]
getAttributeSplice :: Text -> HeistT n IO (DList (Chunk n))
getAttributeSplice :: forall (n :: * -> *). Text -> HeistT n IO (DList (Chunk n))
getAttributeSplice Text
name =
Text -> HeistT n IO (Maybe (Splice n))
forall (n :: * -> *). Text -> HeistT n IO (Maybe (Splice n))
lookupSplice Text
name HeistT n IO (Maybe (Splice n))
-> (Maybe (Splice n) -> Splice n) -> Splice n
forall a b. HeistT n IO a -> (a -> HeistT n IO b) -> HeistT n IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Splice n -> Maybe (Splice n) -> Splice n
forall a. a -> Maybe a -> a
fromMaybe
(DList (Chunk n) -> Splice n
forall a. a -> HeistT n IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (DList (Chunk n) -> Splice n) -> DList (Chunk n) -> Splice n
forall a b. (a -> b) -> a -> b
$ Chunk n -> DList (Chunk n)
forall a. a -> DList a
DL.singleton (Chunk n -> DList (Chunk n)) -> Chunk n -> DList (Chunk n)
forall a b. (a -> b) -> a -> b
$ ByteString -> Chunk n
forall (m :: * -> *). ByteString -> Chunk m
Pure (ByteString -> Chunk n) -> ByteString -> Chunk n
forall a b. (a -> b) -> a -> b
$ Text -> ByteString
T.encodeUtf8 (Text -> ByteString) -> Text -> ByteString
forall a b. (a -> b) -> a -> b
$
[Text] -> Text
T.concat [Text
"${", Text
name, Text
"}"])
{-# INLINE getAttributeSplice #-}
getAttributeSplice2 :: Monad n => Text -> HeistT n IO (RuntimeSplice n Text)
getAttributeSplice2 :: forall (n :: * -> *).
Monad n =>
Text -> HeistT n IO (RuntimeSplice n Text)
getAttributeSplice2 Text
name = do
mSplice <- Text -> HeistT n IO (Maybe (Splice n))
forall (n :: * -> *). Text -> HeistT n IO (Maybe (Splice n))
lookupSplice Text
name
case mSplice of
Maybe (Splice n)
Nothing -> RuntimeSplice n Text -> HeistT n IO (RuntimeSplice n Text)
forall a. a -> HeistT n IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (RuntimeSplice n Text -> HeistT n IO (RuntimeSplice n Text))
-> RuntimeSplice n Text -> HeistT n IO (RuntimeSplice n Text)
forall a b. (a -> b) -> a -> b
$ Text -> RuntimeSplice n Text
forall a. a -> RuntimeSplice n a
forall (m :: * -> *) a. Monad m => a -> m a
return (Text -> RuntimeSplice n Text) -> Text -> RuntimeSplice n Text
forall a b. (a -> b) -> a -> b
$ [Text] -> Text
T.concat [Text
"${", Text
name, Text
"}"]
Just Splice n
splice -> do
res <- Splice n
splice
return $ liftM (T.decodeUtf8 . toByteString) $ codeGen res
{-# INLINE getAttributeSplice2 #-}
newtype Promise a = Promise (HE.Key a)
getPromise :: (Monad n) => Promise a -> RuntimeSplice n a
getPromise :: forall (n :: * -> *) a. Monad n => Promise a -> RuntimeSplice n a
getPromise (Promise Key a
k) = do
mb <- (HeterogeneousEnvironment -> Maybe a) -> RuntimeSplice n (Maybe a)
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets (Key a -> HeterogeneousEnvironment -> Maybe a
forall a. Key a -> HeterogeneousEnvironment -> Maybe a
HE.lookup Key a
k)
return $ fromMaybe e mb
where
e :: a
e = [Char] -> a
forall a. HasCallStack => [Char] -> a
error ([Char] -> a) -> [Char] -> a
forall a b. (a -> b) -> a -> b
$ [Char]
"getPromise: dereferenced empty key (id "
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show (Key a -> Int
forall a. Key a -> Int
HE.getKeyId Key a
k) [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
")"
{-# INLINE getPromise #-}
putPromise :: (Monad n) => Promise a -> a -> RuntimeSplice n ()
putPromise :: forall (n :: * -> *) a.
Monad n =>
Promise a -> a -> RuntimeSplice n ()
putPromise (Promise Key a
k) a
x = (HeterogeneousEnvironment -> HeterogeneousEnvironment)
-> RuntimeSplice n ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify (Key a -> a -> HeterogeneousEnvironment -> HeterogeneousEnvironment
forall a.
Key a -> a -> HeterogeneousEnvironment -> HeterogeneousEnvironment
HE.insert Key a
k a
x)
{-# INLINE putPromise #-}
adjustPromise :: Monad n => Promise a -> (a -> a) -> RuntimeSplice n ()
adjustPromise :: forall (n :: * -> *) a.
Monad n =>
Promise a -> (a -> a) -> RuntimeSplice n ()
adjustPromise (Promise Key a
k) a -> a
f = (HeterogeneousEnvironment -> HeterogeneousEnvironment)
-> RuntimeSplice n ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((a -> a)
-> Key a -> HeterogeneousEnvironment -> HeterogeneousEnvironment
forall a.
(a -> a)
-> Key a -> HeterogeneousEnvironment -> HeterogeneousEnvironment
HE.adjust a -> a
f Key a
k)
{-# INLINE adjustPromise #-}
newEmptyPromise :: HeistT n IO (Promise a)
newEmptyPromise :: forall (n :: * -> *) a. HeistT n IO (Promise a)
newEmptyPromise = do
keygen <- (HeistState n -> KeyGen) -> HeistT n IO KeyGen
forall (m :: * -> *) (n :: * -> *) r.
Monad m =>
(HeistState n -> r) -> HeistT n m r
getsHS HeistState n -> KeyGen
forall (m :: * -> *). HeistState m -> KeyGen
_keygen
key <- liftIO $ HE.makeKey keygen
return $! Promise key
{-# INLINE newEmptyPromise #-}
bindSplice :: Text
-> Splice n
-> HeistState n
-> HeistState n
bindSplice :: forall (n :: * -> *).
Text -> Splice n -> HeistState n -> HeistState n
bindSplice Text
n Splice n
v HeistState n
ts =
HeistState n
ts { _compiledSpliceMap = H.insert n' v (_compiledSpliceMap ts) }
where
n' :: Text
n' = HeistState n -> Text
forall (m :: * -> *). HeistState m -> Text
_splicePrefix HeistState n
ts Text -> Text -> Text
forall a. Monoid a => a -> a -> a
`mappend` Text
n
bindSplices :: Splices (Splice n)
-> HeistState n
-> HeistState n
bindSplices :: forall (n :: * -> *).
Splices (Splice n) -> HeistState n -> HeistState n
bindSplices Splices (Splice n)
ss HeistState n
hs =
HeistState n
hs { _compiledSpliceMap = applySpliceMap hs _compiledSpliceMap ss }
withLocalSplices :: Splices (Splice n)
-> Splices (AttrSplice n)
-> HeistT n IO a
-> HeistT n IO a
withLocalSplices :: forall (n :: * -> *) a.
Splices (Splice n)
-> Splices (AttrSplice n) -> HeistT n IO a -> HeistT n IO a
withLocalSplices Splices (Splice n)
ss Splices (AttrSplice n)
as = (HeistState n -> HeistState n) -> HeistT n IO a -> HeistT n IO a
forall (m :: * -> *) (n :: * -> *) a.
Monad m =>
(HeistState n -> HeistState n) -> HeistT n m a -> HeistT n m a
localHS (Splices (Splice n) -> HeistState n -> HeistState n
forall (n :: * -> *).
Splices (Splice n) -> HeistState n -> HeistState n
bindSplices Splices (Splice n)
ss (HeistState n -> HeistState n)
-> (HeistState n -> HeistState n) -> HeistState n -> HeistState n
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Splices (AttrSplice n) -> HeistState n -> HeistState n
forall (n :: * -> *).
Splices (AttrSplice n) -> HeistState n -> HeistState n
bindAttributeSplices Splices (AttrSplice n)
as)
renderTemplate :: Monad n
=> HeistState n
-> ByteString
-> Maybe (n Builder, MIMEType)
renderTemplate :: forall (n :: * -> *).
Monad n =>
HeistState n -> ByteString -> Maybe (n Builder, ByteString)
renderTemplate HeistState n
hs ByteString
nm =
((([Chunk n], ByteString), TPath) -> (n Builder, ByteString))
-> Maybe (([Chunk n], ByteString), TPath)
-> Maybe (n Builder, ByteString)
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (([Chunk n] -> n Builder)
-> ([Chunk n], ByteString) -> (n Builder, ByteString)
forall b c d. (b -> c) -> (b, d) -> (c, d)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (b, d) (c, d)
first (DList (Chunk n) -> n Builder
forall (n :: * -> *). Monad n => DList (Chunk n) -> n Builder
interpret (DList (Chunk n) -> n Builder)
-> ([Chunk n] -> DList (Chunk n)) -> [Chunk n] -> n Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Chunk n] -> DList (Chunk n)
forall a. [a] -> DList a
DL.fromList) (([Chunk n], ByteString) -> (n Builder, ByteString))
-> ((([Chunk n], ByteString), TPath) -> ([Chunk n], ByteString))
-> (([Chunk n], ByteString), TPath)
-> (n Builder, ByteString)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (([Chunk n], ByteString), TPath) -> ([Chunk n], ByteString)
forall a b. (a, b) -> a
fst) (Maybe (([Chunk n], ByteString), TPath)
-> Maybe (n Builder, ByteString))
-> Maybe (([Chunk n], ByteString), TPath)
-> Maybe (n Builder, ByteString)
forall a b. (a -> b) -> a -> b
$!
ByteString
-> HeistState n
-> (HeistState n -> HashMap TPath ([Chunk n], ByteString))
-> Maybe (([Chunk n], ByteString), TPath)
forall (n :: * -> *) t.
ByteString
-> HeistState n
-> (HeistState n -> HashMap TPath t)
-> Maybe (t, TPath)
lookupTemplate ByteString
nm HeistState n
hs HeistState n -> HashMap TPath ([Chunk n], ByteString)
forall (m :: * -> *).
HeistState m -> HashMap TPath ([Chunk m], ByteString)
_compiledTemplateMap
callTemplate :: Monad n
=> ByteString
-> Splice n
callTemplate :: forall (n :: * -> *). Monad n => ByteString -> Splice n
callTemplate ByteString
nm = do
hs <- HeistT n IO (HeistState n)
forall (m :: * -> *) (n :: * -> *).
Monad m =>
HeistT n m (HeistState n)
getHS
maybe (error err) call $ lookupTemplate nm hs _templateMap
where
err :: [Char]
err = [Char]
"callTemplate: "[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++(Text -> [Char]
T.unpack (Text -> [Char]) -> Text -> [Char]
forall a b. (a -> b) -> a -> b
$ ByteString -> Text
T.decodeUtf8 ByteString
nm)[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++([Char]
" does not exist")
call :: (DocumentFile, b) -> HeistT m IO (DList (Chunk m))
call (DocumentFile
df,b
_) = (HeistState m -> HeistState m)
-> HeistT m IO (DList (Chunk m)) -> HeistT m IO (DList (Chunk m))
forall (m :: * -> *) (n :: * -> *) a.
Monad m =>
(HeistState n -> HeistState n) -> HeistT n m a -> HeistT n m a
localHS (\HeistState m
hs' -> HeistState m
hs' {_curTemplateFile = dfFile df}) (HeistT m IO (DList (Chunk m)) -> HeistT m IO (DList (Chunk m)))
-> HeistT m IO (DList (Chunk m)) -> HeistT m IO (DList (Chunk m))
forall a b. (a -> b) -> a -> b
$
[Node] -> HeistT m IO (DList (Chunk m))
forall (n :: * -> *). Monad n => [Node] -> Splice n
runNodeList ([Node] -> HeistT m IO (DList (Chunk m)))
-> [Node] -> HeistT m IO (DList (Chunk m))
forall a b. (a -> b) -> a -> b
$ Document -> [Node]
X.docContent (Document -> [Node]) -> Document -> [Node]
forall a b. (a -> b) -> a -> b
$ DocumentFile -> Document
dfDoc DocumentFile
df
interpret :: Monad n => DList (Chunk n) -> n Builder
interpret :: forall (n :: * -> *). Monad n => DList (Chunk n) -> n Builder
interpret = (StateT HeterogeneousEnvironment n Builder
-> HeterogeneousEnvironment -> n Builder)
-> HeterogeneousEnvironment
-> StateT HeterogeneousEnvironment n Builder
-> n Builder
forall a b c. (a -> b -> c) -> b -> a -> c
flip StateT HeterogeneousEnvironment n Builder
-> HeterogeneousEnvironment -> n Builder
forall (m :: * -> *) s a. Monad m => StateT s m a -> s -> m a
evalStateT HeterogeneousEnvironment
HE.empty (StateT HeterogeneousEnvironment n Builder -> n Builder)
-> (DList (Chunk n) -> StateT HeterogeneousEnvironment n Builder)
-> DList (Chunk n)
-> n Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RuntimeSplice n Builder
-> StateT HeterogeneousEnvironment n Builder
forall (m :: * -> *) a.
RuntimeSplice m a -> StateT HeterogeneousEnvironment m a
unRT (RuntimeSplice n Builder
-> StateT HeterogeneousEnvironment n Builder)
-> (DList (Chunk n) -> RuntimeSplice n Builder)
-> DList (Chunk n)
-> StateT HeterogeneousEnvironment n Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DList (Chunk n) -> RuntimeSplice n Builder
forall (n :: * -> *).
Monad n =>
DList (Chunk n) -> RuntimeSplice n Builder
codeGen
textSplice :: (a -> Text) -> a -> Builder
textSplice :: forall a. (a -> Text) -> a -> Builder
textSplice a -> Text
f = Text -> Builder
fromText (Text -> Builder) -> (a -> Text) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Text
f
nodeSplice :: (a -> [X.Node]) -> a -> Builder
nodeSplice :: forall a. (a -> [Node]) -> a -> Builder
nodeSplice a -> [Node]
f = Encoding -> [Node] -> Builder
X.renderHtmlFragment Encoding
X.UTF8 ([Node] -> Builder) -> (a -> [Node]) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> [Node]
f
{-# DEPRECATED nodeSplice
"Use xmlNodeSplice or htmlNodeSplice, will be removed in Heist 1.1" #-}
xmlNodeSplice :: (a -> [X.Node]) -> a -> Builder
xmlNodeSplice :: forall a. (a -> [Node]) -> a -> Builder
xmlNodeSplice a -> [Node]
f = Encoding -> [Node] -> Builder
X.renderXmlFragment Encoding
X.UTF8 ([Node] -> Builder) -> (a -> [Node]) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> [Node]
f
htmlNodeSplice :: (a -> [X.Node]) -> a -> Builder
htmlNodeSplice :: forall a. (a -> [Node]) -> a -> Builder
htmlNodeSplice a -> [Node]
f = Encoding -> [Node] -> Builder
X.renderHtmlFragment Encoding
X.UTF8 ([Node] -> Builder) -> (a -> [Node]) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> [Node]
f
pureSplice :: Monad n => (a -> Builder) -> RuntimeSplice n a -> Splice n
pureSplice :: forall (n :: * -> *) a.
Monad n =>
(a -> Builder) -> RuntimeSplice n a -> Splice n
pureSplice a -> Builder
f RuntimeSplice n a
n = DList (Chunk n) -> HeistT n IO (DList (Chunk n))
forall a. a -> HeistT n IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (DList (Chunk n) -> HeistT n IO (DList (Chunk n)))
-> DList (Chunk n) -> HeistT n IO (DList (Chunk n))
forall a b. (a -> b) -> a -> b
$ RuntimeSplice n Builder -> DList (Chunk n)
forall (n :: * -> *). RuntimeSplice n Builder -> DList (Chunk n)
yieldRuntime (Builder -> RuntimeSplice n Builder
forall a. a -> RuntimeSplice n a
forall (m :: * -> *) a. Monad m => a -> m a
return (Builder -> RuntimeSplice n Builder)
-> (a -> Builder) -> a -> RuntimeSplice n Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Builder
f (a -> RuntimeSplice n Builder)
-> RuntimeSplice n a -> RuntimeSplice n Builder
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< RuntimeSplice n a
n)
withSplices :: Monad n
=> Splice n
-> Splices (RuntimeSplice n a -> Splice n)
-> RuntimeSplice n a
-> Splice n
withSplices :: forall (n :: * -> *) a.
Monad n =>
Splice n
-> Splices (RuntimeSplice n a -> Splice n)
-> RuntimeSplice n a
-> Splice n
withSplices Splice n
splice Splices (RuntimeSplice n a -> Splice n)
splices RuntimeSplice n a
runtimeAction =
Splices (Splice n)
-> Splices (AttrSplice n) -> Splice n -> Splice n
forall (n :: * -> *) a.
Splices (Splice n)
-> Splices (AttrSplice n) -> HeistT n IO a -> HeistT n IO a
withLocalSplices Splices (Splice n)
splices' Splices (AttrSplice n)
forall a. Monoid a => a
mempty Splice n
splice
where
splices' :: Splices (Splice n)
splices' = ((RuntimeSplice n a -> Splice n) -> Splice n)
-> Splices (RuntimeSplice n a -> Splice n) -> Splices (Splice n)
forall v1 v2 k a. (v1 -> v2) -> MapSyntaxM k v1 a -> MapSyntax k v2
mapV ((RuntimeSplice n a -> Splice n) -> RuntimeSplice n a -> Splice n
forall a b. (a -> b) -> a -> b
$ RuntimeSplice n a
runtimeAction) Splices (RuntimeSplice n a -> Splice n)
splices
{-# INLINE foldMapM #-}
foldMapM :: (Monad f, Monoid m, Foldable list)
=> (a -> f m)
-> list a
-> f m
foldMapM :: forall (f :: * -> *) m (list :: * -> *) a.
(Monad f, Monoid m, Foldable list) =>
(a -> f m) -> list a -> f m
foldMapM a -> f m
f =
(m -> a -> f m) -> m -> list a -> f m
forall (t :: * -> *) (m :: * -> *) b a.
(Foldable t, Monad m) =>
(b -> a -> m b) -> b -> t a -> m b
Foldable.foldlM (\m
xs a
x -> m
xs m -> f m -> f m
forall a b. a -> b -> b
`seq` (m -> m) -> f m -> f m
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM (m
xs m -> m -> m
forall a. Semigroup a => a -> a -> a
<>) (a -> f m
f a
x)) m
forall a. Monoid a => a
mempty
manyWithSplices :: (Foldable f, Monad n)
=> Splice n
-> Splices (RuntimeSplice n a -> Splice n)
-> RuntimeSplice n (f a)
-> Splice n
manyWithSplices :: forall (f :: * -> *) (n :: * -> *) a.
(Foldable f, Monad n) =>
Splice n
-> Splices (RuntimeSplice n a -> Splice n)
-> RuntimeSplice n (f a)
-> Splice n
manyWithSplices Splice n
splice Splices (RuntimeSplice n a -> Splice n)
splices RuntimeSplice n (f a)
runtimeAction =
Splice n
-> Splices (RuntimeSplice n a -> Splice n)
-> Splices (RuntimeSplice n a -> AttrSplice n)
-> RuntimeSplice n (f a)
-> Splice n
forall (f :: * -> *) (n :: * -> *) a.
(Foldable f, Monad n) =>
Splice n
-> Splices (RuntimeSplice n a -> Splice n)
-> Splices (RuntimeSplice n a -> AttrSplice n)
-> RuntimeSplice n (f a)
-> Splice n
manyWith Splice n
splice Splices (RuntimeSplice n a -> Splice n)
splices Splices (RuntimeSplice n a -> AttrSplice n)
forall a. Monoid a => a
mempty RuntimeSplice n (f a)
runtimeAction
manyWith :: (Foldable f, Monad n)
=> Splice n
-> Splices (RuntimeSplice n a -> Splice n)
-> Splices (RuntimeSplice n a -> AttrSplice n)
-> RuntimeSplice n (f a)
-> Splice n
manyWith :: forall (f :: * -> *) (n :: * -> *) a.
(Foldable f, Monad n) =>
Splice n
-> Splices (RuntimeSplice n a -> Splice n)
-> Splices (RuntimeSplice n a -> AttrSplice n)
-> RuntimeSplice n (f a)
-> Splice n
manyWith Splice n
splice Splices (RuntimeSplice n a -> Splice n)
splices Splices (RuntimeSplice n a -> AttrSplice n)
attrSplices RuntimeSplice n (f a)
runtimeAction = do
p <- HeistT n IO (Promise a)
forall (n :: * -> *) a. HeistT n IO (Promise a)
newEmptyPromise
let splices' = ((RuntimeSplice n a -> Splice n) -> Splice n)
-> Splices (RuntimeSplice n a -> Splice n)
-> MapSyntax Text (Splice n)
forall v1 v2 k a. (v1 -> v2) -> MapSyntaxM k v1 a -> MapSyntax k v2
mapV ((RuntimeSplice n a -> Splice n) -> RuntimeSplice n a -> Splice n
forall a b. (a -> b) -> a -> b
$ Promise a -> RuntimeSplice n a
forall (n :: * -> *) a. Monad n => Promise a -> RuntimeSplice n a
getPromise Promise a
p) Splices (RuntimeSplice n a -> Splice n)
splices
let attrSplices' = ((RuntimeSplice n a -> AttrSplice n) -> AttrSplice n)
-> Splices (RuntimeSplice n a -> AttrSplice n)
-> MapSyntax Text (AttrSplice n)
forall v1 v2 k a. (v1 -> v2) -> MapSyntaxM k v1 a -> MapSyntax k v2
mapV ((RuntimeSplice n a -> AttrSplice n)
-> RuntimeSplice n a -> AttrSplice n
forall a b. (a -> b) -> a -> b
$ Promise a -> RuntimeSplice n a
forall (n :: * -> *) a. Monad n => Promise a -> RuntimeSplice n a
getPromise Promise a
p) Splices (RuntimeSplice n a -> AttrSplice n)
attrSplices
chunks <- withLocalSplices splices' attrSplices' splice
return $ yieldRuntime $ do
items <- runtimeAction
foldMapM (\a
item -> Promise a -> a -> RuntimeSplice n ()
forall (n :: * -> *) a.
Monad n =>
Promise a -> a -> RuntimeSplice n ()
putPromise Promise a
p a
item RuntimeSplice n ()
-> RuntimeSplice n Builder -> RuntimeSplice n Builder
forall a b.
RuntimeSplice n a -> RuntimeSplice n b -> RuntimeSplice n b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> DList (Chunk n) -> RuntimeSplice n Builder
forall (n :: * -> *).
Monad n =>
DList (Chunk n) -> RuntimeSplice n Builder
codeGen DList (Chunk n)
chunks) items
deferMany :: (Foldable f, Monad n)
=> (RuntimeSplice n a -> Splice n)
-> RuntimeSplice n (f a)
-> Splice n
deferMany :: forall (f :: * -> *) (n :: * -> *) a.
(Foldable f, Monad n) =>
(RuntimeSplice n a -> Splice n)
-> RuntimeSplice n (f a) -> Splice n
deferMany RuntimeSplice n a -> Splice n
f RuntimeSplice n (f a)
getItems = do
promise <- HeistT n IO (Promise a)
forall (n :: * -> *) a. HeistT n IO (Promise a)
newEmptyPromise
chunks <- f $ getPromise promise
return $ yieldRuntime $ do
items <- getItems
foldMapM (\a
item -> Promise a -> a -> RuntimeSplice n ()
forall (n :: * -> *) a.
Monad n =>
Promise a -> a -> RuntimeSplice n ()
putPromise Promise a
promise a
item RuntimeSplice n ()
-> RuntimeSplice n Builder -> RuntimeSplice n Builder
forall a b.
RuntimeSplice n a -> RuntimeSplice n b -> RuntimeSplice n b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> DList (Chunk n) -> RuntimeSplice n Builder
forall (n :: * -> *).
Monad n =>
DList (Chunk n) -> RuntimeSplice n Builder
codeGen DList (Chunk n)
chunks) items
defer :: Monad n
=> (RuntimeSplice n a -> Splice n)
-> RuntimeSplice n a -> Splice n
defer :: forall (n :: * -> *) a.
Monad n =>
(RuntimeSplice n a -> Splice n) -> RuntimeSplice n a -> Splice n
defer RuntimeSplice n a -> Splice n
pf RuntimeSplice n a
n = do
p2 <- HeistT n IO (Promise a)
forall (n :: * -> *) a. HeistT n IO (Promise a)
newEmptyPromise
let action = RuntimeSplice n () -> DList (Chunk n)
forall (n :: * -> *).
Monad n =>
RuntimeSplice n () -> DList (Chunk n)
yieldRuntimeEffect (RuntimeSplice n () -> DList (Chunk n))
-> RuntimeSplice n () -> DList (Chunk n)
forall a b. (a -> b) -> a -> b
$ Promise a -> a -> RuntimeSplice n ()
forall (n :: * -> *) a.
Monad n =>
Promise a -> a -> RuntimeSplice n ()
putPromise Promise a
p2 (a -> RuntimeSplice n ())
-> RuntimeSplice n a -> RuntimeSplice n ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< RuntimeSplice n a
n
res <- pf $ getPromise p2
return $ action `mappend` res
deferMap :: Monad n
=> (a -> RuntimeSplice n b)
-> (RuntimeSplice n b -> Splice n)
-> RuntimeSplice n a -> Splice n
deferMap :: forall (n :: * -> *) a b.
Monad n =>
(a -> RuntimeSplice n b)
-> (RuntimeSplice n b -> Splice n) -> RuntimeSplice n a -> Splice n
deferMap a -> RuntimeSplice n b
f RuntimeSplice n b -> Splice n
pf RuntimeSplice n a
n = (RuntimeSplice n b -> Splice n) -> RuntimeSplice n b -> Splice n
forall (n :: * -> *) a.
Monad n =>
(RuntimeSplice n a -> Splice n) -> RuntimeSplice n a -> Splice n
defer RuntimeSplice n b -> Splice n
pf (RuntimeSplice n b -> Splice n) -> RuntimeSplice n b -> Splice n
forall a b. (a -> b) -> a -> b
$ a -> RuntimeSplice n b
f (a -> RuntimeSplice n b) -> RuntimeSplice n a -> RuntimeSplice n b
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< RuntimeSplice n a
n
mayDeferMap :: Monad n
=> (a -> RuntimeSplice n (Maybe b))
-> (RuntimeSplice n b -> Splice n)
-> RuntimeSplice n a -> Splice n
mayDeferMap :: forall (n :: * -> *) a b.
Monad n =>
(a -> RuntimeSplice n (Maybe b))
-> (RuntimeSplice n b -> Splice n) -> RuntimeSplice n a -> Splice n
mayDeferMap a -> RuntimeSplice n (Maybe b)
f RuntimeSplice n b -> Splice n
pf RuntimeSplice n a
n = (RuntimeSplice n b -> Splice n)
-> RuntimeSplice n (Maybe b) -> Splice n
forall (f :: * -> *) (n :: * -> *) a.
(Foldable f, Monad n) =>
(RuntimeSplice n a -> Splice n)
-> RuntimeSplice n (f a) -> Splice n
deferMany RuntimeSplice n b -> Splice n
pf (RuntimeSplice n (Maybe b) -> Splice n)
-> RuntimeSplice n (Maybe b) -> Splice n
forall a b. (a -> b) -> a -> b
$ a -> RuntimeSplice n (Maybe b)
f (a -> RuntimeSplice n (Maybe b))
-> RuntimeSplice n a -> RuntimeSplice n (Maybe b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< RuntimeSplice n a
n
bindLater :: (Monad n)
=> (a -> RuntimeSplice n Builder)
-> RuntimeSplice n a
-> Splice n
bindLater :: forall (n :: * -> *) a.
Monad n =>
(a -> RuntimeSplice n Builder) -> RuntimeSplice n a -> Splice n
bindLater a -> RuntimeSplice n Builder
f RuntimeSplice n a
p = DList (Chunk n) -> HeistT n IO (DList (Chunk n))
forall a. a -> HeistT n IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (DList (Chunk n) -> HeistT n IO (DList (Chunk n)))
-> DList (Chunk n) -> HeistT n IO (DList (Chunk n))
forall a b. (a -> b) -> a -> b
$ RuntimeSplice n Builder -> DList (Chunk n)
forall (n :: * -> *). RuntimeSplice n Builder -> DList (Chunk n)
yieldRuntime (RuntimeSplice n Builder -> DList (Chunk n))
-> RuntimeSplice n Builder -> DList (Chunk n)
forall a b. (a -> b) -> a -> b
$ a -> RuntimeSplice n Builder
f (a -> RuntimeSplice n Builder)
-> RuntimeSplice n a -> RuntimeSplice n Builder
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< RuntimeSplice n a
p