Skip to content

Commit

Permalink
Node: Add textContent function
Browse files Browse the repository at this point in the history
Closes #65.
  • Loading branch information
tindzk committed May 11, 2020
1 parent 2bf960e commit 94e1e1c
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 6 deletions.
27 changes: 21 additions & 6 deletions src/main/scala/pine/Node.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,18 @@ sealed trait Node {
def map(f: Node => Node): T
def flatMap(f: Node => List[Node]): T
def mapFirst(f: PartialFunction[Node, Node]): T

/** Recursively traverses tree and returns content of first text node */
def textContent: Option[String]
}

case class Text(text: String) extends Node {
override type T = Text

def map(f: Node => Node): T = this
def flatMap(f: Node => List[Node]): T = this
def mapFirst(f: PartialFunction[Node, Node]): T = this
override def map(f: Node => Node): T = this
override def flatMap(f: Node => List[Node]): T = this
override def mapFirst(f: PartialFunction[Node, Node]): T = this
override def textContent: Option[String] = Some(text)
}

case class Tag[TagName <: Singleton](tagName : String with TagName,
Expand Down Expand Up @@ -129,7 +133,7 @@ case class Tag[TagName <: Singleton](tagName : String with TagName,
}

/** Recursively map children, excluding root node */
def map(f: Node => Node): Tag[TagName] = set(children.map(f(_).map(f)))
override def map(f: Node => Node): Tag[TagName] = set(children.map(f(_).map(f)))

/** Recursively map tag children, including root node */
def mapRoot(f: Tag[_] => Tag[_]): Tag[TagName] = {
Expand All @@ -142,10 +146,10 @@ case class Tag[TagName <: Singleton](tagName : String with TagName,
iter(this).asInstanceOf[T]
}

def flatMap(f: Node => List[Node]): Tag[TagName] =
override def flatMap(f: Node => List[Node]): Tag[TagName] =
copy(children = children.flatMap(n => f(n.flatMap(f))))

def mapFirst(f: PartialFunction[Node, Node]): Tag[TagName] = {
override def mapFirst(f: PartialFunction[Node, Node]): Tag[TagName] = {
var done = false

def m(n: Node): Node =
Expand All @@ -168,6 +172,17 @@ case class Tag[TagName <: Singleton](tagName : String with TagName,
def partialMap(f: PartialFunction[Node, Node]): Tag[TagName] =
map(node => f.lift(node).getOrElse(node))

override def textContent: Option[String] = {
for (c <- children) {
c.textContent match {
case Some(c) => return Some(c)
case _ =>
}
}

None
}

/**
* Recursively adds `suffix` to every given attribute.
*
Expand Down
26 changes: 26 additions & 0 deletions src/test/scala/pine/NodeSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -406,4 +406,30 @@ class NodeSpec extends FunSuite {
assert(tag.Div.dataLanguage(Language.Spanish).toHtml ==
"""<div data-language="spanish"></div>""")
}

test("textContent") {
// top-level text node
val n = Text("hello world")
assert(n.textContent == Some("hello world"))

// an empty string is treated like a regular text node
val n2 = Text("")
assert(n2.textContent == Some(""))

// one nesting level
val n3 = tag.Div.set(Text("hello"))
assert(n3.textContent == Some("hello"))

// two nesting levels
val n4 = tag.Div.set(tag.Div.set(Text("hello")))
assert(n4.textContent == Some("hello"))

// return only first text node
val n5 = tag.Div.set(List(tag.Div.set(Text("hello")), Text(" world")))
assert(n5.textContent == Some("hello"))

// no text node found
val n6 = tag.Div
assert(n6.textContent == None)
}
}

0 comments on commit 94e1e1c

Please sign in to comment.