aside.go

 1package parser
 2
 3import (
 4	"bytes"
 5
 6	"github.com/gomarkdown/markdown/ast"
 7)
 8
 9// returns aisde prefix length
10func (p *Parser) asidePrefix(data []byte) int {
11	i := 0
12	n := len(data)
13	for i < 3 && i < n && data[i] == ' ' {
14		i++
15	}
16	if i+1 < n && data[i] == 'A' && data[i+1] == '>' {
17		if i+2 < n && data[i+2] == ' ' {
18			return i + 3
19		}
20		return i + 2
21	}
22	return 0
23}
24
25// aside ends with at least one blank line
26// followed by something without a aside prefix
27func (p *Parser) terminateAside(data []byte, beg, end int) bool {
28	if p.isEmpty(data[beg:]) <= 0 {
29		return false
30	}
31	if end >= len(data) {
32		return true
33	}
34	return p.asidePrefix(data[end:]) == 0 && p.isEmpty(data[end:]) == 0
35}
36
37// parse a aside fragment
38func (p *Parser) aside(data []byte) int {
39	var raw bytes.Buffer
40	beg, end := 0, 0
41	// identical to quote
42	for beg < len(data) {
43		end = beg
44		// Step over whole lines, collecting them. While doing that, check for
45		// fenced code and if one's found, incorporate it altogether,
46		// irregardless of any contents inside it
47		for end < len(data) && data[end] != '\n' {
48			if p.extensions&FencedCode != 0 {
49				if i := p.fencedCodeBlock(data[end:], false); i > 0 {
50					// -1 to compensate for the extra end++ after the loop:
51					end += i - 1
52					break
53				}
54			}
55			end++
56		}
57		end = skipCharN(data, end, '\n', 1)
58		if pre := p.asidePrefix(data[beg:]); pre > 0 {
59			// skip the prefix
60			beg += pre
61		} else if p.terminateAside(data, beg, end) {
62			break
63		}
64		// this line is part of the aside
65		raw.Write(data[beg:end])
66		beg = end
67	}
68
69	block := p.addBlock(&ast.Aside{})
70	p.block(raw.Bytes())
71	p.finalize(block)
72	return end
73}