Source file src/cmd/vendor/rsc.io/markdown/para.go

     1  // Copyright 2021 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package markdown
     6  
     7  import (
     8  	"bytes"
     9  	"strings"
    10  )
    11  
    12  type Empty struct {
    13  	Position
    14  }
    15  
    16  func (b *Empty) PrintHTML(buf *bytes.Buffer) {}
    17  
    18  func (b *Empty) printMarkdown(*bytes.Buffer, mdState) {}
    19  
    20  type Paragraph struct {
    21  	Position
    22  	Text *Text
    23  }
    24  
    25  func (b *Paragraph) PrintHTML(buf *bytes.Buffer) {
    26  	buf.WriteString("<p>")
    27  	b.Text.PrintHTML(buf)
    28  	buf.WriteString("</p>\n")
    29  }
    30  
    31  func (b *Paragraph) printMarkdown(buf *bytes.Buffer, s mdState) {
    32  	// // Ignore prefix when in a list.
    33  	// if s.bullet == 0 {
    34  	// 	buf.WriteString(s.prefix)
    35  	// }
    36  	b.Text.printMarkdown(buf, s)
    37  }
    38  
    39  type paraBuilder struct {
    40  	text  []string
    41  	table *tableBuilder
    42  }
    43  
    44  func (b *paraBuilder) extend(p *parseState, s line) (line, bool) {
    45  	return s, false
    46  }
    47  
    48  func (b *paraBuilder) build(p buildState) Block {
    49  	if b.table != nil {
    50  		return b.table.build(p)
    51  	}
    52  
    53  	s := strings.Join(b.text, "\n")
    54  	for s != "" {
    55  		end, ok := parseLinkRefDef(p, s)
    56  		if !ok {
    57  			break
    58  		}
    59  		s = s[skipSpace(s, end):]
    60  	}
    61  
    62  	if s == "" {
    63  		return &Empty{p.pos()}
    64  	}
    65  
    66  	// Recompute EndLine because a line of b.text
    67  	// might have been taken away to start a table.
    68  	pos := p.pos()
    69  	pos.EndLine = pos.StartLine + len(b.text) - 1
    70  	return &Paragraph{
    71  		pos,
    72  		p.newText(pos, s),
    73  	}
    74  }
    75  
    76  func newPara(p *parseState, s line) (line, bool) {
    77  	// Process paragraph continuation text or start new paragraph.
    78  	b := p.para()
    79  	indented := p.lineDepth == len(p.stack)-2 // fully indented, not playing "pargraph continuation text" games
    80  	text := s.trimSpaceString()
    81  
    82  	if b != nil && b.table != nil {
    83  		if indented && text != "" && text != "|" {
    84  			// Continue table.
    85  			b.table.addRow(text)
    86  			return line{}, true
    87  		}
    88  		// Blank or unindented line ends table.
    89  		// (So does a new block structure, but the caller has checked that already.)
    90  		// So does a line with just a pipe:
    91  		// https://github.com/github/cmark-gfm/pull/127 and
    92  		// https://github.com/github/cmark-gfm/pull/128
    93  		// fixed a buffer overread by rejecting | by itself as a table line.
    94  		// That seems to violate the spec, but we will play along.
    95  		b = nil
    96  	}
    97  
    98  	// If we are looking for tables and this is a table start, start a table.
    99  	if p.Table && b != nil && indented && len(b.text) > 0 && isTableStart(b.text[len(b.text)-1], text) {
   100  		hdr := b.text[len(b.text)-1]
   101  		b.text = b.text[:len(b.text)-1]
   102  		tb := new(paraBuilder)
   103  		p.addBlock(tb)
   104  		tb.table = new(tableBuilder)
   105  		tb.table.start(hdr, text)
   106  		return line{}, true
   107  	}
   108  
   109  	if b != nil {
   110  		for i := p.lineDepth; i < len(p.stack); i++ {
   111  			p.stack[i].pos.EndLine = p.lineno
   112  		}
   113  	} else {
   114  		// Note: Ends anything without a matching prefix.
   115  		b = new(paraBuilder)
   116  		p.addBlock(b)
   117  	}
   118  	b.text = append(b.text, text)
   119  	return line{}, true
   120  }
   121  

View as plain text