-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
-
29
-
30
-
31
-
32
-
33
-
34
-
35
-
36
-
37
-
38
-
39
-
40
-
41
-
42
-
43
-
44
-
45
-
46
-
47
-
48
-
49
-
50
-
51
-
52
-
53
-
54
-
55
-
56
-
57
-
58
-
59
-
60
-
61
-
62
-
63
-
64
-
65
-
66
-
67
-
68
-
69
-
70
-
71
-
72
-
73
-
74
-
75
-
76
-
77
-
78
-
79
-
80
-
81
-
82
-
83
-
84
-
85
-
86
-
87
-
88
-
89
-
90
-
91
-
92
-
93
-
94
-
95
-
96
-
97
-
98
-
99
-
100
-
101
-
102
-
103
-
104
-
105
-
106
-
107
-
108
-
109
-
110
-
111
-
112
-
113
-
114
-
115
-
116
-
117
-
118
-
119
-
120
-
121
-
122
-
123
-
124
-
125
-
126
-
127
-
128
-
129
-
130
-
131
-
132
-
133
-
134
-
135
-
136
-
137
-
138
-
139
-
140
-
141
-
142
-
143
-
144
-
145
-
146
-
147
-
148
-
149
-
150
-
151
-
152
-
153
-
154
-
155
-
156
-
157
-
158
-
159
-
160
-
161
-
162
-
163
-
164
-
165
-
166
-
167
-
168
-
169
-
170
-
171
-
172
-
173
-
174
-
175
-
176
-
177
-
178
-
179
-
180
-
181
-
182
-
183
-
184
-
185
-
186
-
187
-
188
-
189
-
190
-
191
-
192
-
193
-
194
-
195
-
196
-
197
-
198
-
199
-
200
-
201
-
202
-
203
-
204
-
205
-
206
-
207
-
208
-
209
-
210
-
211
-
212
-
213
-
214
-
215
-
216
-
217
-
218
-
219
-
220
-
221
-
222
-
223
-
224
-
225
-
226
-
227
-
228
-
229
-
230
-
231
-
232
-
233
-
234
-
235
-
236
-
237
-
238
-
239
-
240
-
241
-
242
-
243
-
244
-
245
-
246
-
247
-
248
-
249
-
250
-
251
-
252
-
253
-
254
-
255
-
256
-
257
-
258
-
259
-
260
-
261
-
262
-
263
-
264
-
265
-
266
-
267
-
268
-
269
-
270
-
271
-
272
-
273
-
274
-
275
-
276
-
277
-
278
-
279
-
280
-
281
-
282
-
283
-
284
-
285
-
286
-
287
-
288
-
289
-
290
-
291
-
292
-
293
-
294
-
295
-
296
-
297
-
298
-
299
-
300
-
301
-
302
-
303
-
304
-
305
-
306
-
307
-
308
-
309
-
310
-
311
-
312
-
313
-
314
-
315
-
316
-
317
-
318
-
319
-
320
-
321
-
322
-
323
-
324
-
325
-
326
-
327
-
328
-
329
-
330
-
331
-
332
-
333
-
334
-
335
-
336
-
337
-
338
-
339
-
340
-
341
-
342
-
343
-
344
-
345
-
346
-
347
-
348
-
349
-
350
-
351
-
352
-
353
-
354
-
355
-
356
-
357
-
358
-
359
-
360
-
361
-
362
-
363
-
364
-
365
-
366
-
367
-
368
-
369
-
370
-
371
-
372
-
373
-
374
-
375
-
376
-
377
-
378
-
379
-
380
-
381
-
382
-
383
-
384
-
385
-
386
-
387
-
388
-
389
-
390
-
391
-
392
-
393
-
394
-
395
-
396
-
397
-
398
-
399
-
400
-
401
-
402
-
403
-
404
-
405
-
406
-
407
-
408
-
409
-
410
-
411
-
412
-
413
-
414
-
415
-
416
-
417
-
418
-
419
-
420
-
421
-
422
-
423
-
424
-
425
-
426
-
427
-
428
-
429
-
430
-
431
-
432
-
433
-
434
-
435
-
436
-
437
-
438
-
439
-
440
-
441
-
442
-
443
-
444
-
445
-
446
-
447
-
448
-
449
-
450
-
451
-
452
-
453
-
454
-
455
-
456
-
457
-
458
-
459
-
460
-
461
-
462
-
463
-
464
-
465
-
466
-
467
-
468
-
469
-
470
-
471
-
472
-
473
-
474
-
475
-
476
-
477
-
478
-
479
-
480
-
481
-
482
-
483
-
484
-
485
-
486
-
487
-
488
-
489
-
490
-
491
-
492
-
493
-
494
-
495
-
496
-
497
-
498
-
499
-
500
-
501
-
502
-
503
-
504
-
505
-
506
-
507
-
508
-
509
-
510
-
511
-
512
-
513
-
514
-
515
-
516
-
517
-
518
-
519
-
520
-
521
-
522
-
523
-
524
-
525
-
526
-
527
-
528
-
529
-
530
-
531
-
532
-
533
-
534
-
535
-
536
-
537
-
538
-
539
-
540
-
541
-
542
-
543
-
544
-
545
-
546
-
547
-
548
package ast
import (
"fmt"
"strings"
textm "github.com/yuin/goldmark/text"
"github.com/yuin/goldmark/util"
)
// A BaseInline struct implements the Node interface partialliy.
type BaseInline struct {
BaseNode
}
// Type implements Node.Type
func (b *BaseInline) Type() NodeType {
return TypeInline
}
// IsRaw implements Node.IsRaw
func (b *BaseInline) IsRaw() bool {
return false
}
// HasBlankPreviousLines implements Node.HasBlankPreviousLines.
func (b *BaseInline) HasBlankPreviousLines() bool {
panic("can not call with inline nodes.")
}
// SetBlankPreviousLines implements Node.SetBlankPreviousLines.
func (b *BaseInline) SetBlankPreviousLines(v bool) {
panic("can not call with inline nodes.")
}
// Lines implements Node.Lines
func (b *BaseInline) Lines() *textm.Segments {
panic("can not call with inline nodes.")
}
// SetLines implements Node.SetLines
func (b *BaseInline) SetLines(v *textm.Segments) {
panic("can not call with inline nodes.")
}
// A Text struct represents a textual content of the Markdown text.
type Text struct {
BaseInline
// Segment is a position in a source text.
Segment textm.Segment
flags uint8
}
const (
textSoftLineBreak = 1 << iota
textHardLineBreak
textRaw
textCode
)
func textFlagsString(flags uint8) string {
buf := []string{}
if flags&textSoftLineBreak != 0 {
buf = append(buf, "SoftLineBreak")
}
if flags&textHardLineBreak != 0 {
buf = append(buf, "HardLineBreak")
}
if flags&textRaw != 0 {
buf = append(buf, "Raw")
}
if flags&textCode != 0 {
buf = append(buf, "Code")
}
return strings.Join(buf, ", ")
}
// Inline implements Inline.Inline.
func (n *Text) Inline() {
}
// SoftLineBreak returns true if this node ends with a new line,
// otherwise false.
func (n *Text) SoftLineBreak() bool {
return n.flags&textSoftLineBreak != 0
}
// SetSoftLineBreak sets whether this node ends with a new line.
func (n *Text) SetSoftLineBreak(v bool) {
if v {
n.flags |= textSoftLineBreak
} else {
n.flags = n.flags &^ textHardLineBreak
}
}
// IsRaw returns true if this text should be rendered without unescaping
// back slash escapes and resolving references.
func (n *Text) IsRaw() bool {
return n.flags&textRaw != 0
}
// SetRaw sets whether this text should be rendered as raw contents.
func (n *Text) SetRaw(v bool) {
if v {
n.flags |= textRaw
} else {
n.flags = n.flags &^ textRaw
}
}
// HardLineBreak returns true if this node ends with a hard line break.
// See https://spec.commonmark.org/0.30/#hard-line-breaks for details.
func (n *Text) HardLineBreak() bool {
return n.flags&textHardLineBreak != 0
}
// SetHardLineBreak sets whether this node ends with a hard line break.
func (n *Text) SetHardLineBreak(v bool) {
if v {
n.flags |= textHardLineBreak
} else {
n.flags = n.flags &^ textHardLineBreak
}
}
// Merge merges a Node n into this node.
// Merge returns true if the given node has been merged, otherwise false.
func (n *Text) Merge(node Node, source []byte) bool {
t, ok := node.(*Text)
if !ok {
return false
}
if n.Segment.Stop != t.Segment.Start || t.Segment.Padding != 0 || source[n.Segment.Stop-1] == '\n' || t.IsRaw() != n.IsRaw() {
return false
}
n.Segment.Stop = t.Segment.Stop
n.SetSoftLineBreak(t.SoftLineBreak())
n.SetHardLineBreak(t.HardLineBreak())
return true
}
// Text implements Node.Text.
func (n *Text) Text(source []byte) []byte {
return n.Segment.Value(source)
}
// Dump implements Node.Dump.
func (n *Text) Dump(source []byte, level int) {
fs := textFlagsString(n.flags)
if len(fs) != 0 {
fs = "(" + fs + ")"
}
fmt.Printf("%sText%s: \"%s\"\n", strings.Repeat(" ", level), fs, strings.TrimRight(string(n.Text(source)), "\n"))
}
// KindText is a NodeKind of the Text node.
var KindText = NewNodeKind("Text")
// Kind implements Node.Kind.
func (n *Text) Kind() NodeKind {
return KindText
}
// NewText returns a new Text node.
func NewText() *Text {
return &Text{
BaseInline: BaseInline{},
}
}
// NewTextSegment returns a new Text node with the given source position.
func NewTextSegment(v textm.Segment) *Text {
return &Text{
BaseInline: BaseInline{},
Segment: v,
}
}
// NewRawTextSegment returns a new Text node with the given source position.
// The new node should be rendered as raw contents.
func NewRawTextSegment(v textm.Segment) *Text {
t := &Text{
BaseInline: BaseInline{},
Segment: v,
}
t.SetRaw(true)
return t
}
// MergeOrAppendTextSegment merges a given s into the last child of the parent if
// it can be merged, otherwise creates a new Text node and appends it to after current
// last child.
func MergeOrAppendTextSegment(parent Node, s textm.Segment) {
last := parent.LastChild()
t, ok := last.(*Text)
if ok && t.Segment.Stop == s.Start && !t.SoftLineBreak() {
t.Segment = t.Segment.WithStop(s.Stop)
} else {
parent.AppendChild(parent, NewTextSegment(s))
}
}
// MergeOrReplaceTextSegment merges a given s into a previous sibling of the node n
// if a previous sibling of the node n is *Text, otherwise replaces Node n with s.
func MergeOrReplaceTextSegment(parent Node, n Node, s textm.Segment) {
prev := n.PreviousSibling()
if t, ok := prev.(*Text); ok && t.Segment.Stop == s.Start && !t.SoftLineBreak() {
t.Segment = t.Segment.WithStop(s.Stop)
parent.RemoveChild(parent, n)
} else {
parent.ReplaceChild(parent, n, NewTextSegment(s))
}
}
// A String struct is a textual content that has a concrete value
type String struct {
BaseInline
Value []byte
flags uint8
}
// Inline implements Inline.Inline.
func (n *String) Inline() {
}
// IsRaw returns true if this text should be rendered without unescaping
// back slash escapes and resolving references.
func (n *String) IsRaw() bool {
return n.flags&textRaw != 0
}
// SetRaw sets whether this text should be rendered as raw contents.
func (n *String) SetRaw(v bool) {
if v {
n.flags |= textRaw
} else {
n.flags = n.flags &^ textRaw
}
}
// IsCode returns true if this text should be rendered without any
// modifications.
func (n *String) IsCode() bool {
return n.flags&textCode != 0
}
// SetCode sets whether this text should be rendered without any modifications.
func (n *String) SetCode(v bool) {
if v {
n.flags |= textCode
} else {
n.flags = n.flags &^ textCode
}
}
// Text implements Node.Text.
func (n *String) Text(source []byte) []byte {
return n.Value
}
// Dump implements Node.Dump.
func (n *String) Dump(source []byte, level int) {
fs := textFlagsString(n.flags)
if len(fs) != 0 {
fs = "(" + fs + ")"
}
fmt.Printf("%sString%s: \"%s\"\n", strings.Repeat(" ", level), fs, strings.TrimRight(string(n.Value), "\n"))
}
// KindString is a NodeKind of the String node.
var KindString = NewNodeKind("String")
// Kind implements Node.Kind.
func (n *String) Kind() NodeKind {
return KindString
}
// NewString returns a new String node.
func NewString(v []byte) *String {
return &String{
Value: v,
}
}
// A CodeSpan struct represents a code span of Markdown text.
type CodeSpan struct {
BaseInline
}
// Inline implements Inline.Inline .
func (n *CodeSpan) Inline() {
}
// IsBlank returns true if this node consists of spaces, otherwise false.
func (n *CodeSpan) IsBlank(source []byte) bool {
for c := n.FirstChild(); c != nil; c = c.NextSibling() {
text := c.(*Text).Segment
if !util.IsBlank(text.Value(source)) {
return false
}
}
return true
}
// Dump implements Node.Dump
func (n *CodeSpan) Dump(source []byte, level int) {
DumpHelper(n, source, level, nil, nil)
}
// KindCodeSpan is a NodeKind of the CodeSpan node.
var KindCodeSpan = NewNodeKind("CodeSpan")
// Kind implements Node.Kind.
func (n *CodeSpan) Kind() NodeKind {
return KindCodeSpan
}
// NewCodeSpan returns a new CodeSpan node.
func NewCodeSpan() *CodeSpan {
return &CodeSpan{
BaseInline: BaseInline{},
}
}
// An Emphasis struct represents an emphasis of Markdown text.
type Emphasis struct {
BaseInline
// Level is a level of the emphasis.
Level int
}
// Dump implements Node.Dump.
func (n *Emphasis) Dump(source []byte, level int) {
m := map[string]string{
"Level": fmt.Sprintf("%v", n.Level),
}
DumpHelper(n, source, level, m, nil)
}
// KindEmphasis is a NodeKind of the Emphasis node.
var KindEmphasis = NewNodeKind("Emphasis")
// Kind implements Node.Kind.
func (n *Emphasis) Kind() NodeKind {
return KindEmphasis
}
// NewEmphasis returns a new Emphasis node with the given level.
func NewEmphasis(level int) *Emphasis {
return &Emphasis{
BaseInline: BaseInline{},
Level: level,
}
}
type baseLink struct {
BaseInline
// Destination is a destination(URL) of this link.
Destination []byte
// Title is a title of this link.
Title []byte
}
// Inline implements Inline.Inline.
func (n *baseLink) Inline() {
}
// A Link struct represents a link of the Markdown text.
type Link struct {
baseLink
}
// Dump implements Node.Dump.
func (n *Link) Dump(source []byte, level int) {
m := map[string]string{}
m["Destination"] = string(n.Destination)
m["Title"] = string(n.Title)
DumpHelper(n, source, level, m, nil)
}
// KindLink is a NodeKind of the Link node.
var KindLink = NewNodeKind("Link")
// Kind implements Node.Kind.
func (n *Link) Kind() NodeKind {
return KindLink
}
// NewLink returns a new Link node.
func NewLink() *Link {
c := &Link{
baseLink: baseLink{
BaseInline: BaseInline{},
},
}
return c
}
// An Image struct represents an image of the Markdown text.
type Image struct {
baseLink
}
// Dump implements Node.Dump.
func (n *Image) Dump(source []byte, level int) {
m := map[string]string{}
m["Destination"] = string(n.Destination)
m["Title"] = string(n.Title)
DumpHelper(n, source, level, m, nil)
}
// KindImage is a NodeKind of the Image node.
var KindImage = NewNodeKind("Image")
// Kind implements Node.Kind.
func (n *Image) Kind() NodeKind {
return KindImage
}
// NewImage returns a new Image node.
func NewImage(link *Link) *Image {
c := &Image{
baseLink: baseLink{
BaseInline: BaseInline{},
},
}
c.Destination = link.Destination
c.Title = link.Title
for n := link.FirstChild(); n != nil; {
next := n.NextSibling()
link.RemoveChild(link, n)
c.AppendChild(c, n)
n = next
}
return c
}
// AutoLinkType defines kind of auto links.
type AutoLinkType int
const (
// AutoLinkEmail indicates that an autolink is an email address.
AutoLinkEmail AutoLinkType = iota + 1
// AutoLinkURL indicates that an autolink is a generic URL.
AutoLinkURL
)
// An AutoLink struct represents an autolink of the Markdown text.
type AutoLink struct {
BaseInline
// Type is a type of this autolink.
AutoLinkType AutoLinkType
// Protocol specified a protocol of the link.
Protocol []byte
value *Text
}
// Inline implements Inline.Inline.
func (n *AutoLink) Inline() {}
// Dump implements Node.Dump
func (n *AutoLink) Dump(source []byte, level int) {
segment := n.value.Segment
m := map[string]string{
"Value": string(segment.Value(source)),
}
DumpHelper(n, source, level, m, nil)
}
// KindAutoLink is a NodeKind of the AutoLink node.
var KindAutoLink = NewNodeKind("AutoLink")
// Kind implements Node.Kind.
func (n *AutoLink) Kind() NodeKind {
return KindAutoLink
}
// URL returns an url of this node.
func (n *AutoLink) URL(source []byte) []byte {
if n.Protocol != nil {
s := n.value.Segment
ret := make([]byte, 0, len(n.Protocol)+s.Len()+3)
ret = append(ret, n.Protocol...)
ret = append(ret, ':', '/', '/')
ret = append(ret, n.value.Text(source)...)
return ret
}
return n.value.Text(source)
}
// Label returns a label of this node.
func (n *AutoLink) Label(source []byte) []byte {
return n.value.Text(source)
}
// NewAutoLink returns a new AutoLink node.
func NewAutoLink(typ AutoLinkType, value *Text) *AutoLink {
return &AutoLink{
BaseInline: BaseInline{},
value: value,
AutoLinkType: typ,
}
}
// A RawHTML struct represents an inline raw HTML of the Markdown text.
type RawHTML struct {
BaseInline
Segments *textm.Segments
}
// Inline implements Inline.Inline.
func (n *RawHTML) Inline() {}
// Dump implements Node.Dump.
func (n *RawHTML) Dump(source []byte, level int) {
m := map[string]string{}
t := []string{}
for i := 0; i < n.Segments.Len(); i++ {
segment := n.Segments.At(i)
t = append(t, string(segment.Value(source)))
}
m["RawText"] = strings.Join(t, "")
DumpHelper(n, source, level, m, nil)
}
// KindRawHTML is a NodeKind of the RawHTML node.
var KindRawHTML = NewNodeKind("RawHTML")
// Kind implements Node.Kind.
func (n *RawHTML) Kind() NodeKind {
return KindRawHTML
}
// NewRawHTML returns a new RawHTML node.
func NewRawHTML() *RawHTML {
return &RawHTML{
Segments: textm.NewSegments(),
}
}