mark/markdown/markdown.go
Paul.Glesmann 32490b2c90 feat: add Support for converting Material for MkDocs Admonitions to Confluence Info Panels
chore: add test files

fix: add tests for stripnewline and droph1

chore: rename Admontion to MkDocsAdmonition, remove annoying comments

fix: import parser instead of copying the file

chore: rename mkDocs renderer function

fix: fix bug and pipeline

feat: add Support for converting Material for MkDocs Admonitions to Confluence Info Panels

fix: add tests for stripnewline and droph1

chore: rename Admontion to MkDocsAdmonition, remove annoying comments

fix: import parser instead of copying the file

chore: rename mkDocs renderer function

fix: fix bug and pipeline

chore: remove test for droph1 and stripNewLines

fix: add admonitions to StripNewLines and dropH1 tests

feat: add Support for converting Material for MkDocs Admonitions to Confluence Info Panels

fix: add tests for stripnewline and droph1

chore: rename Admontion to MkDocsAdmonition, remove annoying comments

fix: import parser instead of copying the file

chore: rename mkDocs renderer function

fix: fix bug and pipeline

feat: add Support for converting Material for MkDocs Admonitions to Confluence Info Panels

chore: rename Admontion to MkDocsAdmonition, remove annoying comments

fix: import parser instead of copying the file

chore: rename mkDocs renderer function

fix: fix bug and pipeline

chore: remove test for droph1 and stripNewLines

fix: add admonitions to StripNewLines and dropH1 tests

feat: add mkdocsadmonition as opt-in renderer and parser

fix: fix unit tests
2025-06-18 11:14:52 +02:00

118 lines
3.6 KiB
Go

package mark
import (
"bytes"
"slices"
"github.com/kovetskiy/mark/attachment"
cparser "github.com/kovetskiy/mark/parser"
crenderer "github.com/kovetskiy/mark/renderer"
"github.com/kovetskiy/mark/stdlib"
"github.com/kovetskiy/mark/types"
"github.com/reconquest/pkg/log"
mkDocsParser "github.com/stefanfritsch/goldmark-admonitions"
"github.com/yuin/goldmark"
"github.com/yuin/goldmark/extension"
"github.com/yuin/goldmark/parser"
"github.com/yuin/goldmark/renderer"
"github.com/yuin/goldmark/renderer/html"
"github.com/yuin/goldmark/util"
)
// Renderer renders anchor [Node]s.
type ConfluenceExtension struct {
html.Config
Stdlib *stdlib.Lib
Path string
MarkConfig types.MarkConfig
Attachments []attachment.Attachment
}
// NewConfluenceRenderer creates a new instance of the ConfluenceRenderer
func NewConfluenceExtension(stdlib *stdlib.Lib, path string, cfg types.MarkConfig) *ConfluenceExtension {
return &ConfluenceExtension{
Config: html.NewConfig(),
Stdlib: stdlib,
Path: path,
MarkConfig: cfg,
Attachments: []attachment.Attachment{},
}
}
func (c *ConfluenceExtension) Attach(a attachment.Attachment) {
c.Attachments = append(c.Attachments, a)
}
func (c *ConfluenceExtension) Extend(m goldmark.Markdown) {
m.Renderer().AddOptions(renderer.WithNodeRenderers(
util.Prioritized(crenderer.NewConfluenceTextRenderer(c.MarkConfig.StripNewlines), 100),
util.Prioritized(crenderer.NewConfluenceBlockQuoteRenderer(), 100),
util.Prioritized(crenderer.NewConfluenceCodeBlockRenderer(c.Stdlib, c.Path), 100),
util.Prioritized(crenderer.NewConfluenceFencedCodeBlockRenderer(c.Stdlib, c, c.MarkConfig), 100),
util.Prioritized(crenderer.NewConfluenceHTMLBlockRenderer(c.Stdlib), 100),
util.Prioritized(crenderer.NewConfluenceHeadingRenderer(c.MarkConfig.DropFirstH1), 100),
util.Prioritized(crenderer.NewConfluenceImageRenderer(c.Stdlib, c, c.Path), 100),
util.Prioritized(crenderer.NewConfluenceParagraphRenderer(), 100),
util.Prioritized(crenderer.NewConfluenceLinkRenderer(), 100),
))
if slices.Contains(c.MarkConfig.Features, "mkdocsadmonitions") {
m.Parser().AddOptions(
parser.WithBlockParsers(
util.Prioritized(mkDocsParser.NewAdmonitionParser(), 100),
),
)
m.Renderer().AddOptions(renderer.WithNodeRenderers(
util.Prioritized(crenderer.NewConfluenceMkDocsAdmonitionRenderer(), 100),
))
}
m.Parser().AddOptions(parser.WithInlineParsers(
// Must be registered with a higher priority than goldmark's linkParser to make sure goldmark doesn't parse
// the <ac:*/> tags.
util.Prioritized(cparser.NewConfluenceTagParser(), 199),
))
}
func CompileMarkdown(markdown []byte, stdlib *stdlib.Lib, path string, cfg types.MarkConfig) (string, []attachment.Attachment) {
log.Tracef(nil, "rendering markdown:\n%s", string(markdown))
confluenceExtension := NewConfluenceExtension(stdlib, path, cfg)
converter := goldmark.New(
goldmark.WithExtensions(
extension.Footnote,
extension.DefinitionList,
extension.NewTable(
extension.WithTableCellAlignMethod(extension.TableCellAlignStyle),
),
confluenceExtension,
extension.GFM,
),
goldmark.WithParserOptions(
parser.WithAutoHeadingID(),
),
goldmark.WithRendererOptions(
html.WithUnsafe(),
html.WithXHTML(),
))
ctx := parser.NewContext(parser.WithIDs(&cparser.ConfluenceIDs{Values: map[string]bool{}}))
var buf bytes.Buffer
err := converter.Convert(markdown, &buf, parser.WithContext(ctx))
if err != nil {
panic(err)
}
html := buf.Bytes()
log.Tracef(nil, "rendered markdown to html:\n%s", string(html))
return string(html), confluenceExtension.Attachments
}