Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cross-compile support for JVM #46

Open
bbarker opened this issue Mar 27, 2017 · 2 comments
Open

Cross-compile support for JVM #46

bbarker opened this issue Mar 27, 2017 · 2 comments

Comments

@bbarker
Copy link
Contributor

bbarker commented Mar 27, 2017

As noted from @OlivierBlanvillain :

Everything is cross compiled/published, expect for the monadic-html project which actually mounts stuff to the DOM. This project is heavily base on the browser DOM APIs (org.scalajs.dom) to create actual things from scala.xml.Node, and then to mutate stuff as needed on Rx updates. To be able to run the exact same logic on the server side (ie cross compile monadic-html) you would need to reimplement something like https://github.com/tmpvar/jsdom on the JVM, then cross compile https://github.com/scala-js/scala-js-dom againts this JVM implementation.
It might be possible have another implementation (ie not cross compiled) of mhtml.mount for server side that instead of being smart about doing the minimum DOM update just recreates everything on any Rx change. The key missing part here would be be a scala.xml.Node => String function (it's non trivial because of event handlers).

@bbarker
Copy link
Contributor Author

bbarker commented Oct 2, 2017

I like the idea of separating mount from HTML emission, as it seems simpler initially and would be more flexible. For instance, many MVC applications might make use of the same views that exist in monadic-html, but have no need to mount. Additionally, monadic-html is really "monadic-xml" at its heart, so this could be used in other XML-oriented projects (though less commonly so I'm sure). Other uses would undoubtedly need their own versions of mount.

@OlivierBlanvillain
Copy link
Owner

I'm not sure it's worth factoring out, the entire mount logic is a simple tree traversal of scala.xml.Node. Here is what remains of the code after stripping out the DOM specific parts (~30 LOC):

def mount0(parent: DomNode, child: XmlNode): Cancelable =
  child match {
    case e @ Elem(_, label, metadata, scope, child @ _*) =>
      /* Create regular DOM node */
      Cancelable { () => ... }

    case e: EntityRef  =>
      /* Create text Node with the entity*/
      Cancelable.empty

    case Group(nodes)  =>
      val cancels = nodes.map(n => mountNode(parent, n))
      Cancelable(() => cancels.foreach(_.cancel))

    case a: Atom[_] => a.data match {
      case n: XmlNode  => mountNode(parent, n)
      case rx: Rx[_]   =>
        var c1 = Cancelable.empty
        val c2 = rx.impure.foreach { v =>
          /* Remove previous node from the DOM */
          c1.cancel
          c1 = mountNode(parent, new Atom(v))
        }
        Cancelable { () => c1.cancel; c2.cancel }
      case seq: Seq[_] => mountNode(parent, new Group(seq.map(new Atom(_))))
      case primitive   =>
        val content = primitive.toString
        if (!content.isEmpty)
          parent.mountHere(/* Create text Node with primitive */)
        Cancelable.empty
    }
  }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants