lila/app/ui/scalatags.scala
2020-01-13 07:44:59 -06:00

166 lines
5.4 KiB
Scala

package lila.app
package ui
import ornicar.scalalib.Zero
import scalatags.Text.all._
import scalatags.text.Builder
import scalatags.Text.{ Aggregate, Cap }
import lila.api.Context
// collection of lila attrs
trait ScalatagsAttrs {
val dataAssetUrl = attr("data-asset-url")
val dataAssetVersion = attr("data-asset-version")
val dataDev = attr("data-dev")
val dataTheme = attr("data-theme")
val dataTag = attr("data-tag")
val dataIcon = attr("data-icon")
val dataHref = attr("data-href")
val dataCount = attr("data-count")
val dataEnableTime = attr("data-enable-time")
val datatime24h = attr("data-time_24h")
val dataColor = attr("data-color")
val dataFen = attr("data-fen")
val dataRel = attr("data-rel")
val novalidate = attr("novalidate").empty
val datetimeAttr = attr("datetime")
val dataBotAttr = attr("data-bot").empty
val deferAttr = attr("defer").empty
object frame {
val scrolling = attr("scrolling")
val allowfullscreen = attr("allowfullscreen").empty
}
}
// collection of lila snippets
trait ScalatagsSnippets extends Cap {
this: ScalatagsExtensions with ScalatagsAttrs =>
import scalatags.Text.all._
val nbsp = raw(" ")
val amp = raw("&")
def iconTag(icon: Char): Tag = iconTag(icon.toString)
def iconTag(icon: String): Tag = i(dataIcon := icon)
def iconTag(icon: Char, text: Frag): Tag = iconTag(icon.toString, text)
def iconTag(icon: String, text: Frag): Tag = i(dataIcon := icon, cls := "text")(text)
val styleTag = tag("style")(tpe := "text/css")
val ratingTag = tag("rating")
val countTag = tag("count")
val goodTag = tag("good")
val badTag = tag("bad")
val timeTag = tag("time")
def dataBot(title: lila.user.Title): Modifier =
if (title == lila.user.Title.BOT) dataBotAttr
else emptyModifier
def pagerNext(pager: lila.common.paginator.Paginator[_], url: Int => String): Option[Frag] =
pager.nextPage.map { np =>
div(cls := "pager none")(a(rel := "next", href := url(np))("Next"))
}
def pagerNextTable(pager: lila.common.paginator.Paginator[_], url: Int => String): Option[Frag] =
pager.nextPage.map { np =>
tr(th(cls := "pager none")(a(rel := "next", href := url(np))("Next")))
}
val utcLink =
a(href := "https://time.is/UTC", target := "_blank", title := "Coordinated Universal Time")("UTC")
}
// basic imports from scalatags
trait ScalatagsBundle
extends Cap
with Attrs
with scalatags.text.Tags
// with DataConverters
with Aggregate
// short prefix
trait ScalatagsPrefix {
object st extends Cap with Attrs with scalatags.text.Tags {
val group = tag("group")
val headTitle = tag("title")
val nav = tag("nav")
val section = tag("section")
val article = tag("article")
val aside = tag("aside")
val rating = tag("rating")
val frameborder = attr("frameborder")
}
}
// what to import in a pure scalatags template
trait ScalatagsTemplate
extends Styles
with ScalatagsBundle
with ScalatagsAttrs
with ScalatagsExtensions
with ScalatagsSnippets
with ScalatagsPrefix {
val trans = lila.i18n.I18nKeys
def main = scalatags.Text.tags2.main
/* Convert play URLs to scalatags attributes with toString */
implicit val playCallAttr = genericAttr[play.api.mvc.Call]
}
object ScalatagsTemplate extends ScalatagsTemplate
// generic extensions
trait ScalatagsExtensions {
implicit def stringValueFrag(sv: StringValue): Frag = new StringFrag(sv.value)
implicit val stringValueAttr = new AttrValue[StringValue] {
def apply(t: scalatags.text.Builder, a: Attr, v: StringValue): Unit =
t.setAttr(a.name, scalatags.text.Builder.GenericAttrValueSource(v.value))
}
implicit val charAttr = genericAttr[Char]
implicit val optionStringAttr = new AttrValue[Option[String]] {
def apply(t: scalatags.text.Builder, a: Attr, v: Option[String]): Unit = {
v foreach { s =>
t.setAttr(a.name, scalatags.text.Builder.GenericAttrValueSource(s))
}
}
}
/* for class maps such as List("foo" -> true, "active" -> isActive) */
implicit val classesAttr = new AttrValue[List[(String, Boolean)]] {
def apply(t: scalatags.text.Builder, a: Attr, m: List[(String, Boolean)]): Unit = {
val cls = m collect { case (s, true) => s } mkString " "
if (cls.nonEmpty) t.setAttr(a.name, scalatags.text.Builder.GenericAttrValueSource(cls))
}
}
val emptyFrag: Frag = new RawFrag("")
implicit val LilaFragZero: Zero[Frag] = Zero.instance(emptyFrag)
val emptyModifier: Modifier = new Modifier {
def applyTo(t: Builder) = {}
}
def ariaTitle(v: String) = new Modifier {
def applyTo(t: Builder) = {
val value = Builder.GenericAttrValueSource(v)
t.setAttr("title", value)
t.setAttr("aria-label", value)
}
}
def titleOrText(blind: Boolean, v: String): Modifier = new Modifier {
def applyTo(t: Builder) = {
if (blind) t.addChild(v)
else t.setAttr("title", Builder.GenericAttrValueSource(v))
}
}
def titleOrText(v: String)(implicit ctx: Context): Modifier = titleOrText(ctx.blind, v)
}