...

Source file src/github.com/yuin/goldmark/ast/block.go

Documentation: github.com/yuin/goldmark/ast

     1  package ast
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	textm "github.com/yuin/goldmark/text"
     8  )
     9  
    10  // A BaseBlock struct implements the Node interface partialliy.
    11  type BaseBlock struct {
    12  	BaseNode
    13  	blankPreviousLines bool
    14  	lines              *textm.Segments
    15  }
    16  
    17  // Type implements Node.Type
    18  func (b *BaseBlock) Type() NodeType {
    19  	return TypeBlock
    20  }
    21  
    22  // IsRaw implements Node.IsRaw
    23  func (b *BaseBlock) IsRaw() bool {
    24  	return false
    25  }
    26  
    27  // HasBlankPreviousLines implements Node.HasBlankPreviousLines.
    28  func (b *BaseBlock) HasBlankPreviousLines() bool {
    29  	return b.blankPreviousLines
    30  }
    31  
    32  // SetBlankPreviousLines implements Node.SetBlankPreviousLines.
    33  func (b *BaseBlock) SetBlankPreviousLines(v bool) {
    34  	b.blankPreviousLines = v
    35  }
    36  
    37  // Lines implements Node.Lines
    38  func (b *BaseBlock) Lines() *textm.Segments {
    39  	if b.lines == nil {
    40  		b.lines = textm.NewSegments()
    41  	}
    42  	return b.lines
    43  }
    44  
    45  // SetLines implements Node.SetLines
    46  func (b *BaseBlock) SetLines(v *textm.Segments) {
    47  	b.lines = v
    48  }
    49  
    50  // A Document struct is a root node of Markdown text.
    51  type Document struct {
    52  	BaseBlock
    53  
    54  	meta map[string]interface{}
    55  }
    56  
    57  // KindDocument is a NodeKind of the Document node.
    58  var KindDocument = NewNodeKind("Document")
    59  
    60  // Dump implements Node.Dump .
    61  func (n *Document) Dump(source []byte, level int) {
    62  	DumpHelper(n, source, level, nil, nil)
    63  }
    64  
    65  // Type implements Node.Type .
    66  func (n *Document) Type() NodeType {
    67  	return TypeDocument
    68  }
    69  
    70  // Kind implements Node.Kind.
    71  func (n *Document) Kind() NodeKind {
    72  	return KindDocument
    73  }
    74  
    75  // OwnerDocument implements Node.OwnerDocument
    76  func (n *Document) OwnerDocument() *Document {
    77  	return n
    78  }
    79  
    80  // Meta returns metadata of this document.
    81  func (n *Document) Meta() map[string]interface{} {
    82  	if n.meta == nil {
    83  		n.meta = map[string]interface{}{}
    84  	}
    85  	return n.meta
    86  }
    87  
    88  // SetMeta sets given metadata to this document.
    89  func (n *Document) SetMeta(meta map[string]interface{}) {
    90  	if n.meta == nil {
    91  		n.meta = map[string]interface{}{}
    92  	}
    93  	for k, v := range meta {
    94  		n.meta[k] = v
    95  	}
    96  }
    97  
    98  // AddMeta adds given metadata to this document.
    99  func (n *Document) AddMeta(key string, value interface{}) {
   100  	if n.meta == nil {
   101  		n.meta = map[string]interface{}{}
   102  	}
   103  	n.meta[key] = value
   104  }
   105  
   106  // NewDocument returns a new Document node.
   107  func NewDocument() *Document {
   108  	return &Document{
   109  		BaseBlock: BaseBlock{},
   110  		meta:      nil,
   111  	}
   112  }
   113  
   114  // A TextBlock struct is a node whose lines
   115  // should be rendered without any containers.
   116  type TextBlock struct {
   117  	BaseBlock
   118  }
   119  
   120  // Dump implements Node.Dump .
   121  func (n *TextBlock) Dump(source []byte, level int) {
   122  	DumpHelper(n, source, level, nil, nil)
   123  }
   124  
   125  // KindTextBlock is a NodeKind of the TextBlock node.
   126  var KindTextBlock = NewNodeKind("TextBlock")
   127  
   128  // Kind implements Node.Kind.
   129  func (n *TextBlock) Kind() NodeKind {
   130  	return KindTextBlock
   131  }
   132  
   133  // NewTextBlock returns a new TextBlock node.
   134  func NewTextBlock() *TextBlock {
   135  	return &TextBlock{
   136  		BaseBlock: BaseBlock{},
   137  	}
   138  }
   139  
   140  // A Paragraph struct represents a paragraph of Markdown text.
   141  type Paragraph struct {
   142  	BaseBlock
   143  }
   144  
   145  // Dump implements Node.Dump .
   146  func (n *Paragraph) Dump(source []byte, level int) {
   147  	DumpHelper(n, source, level, nil, nil)
   148  }
   149  
   150  // KindParagraph is a NodeKind of the Paragraph node.
   151  var KindParagraph = NewNodeKind("Paragraph")
   152  
   153  // Kind implements Node.Kind.
   154  func (n *Paragraph) Kind() NodeKind {
   155  	return KindParagraph
   156  }
   157  
   158  // NewParagraph returns a new Paragraph node.
   159  func NewParagraph() *Paragraph {
   160  	return &Paragraph{
   161  		BaseBlock: BaseBlock{},
   162  	}
   163  }
   164  
   165  // IsParagraph returns true if the given node implements the Paragraph interface,
   166  // otherwise false.
   167  func IsParagraph(node Node) bool {
   168  	_, ok := node.(*Paragraph)
   169  	return ok
   170  }
   171  
   172  // A Heading struct represents headings like SetextHeading and ATXHeading.
   173  type Heading struct {
   174  	BaseBlock
   175  	// Level returns a level of this heading.
   176  	// This value is between 1 and 6.
   177  	Level int
   178  }
   179  
   180  // Dump implements Node.Dump .
   181  func (n *Heading) Dump(source []byte, level int) {
   182  	m := map[string]string{
   183  		"Level": fmt.Sprintf("%d", n.Level),
   184  	}
   185  	DumpHelper(n, source, level, m, nil)
   186  }
   187  
   188  // KindHeading is a NodeKind of the Heading node.
   189  var KindHeading = NewNodeKind("Heading")
   190  
   191  // Kind implements Node.Kind.
   192  func (n *Heading) Kind() NodeKind {
   193  	return KindHeading
   194  }
   195  
   196  // NewHeading returns a new Heading node.
   197  func NewHeading(level int) *Heading {
   198  	return &Heading{
   199  		BaseBlock: BaseBlock{},
   200  		Level:     level,
   201  	}
   202  }
   203  
   204  // A ThematicBreak struct represents a thematic break of Markdown text.
   205  type ThematicBreak struct {
   206  	BaseBlock
   207  }
   208  
   209  // Dump implements Node.Dump .
   210  func (n *ThematicBreak) Dump(source []byte, level int) {
   211  	DumpHelper(n, source, level, nil, nil)
   212  }
   213  
   214  // KindThematicBreak is a NodeKind of the ThematicBreak node.
   215  var KindThematicBreak = NewNodeKind("ThematicBreak")
   216  
   217  // Kind implements Node.Kind.
   218  func (n *ThematicBreak) Kind() NodeKind {
   219  	return KindThematicBreak
   220  }
   221  
   222  // NewThematicBreak returns a new ThematicBreak node.
   223  func NewThematicBreak() *ThematicBreak {
   224  	return &ThematicBreak{
   225  		BaseBlock: BaseBlock{},
   226  	}
   227  }
   228  
   229  // A CodeBlock interface represents an indented code block of Markdown text.
   230  type CodeBlock struct {
   231  	BaseBlock
   232  }
   233  
   234  // IsRaw implements Node.IsRaw.
   235  func (n *CodeBlock) IsRaw() bool {
   236  	return true
   237  }
   238  
   239  // Dump implements Node.Dump .
   240  func (n *CodeBlock) Dump(source []byte, level int) {
   241  	DumpHelper(n, source, level, nil, nil)
   242  }
   243  
   244  // KindCodeBlock is a NodeKind of the CodeBlock node.
   245  var KindCodeBlock = NewNodeKind("CodeBlock")
   246  
   247  // Kind implements Node.Kind.
   248  func (n *CodeBlock) Kind() NodeKind {
   249  	return KindCodeBlock
   250  }
   251  
   252  // NewCodeBlock returns a new CodeBlock node.
   253  func NewCodeBlock() *CodeBlock {
   254  	return &CodeBlock{
   255  		BaseBlock: BaseBlock{},
   256  	}
   257  }
   258  
   259  // A FencedCodeBlock struct represents a fenced code block of Markdown text.
   260  type FencedCodeBlock struct {
   261  	BaseBlock
   262  	// Info returns a info text of this fenced code block.
   263  	Info *Text
   264  
   265  	language []byte
   266  }
   267  
   268  // Language returns an language in an info string.
   269  // Language returns nil if this node does not have an info string.
   270  func (n *FencedCodeBlock) Language(source []byte) []byte {
   271  	if n.language == nil && n.Info != nil {
   272  		segment := n.Info.Segment
   273  		info := segment.Value(source)
   274  		i := 0
   275  		for ; i < len(info); i++ {
   276  			if info[i] == ' ' {
   277  				break
   278  			}
   279  		}
   280  		n.language = info[:i]
   281  	}
   282  	return n.language
   283  }
   284  
   285  // IsRaw implements Node.IsRaw.
   286  func (n *FencedCodeBlock) IsRaw() bool {
   287  	return true
   288  }
   289  
   290  // Dump implements Node.Dump .
   291  func (n *FencedCodeBlock) Dump(source []byte, level int) {
   292  	m := map[string]string{}
   293  	if n.Info != nil {
   294  		m["Info"] = fmt.Sprintf("\"%s\"", n.Info.Text(source))
   295  	}
   296  	DumpHelper(n, source, level, m, nil)
   297  }
   298  
   299  // KindFencedCodeBlock is a NodeKind of the FencedCodeBlock node.
   300  var KindFencedCodeBlock = NewNodeKind("FencedCodeBlock")
   301  
   302  // Kind implements Node.Kind.
   303  func (n *FencedCodeBlock) Kind() NodeKind {
   304  	return KindFencedCodeBlock
   305  }
   306  
   307  // NewFencedCodeBlock return a new FencedCodeBlock node.
   308  func NewFencedCodeBlock(info *Text) *FencedCodeBlock {
   309  	return &FencedCodeBlock{
   310  		BaseBlock: BaseBlock{},
   311  		Info:      info,
   312  	}
   313  }
   314  
   315  // A Blockquote struct represents an blockquote block of Markdown text.
   316  type Blockquote struct {
   317  	BaseBlock
   318  }
   319  
   320  // Dump implements Node.Dump .
   321  func (n *Blockquote) Dump(source []byte, level int) {
   322  	DumpHelper(n, source, level, nil, nil)
   323  }
   324  
   325  // KindBlockquote is a NodeKind of the Blockquote node.
   326  var KindBlockquote = NewNodeKind("Blockquote")
   327  
   328  // Kind implements Node.Kind.
   329  func (n *Blockquote) Kind() NodeKind {
   330  	return KindBlockquote
   331  }
   332  
   333  // NewBlockquote returns a new Blockquote node.
   334  func NewBlockquote() *Blockquote {
   335  	return &Blockquote{
   336  		BaseBlock: BaseBlock{},
   337  	}
   338  }
   339  
   340  // A List struct represents a list of Markdown text.
   341  type List struct {
   342  	BaseBlock
   343  
   344  	// Marker is a marker character like '-', '+', ')' and '.'.
   345  	Marker byte
   346  
   347  	// IsTight is a true if this list is a 'tight' list.
   348  	// See https://spec.commonmark.org/0.30/#loose for details.
   349  	IsTight bool
   350  
   351  	// Start is an initial number of this ordered list.
   352  	// If this list is not an ordered list, Start is 0.
   353  	Start int
   354  }
   355  
   356  // IsOrdered returns true if this list is an ordered list, otherwise false.
   357  func (l *List) IsOrdered() bool {
   358  	return l.Marker == '.' || l.Marker == ')'
   359  }
   360  
   361  // CanContinue returns true if this list can continue with
   362  // the given mark and a list type, otherwise false.
   363  func (l *List) CanContinue(marker byte, isOrdered bool) bool {
   364  	return marker == l.Marker && isOrdered == l.IsOrdered()
   365  }
   366  
   367  // Dump implements Node.Dump.
   368  func (l *List) Dump(source []byte, level int) {
   369  	m := map[string]string{
   370  		"Ordered": fmt.Sprintf("%v", l.IsOrdered()),
   371  		"Marker":  fmt.Sprintf("%c", l.Marker),
   372  		"Tight":   fmt.Sprintf("%v", l.IsTight),
   373  	}
   374  	if l.IsOrdered() {
   375  		m["Start"] = fmt.Sprintf("%d", l.Start)
   376  	}
   377  	DumpHelper(l, source, level, m, nil)
   378  }
   379  
   380  // KindList is a NodeKind of the List node.
   381  var KindList = NewNodeKind("List")
   382  
   383  // Kind implements Node.Kind.
   384  func (l *List) Kind() NodeKind {
   385  	return KindList
   386  }
   387  
   388  // NewList returns a new List node.
   389  func NewList(marker byte) *List {
   390  	return &List{
   391  		BaseBlock: BaseBlock{},
   392  		Marker:    marker,
   393  		IsTight:   true,
   394  	}
   395  }
   396  
   397  // A ListItem struct represents a list item of Markdown text.
   398  type ListItem struct {
   399  	BaseBlock
   400  
   401  	// Offset is an offset position of this item.
   402  	Offset int
   403  }
   404  
   405  // Dump implements Node.Dump.
   406  func (n *ListItem) Dump(source []byte, level int) {
   407  	m := map[string]string{
   408  		"Offset": fmt.Sprintf("%d", n.Offset),
   409  	}
   410  	DumpHelper(n, source, level, m, nil)
   411  }
   412  
   413  // KindListItem is a NodeKind of the ListItem node.
   414  var KindListItem = NewNodeKind("ListItem")
   415  
   416  // Kind implements Node.Kind.
   417  func (n *ListItem) Kind() NodeKind {
   418  	return KindListItem
   419  }
   420  
   421  // NewListItem returns a new ListItem node.
   422  func NewListItem(offset int) *ListItem {
   423  	return &ListItem{
   424  		BaseBlock: BaseBlock{},
   425  		Offset:    offset,
   426  	}
   427  }
   428  
   429  // HTMLBlockType represents kinds of an html blocks.
   430  // See https://spec.commonmark.org/0.30/#html-blocks
   431  type HTMLBlockType int
   432  
   433  const (
   434  	// HTMLBlockType1 represents type 1 html blocks
   435  	HTMLBlockType1 HTMLBlockType = iota + 1
   436  	// HTMLBlockType2 represents type 2 html blocks
   437  	HTMLBlockType2
   438  	// HTMLBlockType3 represents type 3 html blocks
   439  	HTMLBlockType3
   440  	// HTMLBlockType4 represents type 4 html blocks
   441  	HTMLBlockType4
   442  	// HTMLBlockType5 represents type 5 html blocks
   443  	HTMLBlockType5
   444  	// HTMLBlockType6 represents type 6 html blocks
   445  	HTMLBlockType6
   446  	// HTMLBlockType7 represents type 7 html blocks
   447  	HTMLBlockType7
   448  )
   449  
   450  // An HTMLBlock struct represents an html block of Markdown text.
   451  type HTMLBlock struct {
   452  	BaseBlock
   453  
   454  	// Type is a type of this html block.
   455  	HTMLBlockType HTMLBlockType
   456  
   457  	// ClosureLine is a line that closes this html block.
   458  	ClosureLine textm.Segment
   459  }
   460  
   461  // IsRaw implements Node.IsRaw.
   462  func (n *HTMLBlock) IsRaw() bool {
   463  	return true
   464  }
   465  
   466  // HasClosure returns true if this html block has a closure line,
   467  // otherwise false.
   468  func (n *HTMLBlock) HasClosure() bool {
   469  	return n.ClosureLine.Start >= 0
   470  }
   471  
   472  // Dump implements Node.Dump.
   473  func (n *HTMLBlock) Dump(source []byte, level int) {
   474  	indent := strings.Repeat("    ", level)
   475  	fmt.Printf("%s%s {\n", indent, "HTMLBlock")
   476  	indent2 := strings.Repeat("    ", level+1)
   477  	fmt.Printf("%sRawText: \"", indent2)
   478  	for i := 0; i < n.Lines().Len(); i++ {
   479  		s := n.Lines().At(i)
   480  		fmt.Print(string(source[s.Start:s.Stop]))
   481  	}
   482  	fmt.Printf("\"\n")
   483  	for c := n.FirstChild(); c != nil; c = c.NextSibling() {
   484  		c.Dump(source, level+1)
   485  	}
   486  	if n.HasClosure() {
   487  		cl := n.ClosureLine
   488  		fmt.Printf("%sClosure: \"%s\"\n", indent2, string(cl.Value(source)))
   489  	}
   490  	fmt.Printf("%s}\n", indent)
   491  }
   492  
   493  // KindHTMLBlock is a NodeKind of the HTMLBlock node.
   494  var KindHTMLBlock = NewNodeKind("HTMLBlock")
   495  
   496  // Kind implements Node.Kind.
   497  func (n *HTMLBlock) Kind() NodeKind {
   498  	return KindHTMLBlock
   499  }
   500  
   501  // NewHTMLBlock returns a new HTMLBlock node.
   502  func NewHTMLBlock(typ HTMLBlockType) *HTMLBlock {
   503  	return &HTMLBlock{
   504  		BaseBlock:     BaseBlock{},
   505  		HTMLBlockType: typ,
   506  		ClosureLine:   textm.NewSegment(-1, -1),
   507  	}
   508  }
   509  

View as plain text