Class FootnoteHtmlNodeRenderer
- All Implemented Interfaces:
NodeRenderer
Aims to match the rendering of cmark-gfm (which is slightly different from GitHub's when it comes to class attributes, not sure why).
Some notes on how rendering works:
- Footnotes are numbered according to the order of references, starting at 1
- Definitions are rendered at the end of the document, regardless of where the definition was in the source
- Definitions are ordered by number
- Definitions have links back to their references (one or more)
Nested footnotes
Text in footnote definitions can reference other footnotes, even ones that aren't referenced in the main text. This makes them tricky because it's not enough to just go through the main text for references. And before we can render a definition, we need to know all references (because we add links back to references).In other words, footnotes form a directed graph. Footnotes can reference each other so cycles are possible too.
One way to implement it, which is what cmark-gfm does, is to go through the whole document (including definitions) and find all references in order. That guarantees that all definitions are found, but it has strange results for ordering or when the reference is in an unreferenced definition, see tests. In graph terms, it renders all definitions that have an incoming edge, no matter whether they are connected to the main text or not.
The way we implement it:
- Start with the references in the main text; we can render them as we go
- After the main text is rendered, we have the referenced definitions, but there might be more from definition text
- To find the remaining definitions, we visit the definitions from before to look at references
- Repeat (breadth-first search) until we've found all definitions (note that we can't render before that's done because of backrefs)
- Now render the definitions (and any references inside)
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionprivate static class
private static class
private static class
private static class
Visit footnote references/inline footnotes inside the parent (but not the parent itself). -
Field Summary
FieldsModifier and TypeFieldDescriptionprivate final HtmlNodeRendererContext
private DefinitionMap
<FootnoteDefinition> All definitions (even potentially unused ones), for looking up referencesprivate final HtmlWriter
private final Map
<Node, FootnoteHtmlNodeRenderer.ReferencedDefinition> Definitions that were referenced, in order in which they should be rendered.private final Map
<Node, FootnoteHtmlNodeRenderer.ReferenceInfo> Information about references that should be rendered as footnotes. -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionvoid
Called after the root node is rendered, to do any final processing at the end.void
beforeRoot
(Node rootNode) Called before the root node is rendered, to do any initial processing at the start.private String
definitionId
(String definitionKey) private String
definitionKey
(String label, int number) private String
referenceId
(String definitionKey, int number) registerReference
(Node node, String label) void
Render the specified node.private void
renderBackrefs
(Node def, FootnoteHtmlNodeRenderer.ReferencedDefinition referencedDefinition) private void
renderChildren
(Node parent) private void
renderDefinition
(Node def, FootnoteHtmlNodeRenderer.ReferencedDefinition referencedDefinition) private void
renderReference
(Node node, FootnoteHtmlNodeRenderer.ReferenceInfo referenceInfo)
-
Field Details
-
html
-
context
-
definitionMap
All definitions (even potentially unused ones), for looking up references -
referencedDefinitions
Definitions that were referenced, in order in which they should be rendered. -
references
Information about references that should be rendered as footnotes. This doesn't contain all references, just the ones from inside definitions.
-
-
Constructor Details
-
FootnoteHtmlNodeRenderer
-
-
Method Details
-
getNodeTypes
- Specified by:
getNodeTypes
in interfaceNodeRenderer
- Returns:
- the types of nodes that this renderer handles
-
beforeRoot
Description copied from interface:NodeRenderer
Called before the root node is rendered, to do any initial processing at the start.- Specified by:
beforeRoot
in interfaceNodeRenderer
- Parameters:
rootNode
- the root (top-level) node
-
render
Description copied from interface:NodeRenderer
Render the specified node.- Specified by:
render
in interfaceNodeRenderer
- Parameters:
node
- the node to render, will be an instance of one ofNodeRenderer.getNodeTypes()
-
afterRoot
Description copied from interface:NodeRenderer
Called after the root node is rendered, to do any final processing at the end.- Specified by:
afterRoot
in interfaceNodeRenderer
- Parameters:
rootNode
- the root (top-level) node
-
tryRegisterReference
-
registerReference
-
renderReference
-
renderDefinition
private void renderDefinition(Node def, FootnoteHtmlNodeRenderer.ReferencedDefinition referencedDefinition) -
renderBackrefs
private void renderBackrefs(Node def, FootnoteHtmlNodeRenderer.ReferencedDefinition referencedDefinition) -
referenceId
-
definitionKey
-
definitionId
-
renderChildren
-