1
0
mirror of https://github.com/ericchiang/pup synced 2024-11-28 02:48:16 +00:00
pup/printing.go

124 lines
2.9 KiB
Go
Raw Normal View History

2014-09-01 18:18:34 +00:00
package main
import (
"code.google.com/p/go.net/html"
"code.google.com/p/go.net/html/atom"
"fmt"
"github.com/fatih/color"
2014-09-16 01:16:50 +00:00
"github.com/mattn/go-colorable"
2014-09-01 18:50:10 +00:00
"regexp"
2014-09-01 18:18:34 +00:00
)
var (
2014-09-01 18:50:10 +00:00
// Colors
2014-09-01 18:18:34 +00:00
tagColor *color.Color = color.New(color.FgYellow).Add(color.Bold)
tokenColor = color.New(color.FgCyan).Add(color.Bold)
attrKeyColor = color.New(color.FgRed)
quoteColor = color.New(color.FgBlue)
2014-09-01 18:50:10 +00:00
// Regexp helpers
whitespaceRegexp *regexp.Regexp = regexp.MustCompile(`^\s*$`)
2014-09-02 03:53:12 +00:00
preWhitespace = regexp.MustCompile(`^\s+`)
postWhitespace = regexp.MustCompile(`\s+$`)
2014-09-01 18:18:34 +00:00
)
2014-09-16 01:16:50 +00:00
func init() {
color.Output = colorable.NewColorableStdout()
}
2014-09-01 18:18:34 +00:00
// Is this node a tag with no end tag such as <meta> or <br>?
// http://www.w3.org/TR/html-markup/syntax.html#syntax-elements
func isVoidElement(n *html.Node) bool {
switch n.DataAtom {
case atom.Area, atom.Base, atom.Br, atom.Col, atom.Command, atom.Embed,
atom.Hr, atom.Img, atom.Input, atom.Keygen, atom.Link,
atom.Meta, atom.Param, atom.Source, atom.Track, atom.Wbr:
return true
}
return false
}
2014-09-28 15:48:31 +00:00
type TreeDisplayer struct {
IndentString string
}
func (t TreeDisplayer) Display(nodes []*html.Node) {
for _, node := range nodes {
t.printNode(node, 0)
}
}
func (t TreeDisplayer) printChildren(n *html.Node, level int) {
2014-09-01 18:18:34 +00:00
if maxPrintLevel > -1 {
if level >= maxPrintLevel {
2014-09-28 15:48:31 +00:00
t.printIndent(level)
2014-09-01 18:18:34 +00:00
fmt.Println("...")
return
}
}
child := n.FirstChild
for child != nil {
2014-09-28 15:48:31 +00:00
t.printNode(child, level)
2014-09-01 18:18:34 +00:00
child = child.NextSibling
}
}
2014-09-28 15:48:31 +00:00
func (t TreeDisplayer) printIndent(level int) {
for ; level > 0; level-- {
fmt.Print(indentString)
}
}
2014-09-01 18:50:10 +00:00
// Print a node and all of it's children to `maxlevel`.
2014-09-28 15:48:31 +00:00
func (t TreeDisplayer) printNode(n *html.Node, level int) {
2014-09-01 18:18:34 +00:00
switch n.Type {
case html.TextNode:
2014-09-28 16:26:31 +00:00
s := html.EscapeString(n.Data)
2014-09-01 18:18:34 +00:00
if !whitespaceRegexp.MatchString(s) {
s = preWhitespace.ReplaceAllString(s, "")
s = postWhitespace.ReplaceAllString(s, "")
2014-09-28 15:48:31 +00:00
t.printIndent(level)
2014-09-01 18:18:34 +00:00
fmt.Println(s)
}
case html.ElementNode:
2014-09-28 15:48:31 +00:00
t.printIndent(level)
2014-09-01 18:18:34 +00:00
if printColor {
tokenColor.Print("<")
tagColor.Printf("%s", n.Data)
} else {
fmt.Printf("<%s", n.Data)
}
for _, a := range n.Attr {
if printColor {
fmt.Print(" ")
attrKeyColor.Printf("%s", a.Key)
tokenColor.Print("=")
2014-09-28 16:26:31 +00:00
val := html.EscapeString(a.Val)
quoteColor.Printf(`"%s"`, val)
2014-09-01 18:18:34 +00:00
} else {
2014-09-28 16:26:31 +00:00
val := html.EscapeString(a.Val)
fmt.Printf(` %s="%s"`, a.Key, val)
2014-09-01 18:18:34 +00:00
}
}
if printColor {
tokenColor.Println(">")
} else {
fmt.Print(">\n")
}
if !isVoidElement(n) {
2014-09-28 15:48:31 +00:00
t.printChildren(n, level+1)
t.printIndent(level)
2014-09-01 18:18:34 +00:00
if printColor {
tokenColor.Print("</")
tagColor.Printf("%s", n.Data)
tokenColor.Println(">")
} else {
fmt.Printf("</%s>\n", n.Data)
}
}
case html.CommentNode, html.DoctypeNode, html.DocumentNode:
2014-09-28 15:48:31 +00:00
t.printChildren(n, level)
2014-09-01 18:18:34 +00:00
}
}