Skip to content
Permalink
Browse files

Use literal types for tags

  • Loading branch information...
tindzk committed Jun 5, 2017
1 parent 39e9369 commit 253b3afd11fd220507467d102c9e5320fc3479f6
Showing with 2,277 additions and 7,737 deletions.
  1. +15 −3 build.sbt
  2. +1 −1 js/src/main/scala/pine/HtmlParser.scala
  3. +12 −10 js/src/main/scala/pine/dom/DOM.scala
  4. +2 −2 js/src/main/scala/pine/dom/Implicits.scala
  5. +2 −3 js/src/main/scala/pine/dom/Js.scala
  6. +4 −4 js/src/main/scala/pine/dom/NodeRender.scala
  7. +3 −3 js/src/test/scala/pine/dom/DOMSpec.scala
  8. +2 −2 js/src/test/scala/pine/dom/TagRefSpec.scala
  9. +81 −58 project/MDNParser.scala
  10. +1 −1 shared/src/main/scala/pine/Attribute.scala
  11. +8 −8 shared/src/main/scala/pine/Diff.scala
  12. +3 −3 shared/src/main/scala/pine/DiffRender.scala
  13. +51 −71 shared/src/main/scala/pine/Node.scala
  14. +18 −18 shared/src/main/scala/pine/NodeRender.scala
  15. +2 −2 shared/src/main/scala/pine/RenderContext.scala
  16. +11 −10 shared/src/main/scala/pine/TagRef.scala
  17. +1 −2 shared/src/main/scala/pine/dsl/Imports.scala
  18. +3 −3 shared/src/main/scala/pine/internal/HtmlParser.scala
  19. +6 −12 shared/src/main/scala/pine/macros/ExternalHtml.scala
  20. +6 −13 shared/src/main/scala/pine/macros/InlineHtml.scala
  21. +4 −2 shared/src/main/scala/pine/package.scala
  22. +0 −487 shared/src/main/scala/pine/tag/A.scala
  23. +0 −13 shared/src/main/scala/pine/tag/Acronym.scala
  24. +0 −18 shared/src/main/scala/pine/tag/Address.scala
  25. +0 −98 shared/src/main/scala/pine/tag/Applet.scala
  26. +0 −116 shared/src/main/scala/pine/tag/Area.scala
  27. +0 −18 shared/src/main/scala/pine/tag/Article.scala
  28. +1,751 −0 shared/src/main/scala/pine/tag/Attributes.scala
  29. +0 −88 shared/src/main/scala/pine/tag/Audio.scala
  30. +0 −20 shared/src/main/scala/pine/tag/B.scala
  31. +0 −35 shared/src/main/scala/pine/tag/Base.scala
  32. +0 −31 shared/src/main/scala/pine/tag/Basefont.scala
  33. +0 −13 shared/src/main/scala/pine/tag/Big.scala
  34. +0 −76 shared/src/main/scala/pine/tag/Body.scala
  35. +0 −21 shared/src/main/scala/pine/tag/Br.scala
  36. +0 −111 shared/src/main/scala/pine/tag/Button.scala
  37. +0 −46 shared/src/main/scala/pine/tag/Canvas.scala
  38. +0 −37 shared/src/main/scala/pine/tag/Caption.scala
  39. +0 −13 shared/src/main/scala/pine/tag/Center.scala
  40. +0 −12 shared/src/main/scala/pine/tag/Code.scala
  41. +0 −160 shared/src/main/scala/pine/tag/Col.scala
  42. +0 −169 shared/src/main/scala/pine/tag/Colgroup.scala
  43. +0 −12 shared/src/main/scala/pine/tag/Content.scala
  44. +0 −12 shared/src/main/scala/pine/tag/Datalist.scala
  45. +0 −19 shared/src/main/scala/pine/tag/Dd.scala
  46. +0 −23 shared/src/main/scala/pine/tag/Del.scala
  47. +0 −18 shared/src/main/scala/pine/tag/Details.scala
  48. +0 −18 shared/src/main/scala/pine/tag/Dialog.scala
  49. +0 −29 shared/src/main/scala/pine/tag/Dir.scala
  50. +0 −12 shared/src/main/scala/pine/tag/Div.scala
  51. +0 −18 shared/src/main/scala/pine/tag/Dl.scala
  52. +0 −12 shared/src/main/scala/pine/tag/Dt.scala
  53. +0 −15 shared/src/main/scala/pine/tag/Em.scala
  54. +0 −35 shared/src/main/scala/pine/tag/Embed.scala
  55. +0 −66 shared/src/main/scala/pine/tag/Fieldset.scala
  56. +0 −12 shared/src/main/scala/pine/tag/Figcaption.scala
  57. +0 −17 shared/src/main/scala/pine/tag/Figure.scala
  58. +0 −17 shared/src/main/scala/pine/tag/Footer.scala
  59. +0 −117 shared/src/main/scala/pine/tag/Form.scala
  60. +0 −48 shared/src/main/scala/pine/tag/Frame.scala
  61. +0 −24 shared/src/main/scala/pine/tag/Frameset.scala
  62. +0 −12 shared/src/main/scala/pine/tag/H1.scala
  63. +0 −12 shared/src/main/scala/pine/tag/H2.scala
  64. +0 −12 shared/src/main/scala/pine/tag/H3.scala
  65. +0 −12 shared/src/main/scala/pine/tag/H4.scala
  66. +0 −12 shared/src/main/scala/pine/tag/H5.scala
  67. +0 −12 shared/src/main/scala/pine/tag/H6.scala
  68. +0 −265 shared/src/main/scala/pine/tag/HTMLTag.scala
  69. +0 −17 shared/src/main/scala/pine/tag/Head.scala
  70. +0 −16 shared/src/main/scala/pine/tag/Header.scala
  71. +0 −14 shared/src/main/scala/pine/tag/Hgroup.scala
  72. +0 −38 shared/src/main/scala/pine/tag/Hr.scala
  73. +0 −28 shared/src/main/scala/pine/tag/Html.scala
  74. +0 −12 shared/src/main/scala/pine/tag/I.scala
  75. +0 −163 shared/src/main/scala/pine/tag/Iframe.scala
  76. +0 −156 shared/src/main/scala/pine/tag/Img.scala
  77. +0 −414 shared/src/main/scala/pine/tag/Input.scala
  78. +0 −23 shared/src/main/scala/pine/tag/Ins.scala
  79. +0 −23 shared/src/main/scala/pine/tag/Isindex.scala
  80. +0 −114 shared/src/main/scala/pine/tag/Keygen.scala
  81. +0 −31 shared/src/main/scala/pine/tag/Label.scala
  82. +0 −12 shared/src/main/scala/pine/tag/Legend.scala
  83. +0 −44 shared/src/main/scala/pine/tag/Li.scala
  84. +0 −170 shared/src/main/scala/pine/tag/Link.scala
  85. +0 −18 shared/src/main/scala/pine/tag/Listing.scala
  86. +0 −12 shared/src/main/scala/pine/tag/Main.scala
  87. +0 −23 shared/src/main/scala/pine/tag/Map.scala
  88. +0 −46 shared/src/main/scala/pine/tag/Menu.scala
  89. +0 −75 shared/src/main/scala/pine/tag/Menuitem.scala
  90. +0 −362 shared/src/main/scala/pine/tag/Meta.scala
  91. +0 −80 shared/src/main/scala/pine/tag/Meter.scala
  92. +0 −18 shared/src/main/scala/pine/tag/Nav.scala
  93. +0 −12 shared/src/main/scala/pine/tag/Noscript.scala
  94. +0 −105 shared/src/main/scala/pine/tag/Object.scala
  95. +0 −64 shared/src/main/scala/pine/tag/Ol.scala
  96. +0 −25 shared/src/main/scala/pine/tag/Optgroup.scala
  97. +0 −82 shared/src/main/scala/pine/tag/Option.scala
  98. +0 −27 shared/src/main/scala/pine/tag/Output.scala
  99. +0 −12 shared/src/main/scala/pine/tag/P.scala
  100. +0 −39 shared/src/main/scala/pine/tag/Param.scala
  101. +0 −19 shared/src/main/scala/pine/tag/Plaintext.scala
  102. +0 −31 shared/src/main/scala/pine/tag/Pre.scala
  103. +0 −27 shared/src/main/scala/pine/tag/Progress.scala
  104. +0 −77 shared/src/main/scala/pine/tag/Script.scala
  105. +0 −17 shared/src/main/scala/pine/tag/Section.scala
  106. +0 −50 shared/src/main/scala/pine/tag/Select.scala
  107. +0 −12 shared/src/main/scala/pine/tag/Shadow.scala
  108. +0 −12 shared/src/main/scala/pine/tag/Small.scala
  109. +0 −55 shared/src/main/scala/pine/tag/Source.scala
  110. +0 −47 shared/src/main/scala/pine/tag/Spacer.scala
  111. +0 −12 shared/src/main/scala/pine/tag/Span.scala
  112. +0 −20 shared/src/main/scala/pine/tag/Strike.scala
  113. +0 −12 shared/src/main/scala/pine/tag/Strong.scala
  114. +0 −36 shared/src/main/scala/pine/tag/Style.scala
  115. +0 −14 shared/src/main/scala/pine/tag/Summary.scala
  116. +0 −243 shared/src/main/scala/pine/tag/Table.scala
  117. +0 −672 shared/src/main/scala/pine/tag/TagRefAttributes.scala
  118. +0 −139 shared/src/main/scala/pine/tag/Tbody.scala
  119. +0 −202 shared/src/main/scala/pine/tag/Td.scala
  120. +0 −13 shared/src/main/scala/pine/tag/Template.scala
  121. +0 −120 shared/src/main/scala/pine/tag/Textarea.scala
  122. +0 −138 shared/src/main/scala/pine/tag/Tfoot.scala
  123. +0 −204 shared/src/main/scala/pine/tag/Th.scala
  124. +0 −138 shared/src/main/scala/pine/tag/Thead.scala
  125. +0 −12 shared/src/main/scala/pine/tag/Title.scala
  126. +0 −85 shared/src/main/scala/pine/tag/Tr.scala
  127. +0 −91 shared/src/main/scala/pine/tag/Track.scala
  128. +0 −16 shared/src/main/scala/pine/tag/Tt.scala
  129. +0 −53 shared/src/main/scala/pine/tag/Ul.scala
  130. +0 −129 shared/src/main/scala/pine/tag/Video.scala
  131. +0 −18 shared/src/main/scala/pine/tag/Xmp.scala
  132. +218 −0 shared/src/main/scala/pine/tag/package.scala
  133. +5 −5 shared/src/test/scala/pine/DiffSpec.scala
  134. +6 −6 shared/src/test/scala/pine/ExternalHtmlSpec.scala
  135. +8 −8 shared/src/test/scala/pine/HtmlParserSpec.scala
  136. +9 −9 shared/src/test/scala/pine/InlineHtmlSpec.scala
  137. +10 −11 shared/src/test/scala/pine/NodePropSpec.scala
  138. +17 −16 shared/src/test/scala/pine/NodeSpec.scala
  139. +17 −19 shared/src/test/scala/pine/TagRefSpec.scala
@@ -11,7 +11,13 @@ val ScalaJsDom = "0.9.1"
val SharedSettings = Seq(
name := "pine",
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),
pomExtra :=
<url>https://github.com/sparsetech/pine</url>
@@ -44,8 +50,11 @@ lazy val pine = crossProject(JSPlatform, JVMPlatform, NativePlatform)
.in(file("."))
.settings(SharedSettings: _*)
.settings(
addCompilerPlugin("org.scalamacros" % "paradise" % Paradise cross CrossVersion.full),
libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaVersion.value,
addCompilerPlugin("org.scalamacros" % "paradise" % Paradise cross CrossVersion.patch),
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"))
)
.jvmSettings(
@@ -54,6 +63,9 @@ lazy val pine = crossProject(JSPlatform, JVMPlatform, NativePlatform)
"org.scalacheck" %% "scalacheck" % ScalaCheck % "test"
)
).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(
"org.scala-js" %%% "scalajs-dom" % ScalaJsDom,
"org.scalatest" %%% "scalatest" % ScalaTest % "test",
@@ -20,7 +20,7 @@ object HtmlParser {
}

Option(node)
.map(DOM.toTree[Node])
.map(DOM.toTree[SString])
.getOrElse(Text(""))
}
}
@@ -3,7 +3,6 @@ package pine.dom
import org.scalajs.dom

