Skip to content
quarry Artifact [6cd577cd2d]
Login

Artifact [6cd577cd2d]

Artifact 6cd577cd2d7196902f99ffe98b546bd923cd2a4946415f8cf759000c779617d5:


package markup

import (
	"bytes"
	"regexp"
)

// brLine is a line holding nothing but a line break tag.
var brLine = regexp.MustCompile(`(?i)^[ \t]*<br[ \t]*/?>[ \t]*$`)

// separateBreaks ends the block at a line that is only <br>. Fossil's
// markdown reads such a line as a paragraph of its own, so the heading
// a forum post writes right under it is a heading. CommonMark opens an
// HTML block there instead, which runs to the next blank line and
// swallows the heading as text. A blank line after the <br> gives the
// fossil reading. Code fences are left as they are.
func separateBreaks(src []byte) []byte {
	if !bytes.Contains(bytes.ToLower(src), []byte("<br")) {
		return src
	}
	lines := bytes.SplitAfter(src, []byte("\n"))
	var out bytes.Buffer
	fence := ""
	for i, l := range lines {
		out.Write(l)
		t := bytes.TrimLeft(l, " ")
		switch {
		case fence != "":
			if bytes.HasPrefix(t, []byte(fence)) {
				fence = ""
			}
			continue
		case bytes.HasPrefix(t, []byte("```")):
			fence = "```"
			continue
		case bytes.HasPrefix(t, []byte("~~~")):
			fence = "~~~"
			continue
		}
		if brLine.Match(bytes.TrimRight(l, "\r\n")) && i+1 < len(lines) &&
			len(bytes.TrimSpace(lines[i+1])) > 0 {
			if !bytes.HasSuffix(l, []byte("\n")) {
				out.WriteByte('\n')
			}
			out.WriteByte('\n')
		}
	}
	return out.Bytes()
}