-
Notifications
You must be signed in to change notification settings - Fork 45
/
helpers.go
105 lines (92 loc) · 2.07 KB
/
helpers.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
package man
import (
"bytes"
"fmt"
"io"
"github.com/gomarkdown/markdown/ast"
"github.com/gomarkdown/markdown/parser"
)
func (r *Renderer) out(w io.Writer, d []byte) { w.Write(d) }
func (r *Renderer) outs(w io.Writer, s string) { io.WriteString(w, s) }
func (r *Renderer) outOneOf(w io.Writer, outFirst bool, first string, second string) {
if outFirst {
r.outs(w, first)
} else {
r.outs(w, second)
}
}
func needsBackslash(c byte) bool {
for _, r := range []byte("-_&\\") {
if c == r {
return true
}
}
return false
}
func escapeSpecialChars(r *Renderer, w io.Writer, text []byte) {
lt := len(text)
Parse:
for i := 0; i < lt; i++ {
// escape apostrophe or period after newline (making this first char on the line)
if i == 0 && (text[i] == '\'' || text[i] == '.') {
r.outs(w, "\\&")
r.out(w, []byte{text[i]})
continue
}
if i > 0 && text[i-1] == '\n' && (text[i] == '\'' || text[i] == '.') {
r.outs(w, "\\&")
r.out(w, []byte{text[i]})
continue
}
if text[i] == '\t' {
r.outs(w, " ")
continue
}
if needsBackslash(text[i]) {
r.out(w, []byte{'\\'})
}
// callout comments
for _, comment := range r.opts.Comments {
if !bytes.HasPrefix(text[i:], comment) {
break
}
lc := len(comment)
if i+lc < lt {
if id, consumed := parser.IsCallout(text[i+lc:]); consumed > 0 {
// We have seen a callout
io.WriteString(w, fmt.Sprintf("<%s>", id))
i += consumed + lc - 1
continue Parse
}
}
}
r.out(w, []byte{text[i]})
}
}
// return the table cells.
func rows(node *ast.Table) [][]*ast.TableCell {
table := [][]*ast.TableCell{}
row := []*ast.TableCell{}
ast.WalkFunc(node, func(node ast.Node, entering bool) ast.WalkStatus {
switch x := node.(type) {
case *ast.Table:
if !entering {
return ast.Terminate
}
case *ast.TableRow:
if entering {
row = []*ast.TableCell{}
} else {
table = append(table, row)
return ast.GoToNext
}
case *ast.TableCell:
if !entering {
row = append(row, x)
}
return ast.GoToNext
}
return ast.GoToNext
})
return table
}