package content import ( "bytes" "log" "github.com/yuin/goldmark" "github.com/yuin/goldmark/parser" "github.com/yuin/goldmark/renderer/html" "github.com/yuin/goldmark/util" ) // MarkdownProcessor handles minimal markdown processing // Supports only: **bold**, *italic*, and [link](url) type MarkdownProcessor struct { parser goldmark.Markdown } // NewMarkdownProcessor creates a new markdown processor with minimal configuration func NewMarkdownProcessor() *MarkdownProcessor { // Configure goldmark to only support basic inline formatting md := goldmark.New( goldmark.WithParserOptions( parser.WithInlineParsers( // Bold (**text**) and italic (*text*) - same parser handles both util.Prioritized(parser.NewEmphasisParser(), 500), // Links [text](url) util.Prioritized(parser.NewLinkParser(), 600), ), // Disable all block parsers except paragraph (no headings, lists, etc.) parser.WithBlockParsers( util.Prioritized(parser.NewParagraphParser(), 200), ), ), goldmark.WithRendererOptions( html.WithXHTML(), //
instead of
html.WithHardWraps(), // Line breaks become
html.WithUnsafe(), // Allow existing HTML to pass through ), ) return &MarkdownProcessor{parser: md} } // ToHTML converts markdown string to HTML func (mp *MarkdownProcessor) ToHTML(markdown string) (string, error) { if markdown == "" { return "", nil } var buf bytes.Buffer if err := mp.parser.Convert([]byte(markdown), &buf); err != nil { log.Printf("Markdown conversion failed: %v", err) return "", err } html := buf.String() // Clean up goldmark's paragraph wrapping - we want inline content // Remove

and

tags if the content is wrapped in a single paragraph if len(html) > 7 && html[:3] == "

" && html[len(html)-4:] == "

" { html = html[3 : len(html)-4] } return html, nil }