90 lines
2.1 KiB
Go
90 lines
2.1 KiB
Go
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(`<div data-platform="%s">`, 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("</div>"))
|
|
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
|
|
}
|