Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 29 additions & 30 deletions manipulation.go
Original file line number Diff line number Diff line change
Expand Up @@ -382,20 +382,14 @@ func (s *Selection) WrapSelection(sel *Selection) *Selection {
//
// It returns the original set of elements.
func (s *Selection) WrapHtml(htmlStr string) *Selection {
nodesMap := make(map[string][]*html.Node)
for _, context := range s.Nodes {
var parent *html.Node
if context.Parent != nil {
parent = context.Parent
} else {
cache := make(map[string][]*html.Node)
for _, n := range s.Nodes {
parent := n.Parent
if parent == nil {
parent = &html.Node{Type: html.ElementNode}
}
nodes, found := nodesMap[nodeName(parent)]
if !found {
nodes = parseHtmlWithContext(htmlStr, parent)
nodesMap[nodeName(parent)] = nodes
}
newSingleSelection(context, s.document).wrapAllNodes(cloneNodes(nodes)...)
nodes := cachedParseHtmlWithContext(cache, htmlStr, parent)
newSingleSelection(n, s.document).wrapAllNodes(cloneNodes(nodes)...)
}
return s
}
Expand Down Expand Up @@ -530,14 +524,10 @@ func (s *Selection) WrapInnerSelection(sel *Selection) *Selection {
//
// It returns the original set of elements.
func (s *Selection) WrapInnerHtml(htmlStr string) *Selection {
nodesMap := make(map[string][]*html.Node)
for _, context := range s.Nodes {
nodes, found := nodesMap[nodeName(context)]
if !found {
nodes = parseHtmlWithContext(htmlStr, context)
nodesMap[nodeName(context)] = nodes
}
newSingleSelection(context, s.document).wrapInnerNodes(cloneNodes(nodes)...)
cache := make(map[string][]*html.Node)
for _, n := range s.Nodes {
nodes := cachedParseHtmlWithContext(cache, htmlStr, n)
newSingleSelection(n, s.document).wrapInnerNodes(cloneNodes(nodes)...)
}
return s
}
Expand Down Expand Up @@ -662,10 +652,9 @@ func (s *Selection) manipulateNodes(ns []*html.Node, reverse bool,
// isParent can be used to indicate that the elements of the selection should be treated as the parent for the parsed html.
// A cache is used to avoid parsing the html multiple times should the elements of the selection result in the same context.
func (s *Selection) eachNodeHtml(htmlStr string, isParent bool, mergeFn func(n *html.Node, nodes []*html.Node)) *Selection {
// cache to avoid parsing the html for the same context multiple times
nodeCache := make(map[string][]*html.Node)
var context *html.Node
cache := make(map[string][]*html.Node)
for _, n := range s.Nodes {
var context *html.Node
if isParent {
context = n.Parent
} else {
Expand All @@ -674,14 +663,24 @@ func (s *Selection) eachNodeHtml(htmlStr string, isParent bool, mergeFn func(n *
}
context = n
}
if context != nil {
nodes, found := nodeCache[nodeName(context)]
if !found {
nodes = parseHtmlWithContext(htmlStr, context)
nodeCache[nodeName(context)] = nodes
}
mergeFn(n, cloneNodes(nodes))
if context == nil {
continue
}
nodes := cachedParseHtmlWithContext(cache, htmlStr, context)
mergeFn(n, cloneNodes(nodes))
}
return s
}

// cachedParseHtmlWithContext returns parseHtmlWithContext(htmlStr, context), reusing a prior
// result when context's nodeName has already been seen. Callers pass their own
// cache map so the cache lifetime matches the caller's loop scope.
func cachedParseHtmlWithContext(cache map[string][]*html.Node, htmlStr string, context *html.Node) []*html.Node {
key := nodeName(context)
if nodes, ok := cache[key]; ok {
return nodes
}
nodes := parseHtmlWithContext(htmlStr, context)
cache[key] = nodes
return nodes
}
Loading