^{pageBody pc} 从哪里来?

where does ^{pageBody pc} come from?

在 default-layout-wrapper.hamlet 文件中,有 ^{pageBody pc} 允许我嵌入正文内容。我可以在 Foundation.hs 文件中找到 pc 部分。但是 pageBody 是在哪里构建的(在什么文件中)? 此变量的相同问题 #{pageTitle pc}.

Hoogle 在 stackage.org 上是解决此类问题的重要资源:

http://www.stackage.org/lts/hoogle?q=pageBody

pageBody 是在 "variable" 调用的 pc 上调用的函数。正如 Michael 所说,pageBody 是标准 Yesod 库的一部分。当 whamlet 引擎处理您的页面模板时,它将被评估(这就是 ^{...} 所做的)。如果您确实使用 Yesod 创建了一个脚手架站点,请花一些时间阅读自动生成的处理函数 - 您将看到模板是如何处理的。

简化类型:

data PageContent url = PageContent
    { pageTitle :: Html
    , pageHead :: HtmlUrl url
    , pageBody :: HtmlUrl url
    }
widgetToPageContent :: Widget -> Handler (PageContent url)

... 和代码示例:

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes       #-}
{-# LANGUAGE TemplateHaskell   #-}
{-# LANGUAGE TypeFamilies      #-}
import           Yesod

data App = App
mkYesod "App" [parseRoute|
/ HomeR GET
|]

myLayout :: Widget -> Handler Html
myLayout widget = do
    pc <- widgetToPageContent $ do
        widget
        toWidget [lucius| body { font-family: arial } |]
    withUrlRenderer
        [hamlet|
            $doctype 5
            <html>
                <head>
                    <title>#{pageTitle pc}
                    <meta charset=utf-8>
                    ^{pageHead pc}
                <body>
                    <article>
                        ^{pageBody pc}
        |]

instance Yesod App where
    defaultLayout = myLayout

getHomeR :: Handler Html
getHomeR = defaultLayout
    [whamlet|
        <p>Some text!
    |]

main :: IO ()
main = warp 3000 App

在脚手架上 Foundations.hs:

defaultLayout widget = do
    master <- getYesod
    mmsg <- getMessage

    -- We break up the default layout into two components:
    -- default-layout is the contents of the body tag, and
    -- default-layout-wrapper is the entire page. Since the final
    -- value passed to hamletToRepHtml cannot be a widget, this allows
    -- you to use normal widget features in default-layout.

    pc <- widgetToPageContent $ do
        addStylesheet $ StaticR css_bootstrap_css
        $(widgetFile "default-layout")
    withUrlRenderer $(hamletFile "templates/default-layout-wrapper.hamlet")