ast.go

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