package report import ( "fmt" "html/template" "regexp" "strings" "github.com/gomarkdown/markdown" "github.com/gomarkdown/markdown/html" "github.com/gomarkdown/markdown/parser" ) func mdToHTML(md string) template.HTML { md = markdownCheckboxesToHTML(md) // create markdown parser with extensions extensions := parser.CommonExtensions | parser.AutoHeadingIDs | parser.NoEmptyLineBeforeBlock p := parser.NewWithExtensions(extensions) doc := p.Parse([]byte(md)) // create HTML renderer with extensions htmlFlags := html.CommonFlags | html.HrefTargetBlank opts := html.RendererOptions{Flags: htmlFlags} renderer := html.NewRenderer(opts) return template.HTML(markdown.Render(doc, renderer)) } // markdownCheckboxesToHTML keeps a Markdown list but replaces checkboxes with . func markdownCheckboxesToHTML(markdown string) string { lines := strings.Split(markdown, "\n") checkboxPattern := regexp.MustCompile(`^(\s*[-*]\s+)\[( |x|X)\][\p{Zs}\s]*(.*)$`) for i, line := range lines { if matches := checkboxPattern.FindStringSubmatch(line); matches != nil { prefix := matches[1] // "- " or "* " checked := strings.ToLower(matches[2]) == "x" content := matches[3] // task text if checked { lines[i] = fmt.Sprintf(`%s %s`, prefix, content) } else { lines[i] = fmt.Sprintf(`%s %s`, prefix, content) } } } return strings.Join(lines, "\n") }