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)
}

Возможно, вы захотите убрать эти следствия в удобное для вас место, а затем импортировать их в свои контроллеры.

Другие вопросы по тегам