github.com/Kindred87/Obsidian@v0.0.0-20210809203756-86936424b848/retrieval/html/hierarchy.go (about) 1 package html 2 3 import ( 4 "errors" 5 "fmt" 6 "os" 7 8 "github.com/Kindred87/Obsidian/datasource" 9 "github.com/PuerkitoBio/goquery" 10 ) 11 12 // HierarchyFor returns linear node hierarchies for nodes containing the given values. 13 // Value matching is performed on an OR basis. The parent limit parameters must be >= 1. 14 func HierarchyFor(dsAlias string, nodesContaining []string, parentLimit int) ([]NodeList, error) { 15 if parentLimit < 1 { 16 return nil, fmt.Errorf("a parentLimit of %d was given", parentLimit) 17 } 18 19 result, path, err := datasource.Find(dsAlias) 20 if err != nil { 21 return nil, err 22 } else if !result { 23 return nil, errors.New("could not locate datasource by the alias of " + dsAlias) 24 } 25 26 fi, err := os.Open(path) 27 if err != nil { 28 return nil, err 29 } 30 31 sel, err := findNodes(fi, nodesContaining) 32 if err != nil { 33 return nil, err 34 } 35 36 nodeList := []NodeList{} 37 for i := 0; i < len(sel); i++ { 38 nodeList = append(nodeList, listNodeWithNParents(&sel[i], parentLimit)) 39 } 40 41 if err = fi.Close(); err != nil { 42 return nil, err 43 } 44 45 return nodeList, nil 46 } 47 48 // listNodeWithNParents returns a NodeList populated with the given node and up to N parents. 49 // An N value <= 0 is considered as infinite. 50 func listNodeWithNParents(sel *goquery.Selection, N int) NodeList { 51 nList := NodeList{ 52 Name: sel.Nodes[0].Data, 53 } 54 nList = appendNodes(nList, sel) 55 56 if N <= len(nList.Nodes) && N > 0 { 57 nList.Nodes = nList.Nodes[:N] 58 } 59 return nList 60 } 61 62 // appendNodes populates nList with the given node and all of its parents. 63 func appendNodes(nList NodeList, sel *goquery.Selection) NodeList { 64 65 if goquery.NodeName(sel) == "" { 66 return nList 67 } 68 69 nList.Nodes = append(nList.Nodes, nodeFromSelection(len(nList.Nodes)+1, sel)) 70 71 return appendNodes(nList, sel.Parent()) 72 }