From 979d2f6bbbc6ccaa174946e9dc65d539a37c1f1c Mon Sep 17 00:00:00 2001 From: Robin Stocker <robin@nibor.org> Date: Thu, 15 Feb 2024 18:19:04 +1100 Subject: [PATCH] Documentation --- README.md | 35 ++++++++++++++----- commonmark/pom.xml | 2 +- .../java/org/commonmark/package-info.java | 1 + .../markdown/MarkdownNodeRendererContext.java | 3 ++ .../markdown/MarkdownNodeRendererFactory.java | 2 +- .../renderer/markdown/MarkdownRenderer.java | 17 ++++++--- .../renderer/markdown/package-info.java | 4 +++ .../renderer/text/package-info.java | 2 +- .../org/commonmark/test/UsageExampleTest.java | 17 +++++++-- 9 files changed, 65 insertions(+), 18 deletions(-) create mode 100644 commonmark/src/main/java/org/commonmark/renderer/markdown/package-info.java diff --git a/README.md b/README.md index bcf552c5..25df264e 100644 --- a/README.md +++ b/README.md @@ -13,13 +13,14 @@ Java library for parsing and rendering [Markdown] text according to the Introduction ------------ -Provides classes for parsing input to an abstract syntax tree of nodes -(AST), visiting and manipulating nodes, and rendering to HTML. It -started out as a port of [commonmark.js], but has since evolved into a -full library with a nice API and the following features: +Provides classes for parsing input to an abstract syntax tree (AST), +visiting and manipulating nodes, and rendering to HTML or back to Markdown. +It started out as a port of [commonmark.js], but has since evolved into an +extensible library with the following features: * Small (core has no dependencies, extensions in separate artifacts) -* Fast (10-20 times faster than pegdown, see benchmarks in repo) +* Fast (10-20 times faster than [pegdown] which used to be a popular Markdown + library, see benchmarks in repo) * Flexible (manipulate the AST after parsing, customize HTML rendering) * Extensible (tables, strikethrough, autolinking and more, see below) @@ -63,9 +64,9 @@ import org.commonmark.parser.Parser; import org.commonmark.renderer.html.HtmlRenderer; Parser parser = Parser.builder().build(); -Node document = parser.parse("This is *Sparta*"); +Node document = parser.parse("This is *Markdown*"); HtmlRenderer renderer = HtmlRenderer.builder().build(); -renderer.render(document); // "<p>This is <em>Sparta</em></p>\n" +renderer.render(document); // "<p>This is <em>Markdown</em></p>\n" ``` This uses the parser and renderer with default options. Both builders have @@ -81,8 +82,23 @@ to which tags are allowed, etc. That is the responsibility of the caller, and if you expose the resulting HTML, you probably want to run a sanitizer on it after this. -For rendering to plain text, there's also a `TextContentRenderer` with -a very similar API. +#### Render to Markdown + +```java +import org.commonmark.node.*; +import org.commonmark.renderer.markdown.MarkdownRenderer; + +MarkdownRenderer renderer = MarkdownRenderer.builder().build(); +Node document = new Document(); +Heading heading = new Heading(); +heading.setLevel(2); +heading.appendChild(new Text("My title")); +document.appendChild(heading); + +renderer.render(document); // "## My title\n" +``` + +For rendering to plain text with minimal markup, there's also `TextContentRenderer`. #### Use a visitor to process parsed nodes @@ -390,6 +406,7 @@ BSD (2-clause) licensed, see LICENSE.txt file. [CommonMark]: https://commonmark.org/ [Markdown]: https://daringfireball.net/projects/markdown/ [commonmark.js]: https://github.com/commonmark/commonmark.js +[pegdown]: https://github.com/sirthias/pegdown [CommonMark Dingus]: https://spec.commonmark.org/dingus/ [Maven Central]: https://search.maven.org/#search|ga|1|g%3A%22org.commonmark%22 [Semantic Versioning]: https://semver.org/ diff --git a/commonmark/pom.xml b/commonmark/pom.xml index 64c45619..9988370a 100644 --- a/commonmark/pom.xml +++ b/commonmark/pom.xml @@ -9,7 +9,7 @@ <artifactId>commonmark</artifactId> <name>commonmark-java core</name> - <description>Core of commonmark-java (implementation of CommonMark for parsing markdown and rendering to HTML)</description> + <description>Core of commonmark-java (a library for parsing Markdown to an AST, modifying the AST and rendering it to HTML or Markdown)</description> <dependencies> <dependency> diff --git a/commonmark/src/main/java/org/commonmark/package-info.java b/commonmark/src/main/java/org/commonmark/package-info.java index e784703e..b683017f 100644 --- a/commonmark/src/main/java/org/commonmark/package-info.java +++ b/commonmark/src/main/java/org/commonmark/package-info.java @@ -4,6 +4,7 @@ * <li>{@link org.commonmark.parser} for parsing input text to AST nodes</li> * <li>{@link org.commonmark.node} for AST node types and visitors</li> * <li>{@link org.commonmark.renderer.html} for HTML rendering</li> + * <li>{@link org.commonmark.renderer.markdown} for Markdown rendering</li> * </ul> */ package org.commonmark; diff --git a/commonmark/src/main/java/org/commonmark/renderer/markdown/MarkdownNodeRendererContext.java b/commonmark/src/main/java/org/commonmark/renderer/markdown/MarkdownNodeRendererContext.java index 5805c458..40640d1b 100644 --- a/commonmark/src/main/java/org/commonmark/renderer/markdown/MarkdownNodeRendererContext.java +++ b/commonmark/src/main/java/org/commonmark/renderer/markdown/MarkdownNodeRendererContext.java @@ -4,6 +4,9 @@ import org.commonmark.node.Node; import java.util.Set; +/** + * Context that is passed to custom node renderers, see {@link MarkdownNodeRendererFactory#create}. + */ public interface MarkdownNodeRendererContext { /** diff --git a/commonmark/src/main/java/org/commonmark/renderer/markdown/MarkdownNodeRendererFactory.java b/commonmark/src/main/java/org/commonmark/renderer/markdown/MarkdownNodeRendererFactory.java index adfe8a07..14221ea5 100644 --- a/commonmark/src/main/java/org/commonmark/renderer/markdown/MarkdownNodeRendererFactory.java +++ b/commonmark/src/main/java/org/commonmark/renderer/markdown/MarkdownNodeRendererFactory.java @@ -5,7 +5,7 @@ import org.commonmark.renderer.NodeRenderer; import java.util.Set; /** - * Factory for instantiating new node renderers ƒor rendering. + * Factory for instantiating new node renderers for rendering custom nodes. */ public interface MarkdownNodeRendererFactory { 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 92610520..25fa9a14 100644 --- a/commonmark/src/main/java/org/commonmark/renderer/markdown/MarkdownRenderer.java +++ b/commonmark/src/main/java/org/commonmark/renderer/markdown/MarkdownRenderer.java @@ -9,14 +9,17 @@ import org.commonmark.renderer.Renderer; import java.util.*; /** - * Renders nodes to CommonMark Markdown. + * Renders nodes to Markdown (CommonMark syntax); use {@link #builder()} to create a renderer. * <p> - * Note that it does not currently attempt to preserve the exact syntax of the original input Markdown (if any): + * Note that it doesn't currently preserve the exact syntax of the original input Markdown (if any): * <ul> * <li>Headings are output as ATX headings if possible (multi-line headings need Setext headings)</li> * <li>Escaping might be over-eager, e.g. a plain {@code *} might be escaped * even though it doesn't need to be in that particular context</li> + * <li>Leading whitespace in paragraphs is not preserved</li> * </ul> + * However, it should produce Markdown that is semantically equivalent to the input, i.e. if the Markdown was parsed + * again and compared against the original AST, it should be the same (minus bugs). */ public class MarkdownRenderer implements Renderer { @@ -66,7 +69,7 @@ public class MarkdownRenderer implements Renderer { */ public static class Builder { - private List<MarkdownNodeRendererFactory> nodeRendererFactories = new ArrayList<>(); + private final List<MarkdownNodeRendererFactory> nodeRendererFactories = new ArrayList<>(); /** * @return the configured {@link MarkdownRenderer} @@ -106,9 +109,15 @@ public class MarkdownRenderer implements Renderer { } /** - * Extension for {@link MarkdownRenderer}. + * Extension for {@link MarkdownRenderer} for rendering custom nodes. */ public interface MarkdownRendererExtension extends Extension { + + /** + * Extend Markdown rendering, usually by registering custom node renderers using {@link Builder#nodeRendererFactory}. + * + * @param rendererBuilder the renderer builder to extend + */ void extend(Builder rendererBuilder); } diff --git a/commonmark/src/main/java/org/commonmark/renderer/markdown/package-info.java b/commonmark/src/main/java/org/commonmark/renderer/markdown/package-info.java new file mode 100644 index 00000000..f707671d --- /dev/null +++ b/commonmark/src/main/java/org/commonmark/renderer/markdown/package-info.java @@ -0,0 +1,4 @@ +/** + * Markdown rendering (see {@link org.commonmark.renderer.markdown.MarkdownRenderer}) + */ +package org.commonmark.renderer.markdown; diff --git a/commonmark/src/main/java/org/commonmark/renderer/text/package-info.java b/commonmark/src/main/java/org/commonmark/renderer/text/package-info.java index 07a55809..8309f4bd 100644 --- a/commonmark/src/main/java/org/commonmark/renderer/text/package-info.java +++ b/commonmark/src/main/java/org/commonmark/renderer/text/package-info.java @@ -1,4 +1,4 @@ /** - * Text content rendering (see {@link org.commonmark.renderer.text.TextContentRenderer}) + * Plain text rendering with minimal markup (see {@link org.commonmark.renderer.text.TextContentRenderer}) */ package org.commonmark.renderer.text; diff --git a/commonmark/src/test/java/org/commonmark/test/UsageExampleTest.java b/commonmark/src/test/java/org/commonmark/test/UsageExampleTest.java index 9ff64663..08235965 100644 --- a/commonmark/src/test/java/org/commonmark/test/UsageExampleTest.java +++ b/commonmark/src/test/java/org/commonmark/test/UsageExampleTest.java @@ -4,6 +4,7 @@ import org.commonmark.node.*; import org.commonmark.parser.Parser; import org.commonmark.renderer.NodeRenderer; import org.commonmark.renderer.html.*; +import org.commonmark.renderer.markdown.MarkdownRenderer; import org.junit.Ignore; import org.junit.Test; @@ -22,9 +23,21 @@ public class UsageExampleTest { @Test public void parseAndRender() { Parser parser = Parser.builder().build(); - Node document = parser.parse("This is *Sparta*"); + Node document = parser.parse("This is *Markdown*"); HtmlRenderer renderer = HtmlRenderer.builder().escapeHtml(true).build(); - assertEquals("<p>This is <em>Sparta</em></p>\n", renderer.render(document)); + assertEquals("<p>This is <em>Markdown</em></p>\n", renderer.render(document)); + } + + @Test + public void renderToMarkdown() { + MarkdownRenderer renderer = MarkdownRenderer.builder().build(); + Node document = new Document(); + Heading heading = new Heading(); + heading.setLevel(2); + heading.appendChild(new Text("My title")); + document.appendChild(heading); + + assertEquals("## My title\n", renderer.render(document)); } @Test -- GitLab