fix: remove dead level-map infrastructure in mkDocsAdmonitionRenderer

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>
This commit is contained in:
Manuel Rüger 2026-03-13 02:01:45 +01:00
parent b7c9229da4
commit cf0699c088

View File

@ -18,14 +18,12 @@ var MkDocsAdmonitionAttributeFilter = html.GlobalAttributeFilter
// nodes as (X)HTML.
type ConfluenceMkDocsAdmonitionRenderer struct {
html.Config
LevelMap MkDocsAdmonitionLevelMap
}
// NewConfluenceRenderer creates a new instance of the ConfluenceRenderer
// NewConfluenceMkDocsAdmonitionRenderer creates a new instance of the ConfluenceRenderer
func NewConfluenceMkDocsAdmonitionRenderer(opts ...html.Option) renderer.NodeRenderer {
return &ConfluenceMkDocsAdmonitionRenderer{
Config: html.NewConfig(),
LevelMap: nil,
Config: html.NewConfig(),
}
}
@ -49,12 +47,6 @@ func (t MkDocsAdmonitionType) String() string {
return []string{"info", "note", "warning", "tip", "none"}[t]
}
type MkDocsAdmonitionLevelMap map[ast.Node]int
func (m MkDocsAdmonitionLevelMap) Level(node ast.Node) int {
return m[node]
}
func ParseMkDocsAdmonitionType(node ast.Node) MkDocsAdmonitionType {
n, ok := node.(*parser.Admonition)
if !ok {
@ -75,42 +67,13 @@ func ParseMkDocsAdmonitionType(node ast.Node) MkDocsAdmonitionType {
}
}
// GenerateMkDocsAdmonitionLevel walks a given node and returns a map of blockquote levels
func GenerateMkDocsAdmonitionLevel(someNode ast.Node) MkDocsAdmonitionLevelMap {
// We define state variable that tracks BlockQuote level while we walk the tree
admonitionLevel := 0
AdmonitionLevelMap := make(map[ast.Node]int)
rootNode := someNode
for rootNode.Parent() != nil {
rootNode = rootNode.Parent()
}
_ = ast.Walk(rootNode, func(node ast.Node, entering bool) (ast.WalkStatus, error) {
if node.Kind() == ast.KindBlockquote && entering {
AdmonitionLevelMap[node] = admonitionLevel
admonitionLevel += 1
}
if node.Kind() == ast.KindBlockquote && !entering {
admonitionLevel -= 1
}
return ast.WalkContinue, nil
})
return AdmonitionLevelMap
}
// renderBlockQuote will render a BlockQuote
// 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) {
// Initialize BlockQuote level map
n := node.(*parser.Admonition)
if r.LevelMap == nil {
r.LevelMap = GenerateMkDocsAdmonitionLevel(node)
}
admonitionType := ParseMkDocsAdmonitionType(node)
admonitionLevel := r.LevelMap.Level(node)
if admonitionLevel == 0 && entering && admonitionType != ANone {
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
@ -126,7 +89,7 @@ func (r *ConfluenceMkDocsAdmonitionRenderer) renderMkDocsAdmonition(writer util.
return ast.WalkContinue, nil
}
if admonitionLevel == 0 && !entering && admonitionType != ANone {
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