Skip to content

Instantly share code, notes, and snippets.

@abhandaru
Created March 28, 2018 00:51
Show Gist options
  • Save abhandaru/a29799db9f669421d77410d9f2c1f399 to your computer and use it in GitHub Desktop.
Save abhandaru/a29799db9f669421d77410d9f2c1f399 to your computer and use it in GitHub Desktop.
Minimal mustache-scala string template example
import collection.JavaConverters
import com.github.mustachejava.reflect.ReflectionObjectHandler
import com.github.mustachejava.{DefaultMustacheFactory, Iteration, MustacheFactory}
import java.io.{StringReader, StringWriter, Writer}
import java.lang.reflect.{Field, Method}
import java.util.{List => JList}
import runtime.BoxedUnit
import scala.reflect.ClassTag
object Mustache {
private[util] val Factory: MustacheFactory = {
val mf = new DefaultMustacheFactory
mf.setObjectHandler(ScalaObjectHandler)
mf
}
}
case class MustacheTemplate(template: String) {
val innerTemplate = Mustache.Factory.compile(new StringReader(template), "tmp")
def apply(context: Any): String = {
val writer = new StringWriter
innerTemplate.execute(writer, context)
writer.flush
writer.toString
}
}
/**
* Adapted from here:
* https://github.com/spullara/mustache.java/blob/master/scala-extensions/scala-extensions-2.11/src/main/scala/com/twitter/mustache/ScalaObjectHandler.scala
*/
object ScalaObjectHandler extends ReflectionObjectHandler {
import JavaConverters._
override def checkMethod(member: Method) {}
override def checkField(member: Field) {}
override def coerce(value: AnyRef) = {
value match {
case m: collection.Map[_, _] => mapAsJavaMap(m)
case u: BoxedUnit => null
case Some(some: AnyRef) => coerce(some)
case None => null
case _ => value
}
}
override def iterate(iteration: Iteration, writer: Writer, value: AnyRef, scopes: JList[AnyRef]) = {
value match {
case TraversableAnyRef(t) => {
var newWriter = writer
t foreach {
next =>
newWriter = iteration.next(newWriter, coerce(next), scopes)
}
newWriter
}
case n: Number => if (n.intValue() == 0) writer else iteration.next(writer, coerce(value), scopes)
case _ => super.iterate(iteration, writer, value, scopes)
}
}
override def falsey(iteration: Iteration, writer: Writer, value: AnyRef, scopes: JList[AnyRef]) = {
value match {
case TraversableAnyRef(t) => {
if (t.isEmpty) {
iteration.next(writer, value, scopes)
} else {
writer
}
}
case n: Number => if (n.intValue() == 0) iteration.next(writer, coerce(value), scopes) else writer
case _ => super.falsey(iteration, writer, value, scopes)
}
}
val TraversableAnyRef = new Def[Traversable[AnyRef]]
class Def[C: ClassTag] {
def unapply[X: ClassTag](x: X): Option[C] = {
x match {
case c: C => Some(c)
case _ => None
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment