# dom [![Go Reference](https://pkg.go.dev/badge/github.com/JohannesKaufmann/dom.svg)](https://pkg.go.dev/github.com/JohannesKaufmann/dom) Helper functions for "net/html" that make it easier to interact with `*html.Node`. πŸš€ [Getting Started](#getting-started) - πŸ“š [Documentation](#documentation) - πŸ§‘β€πŸ’» [Examples](/examples/) ## Installation ```bash go get -u github.com/JohannesKaufmann/dom ``` > [!NOTE] > This "dom" libary was developed for the needs of the [html-to-markdown](https://github.com/JohannesKaufmann/html-to-markdown) library. > That beeing said, please submit any functions that you need. ## Getting Started ```go package main import ( "fmt" "log" "strings" "github.com/JohannesKaufmann/dom" "golang.org/x/net/html" ) func main() { input := ` ` doc, err := html.Parse(strings.NewReader(input)) if err != nil { log.Fatal(err) } // - - - // firstLink := dom.FindFirstNode(doc, func(node *html.Node) bool { return dom.NodeName(node) == "a" }) fmt.Println("href:", dom.GetAttributeOr(firstLink, "href", "")) } ``` ## Node vs Element The naming scheme in this library is: - "Node" means `*html.Node{}` - This means _any_ node in the tree of nodes. - "Element" means `*html.Node{Type: html.ElementNode}` - This means _only_ nodes with the type of `ElementNode`. For example `

`, ``, ``, ... but not `#text`, ``, ... For most functions, there are two versions. For example: - `FirstChildNode()` and `FirstChildElement()` - `AllChildNodes()` and `AllChildElements()` - ... ## Documentation [![Go Reference](https://pkg.go.dev/badge/github.com/JohannesKaufmann/dom.svg)](https://pkg.go.dev/github.com/JohannesKaufmann/dom) ### Attributes & Content You can get the attributes of a node using `GetAttribute`, `GetAttributeOr` or the more specialized `GetClasses` that returns a slice of strings. For matching nodes, `HasID` and `HasClass` can be used. If you want to collect the #text of all the child nodes, you can call `CollectText`. ```go name := dom.NodeName(node) // "h2" href := dom.GetAttributeOr(node, "href", "") // "github.com" isHeading := dom.HasClass(node, "repo__name") // `true` content := dom.CollectText(node) // "Lorem ipsum" ``` --- ### Children & Siblings You can already use `node.FirstChild` to get the first child _node_. For the convenience we added `FirstChildNode()` and `FirstChildElement()` which returns `*html.Node`. To get all direct children, use `AllChildNodes` and `AllChildElements` which returns `[]*html.Node`. - `PrevSiblingNode` and `PrevSiblingElement` - `NextSiblingNode` and `NextSiblingElement` ### Find Nodes Searching for nodes deep in the tree is made easier with: ```go firstParagraph := dom.FindFirstNode(doc, func(node *html.Node) bool { return dom.NodeName(node) == "p" }) // *html.Node allParagraphs := dom.FindAllNodes(doc, func(node *html.Node) bool { return dom.NodeName(node) == "p" }) // []*html.Node ``` - πŸ§‘β€πŸ’» [Example code, find](/examples/find/main.go) - πŸ§‘β€πŸ’» [Example code, selectors](/examples/selectors/main.go) --- ### Get next/previous neighbors What is special about this? The order! If you are somewhere in the DOM, you can call `GetNextNeighborNode` to get the next node, even if it is _further up_ the tree. The order is the same as you would see the elements in the DOM. ```go node := startNode for node != nil { fmt.Println(dom.NodeName(node)) node = dom.GetNextNeighborNode(node) } ``` If we start the `for` loop at the `