Playframework:使用 Scalatags 而不是 Twirl
Playframework: Use Scalatags instead of Twirl
我更喜欢使用前者而不是后者,但我不确定如何将 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(...)
时,您实际上是在 play.api.mvc.Results
特征上调用 apply
。我们来看看它的签名:
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))
}
不要忘记包含文档类型声明。 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-Type
header 个 text/html; charset=utf-8
。
综合起来:
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)
}
您可能想将这些隐式隐藏在方便的地方,然后将它们导入您的控制器。
我更喜欢使用前者而不是后者,但我不确定如何将 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(...)
时,您实际上是在 play.api.mvc.Results
特征上调用 apply
。我们来看看它的签名:
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))
}
不要忘记包含文档类型声明。 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-Type
header 个 text/html; charset=utf-8
。
综合起来:
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)
}
您可能想将这些隐式隐藏在方便的地方,然后将它们导入您的控制器。