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
|
package markdown
import "strings"
func isBlockquote(line string) bool {
return strings.HasPrefix(strings.TrimLeft(line, " "), ">")
}
func parseBlockquote(lines []string, i int) (Block, int) {
var inner []string
j := i
for j < len(lines) && isBlockquote(lines[j]) {
l := strings.TrimPrefix(strings.TrimLeft(lines[j], " "), ">")
inner = append(inner, strings.TrimPrefix(l, " "))
j++
}
return Block{Kind: KindBlockquote, Children: parseBlocks(inner)}, j
}
func listIndent(line string) int {
n := 0
for n < len(line) && line[n] == ' ' {
n++
}
return n
}
func isListLine(line string) bool {
t := strings.TrimLeft(line, " ")
if strings.HasPrefix(t, "- ") || strings.HasPrefix(t, "* ") || strings.HasPrefix(t, "+ ") {
return true
}
k := 0
for k < len(t) && t[k] >= '0' && t[k] <= '9' {
k++
}
return k > 0 && k+1 < len(t) && t[k] == '.' && t[k+1] == ' '
}
func listMarkerInfo(line string) (ordered bool, contentOffset int) {
t := strings.TrimLeft(line, " ")
lead := len(line) - len(t)
if strings.HasPrefix(t, "- ") || strings.HasPrefix(t, "* ") || strings.HasPrefix(t, "+ ") {
return false, lead + 2
}
k := 0
for k < len(t) && t[k] >= '0' && t[k] <= '9' {
k++
}
return true, lead + k + 2
}
func parseList(lines []string, i, indent int) (Block, int) {
ordered, _ := listMarkerInfo(lines[i])
list := Block{Kind: KindList, Ordered: ordered}
j := i
for j < len(lines) {
if strings.TrimSpace(lines[j]) == "" || !isListLine(lines[j]) {
break
}
ind := listIndent(lines[j])
if ind < indent {
break
}
if ind > indent {
child, next := parseList(lines, j, ind)
if n := len(list.Children); n > 0 {
list.Children[n-1].Children = append(list.Children[n-1].Children, child)
} else {
list.Children = append(list.Children, Block{Kind: KindListItem, Children: []Block{child}})
}
j = next
continue
}
_, off := listMarkerInfo(lines[j])
text := strings.TrimSpace(lines[j][off:])
list.Children = append(list.Children, Block{Kind: KindListItem, Inline: parseInline(text)})
j++
}
return list, j
}
|