diff --git a/commonmark/src/main/java/org/commonmark/renderer/html/HtmlRenderer.java b/commonmark/src/main/java/org/commonmark/renderer/html/HtmlRenderer.java index b0264fc72..5b5815e62 100644 --- a/commonmark/src/main/java/org/commonmark/renderer/html/HtmlRenderer.java +++ b/commonmark/src/main/java/org/commonmark/renderer/html/HtmlRenderer.java @@ -28,6 +28,8 @@ public class HtmlRenderer implements Renderer { private final List attributeProviderFactories; private final List nodeRendererFactories; + + private HtmlRenderer(Builder builder) { this.softbreak = builder.softbreak; this.escapeHtml = builder.escapeHtml; @@ -36,13 +38,20 @@ private HtmlRenderer(Builder builder) { this.sanitizeUrls = builder.sanitizeUrls; this.urlSanitizer = builder.urlSanitizer; this.attributeProviderFactories = new ArrayList<>(builder.attributeProviderFactories); + // Add as last. This means clients can override the rendering of core nodes if they want.*/ + this.nodeRendererFactories = buildNodeRenderers(builder); + } + private static List buildNodeRenderers(Builder builder) { + List result = + new ArrayList<>(builder.nodeRendererFactories.size() + 1); - this.nodeRendererFactories = new ArrayList<>(builder.nodeRendererFactories.size() + 1); - this.nodeRendererFactories.addAll(builder.nodeRendererFactories); - // Add as last. This means clients can override the rendering of core nodes if they want. - this.nodeRendererFactories.add(CoreHtmlNodeRenderer::new); + result.addAll(builder.nodeRendererFactories); + result.add(CoreHtmlNodeRenderer::new); + + return result; } + /** * Create a new builder for configuring an {@link HtmlRenderer}. * @@ -52,15 +61,20 @@ public static Builder builder() { return new Builder(); } + private RendererContext createContext(Appendable output) { + return new RendererContext(new HtmlWriter(output)); + } + @Override public void render(Node node, Appendable output) { Objects.requireNonNull(node, "node must not be null"); - RendererContext context = new RendererContext(new HtmlWriter(output)); + RendererContext context = createContext(output); context.beforeRoot(node); context.render(node); context.afterRoot(node); } + @Override public String render(Node node) { Objects.requireNonNull(node, "node must not be null"); @@ -233,12 +247,18 @@ private class RendererContext implements HtmlNodeRendererContext, AttributeProvi private RendererContext(HtmlWriter htmlWriter) { this.htmlWriter = htmlWriter; - - attributeProviders = new ArrayList<>(attributeProviderFactories.size()); + this.attributeProviders = createAttributeProviders(); + initializeNodeRenderers(); + } + private List createAttributeProviders() { + List providers = new ArrayList<>(attributeProviderFactories.size()); for (var attributeProviderFactory : attributeProviderFactories) { - attributeProviders.add(attributeProviderFactory.create(this)); + providers.add(attributeProviderFactory.create(this)); } + return providers; + } + private void initializeNodeRenderers() { for (var factory : nodeRendererFactories) { var renderer = factory.create(this); nodeRendererMap.add(renderer); 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 e4996fb08..a6f7cd74d 100644 --- a/commonmark/src/main/java/org/commonmark/renderer/markdown/MarkdownRenderer.java +++ b/commonmark/src/main/java/org/commonmark/renderer/markdown/MarkdownRenderer.java @@ -130,12 +130,18 @@ private class RendererContext implements MarkdownNodeRendererContext { private RendererContext(MarkdownWriter writer) { // Set fields that are used by interface this.writer = writer; + this.additionalTextEscapes = createAdditionalTextEscapes(); + initializeNodeRenderers(); + } + private Set createAdditionalTextEscapes() { Set escapes = new HashSet<>(); for (MarkdownNodeRendererFactory factory : nodeRendererFactories) { escapes.addAll(factory.getSpecialCharacters()); } - additionalTextEscapes = Collections.unmodifiableSet(escapes); + return Collections.unmodifiableSet(escapes); + } + private void initializeNodeRenderers(){ for (var factory : nodeRendererFactories) { // Pass in this as context here, which uses the fields set above var renderer = factory.create(this);