aboutsummaryrefslogtreecommitdiff
path: root/markdown/ast_list.go
blob: 9aa36e707a945998d5eca4c6eabd9c8b41d99e6e (plain)
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
package markdown

import (
	"fmt"
	"html/template"
	"regexp"
)

var regexOrdered = regexp.MustCompile(`\d+\.`)

type listType string

const (
	listUnordered listType = "ul"
	listOrdered   listType = "ol"
)

type astList struct {
	tag     listType
	content []*astParagraph
}

func (a *astList) Eval() (template.HTML, *ParseError) {
	var content template.HTML
	for _, c := range a.content {
		ct, err := c.Eval()
		if err != nil {
			return "", err
		}
		content += template.HTML(fmt.Sprintf("<li>%s</li>", trimSpace(ct)))
	}
	return template.HTML(fmt.Sprintf("<%s>%s</%s>", a.tag, content, a.tag)), nil
}

func list(lxs *lexers) (block, *ParseError) {
	tree := new(astList)
	tree.tag = detectListType(lxs.Current().Value)
	if len(tree.tag) == 0 {
		return paragraph(lxs, false)
	}
	n := 0
	for lxs.Next() && n < 2 {
		switch lxs.Current().Type {
		case lexerBreak:
			n += len(lxs.Current().Value)
		case lexerList:
			n = 0
			tp := detectListType(lxs.Current().Value)
			if tp != tree.tag {
				lxs.Before() // because we dit not use it
				return tree, nil
			}
		default:
			n = 0
			c, err := paragraph(lxs, true)
			if err != nil {
				return nil, err
			}
			lxs.Before() // because we must parse the last char
			tree.content = append(tree.content, c)
		}
	}
	lxs.Before() // because we did not use it
	return tree, nil
}

func detectListType(val string) listType {
	first := []rune(val)[0]
	if first == '-' || first == '*' {
		if len(val) > 1 {
			return ""
		}
		return listUnordered
	}
	if !regexOrdered.MatchString(val) {
		return ""
	}
	return listOrdered
}