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  }