Skip to content

Instantly share code, notes, and snippets.

@nafg
Last active Nov 20, 2022
Embed
What would you like to do?
HTML to scalajs-react VDOM
#!/usr/bin/env amm
import scala.xml.{Elem, Node, Text, XML}
def quoteString(s: String) =
'"' +
s.replace("\n", "\\n").replace("\"", "\\\"") +
'"'
def indentSpaces(n: Int) = " " * (n * 2)
def toVDOM(node: Node, indentLevel: Int = 0): Option[String] =
node match {
case elem: Elem =>
val attrArgs =
elem.attributes.asAttrMap.map {
case (key, value) =>
val unsupported = Set("label", "selectedindex", "tabindex", "onclick", "onchange", "style", "onkeyup")
val attr =
key.toLowerCase match {
case s if s.contains("-") || unsupported.contains(s) => "VdomAttr(" + quoteString(s) + ")"
case "class" => "^.cls"
case "for" => "^.htmlFor"
case "type" => "^.tpe"
case _ => "^." + key
}
attr + " := " + quoteString(value)
}.toSeq
val childArgs = elem.child.map(toVDOM(_, indentLevel + 1))
val res =
"<." + elem.label +
"(\n" + indentSpaces(indentLevel + 1) +
(attrArgs ++ childArgs.flatten).mkString(",\n" + indentSpaces(indentLevel + 1)) +
"\n" + indentSpaces(indentLevel) + ")"
Some(res)
case text: Text =>
if (text.data.trim.isEmpty) None
else Some(quoteString(text.data.trim))
}
@main
def main(path: String) =
try
println(toVDOM(XML.loadFile(path)).get)
catch {
case e => e.printStackTrace()
}
@Angel-O
Copy link

Angel-O commented Jun 27, 2020

Hero!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment