Using Servant with Yesod shakespeare (Hamlet, Julius, Lucius)

旧巷老猫 提交于 2019-12-06 14:56:32

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>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!