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
5package markdown
6
7import (
8	"bytes"
9)
10
11type ThematicBreak struct {
12	Position
13	raw string
14}
15
16func (b *ThematicBreak) PrintHTML(buf *bytes.Buffer) {
17	buf.WriteString("<hr />\n")
18}
19
20func (b *ThematicBreak) printMarkdown(buf *bytes.Buffer, s mdState) {
21	buf.WriteString(s.prefix)
22	buf.WriteString(b.raw)
23	buf.WriteByte('\n')
24}
25
26func newHR(p *parseState, s line) (line, bool) {
27	if isHR(s) {
28		p.doneBlock(&ThematicBreak{Position{p.lineno, p.lineno}, s.string()})
29		return line{}, true
30	}
31	return s, false
32}
33
34func isHR(s line) bool {
35	t := s
36	t.trimSpace(0, 3, false)
37	switch c := t.peek(); c {
38	case '-', '_', '*':
39		for i := 0; ; i++ {
40			if !t.trim(c) {
41				if i >= 3 {
42					break
43				}
44				return false
45			}
46			t.skipSpace()
47		}
48		return t.eof()
49	}
50	return false
51}
52
53type HardBreak struct{}
54
55func (*HardBreak) Inline() {}
56
57func (x *HardBreak) PrintHTML(buf *bytes.Buffer) {
58	buf.WriteString("<br />\n")
59}
60
61func (x *HardBreak) printMarkdown(buf *bytes.Buffer) {
62	buf.WriteString("\\\n")
63}
64
65func (x *HardBreak) PrintText(buf *bytes.Buffer) {
66	buf.WriteString("\n")
67}
68
69type SoftBreak struct{}
70
71func (*SoftBreak) Inline() {}
72
73func (x *SoftBreak) PrintHTML(buf *bytes.Buffer) {
74	buf.WriteString("\n")
75}
76
77func (x *SoftBreak) printMarkdown(buf *bytes.Buffer) {
78	buf.WriteString("\n")
79}
80
81func (x *SoftBreak) PrintText(buf *bytes.Buffer) {
82	buf.WriteString("\n")
83}
84
85func parseBreak(_ *parseState, s string, i int) (Inline, int, int, bool) {
86	start := i
87	for start > 0 && (s[start-1] == ' ' || s[start-1] == '\t') {
88		start--
89	}
90	end := i + 1
91	for end < len(s) && (s[end] == ' ' || s[end] == '\t') {
92		end++
93	}
94	// TODO: Do tabs count? That would be a mess.
95	if i >= 2 && s[i-1] == ' ' && s[i-2] == ' ' {
96		return &HardBreak{}, start, end, true
97	}
98	return &SoftBreak{}, start, end, true
99}
100