Compare commits
9 Commits
master
...
core-witho
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
12a82ff8a5 | ||
|
|
c5b27de2ab | ||
|
|
b94828121a | ||
|
|
10680f5108 | ||
|
|
11bf4d9c58 | ||
|
|
23c29b9a24 | ||
|
|
a890cc5329 | ||
|
|
b3733a67f7 | ||
|
|
c45a2c45df |
@ -1,4 +1,5 @@
|
|||||||
./yesod-core
|
./yesod-core
|
||||||
|
./yesod-shakespeare
|
||||||
./yesod-static
|
./yesod-static
|
||||||
./yesod-persistent
|
./yesod-persistent
|
||||||
./yesod-newsfeed
|
./yesod-newsfeed
|
||||||
|
|||||||
@ -13,5 +13,6 @@ packages:
|
|||||||
- ./yesod
|
- ./yesod
|
||||||
- ./yesod-eventsource
|
- ./yesod-eventsource
|
||||||
- ./yesod-websockets
|
- ./yesod-websockets
|
||||||
|
- ./yesod-shakespeare
|
||||||
extra-deps:
|
extra-deps:
|
||||||
- wai-app-static-3.1.0
|
- wai-app-static-3.1.0
|
||||||
|
|||||||
@ -24,6 +24,7 @@ import Web.Authenticate.OAuth
|
|||||||
import Yesod.Auth
|
import Yesod.Auth
|
||||||
import Yesod.Form
|
import Yesod.Form
|
||||||
import Yesod.Core
|
import Yesod.Core
|
||||||
|
import Yesod.Shakespeare
|
||||||
|
|
||||||
data YesodOAuthException = CredentialError String Credential
|
data YesodOAuthException = CredentialError String Credential
|
||||||
| SessionError String
|
| SessionError String
|
||||||
|
|||||||
@ -24,6 +24,7 @@ library
|
|||||||
build-depends: authenticate-oauth >= 1.5 && < 1.6
|
build-depends: authenticate-oauth >= 1.5 && < 1.6
|
||||||
, bytestring >= 0.9.1.4
|
, bytestring >= 0.9.1.4
|
||||||
, yesod-core >= 1.4 && < 1.5
|
, yesod-core >= 1.4 && < 1.5
|
||||||
|
, yesod-shakespeare >= 1.5 && < 1.6
|
||||||
, yesod-auth >= 1.4 && < 1.5
|
, yesod-auth >= 1.4 && < 1.5
|
||||||
, text >= 0.7
|
, text >= 0.7
|
||||||
, yesod-form >= 1.4 && < 1.5
|
, yesod-form >= 1.4 && < 1.5
|
||||||
|
|||||||
@ -63,6 +63,7 @@ import qualified Network.Wai as W
|
|||||||
|
|
||||||
import Yesod.Core
|
import Yesod.Core
|
||||||
import Yesod.Persist
|
import Yesod.Persist
|
||||||
|
import Yesod.Shakespeare
|
||||||
import Yesod.Auth.Message (AuthMessage, defaultMessage)
|
import Yesod.Auth.Message (AuthMessage, defaultMessage)
|
||||||
import qualified Yesod.Auth.Message as Msg
|
import qualified Yesod.Auth.Message as Msg
|
||||||
import Yesod.Form (FormMessage)
|
import Yesod.Form (FormMessage)
|
||||||
@ -146,7 +147,7 @@ class (Yesod master, PathPiece (AuthId master), RenderMessage master FormMessage
|
|||||||
authPlugins :: master -> [AuthPlugin master]
|
authPlugins :: master -> [AuthPlugin master]
|
||||||
|
|
||||||
-- | What to show on the login page.
|
-- | What to show on the login page.
|
||||||
--
|
--
|
||||||
-- Default handler concatenates plugin widgets and wraps the result
|
-- Default handler concatenates plugin widgets and wraps the result
|
||||||
-- in 'authLayout'. Override if you need fancy widget containers
|
-- in 'authLayout'. Override if you need fancy widget containers
|
||||||
-- or entirely custom page.
|
-- or entirely custom page.
|
||||||
|
|||||||
@ -61,6 +61,7 @@ import Data.Text.Encoding (encodeUtf8, decodeUtf8With)
|
|||||||
import Data.Text.Encoding.Error (lenientDecode)
|
import Data.Text.Encoding.Error (lenientDecode)
|
||||||
import Data.Text (Text)
|
import Data.Text (Text)
|
||||||
import Yesod.Core
|
import Yesod.Core
|
||||||
|
import Yesod.Shakespeare
|
||||||
import qualified Yesod.PasswordStore as PS
|
import qualified Yesod.PasswordStore as PS
|
||||||
import qualified Text.Email.Validate
|
import qualified Text.Email.Validate
|
||||||
import qualified Yesod.Auth.Message as Msg
|
import qualified Yesod.Auth.Message as Msg
|
||||||
|
|||||||
@ -21,6 +21,7 @@ import Yesod.Auth
|
|||||||
import qualified Web.Authenticate.OpenId as OpenId
|
import qualified Web.Authenticate.OpenId as OpenId
|
||||||
|
|
||||||
import Yesod.Core
|
import Yesod.Core
|
||||||
|
import Yesod.Shakespeare
|
||||||
import Data.Text (Text)
|
import Data.Text (Text)
|
||||||
import qualified Yesod.Auth.Message as Msg
|
import qualified Yesod.Auth.Message as Msg
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
|
|||||||
@ -83,8 +83,9 @@ import Yesod.Core (HandlerSite, MonadHandler,
|
|||||||
getYesod, invalidArgs, lift,
|
getYesod, invalidArgs, lift,
|
||||||
lookupGetParam,
|
lookupGetParam,
|
||||||
lookupSession, notFound, redirect,
|
lookupSession, notFound, redirect,
|
||||||
setSession, whamlet, (.:),
|
setSession, (.:),
|
||||||
TypedContent, HandlerT, liftIO)
|
TypedContent, HandlerT, liftIO)
|
||||||
|
import Yesod.Shakespeare (whamlet)
|
||||||
|
|
||||||
pid :: Text
|
pid :: Text
|
||||||
pid = "googleemail2"
|
pid = "googleemail2"
|
||||||
|
|||||||
@ -17,6 +17,7 @@ import qualified Web.Authenticate.OpenId as OpenId
|
|||||||
|
|
||||||
import Yesod.Form
|
import Yesod.Form
|
||||||
import Yesod.Core
|
import Yesod.Core
|
||||||
|
import Yesod.Shakespeare
|
||||||
import Text.Cassius (cassius)
|
import Text.Cassius (cassius)
|
||||||
import Data.Text (Text, isPrefixOf)
|
import Data.Text (Text, isPrefixOf)
|
||||||
import qualified Yesod.Auth.Message as Msg
|
import qualified Yesod.Auth.Message as Msg
|
||||||
@ -92,7 +93,7 @@ completeHelper idType gets' = do
|
|||||||
eres <- try $ OpenId.authenticateClaimed gets' (authHttpManager master)
|
eres <- try $ OpenId.authenticateClaimed gets' (authHttpManager master)
|
||||||
either onFailure onSuccess eres
|
either onFailure onSuccess eres
|
||||||
where
|
where
|
||||||
onFailure err = do
|
onFailure err = do
|
||||||
tm <- getRouteToParent
|
tm <- getRouteToParent
|
||||||
lift $ loginErrorMessage (tm LoginR) $ T.pack $
|
lift $ loginErrorMessage (tm LoginR) $ T.pack $
|
||||||
show (err :: SomeException)
|
show (err :: SomeException)
|
||||||
|
|||||||
@ -24,6 +24,7 @@ library
|
|||||||
, authenticate >= 1.3
|
, authenticate >= 1.3
|
||||||
, bytestring >= 0.9.1.4
|
, bytestring >= 0.9.1.4
|
||||||
, yesod-core >= 1.4 && < 1.5
|
, yesod-core >= 1.4 && < 1.5
|
||||||
|
, yesod-shakespeare >= 1.5 && < 1.6
|
||||||
, wai >= 1.4
|
, wai >= 1.4
|
||||||
, template-haskell
|
, template-haskell
|
||||||
, base16-bytestring
|
, base16-bytestring
|
||||||
|
|||||||
@ -28,7 +28,6 @@ module Yesod.Core
|
|||||||
, authorizationCheck
|
, authorizationCheck
|
||||||
-- * Data types
|
-- * Data types
|
||||||
, AuthResult (..)
|
, AuthResult (..)
|
||||||
, unauthorizedI
|
|
||||||
-- * Logging
|
-- * Logging
|
||||||
, defaultMakeLogger
|
, defaultMakeLogger
|
||||||
, defaultMessageLoggerSource
|
, defaultMessageLoggerSource
|
||||||
@ -57,9 +56,6 @@ module Yesod.Core
|
|||||||
, clientSessionDateCacher
|
, clientSessionDateCacher
|
||||||
, loadClientSession
|
, loadClientSession
|
||||||
, Header(..)
|
, Header(..)
|
||||||
-- * JS loaders
|
|
||||||
, ScriptLoadPosition (..)
|
|
||||||
, BottomOfHeadAsync
|
|
||||||
-- * Subsites
|
-- * Subsites
|
||||||
, MonadHandler (..)
|
, MonadHandler (..)
|
||||||
, MonadWidget (..)
|
, MonadWidget (..)
|
||||||
@ -79,7 +75,6 @@ module Yesod.Core
|
|||||||
, module Yesod.Core.Handler
|
, module Yesod.Core.Handler
|
||||||
, module Yesod.Core.Widget
|
, module Yesod.Core.Widget
|
||||||
, module Yesod.Core.Json
|
, module Yesod.Core.Json
|
||||||
, module Text.Shakespeare.I18N
|
|
||||||
, module Yesod.Core.Internal.Util
|
, module Yesod.Core.Internal.Util
|
||||||
, module Text.Blaze.Html
|
, module Text.Blaze.Html
|
||||||
, MonadTrans (..)
|
, MonadTrans (..)
|
||||||
@ -93,21 +88,6 @@ module Yesod.Core
|
|||||||
-- * Utilities
|
-- * Utilities
|
||||||
, showIntegral
|
, showIntegral
|
||||||
, readIntegral
|
, readIntegral
|
||||||
-- * Shakespeare
|
|
||||||
-- ** Hamlet
|
|
||||||
, hamlet
|
|
||||||
, shamlet
|
|
||||||
, xhamlet
|
|
||||||
, HtmlUrl
|
|
||||||
-- ** Julius
|
|
||||||
, julius
|
|
||||||
, JavascriptUrl
|
|
||||||
, renderJavascriptUrl
|
|
||||||
-- ** Cassius/Lucius
|
|
||||||
, cassius
|
|
||||||
, lucius
|
|
||||||
, CssUrl
|
|
||||||
, renderCssUrl
|
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Yesod.Core.Content
|
import Yesod.Core.Content
|
||||||
@ -117,7 +97,6 @@ import Yesod.Core.Class.Handler
|
|||||||
import Yesod.Core.Widget
|
import Yesod.Core.Widget
|
||||||
import Yesod.Core.Json
|
import Yesod.Core.Json
|
||||||
import Yesod.Core.Types
|
import Yesod.Core.Types
|
||||||
import Text.Shakespeare.I18N
|
|
||||||
import Yesod.Core.Internal.Util (formatW3 , formatRFC1123 , formatRFC822)
|
import Yesod.Core.Internal.Util (formatW3 , formatRFC1123 , formatRFC822)
|
||||||
import Text.Blaze.Html (Html, toHtml, preEscapedToMarkup)
|
import Text.Blaze.Html (Html, toHtml, preEscapedToMarkup)
|
||||||
|
|
||||||
@ -139,10 +118,6 @@ import Control.Monad.Trans.Control (MonadBaseControl (..))
|
|||||||
|
|
||||||
import Control.Monad.Trans.Resource (MonadResource (..))
|
import Control.Monad.Trans.Resource (MonadResource (..))
|
||||||
import Yesod.Core.Internal.LiteApp
|
import Yesod.Core.Internal.LiteApp
|
||||||
import Text.Hamlet
|
|
||||||
import Text.Cassius
|
|
||||||
import Text.Lucius
|
|
||||||
import Text.Julius
|
|
||||||
import Network.Wai (Application)
|
import Network.Wai (Application)
|
||||||
|
|
||||||
runFakeHandler :: (Yesod site, MonadIO m) =>
|
runFakeHandler :: (Yesod site, MonadIO m) =>
|
||||||
@ -154,12 +129,6 @@ runFakeHandler :: (Yesod site, MonadIO m) =>
|
|||||||
runFakeHandler = Yesod.Core.Internal.Run.runFakeHandler
|
runFakeHandler = Yesod.Core.Internal.Run.runFakeHandler
|
||||||
{-# DEPRECATED runFakeHandler "import runFakeHandler from Yesod.Core.Unsafe" #-}
|
{-# DEPRECATED runFakeHandler "import runFakeHandler from Yesod.Core.Unsafe" #-}
|
||||||
|
|
||||||
-- | Return an 'Unauthorized' value, with the given i18n message.
|
|
||||||
unauthorizedI :: (MonadHandler m, RenderMessage (HandlerSite m) msg) => msg -> m AuthResult
|
|
||||||
unauthorizedI msg = do
|
|
||||||
mr <- getMessageRender
|
|
||||||
return $ Unauthorized $ mr msg
|
|
||||||
|
|
||||||
yesodVersion :: String
|
yesodVersion :: String
|
||||||
yesodVersion = showVersion Paths_yesod_core.version
|
yesodVersion = showVersion Paths_yesod_core.version
|
||||||
|
|
||||||
|
|||||||
@ -7,12 +7,9 @@
|
|||||||
{-# LANGUAGE UndecidableInstances #-}
|
{-# LANGUAGE UndecidableInstances #-}
|
||||||
module Yesod.Core.Class.Handler
|
module Yesod.Core.Class.Handler
|
||||||
( MonadHandler (..)
|
( MonadHandler (..)
|
||||||
, MonadWidget (..)
|
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Yesod.Core.Types
|
import Yesod.Core.Types
|
||||||
import Data.Monoid (mempty)
|
|
||||||
import Control.Monad (liftM)
|
|
||||||
import Control.Monad.IO.Class (liftIO)
|
import Control.Monad.IO.Class (liftIO)
|
||||||
import Control.Monad.Trans.Resource (MonadResource, MonadResourceBase)
|
import Control.Monad.Trans.Resource (MonadResource, MonadResourceBase)
|
||||||
import Control.Monad.Trans.Class (lift)
|
import Control.Monad.Trans.Class (lift)
|
||||||
@ -43,11 +40,6 @@ instance MonadResourceBase m => MonadHandler (HandlerT site m) where
|
|||||||
liftHandlerT (HandlerT f) = HandlerT $ liftIO . f . replaceToParent
|
liftHandlerT (HandlerT f) = HandlerT $ liftIO . f . replaceToParent
|
||||||
{-# RULES "liftHandlerT (HandlerT site IO)" liftHandlerT = id #-}
|
{-# RULES "liftHandlerT (HandlerT site IO)" liftHandlerT = id #-}
|
||||||
|
|
||||||
instance MonadResourceBase m => MonadHandler (WidgetT site m) where
|
|
||||||
type HandlerSite (WidgetT site m) = site
|
|
||||||
liftHandlerT (HandlerT f) = WidgetT $ liftIO . liftM (, mempty) . f . replaceToParent
|
|
||||||
{-# RULES "liftHandlerT (WidgetT site IO)" forall f. liftHandlerT (HandlerT f) = WidgetT $ liftM (, mempty) . f #-}
|
|
||||||
|
|
||||||
#define GO(T) instance MonadHandler m => MonadHandler (T m) where type HandlerSite (T m) = HandlerSite m; liftHandlerT = lift . liftHandlerT
|
#define GO(T) instance MonadHandler m => MonadHandler (T m) where type HandlerSite (T m) = HandlerSite m; liftHandlerT = lift . liftHandlerT
|
||||||
#define GOX(X, T) instance (X, MonadHandler m) => MonadHandler (T m) where type HandlerSite (T m) = HandlerSite m; liftHandlerT = lift . liftHandlerT
|
#define GOX(X, T) instance (X, MonadHandler m) => MonadHandler (T m) where type HandlerSite (T m) = HandlerSite m; liftHandlerT = lift . liftHandlerT
|
||||||
GO(IdentityT)
|
GO(IdentityT)
|
||||||
@ -65,26 +57,3 @@ GO(Pipe l i o u)
|
|||||||
GO(ConduitM i o)
|
GO(ConduitM i o)
|
||||||
#undef GO
|
#undef GO
|
||||||
#undef GOX
|
#undef GOX
|
||||||
|
|
||||||
class MonadHandler m => MonadWidget m where
|
|
||||||
liftWidgetT :: WidgetT (HandlerSite m) IO a -> m a
|
|
||||||
instance MonadResourceBase m => MonadWidget (WidgetT site m) where
|
|
||||||
liftWidgetT (WidgetT f) = WidgetT $ liftIO . f . replaceToParent
|
|
||||||
|
|
||||||
#define GO(T) instance MonadWidget m => MonadWidget (T m) where liftWidgetT = lift . liftWidgetT
|
|
||||||
#define GOX(X, T) instance (X, MonadWidget m) => MonadWidget (T m) where liftWidgetT = lift . liftWidgetT
|
|
||||||
GO(IdentityT)
|
|
||||||
GO(ListT)
|
|
||||||
GO(MaybeT)
|
|
||||||
GOX(Error e, ErrorT e)
|
|
||||||
GO(ReaderT r)
|
|
||||||
GO(StateT s)
|
|
||||||
GOX(Monoid w, WriterT w)
|
|
||||||
GOX(Monoid w, RWST r w s)
|
|
||||||
GOX(Monoid w, Strict.RWST r w s)
|
|
||||||
GO(Strict.StateT s)
|
|
||||||
GOX(Monoid w, Strict.WriterT w)
|
|
||||||
GO(Pipe l i o u)
|
|
||||||
GO(ConduitM i o)
|
|
||||||
#undef GO
|
|
||||||
#undef GOX
|
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
{-# LANGUAGE CPP #-}
|
{-# LANGUAGE CPP #-}
|
||||||
module Yesod.Core.Class.Yesod where
|
module Yesod.Core.Class.Yesod where
|
||||||
|
|
||||||
|
import Control.Monad (mplus)
|
||||||
import Control.Monad.Logger (logErrorS)
|
import Control.Monad.Logger (logErrorS)
|
||||||
import Yesod.Core.Content
|
import Yesod.Core.Content
|
||||||
import Yesod.Core.Handler
|
import Yesod.Core.Handler
|
||||||
@ -15,24 +16,22 @@ import Blaze.ByteString.Builder (Builder)
|
|||||||
import Blaze.ByteString.Builder.Char.Utf8 (fromText)
|
import Blaze.ByteString.Builder.Char.Utf8 (fromText)
|
||||||
import Control.Arrow ((***), second)
|
import Control.Arrow ((***), second)
|
||||||
import Control.Exception (bracket)
|
import Control.Exception (bracket)
|
||||||
import Control.Monad (forM, when, void)
|
import Control.Monad (when, void)
|
||||||
import Control.Monad.IO.Class (MonadIO (liftIO))
|
import Control.Monad.IO.Class (MonadIO (liftIO))
|
||||||
import Control.Monad.Logger (LogLevel (LevelInfo, LevelOther),
|
import Control.Monad.Logger (LogLevel (LevelInfo, LevelOther),
|
||||||
LogSource)
|
LogSource)
|
||||||
import Control.Monad.Trans.Resource (InternalState, createInternalState, closeInternalState)
|
import Control.Monad.Trans.Resource (InternalState, createInternalState, closeInternalState)
|
||||||
|
import qualified Data.Aeson as J
|
||||||
import qualified Data.ByteString.Char8 as S8
|
import qualified Data.ByteString.Char8 as S8
|
||||||
import qualified Data.ByteString.Lazy as L
|
import qualified Data.ByteString.Lazy as L
|
||||||
import Data.Aeson (object, (.=))
|
import Data.Aeson (object, (.=))
|
||||||
import Data.List (foldl')
|
|
||||||
import Data.List (nub)
|
|
||||||
import qualified Data.Map as Map
|
import qualified Data.Map as Map
|
||||||
|
import Data.Maybe (fromMaybe)
|
||||||
import Data.Monoid
|
import Data.Monoid
|
||||||
import Data.Text (Text)
|
import Data.Text (Text)
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
import qualified Data.Text.Encoding as TE
|
import qualified Data.Text.Encoding as TE
|
||||||
import qualified Data.Text.Encoding.Error as TEE
|
import qualified Data.Text.Encoding.Error as TEE
|
||||||
import Data.Text.Lazy.Builder (toLazyText)
|
|
||||||
import Data.Text.Lazy.Encoding (encodeUtf8)
|
|
||||||
import Data.Word (Word64)
|
import Data.Word (Word64)
|
||||||
import Language.Haskell.TH.Syntax (Loc (..))
|
import Language.Haskell.TH.Syntax (Loc (..))
|
||||||
import Network.HTTP.Types (encodePath)
|
import Network.HTTP.Types (encodePath)
|
||||||
@ -42,19 +41,18 @@ import Network.Wai.Parse (lbsBackEnd,
|
|||||||
tempFileBackEnd)
|
tempFileBackEnd)
|
||||||
import Network.Wai.Logger (ZonedDate, clockDateCacher)
|
import Network.Wai.Logger (ZonedDate, clockDateCacher)
|
||||||
import System.Log.FastLogger
|
import System.Log.FastLogger
|
||||||
import Text.Blaze (customAttribute, textTag,
|
import Text.Blaze.Html (Html)
|
||||||
toValue, (!))
|
|
||||||
import Text.Blaze (preEscapedToMarkup)
|
|
||||||
import qualified Text.Blaze.Html5 as TBH
|
import qualified Text.Blaze.Html5 as TBH
|
||||||
import Text.Hamlet
|
|
||||||
import Text.Julius
|
|
||||||
import qualified Web.ClientSession as CS
|
import qualified Web.ClientSession as CS
|
||||||
import Web.Cookie (parseCookies)
|
import Web.Cookie (parseCookies)
|
||||||
import Web.Cookie (SetCookie (..))
|
import Web.Cookie (SetCookie (..))
|
||||||
import Yesod.Core.Types
|
import Yesod.Core.Types
|
||||||
import Yesod.Core.Internal.Session
|
import Yesod.Core.Internal.Session
|
||||||
import Yesod.Core.Widget
|
|
||||||
import Control.Monad.Trans.Class (lift)
|
-- for jsLoader and defaultErrorHandler
|
||||||
|
import Yesod.Core.Widget (WidgetT, toWidget, setTitle, PageContent(..), ScriptLoadPosition(BottomOfBody), getMessage, widgetToPageContentUnbound)
|
||||||
|
import qualified Data.Foldable
|
||||||
|
|
||||||
|
|
||||||
-- | Define settings for a Yesod applications. All methods have intelligent
|
-- | Define settings for a Yesod applications. All methods have intelligent
|
||||||
-- defaults, and therefore no implementation is required.
|
-- defaults, and therefore no implementation is required.
|
||||||
@ -83,21 +81,7 @@ class RenderRoute site => Yesod site where
|
|||||||
|
|
||||||
-- | Applies some form of layout to the contents of a page.
|
-- | Applies some form of layout to the contents of a page.
|
||||||
defaultLayout :: WidgetT site IO () -> HandlerT site IO Html
|
defaultLayout :: WidgetT site IO () -> HandlerT site IO Html
|
||||||
defaultLayout w = do
|
defaultLayout = defaultDefaultLayout
|
||||||
p <- widgetToPageContent w
|
|
||||||
mmsg <- getMessage
|
|
||||||
withUrlRenderer [hamlet|
|
|
||||||
$newline never
|
|
||||||
$doctype 5
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>#{pageTitle p}
|
|
||||||
^{pageHead p}
|
|
||||||
<body>
|
|
||||||
$maybe msg <- mmsg
|
|
||||||
<p .message>#{msg}
|
|
||||||
^{pageBody p}
|
|
||||||
|]
|
|
||||||
|
|
||||||
-- | Override the rendering function for a particular URL. One use case for
|
-- | Override the rendering function for a particular URL. One use case for
|
||||||
-- this is to offload static hosting to a different domain name to avoid
|
-- this is to offload static hosting to a different domain name to avoid
|
||||||
@ -411,103 +395,74 @@ authorizationCheck = do
|
|||||||
void $ notAuthenticated
|
void $ notAuthenticated
|
||||||
Unauthorized s' -> permissionDenied s'
|
Unauthorized s' -> permissionDenied s'
|
||||||
|
|
||||||
-- | Convert a widget to a 'PageContent'.
|
|
||||||
widgetToPageContent :: (Eq (Route site), Yesod site)
|
|
||||||
=> WidgetT site IO ()
|
|
||||||
-> HandlerT site IO (PageContent (Route site))
|
|
||||||
widgetToPageContent w = do
|
|
||||||
master <- getYesod
|
|
||||||
hd <- HandlerT return
|
|
||||||
((), GWData (Body body) (Last mTitle) scripts' stylesheets' style jscript (Head head')) <- lift $ unWidgetT w hd
|
|
||||||
let title = maybe mempty unTitle mTitle
|
|
||||||
scripts = runUniqueList scripts'
|
|
||||||
stylesheets = runUniqueList stylesheets'
|
|
||||||
|
|
||||||
render <- getUrlRenderParams
|
-- templating types
|
||||||
let renderLoc x =
|
type Render url = url -> [(Text, Text)] -> Text
|
||||||
case x of
|
type HtmlUrl url = Render url -> Html
|
||||||
Nothing -> Nothing
|
|
||||||
Just (Left s) -> Just s
|
|
||||||
Just (Right (u, p)) -> Just $ render u p
|
|
||||||
css <- forM (Map.toList style) $ \(mmedia, content) -> do
|
|
||||||
let rendered = toLazyText $ content render
|
|
||||||
x <- addStaticContent "css" "text/css; charset=utf-8"
|
|
||||||
$ encodeUtf8 rendered
|
|
||||||
return (mmedia,
|
|
||||||
case x of
|
|
||||||
Nothing -> Left $ preEscapedToMarkup rendered
|
|
||||||
Just y -> Right $ either id (uncurry render) y)
|
|
||||||
jsLoc <-
|
|
||||||
case jscript of
|
|
||||||
Nothing -> return Nothing
|
|
||||||
Just s -> do
|
|
||||||
x <- addStaticContent "js" "text/javascript; charset=utf-8"
|
|
||||||
$ encodeUtf8 $ renderJavascriptUrl render s
|
|
||||||
return $ renderLoc x
|
|
||||||
|
|
||||||
-- modernizr should be at the end of the <head> http://www.modernizr.com/docs/#installing
|
maybeH :: Monad m => Maybe a -> (a -> m ()) -> Maybe (m ()) -> m ()
|
||||||
-- the asynchronous loader means your page doesn't have to wait for all the js to load
|
maybeH mv f mm = fromMaybe (return ()) $ fmap f mv `mplus` mm
|
||||||
let (mcomplete, asyncScripts) = asyncHelper render scripts jscript jsLoc
|
|
||||||
regularScriptLoad = [hamlet|
|
|
||||||
$newline never
|
|
||||||
$forall s <- scripts
|
|
||||||
^{mkScriptTag s}
|
|
||||||
$maybe j <- jscript
|
|
||||||
$maybe s <- jsLoc
|
|
||||||
<script src="#{s}">
|
|
||||||
$nothing
|
|
||||||
<script>^{jelper j}
|
|
||||||
|]
|
|
||||||
|
|
||||||
headAll = [hamlet|
|
|
||||||
$newline never
|
|
||||||
\^{head'}
|
|
||||||
$forall s <- stylesheets
|
|
||||||
^{mkLinkTag s}
|
|
||||||
$forall s <- css
|
|
||||||
$maybe t <- right $ snd s
|
|
||||||
$maybe media <- fst s
|
|
||||||
<link rel=stylesheet media=#{media} href=#{t}>
|
|
||||||
$nothing
|
|
||||||
<link rel=stylesheet href=#{t}>
|
|
||||||
$maybe content <- left $ snd s
|
|
||||||
$maybe media <- fst s
|
|
||||||
<style media=#{media}>#{content}
|
|
||||||
$nothing
|
|
||||||
<style>#{content}
|
|
||||||
$case jsLoader master
|
|
||||||
$of BottomOfBody
|
|
||||||
$of BottomOfHeadAsync asyncJsLoader
|
|
||||||
^{asyncJsLoader asyncScripts mcomplete}
|
|
||||||
$of BottomOfHeadBlocking
|
|
||||||
^{regularScriptLoad}
|
|
||||||
|]
|
|
||||||
let bodyScript = [hamlet|
|
|
||||||
$newline never
|
|
||||||
^{body}
|
|
||||||
^{regularScriptLoad}
|
|
||||||
|]
|
|
||||||
|
|
||||||
return $ PageContent title headAll $
|
widgetToPageContent
|
||||||
case jsLoader master of
|
:: (Yesod site, Eq (Route site))
|
||||||
BottomOfBody -> bodyScript
|
=> WidgetT site IO ()
|
||||||
_ -> body
|
-> HandlerT site IO (PageContent (Route site))
|
||||||
|
widgetToPageContent = widgetToPageContentUnbound addStaticContent jsLoader
|
||||||
|
|
||||||
|
|
||||||
|
-- | Provide both an HTML and JSON representation for a piece of
|
||||||
|
-- data, using the default layout for the HTML output
|
||||||
|
-- ('defaultLayout').
|
||||||
|
--
|
||||||
|
-- /Since: 0.3.0/
|
||||||
|
defaultLayoutJson :: (Yesod site, J.ToJSON a)
|
||||||
|
=> WidgetT site IO () -- ^ HTML
|
||||||
|
-> HandlerT site IO a -- ^ JSON
|
||||||
|
-> HandlerT site IO TypedContent
|
||||||
|
defaultLayoutJson w json = selectRep $ do
|
||||||
|
provideRep $ defaultLayout w
|
||||||
|
provideRep $ fmap J.toJSON json
|
||||||
|
|
||||||
|
|
||||||
|
defaultDefaultLayout :: Yesod site => WidgetT site IO () -> HandlerT site IO Html
|
||||||
|
defaultDefaultLayout w = do
|
||||||
|
p <- widgetToPageContent w
|
||||||
|
mmsg <- getMessage
|
||||||
|
withUrlRenderer $ htmlTemplate p mmsg
|
||||||
where
|
where
|
||||||
renderLoc' render' (Local url) = render' url []
|
asHtmlUrl :: HtmlUrl url -> HtmlUrl url
|
||||||
renderLoc' _ (Remote s) = s
|
asHtmlUrl = id
|
||||||
|
|
||||||
addAttr x (y, z) = x ! customAttribute (textTag y) (toValue z)
|
-- equivalent to
|
||||||
mkScriptTag (Script loc attrs) render' =
|
-- [hamlet|
|
||||||
foldl' addAttr TBH.script (("src", renderLoc' render' loc) : attrs) $ return ()
|
-- $newline never
|
||||||
mkLinkTag (Stylesheet loc attrs) render' =
|
-- $doctype 5
|
||||||
foldl' addAttr TBH.link
|
-- <html>
|
||||||
( ("rel", "stylesheet")
|
-- <head>
|
||||||
: ("href", renderLoc' render' loc)
|
-- <title>#{pageTitle p}
|
||||||
: attrs
|
-- ^{pageHead p}
|
||||||
)
|
-- <body>
|
||||||
|
-- $maybe msg <- mmsg
|
||||||
|
-- <p .message>#{msg}
|
||||||
|
-- ^{pageBody p}
|
||||||
|
-- |]
|
||||||
|
htmlTemplate p mmsg = \_render_afYl -> do
|
||||||
|
TBH.preEscapedText $ T.pack "<!DOCTYPE html>\n<html><head><title>"
|
||||||
|
TBH.toHtml (pageTitle p)
|
||||||
|
TBH.preEscapedText $ T.pack "</title>"
|
||||||
|
asHtmlUrl (pageHead p) _render_afYl
|
||||||
|
TBH.preEscapedText $ T.pack "</head><body>"
|
||||||
|
maybeH
|
||||||
|
mmsg
|
||||||
|
(\ msg_afYm
|
||||||
|
-> do { id ((TBH.preEscapedText . T.pack) "<p class=\"message\">");
|
||||||
|
id (TBH.toHtml msg_afYm);
|
||||||
|
id ((TBH.preEscapedText . T.pack) "</p>") })
|
||||||
|
Nothing
|
||||||
|
asHtmlUrl (pageBody p) _render_afYl
|
||||||
|
(TBH.preEscapedText . T.pack) "</body></html>"
|
||||||
|
|
||||||
runUniqueList :: Eq x => UniqueList x -> [x]
|
|
||||||
runUniqueList (UniqueList x) = nub $ x []
|
|
||||||
|
|
||||||
-- | The default error handler for 'errorHandler'.
|
-- | The default error handler for 'errorHandler'.
|
||||||
defaultErrorHandler :: Yesod site => ErrorResponse -> HandlerT site IO TypedContent
|
defaultErrorHandler :: Yesod site => ErrorResponse -> HandlerT site IO TypedContent
|
||||||
@ -516,11 +471,19 @@ defaultErrorHandler NotFound = selectRep $ do
|
|||||||
r <- waiRequest
|
r <- waiRequest
|
||||||
let path' = TE.decodeUtf8With TEE.lenientDecode $ W.rawPathInfo r
|
let path' = TE.decodeUtf8With TEE.lenientDecode $ W.rawPathInfo r
|
||||||
setTitle "Not Found"
|
setTitle "Not Found"
|
||||||
toWidget [hamlet|
|
toWidget $ htmlTemplate path'
|
||||||
<h1>Not Found
|
|
||||||
<p>#{path'}
|
|
||||||
|]
|
|
||||||
provideRep $ return $ object ["message" .= ("Not Found" :: Text)]
|
provideRep $ return $ object ["message" .= ("Not Found" :: Text)]
|
||||||
|
where
|
||||||
|
-- equivalent to
|
||||||
|
--
|
||||||
|
-- [hamlet|
|
||||||
|
-- <h1>Not Found
|
||||||
|
-- <p>#{path'}
|
||||||
|
-- |]
|
||||||
|
htmlTemplate path' = \_renderer -> do
|
||||||
|
TBH.preEscapedText $ T.pack "<h1>Not Found</h1>\n<p>"
|
||||||
|
TBH.toHtml path'
|
||||||
|
TBH.preEscapedText $ T.pack "</p>"
|
||||||
|
|
||||||
-- For API requests.
|
-- For API requests.
|
||||||
-- For a user with a browser,
|
-- For a user with a browser,
|
||||||
@ -529,10 +492,7 @@ defaultErrorHandler NotFound = selectRep $ do
|
|||||||
defaultErrorHandler NotAuthenticated = selectRep $ do
|
defaultErrorHandler NotAuthenticated = selectRep $ do
|
||||||
provideRep $ defaultLayout $ do
|
provideRep $ defaultLayout $ do
|
||||||
setTitle "Not logged in"
|
setTitle "Not logged in"
|
||||||
toWidget [hamlet|
|
toWidget htmlTemplate
|
||||||
<h1>Not logged in
|
|
||||||
<p style="display:none;">Set the authRoute and the user will be redirected there.
|
|
||||||
|]
|
|
||||||
|
|
||||||
provideRep $ do
|
provideRep $ do
|
||||||
-- 401 *MUST* include a WWW-Authenticate header
|
-- 401 *MUST* include a WWW-Authenticate header
|
||||||
@ -550,70 +510,97 @@ defaultErrorHandler NotAuthenticated = selectRep $ do
|
|||||||
case authRoute site of
|
case authRoute site of
|
||||||
Nothing -> []
|
Nothing -> []
|
||||||
Just url -> ["authentication_url" .= rend url]
|
Just url -> ["authentication_url" .= rend url]
|
||||||
|
where
|
||||||
|
-- equivalent to
|
||||||
|
-- [hamlet|
|
||||||
|
-- <h1>Not logged in
|
||||||
|
-- <p style="display:none;">Set the authRoute and the user will be redirected there.
|
||||||
|
-- |]
|
||||||
|
htmlTemplate = \_renderer -> TBH.preEscapedText $ T.pack
|
||||||
|
"<h1>Not logged in</h1>\n<p style=\"display:none;\">Set the authRoute and the user will be redirected there.</p>"
|
||||||
|
|
||||||
|
|
||||||
defaultErrorHandler (PermissionDenied msg) = selectRep $ do
|
defaultErrorHandler (PermissionDenied msg) = selectRep $ do
|
||||||
provideRep $ defaultLayout $ do
|
provideRep $ defaultLayout $ do
|
||||||
setTitle "Permission Denied"
|
setTitle "Permission Denied"
|
||||||
toWidget [hamlet|
|
toWidget htmlTemplate
|
||||||
<h1>Permission denied
|
|
||||||
<p>#{msg}
|
|
||||||
|]
|
|
||||||
provideRep $
|
provideRep $
|
||||||
return $ object $ [
|
return $ object $ [
|
||||||
"message" .= ("Permission Denied. " <> msg)
|
"message" .= ("Permission Denied. " <> msg)
|
||||||
]
|
]
|
||||||
|
where
|
||||||
|
-- equivalent to
|
||||||
|
--
|
||||||
|
-- [hamlet|
|
||||||
|
-- <h1>Permission denied
|
||||||
|
-- <p>#{msg}
|
||||||
|
-- |]
|
||||||
|
htmlTemplate = \_renderer -> do
|
||||||
|
TBH.preEscapedText $ T.pack "<h1>Permission denied</h1>\n<p>"
|
||||||
|
TBH.toHtml msg
|
||||||
|
TBH.preEscapedText $ T.pack "</p>"
|
||||||
|
|
||||||
|
|
||||||
defaultErrorHandler (InvalidArgs ia) = selectRep $ do
|
defaultErrorHandler (InvalidArgs ia) = selectRep $ do
|
||||||
provideRep $ defaultLayout $ do
|
provideRep $ defaultLayout $ do
|
||||||
setTitle "Invalid Arguments"
|
setTitle "Invalid Arguments"
|
||||||
toWidget [hamlet|
|
toWidget htmlTemplate
|
||||||
<h1>Invalid Arguments
|
|
||||||
<ul>
|
|
||||||
$forall msg <- ia
|
|
||||||
<li>#{msg}
|
|
||||||
|]
|
|
||||||
provideRep $ return $ object ["message" .= ("Invalid Arguments" :: Text), "errors" .= ia]
|
provideRep $ return $ object ["message" .= ("Invalid Arguments" :: Text), "errors" .= ia]
|
||||||
|
where
|
||||||
|
-- equivalent to
|
||||||
|
-- [hamlet|
|
||||||
|
-- <h1>Invalid Arguments
|
||||||
|
-- <ul>
|
||||||
|
-- $forall msg <- ia
|
||||||
|
-- <li>#{msg}
|
||||||
|
-- |]
|
||||||
|
htmlTemplate = \_renderer -> do
|
||||||
|
(TBH.preEscapedText . T.pack) "<h1>Invalid Arguments</h1>\n<ul>"
|
||||||
|
Data.Foldable.mapM_
|
||||||
|
(\ msg_afNn
|
||||||
|
-> do { (TBH.preEscapedText . T.pack) "<li>";
|
||||||
|
TBH.toHtml msg_afNn;
|
||||||
|
(TBH.preEscapedText . T.pack) "</li>" })
|
||||||
|
ia;
|
||||||
|
(TBH.preEscapedText . T.pack) "</ul>"
|
||||||
|
|
||||||
|
|
||||||
defaultErrorHandler (InternalError e) = do
|
defaultErrorHandler (InternalError e) = do
|
||||||
$logErrorS "yesod-core" e
|
$logErrorS "yesod-core" e
|
||||||
selectRep $ do
|
selectRep $ do
|
||||||
provideRep $ defaultLayout $ do
|
provideRep $ defaultLayout $ do
|
||||||
setTitle "Internal Server Error"
|
setTitle "Internal Server Error"
|
||||||
toWidget [hamlet|
|
toWidget htmlTemplate
|
||||||
<h1>Internal Server Error
|
|
||||||
<pre>#{e}
|
|
||||||
|]
|
|
||||||
provideRep $ return $ object ["message" .= ("Internal Server Error" :: Text), "error" .= e]
|
provideRep $ return $ object ["message" .= ("Internal Server Error" :: Text), "error" .= e]
|
||||||
|
where
|
||||||
|
-- equivalent to
|
||||||
|
-- [hamlet|
|
||||||
|
-- <h1>Internal Server Error
|
||||||
|
-- <pre>#{e}
|
||||||
|
-- |]
|
||||||
|
htmlTemplate = \_renderer -> do
|
||||||
|
(TBH.preEscapedText . T.pack) "<h1>Internal Server Error</h1>\n<pre>"
|
||||||
|
TBH.toHtml e
|
||||||
|
(TBH.preEscapedText . T.pack) "</pre>"
|
||||||
|
|
||||||
defaultErrorHandler (BadMethod m) = selectRep $ do
|
defaultErrorHandler (BadMethod m) = selectRep $ do
|
||||||
provideRep $ defaultLayout $ do
|
provideRep $ defaultLayout $ do
|
||||||
setTitle"Bad Method"
|
setTitle"Bad Method"
|
||||||
toWidget [hamlet|
|
toWidget $ htmlTemplate
|
||||||
<h1>Method Not Supported
|
|
||||||
<p>Method <code>#{S8.unpack m}</code> not supported
|
|
||||||
|]
|
|
||||||
provideRep $ return $ object ["message" .= ("Bad method" :: Text), "method" .= TE.decodeUtf8With TEE.lenientDecode m]
|
provideRep $ return $ object ["message" .= ("Bad method" :: Text), "method" .= TE.decodeUtf8With TEE.lenientDecode m]
|
||||||
|
|
||||||
asyncHelper :: (url -> [x] -> Text)
|
|
||||||
-> [Script (url)]
|
|
||||||
-> Maybe (JavascriptUrl (url))
|
|
||||||
-> Maybe Text
|
|
||||||
-> (Maybe (HtmlUrl url), [Text])
|
|
||||||
asyncHelper render scripts jscript jsLoc =
|
|
||||||
(mcomplete, scripts'')
|
|
||||||
where
|
where
|
||||||
scripts' = map goScript scripts
|
-- equivalent to
|
||||||
scripts'' =
|
--
|
||||||
case jsLoc of
|
-- [hamlet|
|
||||||
Just s -> scripts' ++ [s]
|
-- <h1>Method Not Supported
|
||||||
Nothing -> scripts'
|
-- <p>Method <code>#{S8.unpack m}</code> not supported
|
||||||
goScript (Script (Local url) _) = render url []
|
-- |]
|
||||||
goScript (Script (Remote s) _) = s
|
htmlTemplate = \ _render -> do
|
||||||
mcomplete =
|
TBH.preEscapedText $ T.pack
|
||||||
case jsLoc of
|
"<h1>Method Not Supported</h1>\n<p>Method <code>"
|
||||||
Just{} -> Nothing
|
TBH.toHtml (S8.unpack m)
|
||||||
Nothing ->
|
TBH.preEscapedText $ T.pack "</code> not supported</p>"
|
||||||
case jscript of
|
|
||||||
Nothing -> Nothing
|
|
||||||
Just j -> Just $ jelper j
|
|
||||||
|
|
||||||
-- | Default formatting for log messages.
|
-- | Default formatting for log messages.
|
||||||
--
|
--
|
||||||
@ -704,20 +691,6 @@ envClientSessionBackend minutes name = do
|
|||||||
(getCachedDate, _closeDateCacher) <- clientSessionDateCacher timeout
|
(getCachedDate, _closeDateCacher) <- clientSessionDateCacher timeout
|
||||||
return $ clientSessionBackend key getCachedDate
|
return $ clientSessionBackend key getCachedDate
|
||||||
|
|
||||||
jsToHtml :: Javascript -> Html
|
|
||||||
jsToHtml (Javascript b) = preEscapedToMarkup $ toLazyText b
|
|
||||||
|
|
||||||
jelper :: JavascriptUrl url -> HtmlUrl url
|
|
||||||
jelper = fmap jsToHtml
|
|
||||||
|
|
||||||
left :: Either a b -> Maybe a
|
|
||||||
left (Left x) = Just x
|
|
||||||
left _ = Nothing
|
|
||||||
|
|
||||||
right :: Either a b -> Maybe b
|
|
||||||
right (Right x) = Just x
|
|
||||||
right _ = Nothing
|
|
||||||
|
|
||||||
clientSessionBackend :: CS.Key -- ^ The encryption key
|
clientSessionBackend :: CS.Key -- ^ The encryption key
|
||||||
-> IO ClientSessionDateCache -- ^ See 'clientSessionDateCacher'
|
-> IO ClientSessionDateCache -- ^ See 'clientSessionDateCacher'
|
||||||
-> SessionBackend
|
-> SessionBackend
|
||||||
|
|||||||
@ -58,8 +58,6 @@ import Control.Monad (liftM)
|
|||||||
import Blaze.ByteString.Builder (Builder, fromByteString, fromLazyByteString)
|
import Blaze.ByteString.Builder (Builder, fromByteString, fromLazyByteString)
|
||||||
import Data.Monoid (mempty)
|
import Data.Monoid (mempty)
|
||||||
|
|
||||||
import Text.Hamlet (Html)
|
|
||||||
import Text.Blaze.Html.Renderer.Utf8 (renderHtmlBuilder)
|
|
||||||
import Data.Conduit (Source, Flush (Chunk), ResumableSource, mapOutput)
|
import Data.Conduit (Source, Flush (Chunk), ResumableSource, mapOutput)
|
||||||
import Control.Monad.Trans.Resource (ResourceT)
|
import Control.Monad.Trans.Resource (ResourceT)
|
||||||
import Data.Conduit.Internal (ResumableSource (ResumableSource))
|
import Data.Conduit.Internal (ResumableSource (ResumableSource))
|
||||||
@ -74,8 +72,6 @@ import Data.Aeson.Encode (fromValue)
|
|||||||
import qualified Blaze.ByteString.Builder.Char.Utf8 as Blaze
|
import qualified Blaze.ByteString.Builder.Char.Utf8 as Blaze
|
||||||
import Data.Text.Lazy.Builder (toLazyText)
|
import Data.Text.Lazy.Builder (toLazyText)
|
||||||
import Yesod.Core.Types
|
import Yesod.Core.Types
|
||||||
import Text.Lucius (Css, renderCss)
|
|
||||||
import Text.Julius (Javascript, unJavascript)
|
|
||||||
|
|
||||||
-- | Zero-length enumerator.
|
-- | Zero-length enumerator.
|
||||||
emptyContent :: Content
|
emptyContent :: Content
|
||||||
@ -106,8 +102,6 @@ instance ToContent Text where
|
|||||||
toContent = toContent . Blaze.fromLazyText
|
toContent = toContent . Blaze.fromLazyText
|
||||||
instance ToContent String where
|
instance ToContent String where
|
||||||
toContent = toContent . Blaze.fromString
|
toContent = toContent . Blaze.fromString
|
||||||
instance ToContent Html where
|
|
||||||
toContent bs = ContentBuilder (renderHtmlBuilder bs) Nothing
|
|
||||||
instance ToContent () where
|
instance ToContent () where
|
||||||
toContent () = toContent B.empty
|
toContent () = toContent B.empty
|
||||||
instance ToContent (ContentType, Content) where
|
instance ToContent (ContentType, Content) where
|
||||||
@ -115,11 +109,6 @@ instance ToContent (ContentType, Content) where
|
|||||||
instance ToContent TypedContent where
|
instance ToContent TypedContent where
|
||||||
toContent (TypedContent _ c) = c
|
toContent (TypedContent _ c) = c
|
||||||
|
|
||||||
instance ToContent Css where
|
|
||||||
toContent = toContent . renderCss
|
|
||||||
instance ToContent Javascript where
|
|
||||||
toContent = toContent . toLazyText . unJavascript
|
|
||||||
|
|
||||||
instance ToFlushBuilder builder => ToContent (CI.Pipe () () builder () (ResourceT IO) ()) where
|
instance ToFlushBuilder builder => ToContent (CI.Pipe () () builder () (ResourceT IO) ()) where
|
||||||
toContent src = ContentSource $ CI.ConduitM (CI.mapOutput toFlushBuilder src >>=)
|
toContent src = ContentSource $ CI.ConduitM (CI.mapOutput toFlushBuilder src >>=)
|
||||||
|
|
||||||
@ -145,8 +134,6 @@ instance ToFlushBuilder (Flush T.Text) where toFlushBuilder = fmap Blaze.fromTex
|
|||||||
instance ToFlushBuilder T.Text where toFlushBuilder = Chunk . Blaze.fromText
|
instance ToFlushBuilder T.Text where toFlushBuilder = Chunk . Blaze.fromText
|
||||||
instance ToFlushBuilder (Flush String) where toFlushBuilder = fmap Blaze.fromString
|
instance ToFlushBuilder (Flush String) where toFlushBuilder = fmap Blaze.fromString
|
||||||
instance ToFlushBuilder String where toFlushBuilder = Chunk . Blaze.fromString
|
instance ToFlushBuilder String where toFlushBuilder = Chunk . Blaze.fromString
|
||||||
instance ToFlushBuilder (Flush Html) where toFlushBuilder = fmap renderHtmlBuilder
|
|
||||||
instance ToFlushBuilder Html where toFlushBuilder = Chunk . renderHtmlBuilder
|
|
||||||
|
|
||||||
repJson :: ToContent a => a -> RepJson
|
repJson :: ToContent a => a -> RepJson
|
||||||
repJson = RepJson . toContent
|
repJson = RepJson . toContent
|
||||||
@ -255,21 +242,12 @@ instance ToContent J.Value where
|
|||||||
instance HasContentType J.Value where
|
instance HasContentType J.Value where
|
||||||
getContentType _ = typeJson
|
getContentType _ = typeJson
|
||||||
|
|
||||||
instance HasContentType Html where
|
|
||||||
getContentType _ = typeHtml
|
|
||||||
|
|
||||||
instance HasContentType Text where
|
instance HasContentType Text where
|
||||||
getContentType _ = typePlain
|
getContentType _ = typePlain
|
||||||
|
|
||||||
instance HasContentType T.Text where
|
instance HasContentType T.Text where
|
||||||
getContentType _ = typePlain
|
getContentType _ = typePlain
|
||||||
|
|
||||||
instance HasContentType Css where
|
|
||||||
getContentType _ = typeCss
|
|
||||||
|
|
||||||
instance HasContentType Javascript where
|
|
||||||
getContentType _ = typeJavascript
|
|
||||||
|
|
||||||
-- | Any type which can be converted to 'TypedContent'.
|
-- | Any type which can be converted to 'TypedContent'.
|
||||||
--
|
--
|
||||||
-- Since 1.2.0
|
-- Since 1.2.0
|
||||||
@ -290,8 +268,6 @@ instance ToTypedContent RepXml where
|
|||||||
toTypedContent (RepXml c) = TypedContent typeXml c
|
toTypedContent (RepXml c) = TypedContent typeXml c
|
||||||
instance ToTypedContent J.Value where
|
instance ToTypedContent J.Value where
|
||||||
toTypedContent v = TypedContent typeJson (toContent v)
|
toTypedContent v = TypedContent typeJson (toContent v)
|
||||||
instance ToTypedContent Html where
|
|
||||||
toTypedContent h = TypedContent typeHtml (toContent h)
|
|
||||||
instance ToTypedContent T.Text where
|
instance ToTypedContent T.Text where
|
||||||
toTypedContent t = TypedContent typePlain (toContent t)
|
toTypedContent t = TypedContent typePlain (toContent t)
|
||||||
instance ToTypedContent [Char] where
|
instance ToTypedContent [Char] where
|
||||||
@ -302,8 +278,3 @@ instance ToTypedContent a => ToTypedContent (DontFullyEvaluate a) where
|
|||||||
toTypedContent (DontFullyEvaluate a) =
|
toTypedContent (DontFullyEvaluate a) =
|
||||||
let TypedContent ct c = toTypedContent a
|
let TypedContent ct c = toTypedContent a
|
||||||
in TypedContent ct (ContentDontEvaluate c)
|
in TypedContent ct (ContentDontEvaluate c)
|
||||||
|
|
||||||
instance ToTypedContent Css where
|
|
||||||
toTypedContent = TypedContent typeCss . toContent
|
|
||||||
instance ToTypedContent Javascript where
|
|
||||||
toTypedContent = TypedContent typeJavascript . toContent
|
|
||||||
|
|||||||
@ -4,7 +4,6 @@
|
|||||||
{-# LANGUAGE FlexibleInstances #-}
|
{-# LANGUAGE FlexibleInstances #-}
|
||||||
{-# LANGUAGE FunctionalDependencies #-}
|
{-# LANGUAGE FunctionalDependencies #-}
|
||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
{-# LANGUAGE QuasiQuotes #-}
|
|
||||||
{-# LANGUAGE RecordWildCards #-}
|
{-# LANGUAGE RecordWildCards #-}
|
||||||
{-# LANGUAGE TupleSections #-}
|
{-# LANGUAGE TupleSections #-}
|
||||||
{-# LANGUAGE TypeFamilies #-}
|
{-# LANGUAGE TypeFamilies #-}
|
||||||
@ -72,21 +71,17 @@ module Yesod.Core.Handler
|
|||||||
, sendChunkLBS
|
, sendChunkLBS
|
||||||
, sendChunkText
|
, sendChunkText
|
||||||
, sendChunkLazyText
|
, sendChunkLazyText
|
||||||
, sendChunkHtml
|
|
||||||
-- ** Redirecting
|
-- ** Redirecting
|
||||||
, RedirectUrl (..)
|
, RedirectUrl (..)
|
||||||
, redirect
|
, redirect
|
||||||
, redirectWith
|
, redirectWith
|
||||||
, redirectToPost
|
|
||||||
, Fragment(..)
|
, Fragment(..)
|
||||||
-- ** Errors
|
-- ** Errors
|
||||||
, notFound
|
, notFound
|
||||||
, badMethod
|
, badMethod
|
||||||
, notAuthenticated
|
, notAuthenticated
|
||||||
, permissionDenied
|
, permissionDenied
|
||||||
, permissionDeniedI
|
|
||||||
, invalidArgs
|
, invalidArgs
|
||||||
, invalidArgsI
|
|
||||||
-- ** Short-circuit responses.
|
-- ** Short-circuit responses.
|
||||||
, sendFile
|
, sendFile
|
||||||
, sendFilePart
|
, sendFilePart
|
||||||
@ -132,13 +127,8 @@ module Yesod.Core.Handler
|
|||||||
, setUltDestReferer
|
, setUltDestReferer
|
||||||
, redirectUltDest
|
, redirectUltDest
|
||||||
, clearUltDest
|
, clearUltDest
|
||||||
-- ** Messages
|
|
||||||
, setMessage
|
|
||||||
, setMessageI
|
|
||||||
, getMessage
|
|
||||||
-- * Helpers for specific content
|
-- * Helpers for specific content
|
||||||
-- ** Hamlet
|
-- ** Hamlet
|
||||||
, hamletToRepHtml
|
|
||||||
, giveUrlRenderer
|
, giveUrlRenderer
|
||||||
, withUrlRenderer
|
, withUrlRenderer
|
||||||
-- ** Misc
|
-- ** Misc
|
||||||
@ -146,8 +136,6 @@ module Yesod.Core.Handler
|
|||||||
-- * Lifting
|
-- * Lifting
|
||||||
, handlerToIO
|
, handlerToIO
|
||||||
, forkHandler
|
, forkHandler
|
||||||
-- * i18n
|
|
||||||
, getMessageRender
|
|
||||||
-- * Per-request caching
|
-- * Per-request caching
|
||||||
, cached
|
, cached
|
||||||
, cachedBy
|
, cachedBy
|
||||||
@ -178,8 +166,6 @@ import qualified Data.Text as T
|
|||||||
import Data.Text.Encoding (decodeUtf8With, encodeUtf8)
|
import Data.Text.Encoding (decodeUtf8With, encodeUtf8)
|
||||||
import Data.Text.Encoding.Error (lenientDecode)
|
import Data.Text.Encoding.Error (lenientDecode)
|
||||||
import qualified Data.Text.Lazy as TL
|
import qualified Data.Text.Lazy as TL
|
||||||
import qualified Text.Blaze.Html.Renderer.Text as RenderText
|
|
||||||
import Text.Hamlet (Html, HtmlUrl, hamlet)
|
|
||||||
|
|
||||||
import qualified Data.ByteString as S
|
import qualified Data.ByteString as S
|
||||||
import qualified Data.ByteString.Lazy as L
|
import qualified Data.ByteString.Lazy as L
|
||||||
@ -190,11 +176,9 @@ import qualified Data.ByteString.Char8 as S8
|
|||||||
import Data.Monoid (Endo (..), mappend, mempty)
|
import Data.Monoid (Endo (..), mappend, mempty)
|
||||||
import Data.Text (Text)
|
import Data.Text (Text)
|
||||||
import qualified Network.Wai.Parse as NWP
|
import qualified Network.Wai.Parse as NWP
|
||||||
import Text.Shakespeare.I18N (RenderMessage (..))
|
|
||||||
import Web.Cookie (SetCookie (..))
|
import Web.Cookie (SetCookie (..))
|
||||||
import Yesod.Core.Content (ToTypedContent (..), simpleContentType, contentTypeTypes, HasContentType (..), ToContent (..), ToFlushBuilder (..))
|
import Yesod.Core.Content (ToTypedContent (..), simpleContentType, contentTypeTypes, HasContentType (..), ToContent (..), ToFlushBuilder (..))
|
||||||
import Yesod.Core.Internal.Util (formatRFC1123)
|
import Yesod.Core.Internal.Util (formatRFC1123)
|
||||||
import Text.Blaze.Html (preEscapedToMarkup, toHtml)
|
|
||||||
|
|
||||||
import qualified Data.IORef.Lifted as I
|
import qualified Data.IORef.Lifted as I
|
||||||
import Data.Maybe (listToMaybe, mapMaybe)
|
import Data.Maybe (listToMaybe, mapMaybe)
|
||||||
@ -482,34 +466,6 @@ redirectUltDest def = do
|
|||||||
clearUltDest :: MonadHandler m => m ()
|
clearUltDest :: MonadHandler m => m ()
|
||||||
clearUltDest = deleteSession ultDestKey
|
clearUltDest = deleteSession ultDestKey
|
||||||
|
|
||||||
msgKey :: Text
|
|
||||||
msgKey = "_MSG"
|
|
||||||
|
|
||||||
-- | Sets a message in the user's session.
|
|
||||||
--
|
|
||||||
-- See 'getMessage'.
|
|
||||||
setMessage :: MonadHandler m => Html -> m ()
|
|
||||||
setMessage = setSession msgKey . T.concat . TL.toChunks . RenderText.renderHtml
|
|
||||||
|
|
||||||
-- | Sets a message in the user's session.
|
|
||||||
--
|
|
||||||
-- See 'getMessage'.
|
|
||||||
setMessageI :: (MonadHandler m, RenderMessage (HandlerSite m) msg)
|
|
||||||
=> msg -> m ()
|
|
||||||
setMessageI msg = do
|
|
||||||
mr <- getMessageRender
|
|
||||||
setMessage $ toHtml $ mr msg
|
|
||||||
|
|
||||||
-- | Gets the message in the user's session, if available, and then clears the
|
|
||||||
-- variable.
|
|
||||||
--
|
|
||||||
-- See 'setMessage'.
|
|
||||||
getMessage :: MonadHandler m => m (Maybe Html)
|
|
||||||
getMessage = do
|
|
||||||
mmsg <- liftM (fmap preEscapedToMarkup) $ lookupSession msgKey
|
|
||||||
deleteSession msgKey
|
|
||||||
return mmsg
|
|
||||||
|
|
||||||
-- | Bypass remaining handler code and output the given file.
|
-- | Bypass remaining handler code and output the given file.
|
||||||
--
|
--
|
||||||
-- For some backends, this is more efficient than reading in the file to
|
-- For some backends, this is more efficient than reading in the file to
|
||||||
@ -624,24 +580,10 @@ notAuthenticated = hcError NotAuthenticated
|
|||||||
permissionDenied :: MonadHandler m => Text -> m a
|
permissionDenied :: MonadHandler m => Text -> m a
|
||||||
permissionDenied = hcError . PermissionDenied
|
permissionDenied = hcError . PermissionDenied
|
||||||
|
|
||||||
-- | Return a 403 permission denied page.
|
|
||||||
permissionDeniedI :: (RenderMessage (HandlerSite m) msg, MonadHandler m)
|
|
||||||
=> msg
|
|
||||||
-> m a
|
|
||||||
permissionDeniedI msg = do
|
|
||||||
mr <- getMessageRender
|
|
||||||
permissionDenied $ mr msg
|
|
||||||
|
|
||||||
-- | Return a 400 invalid arguments page.
|
-- | Return a 400 invalid arguments page.
|
||||||
invalidArgs :: MonadHandler m => [Text] -> m a
|
invalidArgs :: MonadHandler m => [Text] -> m a
|
||||||
invalidArgs = hcError . InvalidArgs
|
invalidArgs = hcError . InvalidArgs
|
||||||
|
|
||||||
-- | Return a 400 invalid arguments page.
|
|
||||||
invalidArgsI :: (MonadHandler m, RenderMessage (HandlerSite m) msg) => [msg] -> m a
|
|
||||||
invalidArgsI msg = do
|
|
||||||
mr <- getMessageRender
|
|
||||||
invalidArgs $ map mr msg
|
|
||||||
|
|
||||||
------- Headers
|
------- Headers
|
||||||
-- | Set the cookie on the client.
|
-- | Set the cookie on the client.
|
||||||
|
|
||||||
@ -838,36 +780,6 @@ newIdent = do
|
|||||||
put x { ghsIdent = i' }
|
put x { ghsIdent = i' }
|
||||||
return $ T.pack $ "hident" ++ show i'
|
return $ T.pack $ "hident" ++ show i'
|
||||||
|
|
||||||
-- | Redirect to a POST resource.
|
|
||||||
--
|
|
||||||
-- This is not technically a redirect; instead, it returns an HTML page with a
|
|
||||||
-- POST form, and some Javascript to automatically submit the form. This can be
|
|
||||||
-- useful when you need to post a plain link somewhere that needs to cause
|
|
||||||
-- changes on the server.
|
|
||||||
redirectToPost :: (MonadHandler m, RedirectUrl (HandlerSite m) url)
|
|
||||||
=> url
|
|
||||||
-> m a
|
|
||||||
redirectToPost url = do
|
|
||||||
urlText <- toTextUrl url
|
|
||||||
withUrlRenderer [hamlet|
|
|
||||||
$newline never
|
|
||||||
$doctype 5
|
|
||||||
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Redirecting...
|
|
||||||
<body onload="document.getElementById('form').submit()">
|
|
||||||
<form id="form" method="post" action=#{urlText}>
|
|
||||||
<noscript>
|
|
||||||
<p>Javascript has been disabled; please click on the button below to be redirected.
|
|
||||||
<input type="submit" value="Continue">
|
|
||||||
|] >>= sendResponse
|
|
||||||
|
|
||||||
-- | Wraps the 'Content' generated by 'hamletToContent' in a 'RepHtml'.
|
|
||||||
hamletToRepHtml :: MonadHandler m => HtmlUrl (Route (HandlerSite m)) -> m Html
|
|
||||||
hamletToRepHtml = withUrlRenderer
|
|
||||||
{-# DEPRECATED hamletToRepHtml "Use withUrlRenderer instead" #-}
|
|
||||||
|
|
||||||
-- | Deprecated synonym for 'withUrlRenderer'.
|
-- | Deprecated synonym for 'withUrlRenderer'.
|
||||||
--
|
--
|
||||||
-- Since 1.2.0
|
-- Since 1.2.0
|
||||||
@ -892,13 +804,6 @@ withUrlRenderer f = do
|
|||||||
waiRequest :: MonadHandler m => m W.Request
|
waiRequest :: MonadHandler m => m W.Request
|
||||||
waiRequest = reqWaiRequest `liftM` getRequest
|
waiRequest = reqWaiRequest `liftM` getRequest
|
||||||
|
|
||||||
getMessageRender :: (MonadHandler m, RenderMessage (HandlerSite m) message)
|
|
||||||
=> m (message -> Text)
|
|
||||||
getMessageRender = do
|
|
||||||
env <- askHandlerEnv
|
|
||||||
l <- reqLangs `liftM` getRequest
|
|
||||||
return $ renderMessage (rheSite env) l
|
|
||||||
|
|
||||||
-- | Use a per-request cache to avoid performing the same action multiple times.
|
-- | Use a per-request cache to avoid performing the same action multiple times.
|
||||||
-- Values are stored by their type, the result of typeOf from Typeable.
|
-- Values are stored by their type, the result of typeOf from Typeable.
|
||||||
-- Therefore, you should use different newtype wrappers at each cache site.
|
-- Therefore, you should use different newtype wrappers at each cache site.
|
||||||
@ -1234,12 +1139,6 @@ sendChunkText = sendChunk
|
|||||||
sendChunkLazyText :: Monad m => TL.Text -> Producer m (Flush Builder)
|
sendChunkLazyText :: Monad m => TL.Text -> Producer m (Flush Builder)
|
||||||
sendChunkLazyText = sendChunk
|
sendChunkLazyText = sendChunk
|
||||||
|
|
||||||
-- | Type-specialized version of 'sendChunk' for @Html@s.
|
|
||||||
--
|
|
||||||
-- Since 1.2.0
|
|
||||||
sendChunkHtml :: Monad m => Html -> Producer m (Flush Builder)
|
|
||||||
sendChunkHtml = sendChunk
|
|
||||||
|
|
||||||
-- | Converts a child handler to a parent handler
|
-- | Converts a child handler to a parent handler
|
||||||
--
|
--
|
||||||
-- Exported since 1.4.11
|
-- Exported since 1.4.11
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import Data.Monoid
|
|||||||
import Yesod.Core.Class.Yesod
|
import Yesod.Core.Class.Yesod
|
||||||
import Yesod.Core.Class.Dispatch
|
import Yesod.Core.Class.Dispatch
|
||||||
import Yesod.Core.Types
|
import Yesod.Core.Types
|
||||||
|
import Yesod.Core.Widget (WidgetT)
|
||||||
import Yesod.Core.Content
|
import Yesod.Core.Content
|
||||||
import Data.Text (Text)
|
import Data.Text (Text)
|
||||||
import Web.PathPieces
|
import Web.PathPieces
|
||||||
|
|||||||
@ -22,6 +22,7 @@ import Yesod.Core.Types
|
|||||||
import Yesod.Core.Content
|
import Yesod.Core.Content
|
||||||
import Yesod.Core.Class.Dispatch
|
import Yesod.Core.Class.Dispatch
|
||||||
import Yesod.Core.Internal.Run
|
import Yesod.Core.Internal.Run
|
||||||
|
import Yesod.Core.Widget (WidgetT)
|
||||||
|
|
||||||
-- | Generates URL datatype and site function for the given 'Resource's. This
|
-- | Generates URL datatype and site function for the given 'Resource's. This
|
||||||
-- is used for creating sites, /not/ subsites. See 'mkYesodSub' for the latter.
|
-- is used for creating sites, /not/ subsites. See 'mkYesodSub' for the latter.
|
||||||
|
|||||||
@ -27,14 +27,12 @@ module Yesod.Core.Json
|
|||||||
, acceptsJson
|
, acceptsJson
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Yesod.Core.Handler (HandlerT, getRequest, invalidArgs, redirect, selectRep, provideRep, rawRequestBody, ProvidedRep)
|
import Yesod.Core.Handler (getRequest, invalidArgs, redirect, provideRep, rawRequestBody, ProvidedRep)
|
||||||
import Control.Monad.Trans.Writer (Writer)
|
import Control.Monad.Trans.Writer (Writer)
|
||||||
import Data.Monoid (Endo)
|
import Data.Monoid (Endo)
|
||||||
import Yesod.Core.Content (TypedContent)
|
|
||||||
import Yesod.Core.Types (reqAccept)
|
import Yesod.Core.Types (reqAccept)
|
||||||
import Yesod.Core.Class.Yesod (defaultLayout, Yesod)
|
import Yesod.Core.Class.Yesod (defaultLayoutJson)
|
||||||
import Yesod.Core.Class.Handler
|
import Yesod.Core.Class.Handler
|
||||||
import Yesod.Core.Widget (WidgetT)
|
|
||||||
import Yesod.Routes.Class
|
import Yesod.Routes.Class
|
||||||
import qualified Data.Aeson as J
|
import qualified Data.Aeson as J
|
||||||
import qualified Data.Aeson.Parser as JP
|
import qualified Data.Aeson.Parser as JP
|
||||||
@ -48,19 +46,6 @@ import qualified Data.ByteString.Char8 as B8
|
|||||||
import Data.Maybe (listToMaybe)
|
import Data.Maybe (listToMaybe)
|
||||||
import Control.Monad (liftM)
|
import Control.Monad (liftM)
|
||||||
|
|
||||||
-- | Provide both an HTML and JSON representation for a piece of
|
|
||||||
-- data, using the default layout for the HTML output
|
|
||||||
-- ('defaultLayout').
|
|
||||||
--
|
|
||||||
-- /Since: 0.3.0/
|
|
||||||
defaultLayoutJson :: (Yesod site, J.ToJSON a)
|
|
||||||
=> WidgetT site IO () -- ^ HTML
|
|
||||||
-> HandlerT site IO a -- ^ JSON
|
|
||||||
-> HandlerT site IO TypedContent
|
|
||||||
defaultLayoutJson w json = selectRep $ do
|
|
||||||
provideRep $ defaultLayout w
|
|
||||||
provideRep $ fmap J.toJSON json
|
|
||||||
|
|
||||||
-- | Wraps a data type in a 'RepJson'. The data type must
|
-- | Wraps a data type in a 'RepJson'. The data type must
|
||||||
-- support conversion to JSON via 'J.ToJSON'.
|
-- support conversion to JSON via 'J.ToJSON'.
|
||||||
--
|
--
|
||||||
|
|||||||
@ -27,10 +27,9 @@ import Data.ByteString (ByteString)
|
|||||||
import qualified Data.ByteString.Lazy as L
|
import qualified Data.ByteString.Lazy as L
|
||||||
import Data.Conduit (Flush, Source)
|
import Data.Conduit (Flush, Source)
|
||||||
import Data.IORef (IORef)
|
import Data.IORef (IORef)
|
||||||
import Data.Map (Map, unionWith)
|
|
||||||
import qualified Data.Map as Map
|
import qualified Data.Map as Map
|
||||||
import Data.Monoid (Endo (..), Last (..),
|
import Data.Map (Map)
|
||||||
Monoid (..))
|
import Data.Monoid (Endo (..), Monoid (..))
|
||||||
import Data.Serialize (Serialize (..),
|
import Data.Serialize (Serialize (..),
|
||||||
putByteString)
|
putByteString)
|
||||||
import Data.String (IsString (fromString))
|
import Data.String (IsString (fromString))
|
||||||
@ -49,8 +48,6 @@ import System.Log.FastLogger (LogStr, LoggerSet, toLogStr
|
|||||||
import qualified System.Random.MWC as MWC
|
import qualified System.Random.MWC as MWC
|
||||||
import Network.Wai.Logger (DateCacheGetter)
|
import Network.Wai.Logger (DateCacheGetter)
|
||||||
import Text.Blaze.Html (Html)
|
import Text.Blaze.Html (Html)
|
||||||
import Text.Hamlet (HtmlUrl)
|
|
||||||
import Text.Julius (JavascriptUrl)
|
|
||||||
import Web.Cookie (SetCookie)
|
import Web.Cookie (SetCookie)
|
||||||
import Yesod.Core.Internal.Util (getTime, putTime)
|
import Yesod.Core.Internal.Util (getTime, putTime)
|
||||||
import Control.Monad.Trans.Class (MonadTrans (..))
|
import Control.Monad.Trans.Class (MonadTrans (..))
|
||||||
@ -159,16 +156,6 @@ type ResolvedApproot = Text
|
|||||||
data AuthResult = Authorized | AuthenticationRequired | Unauthorized Text
|
data AuthResult = Authorized | AuthenticationRequired | Unauthorized Text
|
||||||
deriving (Eq, Show, Read)
|
deriving (Eq, Show, Read)
|
||||||
|
|
||||||
data ScriptLoadPosition master
|
|
||||||
= BottomOfBody
|
|
||||||
| BottomOfHeadBlocking
|
|
||||||
| BottomOfHeadAsync (BottomOfHeadAsync master)
|
|
||||||
|
|
||||||
type BottomOfHeadAsync master
|
|
||||||
= [Text] -- ^ urls to load asynchronously
|
|
||||||
-> Maybe (HtmlUrl (Route master)) -- ^ widget of js to run on async completion
|
|
||||||
-> (HtmlUrl (Route master)) -- ^ widget to insert at the bottom of <head>
|
|
||||||
|
|
||||||
type Texts = [Text]
|
type Texts = [Text]
|
||||||
|
|
||||||
-- | Wrap up a normal WAI application as a Yesod subsite.
|
-- | Wrap up a normal WAI application as a Yesod subsite.
|
||||||
@ -239,18 +226,6 @@ data GHState = GHState
|
|||||||
-- the 'HandlerT' monad and template haskell code should hide it away.
|
-- the 'HandlerT' monad and template haskell code should hide it away.
|
||||||
type YesodApp = YesodRequest -> ResourceT IO YesodResponse
|
type YesodApp = YesodRequest -> ResourceT IO YesodResponse
|
||||||
|
|
||||||
-- | A generic widget, allowing specification of both the subsite and master
|
|
||||||
-- site datatypes. While this is simply a @WriterT@, we define a newtype for
|
|
||||||
-- better error messages.
|
|
||||||
newtype WidgetT site m a = WidgetT
|
|
||||||
{ unWidgetT :: HandlerData site (MonadRoute m) -> m (a, GWData (Route site))
|
|
||||||
}
|
|
||||||
|
|
||||||
instance (a ~ (), Monad m) => Monoid (WidgetT site m a) where
|
|
||||||
mempty = return ()
|
|
||||||
mappend x y = x >> y
|
|
||||||
instance (a ~ (), Monad m) => Semigroup (WidgetT site m a)
|
|
||||||
|
|
||||||
type RY master = Route master -> [(Text, Text)] -> Text
|
type RY master = Route master -> [(Text, Text)] -> Text
|
||||||
|
|
||||||
-- | Newtype wrapper allowing injection of arbitrary content into CSS.
|
-- | Newtype wrapper allowing injection of arbitrary content into CSS.
|
||||||
@ -262,16 +237,6 @@ type RY master = Route master -> [(Text, Text)] -> Text
|
|||||||
-- Since: 1.1.3
|
-- Since: 1.1.3
|
||||||
newtype CssBuilder = CssBuilder { unCssBuilder :: TBuilder.Builder }
|
newtype CssBuilder = CssBuilder { unCssBuilder :: TBuilder.Builder }
|
||||||
|
|
||||||
-- | Content for a web page. By providing this datatype, we can easily create
|
|
||||||
-- generic site templates, which would have the type signature:
|
|
||||||
--
|
|
||||||
-- > PageContent url -> HtmlUrl url
|
|
||||||
data PageContent url = PageContent
|
|
||||||
{ pageTitle :: Html
|
|
||||||
, pageHead :: HtmlUrl url
|
|
||||||
, pageBody :: HtmlUrl url
|
|
||||||
}
|
|
||||||
|
|
||||||
data Content = ContentBuilder !BBuilder.Builder !(Maybe Int) -- ^ The content and optional content length.
|
data Content = ContentBuilder !BBuilder.Builder !(Maybe Int) -- ^ The content and optional content length.
|
||||||
| ContentSource !(Source (ResourceT IO) (Flush BBuilder.Builder))
|
| ContentSource !(Source (ResourceT IO) (Flush BBuilder.Builder))
|
||||||
| ContentFile !FilePath !(Maybe FilePart)
|
| ContentFile !FilePath !(Maybe FilePart)
|
||||||
@ -332,36 +297,8 @@ data Stylesheet url = Stylesheet { styleLocation :: Location url, styleAttribute
|
|||||||
deriving (Show, Eq)
|
deriving (Show, Eq)
|
||||||
newtype Title = Title { unTitle :: Html }
|
newtype Title = Title { unTitle :: Html }
|
||||||
|
|
||||||
newtype Head url = Head (HtmlUrl url)
|
|
||||||
deriving Monoid
|
|
||||||
instance Semigroup (Head a)
|
|
||||||
newtype Body url = Body (HtmlUrl url)
|
|
||||||
deriving Monoid
|
|
||||||
instance Semigroup (Body a)
|
|
||||||
|
|
||||||
type CssBuilderUrl a = (a -> [(Text, Text)] -> Text) -> TBuilder.Builder
|
type CssBuilderUrl a = (a -> [(Text, Text)] -> Text) -> TBuilder.Builder
|
||||||
|
type BuilderUrl url = (url -> [(Text, Text)] -> Text) -> TBuilder.Builder
|
||||||
data GWData a = GWData
|
|
||||||
{ gwdBody :: !(Body a)
|
|
||||||
, gwdTitle :: !(Last Title)
|
|
||||||
, gwdScripts :: !(UniqueList (Script a))
|
|
||||||
, gwdStylesheets :: !(UniqueList (Stylesheet a))
|
|
||||||
, gwdCss :: !(Map (Maybe Text) (CssBuilderUrl a)) -- media type
|
|
||||||
, gwdJavascript :: !(Maybe (JavascriptUrl a))
|
|
||||||
, gwdHead :: !(Head a)
|
|
||||||
}
|
|
||||||
instance Monoid (GWData a) where
|
|
||||||
mempty = GWData mempty mempty mempty mempty mempty mempty mempty
|
|
||||||
mappend (GWData a1 a2 a3 a4 a5 a6 a7)
|
|
||||||
(GWData b1 b2 b3 b4 b5 b6 b7) = GWData
|
|
||||||
(a1 `mappend` b1)
|
|
||||||
(a2 `mappend` b2)
|
|
||||||
(a3 `mappend` b3)
|
|
||||||
(a4 `mappend` b4)
|
|
||||||
(unionWith mappend a5 b5)
|
|
||||||
(a6 `mappend` b6)
|
|
||||||
(a7 `mappend` b7)
|
|
||||||
instance Semigroup (GWData a)
|
|
||||||
|
|
||||||
data HandlerContents =
|
data HandlerContents =
|
||||||
HCContent H.Status !TypedContent
|
HCContent H.Status !TypedContent
|
||||||
@ -383,51 +320,6 @@ instance Show HandlerContents where
|
|||||||
show (HCWaiApp _) = "HCWaiApp"
|
show (HCWaiApp _) = "HCWaiApp"
|
||||||
instance Exception HandlerContents
|
instance Exception HandlerContents
|
||||||
|
|
||||||
-- Instances for WidgetT
|
|
||||||
instance Monad m => Functor (WidgetT site m) where
|
|
||||||
fmap = liftM
|
|
||||||
instance Monad m => Applicative (WidgetT site m) where
|
|
||||||
pure = return
|
|
||||||
(<*>) = ap
|
|
||||||
instance Monad m => Monad (WidgetT site m) where
|
|
||||||
return a = WidgetT $ const $ return (a, mempty)
|
|
||||||
WidgetT x >>= f = WidgetT $ \r -> do
|
|
||||||
(a, wa) <- x r
|
|
||||||
(b, wb) <- unWidgetT (f a) r
|
|
||||||
return (b, wa `mappend` wb)
|
|
||||||
instance MonadIO m => MonadIO (WidgetT site m) where
|
|
||||||
liftIO = lift . liftIO
|
|
||||||
instance MonadBase b m => MonadBase b (WidgetT site m) where
|
|
||||||
liftBase = WidgetT . const . liftBase . fmap (, mempty)
|
|
||||||
instance MonadBaseControl b m => MonadBaseControl b (WidgetT site m) where
|
|
||||||
#if MIN_VERSION_monad_control(1,0,0)
|
|
||||||
type StM (WidgetT site m) a = StM m (a, GWData (Route site))
|
|
||||||
liftBaseWith f = WidgetT $ \reader' ->
|
|
||||||
liftBaseWith $ \runInBase ->
|
|
||||||
liftM (\x -> (x, mempty))
|
|
||||||
(f $ runInBase . flip unWidgetT reader')
|
|
||||||
restoreM = WidgetT . const . restoreM
|
|
||||||
#else
|
|
||||||
data StM (WidgetT site m) a = StW (StM m (a, GWData (Route site)))
|
|
||||||
liftBaseWith f = WidgetT $ \reader' ->
|
|
||||||
liftBaseWith $ \runInBase ->
|
|
||||||
liftM (\x -> (x, mempty))
|
|
||||||
(f $ liftM StW . runInBase . flip unWidgetT reader')
|
|
||||||
restoreM (StW base) = WidgetT $ const $ restoreM base
|
|
||||||
#endif
|
|
||||||
instance Monad m => MonadReader site (WidgetT site m) where
|
|
||||||
ask = WidgetT $ \hd -> return (rheSite $ handlerEnv hd, mempty)
|
|
||||||
local f (WidgetT g) = WidgetT $ \hd -> g hd
|
|
||||||
{ handlerEnv = (handlerEnv hd)
|
|
||||||
{ rheSite = f $ rheSite $ handlerEnv hd
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
instance MonadTrans (WidgetT site) where
|
|
||||||
lift = WidgetT . const . liftM (, mempty)
|
|
||||||
instance MonadThrow m => MonadThrow (WidgetT site m) where
|
|
||||||
throwM = lift . throwM
|
|
||||||
|
|
||||||
instance MonadCatch m => MonadCatch (HandlerT site m) where
|
instance MonadCatch m => MonadCatch (HandlerT site m) where
|
||||||
catch (HandlerT m) c = HandlerT $ \r -> m r `catch` \e -> unHandlerT (c e) r
|
catch (HandlerT m) c = HandlerT $ \r -> m r `catch` \e -> unHandlerT (c e) r
|
||||||
instance MonadMask m => MonadMask (HandlerT site m) where
|
instance MonadMask m => MonadMask (HandlerT site m) where
|
||||||
@ -436,29 +328,6 @@ instance MonadMask m => MonadMask (HandlerT site m) where
|
|||||||
uninterruptibleMask a =
|
uninterruptibleMask a =
|
||||||
HandlerT $ \e -> uninterruptibleMask $ \u -> unHandlerT (a $ q u) e
|
HandlerT $ \e -> uninterruptibleMask $ \u -> unHandlerT (a $ q u) e
|
||||||
where q u (HandlerT b) = HandlerT (u . b)
|
where q u (HandlerT b) = HandlerT (u . b)
|
||||||
instance MonadCatch m => MonadCatch (WidgetT site m) where
|
|
||||||
catch (WidgetT m) c = WidgetT $ \r -> m r `catch` \e -> unWidgetT (c e) r
|
|
||||||
instance MonadMask m => MonadMask (WidgetT site m) where
|
|
||||||
mask a = WidgetT $ \e -> mask $ \u -> unWidgetT (a $ q u) e
|
|
||||||
where q u (WidgetT b) = WidgetT (u . b)
|
|
||||||
uninterruptibleMask a =
|
|
||||||
WidgetT $ \e -> uninterruptibleMask $ \u -> unWidgetT (a $ q u) e
|
|
||||||
where q u (WidgetT b) = WidgetT (u . b)
|
|
||||||
|
|
||||||
instance (Applicative m, MonadIO m, MonadBase IO m, MonadThrow m) => MonadResource (WidgetT site m) where
|
|
||||||
liftResourceT f = WidgetT $ \hd -> liftIO $ fmap (, mempty) $ runInternalState f (handlerResource hd)
|
|
||||||
|
|
||||||
instance MonadIO m => MonadLogger (WidgetT site m) where
|
|
||||||
monadLoggerLog a b c d = WidgetT $ \hd ->
|
|
||||||
liftIO $ fmap (, mempty) $ rheLog (handlerEnv hd) a b c (toLogStr d)
|
|
||||||
|
|
||||||
#if MIN_VERSION_monad_logger(0, 3, 10)
|
|
||||||
instance MonadIO m => MonadLoggerIO (WidgetT site m) where
|
|
||||||
askLoggerIO = WidgetT $ \hd -> return (rheLog (handlerEnv hd), mempty)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
instance MonadActive m => MonadActive (WidgetT site m) where
|
|
||||||
monadActive = lift monadActive
|
|
||||||
instance MonadActive m => MonadActive (HandlerT site m) where
|
instance MonadActive m => MonadActive (HandlerT site m) where
|
||||||
monadActive = lift monadActive
|
monadActive = lift monadActive
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,6 @@
|
|||||||
|
{-# OPTIONS_GHC -fno-warn-orphans #-}
|
||||||
|
|
||||||
|
{-# LANGUAGE ConstraintKinds #-}
|
||||||
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
||||||
{-# LANGUAGE TupleSections #-}
|
{-# LANGUAGE TupleSections #-}
|
||||||
{-# LANGUAGE RankNTypes #-}
|
{-# LANGUAGE RankNTypes #-}
|
||||||
@ -6,6 +9,7 @@
|
|||||||
{-# LANGUAGE TypeFamilies #-}
|
{-# LANGUAGE TypeFamilies #-}
|
||||||
{-# LANGUAGE TemplateHaskell #-}
|
{-# LANGUAGE TemplateHaskell #-}
|
||||||
{-# LANGUAGE MultiParamTypeClasses #-}
|
{-# LANGUAGE MultiParamTypeClasses #-}
|
||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
{-# LANGUAGE TypeSynonymInstances #-}
|
{-# LANGUAGE TypeSynonymInstances #-}
|
||||||
{-# LANGUAGE UndecidableInstances #-}
|
{-# LANGUAGE UndecidableInstances #-}
|
||||||
{-# LANGUAGE CPP #-}
|
{-# LANGUAGE CPP #-}
|
||||||
@ -13,22 +17,27 @@
|
|||||||
-- generator, allowing you to create truly modular HTML components.
|
-- generator, allowing you to create truly modular HTML components.
|
||||||
module Yesod.Core.Widget
|
module Yesod.Core.Widget
|
||||||
( -- * Datatype
|
( -- * Datatype
|
||||||
WidgetT
|
WidgetT(..)
|
||||||
, PageContent (..)
|
, PageContent (..)
|
||||||
-- * Special Hamlet quasiquoter/TH for Widgets
|
|
||||||
, whamlet
|
|
||||||
, whamletFile
|
|
||||||
, ihamletToRepHtml
|
|
||||||
, ihamletToHtml
|
|
||||||
-- * Convert to Widget
|
-- * Convert to Widget
|
||||||
, ToWidget (..)
|
, ToWidget (..)
|
||||||
, ToWidgetHead (..)
|
, ToWidgetHead (..)
|
||||||
, ToWidgetBody (..)
|
, ToWidgetBody (..)
|
||||||
, ToWidgetMedia (..)
|
, ToWidgetMedia (..)
|
||||||
|
|
||||||
|
-- Formerly Yesod.Core.Types
|
||||||
|
, ScriptLoadPosition(..)
|
||||||
|
, BottomOfHeadAsync
|
||||||
|
, GWData(..)
|
||||||
|
, Head(..)
|
||||||
|
, Body(..)
|
||||||
|
|
||||||
|
-- Formerly Yesod.Core
|
||||||
|
, MonadWidget (..)
|
||||||
|
|
||||||
-- * Creating
|
-- * Creating
|
||||||
-- ** Head of page
|
-- ** Head of page
|
||||||
, setTitle
|
, setTitle
|
||||||
, setTitleI
|
|
||||||
-- ** CSS
|
-- ** CSS
|
||||||
, addStylesheet
|
, addStylesheet
|
||||||
, addStylesheetAttrs
|
, addStylesheetAttrs
|
||||||
@ -46,57 +55,115 @@ module Yesod.Core.Widget
|
|||||||
, widgetToParentWidget
|
, widgetToParentWidget
|
||||||
, handlerToWidget
|
, handlerToWidget
|
||||||
-- * Internal
|
-- * Internal
|
||||||
, whamletFileWithSettings
|
|
||||||
, asWidgetT
|
, asWidgetT
|
||||||
|
, tellWidget
|
||||||
|
|
||||||
|
-- Formerly Yesod.Core.Class.Yesod
|
||||||
|
-- *
|
||||||
|
, jelper
|
||||||
|
, asyncHelper
|
||||||
|
, jsToHtml
|
||||||
|
, widgetToPageContentUnbound
|
||||||
|
|
||||||
|
-- Formerly Yesod.Core.Handler
|
||||||
|
-- * Redirecting
|
||||||
|
, redirectToPost
|
||||||
|
-- * Streaming
|
||||||
|
, sendChunkHtml
|
||||||
|
-- * Messages
|
||||||
|
, setMessage
|
||||||
|
, getMessage
|
||||||
|
-- * Hamlet
|
||||||
|
, hamletToRepHtml
|
||||||
|
|
||||||
) where
|
) where
|
||||||
|
|
||||||
|
import Control.Applicative (Applicative(..))
|
||||||
|
import Control.Monad (liftM, ap, forM, mplus)
|
||||||
|
import Control.Monad.Base (MonadBase (liftBase))
|
||||||
|
import Control.Monad.Catch (MonadCatch (..))
|
||||||
|
import Control.Monad.Catch (MonadMask (..))
|
||||||
|
import Control.Monad.Logger (MonadLogger (..))
|
||||||
|
#if MIN_VERSION_monad_logger(0, 3, 10)
|
||||||
|
import Control.Monad.Logger (MonadLoggerIO (..))
|
||||||
|
#endif
|
||||||
|
import Control.Monad.Reader (MonadReader (..))
|
||||||
|
import Control.Monad.Trans.Class (MonadTrans (..))
|
||||||
|
import Control.Monad.Trans.Control (MonadBaseControl (..))
|
||||||
|
import Control.Monad.Trans.Resource (MonadResourceBase, MonadResource (..), runInternalState, MonadThrow (..))
|
||||||
|
import Control.Monad.Trans.Identity ( IdentityT)
|
||||||
|
import Control.Monad.Trans.List ( ListT )
|
||||||
|
import Control.Monad.Trans.Maybe ( MaybeT )
|
||||||
|
import Control.Monad.Trans.Error ( ErrorT, Error)
|
||||||
|
import Control.Monad.Trans.Reader ( ReaderT )
|
||||||
|
import Control.Monad.Trans.State ( StateT )
|
||||||
|
import Control.Monad.Trans.Writer ( WriterT )
|
||||||
|
import Control.Monad.Trans.RWS ( RWST )
|
||||||
|
import qualified Control.Monad.Trans.RWS.Strict as Strict ( RWST )
|
||||||
|
import qualified Control.Monad.Trans.State.Strict as Strict ( StateT )
|
||||||
|
import qualified Control.Monad.Trans.Writer.Strict as Strict ( WriterT )
|
||||||
|
import Blaze.ByteString.Builder (Builder)
|
||||||
|
import qualified Data.ByteString.Lazy as L
|
||||||
|
import Data.Conduit (Flush (Chunk), Producer, ConduitM)
|
||||||
|
import Data.Conduit.Internal (Pipe(..))
|
||||||
|
import Data.Conduit.Lazy (MonadActive, monadActive)
|
||||||
import Data.Monoid
|
import Data.Monoid
|
||||||
import qualified Text.Blaze.Html5 as H
|
import Data.Semigroup (Semigroup)
|
||||||
import Text.Hamlet
|
import qualified Data.Text as T
|
||||||
import Text.Cassius
|
import qualified Text.Blaze.Html.Renderer.Text as RenderText
|
||||||
import Text.Julius
|
import Text.Blaze.Html (preEscapedToMarkup, Html)
|
||||||
|
import Text.Blaze.Html.Renderer.Utf8 (renderHtmlBuilder)
|
||||||
import Yesod.Routes.Class
|
import Yesod.Routes.Class
|
||||||
import Yesod.Core.Handler (getMessageRender, getUrlRenderParams)
|
|
||||||
import Control.Monad.IO.Class (MonadIO, liftIO)
|
import Control.Monad.IO.Class (MonadIO, liftIO)
|
||||||
import Text.Shakespeare.I18N (RenderMessage)
|
|
||||||
import Control.Monad (liftM)
|
|
||||||
import Data.Text (Text)
|
import Data.Text (Text)
|
||||||
|
import Data.Maybe (fromMaybe)
|
||||||
import qualified Data.Map as Map
|
import qualified Data.Map as Map
|
||||||
import Language.Haskell.TH.Quote (QuasiQuoter)
|
|
||||||
import Language.Haskell.TH.Syntax (Q, Exp (InfixE, VarE, LamE, AppE), Pat (VarP), newName)
|
|
||||||
|
|
||||||
import qualified Text.Hamlet as NP
|
import System.Log.FastLogger (toLogStr)
|
||||||
import Data.Text.Lazy.Builder (fromLazyText)
|
|
||||||
import Text.Blaze.Html (toHtml, preEscapedToMarkup)
|
|
||||||
import qualified Data.Text.Lazy as TL
|
import qualified Data.Text.Lazy as TL
|
||||||
|
|
||||||
import Yesod.Core.Types
|
import Yesod.Core.Types
|
||||||
|
import Yesod.Core.Handler (sendResponse, RedirectUrl(..))
|
||||||
import Yesod.Core.Class.Handler
|
import Yesod.Core.Class.Handler
|
||||||
|
import Yesod.Core.Handler (setSession, lookupSession, deleteSession, withUrlRenderer, sendChunk, getUrlRenderParams, getYesod)
|
||||||
|
import Yesod.Core.Content (ToContent(..), ToTypedContent(..), HasContentType(..), ToFlushBuilder(..), typeHtml)
|
||||||
|
import Data.List (foldl', nub)
|
||||||
|
import Data.Map (Map, unionWith)
|
||||||
|
import Data.Text.Lazy.Builder (toLazyText)
|
||||||
|
import qualified Data.Text.Lazy.Builder as TLB
|
||||||
|
import Data.Text.Lazy.Encoding (encodeUtf8)
|
||||||
|
import qualified Data.Foldable
|
||||||
|
import qualified Data.Text
|
||||||
|
import qualified Text.Blaze.Html5 as TBH
|
||||||
|
import qualified Text.Blaze.Html5 as H
|
||||||
|
|
||||||
preEscapedLazyText :: TL.Text -> Html
|
-- templating types
|
||||||
preEscapedLazyText = preEscapedToMarkup
|
type Render url = url -> [(Text, Text)] -> Text
|
||||||
|
type HtmlUrl url = Render url -> Html
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------
|
||||||
|
-- Original Yesod.Core.Widget
|
||||||
|
------------------------------------
|
||||||
class ToWidget site a where
|
class ToWidget site a where
|
||||||
toWidget :: (MonadWidget m, HandlerSite m ~ site) => a -> m ()
|
toWidget :: (MonadWidget m, HandlerSite m ~ site) => a -> m ()
|
||||||
|
|
||||||
instance render ~ RY site => ToWidget site (render -> Html) where
|
instance render ~ RY site => ToWidget site (render -> Html) where
|
||||||
toWidget x = tell $ GWData (Body x) mempty mempty mempty mempty mempty mempty
|
toWidget x = tellWidget $ GWData (Body x) mempty mempty mempty mempty mempty mempty
|
||||||
instance render ~ RY site => ToWidget site (render -> Css) where
|
|
||||||
toWidget x = toWidget $ CssBuilder . fromLazyText . renderCss . x
|
|
||||||
instance ToWidget site Css where
|
|
||||||
toWidget x = toWidget $ CssBuilder . fromLazyText . renderCss . const x
|
|
||||||
instance render ~ RY site => ToWidget site (render -> CssBuilder) where
|
instance render ~ RY site => ToWidget site (render -> CssBuilder) where
|
||||||
toWidget x = tell $ GWData mempty mempty mempty mempty (Map.singleton Nothing $ unCssBuilder . x) mempty mempty
|
toWidget x = tellWidget $ GWData mempty mempty mempty mempty (Map.singleton Nothing $ unCssBuilder . x) mempty mempty
|
||||||
instance ToWidget site CssBuilder where
|
instance ToWidget site CssBuilder where
|
||||||
toWidget x = tell $ GWData mempty mempty mempty mempty (Map.singleton Nothing $ unCssBuilder . const x) mempty mempty
|
toWidget x = tellWidget $ GWData mempty mempty mempty mempty (Map.singleton Nothing $ unCssBuilder . const x) mempty mempty
|
||||||
instance render ~ RY site => ToWidget site (render -> Javascript) where
|
|
||||||
toWidget x = tell $ GWData mempty mempty mempty mempty mempty (Just x) mempty
|
|
||||||
instance ToWidget site Javascript where
|
|
||||||
toWidget x = tell $ GWData mempty mempty mempty mempty mempty (Just $ const x) mempty
|
|
||||||
instance (site' ~ site, IO ~ m, a ~ ()) => ToWidget site' (WidgetT site m a) where
|
instance (site' ~ site, IO ~ m, a ~ ()) => ToWidget site' (WidgetT site m a) where
|
||||||
toWidget = liftWidgetT
|
toWidget = liftWidgetT
|
||||||
instance ToWidget site Html where
|
instance ToWidget site Html where
|
||||||
toWidget = toWidget . const
|
toWidget = toWidget . const
|
||||||
|
instance ToWidgetHead site Html where
|
||||||
|
toWidgetHead = toWidgetHead . const
|
||||||
|
instance render ~ RY site => ToWidgetHead site (render -> CssBuilder) where
|
||||||
|
toWidgetHead = toWidget
|
||||||
|
instance ToWidgetHead site CssBuilder where
|
||||||
|
toWidgetHead = toWidget
|
||||||
|
|
||||||
-- | Allows adding some CSS to the page with a specific media type.
|
-- | Allows adding some CSS to the page with a specific media type.
|
||||||
--
|
--
|
||||||
@ -109,24 +176,16 @@ class ToWidgetMedia site a where
|
|||||||
=> Text -- ^ media value
|
=> Text -- ^ media value
|
||||||
-> a
|
-> a
|
||||||
-> m ()
|
-> m ()
|
||||||
instance render ~ RY site => ToWidgetMedia site (render -> Css) where
|
|
||||||
toWidgetMedia media x = toWidgetMedia media $ CssBuilder . fromLazyText . renderCss . x
|
|
||||||
instance ToWidgetMedia site Css where
|
|
||||||
toWidgetMedia media x = toWidgetMedia media $ CssBuilder . fromLazyText . renderCss . const x
|
|
||||||
instance render ~ RY site => ToWidgetMedia site (render -> CssBuilder) where
|
instance render ~ RY site => ToWidgetMedia site (render -> CssBuilder) where
|
||||||
toWidgetMedia media x = tell $ GWData mempty mempty mempty mempty (Map.singleton (Just media) $ unCssBuilder . x) mempty mempty
|
toWidgetMedia media x = tellWidget $ GWData mempty mempty mempty mempty (Map.singleton (Just media) $ unCssBuilder . x) mempty mempty
|
||||||
instance ToWidgetMedia site CssBuilder where
|
instance ToWidgetMedia site CssBuilder where
|
||||||
toWidgetMedia media x = tell $ GWData mempty mempty mempty mempty (Map.singleton (Just media) $ unCssBuilder . const x) mempty mempty
|
toWidgetMedia media x = tellWidget $ GWData mempty mempty mempty mempty (Map.singleton (Just media) $ unCssBuilder . const x) mempty mempty
|
||||||
|
|
||||||
class ToWidgetBody site a where
|
class ToWidgetBody site a where
|
||||||
toWidgetBody :: (MonadWidget m, HandlerSite m ~ site) => a -> m ()
|
toWidgetBody :: (MonadWidget m, HandlerSite m ~ site) => a -> m ()
|
||||||
|
|
||||||
instance render ~ RY site => ToWidgetBody site (render -> Html) where
|
instance render ~ RY site => ToWidgetBody site (render -> Html) where
|
||||||
toWidgetBody = toWidget
|
toWidgetBody = toWidget
|
||||||
instance render ~ RY site => ToWidgetBody site (render -> Javascript) where
|
|
||||||
toWidgetBody j = toWidget $ \r -> H.script $ preEscapedLazyText $ renderJavascriptUrl r j
|
|
||||||
instance ToWidgetBody site Javascript where
|
|
||||||
toWidgetBody j = toWidget $ \_ -> H.script $ preEscapedLazyText $ renderJavascript j
|
|
||||||
instance ToWidgetBody site Html where
|
instance ToWidgetBody site Html where
|
||||||
toWidgetBody = toWidget
|
toWidgetBody = toWidget
|
||||||
|
|
||||||
@ -134,33 +193,12 @@ class ToWidgetHead site a where
|
|||||||
toWidgetHead :: (MonadWidget m, HandlerSite m ~ site) => a -> m ()
|
toWidgetHead :: (MonadWidget m, HandlerSite m ~ site) => a -> m ()
|
||||||
|
|
||||||
instance render ~ RY site => ToWidgetHead site (render -> Html) where
|
instance render ~ RY site => ToWidgetHead site (render -> Html) where
|
||||||
toWidgetHead = tell . GWData mempty mempty mempty mempty mempty mempty . Head
|
toWidgetHead = tellWidget . GWData mempty mempty mempty mempty mempty mempty . Head
|
||||||
instance render ~ RY site => ToWidgetHead site (render -> Css) where
|
|
||||||
toWidgetHead = toWidget
|
|
||||||
instance ToWidgetHead site Css where
|
|
||||||
toWidgetHead = toWidget
|
|
||||||
instance render ~ RY site => ToWidgetHead site (render -> CssBuilder) where
|
|
||||||
toWidgetHead = toWidget
|
|
||||||
instance ToWidgetHead site CssBuilder where
|
|
||||||
toWidgetHead = toWidget
|
|
||||||
instance render ~ RY site => ToWidgetHead site (render -> Javascript) where
|
|
||||||
toWidgetHead j = toWidgetHead $ \r -> H.script $ preEscapedLazyText $ renderJavascriptUrl r j
|
|
||||||
instance ToWidgetHead site Javascript where
|
|
||||||
toWidgetHead j = toWidgetHead $ \_ -> H.script $ preEscapedLazyText $ renderJavascript j
|
|
||||||
instance ToWidgetHead site Html where
|
|
||||||
toWidgetHead = toWidgetHead . const
|
|
||||||
|
|
||||||
-- | Set the page title. Calling 'setTitle' multiple times overrides previously
|
-- | Set the page title. Calling 'setTitle' multiple times overrides previously
|
||||||
-- set values.
|
-- set values.
|
||||||
setTitle :: MonadWidget m => Html -> m ()
|
setTitle :: MonadWidget m => Html -> m ()
|
||||||
setTitle x = tell $ GWData mempty (Last $ Just $ Title x) mempty mempty mempty mempty mempty
|
setTitle x = tellWidget $ GWData mempty (Last $ Just $ Title x) mempty mempty mempty mempty mempty
|
||||||
|
|
||||||
-- | Set the page title. Calling 'setTitle' multiple times overrides previously
|
|
||||||
-- set values.
|
|
||||||
setTitleI :: (MonadWidget m, RenderMessage (HandlerSite m) msg) => msg -> m ()
|
|
||||||
setTitleI msg = do
|
|
||||||
mr <- getMessageRender
|
|
||||||
setTitle $ toHtml $ mr msg
|
|
||||||
|
|
||||||
-- | Link to the specified local stylesheet.
|
-- | Link to the specified local stylesheet.
|
||||||
addStylesheet :: MonadWidget m => Route (HandlerSite m) -> m ()
|
addStylesheet :: MonadWidget m => Route (HandlerSite m) -> m ()
|
||||||
@ -171,7 +209,7 @@ addStylesheetAttrs :: MonadWidget m
|
|||||||
=> Route (HandlerSite m)
|
=> Route (HandlerSite m)
|
||||||
-> [(Text, Text)]
|
-> [(Text, Text)]
|
||||||
-> m ()
|
-> m ()
|
||||||
addStylesheetAttrs x y = tell $ GWData mempty mempty mempty (toUnique $ Stylesheet (Local x) y) mempty mempty mempty
|
addStylesheetAttrs x y = tellWidget $ GWData mempty mempty mempty (toUnique $ Stylesheet (Local x) y) mempty mempty mempty
|
||||||
|
|
||||||
-- | Link to the specified remote stylesheet.
|
-- | Link to the specified remote stylesheet.
|
||||||
addStylesheetRemote :: MonadWidget m => Text -> m ()
|
addStylesheetRemote :: MonadWidget m => Text -> m ()
|
||||||
@ -179,7 +217,7 @@ addStylesheetRemote = flip addStylesheetRemoteAttrs []
|
|||||||
|
|
||||||
-- | Link to the specified remote stylesheet.
|
-- | Link to the specified remote stylesheet.
|
||||||
addStylesheetRemoteAttrs :: MonadWidget m => Text -> [(Text, Text)] -> m ()
|
addStylesheetRemoteAttrs :: MonadWidget m => Text -> [(Text, Text)] -> m ()
|
||||||
addStylesheetRemoteAttrs x y = tell $ GWData mempty mempty mempty (toUnique $ Stylesheet (Remote x) y) mempty mempty mempty
|
addStylesheetRemoteAttrs x y = tellWidget $ GWData mempty mempty mempty (toUnique $ Stylesheet (Remote x) y) mempty mempty mempty
|
||||||
|
|
||||||
addStylesheetEither :: MonadWidget m
|
addStylesheetEither :: MonadWidget m
|
||||||
=> Either (Route (HandlerSite m)) Text
|
=> Either (Route (HandlerSite m)) Text
|
||||||
@ -197,7 +235,7 @@ addScript = flip addScriptAttrs []
|
|||||||
|
|
||||||
-- | Link to the specified local script.
|
-- | Link to the specified local script.
|
||||||
addScriptAttrs :: MonadWidget m => Route (HandlerSite m) -> [(Text, Text)] -> m ()
|
addScriptAttrs :: MonadWidget m => Route (HandlerSite m) -> [(Text, Text)] -> m ()
|
||||||
addScriptAttrs x y = tell $ GWData mempty mempty (toUnique $ Script (Local x) y) mempty mempty mempty mempty
|
addScriptAttrs x y = tellWidget $ GWData mempty mempty (toUnique $ Script (Local x) y) mempty mempty mempty mempty
|
||||||
|
|
||||||
-- | Link to the specified remote script.
|
-- | Link to the specified remote script.
|
||||||
addScriptRemote :: MonadWidget m => Text -> m ()
|
addScriptRemote :: MonadWidget m => Text -> m ()
|
||||||
@ -205,57 +243,10 @@ addScriptRemote = flip addScriptRemoteAttrs []
|
|||||||
|
|
||||||
-- | Link to the specified remote script.
|
-- | Link to the specified remote script.
|
||||||
addScriptRemoteAttrs :: MonadWidget m => Text -> [(Text, Text)] -> m ()
|
addScriptRemoteAttrs :: MonadWidget m => Text -> [(Text, Text)] -> m ()
|
||||||
addScriptRemoteAttrs x y = tell $ GWData mempty mempty (toUnique $ Script (Remote x) y) mempty mempty mempty mempty
|
addScriptRemoteAttrs x y = tellWidget $ GWData mempty mempty (toUnique $ Script (Remote x) y) mempty mempty mempty mempty
|
||||||
|
|
||||||
whamlet :: QuasiQuoter
|
tellWidget :: MonadWidget m => GWData (Route (HandlerSite m)) -> m ()
|
||||||
whamlet = NP.hamletWithSettings rules NP.defaultHamletSettings
|
tellWidget w = liftWidgetT $ WidgetT $ const $ return ((), w)
|
||||||
|
|
||||||
whamletFile :: FilePath -> Q Exp
|
|
||||||
whamletFile = NP.hamletFileWithSettings rules NP.defaultHamletSettings
|
|
||||||
|
|
||||||
whamletFileWithSettings :: NP.HamletSettings -> FilePath -> Q Exp
|
|
||||||
whamletFileWithSettings = NP.hamletFileWithSettings rules
|
|
||||||
|
|
||||||
asWidgetT :: WidgetT site m () -> WidgetT site m ()
|
|
||||||
asWidgetT = id
|
|
||||||
|
|
||||||
rules :: Q NP.HamletRules
|
|
||||||
rules = do
|
|
||||||
ah <- [|asWidgetT . toWidget|]
|
|
||||||
let helper qg f = do
|
|
||||||
x <- newName "urender"
|
|
||||||
e <- f $ VarE x
|
|
||||||
let e' = LamE [VarP x] e
|
|
||||||
g <- qg
|
|
||||||
bind <- [|(>>=)|]
|
|
||||||
return $ InfixE (Just g) bind (Just e')
|
|
||||||
let ur f = do
|
|
||||||
let env = NP.Env
|
|
||||||
(Just $ helper [|getUrlRenderParams|])
|
|
||||||
(Just $ helper [|liftM (toHtml .) getMessageRender|])
|
|
||||||
f env
|
|
||||||
return $ NP.HamletRules ah ur $ \_ b -> return $ ah `AppE` b
|
|
||||||
|
|
||||||
-- | Wraps the 'Content' generated by 'hamletToContent' in a 'RepHtml'.
|
|
||||||
ihamletToRepHtml :: (MonadHandler m, RenderMessage (HandlerSite m) message)
|
|
||||||
=> HtmlUrlI18n message (Route (HandlerSite m))
|
|
||||||
-> m Html
|
|
||||||
ihamletToRepHtml = ihamletToHtml
|
|
||||||
{-# DEPRECATED ihamletToRepHtml "Please use ihamletToHtml instead" #-}
|
|
||||||
|
|
||||||
-- | Wraps the 'Content' generated by 'hamletToContent' in a 'RepHtml'.
|
|
||||||
--
|
|
||||||
-- Since 1.2.1
|
|
||||||
ihamletToHtml :: (MonadHandler m, RenderMessage (HandlerSite m) message)
|
|
||||||
=> HtmlUrlI18n message (Route (HandlerSite m))
|
|
||||||
-> m Html
|
|
||||||
ihamletToHtml ih = do
|
|
||||||
urender <- getUrlRenderParams
|
|
||||||
mrender <- getMessageRender
|
|
||||||
return $ ih (toHtml . mrender) urender
|
|
||||||
|
|
||||||
tell :: MonadWidget m => GWData (Route (HandlerSite m)) -> m ()
|
|
||||||
tell w = liftWidgetT $ WidgetT $ const $ return ((), w)
|
|
||||||
|
|
||||||
toUnique :: x -> UniqueList x
|
toUnique :: x -> UniqueList x
|
||||||
toUnique = UniqueList . (:)
|
toUnique = UniqueList . (:)
|
||||||
@ -297,3 +288,499 @@ liftGWD tp gwd = GWData
|
|||||||
fixCss f = f . fixRender
|
fixCss f = f . fixRender
|
||||||
|
|
||||||
fixJS f = f . fixRender
|
fixJS f = f . fixRender
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------
|
||||||
|
-- Formerly Yesod.Core.Types
|
||||||
|
------------------------------------
|
||||||
|
data GWData a = GWData
|
||||||
|
{ gwdBody :: !(Body a)
|
||||||
|
, gwdTitle :: !(Last Title)
|
||||||
|
, gwdScripts :: !(UniqueList (Script a))
|
||||||
|
, gwdStylesheets :: !(UniqueList (Stylesheet a))
|
||||||
|
, gwdCss :: !(Map (Maybe Text) (CssBuilderUrl a)) -- media type
|
||||||
|
, gwdJavascript :: !(Maybe (BuilderUrl a))
|
||||||
|
, gwdHead :: !(Head a)
|
||||||
|
}
|
||||||
|
instance Monoid (GWData a) where
|
||||||
|
mempty = GWData mempty mempty mempty mempty mempty mempty mempty
|
||||||
|
mappend (GWData a1 a2 a3 a4 a5 a6 a7)
|
||||||
|
(GWData b1 b2 b3 b4 b5 b6 b7) = GWData
|
||||||
|
(a1 `mappend` b1)
|
||||||
|
(a2 `mappend` b2)
|
||||||
|
(a3 `mappend` b3)
|
||||||
|
(a4 `mappend` b4)
|
||||||
|
(unionWith mappend a5 b5)
|
||||||
|
(a6 `mappend` b6)
|
||||||
|
(a7 `mappend` b7)
|
||||||
|
instance Semigroup (GWData a)
|
||||||
|
|
||||||
|
-- Instances for WidgetT
|
||||||
|
instance Monad m => Functor (WidgetT site m) where
|
||||||
|
fmap = liftM
|
||||||
|
instance Monad m => Applicative (WidgetT site m) where
|
||||||
|
pure = return
|
||||||
|
(<*>) = ap
|
||||||
|
instance Monad m => Monad (WidgetT site m) where
|
||||||
|
return a = WidgetT $ const $ return (a, mempty)
|
||||||
|
WidgetT x >>= f = WidgetT $ \r -> do
|
||||||
|
(a, wa) <- x r
|
||||||
|
(b, wb) <- unWidgetT (f a) r
|
||||||
|
return (b, wa `mappend` wb)
|
||||||
|
instance MonadIO m => MonadIO (WidgetT site m) where
|
||||||
|
liftIO = lift . liftIO
|
||||||
|
instance MonadBase b m => MonadBase b (WidgetT site m) where
|
||||||
|
liftBase = WidgetT . const . liftBase . fmap (, mempty)
|
||||||
|
instance MonadBaseControl b m => MonadBaseControl b (WidgetT site m) where
|
||||||
|
#if MIN_VERSION_monad_control(1,0,0)
|
||||||
|
type StM (WidgetT site m) a = StM m (a, GWData (Route site))
|
||||||
|
liftBaseWith f = WidgetT $ \reader' ->
|
||||||
|
liftBaseWith $ \runInBase ->
|
||||||
|
liftM (\x -> (x, mempty))
|
||||||
|
(f $ runInBase . flip unWidgetT reader')
|
||||||
|
restoreM = WidgetT . const . restoreM
|
||||||
|
#else
|
||||||
|
data StM (WidgetT site m) a = StW (StM m (a, GWData (Route site)))
|
||||||
|
liftBaseWith f = WidgetT $ \reader' ->
|
||||||
|
liftBaseWith $ \runInBase ->
|
||||||
|
liftM (\x -> (x, mempty))
|
||||||
|
(f $ liftM StW . runInBase . flip unWidgetT reader')
|
||||||
|
restoreM (StW base) = WidgetT $ const $ restoreM base
|
||||||
|
#endif
|
||||||
|
instance Monad m => MonadReader site (WidgetT site m) where
|
||||||
|
ask = WidgetT $ \hd -> return (rheSite $ handlerEnv hd, mempty)
|
||||||
|
local f (WidgetT g) = WidgetT $ \hd -> g hd
|
||||||
|
{ handlerEnv = (handlerEnv hd)
|
||||||
|
{ rheSite = f $ rheSite $ handlerEnv hd
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
instance MonadTrans (WidgetT site) where
|
||||||
|
lift = WidgetT . const . liftM (, mempty)
|
||||||
|
instance MonadThrow m => MonadThrow (WidgetT site m) where
|
||||||
|
throwM = lift . throwM
|
||||||
|
|
||||||
|
instance MonadCatch m => MonadCatch (WidgetT site m) where
|
||||||
|
catch (WidgetT m) c = WidgetT $ \r -> m r `catch` \e -> unWidgetT (c e) r
|
||||||
|
instance MonadMask m => MonadMask (WidgetT site m) where
|
||||||
|
mask a = WidgetT $ \e -> mask $ \u -> unWidgetT (a $ q u) e
|
||||||
|
where q u (WidgetT b) = WidgetT (u . b)
|
||||||
|
uninterruptibleMask a =
|
||||||
|
WidgetT $ \e -> uninterruptibleMask $ \u -> unWidgetT (a $ q u) e
|
||||||
|
where q u (WidgetT b) = WidgetT (u . b)
|
||||||
|
|
||||||
|
instance (Applicative m, MonadIO m, MonadBase IO m, MonadThrow m) => MonadResource (WidgetT site m) where
|
||||||
|
liftResourceT f = WidgetT $ \hd -> liftIO $ fmap (, mempty) $ runInternalState f (handlerResource hd)
|
||||||
|
|
||||||
|
instance MonadIO m => MonadLogger (WidgetT site m) where
|
||||||
|
monadLoggerLog a b c d = WidgetT $ \hd ->
|
||||||
|
liftIO $ fmap (, mempty) $ rheLog (handlerEnv hd) a b c (toLogStr d)
|
||||||
|
|
||||||
|
#if MIN_VERSION_monad_logger(0, 3, 10)
|
||||||
|
instance MonadIO m => MonadLoggerIO (WidgetT site m) where
|
||||||
|
askLoggerIO = WidgetT $ \hd -> return (rheLog (handlerEnv hd), mempty)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
instance MonadActive m => MonadActive (WidgetT site m) where
|
||||||
|
monadActive = lift monadActive
|
||||||
|
|
||||||
|
data ScriptLoadPosition master
|
||||||
|
= BottomOfBody
|
||||||
|
| BottomOfHeadBlocking
|
||||||
|
| BottomOfHeadAsync (BottomOfHeadAsync master)
|
||||||
|
|
||||||
|
type BottomOfHeadAsync master
|
||||||
|
= [Text] -- ^ urls to load asynchronously
|
||||||
|
-> Maybe (HtmlUrl (Route master)) -- ^ widget of js to run on async completion
|
||||||
|
-> (HtmlUrl (Route master)) -- ^ widget to insert at the bottom of <head>
|
||||||
|
|
||||||
|
-- | A generic widget, allowing specification of both the subsite and master
|
||||||
|
-- site datatypes. While this is simply a @WriterT@, we define a newtype for
|
||||||
|
-- better error messages.
|
||||||
|
newtype WidgetT site m a = WidgetT
|
||||||
|
{ unWidgetT :: HandlerData site (MonadRoute m) -> m (a, GWData (Route site))
|
||||||
|
}
|
||||||
|
|
||||||
|
instance (a ~ (), Monad m) => Monoid (WidgetT site m a) where
|
||||||
|
mempty = return ()
|
||||||
|
mappend x y = x >> y
|
||||||
|
instance (a ~ (), Monad m) => Semigroup (WidgetT site m a)
|
||||||
|
|
||||||
|
asWidgetT :: WidgetT site m () -> WidgetT site m ()
|
||||||
|
asWidgetT = id
|
||||||
|
|
||||||
|
|
||||||
|
-- | Content for a web page. By providing this datatype, we can easily create
|
||||||
|
-- generic site templates, which would have the type signature:
|
||||||
|
--
|
||||||
|
-- > PageContent url -> HtmlUrl url
|
||||||
|
data PageContent url = PageContent
|
||||||
|
{ pageTitle :: Html
|
||||||
|
, pageHead :: HtmlUrl url
|
||||||
|
, pageBody :: HtmlUrl url
|
||||||
|
}
|
||||||
|
|
||||||
|
newtype Head url = Head (HtmlUrl url)
|
||||||
|
deriving Monoid
|
||||||
|
instance Semigroup (Head a)
|
||||||
|
newtype Body url = Body (HtmlUrl url)
|
||||||
|
deriving Monoid
|
||||||
|
instance Semigroup (Body a)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------
|
||||||
|
-- Formerly Yesod.Core.Content
|
||||||
|
------------------------------------
|
||||||
|
instance ToContent Html where
|
||||||
|
toContent bs = ContentBuilder (renderHtmlBuilder bs) Nothing
|
||||||
|
instance ToTypedContent Html where
|
||||||
|
toTypedContent h = TypedContent typeHtml (toContent h)
|
||||||
|
instance ToFlushBuilder (Flush Html) where toFlushBuilder = fmap renderHtmlBuilder
|
||||||
|
instance ToFlushBuilder Html where toFlushBuilder = Chunk . renderHtmlBuilder
|
||||||
|
|
||||||
|
instance HasContentType Html where
|
||||||
|
getContentType _ = typeHtml
|
||||||
|
|
||||||
|
------------------------------------
|
||||||
|
-- Formerly Yesod.Core.Class.Handler
|
||||||
|
------------------------------------
|
||||||
|
replaceToParent :: HandlerData site route -> HandlerData site ()
|
||||||
|
replaceToParent hd = hd { handlerToParent = const () }
|
||||||
|
|
||||||
|
instance MonadResourceBase m => MonadHandler (WidgetT site m) where
|
||||||
|
type HandlerSite (WidgetT site m) = site
|
||||||
|
liftHandlerT (HandlerT f) = WidgetT $ liftIO . liftM (, mempty) . f . replaceToParent
|
||||||
|
{-# RULES "liftHandlerT (WidgetT site IO)" forall f. liftHandlerT (HandlerT f) = WidgetT $ liftM (, mempty) . f #-}
|
||||||
|
|
||||||
|
class MonadHandler m => MonadWidget m where
|
||||||
|
liftWidgetT :: WidgetT (HandlerSite m) IO a -> m a
|
||||||
|
instance MonadResourceBase m => MonadWidget (WidgetT site m) where
|
||||||
|
liftWidgetT (WidgetT f) = WidgetT $ liftIO . f . replaceToParent
|
||||||
|
|
||||||
|
#define GO(T) instance MonadWidget m => MonadWidget (T m) where liftWidgetT = lift . liftWidgetT
|
||||||
|
#define GOX(X, T) instance (X, MonadWidget m) => MonadWidget (T m) where liftWidgetT = lift . liftWidgetT
|
||||||
|
GO(IdentityT)
|
||||||
|
GO(ListT)
|
||||||
|
GO(MaybeT)
|
||||||
|
GOX(Error e, ErrorT e)
|
||||||
|
GO(ReaderT r)
|
||||||
|
GO(StateT s)
|
||||||
|
GOX(Monoid w, WriterT w)
|
||||||
|
GOX(Monoid w, RWST r w s)
|
||||||
|
GOX(Monoid w, Strict.RWST r w s)
|
||||||
|
GO(Strict.StateT s)
|
||||||
|
GOX(Monoid w, Strict.WriterT w)
|
||||||
|
GO(Pipe l i o u)
|
||||||
|
GO(ConduitM i o)
|
||||||
|
#undef GO
|
||||||
|
#undef GOX
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------
|
||||||
|
-- Formerly Yesod.Core.Handler
|
||||||
|
------------------------------------
|
||||||
|
msgKey :: Text
|
||||||
|
msgKey = T.pack "_MSG"
|
||||||
|
-- | Sets a message in the user's session.
|
||||||
|
--
|
||||||
|
-- See 'getMessage'.
|
||||||
|
setMessage :: MonadHandler m => Html -> m ()
|
||||||
|
setMessage = setSession msgKey . T.concat . TL.toChunks . RenderText.renderHtml
|
||||||
|
|
||||||
|
-- | Gets the message in the user's session, if available, and then clears the
|
||||||
|
-- variable.
|
||||||
|
--
|
||||||
|
-- See 'setMessage'.
|
||||||
|
getMessage :: MonadHandler m => m (Maybe Html)
|
||||||
|
getMessage = do
|
||||||
|
mmsg <- liftM (fmap preEscapedToMarkup) $ lookupSession msgKey
|
||||||
|
deleteSession msgKey
|
||||||
|
return mmsg
|
||||||
|
|
||||||
|
-- | Wraps the 'Content' generated by 'hamletToContent' in a 'RepHtml'.
|
||||||
|
hamletToRepHtml :: MonadHandler m => HtmlUrl (Route (HandlerSite m)) -> m Html
|
||||||
|
hamletToRepHtml = withUrlRenderer
|
||||||
|
{-# DEPRECATED hamletToRepHtml "Use withUrlRenderer instead" #-}
|
||||||
|
|
||||||
|
-- | Redirect to a POST resource.
|
||||||
|
--
|
||||||
|
-- This is not technically a redirect; instead, it returns an HTML page with a
|
||||||
|
-- POST form, and some Javascript to automatically submit the form. This can be
|
||||||
|
-- useful when you need to post a plain link somewhere that needs to cause
|
||||||
|
-- changes on the server.
|
||||||
|
redirectToPost :: (MonadHandler m, RedirectUrl (HandlerSite m) url)
|
||||||
|
=> url
|
||||||
|
-> m a
|
||||||
|
redirectToPost url = do
|
||||||
|
urlText <- toTextUrl url
|
||||||
|
withUrlRenderer (htmlTemplate urlText) >>= sendResponse
|
||||||
|
where
|
||||||
|
{- equivalent to
|
||||||
|
[hamlet|
|
||||||
|
$newline never
|
||||||
|
$doctype 5
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Redirecting...
|
||||||
|
<body onload="document.getElementById('form').submit()">
|
||||||
|
<form id="form" method="post" action=#{urlText}>
|
||||||
|
<noscript>
|
||||||
|
<p>Javascript has been disabled; please click on the button below to be redirected.
|
||||||
|
<input type="submit" value="Continue">
|
||||||
|
|]
|
||||||
|
-}
|
||||||
|
htmlTemplate urlText = \_render_abxV -> do
|
||||||
|
(H.preEscapedText . Data.Text.pack) "<!DOCTYPE html>\n<html><head><title>Redirecting...</title></head><body onload=\"document.getElementById('form').submit()\"><form id=\"form\" method=\"post\" action=\""
|
||||||
|
H.toHtml urlText
|
||||||
|
(H.preEscapedText . Data.Text.pack) "\"><noscript><p>Javascript has been disabled; please click on the button below to be redirected.</p></noscript><input type=\"submit\" value=\"Continue\"></form></body></html>"
|
||||||
|
|
||||||
|
|
||||||
|
-- | Type-specialized version of 'sendChunk' for @Html@s.
|
||||||
|
--
|
||||||
|
-- Since 1.2.0
|
||||||
|
sendChunkHtml :: Monad m => Html -> Producer m (Flush Builder)
|
||||||
|
sendChunkHtml = sendChunk
|
||||||
|
|
||||||
|
|
||||||
|
maybeH :: Monad m => Maybe a -> (a -> m ()) -> Maybe (m ()) -> m ()
|
||||||
|
maybeH mv f mm = fromMaybe (return ()) $ fmap f mv `mplus` mm
|
||||||
|
|
||||||
|
type AddStaticContent site m = Text -- ^ filename extension
|
||||||
|
-> Text -- ^ mime-type
|
||||||
|
-> L.ByteString -- ^ content
|
||||||
|
-> HandlerT site m (Maybe (Either Text (Route site, [(Text, Text)])))
|
||||||
|
|
||||||
|
-- | Convert a widget to a 'PageContent'.
|
||||||
|
-- not bound to the Yesod typeclass
|
||||||
|
widgetToPageContentUnbound
|
||||||
|
:: (MonadBaseControl IO m, MonadThrow m, MonadIO m, Eq (Route site))
|
||||||
|
=> AddStaticContent site m
|
||||||
|
-> (site -> ScriptLoadPosition site)
|
||||||
|
-> WidgetT site m ()
|
||||||
|
-> HandlerT site m (PageContent (Route site))
|
||||||
|
widgetToPageContentUnbound addStaticContent jsLoader w = do
|
||||||
|
master <- getYesod
|
||||||
|
hd <- HandlerT return
|
||||||
|
((), GWData (Body body) (Last mTitle) scripts' stylesheets' style jscript (Head head')) <- lift $ unWidgetT w hd
|
||||||
|
let title = maybe mempty unTitle mTitle
|
||||||
|
scripts = runUniqueList scripts'
|
||||||
|
stylesheets = runUniqueList stylesheets'
|
||||||
|
|
||||||
|
render <- getUrlRenderParams
|
||||||
|
let renderLoc x =
|
||||||
|
case x of
|
||||||
|
Nothing -> Nothing
|
||||||
|
Just (Left s) -> Just s
|
||||||
|
Just (Right (u, p)) -> Just $ render u p
|
||||||
|
css <- forM (Map.toList style) $ \(mmedia, content) -> do
|
||||||
|
let rendered = toLazyText $ content render
|
||||||
|
x <- addStaticContent "css" "text/css; charset=utf-8"
|
||||||
|
$ encodeUtf8 rendered
|
||||||
|
return (mmedia,
|
||||||
|
case x of
|
||||||
|
Nothing -> Left $ preEscapedToMarkup rendered
|
||||||
|
Just y -> Right $ either id (uncurry render) y)
|
||||||
|
jsLoc <-
|
||||||
|
case jscript of
|
||||||
|
Nothing -> return Nothing
|
||||||
|
Just s -> do
|
||||||
|
x <- addStaticContent "js" "text/javascript; charset=utf-8"
|
||||||
|
$ encodeUtf8 $ toLazyText $ s render
|
||||||
|
return $ renderLoc x
|
||||||
|
|
||||||
|
-- modernizr should be at the end of the <head> http://www.modernizr.com/docs/#installing
|
||||||
|
-- the asynchronous loader means your page doesn't have to wait for all the js to load
|
||||||
|
let (mcomplete, asyncScripts) = asyncHelper render scripts jscript jsLoc
|
||||||
|
scriptLoad = regularScriptLoad scripts jscript jsLoc
|
||||||
|
headAll = headContent head' stylesheets css master asyncScripts mcomplete scriptLoad
|
||||||
|
|
||||||
|
let bodyScript = bodyScriptLoad body scriptLoad
|
||||||
|
|
||||||
|
return $ PageContent title headAll $
|
||||||
|
case jsLoader master of
|
||||||
|
BottomOfBody -> bodyScript
|
||||||
|
_ -> body
|
||||||
|
where
|
||||||
|
renderLoc' render' (Local url) = render' url []
|
||||||
|
renderLoc' _ (Remote s) = s
|
||||||
|
|
||||||
|
addAttr x (y, z) = x H.! H.customAttribute (H.textTag y) (H.toValue z)
|
||||||
|
mkScriptTag (Script loc attrs) render' =
|
||||||
|
foldl' addAttr H.script (("src", renderLoc' render' loc) : attrs) $ return ()
|
||||||
|
mkLinkTag (Stylesheet loc attrs) render' =
|
||||||
|
foldl' addAttr H.link
|
||||||
|
( ("rel", "stylesheet")
|
||||||
|
: ("href", renderLoc' render' loc)
|
||||||
|
: attrs
|
||||||
|
)
|
||||||
|
|
||||||
|
runUniqueList :: Eq x => UniqueList x -> [x]
|
||||||
|
runUniqueList (UniqueList x) = nub $ x []
|
||||||
|
|
||||||
|
-- equivalent to
|
||||||
|
--
|
||||||
|
-- [hamlet|
|
||||||
|
-- $newline never
|
||||||
|
-- ^{body}
|
||||||
|
-- ^{scriptLoad}
|
||||||
|
-- |]
|
||||||
|
bodyScriptLoad body scriptLoad = \renderer -> do
|
||||||
|
asHtmlUrl body renderer
|
||||||
|
asHtmlUrl scriptLoad renderer
|
||||||
|
|
||||||
|
-- equivalent to
|
||||||
|
--
|
||||||
|
-- [hamlet|
|
||||||
|
-- $newline never
|
||||||
|
-- $forall s <- scripts
|
||||||
|
-- ^{mkScriptTag s}
|
||||||
|
-- $maybe j <- jscript
|
||||||
|
-- $maybe s <- jsLoc
|
||||||
|
-- <script src="#{s}">
|
||||||
|
-- $nothing
|
||||||
|
-- <script>^{jelper j}
|
||||||
|
-- |]
|
||||||
|
regularScriptLoad scripts jscript jsLoc = \_render_ahpp -> do
|
||||||
|
{ Data.Foldable.mapM_
|
||||||
|
(\ s_ahpq -> asHtmlUrl (mkScriptTag s_ahpq) _render_ahpp) scripts;
|
||||||
|
maybeH
|
||||||
|
jscript
|
||||||
|
(\ j_ahpr
|
||||||
|
-> maybeH
|
||||||
|
jsLoc
|
||||||
|
(\ s_ahps
|
||||||
|
-> do { id ((H.preEscapedText . Data.Text.pack) "<script src=\"");
|
||||||
|
id (TBH.toHtml s_ahps);
|
||||||
|
id ((H.preEscapedText . Data.Text.pack) "\"></script>") })
|
||||||
|
(Just
|
||||||
|
(do { id ((H.preEscapedText . Data.Text.pack) "<script>");
|
||||||
|
asHtmlUrl (jelper j_ahpr) _render_ahpp;
|
||||||
|
id ((H.preEscapedText . Data.Text.pack) "</script>") })))
|
||||||
|
Nothing }
|
||||||
|
|
||||||
|
-- equivalent to
|
||||||
|
--
|
||||||
|
-- [hamlet|
|
||||||
|
-- $newline never
|
||||||
|
-- \^{head'}
|
||||||
|
-- $forall s <- stylesheets
|
||||||
|
-- ^{mkLinkTag s}
|
||||||
|
-- $forall s <- css
|
||||||
|
-- $maybe t <- right $ snd s
|
||||||
|
-- $maybe media <- fst s
|
||||||
|
-- <link rel=stylesheet media=#{media} href=#{t}>
|
||||||
|
-- $nothing
|
||||||
|
-- <link rel=stylesheet href=#{t}>
|
||||||
|
-- $maybe content <- left $ snd s
|
||||||
|
-- $maybe media <- fst s
|
||||||
|
-- <style media=#{media}>#{content}
|
||||||
|
-- $nothing
|
||||||
|
-- <style>#{content}
|
||||||
|
-- $case jsLoader master
|
||||||
|
-- $of BottomOfBody
|
||||||
|
-- $of BottomOfHeadAsync asyncJsLoader
|
||||||
|
-- ^{asyncJsLoader asyncScripts mcomplete}
|
||||||
|
-- $of BottomOfHeadBlocking
|
||||||
|
-- ^{scriptLoad}
|
||||||
|
-- |]
|
||||||
|
headContent head' stylesheets css master asyncScripts mcomplete scriptLoad = \_render_ahmq -> do
|
||||||
|
{ asHtmlUrl head' _render_ahmq;
|
||||||
|
Data.Foldable.mapM_
|
||||||
|
(\ s_ahmr -> asHtmlUrl (mkLinkTag s_ahmr) _render_ahmq)
|
||||||
|
stylesheets;
|
||||||
|
Data.Foldable.mapM_
|
||||||
|
(\ s_ahms
|
||||||
|
-> do { maybeH
|
||||||
|
(right (snd s_ahms))
|
||||||
|
(\ t_ahmt
|
||||||
|
-> maybeH
|
||||||
|
(fst s_ahms)
|
||||||
|
(\ media_ahmu
|
||||||
|
-> do { id
|
||||||
|
((H.preEscapedText . Data.Text.pack)
|
||||||
|
"<link rel=\"stylesheet\" media=\"");
|
||||||
|
id (TBH.toHtml media_ahmu);
|
||||||
|
id
|
||||||
|
((H.preEscapedText . Data.Text.pack)
|
||||||
|
"\" href=\"");
|
||||||
|
id (TBH.toHtml t_ahmt);
|
||||||
|
id ((H.preEscapedText . Data.Text.pack) "\">") })
|
||||||
|
(Just
|
||||||
|
(do { id
|
||||||
|
((H.preEscapedText . Data.Text.pack)
|
||||||
|
"<link rel=\"stylesheet\" href=\"");
|
||||||
|
id (TBH.toHtml t_ahmt);
|
||||||
|
id ((H.preEscapedText . Data.Text.pack) "\">") })))
|
||||||
|
Nothing;
|
||||||
|
maybeH
|
||||||
|
(left (snd s_ahms))
|
||||||
|
(\ content_ahmv
|
||||||
|
-> maybeH
|
||||||
|
(fst s_ahms)
|
||||||
|
(\ media_ahmw
|
||||||
|
-> do { id
|
||||||
|
((H.preEscapedText . Data.Text.pack)
|
||||||
|
"<style media=\"");
|
||||||
|
id (TBH.toHtml media_ahmw);
|
||||||
|
id ((H.preEscapedText . Data.Text.pack) "\">");
|
||||||
|
id (TBH.toHtml content_ahmv);
|
||||||
|
id
|
||||||
|
((H.preEscapedText . Data.Text.pack)
|
||||||
|
"</style>") })
|
||||||
|
(Just
|
||||||
|
(do { id ((H.preEscapedText . Data.Text.pack) "<style>");
|
||||||
|
id (TBH.toHtml content_ahmv);
|
||||||
|
id
|
||||||
|
((H.preEscapedText . Data.Text.pack)
|
||||||
|
"</style>") })))
|
||||||
|
Nothing })
|
||||||
|
css;
|
||||||
|
case jsLoader master of
|
||||||
|
BottomOfBody -> return ()
|
||||||
|
BottomOfHeadAsync asyncJsLoader_ahmx -> asHtmlUrl (asyncJsLoader_ahmx asyncScripts mcomplete) _render_ahmq
|
||||||
|
BottomOfHeadBlocking -> asHtmlUrl scriptLoad _render_ahmq
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
asyncHelper :: (url -> [x] -> Text)
|
||||||
|
-> [Script (url)]
|
||||||
|
-> Maybe (BuilderUrl url)
|
||||||
|
-> Maybe Text
|
||||||
|
-> (Maybe (HtmlUrl url), [Text])
|
||||||
|
asyncHelper render scripts jscript jsLoc =
|
||||||
|
(mcomplete, scripts'')
|
||||||
|
where
|
||||||
|
scripts' = map goScript scripts
|
||||||
|
scripts'' =
|
||||||
|
case jsLoc of
|
||||||
|
Just s -> scripts' ++ [s]
|
||||||
|
Nothing -> scripts'
|
||||||
|
goScript (Script (Local url) _) = render url []
|
||||||
|
goScript (Script (Remote s) _) = s
|
||||||
|
mcomplete =
|
||||||
|
case jsLoc of
|
||||||
|
Just{} -> Nothing
|
||||||
|
Nothing ->
|
||||||
|
case jscript of
|
||||||
|
Nothing -> Nothing
|
||||||
|
Just j -> Just $ jelper j
|
||||||
|
|
||||||
|
jsToHtml :: TLB.Builder -> Html
|
||||||
|
jsToHtml b = preEscapedToMarkup $ toLazyText b
|
||||||
|
|
||||||
|
jelper :: (Render url -> TLB.Builder) -> HtmlUrl url
|
||||||
|
jelper = fmap jsToHtml
|
||||||
|
|
||||||
|
right :: Either a b -> Maybe b
|
||||||
|
right (Right x) = Just x
|
||||||
|
right _ = Nothing
|
||||||
|
|
||||||
|
left :: Either a b -> Maybe a
|
||||||
|
left (Left x) = Just x
|
||||||
|
left _ = Nothing
|
||||||
|
|
||||||
|
asHtmlUrl :: HtmlUrl url -> HtmlUrl url
|
||||||
|
asHtmlUrl = id
|
||||||
|
|||||||
@ -1,10 +1,8 @@
|
|||||||
{-# LANGUAGE CPP #-}
|
{-# LANGUAGE CPP #-}
|
||||||
module YesodCoreTest (specs) where
|
module YesodCoreTest (specs) where
|
||||||
|
|
||||||
import YesodCoreTest.CleanPath
|
import YesodCoreTest.CleanPath
|
||||||
import YesodCoreTest.Exceptions
|
import YesodCoreTest.Exceptions
|
||||||
import YesodCoreTest.Widget
|
|
||||||
import YesodCoreTest.Media
|
|
||||||
import YesodCoreTest.Links
|
import YesodCoreTest.Links
|
||||||
import YesodCoreTest.NoOverloadedStrings
|
import YesodCoreTest.NoOverloadedStrings
|
||||||
import YesodCoreTest.InternalRequest
|
import YesodCoreTest.InternalRequest
|
||||||
@ -28,8 +26,6 @@ specs :: Spec
|
|||||||
specs = do
|
specs = do
|
||||||
cleanPathTest
|
cleanPathTest
|
||||||
exceptionsTest
|
exceptionsTest
|
||||||
widgetTest
|
|
||||||
mediaTest
|
|
||||||
linksTest
|
linksTest
|
||||||
noOverloadedTest
|
noOverloadedTest
|
||||||
internalRequestTest
|
internalRequestTest
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{-# LANGUAGE OverloadedStrings, TemplateHaskell, QuasiQuotes, TypeFamilies, MultiParamTypeClasses #-}
|
{-# LANGUAGE OverloadedStrings, TemplateHaskell, QuasiQuotes, TypeFamilies, MultiParamTypeClasses #-}
|
||||||
module YesodCoreTest.Auth (specs, Widget) where
|
module YesodCoreTest.Auth (specs) where
|
||||||
|
|
||||||
import Yesod.Core
|
import Yesod.Core
|
||||||
import Test.Hspec
|
import Test.Hspec
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
{-# LANGUAGE FlexibleInstances #-}
|
{-# LANGUAGE FlexibleInstances #-}
|
||||||
{-# LANGUAGE DeriveDataTypeable #-}
|
{-# LANGUAGE DeriveDataTypeable #-}
|
||||||
module YesodCoreTest.Cache (cacheTest, Widget) where
|
module YesodCoreTest.Cache (cacheTest) where
|
||||||
|
|
||||||
import Test.Hspec
|
import Test.Hspec
|
||||||
|
|
||||||
@ -13,8 +13,6 @@ import Yesod.Core
|
|||||||
import Data.IORef.Lifted
|
import Data.IORef.Lifted
|
||||||
import Data.Typeable (Typeable)
|
import Data.Typeable (Typeable)
|
||||||
import qualified Data.ByteString.Lazy.Char8 as L8
|
import qualified Data.ByteString.Lazy.Char8 as L8
|
||||||
import Data.Text (Text)
|
|
||||||
import Data.Text.Encoding (encodeUtf8)
|
|
||||||
|
|
||||||
data C = C
|
data C = C
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
{-# LANGUAGE FlexibleInstances, ViewPatterns #-}
|
{-# LANGUAGE FlexibleInstances, ViewPatterns #-}
|
||||||
{-# LANGUAGE CPP #-}
|
{-# LANGUAGE CPP #-}
|
||||||
module YesodCoreTest.CleanPath (cleanPathTest, Widget) where
|
module YesodCoreTest.CleanPath (cleanPathTest) where
|
||||||
|
|
||||||
import Test.Hspec
|
import Test.Hspec
|
||||||
|
|
||||||
|
|||||||
@ -3,13 +3,12 @@
|
|||||||
{-# LANGUAGE ViewPatterns #-}
|
{-# LANGUAGE ViewPatterns #-}
|
||||||
module YesodCoreTest.ErrorHandling
|
module YesodCoreTest.ErrorHandling
|
||||||
( errorHandlingTest
|
( errorHandlingTest
|
||||||
, Widget
|
|
||||||
) where
|
) where
|
||||||
import Yesod.Core
|
import Yesod.Core
|
||||||
|
import Text.Hamlet (hamlet)
|
||||||
import Test.Hspec
|
import Test.Hspec
|
||||||
import Network.Wai
|
import Network.Wai
|
||||||
import Network.Wai.Test
|
import Network.Wai.Test
|
||||||
import Text.Hamlet (hamlet)
|
|
||||||
import qualified Data.ByteString.Lazy as L
|
import qualified Data.ByteString.Lazy as L
|
||||||
import qualified Data.ByteString.Char8 as S8
|
import qualified Data.ByteString.Char8 as S8
|
||||||
import Control.Exception (SomeException, try)
|
import Control.Exception (SomeException, try)
|
||||||
@ -80,7 +79,7 @@ postAfterRunRequestBodyR = do
|
|||||||
getErrorInBodyR :: Handler Html
|
getErrorInBodyR :: Handler Html
|
||||||
getErrorInBodyR = do
|
getErrorInBodyR = do
|
||||||
let foo = error "error in body 19328" :: String
|
let foo = error "error in body 19328" :: String
|
||||||
defaultLayout [whamlet|#{foo}|]
|
defaultLayout $ toWidget [hamlet|#{foo}|]
|
||||||
|
|
||||||
getErrorInBodyNoEvalR :: Handler (DontFullyEvaluate Html)
|
getErrorInBodyNoEvalR :: Handler (DontFullyEvaluate Html)
|
||||||
getErrorInBodyNoEvalR = fmap DontFullyEvaluate getErrorInBodyR
|
getErrorInBodyNoEvalR = fmap DontFullyEvaluate getErrorInBodyR
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{-# LANGUAGE QuasiQuotes, TypeFamilies, TemplateHaskell, MultiParamTypeClasses #-}
|
{-# LANGUAGE QuasiQuotes, TypeFamilies, TemplateHaskell, MultiParamTypeClasses #-}
|
||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
{-# LANGUAGE FlexibleInstances #-}
|
{-# LANGUAGE FlexibleInstances #-}
|
||||||
module YesodCoreTest.Exceptions (exceptionsTest, Widget) where
|
module YesodCoreTest.Exceptions (exceptionsTest) where
|
||||||
|
|
||||||
import Test.Hspec
|
import Test.Hspec
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
{-# LANGUAGE QuasiQuotes, TypeFamilies, TemplateHaskell, MultiParamTypeClasses #-}
|
{-# LANGUAGE QuasiQuotes, TypeFamilies, TemplateHaskell, MultiParamTypeClasses #-}
|
||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
{-# LANGUAGE FlexibleInstances #-}
|
{-# LANGUAGE FlexibleInstances #-}
|
||||||
module YesodCoreTest.JsLoaderSites.Bottom (B(..), Widget) where
|
module YesodCoreTest.JsLoaderSites.Bottom (B(..)) where
|
||||||
|
|
||||||
import Yesod.Core
|
import Yesod.Core
|
||||||
|
import Yesod.Core.Widget
|
||||||
|
|
||||||
data B = B
|
data B = B
|
||||||
mkYesod "B" [parseRoutes|
|
mkYesod "B" [parseRoutes|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{-# LANGUAGE OverloadedStrings, TemplateHaskell, QuasiQuotes, TypeFamilies, MultiParamTypeClasses, ViewPatterns #-}
|
{-# LANGUAGE OverloadedStrings, TemplateHaskell, QuasiQuotes, TypeFamilies, MultiParamTypeClasses, ViewPatterns #-}
|
||||||
module YesodCoreTest.Json (specs, Widget) where
|
module YesodCoreTest.Json (specs) where
|
||||||
|
|
||||||
import Yesod.Core
|
import Yesod.Core
|
||||||
import Test.Hspec
|
import Test.Hspec
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{-# LANGUAGE QuasiQuotes, TypeFamilies, TemplateHaskell, MultiParamTypeClasses #-}
|
{-# LANGUAGE QuasiQuotes, TypeFamilies, TemplateHaskell, MultiParamTypeClasses #-}
|
||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
{-# LANGUAGE FlexibleInstances, ViewPatterns #-}
|
{-# LANGUAGE FlexibleInstances, ViewPatterns #-}
|
||||||
module YesodCoreTest.Links (linksTest, Widget) where
|
module YesodCoreTest.Links (linksTest) where
|
||||||
|
|
||||||
import Test.Hspec
|
import Test.Hspec
|
||||||
|
|
||||||
|
|||||||
@ -7,8 +7,9 @@ import Test.Hspec
|
|||||||
import YesodCoreTest.NoOverloadedStringsSub
|
import YesodCoreTest.NoOverloadedStringsSub
|
||||||
|
|
||||||
import Yesod.Core
|
import Yesod.Core
|
||||||
import Network.Wai
|
import Text.Hamlet (hamlet)
|
||||||
import Network.Wai.Test
|
import Network.Wai.Test
|
||||||
|
import Network.Wai (pathInfo)
|
||||||
import Data.Monoid (mempty)
|
import Data.Monoid (mempty)
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
import qualified Data.ByteString.Lazy.Char8 as L8
|
import qualified Data.ByteString.Lazy.Char8 as L8
|
||||||
@ -20,11 +21,11 @@ getBarR :: Monad m => m T.Text
|
|||||||
getBarR = return $ T.pack "BarR"
|
getBarR = return $ T.pack "BarR"
|
||||||
|
|
||||||
getBazR :: Yesod master => HandlerT Subsite (HandlerT master IO) Html
|
getBazR :: Yesod master => HandlerT Subsite (HandlerT master IO) Html
|
||||||
getBazR = lift $ defaultLayout [whamlet|Used Default Layout|]
|
getBazR = lift $ defaultLayout $ toWidget [hamlet|Used Default Layout|]
|
||||||
|
|
||||||
getBinR :: Yesod master => HandlerT Subsite (HandlerT master IO) Html
|
getBinR :: Yesod master => HandlerT Subsite (HandlerT master IO) Html
|
||||||
getBinR = do
|
getBinR = do
|
||||||
widget <- widgetToParentWidget [whamlet|
|
widget <- widgetToParentWidget $ toWidget [hamlet|
|
||||||
<p>Used defaultLayoutT
|
<p>Used defaultLayoutT
|
||||||
<a href=@{BazR}>Baz
|
<a href=@{BazR}>Baz
|
||||||
|]
|
|]
|
||||||
@ -48,10 +49,8 @@ mkYesod "Y" [parseRoutes|
|
|||||||
|
|
||||||
instance Yesod Y
|
instance Yesod Y
|
||||||
|
|
||||||
getRootR :: Handler ()
|
getRootR, getFooR :: Handler ()
|
||||||
getRootR = return ()
|
getRootR = return ()
|
||||||
|
|
||||||
getFooR :: Handler ()
|
|
||||||
getFooR = return ()
|
getFooR = return ()
|
||||||
|
|
||||||
runner :: Session () -> IO ()
|
runner :: Session () -> IO ()
|
||||||
@ -88,7 +87,7 @@ case_deflayoutT = runner $ do
|
|||||||
|
|
||||||
noOverloadedTest :: Spec
|
noOverloadedTest :: Spec
|
||||||
noOverloadedTest = describe "Test.NoOverloadedStrings" $ do
|
noOverloadedTest = describe "Test.NoOverloadedStrings" $ do
|
||||||
it "sanity" case_sanity
|
it "sanity" case_sanity
|
||||||
it "subsite" case_subsite
|
it "subsite" case_subsite
|
||||||
it "deflayout" case_deflayout
|
it "deflayout" case_deflayout
|
||||||
it "deflayoutT" case_deflayoutT
|
it "deflayoutT" case_deflayoutT
|
||||||
|
|||||||
@ -8,7 +8,6 @@
|
|||||||
module YesodCoreTest.NoOverloadedStringsSub where
|
module YesodCoreTest.NoOverloadedStringsSub where
|
||||||
|
|
||||||
import Yesod.Core
|
import Yesod.Core
|
||||||
import Network.Wai
|
|
||||||
import Yesod.Core.Types
|
import Yesod.Core.Types
|
||||||
|
|
||||||
data Subsite = Subsite (forall master. Yesod master => YesodSubRunnerEnv Subsite master (HandlerT master IO) -> Application)
|
data Subsite = Subsite (forall master. Yesod master => YesodSubRunnerEnv Subsite master (HandlerT master IO) -> Application)
|
||||||
|
|||||||
@ -1,13 +1,9 @@
|
|||||||
{-# LANGUAGE OverloadedStrings, TemplateHaskell, QuasiQuotes, TypeFamilies, MultiParamTypeClasses, ScopedTypeVariables #-}
|
{-# LANGUAGE OverloadedStrings, TemplateHaskell, QuasiQuotes, TypeFamilies, MultiParamTypeClasses, ScopedTypeVariables #-}
|
||||||
module YesodCoreTest.RawResponse (specs, Widget) where
|
module YesodCoreTest.RawResponse (specs) where
|
||||||
|
|
||||||
import Yesod.Core
|
import Yesod.Core
|
||||||
import Test.Hspec
|
import Test.Hspec
|
||||||
import qualified Data.Map as Map
|
|
||||||
import Network.Wai.Test
|
|
||||||
import Network.Wai (responseStream)
|
import Network.Wai (responseStream)
|
||||||
import Data.Text (Text)
|
|
||||||
import Data.ByteString.Lazy (ByteString)
|
|
||||||
import qualified Data.Conduit.List as CL
|
import qualified Data.Conduit.List as CL
|
||||||
import qualified Data.ByteString.Char8 as S8
|
import qualified Data.ByteString.Char8 as S8
|
||||||
import Data.Conduit
|
import Data.Conduit
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
{-# LANGUAGE QuasiQuotes, TemplateHaskell, TypeFamilies, MultiParamTypeClasses, OverloadedStrings #-}
|
{-# LANGUAGE QuasiQuotes, TemplateHaskell #-}
|
||||||
module YesodCoreTest.Redirect (specs, Widget) where
|
{-# LANGUAGE TypeFamilies, MultiParamTypeClasses #-}
|
||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
module YesodCoreTest.Redirect (specs) where
|
||||||
|
|
||||||
import YesodCoreTest.YesodTest
|
import YesodCoreTest.YesodTest
|
||||||
import Yesod.Core.Handler (redirectWith, setEtag)
|
import Yesod.Core.Handler (redirectWith, setEtag)
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
{-# LANGUAGE OverloadedStrings, TemplateHaskell, QuasiQuotes, TypeFamilies, MultiParamTypeClasses, ViewPatterns #-}
|
{-# LANGUAGE TemplateHaskell, QuasiQuotes #-}
|
||||||
module YesodCoreTest.Reps (specs, Widget) where
|
{-# LANGUAGE TypeFamilies, MultiParamTypeClasses, ViewPatterns, OverloadedStrings #-}
|
||||||
|
module YesodCoreTest.Reps (specs) where
|
||||||
|
|
||||||
import Yesod.Core
|
import Yesod.Core
|
||||||
import Test.Hspec
|
import Test.Hspec
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{-# LANGUAGE QuasiQuotes, TypeFamilies, TemplateHaskell, MultiParamTypeClasses #-}
|
{-# LANGUAGE QuasiQuotes, TypeFamilies, TemplateHaskell, MultiParamTypeClasses #-}
|
||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
{-# LANGUAGE FlexibleInstances #-}
|
{-# LANGUAGE FlexibleInstances #-}
|
||||||
module YesodCoreTest.RequestBodySize (specs, Widget) where
|
module YesodCoreTest.RequestBodySize (specs) where
|
||||||
|
|
||||||
import Test.Hspec
|
import Test.Hspec
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
module YesodCoreTest.StubSslOnly ( App ( App ) ) where
|
module YesodCoreTest.StubSslOnly ( App ( App ) ) where
|
||||||
|
|
||||||
import Yesod.Core
|
import Yesod.Core
|
||||||
|
import Text.Hamlet (hamlet)
|
||||||
import qualified Web.ClientSession as CS
|
import qualified Web.ClientSession as CS
|
||||||
|
|
||||||
data App = App
|
data App = App
|
||||||
@ -16,8 +17,8 @@ instance Yesod App where
|
|||||||
fmap Just $ defaultClientSessionBackend 120 CS.defaultKeyFile
|
fmap Just $ defaultClientSessionBackend 120 CS.defaultKeyFile
|
||||||
|
|
||||||
getHomeR :: Handler Html
|
getHomeR :: Handler Html
|
||||||
getHomeR = defaultLayout
|
getHomeR = defaultLayout $ toWidget
|
||||||
[whamlet|
|
[hamlet|
|
||||||
<p>
|
<p>
|
||||||
Welcome to my test application.
|
Welcome to my test application.
|
||||||
|]
|
|]
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
module YesodCoreTest.StubUnsecured ( App ( App ) ) where
|
module YesodCoreTest.StubUnsecured ( App ( App ) ) where
|
||||||
|
|
||||||
import Yesod.Core
|
import Yesod.Core
|
||||||
|
import Text.Hamlet (hamlet)
|
||||||
|
|
||||||
data App = App
|
data App = App
|
||||||
|
|
||||||
@ -12,8 +13,8 @@ mkYesod "App" [parseRoutes|
|
|||||||
instance Yesod App
|
instance Yesod App
|
||||||
|
|
||||||
getHomeR :: Handler Html
|
getHomeR :: Handler Html
|
||||||
getHomeR = defaultLayout
|
getHomeR = defaultLayout $ toWidget
|
||||||
[whamlet|
|
[hamlet|
|
||||||
<p>
|
<p>
|
||||||
Welcome to my test application.
|
Welcome to my test application.
|
||||||
|]
|
|]
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{-# LANGUAGE CPP, QuasiQuotes, TemplateHaskell, TypeFamilies, MultiParamTypeClasses, OverloadedStrings #-}
|
{-# LANGUAGE CPP, QuasiQuotes, TemplateHaskell, TypeFamilies, MultiParamTypeClasses, OverloadedStrings #-}
|
||||||
module YesodCoreTest.WaiSubsite (specs, Widget) where
|
module YesodCoreTest.WaiSubsite (specs) where
|
||||||
|
|
||||||
import YesodCoreTest.YesodTest
|
import YesodCoreTest.YesodTest
|
||||||
import Yesod.Core
|
import Yesod.Core
|
||||||
|
|||||||
@ -16,7 +16,6 @@ extra-source-files:
|
|||||||
test/YesodCoreTest.hs
|
test/YesodCoreTest.hs
|
||||||
test/YesodCoreTest/*.hs
|
test/YesodCoreTest/*.hs
|
||||||
test/YesodCoreTest/JsLoaderSites/Bottom.hs
|
test/YesodCoreTest/JsLoaderSites/Bottom.hs
|
||||||
test/en.msg
|
|
||||||
test/test.hs
|
test/test.hs
|
||||||
ChangeLog.md
|
ChangeLog.md
|
||||||
README.md
|
README.md
|
||||||
@ -30,7 +29,6 @@ library
|
|||||||
, text >= 0.7
|
, text >= 0.7
|
||||||
, template-haskell
|
, template-haskell
|
||||||
, path-pieces >= 0.1.2 && < 0.3
|
, path-pieces >= 0.1.2 && < 0.3
|
||||||
, shakespeare >= 2.0
|
|
||||||
, blaze-builder >= 0.2.1.4 && < 0.5
|
, blaze-builder >= 0.2.1.4 && < 0.5
|
||||||
, transformers >= 0.2.2
|
, transformers >= 0.2.2
|
||||||
, mtl
|
, mtl
|
||||||
@ -163,22 +161,9 @@ test-suite tests
|
|||||||
, wai-extra
|
, wai-extra
|
||||||
, mwc-random
|
, mwc-random
|
||||||
, cookie >= 0.4.1 && < 0.5
|
, cookie >= 0.4.1 && < 0.5
|
||||||
ghc-options: -Wall
|
ghc-options: -Wall -fno-warn-unused-binds
|
||||||
extensions: TemplateHaskell
|
extensions: TemplateHaskell
|
||||||
|
|
||||||
benchmark widgets
|
|
||||||
type: exitcode-stdio-1.0
|
|
||||||
hs-source-dirs: bench
|
|
||||||
build-depends: base
|
|
||||||
, criterion
|
|
||||||
, bytestring
|
|
||||||
, text
|
|
||||||
, transformers
|
|
||||||
, yesod-core
|
|
||||||
, blaze-html
|
|
||||||
main-is: widget.hs
|
|
||||||
ghc-options: -Wall -O2
|
|
||||||
|
|
||||||
source-repository head
|
source-repository head
|
||||||
type: git
|
type: git
|
||||||
location: https://github.com/yesodweb/yesod
|
location: https://github.com/yesodweb/yesod
|
||||||
|
|||||||
@ -33,6 +33,7 @@ import Control.Monad (liftM)
|
|||||||
import Data.Text (Text)
|
import Data.Text (Text)
|
||||||
import Data.String (IsString(..))
|
import Data.String (IsString(..))
|
||||||
import Yesod.Core
|
import Yesod.Core
|
||||||
|
import Yesod.Shakespeare
|
||||||
|
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
|
|
||||||
@ -314,4 +315,4 @@ bootstrapSubmitId = "b:ootstrap___unique__:::::::::::::::::submit-id"
|
|||||||
-- > <$> areq textField nameSettings Nothing
|
-- > <$> areq textField nameSettings Nothing
|
||||||
-- > where nameSettings = withAutofocus $
|
-- > where nameSettings = withAutofocus $
|
||||||
-- > withPlaceholder "First name" $
|
-- > withPlaceholder "First name" $
|
||||||
-- > (bfs ("Name" :: Text))
|
-- > (bfs ("Name" :: Text))
|
||||||
|
|||||||
@ -62,6 +62,7 @@ import Yesod.Form.Types
|
|||||||
import Yesod.Form.I18n.English
|
import Yesod.Form.I18n.English
|
||||||
import Yesod.Form.Functions (parseHelper)
|
import Yesod.Form.Functions (parseHelper)
|
||||||
import Yesod.Core
|
import Yesod.Core
|
||||||
|
import Yesod.Shakespeare
|
||||||
import Text.Hamlet
|
import Text.Hamlet
|
||||||
import Text.Blaze (ToMarkup (toMarkup), unsafeByteString)
|
import Text.Blaze (ToMarkup (toMarkup), unsafeByteString)
|
||||||
#define ToHtml ToMarkup
|
#define ToHtml ToMarkup
|
||||||
@ -91,7 +92,7 @@ import qualified Data.ByteString.Lazy as L
|
|||||||
import Data.Text as T ( Text, append, concat, cons, head
|
import Data.Text as T ( Text, append, concat, cons, head
|
||||||
, intercalate, isPrefixOf, null, unpack, pack, splitOn
|
, intercalate, isPrefixOf, null, unpack, pack, splitOn
|
||||||
)
|
)
|
||||||
import qualified Data.Text as T (drop, dropWhile)
|
import qualified Data.Text as T (drop, dropWhile)
|
||||||
import qualified Data.Text.Read
|
import qualified Data.Text.Read
|
||||||
|
|
||||||
import qualified Data.Map as Map
|
import qualified Data.Map as Map
|
||||||
@ -161,15 +162,15 @@ timeField = timeFieldTypeText
|
|||||||
{-# DEPRECATED timeField "'timeField' currently defaults to an input of type=\"text\". In the next major release, it will default to type=\"time\". To opt in to the new functionality, use 'timeFieldTypeTime'. To keep the existing behavior, use 'timeFieldTypeText'. See 'https://github.com/yesodweb/yesod/pull/874' for details." #-}
|
{-# DEPRECATED timeField "'timeField' currently defaults to an input of type=\"text\". In the next major release, it will default to type=\"time\". To opt in to the new functionality, use 'timeFieldTypeTime'. To keep the existing behavior, use 'timeFieldTypeText'. See 'https://github.com/yesodweb/yesod/pull/874' for details." #-}
|
||||||
|
|
||||||
-- | Creates an input with @type="time"@. <http://caniuse.com/#search=time%20input%20type Browsers not supporting this type> will fallback to a text field, and Yesod will parse the time as described in 'timeFieldTypeText'.
|
-- | Creates an input with @type="time"@. <http://caniuse.com/#search=time%20input%20type Browsers not supporting this type> will fallback to a text field, and Yesod will parse the time as described in 'timeFieldTypeText'.
|
||||||
--
|
--
|
||||||
-- Add the @time@ package and import the "Data.Time.LocalTime" module to use this function.
|
-- Add the @time@ package and import the "Data.Time.LocalTime" module to use this function.
|
||||||
--
|
--
|
||||||
-- Since 1.4.2
|
-- Since 1.4.2
|
||||||
timeFieldTypeTime :: Monad m => RenderMessage (HandlerSite m) FormMessage => Field m TimeOfDay
|
timeFieldTypeTime :: Monad m => RenderMessage (HandlerSite m) FormMessage => Field m TimeOfDay
|
||||||
timeFieldTypeTime = timeFieldOfType "time"
|
timeFieldTypeTime = timeFieldOfType "time"
|
||||||
|
|
||||||
-- | Creates an input with @type="text"@, parsing the time from an [H]H:MM[:SS] format, with an optional AM or PM (if not given, AM is assumed for compatibility with the 24 hour clock system).
|
-- | Creates an input with @type="text"@, parsing the time from an [H]H:MM[:SS] format, with an optional AM or PM (if not given, AM is assumed for compatibility with the 24 hour clock system).
|
||||||
--
|
--
|
||||||
-- Add the @time@ package and import the "Data.Time.LocalTime" module to use this function.
|
-- Add the @time@ package and import the "Data.Time.LocalTime" module to use this function.
|
||||||
--
|
--
|
||||||
-- Since 1.4.2
|
-- Since 1.4.2
|
||||||
@ -205,7 +206,7 @@ $newline never
|
|||||||
where showVal = either id (pack . renderHtml)
|
where showVal = either id (pack . renderHtml)
|
||||||
|
|
||||||
-- | A newtype wrapper around a 'Text' whose 'ToMarkup' instance converts newlines to HTML @\<br>@ tags.
|
-- | A newtype wrapper around a 'Text' whose 'ToMarkup' instance converts newlines to HTML @\<br>@ tags.
|
||||||
--
|
--
|
||||||
-- (When text is entered into a @\<textarea>@, newline characters are used to separate lines.
|
-- (When text is entered into a @\<textarea>@, newline characters are used to separate lines.
|
||||||
-- If this text is then placed verbatim into HTML, the lines won't be separated, thus the need for replacing with @\<br>@ tags).
|
-- If this text is then placed verbatim into HTML, the lines won't be separated, thus the need for replacing with @\<br>@ tags).
|
||||||
-- If you don't need this functionality, simply use 'unTextarea' to access the raw text.
|
-- If you don't need this functionality, simply use 'unTextarea' to access the raw text.
|
||||||
@ -333,7 +334,7 @@ timeParser = do
|
|||||||
if i < 0 || i >= 60
|
if i < 0 || i >= 60
|
||||||
then fail $ show $ msg $ pack xy
|
then fail $ show $ msg $ pack xy
|
||||||
else return $ fromIntegral (i :: Int)
|
else return $ fromIntegral (i :: Int)
|
||||||
|
|
||||||
-- | Creates an input with @type="email"@. Yesod will validate the email's correctness according to RFC5322 and canonicalize it by removing comments and whitespace (see "Text.Email.Validate").
|
-- | Creates an input with @type="email"@. Yesod will validate the email's correctness according to RFC5322 and canonicalize it by removing comments and whitespace (see "Text.Email.Validate").
|
||||||
emailField :: Monad m => RenderMessage (HandlerSite m) FormMessage => Field m Text
|
emailField :: Monad m => RenderMessage (HandlerSite m) FormMessage => Field m Text
|
||||||
emailField = Field
|
emailField = Field
|
||||||
@ -525,7 +526,7 @@ $newline never
|
|||||||
--
|
--
|
||||||
-- If this field is optional, the first radio button is labeled "\<None>", the second \"Yes" and the third \"No".
|
-- If this field is optional, the first radio button is labeled "\<None>", the second \"Yes" and the third \"No".
|
||||||
--
|
--
|
||||||
-- If this field is required, the first radio button is labeled \"Yes" and the second \"No".
|
-- If this field is required, the first radio button is labeled \"Yes" and the second \"No".
|
||||||
--
|
--
|
||||||
-- (Exact label titles will depend on localization).
|
-- (Exact label titles will depend on localization).
|
||||||
boolField :: Monad m => RenderMessage (HandlerSite m) FormMessage => Field m Bool
|
boolField :: Monad m => RenderMessage (HandlerSite m) FormMessage => Field m Bool
|
||||||
@ -559,7 +560,7 @@ $newline never
|
|||||||
t -> Left $ SomeMessage $ MsgInvalidBool t
|
t -> Left $ SomeMessage $ MsgInvalidBool t
|
||||||
showVal = either (\_ -> False)
|
showVal = either (\_ -> False)
|
||||||
|
|
||||||
-- | Creates an input with @type="checkbox"@.
|
-- | Creates an input with @type="checkbox"@.
|
||||||
-- While the default @'boolField'@ implements a radio button so you
|
-- While the default @'boolField'@ implements a radio button so you
|
||||||
-- can differentiate between an empty response (@Nothing@) and a no
|
-- can differentiate between an empty response (@Nothing@) and a no
|
||||||
-- response (@Just False@), this simpler checkbox field returns an empty
|
-- response (@Just False@), this simpler checkbox field returns an empty
|
||||||
@ -814,7 +815,7 @@ prependZero t0 = if T.null t1
|
|||||||
|
|
||||||
-- $optionsOverview
|
-- $optionsOverview
|
||||||
-- These functions create inputs where one or more options can be selected from a list.
|
-- These functions create inputs where one or more options can be selected from a list.
|
||||||
--
|
--
|
||||||
-- The basic datastructure used is an 'Option', which combines a user-facing display value, the internal Haskell value being selected, and an external 'Text' stored as the @value@ in the form (used to map back to the internal value). A list of these, together with a function mapping from an external value back to a Haskell value, form an 'OptionList', which several of these functions take as an argument.
|
-- The basic datastructure used is an 'Option', which combines a user-facing display value, the internal Haskell value being selected, and an external 'Text' stored as the @value@ in the form (used to map back to the internal value). A list of these, together with a function mapping from an external value back to a Haskell value, form an 'OptionList', which several of these functions take as an argument.
|
||||||
--
|
--
|
||||||
-- Typically, you won't need to create an 'OptionList' directly and can instead make one with functions like 'optionsPairs' or 'optionsEnum'. Alternatively, you can use functions like 'selectFieldList', which use their @[(msg, a)]@ parameter to create an 'OptionList' themselves.
|
-- Typically, you won't need to create an 'OptionList' directly and can instead make one with functions like 'optionsPairs' or 'optionsEnum'. Alternatively, you can use functions like 'selectFieldList', which use their @[(msg, a)]@ parameter to create an 'OptionList' themselves.
|
||||||
|
|||||||
@ -59,6 +59,7 @@ import Text.Blaze (Markup, toMarkup)
|
|||||||
#define Html Markup
|
#define Html Markup
|
||||||
#define toHtml toMarkup
|
#define toHtml toMarkup
|
||||||
import Yesod.Core
|
import Yesod.Core
|
||||||
|
import Yesod.Shakespeare
|
||||||
import Network.Wai (requestMethod)
|
import Network.Wai (requestMethod)
|
||||||
import Text.Hamlet (shamlet)
|
import Text.Hamlet (shamlet)
|
||||||
import Data.Monoid (mempty)
|
import Data.Monoid (mempty)
|
||||||
|
|||||||
@ -17,6 +17,7 @@ import Yesod.Form.Types
|
|||||||
import Data.Text (Text)
|
import Data.Text (Text)
|
||||||
import Control.Applicative (Applicative (..))
|
import Control.Applicative (Applicative (..))
|
||||||
import Yesod.Core
|
import Yesod.Core
|
||||||
|
import Yesod.Shakespeare
|
||||||
import Control.Monad (liftM, (<=<))
|
import Control.Monad (liftM, (<=<))
|
||||||
import qualified Data.Map as Map
|
import qualified Data.Map as Map
|
||||||
import Data.Maybe (fromMaybe)
|
import Data.Maybe (fromMaybe)
|
||||||
|
|||||||
@ -15,6 +15,7 @@ module Yesod.Form.Jquery
|
|||||||
) where
|
) where
|
||||||
|
|
||||||
import Yesod.Core
|
import Yesod.Core
|
||||||
|
import Yesod.Shakespeare
|
||||||
import Yesod.Form
|
import Yesod.Form
|
||||||
import Data.Time (Day)
|
import Data.Time (Day)
|
||||||
import Data.Default
|
import Data.Default
|
||||||
|
|||||||
@ -13,6 +13,7 @@ import Yesod.Form.Types
|
|||||||
import Yesod.Form.Functions
|
import Yesod.Form.Functions
|
||||||
import Yesod.Form.Fields (checkBoxField)
|
import Yesod.Form.Fields (checkBoxField)
|
||||||
import Yesod.Core
|
import Yesod.Core
|
||||||
|
import Yesod.Shakespeare
|
||||||
import Control.Monad.Trans.RWS (get, put, ask)
|
import Control.Monad.Trans.RWS (get, put, ask)
|
||||||
import Data.Maybe (fromMaybe)
|
import Data.Maybe (fromMaybe)
|
||||||
import Data.Text.Read (decimal)
|
import Data.Text.Read (decimal)
|
||||||
|
|||||||
@ -33,6 +33,7 @@ import Control.Monad (liftM)
|
|||||||
import Control.Monad.Trans.Class
|
import Control.Monad.Trans.Class
|
||||||
import Data.String (IsString (..))
|
import Data.String (IsString (..))
|
||||||
import Yesod.Core
|
import Yesod.Core
|
||||||
|
import Yesod.Shakespeare
|
||||||
import qualified Data.Map as Map
|
import qualified Data.Map as Map
|
||||||
import Data.Semigroup (Semigroup, (<>))
|
import Data.Semigroup (Semigroup, (<>))
|
||||||
|
|
||||||
|
|||||||
@ -22,6 +22,7 @@ library
|
|||||||
build-depends: base >= 4 && < 5
|
build-depends: base >= 4 && < 5
|
||||||
, yesod-core >= 1.4 && < 1.5
|
, yesod-core >= 1.4 && < 1.5
|
||||||
, yesod-persistent >= 1.4 && < 1.5
|
, yesod-persistent >= 1.4 && < 1.5
|
||||||
|
, yesod-shakespeare >= 1.5 && < 1.6
|
||||||
, time >= 1.1.4
|
, time >= 1.1.4
|
||||||
, shakespeare >= 2.0
|
, shakespeare >= 2.0
|
||||||
, persistent
|
, persistent
|
||||||
|
|||||||
3
yesod-shakespeare/ChangeLog.md
Normal file
3
yesod-shakespeare/ChangeLog.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
## 1.5
|
||||||
|
|
||||||
|
* split off from yesod-core
|
||||||
20
yesod-shakespeare/LICENSE
Normal file
20
yesod-shakespeare/LICENSE
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
Copyright (c) 2012 Michael Snoyman, http://www.yesodweb.com/
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
6
yesod-shakespeare/README.md
Normal file
6
yesod-shakespeare/README.md
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
## yesod-shakespeare
|
||||||
|
|
||||||
|
This package adds shakespeare integration on top of yesod-core.
|
||||||
|
The yesod package automatically adds in shakespeare functionality.
|
||||||
|
|
||||||
|
Yesod is well documented on [its website](http://www.yesodweb.com/).
|
||||||
214
yesod-shakespeare/Yesod/Shakespeare.hs
Normal file
214
yesod-shakespeare/Yesod/Shakespeare.hs
Normal file
@ -0,0 +1,214 @@
|
|||||||
|
{-# OPTIONS_GHC -fno-warn-orphans #-}
|
||||||
|
|
||||||
|
{-# LANGUAGE FlexibleInstances, FlexibleContexts #-}
|
||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
{-# LANGUAGE QuasiQuotes #-}
|
||||||
|
{-# LANGUAGE TypeFamilies #-}
|
||||||
|
module Yesod.Shakespeare (
|
||||||
|
whamlet
|
||||||
|
, whamletFile
|
||||||
|
-- * Special Hamlet quasiquoter/TH for Widgets
|
||||||
|
, ihamletToRepHtml
|
||||||
|
, ihamletToHtml
|
||||||
|
-- * Internal
|
||||||
|
, whamletFileWithSettings
|
||||||
|
-- * Creating
|
||||||
|
-- ** Head of page
|
||||||
|
, setTitleI
|
||||||
|
-- ** Errors
|
||||||
|
, permissionDeniedI
|
||||||
|
, invalidArgsI
|
||||||
|
, unauthorizedI
|
||||||
|
-- ** Messages
|
||||||
|
, setMessageI
|
||||||
|
-- * i18n
|
||||||
|
, getMessageRender
|
||||||
|
|
||||||
|
-- * Shakespeare
|
||||||
|
-- ** Hamlet
|
||||||
|
, hamlet
|
||||||
|
, shamlet
|
||||||
|
, xhamlet
|
||||||
|
, HtmlUrl
|
||||||
|
-- ** Julius
|
||||||
|
, julius
|
||||||
|
, JavascriptUrl
|
||||||
|
, renderJavascriptUrl
|
||||||
|
-- ** Cassius/Lucius
|
||||||
|
, cassius
|
||||||
|
, lucius
|
||||||
|
, CssUrl
|
||||||
|
, renderCssUrl
|
||||||
|
|
||||||
|
, module Text.Shakespeare.I18N
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Control.Monad (liftM)
|
||||||
|
import Text.Shakespeare.I18N
|
||||||
|
import Text.Blaze.Html (preEscapedToMarkup, toHtml, Html)
|
||||||
|
import qualified Text.Blaze.Html5 as H
|
||||||
|
import Language.Haskell.TH.Quote (QuasiQuoter)
|
||||||
|
import Language.Haskell.TH.Syntax (Q, Exp (InfixE, VarE, LamE, AppE), Pat (VarP), newName)
|
||||||
|
import Data.Text (Text)
|
||||||
|
import qualified Data.Text.Lazy as TL
|
||||||
|
import Data.Text.Lazy.Builder (fromLazyText, toLazyText)
|
||||||
|
import Data.Monoid (mempty)
|
||||||
|
|
||||||
|
import qualified Text.Hamlet as NP
|
||||||
|
import Text.Julius (Javascript(..), JavascriptUrl, renderJavascript, renderJavascriptUrl, julius)
|
||||||
|
import Text.Hamlet (hamlet, shamlet, xhamlet)
|
||||||
|
import Text.Lucius (Css, renderCss, CssUrl, renderCssUrl, lucius)
|
||||||
|
import Text.Cassius (cassius)
|
||||||
|
|
||||||
|
import Yesod.Core ( HandlerSite, MonadHandler
|
||||||
|
, getUrlRenderParams, invalidArgs, permissionDenied, getRequest, getYesod
|
||||||
|
, ToContent(..), ToTypedContent(..), HasContentType(..), typeJavascript, typeCss
|
||||||
|
, Route
|
||||||
|
, ToWidget(..), ToWidgetBody(..), ToWidgetMedia(..), ToWidgetHead(..), MonadWidget(..), asWidgetT, tellWidget, GWData(..), setMessage, setTitle
|
||||||
|
)
|
||||||
|
import Yesod.Core.Types
|
||||||
|
|
||||||
|
type Translate msg = msg -> Html
|
||||||
|
type HtmlUrlI18n msg url = Translate msg -> Render url -> Html
|
||||||
|
type Render url = url -> [(Text, Text)] -> Text
|
||||||
|
type HtmlUrl url = Render url -> Html
|
||||||
|
|
||||||
|
preEscapedLazyText :: TL.Text -> Html
|
||||||
|
preEscapedLazyText = preEscapedToMarkup
|
||||||
|
|
||||||
|
whamlet :: QuasiQuoter
|
||||||
|
whamlet = NP.hamletWithSettings rules NP.defaultHamletSettings
|
||||||
|
|
||||||
|
whamletFile :: FilePath -> Q Exp
|
||||||
|
whamletFile = NP.hamletFileWithSettings rules NP.defaultHamletSettings
|
||||||
|
|
||||||
|
whamletFileWithSettings :: NP.HamletSettings -> FilePath -> Q Exp
|
||||||
|
whamletFileWithSettings = NP.hamletFileWithSettings rules
|
||||||
|
|
||||||
|
rules :: Q NP.HamletRules
|
||||||
|
rules = do
|
||||||
|
ah <- [|asWidgetT . toWidget|]
|
||||||
|
let helper qg f = do
|
||||||
|
x <- newName "urender"
|
||||||
|
e <- f $ VarE x
|
||||||
|
let e' = LamE [VarP x] e
|
||||||
|
g <- qg
|
||||||
|
bind <- [|(>>=)|]
|
||||||
|
return $ InfixE (Just g) bind (Just e')
|
||||||
|
let ur f = do
|
||||||
|
let env = NP.Env
|
||||||
|
(Just $ helper [|getUrlRenderParams|])
|
||||||
|
(Just $ helper [|liftM (toHtml .) getMessageRender|])
|
||||||
|
f env
|
||||||
|
return $ NP.HamletRules ah ur $ \_ b -> return $ ah `AppE` b
|
||||||
|
|
||||||
|
-- | Wraps the 'Content' generated by 'hamletToContent' in a 'RepHtml'.
|
||||||
|
ihamletToRepHtml :: (MonadHandler m, RenderMessage (HandlerSite m) message)
|
||||||
|
=> HtmlUrlI18n message (Route (HandlerSite m))
|
||||||
|
-> m Html
|
||||||
|
ihamletToRepHtml = ihamletToHtml
|
||||||
|
{-# DEPRECATED ihamletToRepHtml "Please use ihamletToHtml instead" #-}
|
||||||
|
|
||||||
|
-- | Wraps the 'Content' generated by 'hamletToContent' in a 'RepHtml'.
|
||||||
|
--
|
||||||
|
-- Since 1.2.1
|
||||||
|
ihamletToHtml :: (MonadHandler m, RenderMessage (HandlerSite m) message)
|
||||||
|
=> HtmlUrlI18n message (Route (HandlerSite m))
|
||||||
|
-> m Html
|
||||||
|
ihamletToHtml ih = do
|
||||||
|
urender <- getUrlRenderParams
|
||||||
|
mrender <- getMessageRender
|
||||||
|
return $ ih (toHtml . mrender) urender
|
||||||
|
|
||||||
|
------------------------------------
|
||||||
|
-- Formerly Yesod.Core.Content
|
||||||
|
------------------------------------
|
||||||
|
instance ToContent Css where
|
||||||
|
toContent = toContent . renderCss
|
||||||
|
instance ToContent Javascript where
|
||||||
|
toContent = toContent . toLazyText . unJavascript
|
||||||
|
instance HasContentType Css where
|
||||||
|
getContentType _ = typeCss
|
||||||
|
instance HasContentType Javascript where
|
||||||
|
getContentType _ = typeJavascript
|
||||||
|
instance ToTypedContent Css where
|
||||||
|
toTypedContent = TypedContent typeCss . toContent
|
||||||
|
instance ToTypedContent Javascript where
|
||||||
|
toTypedContent = TypedContent typeJavascript . toContent
|
||||||
|
|
||||||
|
------------------------------------
|
||||||
|
-- Formerly Yesod.Core.Widget
|
||||||
|
------------------------------------
|
||||||
|
instance render ~ RY site => ToWidget site (render -> Css) where
|
||||||
|
toWidget x = toWidget $ CssBuilder . fromLazyText . renderCss . x
|
||||||
|
instance ToWidget site Css where
|
||||||
|
toWidget x = toWidget $ CssBuilder . fromLazyText . renderCss . const x
|
||||||
|
instance render ~ RY site => ToWidget site (render -> Javascript) where
|
||||||
|
toWidget x = tellWidget $ GWData mempty mempty mempty mempty mempty (Just $ unJavascript . x) mempty
|
||||||
|
instance ToWidget site Javascript where
|
||||||
|
toWidget x = tellWidget $ GWData mempty mempty mempty mempty mempty (Just $ const $ unJavascript x) mempty
|
||||||
|
instance render ~ RY site => ToWidgetMedia site (render -> Css) where
|
||||||
|
toWidgetMedia media x = toWidgetMedia media $ CssBuilder . fromLazyText . renderCss . x
|
||||||
|
instance ToWidgetMedia site Css where
|
||||||
|
toWidgetMedia media x = toWidgetMedia media $ CssBuilder . fromLazyText . renderCss . const x
|
||||||
|
instance render ~ RY site => ToWidgetHead site (render -> Css) where
|
||||||
|
toWidgetHead = toWidget
|
||||||
|
instance render ~ RY site => ToWidgetHead site (render -> Javascript) where
|
||||||
|
toWidgetHead j = toWidgetHead $ \r -> H.script $ preEscapedLazyText $ renderJavascriptUrl r j
|
||||||
|
instance ToWidgetHead site Javascript where
|
||||||
|
toWidgetHead j = toWidgetHead $ \_ -> H.script $ preEscapedLazyText $ renderJavascript j
|
||||||
|
instance render ~ RY site => ToWidgetBody site (render -> Javascript) where
|
||||||
|
toWidgetBody j = toWidget $ \r -> H.script $ preEscapedLazyText $ renderJavascriptUrl r j
|
||||||
|
instance ToWidgetBody site Javascript where
|
||||||
|
toWidgetBody j = toWidget $ \_ -> H.script $ preEscapedLazyText $ renderJavascript j
|
||||||
|
instance ToWidgetHead site Css where
|
||||||
|
toWidgetHead = toWidget
|
||||||
|
|
||||||
|
-- | Set the page title. Calling 'setTitle' multiple times overrides previously
|
||||||
|
-- set values.
|
||||||
|
setTitleI :: (MonadWidget m, RenderMessage (HandlerSite m) msg) => msg -> m ()
|
||||||
|
setTitleI msg = do
|
||||||
|
mr <- getMessageRender
|
||||||
|
setTitle $ toHtml $ mr msg
|
||||||
|
|
||||||
|
|
||||||
|
-- | Sets a message in the user's session.
|
||||||
|
--
|
||||||
|
-- See 'getMessage'.
|
||||||
|
setMessageI :: (MonadHandler m, RenderMessage (HandlerSite m) msg)
|
||||||
|
=> msg -> m ()
|
||||||
|
setMessageI msg = do
|
||||||
|
mr <- getMessageRender
|
||||||
|
setMessage $ toHtml $ mr msg
|
||||||
|
|
||||||
|
-- | Return a 403 permission denied page.
|
||||||
|
permissionDeniedI :: (RenderMessage (HandlerSite m) msg, MonadHandler m)
|
||||||
|
=> msg
|
||||||
|
-> m a
|
||||||
|
permissionDeniedI msg = do
|
||||||
|
mr <- getMessageRender
|
||||||
|
permissionDenied $ mr msg
|
||||||
|
|
||||||
|
-- | Return a 400 invalid arguments page.
|
||||||
|
invalidArgsI :: (MonadHandler m, RenderMessage (HandlerSite m) msg) => [msg] -> m a
|
||||||
|
invalidArgsI msg = do
|
||||||
|
mr <- getMessageRender
|
||||||
|
invalidArgs $ map mr msg
|
||||||
|
|
||||||
|
|
||||||
|
getMessageRender :: (MonadHandler m, RenderMessage (HandlerSite m) message)
|
||||||
|
=> m (message -> Text)
|
||||||
|
getMessageRender = do
|
||||||
|
site <- getYesod
|
||||||
|
l <- reqLangs `liftM` getRequest
|
||||||
|
return $ renderMessage site l
|
||||||
|
|
||||||
|
-----------------------------
|
||||||
|
-- originally from Yesod.Core
|
||||||
|
-----------------------------
|
||||||
|
-- | Return an 'Unauthorized' value, with the given i18n message.
|
||||||
|
unauthorizedI :: (MonadHandler m, RenderMessage (HandlerSite m) msg) => msg -> m AuthResult
|
||||||
|
unauthorizedI msg = do
|
||||||
|
mr <- getMessageRender
|
||||||
|
return $ Unauthorized $ mr msg
|
||||||
|
|
||||||
@ -5,7 +5,7 @@
|
|||||||
module Main where
|
module Main where
|
||||||
|
|
||||||
import Criterion.Main
|
import Criterion.Main
|
||||||
import Text.Hamlet
|
import Yesod.Shakespeare
|
||||||
import Numeric (showInt)
|
import Numeric (showInt)
|
||||||
import qualified Data.ByteString.Lazy as L
|
import qualified Data.ByteString.Lazy as L
|
||||||
import qualified Text.Blaze.Html.Renderer.Utf8 as Utf8
|
import qualified Text.Blaze.Html.Renderer.Utf8 as Utf8
|
||||||
@ -2,14 +2,14 @@
|
|||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
{-# LANGUAGE FlexibleInstances, ViewPatterns #-}
|
{-# LANGUAGE FlexibleInstances, ViewPatterns #-}
|
||||||
{-# OPTIONS_GHC -fno-warn-orphans #-}
|
{-# OPTIONS_GHC -fno-warn-orphans #-}
|
||||||
module YesodCoreTest.Media (mediaTest, Widget) where
|
module YesodShakespeareTest.Media (mediaTest, Widget) where
|
||||||
|
|
||||||
import Test.Hspec
|
import Test.Hspec
|
||||||
import Yesod.Core
|
import Yesod.Core
|
||||||
|
import Yesod.Shakespeare
|
||||||
import Network.Wai
|
import Network.Wai
|
||||||
import Network.Wai.Test
|
import Network.Wai.Test
|
||||||
import Text.Lucius
|
import YesodShakespeareTest.MediaData
|
||||||
import YesodCoreTest.MediaData
|
|
||||||
|
|
||||||
mkYesodDispatch "Y" resourcesY
|
mkYesodDispatch "Y" resourcesY
|
||||||
|
|
||||||
@ -1,7 +1,7 @@
|
|||||||
{-# LANGUAGE QuasiQuotes, TypeFamilies, TemplateHaskell, MultiParamTypeClasses #-}
|
{-# LANGUAGE QuasiQuotes, TypeFamilies, TemplateHaskell, MultiParamTypeClasses #-}
|
||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
{-# LANGUAGE FlexibleInstances #-}
|
{-# LANGUAGE FlexibleInstances #-}
|
||||||
module YesodCoreTest.MediaData where
|
module YesodShakespeareTest.MediaData where
|
||||||
|
|
||||||
import Yesod.Core
|
import Yesod.Core
|
||||||
|
|
||||||
@ -1,14 +1,12 @@
|
|||||||
{-# LANGUAGE QuasiQuotes, TypeFamilies, TemplateHaskell, MultiParamTypeClasses #-}
|
{-# LANGUAGE QuasiQuotes, TypeFamilies, TemplateHaskell, MultiParamTypeClasses #-}
|
||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
{-# LANGUAGE FlexibleInstances, ViewPatterns #-}
|
{-# LANGUAGE FlexibleInstances, ViewPatterns #-}
|
||||||
module YesodCoreTest.Widget (widgetTest) where
|
module YesodShakespeareTest.Widget (widgetTest) where
|
||||||
|
|
||||||
import Test.Hspec
|
import Test.Hspec
|
||||||
|
|
||||||
import Yesod.Core
|
import Yesod.Core
|
||||||
import Text.Julius
|
import Yesod.Shakespeare
|
||||||
import Text.Lucius
|
|
||||||
import Text.Hamlet
|
|
||||||
|
|
||||||
import Network.Wai
|
import Network.Wai
|
||||||
import Network.Wai.Test
|
import Network.Wai.Test
|
||||||
11
yesod-shakespeare/test/test.hs
Normal file
11
yesod-shakespeare/test/test.hs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import Test.Hspec
|
||||||
|
import YesodShakespeareTest.Widget
|
||||||
|
import YesodShakespeareTest.Media
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = hspec specs
|
||||||
|
|
||||||
|
specs :: Spec
|
||||||
|
specs = do
|
||||||
|
widgetTest
|
||||||
|
mediaTest
|
||||||
73
yesod-shakespeare/yesod-shakespeare.cabal
Normal file
73
yesod-shakespeare/yesod-shakespeare.cabal
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
name: yesod-shakespeare
|
||||||
|
version: 1.5
|
||||||
|
license: MIT
|
||||||
|
license-file: LICENSE
|
||||||
|
author: Michael Snoyman <michael@snoyman.com>
|
||||||
|
maintainer: Michael Snoyman <michael@snoyman.com>
|
||||||
|
synopsis: Creation of type-safe, RESTful web applications.
|
||||||
|
description: API docs and the README are available at <http://www.stackage.org/package/yesod-core>
|
||||||
|
category: Web, Yesod
|
||||||
|
stability: Stable
|
||||||
|
cabal-version: >= 1.8
|
||||||
|
build-type: Simple
|
||||||
|
homepage: http://www.yesodweb.com/
|
||||||
|
extra-source-files:
|
||||||
|
test/YesodShakespeareTest/*.hs
|
||||||
|
test/en.msg
|
||||||
|
test/test.hs
|
||||||
|
ChangeLog.md
|
||||||
|
README.md
|
||||||
|
|
||||||
|
library
|
||||||
|
build-depends: base >= 4.3 && < 5
|
||||||
|
, shakespeare
|
||||||
|
, yesod-core >= 1.4
|
||||||
|
, text >= 0.7
|
||||||
|
, template-haskell
|
||||||
|
, bytestring >= 0.9.1.4
|
||||||
|
, transformers >= 0.2.2
|
||||||
|
, blaze-html >= 0.5
|
||||||
|
, containers >= 0.2
|
||||||
|
|
||||||
|
exposed-modules: Yesod.Shakespeare
|
||||||
|
|
||||||
|
ghc-options: -Wall
|
||||||
|
-- Following line added due to: https://github.com/yesodweb/yesod/issues/545
|
||||||
|
-- This looks like a GHC bug
|
||||||
|
extensions: MultiParamTypeClasses
|
||||||
|
|
||||||
|
-- Workaround for: http://ghc.haskell.org/trac/ghc/ticket/8443
|
||||||
|
extensions: TemplateHaskell
|
||||||
|
|
||||||
|
test-suite tests
|
||||||
|
type: exitcode-stdio-1.0
|
||||||
|
main-is: test.hs
|
||||||
|
hs-source-dirs: test
|
||||||
|
|
||||||
|
cpp-options: -DTEST
|
||||||
|
build-depends: base
|
||||||
|
,hspec >= 1.3
|
||||||
|
,hspec-expectations
|
||||||
|
,yesod-core
|
||||||
|
,yesod-shakespeare
|
||||||
|
,wai
|
||||||
|
,wai-extra
|
||||||
|
ghc-options: -Wall -fno-warn-unused-binds
|
||||||
|
extensions: TemplateHaskell
|
||||||
|
|
||||||
|
benchmark widgets
|
||||||
|
type: exitcode-stdio-1.0
|
||||||
|
hs-source-dirs: bench
|
||||||
|
build-depends: base
|
||||||
|
, yesod-shakespeare
|
||||||
|
, yesod-core
|
||||||
|
, transformers
|
||||||
|
, blaze-html
|
||||||
|
, bytestring
|
||||||
|
, criterion
|
||||||
|
main-is: widget.hs
|
||||||
|
ghc-options: -Wall -O2
|
||||||
|
|
||||||
|
source-repository head
|
||||||
|
type: git
|
||||||
|
location: https://github.com/yesodweb/yesod
|
||||||
@ -11,6 +11,7 @@ import Network.Wai.Test (SResponse(simpleHeaders))
|
|||||||
import Test.HUnit (assertFailure, assertBool)
|
import Test.HUnit (assertFailure, assertBool)
|
||||||
import Test.Hspec (Spec)
|
import Test.Hspec (Spec)
|
||||||
import Yesod.Core
|
import Yesod.Core
|
||||||
|
import Yesod.Shakespeare
|
||||||
import Yesod.EmbeddedStatic
|
import Yesod.EmbeddedStatic
|
||||||
import Yesod.Test
|
import Yesod.Test
|
||||||
import qualified Data.ByteString as B
|
import qualified Data.ByteString as B
|
||||||
|
|||||||
@ -80,6 +80,7 @@ test-suite tests
|
|||||||
build-depends: base
|
build-depends: base
|
||||||
, hspec >= 1.3
|
, hspec >= 1.3
|
||||||
, yesod-test >= 1.4
|
, yesod-test >= 1.4
|
||||||
|
, yesod-shakespeare >= 1.5
|
||||||
, wai-extra
|
, wai-extra
|
||||||
, HUnit
|
, HUnit
|
||||||
|
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import Test.Hspec
|
|||||||
|
|
||||||
import Yesod.Core
|
import Yesod.Core
|
||||||
import Yesod.Form
|
import Yesod.Form
|
||||||
|
import Yesod.Shakespeare
|
||||||
import Yesod.Test
|
import Yesod.Test
|
||||||
import Yesod.Test.CssQuery
|
import Yesod.Test.CssQuery
|
||||||
import Yesod.Test.TransversingCSS
|
import Yesod.Test.TransversingCSS
|
||||||
|
|||||||
@ -57,6 +57,7 @@ test-suite test
|
|||||||
, containers
|
, containers
|
||||||
, html-conduit
|
, html-conduit
|
||||||
, yesod-core
|
, yesod-core
|
||||||
|
, yesod-shakespeare
|
||||||
, yesod-form
|
, yesod-form
|
||||||
, text
|
, text
|
||||||
, wai
|
, wai
|
||||||
|
|||||||
@ -4,10 +4,12 @@
|
|||||||
module Yesod
|
module Yesod
|
||||||
( -- * Re-exports from yesod-core
|
( -- * Re-exports from yesod-core
|
||||||
module Yesod.Core
|
module Yesod.Core
|
||||||
|
, module Yesod.Shakespeare
|
||||||
, module Yesod.Form
|
, module Yesod.Form
|
||||||
, module Yesod.Persist
|
, module Yesod.Persist
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Yesod.Core
|
import Yesod.Core
|
||||||
|
import Yesod.Shakespeare
|
||||||
import Yesod.Form
|
import Yesod.Form
|
||||||
import Yesod.Persist
|
import Yesod.Persist
|
||||||
|
|||||||
@ -17,6 +17,7 @@ module Yesod.Default.Util
|
|||||||
import qualified Data.ByteString.Lazy as L
|
import qualified Data.ByteString.Lazy as L
|
||||||
import Data.Text (Text, pack, unpack)
|
import Data.Text (Text, pack, unpack)
|
||||||
import Yesod.Core -- purposely using complete import so that Haddock will see addStaticContent
|
import Yesod.Core -- purposely using complete import so that Haddock will see addStaticContent
|
||||||
|
import Yesod.Shakespeare
|
||||||
import Control.Monad (when, unless)
|
import Control.Monad (when, unless)
|
||||||
import System.Directory (doesFileExist, createDirectoryIfMissing)
|
import System.Directory (doesFileExist, createDirectoryIfMissing)
|
||||||
import Language.Haskell.TH.Syntax
|
import Language.Haskell.TH.Syntax
|
||||||
|
|||||||
@ -19,6 +19,7 @@ library
|
|||||||
|
|
||||||
build-depends: base >= 4.3 && < 5
|
build-depends: base >= 4.3 && < 5
|
||||||
, yesod-core >= 1.4 && < 1.5
|
, yesod-core >= 1.4 && < 1.5
|
||||||
|
, yesod-shakespeare >= 1.5 && < 1.6
|
||||||
, yesod-auth >= 1.4 && < 1.5
|
, yesod-auth >= 1.4 && < 1.5
|
||||||
, yesod-persistent >= 1.4 && < 1.5
|
, yesod-persistent >= 1.4 && < 1.5
|
||||||
, yesod-form >= 1.4 && < 1.5
|
, yesod-form >= 1.4 && < 1.5
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user