How i can use shakespeare (from yesod) for servant webservices APIs?
I try:
type TestAPI
= "tests" :> Get '[JSON] [Test]
:<|> "Test.html" :> Get '[HTML] Html
serverTestAPI :: ServerT TestAPI AppM
serverTestAPI = tests
:<|> test
:<|> testHtml
tests :: AppM [Test]
tests = do return [ Test 1 "Test 1"
, Test 2 "Test 2"
]
testHtml = [hamlet|
$doctype 5
.........
|]
But I get error!
As @Carsten points out, in this case what you want is shamlet
. The key thing is implementing proper instances of the ToMarkup
typeclass. I recommend you to read this excellent introduction on Shakespeare templates. A working example:
data Person = Person
{ firstName :: String
, lastName :: String
} deriving Generic
instance ToJSON Person
type PersonAPI = "persons" :> Get '[JSON, HTML] [Person]
people :: [Person]
people =
[ Person "Isaac" "Newton"
, Person "Albert" "Einstein"
]
instance ToMarkup Person where
toMarkup person = showPerson person
-- this isn't properly implemented
preEscapedToMarkup p = showPerson p
-- HTML serialization of a list of persons
instance ToMarkup [Person] where
toMarkup persons = showPersons persons
preEscapedToMarkup p = showPersons p
showPerson :: Person -> Html
showPerson p = [shamlet|
<body>
<p>This is my page.
<h1>#{firstName p}
|]
showPersons :: [Person] -> Html
showPersons p = [shamlet|
<body>
<p>This is my page.
$forall person <- p
<h1>#{firstName person}
|]
Here is a small complete example that works for me:
{-# LANGUAGE DataKinds, PolyKinds, TypeOperators, DeriveGeneric #-}
{-# LANGUAGE QuasiQuotes #-}
module Main where
import Data.Aeson
import Data.Proxy
import GHC.Generics
import Network.Wai.Handler.Warp
import Servant.API
import Servant.HTML.Blaze
import Servant.Server
import Text.Blaze.Html
import Text.Hamlet
data Test = Test Int String
deriving (Generic)
instance ToJSON Test
type TestAPI
= "tests" :> Get '[JSON] [Test]
:<|> "Test.html" :> Get '[HTML] Html
main :: IO ()
main = run 8080 (serve (Proxy :: Proxy TestAPI) serverTestAPI)
serverTestAPI :: Server TestAPI
serverTestAPI = tests :<|> testHtml
tests = return [ Test 1 "Test 1"
, Test 2 "Test 2"
]
testHtml = return [shamlet|
$doctype 5
<html>
<head>
<title>This is a title
<body>
<p>This is text
|]
Thank you all for your help!
Implemented as follows:
<code>type TestAPI
= "tests" :> Get '[JSON] [Test]
:<|> "test" :> Get '[JSON] Test
:<|> "TestHTML.html" :> Get '[HTML] Page_TestHTML
serverTestAPI :: ServerT TestAPI AppM
serverTestAPI = tests
:<|> test
:<|> testHtml
data Page_TestHTML = Page_TestHTML
instance ToMarkup Page_TestHTML where
toMarkup Page_TestHTML = builderHtml
testHtml = return Page_TestHTML
builderHtml = [shamlet|
$doctype 5
<html>
<head>
<title>Greeting2
<body>
<h2> Hello world HTML Qqqqq |]</code>