Blackfriday 是目前Go用的比较多的MD解析库:

import (
    "github.com/microcosm-cc/bluemonday"
    "github.com/russross/blackfriday"
)

// ...
unsafe := blackfriday.Run(input)
html := bluemonday.UGCPolicy().SanitizeBytes(unsafe)

优点是简单,不过比较难以扩展,有一个需求是对markdown文本中的图片节点的链接进行修复,通过对原有的渲染器进行封装,从而实现修复图片地址:

type HTMLRenderer struct {
	PathRepair func([]byte) []byte
	*blackfriday.HTMLRenderer
}

func (r *HTMLRenderer) RenderNode(w io.Writer, node *blackfriday.Node, entering bool) blackfriday.WalkStatus {
	if node.Type == blackfriday.Image {
		node.LinkData.Destination = r.PathRepair(node.LinkData.Destination)
	}
	return r.HTMLRenderer.RenderNode(w, node, entering)
}

// repair是路径修复函数
	r := &HTMLRenderer{PathRepair: repair, HTMLRenderer: blackfriday.NewHTMLRenderer(blackfriday.HTMLRendererParameters{
		Flags: blackfriday.CommonHTMLFlags,
	})}
html := blackfriday.Run(mdContent, blackfriday.WithRenderer(r))

另外一个库是goldmark,将渲染器和解析器分开来,先解析成AST树,然后在渲染,能很好的扩展和定制,还有一些比较棒的插件,比如代码高亮或是数学公式支持,比较推荐使用这个库。

要实现对图片节点进行拦截,修改图片地址的方法是用一个新的行内解析器代替原有的解析器:

type ImageParser struct {
	parser.InlineParser
}

func (i *ImageParser) Parse(parent ast.Node, block text.Reader, pc parser.Context) (node ast.Node) {
	node = i.InlineParser.Parse(parent, block, pc)
	img, ok := node.(*ast.Image)
	if !ok {
		return
	}
    // 此处对图片地址处理
	return img
}
var md = goldmark.New(goldmark.WithParserOptions(parser.WithInlineParsers(util.Prioritized(&ImageParser{parser.NewLinkParser()}, 199)),
	),
)

原有的链接解析器优先权是200,这里插入一个199的解析器代替原有解析器,新的链接解析器对原有解析器结果进行处理。