-
Notifications
You must be signed in to change notification settings - Fork 85
/
output.go
117 lines (106 loc) · 2.31 KB
/
output.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package terminal
import (
"bytes"
"strings"
)
type outputBuffer struct {
buf bytes.Buffer
}
func (b *outputBuffer) appendNodeStyle(n node) {
b.buf.Write([]byte(`<span class="`))
for idx, class := range n.style.asClasses() {
if idx > 0 {
b.buf.Write([]byte(" "))
}
b.buf.Write([]byte(class))
}
b.buf.Write([]byte(`">`))
}
func (b *outputBuffer) closeStyle() {
b.buf.Write([]byte("</span>"))
}
func (b *outputBuffer) appendANSIStyle(n node) {
for _, code := range n.style.asANSICodes() {
b.buf.Write([]byte(code))
}
}
func (b *outputBuffer) resetANSI() {
b.buf.Write([]byte("\u001b[0m"))
}
// Append a character to our outputbuffer, escaping HTML bits as necessary.
func (b *outputBuffer) appendChar(char rune) {
switch char {
case '&':
b.buf.WriteString("&")
case '\'':
b.buf.WriteString("'")
case '<':
b.buf.WriteString("<")
case '>':
b.buf.WriteString(">")
case '"':
b.buf.WriteString(""")
case '/':
b.buf.WriteString("/")
default:
b.buf.WriteRune(char)
}
}
func outputLineAsHTML(line []node) string {
var spanOpen bool
var lineBuf outputBuffer
for idx, node := range line {
if idx == 0 && !node.style.isEmpty() {
lineBuf.appendNodeStyle(node)
spanOpen = true
} else if idx > 0 {
previous := line[idx-1]
if !node.hasSameStyle(previous) {
if spanOpen {
lineBuf.closeStyle()
spanOpen = false
}
if !node.style.isEmpty() {
lineBuf.appendNodeStyle(node)
spanOpen = true
}
}
}
if node.elem != nil {
lineBuf.buf.WriteString(node.elem.asHTML())
} else {
lineBuf.appendChar(node.blob)
}
}
if spanOpen {
lineBuf.closeStyle()
}
return strings.TrimRight(lineBuf.buf.String(), " \t")
}
func outputLineAsANSI(line []node) string {
var styleApplied bool
var lineBuf outputBuffer
for idx, node := range line {
if idx == 0 && !node.style.isEmpty() {
lineBuf.appendANSIStyle(node)
styleApplied = true
} else if idx > 0 {
previous := line[idx-1]
if !node.hasSameStyle(previous) {
if styleApplied {
lineBuf.resetANSI()
styleApplied = false
}
if !node.style.isEmpty() {
lineBuf.appendANSIStyle(node)
styleApplied = true
}
}
}
lineBuf.buf.WriteRune(node.blob)
}
if styleApplied {
lineBuf.resetANSI()
}
return strings.TrimRight(lineBuf.buf.String(), " \t")
}