<commit_before>import org.scalajs.dom
import rescala._

import scala.language.implicitConversions
import scalatags.JsDom.all._

package object rescalatags {

  implicit class SignalToScalatags(signal: Signal[Tag]) {
    /**
      * converts a Signal of a scalatags Tag to a scalatags Frag which automatically reflects changes to the signal in the dom
      */
    def asFragment: Frag = {
      new Frag {
        val rendered: Signal[dom.Node] = signal
          .map(_.render)
          .recover(t => span(t.toString).render)
          .withDefault(() => "".render)

        rendered.change.observe { case (lastTag, newTag) =>
          if (lastTag.parentNode != null && !scalajs.js.isUndefined(lastTag.parentNode)) {
            lastTag.parentNode.replaceChild(newTag, lastTag)
          }
        }

        def applyTo(t: dom.Element) = t.appendChild(rendered.now)
        def render: dom.Node = rendered.now
      }
    }
  }


  implicit def attrValue[T: AttrValue]: AttrValue[Signal[T]] = new AttrValue[Signal[T]] {
    def apply(t: dom.Element, a: Attr, signal: Signal[T]): Unit = {
      signal.observe { value => implicitly[AttrValue[T]].apply(t, a, value) }
    }
  }

  implicit def styleValue[T: StyleValue]: StyleValue[Signal[T]] = new StyleValue[Signal[T]] {
    def apply(t: dom.Element, s: Style, signal: Signal[T]): Unit = {
      signal.observe { value => implicitly[StyleValue[T]].apply(t, s, value) }
    }
  }
}<commit_msg>improve rescalatags type inference (or something)<commit_after>import org.scalajs.dom
import rescala._

import scala.language.{higherKinds, implicitConversions}
import scalatags.JsDom.all._

package object rescalatags {

  implicit class SignalToScalatags(signal: Signal[Tag]) {
    /**
      * converts a Signal of a scalatags Tag to a scalatags Frag which automatically reflects changes to the signal in the dom
      */
    def asFrag: Frag = {
      new Frag {
        val rendered: Signal[dom.Node] = signal
          .map(_.render)
          .recover(t => span(t.toString).render)
          .withDefault(() => "".render)

        rendered.change.observe { case (lastTag, newTag) =>
          if (lastTag.parentNode != null && !scalajs.js.isUndefined(lastTag.parentNode)) {
            lastTag.parentNode.replaceChild(newTag, lastTag)
          }
        }

        def applyTo(t: dom.Element) = t.appendChild(rendered.now)
        def render: dom.Node = rendered.now
      }
    }
  }


  implicit def attrValue[T: AttrValue, Sig[T2] <: Signal[T2]]: AttrValue[Sig[T]] = new AttrValue[Sig[T]] {
    def apply(t: dom.Element, a: Attr, signal: Sig[T]): Unit = {
      signal.observe { value => implicitly[AttrValue[T]].apply(t, a, value) }
    }
  }

  implicit def styleValue[T: StyleValue, Sig[T2] <: Signal[T2]]: StyleValue[Sig[T]] = new StyleValue[Sig[T]] {
    def apply(t: dom.Element, s: Style, signal: Sig[T]): Unit = {
      signal.observe { value => implicitly[StyleValue[T]].apply(t, s, value) }
    }
  }
}
{'fraction_non_alphanumeric': 0.13313110886417256, 'fraction_numerical': 0.0013481631277384564, 'mean_word_length': 2.9207397622192866, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3830828', 'n_tokens_mistral': 996, 'n_tokens_neox': 959, 'n_words': 226}