Skip to content

Commit

Permalink
add document fragment
Browse files Browse the repository at this point in the history
  • Loading branch information
crhntr committed Mar 20, 2024
1 parent 557990a commit f4c1d3e
Show file tree
Hide file tree
Showing 6 changed files with 538 additions and 28 deletions.
19 changes: 19 additions & 0 deletions domtest/document.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"strings"

"golang.org/x/net/html"
"golang.org/x/net/html/atom"

"github.com/crhntr/dom"
"github.com/crhntr/dom/spec"
Expand Down Expand Up @@ -52,3 +53,21 @@ func Reader(t T, r io.Reader) spec.Document {
}
return dom.NewNode(node).(spec.Document)
}

func DocumentFragment(t T, r io.Reader, parent atom.Atom) []spec.Element {
t.Helper()
nodes, err := html.ParseFragment(r, &html.Node{
Type: html.ElementNode,
Data: parent.String(),
DataAtom: parent,
})
if err != nil {
t.Error(err)
return nil
}
var result []spec.Element
for _, node := range nodes {
result = append(result, dom.NewNode(node).(spec.Element))
}
return result
}
14 changes: 7 additions & 7 deletions element.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,13 @@ func (e *Element) Length() int {

// ParentNode

func (e *Element) Children() spec.ElementCollection { return children(e.node) }
func (e *Element) FirstElementChild() spec.Element { return firstElementChild(e.node) }
func (e *Element) LastElementChild() spec.Element { return lastElementChild(e.node) }
func (e *Element) ChildElementCount() int { return childElementCount(e.node) }
func (e *Element) Prepend(nodes ...spec.ChildNode) { prependNodes(e.node, nodes) }
func (e *Element) Append(nodes ...spec.ChildNode) { appendNodes(e.node, nodes) }
func (e *Element) ReplaceChildren(nodes ...spec.ChildNode) { replaceChildren(e.node, nodes) }
func (e *Element) Children() spec.ElementCollection { return children(e.node) }
func (e *Element) FirstElementChild() spec.Element { return firstElementChild(e.node) }
func (e *Element) LastElementChild() spec.Element { return lastElementChild(e.node) }
func (e *Element) ChildElementCount() int { return childElementCount(e.node) }
func (e *Element) Prepend(nodes ...spec.Node) { prependNodes(e.node, nodes) }
func (e *Element) Append(nodes ...spec.Node) { appendNodes(e.node, nodes...) }
func (e *Element) ReplaceChildren(nodes ...spec.Node) { replaceChildren(e.node, nodes) }
func (e *Element) GetElementsByTagName(name string) spec.ElementCollection {
return getElementsByTagName(e.node, name)
}
Expand Down
127 changes: 127 additions & 0 deletions fragment.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
package dom

import (
"bytes"
"slices"

"golang.org/x/net/html"

"github.com/crhntr/dom/spec"
)

type DocumentFragment struct {
nodes []*html.Node
}

func NewDocumentFragment(nodes []*html.Node) *DocumentFragment {
return &DocumentFragment{nodes: nodes}
}

func (d *DocumentFragment) NodeType() spec.NodeType { return spec.NodeTypeDocumentFragment }

func (d *DocumentFragment) CloneNode(deep bool) spec.Node {
if !deep {
return &DocumentFragment{nodes: d.nodes}
}
df := &DocumentFragment{nodes: make([]*html.Node, len(d.nodes))}
for _, e := range d.nodes {
df.nodes = append(df.nodes, cloneNode(e, deep))
}
return df
}

func (d *DocumentFragment) IsSameNode(other spec.Node) bool {
o, ok := other.(*DocumentFragment)
if !ok {
return false
}
return d == o
}

func (d *DocumentFragment) TextContent() string {
var buf bytes.Buffer
for _, n := range d.nodes {
recursiveTextContent(&buf, n)
}
return buf.String()
}

func (d *DocumentFragment) Children() spec.ElementCollection {
elementChildren := make(elementList, 0, len(d.nodes))
for _, n := range d.nodes {
if n != nil && n.Type == html.ElementNode {
elementChildren = append(elementChildren, n)
}
}
return slices.Clip(elementChildren)
}

func (d *DocumentFragment) FirstElementChild() spec.Element {
for _, n := range d.nodes {
if n.Type == html.ElementNode {
return &Element{node: n}
}
}
return nil
}

func (d *DocumentFragment) LastElementChild() spec.Element {
for i := range d.nodes {
n := d.nodes[len(d.nodes)-1-i]
if n.Type == html.ElementNode {
return &Element{node: n}
}
}
return nil
}

func (d *DocumentFragment) ChildElementCount() int {
count := 0
for _, n := range d.nodes {
if n.Type == html.ElementNode {
count++
}
}
return count
}

func (d *DocumentFragment) Append(nodes ...spec.ChildNode) {
d.nodes = slices.Grow(d.nodes, len(nodes))
for _, node := range nodes {
d.nodes = append(d.nodes, domNodeToHTMLNode(node))
}
}

func (d *DocumentFragment) Prepend(nodes ...spec.ChildNode) {
children := make([]*html.Node, 0, len(d.nodes)+len(nodes))
for _, node := range nodes {
children = append(children, domNodeToHTMLNode(node))
}
d.nodes = append(children, d.nodes...)
}

func (d *DocumentFragment) ReplaceChildren(nodes ...spec.ChildNode) {
list := make([]*html.Node, 0, len(nodes))
for _, node := range nodes {
list = append(list, domNodeToHTMLNode(node))
}
d.nodes = list
}

func (d *DocumentFragment) QuerySelector(query string) spec.Element {
for _, n := range d.nodes {
el := querySelector(n, query)
if el != nil {
return el
}
}
return nil
}

func (d *DocumentFragment) QuerySelectorAll(query string) spec.NodeList[spec.Element] {
var list nodeListHTMLElements
for _, n := range d.nodes {
list = append(list, querySelectorAll(n, query)...)
}
return slices.Clip(list)
}
Loading

0 comments on commit f4c1d3e

Please sign in to comment.