blob: 5e976ebd9859ae3e3cb24c9970886ac672e6b47d (
plain) (
blame)
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
|
// Copyright 2015 The Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package markdown
import "unicode/utf8"
type ParserInline struct {
}
type (
InlineRule func(*StateInline, bool) bool
PostprocessRule func(*StateInline)
)
var (
inlineRules []InlineRule
postprocessRules []PostprocessRule
)
func (i ParserInline) Parse(src string, md *Markdown, env *Environment) []Token {
if src == "" {
return nil
}
var s StateInline
s.Src = src
s.Md = md
s.Env = env
s.PosMax = len(src)
s.Tokens = s.bootstrap[:0]
i.Tokenize(&s)
for _, r := range postprocessRules {
r(&s)
}
return s.Tokens
}
func (ParserInline) Tokenize(s *StateInline) {
end := s.PosMax
src := s.Src
maxNesting := s.Md.MaxNesting
ok := false
for s.Pos < end {
if s.Level < maxNesting {
for _, rule := range inlineRules {
ok = rule(s, false)
if ok {
break
}
}
}
if ok {
if s.Pos >= end {
break
}
continue
}
r, size := utf8.DecodeRuneInString(src[s.Pos:])
s.Pending.WriteRune(r)
s.Pos += size
}
if s.Pending.Len() > 0 {
s.PushPending()
}
}
func (ParserInline) SkipToken(s *StateInline) {
pos := s.Pos
if s.Cache != nil {
if newPos, ok := s.Cache[pos]; ok {
s.Pos = newPos
return
}
} else {
s.Cache = make(map[int]int)
}
ok := false
if s.Level < s.Md.MaxNesting {
for _, r := range inlineRules {
s.Level++
ok = r(s, true)
s.Level--
if ok {
break
}
}
} else {
s.Pos = s.PosMax
}
if !ok {
_, size := utf8.DecodeRuneInString(s.Src[s.Pos:])
s.Pos += size
}
s.Cache[pos] = s.Pos
}
|