Skip to content
quarry Artifact [88f2009c4e]
Login

Artifact [88f2009c4e]

Artifact 88f2009c4e25bc113d31492aa927ee91f79188b0dbd53c8eaf0fbfbeed438e75:


package markup

import (
	"bytes"
	"regexp"

	"github.com/yuin/goldmark"
	"github.com/yuin/goldmark/ast"
	"github.com/yuin/goldmark/parser"
	"github.com/yuin/goldmark/text"
	"github.com/yuin/goldmark/util"
)

// fossilBlockTag is what fossil's markdown takes as the start of an HTML
// block: <html>, <pre> or <script>, a comment, or <hr> (block_tags and
// parse_htmlblock in src/markdown.c).
var fossilBlockTag = regexp.MustCompile(`(?i)^ {0,3}<(?:(?:html|pre|script)[\s>]|!--|hr[\s/>])`)

// fossilHTMLBlocks is goldmark's HTML block parser, narrowed to the
// blocks fossil's markdown has. Any other tag — a <table>, a <div> — is
// inline HTML in a paragraph there, so the markdown between the tags is
// rendered: a forum post laying a formula out in a table writes `x` in
// its cells and means code. CommonMark makes such a tag a raw block,
// and the post showed its backticks. And as in fossil, only a blank
// line, a heading, a rule or a list item ends a paragraph, never a tag.
type fossilHTMLBlocks struct{ parser.BlockParser }

func (p fossilHTMLBlocks) Open(parent ast.Node, reader text.Reader, pc parser.Context) (ast.Node, parser.State) {
	line, _ := reader.PeekLine()
	if !fossilBlockTag.Match(bytes.TrimRight(line, "\r\n")) {
		return nil, parser.NoChildren
	}
	return p.BlockParser.Open(parent, reader, pc)
}

func (fossilHTMLBlocks) CanInterruptParagraph() bool { return false }

// fossilParser is goldmark's default parser with fossil's HTML blocks.
func fossilParser() goldmark.Option {
	blocks := parser.DefaultBlockParsers()
	for i, b := range blocks {
		if b.Priority == 900 { // NewHTMLBlockParser, per DefaultBlockParsers
			blocks[i] = util.Prioritized(fossilHTMLBlocks{parser.NewHTMLBlockParser()}, 900)
		}
	}
	return goldmark.WithParser(parser.NewParser(parser.WithBlockParsers(blocks...),
		parser.WithInlineParsers(parser.DefaultInlineParsers()...),
		parser.WithParagraphTransformers(parser.DefaultParagraphTransformers()...)))
}