summaryrefslogtreecommitdiff
path: root/vendor/github.com/yuin/goldmark/ast
diff options
context:
space:
mode:
authorLibravatar Autumn! <86073772+autumnull@users.noreply.github.com>2022-12-16 11:20:22 +0000
committerLibravatar GitHub <noreply@github.com>2022-12-16 12:20:22 +0100
commiteb08529f35ce33ed98c34fb48013f0f4a5fc9635 (patch)
tree394fd774a943f5c33ce793c67b5865f2570b46c5 /vendor/github.com/yuin/goldmark/ast
parent[bugfix] use match-sorter for filtering domain blocks (#1270) (diff)
downloadgotosocial-eb08529f35ce33ed98c34fb48013f0f4a5fc9635.tar.xz
[chore/bugfix] Switch markdown from blackfriday to goldmark (#1267)
Co-authored-by: Autumn! <autumnull@posteo.net>
Diffstat (limited to 'vendor/github.com/yuin/goldmark/ast')
-rw-r--r--vendor/github.com/yuin/goldmark/ast/ast.go508
-rw-r--r--vendor/github.com/yuin/goldmark/ast/block.go508
-rw-r--r--vendor/github.com/yuin/goldmark/ast/inline.go548
3 files changed, 1564 insertions, 0 deletions
diff --git a/vendor/github.com/yuin/goldmark/ast/ast.go b/vendor/github.com/yuin/goldmark/ast/ast.go
new file mode 100644
index 000000000..3719ebbd8
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/ast/ast.go
@@ -0,0 +1,508 @@
+// 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{}
+}
+
+// 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)
+
+ // OwnerDocument returns this node's owner document.
+ // If this node is not a child of the Document node, OwnerDocument
+ // returns nil.
+ OwnerDocument() *Document
+
+ // 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 partialliy.
+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)
+ }
+}
+
+// OwnerDocument implements Node.OwnerDocument
+func (n *BaseNode) OwnerDocument() *Document {
+ d := n.Parent()
+ for {
+ p := d.Parent()
+ if p == nil {
+ if v, ok := d.(*Document); ok {
+ return v
+ }
+ break
+ }
+ d = p
+ }
+ return nil
+}
+
+// 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
+}
diff --git a/vendor/github.com/yuin/goldmark/ast/block.go b/vendor/github.com/yuin/goldmark/ast/block.go
new file mode 100644
index 000000000..02e9d5190
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/ast/block.go
@@ -0,0 +1,508 @@
+package ast
+
+import (
+ "fmt"
+ "strings"
+
+ textm "github.com/yuin/goldmark/text"
+)
+
+// A BaseBlock struct implements the Node interface partialliy.
+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
+
+ meta map[string]interface{}
+}
+
+// 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
+}
+
+// OwnerDocument implements Node.OwnerDocument
+func (n *Document) OwnerDocument() *Document {
+ return n
+}
+
+// Meta returns metadata of this document.
+func (n *Document) Meta() map[string]interface{} {
+ if n.meta == nil {
+ n.meta = map[string]interface{}{}
+ }
+ return n.meta
+}
+
+// SetMeta sets given metadata to this document.
+func (n *Document) SetMeta(meta map[string]interface{}) {
+ if n.meta == nil {
+ n.meta = map[string]interface{}{}
+ }
+ for k, v := range meta {
+ n.meta[k] = v
+ }
+}
+
+// AddMeta adds given metadata to this document.
+func (n *Document) AddMeta(key string, value interface{}) {
+ if n.meta == nil {
+ n.meta = map[string]interface{}{}
+ }
+ n.meta[key] = value
+}
+
+// NewDocument returns a new Document node.
+func NewDocument() *Document {
+ return &Document{
+ BaseBlock: BaseBlock{},
+ meta: nil,
+ }
+}
+
+// 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.30/#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.30/#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),
+ }
+}
diff --git a/vendor/github.com/yuin/goldmark/ast/inline.go b/vendor/github.com/yuin/goldmark/ast/inline.go
new file mode 100644
index 000000000..7da098f25
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/ast/inline.go
@@ -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 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 &^ textSoftLineBreak
+ }
+}
+
+// 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(),
+ }
+}