package wasm import ( "strconv" "syscall/js" ) type Node struct { tag string id string attrs []*Attribute children []*Node jsElement js.Value innerText string } type Attribute struct { Name string Value string } func document(document js.Value) *Node { return &Node{jsElement: document} } func (n *Node) createElement(document js.Value) { var el = document.Call("createElement", n.tag) el.Call("setAttribute", "id", n.id) for _, attr := range n.attrs { el.Call("setAttribute", attr.Name, attr.Value) } n.jsElement = el } func (n *Node) AppendChild(child *Node) { if child.tag != "" { n.children = append(n.children, child) n.jsElement.Call("appendChild", child.jsElement) } else { n.jsElement.Set("innerText", child.innerText) } } func (n *Node) GetChildren() []*Node { return n.children } func (n *Node) ReplaceChildren(newChildren []*Node) { n.children = newChildren for { child := n.jsElement.Get("firstChild") if child.IsNull() { break } n.jsElement.Call("removeChild", child) } for _, child := range n.children { n.AppendChild(child) } } type NodeFactory struct { document *Node idCounter int64 root *Node } func NewNodeFactory(jsDocument js.Value) *NodeFactory { var f = &NodeFactory{document: document(jsDocument), idCounter: 0} f.setRoot() return f } func (f *NodeFactory) setRoot() { var rootElement = f.document.jsElement.Get("firstElementChild") if rootElement.IsNull() { f.root = f.NewNode("html") } else { f.root = &Node{tag: "html", jsElement: rootElement} f.document.AppendChild(f.root) } } func (f *NodeFactory) Root() *Node { return f.root } func (f *NodeFactory) NewBody() *Node { var body = f.NewNode("body") f.root.AppendChild(body) return body } func (f *NodeFactory) NewNode(tag string, attributes ...*Attribute) *Node { var id = f.idCounter f.idCounter++ var n = &Node{tag: tag, id: strconv.FormatInt(id, 10), attrs: attributes} n.createElement(f.document.jsElement) return n } func (f *NodeFactory) NewTextNode(text string) *Node { return &Node{innerText: text} }