import pine._
import pine.tag.HTMLTag

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

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

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

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

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

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

def toTree[T <: Tag](id: String): T =
toTree[T](dom.document.getElementById(id))
def toTree[T <: SString](node: dom.Node): Tag[T] =
_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)

@@ -6,7 +6,7 @@ import org.scalajs.dom.ext.KeyCode
import pine._

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 =
tagRef.keyPress := { e =>
if (e.keyCode == KeyCode.Enter)
@@ -125,7 +125,7 @@ trait Implicits {
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? */
def get(implicit js: Js[T]): G =
if (HtmlHelpers.BooleanAttributes.contains(attribute.name))
@@ -3,10 +3,10 @@ package pine.dom
import org.scalajs.dom
import pine._

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

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 {
@@ -28,7 +28,6 @@ object Js extends JsLowPrio {
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 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 JsFieldSet extends Js[tag.Fieldset] { override type X = dom.html.FieldSet }
implicit object JsForm extends Js[tag.Form] { override type X = dom.html.Form }
@@ -13,12 +13,12 @@ object NodeRender extends NodeRender[Node, dom.Element] {

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

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

node.attributes.foreach { case (k, v) =>
@@ -253,7 +253,7 @@ class DOMSpec extends FunSuite {
assert(test.id.get == "test")
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(node.childNodes.length == 1)
@@ -264,13 +264,13 @@ class DOMSpec extends FunSuite {
val div = DOM.render(html"""<div id="test"><span id="hello">Hello</span></div>""")
dom.document.body.appendChild(div)

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

assert(
DOM.toTree[Tag](dom.document.getElementById("test")) ==
DOM.toTree(dom.document.getElementById("test")) ==
html"""<div id="test"><div>World</div></div>""")
dom.document.body.removeChild(div)
}
@@ -145,8 +145,8 @@ class TagRefSpec extends FunSuite {
document.body.appendChild(node)
document.body.appendChild(div)

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

assert(tagRef1.dom == node)
assert(tagRef2.dom == div)
Oops, something went wrong.

0 comments on commit 253b3af

Please sign in to comment.
You can’t perform that action at this time.