mirror of
				https://gitea.com/gitea/tea.git
				synced 2025-10-31 17:25:27 +01:00 
			
		
		
		
	Use glamour and termev to render/colorize content (#181)
Merge branch 'master' into use-glamour select Glamour Theme based on BackgroundColor Merge branch 'master' into use-glamour Merge branch 'master' into use-glamour update termev update go.mod label color colorate use glamour for issue content Vendor: Add glamour Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com> Co-authored-by: 6543 <6543@obermui.de> Reviewed-on: https://gitea.com/gitea/tea/pulls/181 Reviewed-by: techknowlogick <techknowlogick@gitea.io> Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
This commit is contained in:
		
							
								
								
									
										492
									
								
								vendor/github.com/yuin/goldmark/ast/ast.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										492
									
								
								vendor/github.com/yuin/goldmark/ast/ast.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,492 @@ | ||||
| // Package ast defines AST nodes that represent markdown elements. | ||||
| package ast | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"fmt" | ||||
| 	"strings" | ||||
|  | ||||
| 	textm "github.com/yuin/goldmark/text" | ||||
| 	"github.com/yuin/goldmark/util" | ||||
| ) | ||||
|  | ||||
| // A NodeType indicates what type a node belongs to. | ||||
| type NodeType int | ||||
|  | ||||
| const ( | ||||
| 	// TypeBlock indicates that a node is kind of block nodes. | ||||
| 	TypeBlock NodeType = iota + 1 | ||||
| 	// TypeInline indicates that a node is kind of inline nodes. | ||||
| 	TypeInline | ||||
| 	// TypeDocument indicates that a node is kind of document nodes. | ||||
| 	TypeDocument | ||||
| ) | ||||
|  | ||||
| // NodeKind indicates more specific type than NodeType. | ||||
| type NodeKind int | ||||
|  | ||||
| func (k NodeKind) String() string { | ||||
| 	return kindNames[k] | ||||
| } | ||||
|  | ||||
| var kindMax NodeKind | ||||
| var kindNames = []string{""} | ||||
|  | ||||
| // NewNodeKind returns a new Kind value. | ||||
| func NewNodeKind(name string) NodeKind { | ||||
| 	kindMax++ | ||||
| 	kindNames = append(kindNames, name) | ||||
| 	return kindMax | ||||
| } | ||||
|  | ||||
| // An Attribute is an attribute of the Node | ||||
| type Attribute struct { | ||||
| 	Name  []byte | ||||
| 	Value interface{} | ||||
| } | ||||
|  | ||||
| var attrNameIDS = []byte("#") | ||||
| var attrNameID = []byte("id") | ||||
| var attrNameClassS = []byte(".") | ||||
| var attrNameClass = []byte("class") | ||||
|  | ||||
| // A Node interface defines basic AST node functionalities. | ||||
| type Node interface { | ||||
| 	// Type returns a type of this node. | ||||
| 	Type() NodeType | ||||
|  | ||||
| 	// Kind returns a kind of this node. | ||||
| 	Kind() NodeKind | ||||
|  | ||||
| 	// NextSibling returns a next sibling node of this node. | ||||
| 	NextSibling() Node | ||||
|  | ||||
| 	// PreviousSibling returns a previous sibling node of this node. | ||||
| 	PreviousSibling() Node | ||||
|  | ||||
| 	// Parent returns a parent node of this node. | ||||
| 	Parent() Node | ||||
|  | ||||
| 	// SetParent sets a parent node to this node. | ||||
| 	SetParent(Node) | ||||
|  | ||||
| 	// SetPreviousSibling sets a previous sibling node to this node. | ||||
| 	SetPreviousSibling(Node) | ||||
|  | ||||
| 	// SetNextSibling sets a next sibling node to this node. | ||||
| 	SetNextSibling(Node) | ||||
|  | ||||
| 	// HasChildren returns true if this node has any children, otherwise false. | ||||
| 	HasChildren() bool | ||||
|  | ||||
| 	// ChildCount returns a total number of children. | ||||
| 	ChildCount() int | ||||
|  | ||||
| 	// FirstChild returns a first child of this node. | ||||
| 	FirstChild() Node | ||||
|  | ||||
| 	// LastChild returns a last child of this node. | ||||
| 	LastChild() Node | ||||
|  | ||||
| 	// AppendChild append a node child to the tail of the children. | ||||
| 	AppendChild(self, child Node) | ||||
|  | ||||
| 	// RemoveChild removes a node child from this node. | ||||
| 	// If a node child is not children of this node, RemoveChild nothing to do. | ||||
| 	RemoveChild(self, child Node) | ||||
|  | ||||
| 	// RemoveChildren removes all children from this node. | ||||
| 	RemoveChildren(self Node) | ||||
|  | ||||
| 	// SortChildren sorts childrens by comparator. | ||||
| 	SortChildren(comparator func(n1, n2 Node) int) | ||||
|  | ||||
| 	// ReplaceChild replace a node v1 with a node insertee. | ||||
| 	// If v1 is not children of this node, ReplaceChild append a insetee to the | ||||
| 	// tail of the children. | ||||
| 	ReplaceChild(self, v1, insertee Node) | ||||
|  | ||||
| 	// InsertBefore inserts a node insertee before a node v1. | ||||
| 	// If v1 is not children of this node, InsertBefore append a insetee to the | ||||
| 	// tail of the children. | ||||
| 	InsertBefore(self, v1, insertee Node) | ||||
|  | ||||
| 	// InsertAfterinserts a node insertee after a node v1. | ||||
| 	// If v1 is not children of this node, InsertBefore append a insetee to the | ||||
| 	// tail of the children. | ||||
| 	InsertAfter(self, v1, insertee Node) | ||||
|  | ||||
| 	// Dump dumps an AST tree structure to stdout. | ||||
| 	// This function completely aimed for debugging. | ||||
| 	// level is a indent level. Implementer should indent informations with | ||||
| 	// 2 * level spaces. | ||||
| 	Dump(source []byte, level int) | ||||
|  | ||||
| 	// Text returns text values of this node. | ||||
| 	Text(source []byte) []byte | ||||
|  | ||||
| 	// HasBlankPreviousLines returns true if the row before this node is blank, | ||||
| 	// otherwise false. | ||||
| 	// This method is valid only for block nodes. | ||||
| 	HasBlankPreviousLines() bool | ||||
|  | ||||
| 	// SetBlankPreviousLines sets whether the row before this node is blank. | ||||
| 	// This method is valid only for block nodes. | ||||
| 	SetBlankPreviousLines(v bool) | ||||
|  | ||||
| 	// Lines returns text segments that hold positions in a source. | ||||
| 	// This method is valid only for block nodes. | ||||
| 	Lines() *textm.Segments | ||||
|  | ||||
| 	// SetLines sets text segments that hold positions in a source. | ||||
| 	// This method is valid only for block nodes. | ||||
| 	SetLines(*textm.Segments) | ||||
|  | ||||
| 	// IsRaw returns true if contents should be rendered as 'raw' contents. | ||||
| 	IsRaw() bool | ||||
|  | ||||
| 	// SetAttribute sets the given value to the attributes. | ||||
| 	SetAttribute(name []byte, value interface{}) | ||||
|  | ||||
| 	// SetAttributeString sets the given value to the attributes. | ||||
| 	SetAttributeString(name string, value interface{}) | ||||
|  | ||||
| 	// Attribute returns a (attribute value, true) if an attribute | ||||
| 	// associated with the given name is found, otherwise | ||||
| 	// (nil, false) | ||||
| 	Attribute(name []byte) (interface{}, bool) | ||||
|  | ||||
| 	// AttributeString returns a (attribute value, true) if an attribute | ||||
| 	// associated with the given name is found, otherwise | ||||
| 	// (nil, false) | ||||
| 	AttributeString(name string) (interface{}, bool) | ||||
|  | ||||
| 	// Attributes returns a list of attributes. | ||||
| 	// This may be a nil if there are no attributes. | ||||
| 	Attributes() []Attribute | ||||
|  | ||||
| 	// RemoveAttributes removes all attributes from this node. | ||||
| 	RemoveAttributes() | ||||
| } | ||||
|  | ||||
| // A BaseNode struct implements the Node interface. | ||||
| type BaseNode struct { | ||||
| 	firstChild Node | ||||
| 	lastChild  Node | ||||
| 	parent     Node | ||||
| 	next       Node | ||||
| 	prev       Node | ||||
| 	childCount int | ||||
| 	attributes []Attribute | ||||
| } | ||||
|  | ||||
| func ensureIsolated(v Node) { | ||||
| 	if p := v.Parent(); p != nil { | ||||
| 		p.RemoveChild(p, v) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // HasChildren implements Node.HasChildren . | ||||
| func (n *BaseNode) HasChildren() bool { | ||||
| 	return n.firstChild != nil | ||||
| } | ||||
|  | ||||
| // SetPreviousSibling implements Node.SetPreviousSibling . | ||||
| func (n *BaseNode) SetPreviousSibling(v Node) { | ||||
| 	n.prev = v | ||||
| } | ||||
|  | ||||
| // SetNextSibling implements Node.SetNextSibling . | ||||
| func (n *BaseNode) SetNextSibling(v Node) { | ||||
| 	n.next = v | ||||
| } | ||||
|  | ||||
| // PreviousSibling implements Node.PreviousSibling . | ||||
| func (n *BaseNode) PreviousSibling() Node { | ||||
| 	return n.prev | ||||
| } | ||||
|  | ||||
| // NextSibling implements Node.NextSibling . | ||||
| func (n *BaseNode) NextSibling() Node { | ||||
| 	return n.next | ||||
| } | ||||
|  | ||||
| // RemoveChild implements Node.RemoveChild . | ||||
| func (n *BaseNode) RemoveChild(self, v Node) { | ||||
| 	if v.Parent() != self { | ||||
| 		return | ||||
| 	} | ||||
| 	n.childCount-- | ||||
| 	prev := v.PreviousSibling() | ||||
| 	next := v.NextSibling() | ||||
| 	if prev != nil { | ||||
| 		prev.SetNextSibling(next) | ||||
| 	} else { | ||||
| 		n.firstChild = next | ||||
| 	} | ||||
| 	if next != nil { | ||||
| 		next.SetPreviousSibling(prev) | ||||
| 	} else { | ||||
| 		n.lastChild = prev | ||||
| 	} | ||||
| 	v.SetParent(nil) | ||||
| 	v.SetPreviousSibling(nil) | ||||
| 	v.SetNextSibling(nil) | ||||
| } | ||||
|  | ||||
| // RemoveChildren implements Node.RemoveChildren . | ||||
| func (n *BaseNode) RemoveChildren(self Node) { | ||||
| 	for c := n.firstChild; c != nil; { | ||||
| 		c.SetParent(nil) | ||||
| 		c.SetPreviousSibling(nil) | ||||
| 		next := c.NextSibling() | ||||
| 		c.SetNextSibling(nil) | ||||
| 		c = next | ||||
| 	} | ||||
| 	n.firstChild = nil | ||||
| 	n.lastChild = nil | ||||
| 	n.childCount = 0 | ||||
| } | ||||
|  | ||||
| // SortChildren implements Node.SortChildren | ||||
| func (n *BaseNode) SortChildren(comparator func(n1, n2 Node) int) { | ||||
| 	var sorted Node | ||||
| 	current := n.firstChild | ||||
| 	for current != nil { | ||||
| 		next := current.NextSibling() | ||||
| 		if sorted == nil || comparator(sorted, current) >= 0 { | ||||
| 			current.SetNextSibling(sorted) | ||||
| 			if sorted != nil { | ||||
| 				sorted.SetPreviousSibling(current) | ||||
| 			} | ||||
| 			sorted = current | ||||
| 			sorted.SetPreviousSibling(nil) | ||||
| 		} else { | ||||
| 			c := sorted | ||||
| 			for c.NextSibling() != nil && comparator(c.NextSibling(), current) < 0 { | ||||
| 				c = c.NextSibling() | ||||
| 			} | ||||
| 			current.SetNextSibling(c.NextSibling()) | ||||
| 			current.SetPreviousSibling(c) | ||||
| 			if c.NextSibling() != nil { | ||||
| 				c.NextSibling().SetPreviousSibling(current) | ||||
| 			} | ||||
| 			c.SetNextSibling(current) | ||||
| 		} | ||||
| 		current = next | ||||
| 	} | ||||
| 	n.firstChild = sorted | ||||
| 	for c := n.firstChild; c != nil; c = c.NextSibling() { | ||||
| 		n.lastChild = c | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // FirstChild implements Node.FirstChild . | ||||
| func (n *BaseNode) FirstChild() Node { | ||||
| 	return n.firstChild | ||||
| } | ||||
|  | ||||
| // LastChild implements Node.LastChild . | ||||
| func (n *BaseNode) LastChild() Node { | ||||
| 	return n.lastChild | ||||
| } | ||||
|  | ||||
| // ChildCount implements Node.ChildCount . | ||||
| func (n *BaseNode) ChildCount() int { | ||||
| 	return n.childCount | ||||
| } | ||||
|  | ||||
| // Parent implements Node.Parent . | ||||
| func (n *BaseNode) Parent() Node { | ||||
| 	return n.parent | ||||
| } | ||||
|  | ||||
| // SetParent implements Node.SetParent . | ||||
| func (n *BaseNode) SetParent(v Node) { | ||||
| 	n.parent = v | ||||
| } | ||||
|  | ||||
| // AppendChild implements Node.AppendChild . | ||||
| func (n *BaseNode) AppendChild(self, v Node) { | ||||
| 	ensureIsolated(v) | ||||
| 	if n.firstChild == nil { | ||||
| 		n.firstChild = v | ||||
| 		v.SetNextSibling(nil) | ||||
| 		v.SetPreviousSibling(nil) | ||||
| 	} else { | ||||
| 		last := n.lastChild | ||||
| 		last.SetNextSibling(v) | ||||
| 		v.SetPreviousSibling(last) | ||||
| 	} | ||||
| 	v.SetParent(self) | ||||
| 	n.lastChild = v | ||||
| 	n.childCount++ | ||||
| } | ||||
|  | ||||
| // ReplaceChild implements Node.ReplaceChild . | ||||
| func (n *BaseNode) ReplaceChild(self, v1, insertee Node) { | ||||
| 	n.InsertBefore(self, v1, insertee) | ||||
| 	n.RemoveChild(self, v1) | ||||
| } | ||||
|  | ||||
| // InsertAfter implements Node.InsertAfter . | ||||
| func (n *BaseNode) InsertAfter(self, v1, insertee Node) { | ||||
| 	n.InsertBefore(self, v1.NextSibling(), insertee) | ||||
| } | ||||
|  | ||||
| // InsertBefore implements Node.InsertBefore . | ||||
| func (n *BaseNode) InsertBefore(self, v1, insertee Node) { | ||||
| 	n.childCount++ | ||||
| 	if v1 == nil { | ||||
| 		n.AppendChild(self, insertee) | ||||
| 		return | ||||
| 	} | ||||
| 	ensureIsolated(insertee) | ||||
| 	if v1.Parent() == self { | ||||
| 		c := v1 | ||||
| 		prev := c.PreviousSibling() | ||||
| 		if prev != nil { | ||||
| 			prev.SetNextSibling(insertee) | ||||
| 			insertee.SetPreviousSibling(prev) | ||||
| 		} else { | ||||
| 			n.firstChild = insertee | ||||
| 			insertee.SetPreviousSibling(nil) | ||||
| 		} | ||||
| 		insertee.SetNextSibling(c) | ||||
| 		c.SetPreviousSibling(insertee) | ||||
| 		insertee.SetParent(self) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Text implements Node.Text  . | ||||
| func (n *BaseNode) Text(source []byte) []byte { | ||||
| 	var buf bytes.Buffer | ||||
| 	for c := n.firstChild; c != nil; c = c.NextSibling() { | ||||
| 		buf.Write(c.Text(source)) | ||||
| 	} | ||||
| 	return buf.Bytes() | ||||
| } | ||||
|  | ||||
| // SetAttribute implements Node.SetAttribute. | ||||
| func (n *BaseNode) SetAttribute(name []byte, value interface{}) { | ||||
| 	if n.attributes == nil { | ||||
| 		n.attributes = make([]Attribute, 0, 10) | ||||
| 	} else { | ||||
| 		for i, a := range n.attributes { | ||||
| 			if bytes.Equal(a.Name, name) { | ||||
| 				n.attributes[i].Name = name | ||||
| 				n.attributes[i].Value = value | ||||
| 				return | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	n.attributes = append(n.attributes, Attribute{name, value}) | ||||
| } | ||||
|  | ||||
| // SetAttributeString implements Node.SetAttributeString | ||||
| func (n *BaseNode) SetAttributeString(name string, value interface{}) { | ||||
| 	n.SetAttribute(util.StringToReadOnlyBytes(name), value) | ||||
| } | ||||
|  | ||||
| // Attribute implements Node.Attribute. | ||||
| func (n *BaseNode) Attribute(name []byte) (interface{}, bool) { | ||||
| 	if n.attributes == nil { | ||||
| 		return nil, false | ||||
| 	} | ||||
| 	for i, a := range n.attributes { | ||||
| 		if bytes.Equal(a.Name, name) { | ||||
| 			return n.attributes[i].Value, true | ||||
| 		} | ||||
| 	} | ||||
| 	return nil, false | ||||
| } | ||||
|  | ||||
| // AttributeString implements Node.AttributeString. | ||||
| func (n *BaseNode) AttributeString(s string) (interface{}, bool) { | ||||
| 	return n.Attribute(util.StringToReadOnlyBytes(s)) | ||||
| } | ||||
|  | ||||
| // Attributes implements Node.Attributes | ||||
| func (n *BaseNode) Attributes() []Attribute { | ||||
| 	return n.attributes | ||||
| } | ||||
|  | ||||
| // RemoveAttributes implements Node.RemoveAttributes | ||||
| func (n *BaseNode) RemoveAttributes() { | ||||
| 	n.attributes = nil | ||||
| } | ||||
|  | ||||
| // DumpHelper is a helper function to implement Node.Dump. | ||||
| // kv is pairs of an attribute name and an attribute value. | ||||
| // cb is a function called after wrote a name and attributes. | ||||
| func DumpHelper(v Node, source []byte, level int, kv map[string]string, cb func(int)) { | ||||
| 	name := v.Kind().String() | ||||
| 	indent := strings.Repeat("    ", level) | ||||
| 	fmt.Printf("%s%s {\n", indent, name) | ||||
| 	indent2 := strings.Repeat("    ", level+1) | ||||
| 	if v.Type() == TypeBlock { | ||||
| 		fmt.Printf("%sRawText: \"", indent2) | ||||
| 		for i := 0; i < v.Lines().Len(); i++ { | ||||
| 			line := v.Lines().At(i) | ||||
| 			fmt.Printf("%s", line.Value(source)) | ||||
| 		} | ||||
| 		fmt.Printf("\"\n") | ||||
| 		fmt.Printf("%sHasBlankPreviousLines: %v\n", indent2, v.HasBlankPreviousLines()) | ||||
| 	} | ||||
| 	for name, value := range kv { | ||||
| 		fmt.Printf("%s%s: %s\n", indent2, name, value) | ||||
| 	} | ||||
| 	if cb != nil { | ||||
| 		cb(level + 1) | ||||
| 	} | ||||
| 	for c := v.FirstChild(); c != nil; c = c.NextSibling() { | ||||
| 		c.Dump(source, level+1) | ||||
| 	} | ||||
| 	fmt.Printf("%s}\n", indent) | ||||
| } | ||||
|  | ||||
| // WalkStatus represents a current status of the Walk function. | ||||
| type WalkStatus int | ||||
|  | ||||
| const ( | ||||
| 	// WalkStop indicates no more walking needed. | ||||
| 	WalkStop WalkStatus = iota + 1 | ||||
|  | ||||
| 	// WalkSkipChildren indicates that Walk wont walk on children of current | ||||
| 	// node. | ||||
| 	WalkSkipChildren | ||||
|  | ||||
| 	// WalkContinue indicates that Walk can continue to walk. | ||||
| 	WalkContinue | ||||
| ) | ||||
|  | ||||
| // Walker is a function that will be called when Walk find a | ||||
| // new node. | ||||
| // entering is set true before walks children, false after walked children. | ||||
| // If Walker returns error, Walk function immediately stop walking. | ||||
| type Walker func(n Node, entering bool) (WalkStatus, error) | ||||
|  | ||||
| // Walk walks a AST tree by the depth first search algorithm. | ||||
| func Walk(n Node, walker Walker) error { | ||||
| 	_, err := walkHelper(n, walker) | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| func walkHelper(n Node, walker Walker) (WalkStatus, error) { | ||||
| 	status, err := walker(n, true) | ||||
| 	if err != nil || status == WalkStop { | ||||
| 		return status, err | ||||
| 	} | ||||
| 	if status != WalkSkipChildren { | ||||
| 		for c := n.FirstChild(); c != nil; c = c.NextSibling() { | ||||
| 			if st, err := walkHelper(c, walker); err != nil || st == WalkStop { | ||||
| 				return WalkStop, err | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	status, err = walker(n, false) | ||||
| 	if err != nil || status == WalkStop { | ||||
| 		return WalkStop, err | ||||
| 	} | ||||
| 	return WalkContinue, nil | ||||
| } | ||||
							
								
								
									
										474
									
								
								vendor/github.com/yuin/goldmark/ast/block.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										474
									
								
								vendor/github.com/yuin/goldmark/ast/block.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,474 @@ | ||||
| package ast | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"strings" | ||||
|  | ||||
| 	textm "github.com/yuin/goldmark/text" | ||||
| ) | ||||
|  | ||||
| // A BaseBlock struct implements the Node interface. | ||||
| type BaseBlock struct { | ||||
| 	BaseNode | ||||
| 	blankPreviousLines bool | ||||
| 	lines              *textm.Segments | ||||
| } | ||||
|  | ||||
| // Type implements Node.Type | ||||
| func (b *BaseBlock) Type() NodeType { | ||||
| 	return TypeBlock | ||||
| } | ||||
|  | ||||
| // IsRaw implements Node.IsRaw | ||||
| func (b *BaseBlock) IsRaw() bool { | ||||
| 	return false | ||||
| } | ||||
|  | ||||
| // HasBlankPreviousLines implements Node.HasBlankPreviousLines. | ||||
| func (b *BaseBlock) HasBlankPreviousLines() bool { | ||||
| 	return b.blankPreviousLines | ||||
| } | ||||
|  | ||||
| // SetBlankPreviousLines implements Node.SetBlankPreviousLines. | ||||
| func (b *BaseBlock) SetBlankPreviousLines(v bool) { | ||||
| 	b.blankPreviousLines = v | ||||
| } | ||||
|  | ||||
| // Lines implements Node.Lines | ||||
| func (b *BaseBlock) Lines() *textm.Segments { | ||||
| 	if b.lines == nil { | ||||
| 		b.lines = textm.NewSegments() | ||||
| 	} | ||||
| 	return b.lines | ||||
| } | ||||
|  | ||||
| // SetLines implements Node.SetLines | ||||
| func (b *BaseBlock) SetLines(v *textm.Segments) { | ||||
| 	b.lines = v | ||||
| } | ||||
|  | ||||
| // A Document struct is a root node of Markdown text. | ||||
| type Document struct { | ||||
| 	BaseBlock | ||||
| } | ||||
|  | ||||
| // KindDocument is a NodeKind of the Document node. | ||||
| var KindDocument = NewNodeKind("Document") | ||||
|  | ||||
| // Dump implements Node.Dump . | ||||
| func (n *Document) Dump(source []byte, level int) { | ||||
| 	DumpHelper(n, source, level, nil, nil) | ||||
| } | ||||
|  | ||||
| // Type implements Node.Type . | ||||
| func (n *Document) Type() NodeType { | ||||
| 	return TypeDocument | ||||
| } | ||||
|  | ||||
| // Kind implements Node.Kind. | ||||
| func (n *Document) Kind() NodeKind { | ||||
| 	return KindDocument | ||||
| } | ||||
|  | ||||
| // NewDocument returns a new Document node. | ||||
| func NewDocument() *Document { | ||||
| 	return &Document{ | ||||
| 		BaseBlock: BaseBlock{}, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // A TextBlock struct is a node whose lines | ||||
| // should be rendered without any containers. | ||||
| type TextBlock struct { | ||||
| 	BaseBlock | ||||
| } | ||||
|  | ||||
| // Dump implements Node.Dump . | ||||
| func (n *TextBlock) Dump(source []byte, level int) { | ||||
| 	DumpHelper(n, source, level, nil, nil) | ||||
| } | ||||
|  | ||||
| // KindTextBlock is a NodeKind of the TextBlock node. | ||||
| var KindTextBlock = NewNodeKind("TextBlock") | ||||
|  | ||||
| // Kind implements Node.Kind. | ||||
| func (n *TextBlock) Kind() NodeKind { | ||||
| 	return KindTextBlock | ||||
| } | ||||
|  | ||||
| // NewTextBlock returns a new TextBlock node. | ||||
| func NewTextBlock() *TextBlock { | ||||
| 	return &TextBlock{ | ||||
| 		BaseBlock: BaseBlock{}, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // A Paragraph struct represents a paragraph of Markdown text. | ||||
| type Paragraph struct { | ||||
| 	BaseBlock | ||||
| } | ||||
|  | ||||
| // Dump implements Node.Dump . | ||||
| func (n *Paragraph) Dump(source []byte, level int) { | ||||
| 	DumpHelper(n, source, level, nil, nil) | ||||
| } | ||||
|  | ||||
| // KindParagraph is a NodeKind of the Paragraph node. | ||||
| var KindParagraph = NewNodeKind("Paragraph") | ||||
|  | ||||
| // Kind implements Node.Kind. | ||||
| func (n *Paragraph) Kind() NodeKind { | ||||
| 	return KindParagraph | ||||
| } | ||||
|  | ||||
| // NewParagraph returns a new Paragraph node. | ||||
| func NewParagraph() *Paragraph { | ||||
| 	return &Paragraph{ | ||||
| 		BaseBlock: BaseBlock{}, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // IsParagraph returns true if the given node implements the Paragraph interface, | ||||
| // otherwise false. | ||||
| func IsParagraph(node Node) bool { | ||||
| 	_, ok := node.(*Paragraph) | ||||
| 	return ok | ||||
| } | ||||
|  | ||||
| // A Heading struct represents headings like SetextHeading and ATXHeading. | ||||
| type Heading struct { | ||||
| 	BaseBlock | ||||
| 	// Level returns a level of this heading. | ||||
| 	// This value is between 1 and 6. | ||||
| 	Level int | ||||
| } | ||||
|  | ||||
| // Dump implements Node.Dump . | ||||
| func (n *Heading) Dump(source []byte, level int) { | ||||
| 	m := map[string]string{ | ||||
| 		"Level": fmt.Sprintf("%d", n.Level), | ||||
| 	} | ||||
| 	DumpHelper(n, source, level, m, nil) | ||||
| } | ||||
|  | ||||
| // KindHeading is a NodeKind of the Heading node. | ||||
| var KindHeading = NewNodeKind("Heading") | ||||
|  | ||||
| // Kind implements Node.Kind. | ||||
| func (n *Heading) Kind() NodeKind { | ||||
| 	return KindHeading | ||||
| } | ||||
|  | ||||
| // NewHeading returns a new Heading node. | ||||
| func NewHeading(level int) *Heading { | ||||
| 	return &Heading{ | ||||
| 		BaseBlock: BaseBlock{}, | ||||
| 		Level:     level, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // A ThematicBreak struct represents a thematic break of Markdown text. | ||||
| type ThematicBreak struct { | ||||
| 	BaseBlock | ||||
| } | ||||
|  | ||||
| // Dump implements Node.Dump . | ||||
| func (n *ThematicBreak) Dump(source []byte, level int) { | ||||
| 	DumpHelper(n, source, level, nil, nil) | ||||
| } | ||||
|  | ||||
| // KindThematicBreak is a NodeKind of the ThematicBreak node. | ||||
| var KindThematicBreak = NewNodeKind("ThematicBreak") | ||||
|  | ||||
| // Kind implements Node.Kind. | ||||
| func (n *ThematicBreak) Kind() NodeKind { | ||||
| 	return KindThematicBreak | ||||
| } | ||||
|  | ||||
| // NewThematicBreak returns a new ThematicBreak node. | ||||
| func NewThematicBreak() *ThematicBreak { | ||||
| 	return &ThematicBreak{ | ||||
| 		BaseBlock: BaseBlock{}, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // A CodeBlock interface represents an indented code block of Markdown text. | ||||
| type CodeBlock struct { | ||||
| 	BaseBlock | ||||
| } | ||||
|  | ||||
| // IsRaw implements Node.IsRaw. | ||||
| func (n *CodeBlock) IsRaw() bool { | ||||
| 	return true | ||||
| } | ||||
|  | ||||
| // Dump implements Node.Dump . | ||||
| func (n *CodeBlock) Dump(source []byte, level int) { | ||||
| 	DumpHelper(n, source, level, nil, nil) | ||||
| } | ||||
|  | ||||
| // KindCodeBlock is a NodeKind of the CodeBlock node. | ||||
| var KindCodeBlock = NewNodeKind("CodeBlock") | ||||
|  | ||||
| // Kind implements Node.Kind. | ||||
| func (n *CodeBlock) Kind() NodeKind { | ||||
| 	return KindCodeBlock | ||||
| } | ||||
|  | ||||
| // NewCodeBlock returns a new CodeBlock node. | ||||
| func NewCodeBlock() *CodeBlock { | ||||
| 	return &CodeBlock{ | ||||
| 		BaseBlock: BaseBlock{}, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // A FencedCodeBlock struct represents a fenced code block of Markdown text. | ||||
| type FencedCodeBlock struct { | ||||
| 	BaseBlock | ||||
| 	// Info returns a info text of this fenced code block. | ||||
| 	Info *Text | ||||
|  | ||||
| 	language []byte | ||||
| } | ||||
|  | ||||
| // Language returns an language in an info string. | ||||
| // Language returns nil if this node does not have an info string. | ||||
| func (n *FencedCodeBlock) Language(source []byte) []byte { | ||||
| 	if n.language == nil && n.Info != nil { | ||||
| 		segment := n.Info.Segment | ||||
| 		info := segment.Value(source) | ||||
| 		i := 0 | ||||
| 		for ; i < len(info); i++ { | ||||
| 			if info[i] == ' ' { | ||||
| 				break | ||||
| 			} | ||||
| 		} | ||||
| 		n.language = info[:i] | ||||
| 	} | ||||
| 	return n.language | ||||
| } | ||||
|  | ||||
| // IsRaw implements Node.IsRaw. | ||||
| func (n *FencedCodeBlock) IsRaw() bool { | ||||
| 	return true | ||||
| } | ||||
|  | ||||
| // Dump implements Node.Dump . | ||||
| func (n *FencedCodeBlock) Dump(source []byte, level int) { | ||||
| 	m := map[string]string{} | ||||
| 	if n.Info != nil { | ||||
| 		m["Info"] = fmt.Sprintf("\"%s\"", n.Info.Text(source)) | ||||
| 	} | ||||
| 	DumpHelper(n, source, level, m, nil) | ||||
| } | ||||
|  | ||||
| // KindFencedCodeBlock is a NodeKind of the FencedCodeBlock node. | ||||
| var KindFencedCodeBlock = NewNodeKind("FencedCodeBlock") | ||||
|  | ||||
| // Kind implements Node.Kind. | ||||
| func (n *FencedCodeBlock) Kind() NodeKind { | ||||
| 	return KindFencedCodeBlock | ||||
| } | ||||
|  | ||||
| // NewFencedCodeBlock return a new FencedCodeBlock node. | ||||
| func NewFencedCodeBlock(info *Text) *FencedCodeBlock { | ||||
| 	return &FencedCodeBlock{ | ||||
| 		BaseBlock: BaseBlock{}, | ||||
| 		Info:      info, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // A Blockquote struct represents an blockquote block of Markdown text. | ||||
| type Blockquote struct { | ||||
| 	BaseBlock | ||||
| } | ||||
|  | ||||
| // Dump implements Node.Dump . | ||||
| func (n *Blockquote) Dump(source []byte, level int) { | ||||
| 	DumpHelper(n, source, level, nil, nil) | ||||
| } | ||||
|  | ||||
| // KindBlockquote is a NodeKind of the Blockquote node. | ||||
| var KindBlockquote = NewNodeKind("Blockquote") | ||||
|  | ||||
| // Kind implements Node.Kind. | ||||
| func (n *Blockquote) Kind() NodeKind { | ||||
| 	return KindBlockquote | ||||
| } | ||||
|  | ||||
| // NewBlockquote returns a new Blockquote node. | ||||
| func NewBlockquote() *Blockquote { | ||||
| 	return &Blockquote{ | ||||
| 		BaseBlock: BaseBlock{}, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // A List struct represents a list of Markdown text. | ||||
| type List struct { | ||||
| 	BaseBlock | ||||
|  | ||||
| 	// Marker is a marker character like '-', '+', ')' and '.'. | ||||
| 	Marker byte | ||||
|  | ||||
| 	// IsTight is a true if this list is a 'tight' list. | ||||
| 	// See https://spec.commonmark.org/0.29/#loose for details. | ||||
| 	IsTight bool | ||||
|  | ||||
| 	// Start is an initial number of this ordered list. | ||||
| 	// If this list is not an ordered list, Start is 0. | ||||
| 	Start int | ||||
| } | ||||
|  | ||||
| // IsOrdered returns true if this list is an ordered list, otherwise false. | ||||
| func (l *List) IsOrdered() bool { | ||||
| 	return l.Marker == '.' || l.Marker == ')' | ||||
| } | ||||
|  | ||||
| // CanContinue returns true if this list can continue with | ||||
| // the given mark and a list type, otherwise false. | ||||
| func (l *List) CanContinue(marker byte, isOrdered bool) bool { | ||||
| 	return marker == l.Marker && isOrdered == l.IsOrdered() | ||||
| } | ||||
|  | ||||
| // Dump implements Node.Dump. | ||||
| func (l *List) Dump(source []byte, level int) { | ||||
| 	m := map[string]string{ | ||||
| 		"Ordered": fmt.Sprintf("%v", l.IsOrdered()), | ||||
| 		"Marker":  fmt.Sprintf("%c", l.Marker), | ||||
| 		"Tight":   fmt.Sprintf("%v", l.IsTight), | ||||
| 	} | ||||
| 	if l.IsOrdered() { | ||||
| 		m["Start"] = fmt.Sprintf("%d", l.Start) | ||||
| 	} | ||||
| 	DumpHelper(l, source, level, m, nil) | ||||
| } | ||||
|  | ||||
| // KindList is a NodeKind of the List node. | ||||
| var KindList = NewNodeKind("List") | ||||
|  | ||||
| // Kind implements Node.Kind. | ||||
| func (l *List) Kind() NodeKind { | ||||
| 	return KindList | ||||
| } | ||||
|  | ||||
| // NewList returns a new List node. | ||||
| func NewList(marker byte) *List { | ||||
| 	return &List{ | ||||
| 		BaseBlock: BaseBlock{}, | ||||
| 		Marker:    marker, | ||||
| 		IsTight:   true, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // A ListItem struct represents a list item of Markdown text. | ||||
| type ListItem struct { | ||||
| 	BaseBlock | ||||
|  | ||||
| 	// Offset is an offset position of this item. | ||||
| 	Offset int | ||||
| } | ||||
|  | ||||
| // Dump implements Node.Dump. | ||||
| func (n *ListItem) Dump(source []byte, level int) { | ||||
| 	m := map[string]string{ | ||||
| 		"Offset": fmt.Sprintf("%d", n.Offset), | ||||
| 	} | ||||
| 	DumpHelper(n, source, level, m, nil) | ||||
| } | ||||
|  | ||||
| // KindListItem is a NodeKind of the ListItem node. | ||||
| var KindListItem = NewNodeKind("ListItem") | ||||
|  | ||||
| // Kind implements Node.Kind. | ||||
| func (n *ListItem) Kind() NodeKind { | ||||
| 	return KindListItem | ||||
| } | ||||
|  | ||||
| // NewListItem returns a new ListItem node. | ||||
| func NewListItem(offset int) *ListItem { | ||||
| 	return &ListItem{ | ||||
| 		BaseBlock: BaseBlock{}, | ||||
| 		Offset:    offset, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // HTMLBlockType represents kinds of an html blocks. | ||||
| // See https://spec.commonmark.org/0.29/#html-blocks | ||||
| type HTMLBlockType int | ||||
|  | ||||
| const ( | ||||
| 	// HTMLBlockType1 represents type 1 html blocks | ||||
| 	HTMLBlockType1 HTMLBlockType = iota + 1 | ||||
| 	// HTMLBlockType2 represents type 2 html blocks | ||||
| 	HTMLBlockType2 | ||||
| 	// HTMLBlockType3 represents type 3 html blocks | ||||
| 	HTMLBlockType3 | ||||
| 	// HTMLBlockType4 represents type 4 html blocks | ||||
| 	HTMLBlockType4 | ||||
| 	// HTMLBlockType5 represents type 5 html blocks | ||||
| 	HTMLBlockType5 | ||||
| 	// HTMLBlockType6 represents type 6 html blocks | ||||
| 	HTMLBlockType6 | ||||
| 	// HTMLBlockType7 represents type 7 html blocks | ||||
| 	HTMLBlockType7 | ||||
| ) | ||||
|  | ||||
| // An HTMLBlock struct represents an html block of Markdown text. | ||||
| type HTMLBlock struct { | ||||
| 	BaseBlock | ||||
|  | ||||
| 	// Type is a type of this html block. | ||||
| 	HTMLBlockType HTMLBlockType | ||||
|  | ||||
| 	// ClosureLine is a line that closes this html block. | ||||
| 	ClosureLine textm.Segment | ||||
| } | ||||
|  | ||||
| // IsRaw implements Node.IsRaw. | ||||
| func (n *HTMLBlock) IsRaw() bool { | ||||
| 	return true | ||||
| } | ||||
|  | ||||
| // HasClosure returns true if this html block has a closure line, | ||||
| // otherwise false. | ||||
| func (n *HTMLBlock) HasClosure() bool { | ||||
| 	return n.ClosureLine.Start >= 0 | ||||
| } | ||||
|  | ||||
| // Dump implements Node.Dump. | ||||
| func (n *HTMLBlock) Dump(source []byte, level int) { | ||||
| 	indent := strings.Repeat("    ", level) | ||||
| 	fmt.Printf("%s%s {\n", indent, "HTMLBlock") | ||||
| 	indent2 := strings.Repeat("    ", level+1) | ||||
| 	fmt.Printf("%sRawText: \"", indent2) | ||||
| 	for i := 0; i < n.Lines().Len(); i++ { | ||||
| 		s := n.Lines().At(i) | ||||
| 		fmt.Print(string(source[s.Start:s.Stop])) | ||||
| 	} | ||||
| 	fmt.Printf("\"\n") | ||||
| 	for c := n.FirstChild(); c != nil; c = c.NextSibling() { | ||||
| 		c.Dump(source, level+1) | ||||
| 	} | ||||
| 	if n.HasClosure() { | ||||
| 		cl := n.ClosureLine | ||||
| 		fmt.Printf("%sClosure: \"%s\"\n", indent2, string(cl.Value(source))) | ||||
| 	} | ||||
| 	fmt.Printf("%s}\n", indent) | ||||
| } | ||||
|  | ||||
| // KindHTMLBlock is a NodeKind of the HTMLBlock node. | ||||
| var KindHTMLBlock = NewNodeKind("HTMLBlock") | ||||
|  | ||||
| // Kind implements Node.Kind. | ||||
| func (n *HTMLBlock) Kind() NodeKind { | ||||
| 	return KindHTMLBlock | ||||
| } | ||||
|  | ||||
| // NewHTMLBlock returns a new HTMLBlock node. | ||||
| func NewHTMLBlock(typ HTMLBlockType) *HTMLBlock { | ||||
| 	return &HTMLBlock{ | ||||
| 		BaseBlock:     BaseBlock{}, | ||||
| 		HTMLBlockType: typ, | ||||
| 		ClosureLine:   textm.NewSegment(-1, -1), | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										548
									
								
								vendor/github.com/yuin/goldmark/ast/inline.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										548
									
								
								vendor/github.com/yuin/goldmark/ast/inline.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,548 @@ | ||||
| package ast | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"strings" | ||||
|  | ||||
| 	textm "github.com/yuin/goldmark/text" | ||||
| 	"github.com/yuin/goldmark/util" | ||||
| ) | ||||
|  | ||||
| // A BaseInline struct implements the Node interface. | ||||
| 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.29/#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(), | ||||
| 	} | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 6543
					6543