Playframework: используйте Scalatags вместо 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")
но разве это единственный путь? (Без создания вспомогательного метода, который есть)
1 ответ
Я полагаю, вы хотите иметь возможность позвонить Ok(views.Test.build)
, Игра не знает 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))
}
Не забудьте включить декларацию типа документа. 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
заголовок 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)
}
Возможно, вы захотите убрать эти следствия в удобное для вас место, а затем импортировать их в свои контроллеры.