Skip to content

Commit

Permalink
Merge pull request #57 from prismicio/alw/targetblank
Browse files Browse the repository at this point in the history
add target blank support for parsing and render
  • Loading branch information
srenault authored Apr 23, 2018
2 parents c962ee9 + dca0f33 commit b2cc720
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 58 deletions.
4 changes: 2 additions & 2 deletions src/main/scala/io/prismic/Fragments.scala
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,8 @@ object Fragment {
case a: Timestamp => a.asHtml
case a: Embed => a.asHtml()
case a: Image => a.asHtml
case a: WebLink => a.asHtml
case a: FileLink => a.asHtml
case a: WebLink => a.asHtml()
case a: FileLink => a.asHtml()
case a: GeoPoint => a.asHtml
case a: DocumentLink => a.asHtml(linkResolver)
case a: Group => a asHtml linkResolver
Expand Down
36 changes: 21 additions & 15 deletions src/main/scala/io/prismic/PrismicJsonProtocol.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,27 +15,32 @@ object PrismicJsonProtocol extends DefaultJsonProtocol with NullOptions {
// Fragments

implicit object WeblinkFormat extends RootJsonFormat[WebLink] {
override def read(json: JsValue): WebLink = json.asJsObject.getFields("url") match {
case Seq(JsString(url)) => WebLink(url)
case _ => throw new DeserializationException("Expected url field")
}
override def read(json: JsValue): WebLink = WebLink(
(json \ "url").convertTo[String],
(json \ "target").toOpt[String]
)
override def write(obj: WebLink): JsValue = throw new SerializationException("Not implemented")
}

implicit object FileLinkFormat extends RootJsonFormat[FileLink] {
override def read(json: JsValue): FileLink = (json \ "file").asJsObject.getFields("url", "kind", "size", "name") match {
case Seq(JsString(url), JsString(kind), JsString(size), JsString(name)) => FileLink(url, kind, size.toLong, name)
case _ => throw new DeserializationException("Missing field")
}

override def read(json: JsValue): FileLink = FileLink(
(json \ "url").convertTo[String],
(json \ "kind").convertTo[String],
(json \ "size").convertTo[String].toLong,
(json \ "name").convertTo[String],
(json \ "target").toOpt[String]
)
override def write(obj: FileLink): JsValue = throw new SerializationException("Not implemented")
}

implicit object ImageLinkFormat extends RootJsonFormat[ImageLink] {
override def read(json: JsValue): ImageLink = (json \ "image").asJsObject.getFields("url", "kind", "size", "name") match {
case Seq(JsString(url), JsString(kind), JsString(size), JsString(name)) => ImageLink(url, kind, size.toLong, name)
case _ => throw new DeserializationException("Missing field")
}
override def read(json: JsValue): ImageLink = ImageLink(
(json \ "url").convertTo[String],
(json \ "kind").convertTo[String],
(json \ "size").convertTo[String].toLong,
(json \ "name").convertTo[String],
(json \ "target").toOpt[String]
)

override def write(obj: ImageLink): JsValue = throw new SerializationException("Not implemented")
}
Expand All @@ -56,7 +61,8 @@ object PrismicJsonProtocol extends DefaultJsonProtocol with NullOptions {
(json \ "document" \ "slug").convertTo[String],
(json \ "document" \ "lang").convertTo[String],
fragments,
(json \ "isBroken").toOpt[Boolean].getOrElse(false)
(json \ "isBroken").toOpt[Boolean].getOrElse(false),
(json \ "target").toOpt[String]
)
}
override def write(obj: DocumentLink): JsValue = throw new SerializationException("Not implemented")
Expand Down Expand Up @@ -345,7 +351,7 @@ object PrismicJsonProtocol extends DefaultJsonProtocol with NullOptions {
case Some(structuredText) =>
Seq(s"$typ.$key" -> structuredText)

case None =>
case None =>
jsons.elements.zipWithIndex.collect {
case (json: JsObject, i) => json.toOpt[Fragment].toList.map(fragment => (s"$typ.$key[$i]", fragment))
case (jsval, i) => Nil
Expand Down
51 changes: 37 additions & 14 deletions src/main/scala/io/prismic/fragments/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,39 @@ case object Separator extends Fragment {

sealed trait Link extends Fragment {
def getUrl(linkResolver: DocumentLinkResolver): String
def render(href: String, content: String): String
}

case class WebLink(url: String, contentType: Option[String] = None) extends Link {
case class WebLink(url: String, target: Option[String] = None) extends Link {
override def getUrl(linkResolver: DocumentLinkResolver) = url
def asHtml(): String = s"""<a href="$url">$url</a>"""
override def render(href: String, content: String): String = {
val renderTarget = target.map { t => s""" target="$t" rel="noopener"""" }.getOrElse("")
s"""<a href="$href"$renderTarget>$content</a>"""
}
def asHtml(): String = render(href = url, content = url)
}

case class FileLink(url: String, kind: String, size: Long, filename: String) extends Link {
case class FileLink(url: String, kind: String, size: Long, filename: String, target: Option[String] = None) extends Link {
override def getUrl(linkResolver: DocumentLinkResolver) = url
def asHtml: String = s"""<a href="$url">$filename</a>"""
override def render(href: String, content: String): String = {
val renderTarget = target.map { t => s""" target="$t" rel="noopener"""" }.getOrElse("")
s"""<a href="$href"$renderTarget>$content</a>"""
}
def asHtml(): String = render(href = url, content = filename)
}

case class ImageLink(url: String, kind: String, size: Long, filename: String) extends Link {
case class ImageLink(url: String, kind: String, size: Long, filename: String, target: Option[String] = None) extends Link {
override def getUrl(linkResolver: DocumentLinkResolver) = url
def asHtml: String = s"""<img src="$url" alt="$filename"/>"""
override def render(href: String, content: String): String = {

val img = s"""<img src="$href" alt="$content"/>"""

target match {
case Some(t) => s"""<a href="$href" target="$t" rel="noopener">$img</a>"""
case None => img
}
}
def asHtml(): String = render(href = url, content = filename)
}

case class DocumentLink(id: String,
Expand All @@ -34,9 +52,14 @@ case class DocumentLink(id: String,
slug: String,
lang: String,
fragments: Map[String, Fragment],
isBroken: Boolean) extends Link with WithFragments {
isBroken: Boolean,
target: Option[String] = None) extends Link with WithFragments {
override def getUrl(linkResolver: DocumentLinkResolver) = linkResolver(this)
override def asHtml(linkResolver: DocumentLinkResolver): String = s"""<a href="${linkResolver(this)}">$slug</a>"""
override def asHtml(linkResolver: DocumentLinkResolver): String = render(href = linkResolver(this), content = slug)
override def render(href: String, content: String): String = {
val renderTarget = target.map { t => s""" target="$t" rel="noopener"""" }.getOrElse("")
s"""<a href="$href"$renderTarget>$content</a>"""
}
}

case class AlternateLanguage(id: String, uid: Option[String], typ: String, lang: String)
Expand Down Expand Up @@ -243,9 +266,9 @@ object StructuredText {
case b: Block => Block.asHtml(b, linkResolver)
case _: Span.Em => s"<em>$content</em>"
case _: Span.Strong => s"<strong>$content</strong>"
case Span.Hyperlink(_, _, link: DocumentLink) => s"""<a href="${linkResolver(link)}">$content</a>"""
case Span.Hyperlink(_, _, link: FileLink) => s"""<a href="${link.url}">$content</a>"""
case Span.Hyperlink(_, _, link: WebLink) => s"""<a href="${link.url}">$content</a>"""
case Span.Hyperlink(_, _, link: DocumentLink) => link.render(href = linkResolver(link), content)
case Span.Hyperlink(_, _, link: FileLink) => link.render(href = link.url, content)
case Span.Hyperlink(_, _, link: WebLink) => link.render(href = link.url, content)
case Span.Label(_, _, label) => s"""<span class="$label">$content</span>"""
case _ => s"<span>$content</span>"
}
Expand Down Expand Up @@ -346,9 +369,9 @@ object StructuredText {
case StructuredText.Block.ListItem(text, spans, _, _, _) => s"""<li$cls>$body</li>"""
case StructuredText.Block.Image(view, hyperlink, label, dir) => {
val linkbody = hyperlink match {
case Some(link: DocumentLink) => s"""<a href="$linkResolver(link)">${view.asHtml}</a>"""
case Some(link: WebLink) => s"""<a href="${link.url}">${view.asHtml}</a>"""
case Some(link: FileLink) => s"""<a href="${link.url}">${view.asHtml}</a>"""
case Some(link: DocumentLink) => link.render(href = linkResolver(link), content = view.asHtml)
case Some(link: WebLink) => link.render(href = link.url, content = view.asHtml)
case Some(link: FileLink) => link.render(href = link.url, content = view.asHtml)
case _ => view.asHtml
}
s"""<p${dir.map(d => s""" dir="$d"""").getOrElse("")} class="${(label.toSeq :+ "block-img").mkString(" ")}">$linkbody</p>"""
Expand Down
51 changes: 27 additions & 24 deletions src/test/scala/FragmentSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -52,20 +52,10 @@ class FragmentSpec extends Specification {
}
}
}
"Link" should {
val api = await(Api.get("https://test-public.prismic.io/api"))
def query(q: String) = await(api.forms("everything").ref(api.master).query(q).submit())
val doc = query("""[[:d = at(document.id, "Uyr9_wEAAKYARDMV")]]""").results.head
"support media" in {
doc getLink "test-link.related" must beSome.like {
case l: FileLink => l.filename must_== "baastad.pdf"
}
}
}
"Link" should {
lazy val document = Fixtures.document
document.getLink("store.link") must beSome.like {
case d: DocumentLink =>
case d: DocumentLink =>
d.fragments.get("timestamp.text") must beSome.like {
case s: StructuredText =>
s.asHtml(resolver) must_== "<p>This is text</p>"
Expand Down Expand Up @@ -310,19 +300,6 @@ class FragmentSpec extends Specification {
}
}

"Image" should {
val api = await(Api.get("https://test-public.prismic.io/api"))
def query(q: String) = await(api.forms("everything").ref(api.master).query(q).submit())
val doc = query("""[[:d = at(document.id, "Uyr9sgEAAGVHNoFZ")]]""").results.head
val img = doc.getImage("article.illustration", "icon")
val url = "https://prismic-io.s3.amazonaws.com/test-public/9f5f4e8a5d95c7259108e9cfdde953b5e60dcbb6.jpg"
"find first" in {
img must beSome.like {
case v: Fragment.Image.View => v.asHtml must_== s"""<img alt="some alt text" src="$url" width="100" height="100" />"""
}
}
}

"Image as link" should {
val json = JsonParser(
"""
Expand Down Expand Up @@ -351,4 +328,30 @@ class FragmentSpec extends Specification {
"<p class=\"block-img\"><a href=\"http://sentione.com\"><img alt=\"\" src=\"http://cdn.sentione.com/season-logo/logo.png\" width=\"180\" height=\"82\" /></a></p>"
}
}

"WebLink" should {

"deserialize to weblink without target" in {
val json = JsonParser(
"""
|{
| "url": "https://google.fr"
|}
""".stripMargin)

json.convertTo[WebLink].asHtml() mustEqual """<a href="https://google.fr">https://google.fr</a>"""
}

"deserialize to weblink with target blank" in {
val json = JsonParser(
"""
|{
| "url": "https://google.fr",
| "target": "_blank"
|}
""".stripMargin)

json.convertTo[WebLink].asHtml() mustEqual """<a href="https://google.fr" target="_blank" rel="noopener">https://google.fr</a>"""
}
}
}
6 changes: 3 additions & 3 deletions src/test/scala/PaginationSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class PaginationSpec extends Specification {
res.resultsPerPage must_== 20
res.resultsSize must_== 20
res.totalPages must_== 2
res.nextPage must_== Some("https://micro.prismic.io/api/v1/documents/search?ref=WH8MzyoAAGoSGJwT&page=2&pageSize=20")
res.nextPage must_== Some("https://micro.cdn.prismic.io/api/v1/documents/search?ref=WH8MzyoAAGoSGJwT&page=2&pageSize=20")
res.prevPage must_== None
}
"second page" in {
Expand All @@ -40,7 +40,7 @@ class PaginationSpec extends Specification {
res.resultsSize must_== 4
res.totalPages must_== 2
res.nextPage must_== None
res.prevPage must_== Some(s"https://micro.prismic.io/api/v1/documents/search?ref=WH8MzyoAAGoSGJwT&page=1&pageSize=20")
res.prevPage must_== Some(s"https://micro.cdn.prismic.io/api/v1/documents/search?ref=WH8MzyoAAGoSGJwT&page=1&pageSize=20")
}
"setting page size" in {
val res = query(1, 7)
Expand All @@ -49,7 +49,7 @@ class PaginationSpec extends Specification {
res.resultsPerPage must_== 7
res.resultsSize must_== 7
res.totalPages must_== 4
res.nextPage must_== Some(s"https://micro.prismic.io/api/v1/documents/search?ref=WH8MzyoAAGoSGJwT&page=2&pageSize=7")
res.nextPage must_== Some(s"https://micro.cdn.prismic.io/api/v1/documents/search?ref=WH8MzyoAAGoSGJwT&page=2&pageSize=7")
res.prevPage must_== None
}
}
Expand Down

0 comments on commit b2cc720

Please sign in to comment.