package render import ( "bytes" "fmt" "regexp" chromahtml "github.com/alecthomas/chroma/v2/formatters/html" "github.com/yuin/goldmark" highlighting "github.com/yuin/goldmark-highlighting/v2" "github.com/yuin/goldmark/extension" "github.com/yuin/goldmark/parser" "github.com/yuin/goldmark/renderer/html" ) var ( md goldmark.Markdown platformRe = regexp.MustCompile("^```(\\w+)\\s+(pico|esp32s3|esp32c3)\\s*$") ) func init() { md = goldmark.New( goldmark.WithExtensions( extension.GFM, highlighting.NewHighlighting( highlighting.WithFormatOptions( chromahtml.WithClasses(true), chromahtml.ClassPrefix("hl-"), ), ), ), goldmark.WithParserOptions( parser.WithAutoHeadingID(), ), goldmark.WithRendererOptions( html.WithUnsafe(), ), ) } // preprocessPlatformBlocks rewrites fenced code blocks tagged with a platform // (e.g. ```cpp pico) into an HTML wrapper div + untagged fence so Goldmark // renders them normally while preserving the data-platform attribute. func preprocessPlatformBlocks(src []byte) []byte { lines := bytes.Split(src, []byte("\n")) var out [][]byte inFence := false platformFence := false for _, line := range lines { trimmed := bytes.TrimSpace(line) if !inFence { if m := platformRe.FindSubmatch(trimmed); m != nil { out = append(out, []byte(fmt.Sprintf(`
`, m[2]))) out = append(out, []byte{}) out = append(out, []byte("```"+string(m[1]))) inFence = true platformFence = true continue } if bytes.HasPrefix(trimmed, []byte("```")) { inFence = true } } else if bytes.Equal(trimmed, []byte("```")) { inFence = false if platformFence { out = append(out, line) out = append(out, []byte{}) out = append(out, []byte("
")) platformFence = false continue } } out = append(out, line) } return bytes.Join(out, []byte("\n")) } func Markdown(src []byte) ([]byte, error) { src = preprocessPlatformBlocks(src) var buf bytes.Buffer if err := md.Convert(src, &buf); err != nil { return nil, err } return buf.Bytes(), nil }