package markdown import ( "bytes" "html/template" "github.com/microcosm-cc/bluemonday" "github.com/yuin/goldmark" highlighting "github.com/yuin/goldmark-highlighting/v2" "github.com/yuin/goldmark/extension" "github.com/yuin/goldmark/renderer/html" ) var ( md goldmark.Markdown policy *bluemonday.Policy ) func init() { md = goldmark.New( goldmark.WithExtensions( extension.GFM, highlighting.NewHighlighting( highlighting.WithStyle("github"), ), ), goldmark.WithRendererOptions( html.WithHardWraps(), ), ) policy = bluemonday.UGCPolicy() policy.AllowAttrs("class").OnElements("code", "pre", "span", "div") policy.AllowAttrs("style").OnElements("span", "pre", "code") } // RenderMarkdown converts markdown text to sanitized HTML. func RenderMarkdown(input string) template.HTML { var buf bytes.Buffer if err := md.Convert([]byte(input), &buf); err != nil { return template.HTML(template.HTMLEscapeString(input)) } sanitized := policy.SanitizeBytes(buf.Bytes()) return template.HTML(sanitized) }