From a7a9c2dcedfc1070747a8c6377370d92b5f597c0 Mon Sep 17 00:00:00 2001 From: jvoisin Date: Fri, 5 Jun 2026 22:51:00 +0200 Subject: [PATCH] cleanup: extract cachedParse helper for parse-result reuse WrapHtml, WrapInnerHtml, and eachNodeHtml each open-coded the same lookup-or-parse-and-store sequence against a map[string][]*html.Node keyed by the context node's name. Extract that 4-line sequence into a tiny cachedParseHtmlWithContext(cache, htmlStr, context) helper; each call site becomes a linear, closure-free loop and the only duplicated bit (the cache lookup) lives in one place. --- manipulation.go | 59 ++++++++++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 30 deletions(-) diff --git a/manipulation.go b/manipulation.go index 0ca7da7..f2f49f0 100644 --- a/manipulation.go +++ b/manipulation.go @@ -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 } @@ -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 } @@ -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 { @@ -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 +}