mirror of
https://github.com/kovetskiy/mark.git
synced 2026-03-19 17:17:38 +08:00
GenerateMkDocsAdmonitionLevel walked the AST looking for ast.KindBlockquote nodes to build a nesting-level map, but the renderer is registered for parser.KindAdmonition nodes. Because admonition nodes were never added to the map, LevelMap.Level() always returned 0 for every admonition, making the level check in renderMkDocsAdmonition a no-op. The intended behaviour (all admonitions rendered as Confluence structured macros regardless of nesting) was accidentally working because of this bug. Remove the dead MkDocsAdmonitionLevelMap type, GenerateMkDocsAdmonitionLevel function, and LevelMap field, and simplify renderMkDocsAdmonition to directly render the Confluence macro for all known admonition types. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
117 lines
3.3 KiB
Go
117 lines
3.3 KiB
Go
package renderer
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
|
|
parser "github.com/stefanfritsch/goldmark-admonitions"
|
|
"github.com/yuin/goldmark/ast"
|
|
"github.com/yuin/goldmark/renderer"
|
|
"github.com/yuin/goldmark/renderer/html"
|
|
"github.com/yuin/goldmark/util"
|
|
)
|
|
|
|
// HeadingAttributeFilter defines attribute names which heading elements can have
|
|
var MkDocsAdmonitionAttributeFilter = html.GlobalAttributeFilter
|
|
|
|
// A Renderer struct is an implementation of renderer.NodeRenderer that renders
|
|
// nodes as (X)HTML.
|
|
type ConfluenceMkDocsAdmonitionRenderer struct {
|
|
html.Config
|
|
}
|
|
|
|
// NewConfluenceMkDocsAdmonitionRenderer creates a new instance of the ConfluenceRenderer
|
|
func NewConfluenceMkDocsAdmonitionRenderer(opts ...html.Option) renderer.NodeRenderer {
|
|
return &ConfluenceMkDocsAdmonitionRenderer{
|
|
Config: html.NewConfig(),
|
|
}
|
|
}
|
|
|
|
// RegisterFuncs implements NodeRenderer.RegisterFuncs.
|
|
func (r *ConfluenceMkDocsAdmonitionRenderer) RegisterFuncs(reg renderer.NodeRendererFuncRegisterer) {
|
|
reg.Register(parser.KindAdmonition, r.renderMkDocsAdmonition)
|
|
}
|
|
|
|
// Define MkDocsAdmonitionType enum
|
|
type MkDocsAdmonitionType int
|
|
|
|
const (
|
|
AInfo MkDocsAdmonitionType = iota
|
|
ANote
|
|
AWarn
|
|
ATip
|
|
ANone
|
|
)
|
|
|
|
func (t MkDocsAdmonitionType) String() string {
|
|
return []string{"info", "note", "warning", "tip", "none"}[t]
|
|
}
|
|
|
|
func ParseMkDocsAdmonitionType(node ast.Node) MkDocsAdmonitionType {
|
|
n, ok := node.(*parser.Admonition)
|
|
if !ok {
|
|
return ANone
|
|
}
|
|
|
|
switch string(n.AdmonitionClass) {
|
|
case "info":
|
|
return AInfo
|
|
case "note":
|
|
return ANote
|
|
case "warning":
|
|
return AWarn
|
|
case "tip":
|
|
return ATip
|
|
default:
|
|
return ANone
|
|
}
|
|
}
|
|
|
|
// renderMkDocsAdmonition renders an admonition node as a Confluence structured macro.
|
|
// All admonitions (including nested ones) are rendered as Confluence macros.
|
|
func (r *ConfluenceMkDocsAdmonitionRenderer) renderMkDocsAdmonition(writer util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
|
|
n := node.(*parser.Admonition)
|
|
admonitionType := ParseMkDocsAdmonitionType(node)
|
|
|
|
if entering && admonitionType != ANone {
|
|
prefix := fmt.Sprintf("<ac:structured-macro ac:name=\"%s\"><ac:parameter ac:name=\"icon\">true</ac:parameter><ac:rich-text-body>\n", admonitionType)
|
|
if _, err := writer.Write([]byte(prefix)); err != nil {
|
|
return ast.WalkStop, err
|
|
}
|
|
|
|
title, _ := strconv.Unquote(string(n.Title))
|
|
if title != "" {
|
|
titleHTML := fmt.Sprintf("<p><strong>%s</strong></p>\n", title)
|
|
if _, err := writer.Write([]byte(titleHTML)); err != nil {
|
|
return ast.WalkStop, err
|
|
}
|
|
}
|
|
|
|
return ast.WalkContinue, nil
|
|
}
|
|
if !entering && admonitionType != ANone {
|
|
suffix := "</ac:rich-text-body></ac:structured-macro>\n"
|
|
if _, err := writer.Write([]byte(suffix)); err != nil {
|
|
return ast.WalkStop, err
|
|
}
|
|
return ast.WalkContinue, nil
|
|
}
|
|
return r.renderMkDocsAdmon(writer, source, node, entering)
|
|
}
|
|
|
|
func (r *ConfluenceMkDocsAdmonitionRenderer) renderMkDocsAdmon(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
|
|
n := node.(*parser.Admonition)
|
|
if entering {
|
|
if n.Attributes() != nil {
|
|
_, _ = w.WriteString("<blockquote")
|
|
html.RenderAttributes(w, n, MkDocsAdmonitionAttributeFilter)
|
|
_ = w.WriteByte('>')
|
|
} else {
|
|
_, _ = w.WriteString("<blockquote>\n")
|
|
}
|
|
} else {
|
|
_, _ = w.WriteString("</blockquote>\n")
|
|
}
|
|
return ast.WalkContinue, nil
|
|
}
|