thematic_break.go

 1package parser
 2
 3import (
 4	"github.com/yuin/goldmark/ast"
 5	"github.com/yuin/goldmark/text"
 6	"github.com/yuin/goldmark/util"
 7)
 8
 9type thematicBreakPraser struct {
10}
11
12var defaultThematicBreakPraser = &thematicBreakPraser{}
13
14// NewThematicBreakParser returns a new BlockParser that
15// parses thematic breaks.
16func NewThematicBreakParser() BlockParser {
17	return defaultThematicBreakPraser
18}
19
20func isThematicBreak(line []byte, offset int) bool {
21	w, pos := util.IndentWidth(line, offset)
22	if w > 3 {
23		return false
24	}
25	mark := byte(0)
26	count := 0
27	for i := pos; i < len(line); i++ {
28		c := line[i]
29		if util.IsSpace(c) {
30			continue
31		}
32		if mark == 0 {
33			mark = c
34			count = 1
35			if mark == '*' || mark == '-' || mark == '_' {
36				continue
37			}
38			return false
39		}
40		if c != mark {
41			return false
42		}
43		count++
44	}
45	return count > 2
46}
47
48func (b *thematicBreakPraser) Trigger() []byte {
49	return []byte{'-', '*', '_'}
50}
51
52func (b *thematicBreakPraser) Open(parent ast.Node, reader text.Reader, pc Context) (ast.Node, State) {
53	line, segment := reader.PeekLine()
54	if isThematicBreak(line, reader.LineOffset()) {
55		reader.Advance(segment.Len() - 1)
56		return ast.NewThematicBreak(), NoChildren
57	}
58	return nil, NoChildren
59}
60
61func (b *thematicBreakPraser) Continue(node ast.Node, reader text.Reader, pc Context) State {
62	return Close
63}
64
65func (b *thematicBreakPraser) Close(node ast.Node, reader text.Reader, pc Context) {
66	// nothing to do
67}
68
69func (b *thematicBreakPraser) CanInterruptParagraph() bool {
70	return true
71}
72
73func (b *thematicBreakPraser) CanAcceptIndentedLine() bool {
74	return false
75}