Created
March 1, 2013 18:51
-
-
Save hexx/5066853 to your computer and use it in GitHub Desktop.
HtmlDSL using Dynamic
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import scala.language.dynamics | |
import scala.util.DynamicVariable | |
sealed trait Node { | |
def toXml: String | |
} | |
case class ElementNode(name: String, attributes: Map[String, String], children: List[Node]) extends Node { | |
def toXml = { | |
val as = attributes.mapValues("\"" + _ + "\"") | |
s"""<${name}${as.map { case (l, r) => s" $l=$r" }.mkString}>${children.map(_.toXml).mkString}</${name}>""" | |
} | |
} | |
case class TextNode(text: String) extends Node { | |
def toXml = text | |
} | |
trait HtmlDSL { | |
protected val nodes = new DynamicVariable[List[Node]](null) | |
protected val attributes = new DynamicVariable[List[(String, String)]](null) | |
object % extends Dynamic{ | |
def selectDynamic(name: String) = applyDynamic(name){} | |
def applyDynamic(name: String)(body: => Unit): Unit = { | |
val (ns, as) = | |
nodes.withValue(List()) { | |
attributes.withValue(List()) { | |
body | |
(nodes.value.reverse, attributes.value.toMap) | |
} | |
} | |
nodes.value = ElementNode(name, as, ns) :: nodes.value | |
} | |
} | |
def $(as: (String, String)*) = attributes.value = attributes.value ++ as | |
def t(text: String) = nodes.value = TextNode(text) :: nodes.value | |
def dsl(body: => Unit) = nodes.withValue(List()) { | |
body | |
nodes.value.head | |
} | |
} | |
object Sample extends HtmlDSL { | |
val html = dsl { | |
%html { | |
%head { | |
%link($("rel" -> "stylesheet", "href" -> "style.css")) | |
%title { | |
t("タイトルだよ") | |
} | |
} | |
%body { | |
%p { | |
t("本文だよ") | |
} | |
} | |
} | |
} | |
def print = println(html.toXml) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment