Skip to content

Commit

Permalink
Use literal types for tags
Browse files Browse the repository at this point in the history
  • Loading branch information
tindzk committed Jun 5, 2017
1 parent 39e9369 commit 253b3af
Show file tree
Hide file tree
Showing 139 changed files with 2,277 additions and 7,737 deletions.
18 changes: 15 additions & 3 deletions build.sbt
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -11,7 +11,13 @@ val ScalaJsDom = "0.9.1"
val SharedSettings = Seq( val SharedSettings = Seq(
name := "pine", name := "pine",
organization := "tech.sparse", organization := "tech.sparse",
scalaVersion := Scala2_12,
// scalaVersion := Scala2_12,
scalaOrganization := "org.typelevel",
scalaVersion := "2.12.2-bin-typelevel-4",

scalacOptions += "-Yliteral-types",

crossScalaVersions := Seq(Scala2_12, Scala2_11), crossScalaVersions := Seq(Scala2_12, Scala2_11),
pomExtra := pomExtra :=
<url>https://github.com/sparsetech/pine</url> <url>https://github.com/sparsetech/pine</url>
Expand Down Expand Up @@ -44,8 +50,11 @@ lazy val pine = crossProject(JSPlatform, JVMPlatform, NativePlatform)
.in(file(".")) .in(file("."))
.settings(SharedSettings: _*) .settings(SharedSettings: _*)
.settings( .settings(
addCompilerPlugin("org.scalamacros" % "paradise" % Paradise cross CrossVersion.full), addCompilerPlugin("org.scalamacros" % "paradise" % Paradise cross CrossVersion.patch),
libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaVersion.value, libraryDependencies ++= Seq(
scalaOrganization.value % "scala-reflect" % scalaVersion.value % "provided",
scalaOrganization.value % "scala-compiler" % scalaVersion.value % "provided"
),
convertMDN := MDNParser.createFiles(new File("shared/src/main/scala")) convertMDN := MDNParser.createFiles(new File("shared/src/main/scala"))
) )
.jvmSettings( .jvmSettings(
Expand All @@ -54,6 +63,9 @@ lazy val pine = crossProject(JSPlatform, JVMPlatform, NativePlatform)
"org.scalacheck" %% "scalacheck" % ScalaCheck % "test" "org.scalacheck" %% "scalacheck" % ScalaCheck % "test"
) )
).jsSettings( ).jsSettings(
// From https://github.com/scala-js/scala-js/pull/2954
libraryDependencies := libraryDependencies.value.filterNot(_.name == "scalajs-compiler"),
addCompilerPlugin("org.scala-js" % "scalajs-compiler" % scalaJSVersion cross CrossVersion.patch),
libraryDependencies ++= Seq( libraryDependencies ++= Seq(
"org.scala-js" %%% "scalajs-dom" % ScalaJsDom, "org.scala-js" %%% "scalajs-dom" % ScalaJsDom,
"org.scalatest" %%% "scalatest" % ScalaTest % "test", "org.scalatest" %%% "scalatest" % ScalaTest % "test",
Expand Down
2 changes: 1 addition & 1 deletion js/src/main/scala/pine/HtmlParser.scala
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ object HtmlParser {
} }


Option(node) Option(node)
.map(DOM.toTree[Node]) .map(DOM.toTree[SString])
.getOrElse(Text("")) .getOrElse(Text(""))
} }
} }
22 changes: 12 additions & 10 deletions js/src/main/scala/pine/dom/DOM.scala
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package pine.dom
import org.scalajs.dom import org.scalajs.dom


import pine._ import pine._
import pine.tag.HTMLTag


object DOM { object DOM {
trait Extensions { trait Extensions {
Expand All @@ -24,7 +23,7 @@ object DOM {
if (reference == null || reference.nextSibling == null) parent.appendChild(node) if (reference == null || reference.nextSibling == null) parent.appendChild(node)
else parent.insertBefore(node, reference.nextSibling) else parent.insertBefore(node, reference.nextSibling)


def toTree[T <: Node]: T = DOM.toTree(parent) def toTree[T <: SString]: Tag[T] = DOM.toTree[T](parent)
} }
} }


Expand All @@ -43,9 +42,9 @@ object DOM {
case _ => Map.empty case _ => Map.empty
} }


def toTree[T <: Node](node: dom.Node): T = private def _toTree(node: dom.Node): Node =
node match { node match {
case t: dom.raw.Text => Text(t.textContent).asInstanceOf[T] case t: dom.raw.Text => Text(t.textContent)


case e: dom.Element => case e: dom.Element =>
val attributes = (0 until e.attributes.length) val attributes = (0 until e.attributes.length)
Expand All @@ -61,17 +60,20 @@ object DOM {
.filter { .filter {
case _: dom.Comment => false case _: dom.Comment => false
case _ => true case _ => true
}.map(toTree[Node]) }.map(_toTree)


HTMLTag.fromTag( Tag(
tagName = e.tagName, tagName = e.tagName.asInstanceOf[SString], // TODO Remove cast
attributes = attributes, attributes = attributes,
children = children children = children
).asInstanceOf[T] )
} }


def toTree[T <: Tag](id: String): T = def toTree[T <: SString](node: dom.Node): Tag[T] =
toTree[T](dom.document.getElementById(id)) _toTree(node).asInstanceOf[Tag[T]]

def toTree[T <: SString](id: String): Tag[T] =
toTree(dom.document.getElementById(id)).as[T]


def render(node: Node): dom.Element = NodeRender.render(node) def render(node: Node): dom.Element = NodeRender.render(node)


Expand Down
4 changes: 2 additions & 2 deletions js/src/main/scala/pine/dom/Implicits.scala
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import org.scalajs.dom.ext.KeyCode
import pine._ import pine._


trait Implicits { trait Implicits {
implicit class TagRefExtensions[T <: Tag](tagRef: TagRef[T]) { implicit class TagRefExtensions[T <: SString](tagRef: TagRef[T]) {
def onEnter(f: String => Unit)(implicit js: Js[T], ev: T <:< tag.Input): Unit = def onEnter(f: String => Unit)(implicit js: Js[T], ev: T <:< tag.Input): Unit =
tagRef.keyPress := { e => tagRef.keyPress := { e =>
if (e.keyCode == KeyCode.Enter) if (e.keyCode == KeyCode.Enter)
Expand Down Expand Up @@ -125,7 +125,7 @@ trait Implicits {
new Event(dom.oninput = _) new Event(dom.oninput = _)
} }


implicit class AttributeExtensions[T <: Tag, G](attribute: Attribute[T, G, _]) { implicit class AttributeExtensions[T <: SString, G](attribute: Attribute[T, G, _]) {
/** TODO Introduce BooleanAttribute and StringAttribute for better type-safety? */ /** TODO Introduce BooleanAttribute and StringAttribute for better type-safety? */
def get(implicit js: Js[T]): G = def get(implicit js: Js[T]): G =
if (HtmlHelpers.BooleanAttributes.contains(attribute.name)) if (HtmlHelpers.BooleanAttributes.contains(attribute.name))
Expand Down
5 changes: 2 additions & 3 deletions js/src/main/scala/pine/dom/Js.scala
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ package pine.dom
import org.scalajs.dom import org.scalajs.dom
import pine._ import pine._


trait Js[T <: Tag] { type X <: dom.html.Element } trait Js[T <: SString] { type X <: dom.html.Element }


trait JsLowPrio { trait JsLowPrio {
implicit object JsTag extends Js[Tag] { override type X = dom.html.Element } implicit object JsTag extends Js[SString] { override type X = dom.html.Element }
} }


object Js extends JsLowPrio { object Js extends JsLowPrio {
Expand All @@ -28,7 +28,6 @@ object Js extends JsLowPrio {
implicit object JsDataList extends Js[tag.Datalist] { override type X = dom.html.DataList } implicit object JsDataList extends Js[tag.Datalist] { override type X = dom.html.DataList }
implicit object JsDirectory extends Js[tag.Dir] { override type X = dom.html.Directory } implicit object JsDirectory extends Js[tag.Dir] { override type X = dom.html.Directory }
implicit object JsDiv extends Js[tag.Div] { override type X = dom.html.Div } implicit object JsDiv extends Js[tag.Div] { override type X = dom.html.Div }
implicit object JsElement extends Js[tag.HTMLTag] { override type X = dom.html.Element }
implicit object JsEmbed extends Js[tag.Embed] { override type X = dom.html.Embed } implicit object JsEmbed extends Js[tag.Embed] { override type X = dom.html.Embed }
implicit object JsFieldSet extends Js[tag.Fieldset] { override type X = dom.html.FieldSet } implicit object JsFieldSet extends Js[tag.Fieldset] { override type X = dom.html.FieldSet }
implicit object JsForm extends Js[tag.Form] { override type X = dom.html.Form } implicit object JsForm extends Js[tag.Form] { override type X = dom.html.Form }
Expand Down
8 changes: 4 additions & 4 deletions js/src/main/scala/pine/dom/NodeRender.scala
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ object NodeRender extends NodeRender[Node, dom.Element] {


override def render(node: Node): dom.Element = override def render(node: Node): dom.Element =
node match { node match {
case n: Tag => RenderTag.render(n) case n: Tag[SString] => RenderTag.render(n)
case n: Text => RenderText.render(n) case n: Text => RenderText.render(n)
} }


implicit case object RenderTag extends NodeRender[Tag, dom.Element] { implicit case object RenderTag extends NodeRender[Tag[SString], dom.Element] {
def render(node: Tag): dom.Element = { def render(node: Tag[SString]): dom.Element = {
val element = dom.document.createElement(node.tagName) val element = dom.document.createElement(node.tagName)


node.attributes.foreach { case (k, v) => node.attributes.foreach { case (k, v) =>
Expand Down
6 changes: 3 additions & 3 deletions js/src/test/scala/pine/dom/DOMSpec.scala
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ class DOMSpec extends FunSuite {
assert(test.id.get == "test") assert(test.id.get == "test")
assert(test.children.nonEmpty) assert(test.children.nonEmpty)


val input = test.children.head.asInstanceOf[tag.Input] val input = test.children.head.asInstanceOf[Tag[tag.Input]]
assert(input.checked) assert(input.checked)


assert(node.childNodes.length == 1) assert(node.childNodes.length == 1)
Expand All @@ -264,13 +264,13 @@ class DOMSpec extends FunSuite {
val div = DOM.render(html"""<div id="test"><span id="hello">Hello</span></div>""") val div = DOM.render(html"""<div id="test"><span id="hello">Hello</span></div>""")
dom.document.body.appendChild(div) dom.document.body.appendChild(div)


val ref = TagRef(tag.Span()) val ref = TagRef[tag.Span]
DOM.render { implicit ctx => DOM.render { implicit ctx =>
ref.replace(html"<div>World</div>") ref.replace(html"<div>World</div>")
} }


assert( assert(
DOM.toTree[Tag](dom.document.getElementById("test")) == DOM.toTree(dom.document.getElementById("test")) ==
html"""<div id="test"><div>World</div></div>""") html"""<div id="test"><div>World</div></div>""")
dom.document.body.removeChild(div) dom.document.body.removeChild(div)
} }
Expand Down
4 changes: 2 additions & 2 deletions js/src/test/scala/pine/dom/TagRefSpec.scala
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -145,8 +145,8 @@ class TagRefSpec extends FunSuite {
document.body.appendChild(node) document.body.appendChild(node)
document.body.appendChild(div) document.body.appendChild(div)


val tagRef1 = TagRef(tag.Input()) val tagRef1 = TagRef[tag.Input]
val tagRef2 = TagRef(tag.Div()) val tagRef2 = TagRef[tag.Div]


assert(tagRef1.dom == node) assert(tagRef1.dom == node)
assert(tagRef2.dom == div) assert(tagRef2.dom == div)
Expand Down
Loading

0 comments on commit 253b3af

Please sign in to comment.