Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Surprising behavior with Appendable subclasses. #84

Open
pauldraper opened this issue Jun 28, 2015 · 1 comment
Open

Surprising behavior with Appendable subclasses. #84

pauldraper opened this issue Jun 28, 2015 · 1 comment

Comments

@pauldraper
Copy link
Contributor

This is a custom format that escapes | as bar.

src/main/scala/example/Example.scala

package example

import play.twirl.api._
import scala.collection.immutable

sealed trait Example extends Appendable[Example] {
  val contentType = "text/example"

  def appendTo(sb: StringBuilder)

  override def toString = {
    val sb = new StringBuilder
    appendTo(sb)
    sb.toString
  }
}

object ExampleFormat extends Format[Example] {
  val empty = raw("")

  def escape(text: String) = raw(text.replace("|", "bar"))

  def fill(elements: immutable.Seq[Example]) = new Example {
    def appendTo(sb: StringBuilder): Unit = elements.foreach(_.appendTo(sb))
  }

  def raw(text: String) = new Example {
    def appendTo(sb: StringBuilder): Unit = sb ++= text
  }
}

src/main/twirl/example/my.ex

@(text: String)

| @text |

The result of example.ex.my("bar") is bar bar bar instead of | bar |.

The template text is unexpectedly being escaped. This is because the runtime type is not Example and https://github.com/playframework/twirl/blob/master/api/src/main/scala/play/twirl/api/BaseScalaTemplate.scala#L20.

This could be improved to be T or a subtype, instead of only T.


(More generally, I feel like the runtime type branching in BaseScalaTemplate could be eliminated.)

@szeiger
Copy link

szeiger commented Aug 15, 2016

I just ran into the same issue with HtmlFormat. Here's a simple reproduction:

@{(new play.twirl.api.Html("<foo>")): play.twirl.api.HtmlFormat.Appendable}
@{(new play.twirl.api.Html("<foo>") {}): play.twirl.api.HtmlFormat.Appendable}

renders as:

<foo>
&lt;foo&gt;

This makes it impossible to implement any meaningful subclasses of Html for custom rendering.

It's not clear to me why it doesn't pick the correct static overload in the first place but at least the dynamic version should behave the same (i.e. allows subtypes).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants