@@ -67,7 +67,7 @@ public class FootnoteHtmlNodeRenderer implements NodeRenderer {
6767 * Information about references that should be rendered as footnotes. This doesn't contain all references, just the
6868 * ones from inside definitions.
6969 */
70- private final Map <FootnoteReference , ReferenceInfo > references = new HashMap <>();
70+ private final Map <Node , ReferenceInfo > references = new HashMap <>();
7171
7272 public FootnoteHtmlNodeRenderer (HtmlNodeRendererContext context ) {
7373 this .html = context .getWriter ();
@@ -91,6 +91,7 @@ public void beforeRoot(Node node) {
9191 public void render (Node node ) {
9292 if (node instanceof FootnoteReference ) {
9393 // This is called for all references, even ones inside definitions that we render at the end.
94+ // Inside definitions, we have registered the reference already.
9495 var ref = (FootnoteReference ) node ;
9596 // Use containsKey because if value is null, we don't need to try registering again.
9697 var info = references .containsKey (ref ) ? references .get (ref ) : tryRegisterReference (ref );
@@ -101,13 +102,16 @@ public void render(Node node) {
101102 html .text ("[^" + ref .getLabel () + "]" );
102103 }
103104 } else if (node instanceof InlineFootnote ) {
104- var info = registerReference (node , null );
105+ var info = references .get (node );
106+ if (info == null ) {
107+ info = registerReference (node , null );
108+ }
105109 renderReference (node , info );
106110 }
107111 }
108112
109113 @ Override
110- public void afterRoot (Node node ) {
114+ public void afterRoot (Node rootNode ) {
111115 // Now render the referenced definitions if there are any.
112116 if (referencedDefinitions .isEmpty ()) {
113117 return ;
@@ -127,13 +131,19 @@ public void afterRoot(Node node) {
127131 var check = new LinkedList <>(referencedDefinitions .keySet ());
128132 while (!check .isEmpty ()) {
129133 var def = check .removeFirst ();
130- def .accept (new ReferenceVisitor (ref -> {
131- var d = definitionMap .get (ref .getLabel ());
132- if (d != null ) {
133- if (!referencedDefinitions .containsKey (d )) {
134- check .addLast (d );
134+ def .accept (new ShallowReferenceVisitor (def , node -> {
135+ if (node instanceof FootnoteReference ) {
136+ var ref = (FootnoteReference ) node ;
137+ var d = definitionMap .get (ref .getLabel ());
138+ if (d != null ) {
139+ if (!referencedDefinitions .containsKey (d )) {
140+ check .addLast (d );
141+ }
142+ references .put (ref , registerReference (d , d .getLabel ()));
135143 }
136- references .put (ref , registerReference (d , d .getLabel ()));
144+ } else if (node instanceof InlineFootnote ) {
145+ check .addLast (node );
146+ references .put (node , registerReference (node , null ));
137147 }
138148 }));
139149 }
@@ -307,18 +317,31 @@ public void visit(CustomBlock customBlock) {
307317 }
308318 }
309319
310- private static class ReferenceVisitor extends AbstractVisitor {
311- private final Consumer <FootnoteReference > consumer ;
320+ /**
321+ * Visit footnote references/inline footnotes inside the parent (but not the parent itself). We want a shallow visit
322+ * because the caller wants to control when to descend.
323+ */
324+ private static class ShallowReferenceVisitor extends AbstractVisitor {
325+ private final Node parent ;
326+ private final Consumer <Node > consumer ;
312327
313- private ReferenceVisitor (Consumer <FootnoteReference > consumer ) {
328+ private ShallowReferenceVisitor (Node parent , Consumer <Node > consumer ) {
329+ this .parent = parent ;
314330 this .consumer = consumer ;
315331 }
316332
317333 @ Override
318334 public void visit (CustomNode customNode ) {
319335 if (customNode instanceof FootnoteReference ) {
320- var ref = (FootnoteReference ) customNode ;
321- consumer .accept (ref );
336+ consumer .accept (customNode );
337+ } else if (customNode instanceof InlineFootnote ) {
338+ if (customNode == parent ) {
339+ // Descend into the parent (inline footnotes can contain inline footnotes)
340+ super .visit (customNode );
341+ } else {
342+ // Don't descend here because we want to be shallow.
343+ consumer .accept (customNode );
344+ }
322345 } else {
323346 super .visit (customNode );
324347 }
0 commit comments