github.com/aarzilli/tools@v0.0.0-20151123112009-0d27094f75e0/net/http/dom/mini_go_query.go (about)

     1  // Package dom supplies simple node manipulations.
     2  package dom
     3  
     4  import (
     5  	"bytes"
     6  	"fmt"
     7  	"log"
     8  	"os"
     9  	"strings"
    10  
    11  	"github.com/pbberlin/tools/runtimepb"
    12  	"golang.org/x/net/html"
    13  )
    14  
    15  var wpf = fmt.Fprintf
    16  
    17  // inspired by https://github.com/PuerkitoBio/goquery/blob/master/manipulation.go
    18  
    19  func ReplaceNode(self, dst *html.Node) {
    20  	InsertAfter(self, dst)
    21  	RemoveNode(self)
    22  }
    23  
    24  func RemoveNode(n *html.Node) {
    25  	par := n.Parent
    26  	if par != nil {
    27  		par.RemoveChild(n)
    28  	} else {
    29  		log.Printf("\nNode to remove has no Parent\n")
    30  		runtimepb.StackTrace(4)
    31  	}
    32  }
    33  
    34  // InsertBefore inserts before itself.
    35  // node.InsertBefore refers to its children
    36  func InsertBefore(insPnt, toInsert *html.Node) {
    37  	if insPnt.Parent != nil {
    38  		insPnt.Parent.InsertBefore(toInsert, insPnt)
    39  	} else {
    40  		log.Printf("\nInsertBefore - insPnt has no Parent\n")
    41  		runtimepb.StackTrace(4)
    42  	}
    43  }
    44  
    45  // InsertBefore inserts at the end, when NextSibling is null.
    46  // compare http://stackoverflow.com/questions/4793604/how-to-do-insert-after-in-javascript-without-using-a-library
    47  func InsertAfter(insPnt, toInsert *html.Node) {
    48  	if insPnt.Parent != nil {
    49  		insPnt.Parent.InsertBefore(toInsert, insPnt.NextSibling)
    50  	} else {
    51  		log.Printf("\nInsertAfter - insPnt has no Parent\n")
    52  		runtimepb.StackTrace(4)
    53  	}
    54  }
    55  
    56  //
    57  //
    58  // Deep copy a node.
    59  // The new node has clones of all the original node's
    60  // children but none of its parents or siblings
    61  func CloneNodeWithSubtree(n *html.Node) *html.Node {
    62  	nn := &html.Node{
    63  		Type:     n.Type,
    64  		DataAtom: n.DataAtom,
    65  		Data:     n.Data,
    66  		Attr:     make([]html.Attribute, len(n.Attr)),
    67  	}
    68  
    69  	copy(nn.Attr, n.Attr)
    70  	for c := n.FirstChild; c != nil; c = c.NextSibling {
    71  		nn.AppendChild(CloneNodeWithSubtree(c)) // recursion
    72  	}
    73  	return nn
    74  }
    75  
    76  //
    77  //
    78  // Deep copy a node.
    79  // no children, no parent, no siblings
    80  func CloneNode(n *html.Node) *html.Node {
    81  	nn := &html.Node{
    82  		Type:     n.Type,
    83  		DataAtom: n.DataAtom,
    84  		Data:     n.Data,
    85  		Attr:     make([]html.Attribute, len(n.Attr)),
    86  	}
    87  	copy(nn.Attr, n.Attr)
    88  	return nn
    89  }
    90  
    91  //
    92  func PrintSubtree(n *html.Node) *bytes.Buffer {
    93  	b := new(bytes.Buffer)
    94  	return printSubtree(n, b, 0)
    95  }
    96  func printSubtree(n *html.Node, b *bytes.Buffer, lvl int) *bytes.Buffer {
    97  
    98  	if lvl > 40 {
    99  		log.Printf("%s", b.String())
   100  		log.Printf("possible circular relationship\n")
   101  		os.Exit(1)
   102  	}
   103  
   104  	ind := strings.Repeat("  ", lvl)
   105  	slvl := fmt.Sprintf("%sL%v", ind, lvl)
   106  	wpf(b, "%-10v %v", slvl, NodeTypeStr(n.Type))
   107  	wpf(b, " %v\n", strings.TrimSpace(n.Data))
   108  
   109  	for c := n.FirstChild; c != nil; c = c.NextSibling {
   110  		printSubtree(c, b, lvl+1) // recursion
   111  	}
   112  
   113  	return b
   114  }
   115  
   116  func Nd(ntype string, content ...string) *html.Node {
   117  
   118  	nd0 := new(html.Node)
   119  
   120  	if ntype == "text" {
   121  		nd0.Type = html.TextNode
   122  		if len(content) > 0 {
   123  			nd0.Data = content[0]
   124  		}
   125  	} else {
   126  		nd0.Type = html.ElementNode
   127  		nd0.Data = ntype
   128  		if len(content) > 0 {
   129  			runtimepb.StackTrace(4)
   130  			log.Printf("Element nodes can't have content")
   131  		}
   132  	}
   133  
   134  	return nd0
   135  
   136  }