From eb246155aefaa22e92e6942e59e889a93a308b15 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Thu, 30 Jan 2025 15:33:44 +0000 Subject: [PATCH] Enable adding own markdown renderers in builder --- .../renderer/markdown/MarkdownRenderer.java | 6 +- .../markdown/NodeRendererFactoriesTest.java | 73 +++++++++++++++++++ 2 files changed, 76 insertions(+), 3 deletions(-) create mode 100644 commonmark/src/test/java/org/commonmark/renderer/markdown/NodeRendererFactoriesTest.java diff --git a/commonmark/src/main/java/org/commonmark/renderer/markdown/MarkdownRenderer.java b/commonmark/src/main/java/org/commonmark/renderer/markdown/MarkdownRenderer.java index 0f8559f3..64f2fbeb 100644 --- a/commonmark/src/main/java/org/commonmark/renderer/markdown/MarkdownRenderer.java +++ b/commonmark/src/main/java/org/commonmark/renderer/markdown/MarkdownRenderer.java @@ -136,9 +136,9 @@ private RendererContext(MarkdownWriter writer) { } additionalTextEscapes = Collections.unmodifiableSet(escapes); - // The first node renderer for a node type "wins". - for (int i = nodeRendererFactories.size() - 1; i >= 0; i--) { - MarkdownNodeRendererFactory nodeRendererFactory = nodeRendererFactories.get(i); + // The first node renderer for a node type "wins". The NodeRendererMap + // disallows overwriting. + for (MarkdownNodeRendererFactory nodeRendererFactory : nodeRendererFactories) { // Pass in this as context here, which uses the fields set above NodeRenderer nodeRenderer = nodeRendererFactory.create(this); nodeRendererMap.add(nodeRenderer); diff --git a/commonmark/src/test/java/org/commonmark/renderer/markdown/NodeRendererFactoriesTest.java b/commonmark/src/test/java/org/commonmark/renderer/markdown/NodeRendererFactoriesTest.java new file mode 100644 index 00000000..4c7f59a5 --- /dev/null +++ b/commonmark/src/test/java/org/commonmark/renderer/markdown/NodeRendererFactoriesTest.java @@ -0,0 +1,73 @@ +package org.commonmark.renderer.markdown; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.Set; + +import org.commonmark.node.Heading; +import org.commonmark.node.Node; +import org.commonmark.parser.Parser; +import org.commonmark.renderer.NodeRenderer; +import org.junit.Test; + +public class NodeRendererFactoriesTest { + + @Test + public void testAddedNodeRendererFactoryOverrides() { + String input = "# Header"; + TestCoreMarkdownNodeRenderer.called = false; + parseAndRender(input, new TestNodeRendererFactory()); + assertTrue(TestCoreMarkdownNodeRenderer.called); + } + + private void assertRoundTrip(String input, MarkdownNodeRendererFactory factory) { + String rendered = parseAndRender(input, factory); + assertEquals(input, rendered); + } + + private String parseAndRender(String source, MarkdownNodeRendererFactory factory) { + Node parsed = parse(source); + return render(parsed, factory); + } + + private Node parse(String source) { + return Parser.builder().build().parse(source); + } + + private String render(Node node, MarkdownNodeRendererFactory factory) { + return MarkdownRenderer.builder().nodeRendererFactory(factory).build().render(node); + } + + private static class TestNodeRendererFactory implements MarkdownNodeRendererFactory { + @Override + public NodeRenderer create(MarkdownNodeRendererContext context) { + return new TestCoreMarkdownNodeRenderer(context); + } + + @Override + public Set getSpecialCharacters() { + return Set.of(); + } + } + + private static class TestCoreMarkdownNodeRenderer extends CoreMarkdownNodeRenderer { + static boolean called = false; + + public TestCoreMarkdownNodeRenderer(MarkdownNodeRendererContext context) { + super(context); + } + + @Override + public Set> getNodeTypes() { + return super.getNodeTypes(); + } + + @Override + public void visit(Heading heading) { + called = true; + super.visit(heading); + } + } + +}