annotate vendor/github.com/russross/blackfriday/v2/inline.go @ 87:0b78d345c179 draft

lint Signed-off-by: Izuru Yakumo <yakumo.izuru@chaotic.ninja>
author yakumo.izuru
date Mon, 17 Jun 2024 15:43:09 +0000
parents 787b5ee0289d
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
66
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2 // Blackfriday Markdown Processor
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
3 // Available at http://github.com/russross/blackfriday
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
4 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
5 // Copyright © 2011 Russ Ross <russ@russross.com>.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
6 // Distributed under the Simplified BSD License.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
7 // See README.md for details.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
8 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
9
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
10 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
11 // Functions to parse inline elements.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
12 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
13
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
14 package blackfriday
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
15
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
16 import (
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
17 "bytes"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
18 "regexp"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
19 "strconv"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
20 )
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
21
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
22 var (
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
23 urlRe = `((https?|ftp):\/\/|\/)[-A-Za-z0-9+&@#\/%?=~_|!:,.;\(\)]+`
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
24 anchorRe = regexp.MustCompile(`^(<a\shref="` + urlRe + `"(\stitle="[^"<>]+")?\s?>` + urlRe + `<\/a>)`)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
25
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
26 // https://www.w3.org/TR/html5/syntax.html#character-references
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
27 // highest unicode code point in 17 planes (2^20): 1,114,112d =
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
28 // 7 dec digits or 6 hex digits
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
29 // named entity references can be 2-31 characters with stuff like &lt;
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
30 // at one end and &CounterClockwiseContourIntegral; at the other. There
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
31 // are also sometimes numbers at the end, although this isn't inherent
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
32 // in the specification; there are never numbers anywhere else in
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
33 // current character references, though; see &frac34; and &blk12;, etc.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
34 // https://www.w3.org/TR/html5/syntax.html#named-character-references
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
35 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
36 // entity := "&" (named group | number ref) ";"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
37 // named group := [a-zA-Z]{2,31}[0-9]{0,2}
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
38 // number ref := "#" (dec ref | hex ref)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
39 // dec ref := [0-9]{1,7}
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
40 // hex ref := ("x" | "X") [0-9a-fA-F]{1,6}
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
41 htmlEntityRe = regexp.MustCompile(`&([a-zA-Z]{2,31}[0-9]{0,2}|#([0-9]{1,7}|[xX][0-9a-fA-F]{1,6}));`)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
42 )
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
43
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
44 // Functions to parse text within a block
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
45 // Each function returns the number of chars taken care of
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
46 // data is the complete block being rendered
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
47 // offset is the number of valid chars before the current cursor
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
48
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
49 func (p *Markdown) inline(currBlock *Node, data []byte) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
50 // handlers might call us recursively: enforce a maximum depth
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
51 if p.nesting >= p.maxNesting || len(data) == 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
52 return
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
53 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
54 p.nesting++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
55 beg, end := 0, 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
56 for end < len(data) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
57 handler := p.inlineCallback[data[end]]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
58 if handler != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
59 if consumed, node := handler(p, data, end); consumed == 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
60 // No action from the callback.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
61 end++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
62 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
63 // Copy inactive chars into the output.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
64 currBlock.AppendChild(text(data[beg:end]))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
65 if node != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
66 currBlock.AppendChild(node)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
67 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
68 // Skip past whatever the callback used.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
69 beg = end + consumed
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
70 end = beg
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
71 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
72 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
73 end++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
74 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
75 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
76 if beg < len(data) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
77 if data[end-1] == '\n' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
78 end--
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
79 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
80 currBlock.AppendChild(text(data[beg:end]))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
81 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
82 p.nesting--
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
83 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
84
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
85 // single and double emphasis parsing
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
86 func emphasis(p *Markdown, data []byte, offset int) (int, *Node) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
87 data = data[offset:]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
88 c := data[0]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
89
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
90 if len(data) > 2 && data[1] != c {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
91 // whitespace cannot follow an opening emphasis;
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
92 // strikethrough only takes two characters '~~'
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
93 if c == '~' || isspace(data[1]) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
94 return 0, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
95 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
96 ret, node := helperEmphasis(p, data[1:], c)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
97 if ret == 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
98 return 0, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
99 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
100
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
101 return ret + 1, node
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
102 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
103
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
104 if len(data) > 3 && data[1] == c && data[2] != c {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
105 if isspace(data[2]) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
106 return 0, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
107 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
108 ret, node := helperDoubleEmphasis(p, data[2:], c)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
109 if ret == 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
110 return 0, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
111 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
112
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
113 return ret + 2, node
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
114 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
115
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
116 if len(data) > 4 && data[1] == c && data[2] == c && data[3] != c {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
117 if c == '~' || isspace(data[3]) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
118 return 0, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
119 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
120 ret, node := helperTripleEmphasis(p, data, 3, c)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
121 if ret == 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
122 return 0, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
123 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
124
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
125 return ret + 3, node
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
126 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
127
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
128 return 0, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
129 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
130
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
131 func codeSpan(p *Markdown, data []byte, offset int) (int, *Node) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
132 data = data[offset:]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
133
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
134 nb := 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
135
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
136 // count the number of backticks in the delimiter
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
137 for nb < len(data) && data[nb] == '`' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
138 nb++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
139 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
140
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
141 // find the next delimiter
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
142 i, end := 0, 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
143 for end = nb; end < len(data) && i < nb; end++ {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
144 if data[end] == '`' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
145 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
146 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
147 i = 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
148 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
149 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
150
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
151 // no matching delimiter?
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
152 if i < nb && end >= len(data) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
153 return 0, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
154 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
155
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
156 // trim outside whitespace
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
157 fBegin := nb
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
158 for fBegin < end && data[fBegin] == ' ' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
159 fBegin++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
160 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
161
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
162 fEnd := end - nb
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
163 for fEnd > fBegin && data[fEnd-1] == ' ' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
164 fEnd--
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
165 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
166
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
167 // render the code span
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
168 if fBegin != fEnd {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
169 code := NewNode(Code)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
170 code.Literal = data[fBegin:fEnd]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
171 return end, code
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
172 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
173
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
174 return end, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
175 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
176
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
177 // newline preceded by two spaces becomes <br>
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
178 func maybeLineBreak(p *Markdown, data []byte, offset int) (int, *Node) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
179 origOffset := offset
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
180 for offset < len(data) && data[offset] == ' ' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
181 offset++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
182 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
183
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
184 if offset < len(data) && data[offset] == '\n' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
185 if offset-origOffset >= 2 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
186 return offset - origOffset + 1, NewNode(Hardbreak)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
187 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
188 return offset - origOffset, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
189 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
190 return 0, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
191 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
192
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
193 // newline without two spaces works when HardLineBreak is enabled
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
194 func lineBreak(p *Markdown, data []byte, offset int) (int, *Node) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
195 if p.extensions&HardLineBreak != 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
196 return 1, NewNode(Hardbreak)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
197 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
198 return 0, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
199 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
200
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
201 type linkType int
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
202
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
203 const (
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
204 linkNormal linkType = iota
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
205 linkImg
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
206 linkDeferredFootnote
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
207 linkInlineFootnote
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
208 )
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
209
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
210 func isReferenceStyleLink(data []byte, pos int, t linkType) bool {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
211 if t == linkDeferredFootnote {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
212 return false
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
213 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
214 return pos < len(data)-1 && data[pos] == '[' && data[pos+1] != '^'
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
215 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
216
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
217 func maybeImage(p *Markdown, data []byte, offset int) (int, *Node) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
218 if offset < len(data)-1 && data[offset+1] == '[' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
219 return link(p, data, offset)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
220 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
221 return 0, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
222 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
223
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
224 func maybeInlineFootnote(p *Markdown, data []byte, offset int) (int, *Node) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
225 if offset < len(data)-1 && data[offset+1] == '[' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
226 return link(p, data, offset)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
227 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
228 return 0, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
229 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
230
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
231 // '[': parse a link or an image or a footnote
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
232 func link(p *Markdown, data []byte, offset int) (int, *Node) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
233 // no links allowed inside regular links, footnote, and deferred footnotes
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
234 if p.insideLink && (offset > 0 && data[offset-1] == '[' || len(data)-1 > offset && data[offset+1] == '^') {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
235 return 0, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
236 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
237
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
238 var t linkType
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
239 switch {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
240 // special case: ![^text] == deferred footnote (that follows something with
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
241 // an exclamation point)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
242 case p.extensions&Footnotes != 0 && len(data)-1 > offset && data[offset+1] == '^':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
243 t = linkDeferredFootnote
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
244 // ![alt] == image
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
245 case offset >= 0 && data[offset] == '!':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
246 t = linkImg
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
247 offset++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
248 // ^[text] == inline footnote
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
249 // [^refId] == deferred footnote
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
250 case p.extensions&Footnotes != 0:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
251 if offset >= 0 && data[offset] == '^' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
252 t = linkInlineFootnote
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
253 offset++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
254 } else if len(data)-1 > offset && data[offset+1] == '^' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
255 t = linkDeferredFootnote
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
256 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
257 // [text] == regular link
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
258 default:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
259 t = linkNormal
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
260 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
261
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
262 data = data[offset:]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
263
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
264 var (
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
265 i = 1
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
266 noteID int
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
267 title, link, altContent []byte
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
268 textHasNl = false
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
269 )
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
270
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
271 if t == linkDeferredFootnote {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
272 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
273 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
274
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
275 // look for the matching closing bracket
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
276 for level := 1; level > 0 && i < len(data); i++ {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
277 switch {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
278 case data[i] == '\n':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
279 textHasNl = true
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
280
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
281 case isBackslashEscaped(data, i):
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
282 continue
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
283
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
284 case data[i] == '[':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
285 level++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
286
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
287 case data[i] == ']':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
288 level--
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
289 if level <= 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
290 i-- // compensate for extra i++ in for loop
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
291 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
292 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
293 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
294
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
295 if i >= len(data) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
296 return 0, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
297 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
298
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
299 txtE := i
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
300 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
301 var footnoteNode *Node
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
302
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
303 // skip any amount of whitespace or newline
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
304 // (this is much more lax than original markdown syntax)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
305 for i < len(data) && isspace(data[i]) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
306 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
307 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
308
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
309 // inline style link
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
310 switch {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
311 case i < len(data) && data[i] == '(':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
312 // skip initial whitespace
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
313 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
314
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
315 for i < len(data) && isspace(data[i]) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
316 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
317 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
318
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
319 linkB := i
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
320
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
321 // look for link end: ' " )
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
322 findlinkend:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
323 for i < len(data) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
324 switch {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
325 case data[i] == '\\':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
326 i += 2
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
327
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
328 case data[i] == ')' || data[i] == '\'' || data[i] == '"':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
329 break findlinkend
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
330
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
331 default:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
332 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
333 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
334 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
335
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
336 if i >= len(data) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
337 return 0, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
338 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
339 linkE := i
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
340
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
341 // look for title end if present
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
342 titleB, titleE := 0, 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
343 if data[i] == '\'' || data[i] == '"' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
344 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
345 titleB = i
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
346
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
347 findtitleend:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
348 for i < len(data) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
349 switch {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
350 case data[i] == '\\':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
351 i += 2
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
352
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
353 case data[i] == ')':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
354 break findtitleend
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
355
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
356 default:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
357 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
358 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
359 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
360
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
361 if i >= len(data) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
362 return 0, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
363 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
364
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
365 // skip whitespace after title
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
366 titleE = i - 1
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
367 for titleE > titleB && isspace(data[titleE]) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
368 titleE--
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
369 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
370
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
371 // check for closing quote presence
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
372 if data[titleE] != '\'' && data[titleE] != '"' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
373 titleB, titleE = 0, 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
374 linkE = i
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
375 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
376 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
377
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
378 // remove whitespace at the end of the link
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
379 for linkE > linkB && isspace(data[linkE-1]) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
380 linkE--
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
381 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
382
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
383 // remove optional angle brackets around the link
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
384 if data[linkB] == '<' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
385 linkB++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
386 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
387 if data[linkE-1] == '>' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
388 linkE--
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
389 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
390
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
391 // build escaped link and title
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
392 if linkE > linkB {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
393 link = data[linkB:linkE]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
394 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
395
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
396 if titleE > titleB {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
397 title = data[titleB:titleE]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
398 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
399
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
400 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
401
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
402 // reference style link
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
403 case isReferenceStyleLink(data, i, t):
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
404 var id []byte
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
405 altContentConsidered := false
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
406
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
407 // look for the id
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
408 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
409 linkB := i
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
410 for i < len(data) && data[i] != ']' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
411 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
412 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
413 if i >= len(data) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
414 return 0, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
415 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
416 linkE := i
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
417
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
418 // find the reference
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
419 if linkB == linkE {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
420 if textHasNl {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
421 var b bytes.Buffer
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
422
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
423 for j := 1; j < txtE; j++ {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
424 switch {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
425 case data[j] != '\n':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
426 b.WriteByte(data[j])
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
427 case data[j-1] != ' ':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
428 b.WriteByte(' ')
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
429 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
430 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
431
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
432 id = b.Bytes()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
433 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
434 id = data[1:txtE]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
435 altContentConsidered = true
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
436 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
437 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
438 id = data[linkB:linkE]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
439 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
440
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
441 // find the reference with matching id
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
442 lr, ok := p.getRef(string(id))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
443 if !ok {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
444 return 0, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
445 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
446
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
447 // keep link and title from reference
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
448 link = lr.link
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
449 title = lr.title
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
450 if altContentConsidered {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
451 altContent = lr.text
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
452 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
453 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
454
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
455 // shortcut reference style link or reference or inline footnote
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
456 default:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
457 var id []byte
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
458
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
459 // craft the id
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
460 if textHasNl {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
461 var b bytes.Buffer
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
462
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
463 for j := 1; j < txtE; j++ {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
464 switch {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
465 case data[j] != '\n':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
466 b.WriteByte(data[j])
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
467 case data[j-1] != ' ':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
468 b.WriteByte(' ')
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
469 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
470 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
471
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
472 id = b.Bytes()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
473 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
474 if t == linkDeferredFootnote {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
475 id = data[2:txtE] // get rid of the ^
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
476 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
477 id = data[1:txtE]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
478 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
479 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
480
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
481 footnoteNode = NewNode(Item)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
482 if t == linkInlineFootnote {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
483 // create a new reference
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
484 noteID = len(p.notes) + 1
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
485
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
486 var fragment []byte
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
487 if len(id) > 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
488 if len(id) < 16 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
489 fragment = make([]byte, len(id))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
490 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
491 fragment = make([]byte, 16)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
492 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
493 copy(fragment, slugify(id))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
494 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
495 fragment = append([]byte("footnote-"), []byte(strconv.Itoa(noteID))...)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
496 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
497
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
498 ref := &reference{
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
499 noteID: noteID,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
500 hasBlock: false,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
501 link: fragment,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
502 title: id,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
503 footnote: footnoteNode,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
504 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
505
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
506 p.notes = append(p.notes, ref)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
507
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
508 link = ref.link
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
509 title = ref.title
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
510 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
511 // find the reference with matching id
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
512 lr, ok := p.getRef(string(id))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
513 if !ok {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
514 return 0, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
515 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
516
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
517 if t == linkDeferredFootnote {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
518 lr.noteID = len(p.notes) + 1
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
519 lr.footnote = footnoteNode
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
520 p.notes = append(p.notes, lr)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
521 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
522
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
523 // keep link and title from reference
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
524 link = lr.link
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
525 // if inline footnote, title == footnote contents
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
526 title = lr.title
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
527 noteID = lr.noteID
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
528 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
529
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
530 // rewind the whitespace
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
531 i = txtE + 1
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
532 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
533
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
534 var uLink []byte
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
535 if t == linkNormal || t == linkImg {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
536 if len(link) > 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
537 var uLinkBuf bytes.Buffer
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
538 unescapeText(&uLinkBuf, link)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
539 uLink = uLinkBuf.Bytes()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
540 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
541
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
542 // links need something to click on and somewhere to go
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
543 if len(uLink) == 0 || (t == linkNormal && txtE <= 1) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
544 return 0, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
545 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
546 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
547
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
548 // call the relevant rendering function
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
549 var linkNode *Node
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
550 switch t {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
551 case linkNormal:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
552 linkNode = NewNode(Link)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
553 linkNode.Destination = normalizeURI(uLink)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
554 linkNode.Title = title
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
555 if len(altContent) > 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
556 linkNode.AppendChild(text(altContent))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
557 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
558 // links cannot contain other links, so turn off link parsing
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
559 // temporarily and recurse
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
560 insideLink := p.insideLink
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
561 p.insideLink = true
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
562 p.inline(linkNode, data[1:txtE])
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
563 p.insideLink = insideLink
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
564 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
565
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
566 case linkImg:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
567 linkNode = NewNode(Image)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
568 linkNode.Destination = uLink
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
569 linkNode.Title = title
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
570 linkNode.AppendChild(text(data[1:txtE]))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
571 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
572
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
573 case linkInlineFootnote, linkDeferredFootnote:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
574 linkNode = NewNode(Link)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
575 linkNode.Destination = link
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
576 linkNode.Title = title
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
577 linkNode.NoteID = noteID
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
578 linkNode.Footnote = footnoteNode
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
579 if t == linkInlineFootnote {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
580 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
581 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
582
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
583 default:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
584 return 0, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
585 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
586
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
587 return i, linkNode
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
588 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
589
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
590 func (p *Markdown) inlineHTMLComment(data []byte) int {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
591 if len(data) < 5 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
592 return 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
593 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
594 if data[0] != '<' || data[1] != '!' || data[2] != '-' || data[3] != '-' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
595 return 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
596 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
597 i := 5
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
598 // scan for an end-of-comment marker, across lines if necessary
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
599 for i < len(data) && !(data[i-2] == '-' && data[i-1] == '-' && data[i] == '>') {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
600 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
601 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
602 // no end-of-comment marker
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
603 if i >= len(data) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
604 return 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
605 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
606 return i + 1
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
607 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
608
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
609 func stripMailto(link []byte) []byte {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
610 if bytes.HasPrefix(link, []byte("mailto://")) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
611 return link[9:]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
612 } else if bytes.HasPrefix(link, []byte("mailto:")) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
613 return link[7:]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
614 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
615 return link
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
616 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
617 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
618
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
619 // autolinkType specifies a kind of autolink that gets detected.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
620 type autolinkType int
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
621
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
622 // These are the possible flag values for the autolink renderer.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
623 const (
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
624 notAutolink autolinkType = iota
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
625 normalAutolink
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
626 emailAutolink
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
627 )
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
628
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
629 // '<' when tags or autolinks are allowed
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
630 func leftAngle(p *Markdown, data []byte, offset int) (int, *Node) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
631 data = data[offset:]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
632 altype, end := tagLength(data)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
633 if size := p.inlineHTMLComment(data); size > 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
634 end = size
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
635 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
636 if end > 2 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
637 if altype != notAutolink {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
638 var uLink bytes.Buffer
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
639 unescapeText(&uLink, data[1:end+1-2])
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
640 if uLink.Len() > 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
641 link := uLink.Bytes()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
642 node := NewNode(Link)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
643 node.Destination = link
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
644 if altype == emailAutolink {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
645 node.Destination = append([]byte("mailto:"), link...)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
646 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
647 node.AppendChild(text(stripMailto(link)))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
648 return end, node
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
649 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
650 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
651 htmlTag := NewNode(HTMLSpan)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
652 htmlTag.Literal = data[:end]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
653 return end, htmlTag
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
654 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
655 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
656
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
657 return end, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
658 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
659
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
660 // '\\' backslash escape
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
661 var escapeChars = []byte("\\`*_{}[]()#+-.!:|&<>~")
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
662
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
663 func escape(p *Markdown, data []byte, offset int) (int, *Node) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
664 data = data[offset:]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
665
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
666 if len(data) > 1 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
667 if p.extensions&BackslashLineBreak != 0 && data[1] == '\n' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
668 return 2, NewNode(Hardbreak)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
669 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
670 if bytes.IndexByte(escapeChars, data[1]) < 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
671 return 0, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
672 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
673
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
674 return 2, text(data[1:2])
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
675 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
676
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
677 return 2, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
678 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
679
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
680 func unescapeText(ob *bytes.Buffer, src []byte) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
681 i := 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
682 for i < len(src) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
683 org := i
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
684 for i < len(src) && src[i] != '\\' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
685 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
686 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
687
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
688 if i > org {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
689 ob.Write(src[org:i])
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
690 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
691
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
692 if i+1 >= len(src) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
693 break
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
694 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
695
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
696 ob.WriteByte(src[i+1])
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
697 i += 2
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
698 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
699 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
700
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
701 // '&' escaped when it doesn't belong to an entity
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
702 // valid entities are assumed to be anything matching &#?[A-Za-z0-9]+;
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
703 func entity(p *Markdown, data []byte, offset int) (int, *Node) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
704 data = data[offset:]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
705
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
706 end := 1
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
707
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
708 if end < len(data) && data[end] == '#' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
709 end++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
710 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
711
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
712 for end < len(data) && isalnum(data[end]) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
713 end++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
714 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
715
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
716 if end < len(data) && data[end] == ';' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
717 end++ // real entity
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
718 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
719 return 0, nil // lone '&'
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
720 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
721
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
722 ent := data[:end]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
723 // undo &amp; escaping or it will be converted to &amp;amp; by another
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
724 // escaper in the renderer
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
725 if bytes.Equal(ent, []byte("&amp;")) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
726 ent = []byte{'&'}
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
727 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
728
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
729 return end, text(ent)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
730 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
731
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
732 func linkEndsWithEntity(data []byte, linkEnd int) bool {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
733 entityRanges := htmlEntityRe.FindAllIndex(data[:linkEnd], -1)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
734 return entityRanges != nil && entityRanges[len(entityRanges)-1][1] == linkEnd
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
735 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
736
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
737 // hasPrefixCaseInsensitive is a custom implementation of
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
738 // strings.HasPrefix(strings.ToLower(s), prefix)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
739 // we rolled our own because ToLower pulls in a huge machinery of lowercasing
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
740 // anything from Unicode and that's very slow. Since this func will only be
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
741 // used on ASCII protocol prefixes, we can take shortcuts.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
742 func hasPrefixCaseInsensitive(s, prefix []byte) bool {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
743 if len(s) < len(prefix) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
744 return false
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
745 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
746 delta := byte('a' - 'A')
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
747 for i, b := range prefix {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
748 if b != s[i] && b != s[i]+delta {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
749 return false
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
750 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
751 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
752 return true
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
753 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
754
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
755 var protocolPrefixes = [][]byte{
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
756 []byte("http://"),
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
757 []byte("https://"),
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
758 []byte("ftp://"),
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
759 []byte("file://"),
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
760 []byte("mailto:"),
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
761 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
762
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
763 const shortestPrefix = 6 // len("ftp://"), the shortest of the above
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
764
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
765 func maybeAutoLink(p *Markdown, data []byte, offset int) (int, *Node) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
766 // quick check to rule out most false hits
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
767 if p.insideLink || len(data) < offset+shortestPrefix {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
768 return 0, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
769 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
770 for _, prefix := range protocolPrefixes {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
771 endOfHead := offset + 8 // 8 is the len() of the longest prefix
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
772 if endOfHead > len(data) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
773 endOfHead = len(data)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
774 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
775 if hasPrefixCaseInsensitive(data[offset:endOfHead], prefix) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
776 return autoLink(p, data, offset)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
777 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
778 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
779 return 0, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
780 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
781
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
782 func autoLink(p *Markdown, data []byte, offset int) (int, *Node) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
783 // Now a more expensive check to see if we're not inside an anchor element
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
784 anchorStart := offset
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
785 offsetFromAnchor := 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
786 for anchorStart > 0 && data[anchorStart] != '<' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
787 anchorStart--
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
788 offsetFromAnchor++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
789 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
790
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
791 anchorStr := anchorRe.Find(data[anchorStart:])
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
792 if anchorStr != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
793 anchorClose := NewNode(HTMLSpan)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
794 anchorClose.Literal = anchorStr[offsetFromAnchor:]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
795 return len(anchorStr) - offsetFromAnchor, anchorClose
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
796 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
797
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
798 // scan backward for a word boundary
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
799 rewind := 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
800 for offset-rewind > 0 && rewind <= 7 && isletter(data[offset-rewind-1]) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
801 rewind++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
802 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
803 if rewind > 6 { // longest supported protocol is "mailto" which has 6 letters
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
804 return 0, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
805 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
806
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
807 origData := data
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
808 data = data[offset-rewind:]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
809
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
810 if !isSafeLink(data) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
811 return 0, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
812 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
813
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
814 linkEnd := 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
815 for linkEnd < len(data) && !isEndOfLink(data[linkEnd]) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
816 linkEnd++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
817 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
818
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
819 // Skip punctuation at the end of the link
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
820 if (data[linkEnd-1] == '.' || data[linkEnd-1] == ',') && data[linkEnd-2] != '\\' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
821 linkEnd--
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
822 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
823
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
824 // But don't skip semicolon if it's a part of escaped entity:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
825 if data[linkEnd-1] == ';' && data[linkEnd-2] != '\\' && !linkEndsWithEntity(data, linkEnd) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
826 linkEnd--
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
827 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
828
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
829 // See if the link finishes with a punctuation sign that can be closed.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
830 var copen byte
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
831 switch data[linkEnd-1] {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
832 case '"':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
833 copen = '"'
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
834 case '\'':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
835 copen = '\''
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
836 case ')':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
837 copen = '('
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
838 case ']':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
839 copen = '['
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
840 case '}':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
841 copen = '{'
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
842 default:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
843 copen = 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
844 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
845
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
846 if copen != 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
847 bufEnd := offset - rewind + linkEnd - 2
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
848
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
849 openDelim := 1
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
850
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
851 /* Try to close the final punctuation sign in this same line;
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
852 * if we managed to close it outside of the URL, that means that it's
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
853 * not part of the URL. If it closes inside the URL, that means it
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
854 * is part of the URL.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
855 *
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
856 * Examples:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
857 *
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
858 * foo http://www.pokemon.com/Pikachu_(Electric) bar
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
859 * => http://www.pokemon.com/Pikachu_(Electric)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
860 *
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
861 * foo (http://www.pokemon.com/Pikachu_(Electric)) bar
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
862 * => http://www.pokemon.com/Pikachu_(Electric)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
863 *
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
864 * foo http://www.pokemon.com/Pikachu_(Electric)) bar
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
865 * => http://www.pokemon.com/Pikachu_(Electric))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
866 *
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
867 * (foo http://www.pokemon.com/Pikachu_(Electric)) bar
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
868 * => foo http://www.pokemon.com/Pikachu_(Electric)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
869 */
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
870
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
871 for bufEnd >= 0 && origData[bufEnd] != '\n' && openDelim != 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
872 if origData[bufEnd] == data[linkEnd-1] {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
873 openDelim++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
874 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
875
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
876 if origData[bufEnd] == copen {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
877 openDelim--
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
878 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
879
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
880 bufEnd--
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
881 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
882
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
883 if openDelim == 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
884 linkEnd--
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
885 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
886 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
887
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
888 var uLink bytes.Buffer
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
889 unescapeText(&uLink, data[:linkEnd])
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
890
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
891 if uLink.Len() > 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
892 node := NewNode(Link)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
893 node.Destination = uLink.Bytes()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
894 node.AppendChild(text(uLink.Bytes()))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
895 return linkEnd, node
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
896 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
897
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
898 return linkEnd, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
899 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
900
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
901 func isEndOfLink(char byte) bool {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
902 return isspace(char) || char == '<'
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
903 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
904
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
905 var validUris = [][]byte{[]byte("http://"), []byte("https://"), []byte("ftp://"), []byte("mailto://")}
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
906 var validPaths = [][]byte{[]byte("/"), []byte("./"), []byte("../")}
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
907
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
908 func isSafeLink(link []byte) bool {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
909 for _, path := range validPaths {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
910 if len(link) >= len(path) && bytes.Equal(link[:len(path)], path) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
911 if len(link) == len(path) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
912 return true
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
913 } else if isalnum(link[len(path)]) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
914 return true
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
915 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
916 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
917 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
918
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
919 for _, prefix := range validUris {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
920 // TODO: handle unicode here
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
921 // case-insensitive prefix test
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
922 if len(link) > len(prefix) && bytes.Equal(bytes.ToLower(link[:len(prefix)]), prefix) && isalnum(link[len(prefix)]) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
923 return true
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
924 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
925 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
926
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
927 return false
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
928 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
929
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
930 // return the length of the given tag, or 0 is it's not valid
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
931 func tagLength(data []byte) (autolink autolinkType, end int) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
932 var i, j int
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
933
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
934 // a valid tag can't be shorter than 3 chars
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
935 if len(data) < 3 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
936 return notAutolink, 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
937 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
938
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
939 // begins with a '<' optionally followed by '/', followed by letter or number
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
940 if data[0] != '<' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
941 return notAutolink, 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
942 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
943 if data[1] == '/' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
944 i = 2
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
945 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
946 i = 1
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
947 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
948
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
949 if !isalnum(data[i]) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
950 return notAutolink, 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
951 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
952
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
953 // scheme test
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
954 autolink = notAutolink
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
955
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
956 // try to find the beginning of an URI
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
957 for i < len(data) && (isalnum(data[i]) || data[i] == '.' || data[i] == '+' || data[i] == '-') {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
958 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
959 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
960
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
961 if i > 1 && i < len(data) && data[i] == '@' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
962 if j = isMailtoAutoLink(data[i:]); j != 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
963 return emailAutolink, i + j
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
964 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
965 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
966
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
967 if i > 2 && i < len(data) && data[i] == ':' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
968 autolink = normalAutolink
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
969 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
970 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
971
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
972 // complete autolink test: no whitespace or ' or "
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
973 switch {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
974 case i >= len(data):
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
975 autolink = notAutolink
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
976 case autolink != notAutolink:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
977 j = i
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
978
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
979 for i < len(data) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
980 if data[i] == '\\' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
981 i += 2
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
982 } else if data[i] == '>' || data[i] == '\'' || data[i] == '"' || isspace(data[i]) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
983 break
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
984 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
985 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
986 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
987
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
988 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
989
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
990 if i >= len(data) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
991 return autolink, 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
992 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
993 if i > j && data[i] == '>' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
994 return autolink, i + 1
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
995 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
996
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
997 // one of the forbidden chars has been found
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
998 autolink = notAutolink
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
999 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1000 i += bytes.IndexByte(data[i:], '>')
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1001 if i < 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1002 return autolink, 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1003 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1004 return autolink, i + 1
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1005 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1006
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1007 // look for the address part of a mail autolink and '>'
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1008 // this is less strict than the original markdown e-mail address matching
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1009 func isMailtoAutoLink(data []byte) int {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1010 nb := 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1011
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1012 // address is assumed to be: [-@._a-zA-Z0-9]+ with exactly one '@'
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1013 for i := 0; i < len(data); i++ {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1014 if isalnum(data[i]) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1015 continue
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1016 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1017
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1018 switch data[i] {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1019 case '@':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1020 nb++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1021
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1022 case '-', '.', '_':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1023 break
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1024
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1025 case '>':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1026 if nb == 1 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1027 return i + 1
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1028 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1029 return 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1030 default:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1031 return 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1032 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1033 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1034
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1035 return 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1036 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1037
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1038 // look for the next emph char, skipping other constructs
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1039 func helperFindEmphChar(data []byte, c byte) int {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1040 i := 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1041
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1042 for i < len(data) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1043 for i < len(data) && data[i] != c && data[i] != '`' && data[i] != '[' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1044 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1045 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1046 if i >= len(data) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1047 return 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1048 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1049 // do not count escaped chars
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1050 if i != 0 && data[i-1] == '\\' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1051 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1052 continue
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1053 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1054 if data[i] == c {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1055 return i
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1056 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1057
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1058 if data[i] == '`' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1059 // skip a code span
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1060 tmpI := 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1061 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1062 for i < len(data) && data[i] != '`' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1063 if tmpI == 0 && data[i] == c {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1064 tmpI = i
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1065 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1066 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1067 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1068 if i >= len(data) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1069 return tmpI
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1070 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1071 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1072 } else if data[i] == '[' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1073 // skip a link
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1074 tmpI := 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1075 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1076 for i < len(data) && data[i] != ']' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1077 if tmpI == 0 && data[i] == c {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1078 tmpI = i
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1079 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1080 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1081 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1082 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1083 for i < len(data) && (data[i] == ' ' || data[i] == '\n') {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1084 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1085 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1086 if i >= len(data) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1087 return tmpI
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1088 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1089 if data[i] != '[' && data[i] != '(' { // not a link
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1090 if tmpI > 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1091 return tmpI
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1092 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1093 continue
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1094 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1095 cc := data[i]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1096 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1097 for i < len(data) && data[i] != cc {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1098 if tmpI == 0 && data[i] == c {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1099 return i
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1100 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1101 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1102 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1103 if i >= len(data) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1104 return tmpI
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1105 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1106 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1107 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1108 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1109 return 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1110 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1111
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1112 func helperEmphasis(p *Markdown, data []byte, c byte) (int, *Node) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1113 i := 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1114
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1115 // skip one symbol if coming from emph3
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1116 if len(data) > 1 && data[0] == c && data[1] == c {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1117 i = 1
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1118 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1119
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1120 for i < len(data) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1121 length := helperFindEmphChar(data[i:], c)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1122 if length == 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1123 return 0, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1124 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1125 i += length
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1126 if i >= len(data) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1127 return 0, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1128 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1129
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1130 if i+1 < len(data) && data[i+1] == c {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1131 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1132 continue
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1133 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1134
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1135 if data[i] == c && !isspace(data[i-1]) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1136
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1137 if p.extensions&NoIntraEmphasis != 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1138 if !(i+1 == len(data) || isspace(data[i+1]) || ispunct(data[i+1])) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1139 continue
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1140 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1141 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1142
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1143 emph := NewNode(Emph)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1144 p.inline(emph, data[:i])
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1145 return i + 1, emph
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1146 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1147 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1148
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1149 return 0, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1150 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1151
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1152 func helperDoubleEmphasis(p *Markdown, data []byte, c byte) (int, *Node) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1153 i := 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1154
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1155 for i < len(data) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1156 length := helperFindEmphChar(data[i:], c)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1157 if length == 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1158 return 0, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1159 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1160 i += length
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1161
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1162 if i+1 < len(data) && data[i] == c && data[i+1] == c && i > 0 && !isspace(data[i-1]) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1163 nodeType := Strong
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1164 if c == '~' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1165 nodeType = Del
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1166 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1167 node := NewNode(nodeType)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1168 p.inline(node, data[:i])
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1169 return i + 2, node
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1170 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1171 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1172 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1173 return 0, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1174 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1175
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1176 func helperTripleEmphasis(p *Markdown, data []byte, offset int, c byte) (int, *Node) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1177 i := 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1178 origData := data
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1179 data = data[offset:]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1180
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1181 for i < len(data) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1182 length := helperFindEmphChar(data[i:], c)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1183 if length == 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1184 return 0, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1185 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1186 i += length
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1187
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1188 // skip whitespace preceded symbols
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1189 if data[i] != c || isspace(data[i-1]) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1190 continue
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1191 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1192
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1193 switch {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1194 case i+2 < len(data) && data[i+1] == c && data[i+2] == c:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1195 // triple symbol found
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1196 strong := NewNode(Strong)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1197 em := NewNode(Emph)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1198 strong.AppendChild(em)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1199 p.inline(em, data[:i])
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1200 return i + 3, strong
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1201 case (i+1 < len(data) && data[i+1] == c):
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1202 // double symbol found, hand over to emph1
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1203 length, node := helperEmphasis(p, origData[offset-2:], c)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1204 if length == 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1205 return 0, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1206 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1207 return length - 2, node
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1208 default:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1209 // single symbol found, hand over to emph2
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1210 length, node := helperDoubleEmphasis(p, origData[offset-1:], c)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1211 if length == 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1212 return 0, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1213 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1214 return length - 1, node
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1215 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1216 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1217 return 0, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1218 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1219
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1220 func text(s []byte) *Node {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1221 node := NewNode(Text)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1222 node.Literal = s
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1223 return node
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1224 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1225
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1226 func normalizeURI(s []byte) []byte {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1227 return s // TODO: implement
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1228 }