我更喜欢使用前者而不是后者,但不确定如何将Scalatags整合到游戏框架中。

这是我的简单布局:

object Test
{
  import scalatags.Text.all._
  def build =
  {

    html(
      head(
        title := "Test"
      ),
      body(

        h1("This is a Triumph"),
        div(
          "Test"
        )
      )
    )
  }
}

这是我尝试呈现的方式:
Ok(views.Test.build.render)

问题是,我将其作为纯字符串而不是HTML来获取。

现在,一种解决方案当然是简单地追加。
Ok(views.Test.build.render).as("text/html")

但这真的是唯一的方法吗? (不创建是这样的辅助方法)

最佳答案

我假设您希望能够调用Ok(views.Test.build)。 Play 不了解ScalaTags,因此我们将不得不在这里自己编写一些东西。

Play使用了一些隐式机制来生成HTTP响应。当您调用Ok(...)时,您实际上是在apply特性上调用play.api.mvc.Results。让我们看一下它的签名:

def apply[C](content: C)(implicit writeable: Writeable[C]): Result

因此,我们可以看到我们需要一个隐式的Writeable[scalatags.Text.all.Tag]:
implicit def writeableOfTag(implicit codec: Codec): Writeable[Tag] = {
  Writeable(tag => codec.encode("<!DOCTYPE html>\n" + tag.render))
}

不要忘了包括一个doctype声明。 ScalaTags没有给您一个。

Writeable.apply本身的调用需要另一个隐式函数来确定内容类型。这是它的签名:
def apply[A](transform: A => ByteString)(implicit ct: ContentTypeOf[A]): Writeable[A]

因此,让我们写一个隐式的ContentTypeOf[Tag]:
implicit def contentTypeOfTag(implicit codec: Codec): ContentTypeOf[Tag] = {
  ContentTypeOf[Tag](Some(ContentTypes.HTML))
}

这使我们避免了必须显式地编写as("text/html"),并且它包括字符集(由隐式编解码器提供),从而产生了Content-Typetext/html; charset=utf-8 header 。

放在一起:
import play.api.http.{ ContentTypeOf, ContentTypes, Writeable }
import play.api.mvc.Results.Ok
import scalatags.Text.all._

def build: Tag = {
  html(
    head(
      title := "Test"
    ),
    body(

      h1("This is a Triumph"),
      div(
        "Test"
      )
    )
  )
}

implicit def contentTypeOfTag(implicit codec: Codec): ContentTypeOf[Tag] = {
  ContentTypeOf[Tag](Some(ContentTypes.HTML))
}

implicit def writeableOfTag(implicit codec: Codec): Writeable[Tag] = {
  Writeable(tag => codec.encode("<!DOCTYPE html>\n" + tag.render))
}

def foo = Action { implicit request =>
  Ok(build)
}

您可能希望将这些隐式变量塞在方便的地方,然后将其导入到 Controller 中。

10-06 10:16