ref: c9faa5d093ef6a890e00fb92880ab1a2edf9801c
dir: /nodes/nodes.go/
package nodes import ( "golang.org/x/net/html" "opossum/logger" "opossum/style" "strings" ) var log *logger.Logger func SetLogger(l *logger.Logger) { log = l } // Node represents a node at the render stage. It // represents a subTree or just a single html node. type Node struct { DomSubtree *html.Node Text string Wrappable bool Attr []html.Attribute style.Map Children []*Node Parent *Node } // NewNodeTree propagates the cascading styles to the leaves // // First applies the global style and at the end the local style attribute's style is attached. func NewNodeTree(doc *html.Node, cs style.Map, nodeMap map[*html.Node]style.Map, parent *Node) (n *Node) { ncs := cs if m, ok := nodeMap[doc]; ok { ncs = ncs.ApplyChildStyle(m) } ncs = ncs.ApplyChildStyle(style.NewMap(doc)) data := doc.Data if doc.Type == html.ElementNode { data = strings.ToLower(data) } n = &Node{ //Data: data, //Type: doc.Type, DomSubtree: doc, Attr: doc.Attr, Map: ncs, Children: make([]*Node, 0, 2), Parent: parent, } n.Wrappable = doc.Type == html.TextNode || doc.Data == "span" // TODO: probably this list needs to be extended if doc.Type == html.TextNode { n.Text = filterText(doc.Data) } i := 0 for c := doc.FirstChild; c != nil; c = c.NextSibling { if c.Type != html.CommentNode { n.Children = append(n.Children, NewNodeTree(c, ncs, nodeMap, n)) i++ } } return } // filterText removes line break runes (TODO: add this later but handle properly) func filterText(t string) (text string) { return strings.ReplaceAll(t, "", "") } func (n Node) Type() html.NodeType { return n.DomSubtree.Type } func (n Node) Data() string { return n.DomSubtree.Data } func (n *Node) ParentForm() *Node { log.Printf("<%v>.ParentForm()", n.DomSubtree.Data) if n.DomSubtree.Data == "form" { log.Printf(" I'm a form :-)") return n } if n.Parent != nil { log.Printf(" go to my parent") return n.Parent.ParentForm() } return nil } func IsPureTextContent(n Node) bool { if n.Text != "" { return true } for _, c := range n.Children { if c.Text == "" { return false } } return true } func ContentFrom(n Node) string { var content string if n.Text != "" && n.Type() == html.TextNode && !n.Map.IsDisplayNone() { content += n.Text } for _, c := range n.Children { if !c.Map.IsDisplayNone() { content += ContentFrom(*c) } } return strings.TrimSpace(content) }