Skip to content

Commit

Permalink
Merge pull request #157 from armanbilge/pr/i138
Browse files Browse the repository at this point in the history
Cleanup `Codec`
  • Loading branch information
armanbilge authored Jan 23, 2023
2 parents 873ede1 + 01beaba commit c813d6e
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 102 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
* limitations under the License.
*/

package calico.html.codecs
package calico.html

import scala.scalajs.js

/**
* This trait represents a way to encode and decode HTML attribute or DOM property values.
Expand All @@ -27,7 +29,7 @@ package calico.html.codecs
* Scala DOM Types hides all this mess from you using codecs. All those pseudo-boolean
* attributes would be simply `Attr[Boolean](name, codec)` in your code.
*/
trait Codec[ScalaType, DomType] {
private sealed abstract class Codec[ScalaType, DomType]:

/**
* Convert the result of a `dom.Node.getAttribute` call to appropriate Scala type.
Expand All @@ -48,10 +50,15 @@ trait Codec[ScalaType, DomType] {
* under the hood.
*/
def encode(scalaValue: ScalaType): DomType
}

object Codec {
private[calico] val whitespaceSeparatedStringsCodec: Codec[List[String], String] = new:
private object Codec:

inline def identity[A]: Codec[A, A] = identityInstance.asInstanceOf[Codec[A, A]]
private val identityInstance: Codec[Any, Any] = new:
def decode(domValue: Any): Any = domValue
def encode(scalaValue: Any): Any = scalaValue

val whitespaceSeparatedStrings: Codec[List[String], String] = new:
def decode(domValue: String) = domValue.split(" ").toList

def encode(scalaValue: List[String]) =
Expand All @@ -64,48 +71,26 @@ object Codec {
tail = tail.tail
acc

object BooleanAsAttrPresenceCodec extends Codec[Boolean, String] {
override def decode(domValue: String): Boolean = domValue != null
override def encode(scalaValue: Boolean): String = if scalaValue then "" else null
}

object BooleanAsTrueFalseStringCodec extends Codec[Boolean, String] {
override def decode(domValue: String): Boolean = domValue == "true"
override def encode(scalaValue: Boolean): String = if scalaValue then "true" else "false"
}

object BooleanAsYesNoStringCodec extends Codec[Boolean, String] {
override def decode(domValue: String): Boolean = domValue == "yes"
override def encode(scalaValue: Boolean): String = if scalaValue then "yes" else "no"
}

object BooleanAsOnOffStringCodec extends Codec[Boolean, String] {
override def decode(domValue: String): Boolean = domValue == "on"
override def encode(scalaValue: Boolean): String = if scalaValue then "on" else "off"
}
val booleanAsAttrPresence: Codec[Boolean, String] = new:
def decode(domValue: String): Boolean = domValue ne null
def encode(scalaValue: Boolean): String = if scalaValue then "" else null

object IterableAsSpaceSeparatedStringCodec extends Codec[Iterable[String], String] { // use for e.g. className
override def decode(domValue: String): Iterable[String] =
if domValue == "" then Nil else domValue.split(' ')
override def encode(scalaValue: Iterable[String]): String = scalaValue.mkString(" ")
}
val booleanAsTrueFalseString: Codec[Boolean, String] = new:
def decode(domValue: String): Boolean = domValue == "true"
def encode(scalaValue: Boolean): String = if scalaValue then "true" else "false"

object IterableAsCommaSeparatedStringCodec extends Codec[Iterable[String], String] { // use for lists of IDs
override def decode(domValue: String): Iterable[String] =
if domValue == "" then Nil else domValue.split(',')
override def encode(scalaValue: Iterable[String]): String = scalaValue.mkString(",")
}
val booleanAsYesNoString: Codec[Boolean, String] = new:
def decode(domValue: String): Boolean = domValue == "yes"
def encode(scalaValue: Boolean): String = if scalaValue then "yes" else "no"

object DoubleAsStringCodec extends Codec[Double, String] {
override def decode(domValue: String): Double =
domValue.toDouble // @TODO this can throw exception. How do we handle this?
override def encode(scalaValue: Double): String = scalaValue.toString
}
val booleanAsOnOffString: Codec[Boolean, String] = new:
def decode(domValue: String): Boolean = domValue == "on"
def encode(scalaValue: Boolean): String = if scalaValue then "on" else "off"

object IntAsStringCodec extends Codec[Int, String] {
override def decode(domValue: String): Int =
domValue.toInt // @TODO this can throw exception. How do we handle this?
override def encode(scalaValue: Int): String = scalaValue.toString
}
inline def doubleAsString: Codec[Double, String] = new:
def decode(domValue: String): Double = domValue.toDouble
def encode(scalaValue: Double): String = scalaValue.toString

}
inline def intAsString: Codec[Int, String] = new:
def decode(domValue: String): Int = domValue.toInt
def encode(scalaValue: Int): String = scalaValue.toString
8 changes: 3 additions & 5 deletions calico/src/main/scala/calico/html/Html.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
package calico
package html

import calico.html.codecs.AsIsCodec
import calico.html.codecs.Codec
import cats.effect.IO
import cats.effect.kernel.Async
import cats.effect.kernel.Resource
Expand Down Expand Up @@ -47,15 +45,15 @@ sealed trait Html[F[_]](using F: Async[F])

def cls: ClassProp[F] = ClassProp[F]

def role: HtmlAttr[F, List[String]] = HtmlAttr("role", Codec.whitespaceSeparatedStringsCodec)
def role: HtmlAttr[F, List[String]] = HtmlAttr("role", Codec.whitespaceSeparatedStrings)

def dataAttr(suffix: String): HtmlAttr[F, String] =
HtmlAttr("data-" + suffix, AsIsCodec.StringAsIsCodec)
HtmlAttr("data-" + suffix, Codec.identity)

def children: Children[F] = Children[F]

def children[K](f: K => Resource[F, fs2.dom.Node[F]]): KeyedChildren[F, K] =
KeyedChildren[F, K](f)

def styleAttr: HtmlAttr[F, String] =
HtmlAttr("style", AsIsCodec.StringAsIsCodec)
HtmlAttr("style", Codec.identity)
1 change: 0 additions & 1 deletion calico/src/main/scala/calico/html/HtmlAttr.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

package calico.html

import calico.html.codecs.Codec
import cats.effect.kernel.Async
import cats.effect.kernel.Resource
import fs2.concurrent.Signal
Expand Down
3 changes: 1 addition & 2 deletions calico/src/main/scala/calico/html/Prop.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
package calico
package html

import calico.html.codecs.Codec
import calico.syntax.*
import cats.effect.kernel.Async
import cats.effect.kernel.Resource
Expand Down Expand Up @@ -110,7 +109,7 @@ private trait EventPropModifiers[F[_]](using F: Async[F]):
final class ClassProp[F[_]] private[calico]
extends Prop[F, List[String], String](
"className",
Codec.whitespaceSeparatedStringsCodec
Codec.whitespaceSeparatedStrings
):
import ClassProp.*

Expand Down
41 changes: 0 additions & 41 deletions calico/src/main/scala/calico/html/codecs/AsIsCodec.scala

This file was deleted.

16 changes: 8 additions & 8 deletions project/src/main/scala/calico/html/codegen/CalicoGenerator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,12 @@ private[codegen] class CalicoGenerator(srcManaged: File)

override def tagKeysPackagePath: String = basePackagePath

override val codecsImport: String =
List(
s"import ${basePackagePath}.codecs.Codec.*",
s"import ${basePackagePath}.codecs.AsIsCodec.*",
s"import ${basePackagePath}.codecs.*"
).mkString("\n")
override val codecsImport: String = ""

private def transformCodecName(codec: String) = codec match {
case c if c.endsWith("AsIs") => s"Codec.identity[${c.dropRight(4)}]"
case c => s"Codec.${c(0).toLower}${c.substring(1)}"
}

override def generateTagsTrait(
tagType: TagType,
Expand Down Expand Up @@ -176,7 +176,7 @@ private[codegen] class CalicoGenerator(srcManaged: File)
baseImplDefComments = baseImplDefComments,
baseImplName = baseImplName,
baseImplDef = baseImplDef,
transformCodecName = _ + "Codec",
transformCodecName = transformCodecName,
namespaceImpl = namespaceImpl,
outputImplDefs = true,
format = format
Expand Down Expand Up @@ -224,7 +224,7 @@ private[codegen] class CalicoGenerator(srcManaged: File)
baseImplDefComments = baseImplDefComments,
baseImplName = baseImplName,
baseImplDef = baseImplDef,
transformCodecName = _ + "Codec",
transformCodecName = transformCodecName,
outputImplDefs = true,
format = format
).printTrait().getOutput()
Expand Down

0 comments on commit c813d6e

Please sign in to comment.