{-# 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 -- * Formerly Yesod.Core.Handler -- ** Redirecting , redirectToPost -- * Shakespeare -- ** Hamlet , hamlet , shamlet , xhamlet , HtmlUrl -- ** Julius , julius , JavascriptUrl , renderJavascriptUrl -- ** Cassius/Lucius , cassius , lucius , CssUrl , renderCssUrl , module Text.Shakespeare.I18N ) where import Control.Monad.IO.Class (MonadIO) import Control.Monad (liftM, forM) import Control.Monad.Trans.Class (lift) import Text.Shakespeare.I18N import qualified Data.ByteString.Lazy as L import Data.List (foldl', nub) 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 (Last(..), mempty) import qualified Data.Map as Map 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.Types import Yesod.Core.Widget import Yesod.Core.Class.Handler (HandlerSite, MonadHandler) import Yesod.Core.Handler (getUrlRenderParams, toTextUrl, invalidArgs, permissionDenied, RedirectUrl, withUrlRenderer, getRequest, getYesod, sendResponse) import Yesod.Core.Content (ToContent(..), ToTypedContent(..), HasContentType(..), typeJavascript, typeCss) import Yesod.Routes.Class (Route) -- for hamlet expansion import qualified Data.Foldable import qualified Data.Text import Text.Hamlet (asHtmlUrl) 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 -- | 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