1
2 package ast
3
4 import (
5 "bytes"
6 "fmt"
7 "strings"
8
9 textm "github.com/yuin/goldmark/text"
10 "github.com/yuin/goldmark/util"
11 )
12
13
14 type NodeType int
15
16 const (
17
18 TypeBlock NodeType = iota + 1
19
20 TypeInline
21
22 TypeDocument
23 )
24
25
26 type NodeKind int
27
28 func (k NodeKind) String() string {
29 return kindNames[k]
30 }
31
32 var kindMax NodeKind
33 var kindNames = []string{""}
34
35
36 func NewNodeKind(name string) NodeKind {
37 kindMax++
38 kindNames = append(kindNames, name)
39 return kindMax
40 }
41
42
43 type Attribute struct {
44 Name []byte
45 Value interface{}
46 }
47
48
49 type Node interface {
50
51 Type() NodeType
52
53
54 Kind() NodeKind
55
56
57 NextSibling() Node
58
59
60 PreviousSibling() Node
61
62
63 Parent() Node
64
65
66 SetParent(Node)
67
68
69 SetPreviousSibling(Node)
70
71
72 SetNextSibling(Node)
73
74
75 HasChildren() bool
76
77
78 ChildCount() int
79
80
81 FirstChild() Node
82
83
84 LastChild() Node
85
86
87 AppendChild(self, child Node)
88
89
90
91 RemoveChild(self, child Node)
92
93
94 RemoveChildren(self Node)
95
96
97 SortChildren(comparator func(n1, n2 Node) int)
98
99
100
101
102 ReplaceChild(self, v1, insertee Node)
103
104
105
106
107 InsertBefore(self, v1, insertee Node)
108
109
110
111
112 InsertAfter(self, v1, insertee Node)
113
114
115
116
117 OwnerDocument() *Document
118
119
120
121
122
123 Dump(source []byte, level int)
124
125
126 Text(source []byte) []byte
127
128
129
130
131 HasBlankPreviousLines() bool
132
133
134
135 SetBlankPreviousLines(v bool)
136
137
138
139 Lines() *textm.Segments
140
141
142
143 SetLines(*textm.Segments)
144
145
146 IsRaw() bool
147
148
149 SetAttribute(name []byte, value interface{})
150
151
152 SetAttributeString(name string, value interface{})
153
154
155
156
157 Attribute(name []byte) (interface{}, bool)
158
159
160
161
162 AttributeString(name string) (interface{}, bool)
163
164
165
166 Attributes() []Attribute
167
168
169 RemoveAttributes()
170 }
171
172
173 type BaseNode struct {
174 firstChild Node
175 lastChild Node
176 parent Node
177 next Node
178 prev Node
179 childCount int
180 attributes []Attribute
181 }
182
183 func ensureIsolated(v Node) {
184 if p := v.Parent(); p != nil {
185 p.RemoveChild(p, v)
186 }
187 }
188
189
190 func (n *BaseNode) HasChildren() bool {
191 return n.firstChild != nil
192 }
193
194
195 func (n *BaseNode) SetPreviousSibling(v Node) {
196 n.prev = v
197 }
198
199
200 func (n *BaseNode) SetNextSibling(v Node) {
201 n.next = v
202 }
203
204
205 func (n *BaseNode) PreviousSibling() Node {
206 return n.prev
207 }
208
209
210 func (n *BaseNode) NextSibling() Node {
211 return n.next
212 }
213
214
215 func (n *BaseNode) RemoveChild(self, v Node) {
216 if v.Parent() != self {
217 return
218 }
219 n.childCount--
220 prev := v.PreviousSibling()
221 next := v.NextSibling()
222 if prev != nil {
223 prev.SetNextSibling(next)
224 } else {
225 n.firstChild = next
226 }
227 if next != nil {
228 next.SetPreviousSibling(prev)
229 } else {
230 n.lastChild = prev
231 }
232 v.SetParent(nil)
233 v.SetPreviousSibling(nil)
234 v.SetNextSibling(nil)
235 }
236
237
238 func (n *BaseNode) RemoveChildren(self Node) {
239 for c := n.firstChild; c != nil; {
240 c.SetParent(nil)
241 c.SetPreviousSibling(nil)
242 next := c.NextSibling()
243 c.SetNextSibling(nil)
244 c = next
245 }
246 n.firstChild = nil
247 n.lastChild = nil
248 n.childCount = 0
249 }
250
251
252 func (n *BaseNode) SortChildren(comparator func(n1, n2 Node) int) {
253 var sorted Node
254 current := n.firstChild
255 for current != nil {
256 next := current.NextSibling()
257 if sorted == nil || comparator(sorted, current) >= 0 {
258 current.SetNextSibling(sorted)
259 if sorted != nil {
260 sorted.SetPreviousSibling(current)
261 }
262 sorted = current
263 sorted.SetPreviousSibling(nil)
264 } else {
265 c := sorted
266 for c.NextSibling() != nil && comparator(c.NextSibling(), current) < 0 {
267 c = c.NextSibling()
268 }
269 current.SetNextSibling(c.NextSibling())
270 current.SetPreviousSibling(c)
271 if c.NextSibling() != nil {
272 c.NextSibling().SetPreviousSibling(current)
273 }
274 c.SetNextSibling(current)
275 }
276 current = next
277 }
278 n.firstChild = sorted
279 for c := n.firstChild; c != nil; c = c.NextSibling() {
280 n.lastChild = c
281 }
282 }
283
284
285 func (n *BaseNode) FirstChild() Node {
286 return n.firstChild
287 }
288
289
290 func (n *BaseNode) LastChild() Node {
291 return n.lastChild
292 }
293
294
295 func (n *BaseNode) ChildCount() int {
296 return n.childCount
297 }
298
299
300 func (n *BaseNode) Parent() Node {
301 return n.parent
302 }
303
304
305 func (n *BaseNode) SetParent(v Node) {
306 n.parent = v
307 }
308
309
310 func (n *BaseNode) AppendChild(self, v Node) {
311 ensureIsolated(v)
312 if n.firstChild == nil {
313 n.firstChild = v
314 v.SetNextSibling(nil)
315 v.SetPreviousSibling(nil)
316 } else {
317 last := n.lastChild
318 last.SetNextSibling(v)
319 v.SetPreviousSibling(last)
320 }
321 v.SetParent(self)
322 n.lastChild = v
323 n.childCount++
324 }
325
326
327 func (n *BaseNode) ReplaceChild(self, v1, insertee Node) {
328 n.InsertBefore(self, v1, insertee)
329 n.RemoveChild(self, v1)
330 }
331
332
333 func (n *BaseNode) InsertAfter(self, v1, insertee Node) {
334 n.InsertBefore(self, v1.NextSibling(), insertee)
335 }
336
337
338 func (n *BaseNode) InsertBefore(self, v1, insertee Node) {
339 n.childCount++
340 if v1 == nil {
341 n.AppendChild(self, insertee)
342 return
343 }
344 ensureIsolated(insertee)
345 if v1.Parent() == self {
346 c := v1
347 prev := c.PreviousSibling()
348 if prev != nil {
349 prev.SetNextSibling(insertee)
350 insertee.SetPreviousSibling(prev)
351 } else {
352 n.firstChild = insertee
353 insertee.SetPreviousSibling(nil)
354 }
355 insertee.SetNextSibling(c)
356 c.SetPreviousSibling(insertee)
357 insertee.SetParent(self)
358 }
359 }
360
361
362 func (n *BaseNode) OwnerDocument() *Document {
363 d := n.Parent()
364 for {
365 p := d.Parent()
366 if p == nil {
367 if v, ok := d.(*Document); ok {
368 return v
369 }
370 break
371 }
372 d = p
373 }
374 return nil
375 }
376
377
378 func (n *BaseNode) Text(source []byte) []byte {
379 var buf bytes.Buffer
380 for c := n.firstChild; c != nil; c = c.NextSibling() {
381 buf.Write(c.Text(source))
382 }
383 return buf.Bytes()
384 }
385
386
387 func (n *BaseNode) SetAttribute(name []byte, value interface{}) {
388 if n.attributes == nil {
389 n.attributes = make([]Attribute, 0, 10)
390 } else {
391 for i, a := range n.attributes {
392 if bytes.Equal(a.Name, name) {
393 n.attributes[i].Name = name
394 n.attributes[i].Value = value
395 return
396 }
397 }
398 }
399 n.attributes = append(n.attributes, Attribute{name, value})
400 }
401
402
403 func (n *BaseNode) SetAttributeString(name string, value interface{}) {
404 n.SetAttribute(util.StringToReadOnlyBytes(name), value)
405 }
406
407
408 func (n *BaseNode) Attribute(name []byte) (interface{}, bool) {
409 if n.attributes == nil {
410 return nil, false
411 }
412 for i, a := range n.attributes {
413 if bytes.Equal(a.Name, name) {
414 return n.attributes[i].Value, true
415 }
416 }
417 return nil, false
418 }
419
420
421 func (n *BaseNode) AttributeString(s string) (interface{}, bool) {
422 return n.Attribute(util.StringToReadOnlyBytes(s))
423 }
424
425
426 func (n *BaseNode) Attributes() []Attribute {
427 return n.attributes
428 }
429
430
431 func (n *BaseNode) RemoveAttributes() {
432 n.attributes = nil
433 }
434
435
436
437
438 func DumpHelper(v Node, source []byte, level int, kv map[string]string, cb func(int)) {
439 name := v.Kind().String()
440 indent := strings.Repeat(" ", level)
441 fmt.Printf("%s%s {\n", indent, name)
442 indent2 := strings.Repeat(" ", level+1)
443 if v.Type() == TypeBlock {
444 fmt.Printf("%sRawText: \"", indent2)
445 for i := 0; i < v.Lines().Len(); i++ {
446 line := v.Lines().At(i)
447 fmt.Printf("%s", line.Value(source))
448 }
449 fmt.Printf("\"\n")
450 fmt.Printf("%sHasBlankPreviousLines: %v\n", indent2, v.HasBlankPreviousLines())
451 }
452 for name, value := range kv {
453 fmt.Printf("%s%s: %s\n", indent2, name, value)
454 }
455 if cb != nil {
456 cb(level + 1)
457 }
458 for c := v.FirstChild(); c != nil; c = c.NextSibling() {
459 c.Dump(source, level+1)
460 }
461 fmt.Printf("%s}\n", indent)
462 }
463
464
465 type WalkStatus int
466
467 const (
468
469 WalkStop WalkStatus = iota + 1
470
471
472
473 WalkSkipChildren
474
475
476 WalkContinue
477 )
478
479
480
481
482
483 type Walker func(n Node, entering bool) (WalkStatus, error)
484
485
486 func Walk(n Node, walker Walker) error {
487 _, err := walkHelper(n, walker)
488 return err
489 }
490
491 func walkHelper(n Node, walker Walker) (WalkStatus, error) {
492 status, err := walker(n, true)
493 if err != nil || status == WalkStop {
494 return status, err
495 }
496 if status != WalkSkipChildren {
497 for c := n.FirstChild(); c != nil; c = c.NextSibling() {
498 if st, err := walkHelper(c, walker); err != nil || st == WalkStop {
499 return WalkStop, err
500 }
501 }
502 }
503 status, err = walker(n, false)
504 if err != nil || status == WalkStop {
505 return WalkStop, err
506 }
507 return WalkContinue, nil
508 }
509
View as plain text