Compare commits

...
Author SHA1 Message Date
Martin Angers b3706f8903 update readme to prepare for new release 2020-10-08 09:16:43 -04:00
Martin AngersandGitHub 7ebd145bd7 Merge pull request #348 from thiemok/context
Send context to parseHtml. Closes #178 .
2020-10-08 09:10:18 -04:00
Martin Angers 4a687a672f add test cases to check html insertion order 2020-10-08 09:02:13 -04:00
thiemok 94c2530dd8 fix(manipulation): fix node insertion and caching issues
Node caching was still using the node type instead of the node name in a
few places. Updated those to also use the node name as the cache key.

ReplaceWithHtml and PrependHtml inserted parsed nodes in the wrong
order. Kept track of the correct parent to fix this.

Use correct parent flag for SetHtml
2020-10-07 20:04:45 +02:00
3 changed files with 29 additions and 21 deletions
+4 -1
View File
@@ -37,6 +37,7 @@ Please note that because of the net/html dependency, goquery requires Go1.1+.
**Note that goquery's API is now stable, and will not break.**
* **2020-10-08 (v1.6.0)** : Parse html in context of the container node for all functions that deal with html strings (`AfterHtml`, `AppendHtml`, etc.). Thanks to [@thiemok][thiemok] and [@davidjwilkins][djw] for their work on this.
* **2020-02-04 (v1.5.1)** : Update module dependencies.
* **2018-11-15 (v1.5.0)** : Go module support (thanks @Zaba505).
* **2018-06-07 (v1.4.1)** : Add `NewDocumentFromReader` examples.
@@ -143,7 +144,7 @@ func main() {
- [gnulnx/goperf](https://github.com/gnulnx/goperf), a website performance test tool that also fetches static assets.
- [MontFerret/ferret](https://github.com/MontFerret/ferret), declarative web scraping.
- [tacusci/berrycms](https://github.com/tacusci/berrycms), a modern simple to use CMS with easy to write plugins
- [Dataflow kit](https://github.com/slotix/dataflowkit), Web Scraping framework for Gophers.
- [Dataflow kit](https://github.com/slotix/dataflowkit), Web Scraping framework for Gophers.
- [Geziyor](https://github.com/geziyor/geziyor), a fast web crawling & scraping framework for Go. Supports JS rendering.
- [Pagser](https://github.com/foolin/pagser), a simple, easy, extensible, configurable HTML parser to struct based on goquery and struct tags.
@@ -182,3 +183,5 @@ The [BSD 3-Clause license][bsd], the same as the [Go language][golic]. Cascadia'
[thatguystone]: https://github.com/thatguystone
[piotr]: https://github.com/piotrkowalczuk
[goq]: https://github.com/andrewstuart/goq
[thiemok]: https://github.com/thiemok
[djw]: https://github.com/davidjwilkins
+13 -10
View File
@@ -41,9 +41,10 @@ func (s *Selection) AfterSelection(sel *Selection) *Selection {
// This follows the same rules as Selection.Append.
func (s *Selection) AfterHtml(htmlStr string) *Selection {
return s.eachNodeHtml(htmlStr, true, func(node *html.Node, nodes []*html.Node) {
nextSibling := node.NextSibling
for _, n := range nodes {
if node.Parent != nil {
node.Parent.InsertBefore(n, node.NextSibling)
node.Parent.InsertBefore(n, nextSibling)
}
}
})
@@ -202,8 +203,9 @@ func (s *Selection) PrependSelection(sel *Selection) *Selection {
// PrependHtml parses the html and prepends it to the set of matched elements.
func (s *Selection) PrependHtml(htmlStr string) *Selection {
return s.eachNodeHtml(htmlStr, false, func(node *html.Node, nodes []*html.Node) {
firstChild := node.FirstChild
for _, n := range nodes {
node.InsertBefore(n, node.FirstChild)
node.InsertBefore(n, firstChild)
}
})
}
@@ -283,9 +285,10 @@ func (s *Selection) ReplaceWithSelection(sel *Selection) *Selection {
// This follows the same rules as Selection.Append.
func (s *Selection) ReplaceWithHtml(htmlStr string) *Selection {
s.eachNodeHtml(htmlStr, true, func(node *html.Node, nodes []*html.Node) {
nextSibling := node.NextSibling
for _, n := range nodes {
if node.Parent != nil {
node.Parent.InsertBefore(n, node.NextSibling)
node.Parent.InsertBefore(n, nextSibling)
}
}
})
@@ -310,7 +313,7 @@ func (s *Selection) SetHtml(htmlStr string) *Selection {
context.RemoveChild(c)
}
}
return s.eachNodeHtml(htmlStr, true, func(node *html.Node, nodes []*html.Node) {
return s.eachNodeHtml(htmlStr, false, func(node *html.Node, nodes []*html.Node) {
for _, n := range nodes {
node.AppendChild(n)
}
@@ -371,7 +374,7 @@ func (s *Selection) WrapSelection(sel *Selection) *Selection {
//
// It returns the original set of elements.
func (s *Selection) WrapHtml(htmlStr string) *Selection {
nodesMap := make(map[html.NodeType][]*html.Node)
nodesMap := make(map[string][]*html.Node)
for _, context := range s.Nodes {
var parent *html.Node
if context.Parent != nil {
@@ -379,10 +382,10 @@ func (s *Selection) WrapHtml(htmlStr string) *Selection {
} else {
parent = &html.Node{Type: html.ElementNode}
}
nodes, found := nodesMap[parent.Type]
nodes, found := nodesMap[nodeName(parent)]
if !found {
nodes = parseHtmlWithContext(htmlStr, parent)
nodesMap[parent.Type] = nodes
nodesMap[nodeName(parent)] = nodes
}
newSingleSelection(context, s.document).wrapAllNodes(cloneNodes(nodes)...)
}
@@ -519,12 +522,12 @@ func (s *Selection) WrapInnerSelection(sel *Selection) *Selection {
//
// It returns the original set of elements.
func (s *Selection) WrapInnerHtml(htmlStr string) *Selection {
nodesMap := make(map[html.NodeType][]*html.Node)
nodesMap := make(map[string][]*html.Node)
for _, context := range s.Nodes {
nodes, found := nodesMap[context.Type]
nodes, found := nodesMap[nodeName(context)]
if !found {
nodes = parseHtmlWithContext(htmlStr, context)
nodesMap[context.Type] = nodes
nodesMap[nodeName(context)] = nodes
}
newSingleSelection(context, s.document).wrapInnerNodes(cloneNodes(nodes)...)
}
+12 -10
View File
@@ -70,8 +70,9 @@ func TestAfterHtmlContext(t *testing.T) {
</table>
</body>
</html>`)
doc.Find("table tr td").AfterHtml("<td>Test</td>")
assertLength(t, doc.Find("table tr td").Nodes, 4)
doc.Find("table tr td").AfterHtml("<td class='c1'>Test</td><td class='c2'>Again</td>")
assertLength(t, doc.Find("table tr td").Nodes, 6)
assertClass(t, doc.Find("table tr td").Last(), "c2")
printSel(t, doc.Selection)
}
@@ -146,10 +147,10 @@ func TestAppendHtmlContext(t *testing.T) {
</table>
</body>
</html>`)
doc.Find("table tr").AppendHtml("<td class='new-node'>new node</td>")
doc.Find("table tr").AppendHtml("<td class='c1'>new1</td><td class='c2'>new2</td>")
assertLength(t, doc.Find("table td").Nodes, 4)
assertClass(t, doc.Find("table td").Last(), "new-node")
assertLength(t, doc.Find("table td").Nodes, 6)
assertClass(t, doc.Find("table td").Last(), "c2")
printSel(t, doc.Selection)
}
@@ -205,10 +206,10 @@ func TestBeforeHtmlContext(t *testing.T) {
</table>
</body>
</html>`)
doc.Find("table tr td:first-child").BeforeHtml("<td class='new-node'>new node</td>")
doc.Find("table tr td:first-child").BeforeHtml("<td class='c1'>new1</td><td class='c2'>new2</td>")
assertLength(t, doc.Find("table td").Nodes, 4)
assertClass(t, doc.Find("table td").First(), "new-node")
assertLength(t, doc.Find("table td").Nodes, 6)
assertClass(t, doc.Find("table td").First(), "c1")
printSel(t, doc.Selection)
}
@@ -374,10 +375,11 @@ func TestReplaceWithHtmlContext(t *testing.T) {
</table>
</body>
</html>`)
doc.Find("table th").ReplaceWithHtml("<td>Test</td><td>Replace</td>")
doc.Find("table th").ReplaceWithHtml("<td class='c1'>Test</td><td class='c2'>Replace</td>")
assertLength(t, doc.Find("table th").Nodes, 0)
assertLength(t, doc.Find("table tr td").Nodes, 4)
assertClass(t, doc.Find("table tr td").First(), "c1")
printSel(t, doc.Selection)
}
@@ -434,7 +436,7 @@ func TestSetHtmlContext(t *testing.T) {
assertLength(t, doc.Find("table th").Nodes, 0)
assertLength(t, doc.Find("table td").Nodes, 4)
assertLength(t, doc.Find("table t2").Nodes, 2)
assertLength(t, doc.Find("table tr").Nodes, 2)
printSel(t, doc.Selection)
}