Convert Figma logo to code with AI

commonmark logocommonmark-java

Java library for parsing and rendering CommonMark (Markdown)

2,257
287
2,257
14

Top Related Projects

CommonMark/Markdown Java parser with source level AST. CommonMark 0.28, emulation of: pegdown, kramdown, markdown.pl, MultiMarkdown. With HTML to MD, MD to PDF, MD to DOCX conversion modules.

Java library for parsing and rendering CommonMark (Markdown)

1,291

A pure-Java Markdown processor based on a parboiled PEG parser supporting a number of extensions

The missing emoji library for Java :heart:

Quick Overview

The CommonMark-Java project is a Java implementation of the CommonMark specification, a strongly-defined, highly compatible markdown parser. It provides a robust and flexible way to convert Markdown-formatted text to HTML, with support for a wide range of Markdown features and customization options.

Pros

  • Comprehensive Markdown Support: The library supports a wide range of Markdown features, including tables, lists, links, images, and more, ensuring accurate and consistent conversion from Markdown to HTML.
  • Customizable Rendering: The library allows for customization of the rendering process, enabling developers to tailor the output to their specific needs.
  • Robust and Reliable: The library is well-tested and maintained, ensuring a stable and reliable Markdown parsing experience.
  • Actively Maintained: The project is actively maintained, with regular updates and bug fixes, ensuring ongoing support and improvements.

Cons

  • Java-Specific: The library is specific to the Java programming language, which may limit its usefulness for developers working in other languages.
  • Learning Curve: While the library is well-documented, there may be a learning curve for developers who are new to the CommonMark specification or Markdown parsing in general.
  • Performance Overhead: Depending on the size and complexity of the Markdown content, the parsing and rendering process may introduce some performance overhead.
  • Limited Customization: While the library allows for some customization, the range of customization options may be limited compared to other Markdown parsing libraries.

Code Examples

Here are a few examples of how to use the CommonMark-Java library:

// Basic Markdown to HTML conversion
String markdown = "# Hello, World!\n\nThis is a paragraph.";
Node document = Parser.builder().build().parse(markdown);
HtmlRenderer renderer = HtmlRenderer.builder().build();
String html = renderer.render(document);
System.out.println(html);
// Customizing the rendering process
HtmlRenderer renderer = HtmlRenderer.builder()
    .softbreak("\n")
    .escapeHtml(true)
    .build();
String html = renderer.render(document);
// Extending the CommonMark specification
Parser parser = Parser.builder()
    .extensions(Arrays.asList(TableExtension.create()))
    .build();
Node document = parser.parse(markdown);
String html = HtmlRenderer.builder().build().render(document);
// Handling custom block types
BlockParserFactory factory = new BlockParserFactory();
factory.addDelimiterProcessor(new CustomDelimiterProcessor());
Parser parser = Parser.builder()
    .blockParserFactory(factory)
    .build();
Node document = parser.parse(markdown);
String html = HtmlRenderer.builder().build().render(document);

Getting Started

To get started with the CommonMark-Java library, follow these steps:

  1. Add the library to your project's dependencies. In a Maven-based project, you can add the following dependency to your pom.xml file:
<dependency>
    <groupId>com.atlassian.commonmark</groupId>
    <artifactId>commonmark</artifactId>
    <version>0.17.1</version>
</dependency>
  1. Create a Parser instance and use it to parse Markdown content:
String markdown = "# Hello, World!\n\nThis is a paragraph.";
Parser parser = Parser.builder().build();
Node document = parser.parse(markdown);
  1. Create an HtmlRenderer instance and use it to render the parsed Markdown content to HTML:
HtmlRenderer renderer = HtmlRenderer.builder().build();
String html = renderer.render(document);
System.out.println(html);
  1. Optionally, you can customize the parsing and rendering process by configuring the Parser and HtmlRenderer instances with various options and extensions.

For more detailed information and advanced usage examples, please refer to the CommonMark-Java project documentation.

Competitor Comparisons

CommonMark/Markdown Java parser with source level AST. CommonMark 0.28, emulation of: pegdown, kramdown, markdown.pl, MultiMarkdown. With HTML to MD, MD to PDF, MD to DOCX conversion modules.

Pros of flexmark-java

  • More extensive feature set, including support for additional Markdown extensions
  • Highly customizable and configurable
  • Better performance for parsing and rendering large documents

Cons of flexmark-java

  • Steeper learning curve due to its complexity and extensive options
  • Larger library size, which may impact application size

Code Comparison

flexmark-java:

MutableDataSet options = new MutableDataSet();
Parser parser = Parser.builder(options).build();
HtmlRenderer renderer = HtmlRenderer.builder(options).build();
Node document = parser.parse("Hello *Markdown*!");
String html = renderer.render(document);

commonmark-java:

Parser parser = Parser.builder().build();
Node document = parser.parse("Hello *Markdown*!");
HtmlRenderer renderer = HtmlRenderer.builder().build();
String html = renderer.render(document);

Both libraries offer similar basic usage, but flexmark-java provides more options for customization through the MutableDataSet. This allows for fine-tuning of parsing and rendering behavior, which can be beneficial for complex use cases but may be unnecessary for simpler applications.

flexmark-java is generally preferred for projects requiring advanced Markdown features or extensive customization, while commonmark-java is suitable for simpler implementations focusing on core Markdown syntax.

Java library for parsing and rendering CommonMark (Markdown)

Pros of commonmark-java

  • Actively maintained with regular updates and bug fixes
  • Comprehensive documentation and examples for easy integration
  • Supports a wide range of CommonMark extensions

Cons of commonmark-java

  • Slightly larger library size compared to alternatives
  • May have a steeper learning curve for complex customizations

Code Comparison

commonmark-java:

Parser parser = Parser.builder().build();
Node document = parser.parse("This is *Markdown*");
HtmlRenderer renderer = HtmlRenderer.builder().build();
String html = renderer.render(document);

commonmark-java:

Parser parser = Parser.builder().build();
Node document = parser.parse("This is *Markdown*");
HtmlRenderer renderer = HtmlRenderer.builder().build();
String html = renderer.render(document);

Both repositories appear to be the same project, as they have identical code examples and functionality. The comparison above is based on the features and characteristics of the commonmark-java project itself, rather than comparing two distinct repositories.

commonmark-java is a robust Java library for parsing and rendering CommonMark, a standardized Markdown specification. It offers a balance between performance and flexibility, making it suitable for a wide range of applications that require Markdown processing in Java environments.

1,291

A pure-Java Markdown processor based on a parboiled PEG parser supporting a number of extensions

Pros of Pegdown

  • Pegdown provides a more extensive set of extensions and customization options, allowing for greater flexibility in handling different Markdown variants and use cases.
  • The library has a larger community and more active development, with more contributors and a longer history compared to CommonMark-Java.
  • Pegdown's performance is generally faster than CommonMark-Java, especially for larger documents.

Cons of Pegdown

  • Pegdown's codebase is more complex and less modular than CommonMark-Java, making it potentially more difficult to maintain and extend.
  • The library's API is less intuitive and more verbose compared to the more streamlined and user-friendly CommonMark-Java API.

Code Comparison

CommonMark-Java:

Parser parser = Parser.builder().build();
Node document = parser.parse("# Hello, World!");
HtmlRenderer renderer = HtmlRenderer.builder().build();
String html = renderer.render(document);

Pegdown:

PegDownProcessor processor = new PegDownProcessor();
String html = processor.markdownToHtml("# Hello, World!");

The missing emoji library for Java :heart:

Pros of emoji-java

  • Focused specifically on emoji handling and conversion
  • Lightweight library with minimal dependencies
  • Includes methods for parsing and generating HTML entities for emojis

Cons of emoji-java

  • Limited scope compared to commonmark-java's full Markdown parsing capabilities
  • Less active development and community support
  • Lacks extensive documentation and examples

Code Comparison

emoji-java:

String str = "An 😀awesome 😃string with a few 😉emojis!";
String result = EmojiParser.parseToAliases(str);
// result: "An :grinning:awesome :smiley:string with a few :wink:emojis!"

commonmark-java:

Parser parser = Parser.builder().build();
Node document = parser.parse("# Hello World\n\nThis is *Markdown*");
HtmlRenderer renderer = HtmlRenderer.builder().build();
String html = renderer.render(document);

Summary

emoji-java is a specialized library for handling emojis in Java, offering simple emoji parsing and conversion. It's lightweight but limited in scope. commonmark-java, on the other hand, is a full-featured Markdown parser with broader capabilities, including emoji support. While emoji-java excels in its specific domain, commonmark-java provides a more comprehensive solution for Markdown processing, including emoji handling as part of its larger feature set.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

commonmark-java

Java library for parsing and rendering Markdown text according to the CommonMark specification (and some extensions).

Maven Central status javadoc ci codecov SourceSpy Dashboard

Introduction

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 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)

The library is supported on Java 11 and later. It works on Android too, but that is on a best-effort basis, please report problems. For Android the minimum API level is 19, see the commonmark-android-test directory.

Coordinates for core library (see all on Maven Central):

<dependency>
    <groupId>org.commonmark</groupId>
    <artifactId>commonmark</artifactId>
    <version>0.22.0</version>
</dependency>

The module names to use in Java 9 are org.commonmark, org.commonmark.ext.autolink, etc, corresponding to package names.

Note that for 0.x releases of this library, the API is not considered stable yet and may break between minor releases. After 1.0, Semantic Versioning will be followed. A package containing beta means it's not subject to stable API guarantees yet; but for normal usage it should not be necessary to use.

See the spec.txt file if you're wondering which version of the spec is currently implemented. Also check out the CommonMark dingus for getting familiar with the syntax or trying out edge cases. If you clone the repository, you can also use the DingusApp class to try out things interactively.

Usage

Parse and render to HTML

import org.commonmark.node.*;
import org.commonmark.parser.Parser;
import org.commonmark.renderer.html.HtmlRenderer;

Parser parser = Parser.builder().build();
Node document = parser.parse("This is *Markdown*");
HtmlRenderer renderer = HtmlRenderer.builder().build();
renderer.render(document);  // "<p>This is <em>Markdown</em></p>\n"

This uses the parser and renderer with default options. Both builders have methods for configuring their behavior:

  • escapeHtml(true) on HtmlRenderer will escape raw HTML tags and blocks.
  • sanitizeUrls(true) on HtmlRenderer will strip potentially unsafe URLs from <a> and <img> tags
  • For all available options, see methods on the builders.

Note that this library doesn't try to sanitize the resulting HTML with regards 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.

Render to Markdown

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

After the source text has been parsed, the result is a tree of nodes. That tree can be modified before rendering, or just inspected without rendering:

Node node = parser.parse("Example\n=======\n\nSome more text");
WordCountVisitor visitor = new WordCountVisitor();
node.accept(visitor);
visitor.wordCount;  // 4

class WordCountVisitor extends AbstractVisitor {
    int wordCount = 0;

    @Override
    public void visit(Text text) {
        // This is called for all Text nodes. Override other visit methods for other node types.

        // Count words (this is just an example, don't actually do it this way for various reasons).
        wordCount += text.getLiteral().split("\\W+").length;

        // Descend into children (could be omitted in this case because Text nodes don't have children).
        visitChildren(text);
    }
}

Add or change attributes of HTML elements

Sometimes you might want to customize how HTML is rendered. If all you want to do is add or change attributes on some elements, there's a simple way to do that.

In this example, we register a factory for an AttributeProvider on the renderer to set a class="border" attribute on img elements.

Parser parser = Parser.builder().build();
HtmlRenderer renderer = HtmlRenderer.builder()
        .attributeProviderFactory(new AttributeProviderFactory() {
            public AttributeProvider create(AttributeProviderContext context) {
                return new ImageAttributeProvider();
            }
        })
        .build();

Node document = parser.parse("![text](/url.png)");
renderer.render(document);
// "<p><img src=\"/url.png\" alt=\"text\" class=\"border\" /></p>\n"

class ImageAttributeProvider implements AttributeProvider {
    @Override
    public void setAttributes(Node node, String tagName, Map<String, String> attributes) {
        if (node instanceof Image) {
            attributes.put("class", "border");
        }
    }
}

Customize HTML rendering

If you want to do more than just change attributes, there's also a way to take complete control over how HTML is rendered.

In this example, we're changing the rendering of indented code blocks to only wrap them in pre instead of pre and code:

Parser parser = Parser.builder().build();
HtmlRenderer renderer = HtmlRenderer.builder()
        .nodeRendererFactory(new HtmlNodeRendererFactory() {
            public NodeRenderer create(HtmlNodeRendererContext context) {
                return new IndentedCodeBlockNodeRenderer(context);
            }
        })
        .build();

Node document = parser.parse("Example:\n\n    code");
renderer.render(document);
// "<p>Example:</p>\n<pre>code\n</pre>\n"

class IndentedCodeBlockNodeRenderer implements NodeRenderer {

    private final HtmlWriter html;

    IndentedCodeBlockNodeRenderer(HtmlNodeRendererContext context) {
        this.html = context.getWriter();
    }

    @Override
    public Set<Class<? extends Node>> getNodeTypes() {
        // Return the node types we want to use this renderer for.
        return Set.of(IndentedCodeBlock.class);
    }

    @Override
    public void render(Node node) {
        // We only handle one type as per getNodeTypes, so we can just cast it here.
        IndentedCodeBlock codeBlock = (IndentedCodeBlock) node;
        html.line();
        html.tag("pre");
        html.text(codeBlock.getLiteral());
        html.tag("/pre");
        html.line();
    }
}

Add your own node types

In case you want to store additional data in the document or have custom elements in the resulting HTML, you can create your own subclass of CustomNode and add instances as child nodes to existing nodes.

To define the HTML rendering for them, you can use a NodeRenderer as explained above.

Customize parsing

There are a few ways to extend parsing or even override built-in parsing, all of them via methods on Parser.Builder (see Blocks and inlines in the spec for an overview of blocks/inlines):

  • Parsing of specific block types (e.g. headings, code blocks, etc) can be enabled/disabled with enabledBlockTypes
  • Parsing of blocks can be extended/overridden with customBlockParserFactory
  • Parsing of inline content can be extended/overridden with customInlineContentParserFactory
  • Parsing of delimiters in inline content can be extended with customDelimiterProcessor

Thread-safety

Both the Parser and HtmlRenderer are designed so that you can configure them once using the builders and then use them multiple times/from multiple threads. This is done by separating the state for parsing/rendering from the configuration.

Having said that, there might be bugs of course. If you find one, please report an issue.

API documentation

Javadocs are available online on javadoc.io.

Extensions

Extensions need to extend the parser, or the HTML renderer, or both. To use an extension, the builder objects can be configured with a list of extensions. Because extensions are optional, they live in separate artifacts, so additional dependencies need to be added as well.

Let's look at how to enable tables from GitHub Flavored Markdown. First, add an additional dependency (see Maven Central for others):

<dependency>
    <groupId>org.commonmark</groupId>
    <artifactId>commonmark-ext-gfm-tables</artifactId>
    <version>0.22.0</version>
</dependency>

Then, configure the extension on the builders:

import org.commonmark.ext.gfm.tables.TablesExtension;

List<Extension> extensions = List.of(TablesExtension.create());
Parser parser = Parser.builder()
        .extensions(extensions)
        .build();
HtmlRenderer renderer = HtmlRenderer.builder()
        .extensions(extensions)
        .build();

To configure another extension in the above example, just add it to the list.

The following extensions are developed with this library, each in their own artifact.

Autolink

Turns plain links such as URLs and email addresses into links (based on autolink-java).

Use class AutolinkExtension from artifact commonmark-ext-autolink.

Strikethrough

Enables strikethrough of text by enclosing it in ~~. For example, in hey ~~you~~, you will be rendered as strikethrough text.

Use class StrikethroughExtension in artifact commonmark-ext-gfm-strikethrough.

Tables

Enables tables using pipes as in GitHub Flavored Markdown.

Use class TablesExtension in artifact commonmark-ext-gfm-tables.

Heading anchor

Enables adding auto generated "id" attributes to heading tags. The "id" is based on the text of the heading.

# Heading will be rendered as:

<h1 id="heading">Heading</h1>

Use class HeadingAnchorExtension in artifact commonmark-ext-heading-anchor.

In case you want custom rendering of the heading instead, you can use the IdGenerator class directly together with a HtmlNodeRendererFactory (see example above).

Ins

Enables underlining of text by enclosing it in ++. For example, in hey ++you++, you will be rendered as underline text. Uses the <ins> tag.

Use class InsExtension in artifact commonmark-ext-ins.

YAML front matter

Adds support for metadata through a YAML front matter block. This extension only supports a subset of YAML syntax. Here's an example of what's supported:

---
key: value
list:
  - value 1
  - value 2
literal: |
  this is literal value.

  literal values 2
---

document start here

Use class YamlFrontMatterExtension in artifact commonmark-ext-yaml-front-matter. To fetch metadata, use YamlFrontMatterVisitor.

Image Attributes

Adds support for specifying attributes (specifically height and width) for images.

The attribute elements are given as key=value pairs inside curly braces { } after the image node to which they apply, for example:

![text](/url.png){width=640 height=480}

will be rendered as:

<img src="/url.png" alt="text" width="640" height="480" />

Use class ImageAttributesExtension in artifact commonmark-ext-image-attributes.

Note: since this extension uses curly braces { } as its delimiters (in StylesDelimiterProcessor), this means that other delimiter processors cannot use curly braces for delimiting.

Task List Items

Adds support for tasks as list items.

A task can be represented as a list item where the first non-whitespace character is a left bracket [, then a single whitespace character or the letter x in lowercase or uppercase, then a right bracket ] followed by at least one whitespace before any other content.

For example:

- [ ] task #1
- [x] task #2

will be rendered as:

<ul>
<li><input type="checkbox" disabled=""> task #1</li>
<li><input type="checkbox" disabled="" checked=""> task #2</li>
</ul>

Use class TaskListItemsExtension in artifact commonmark-ext-task-list-items.

Third-party extensions

You can also find other extensions in the wild:

  • commonmark-ext-notifications: this extension allows to easily create notifications/admonitions paragraphs like INFO, SUCCESS, WARNING or ERROR

See also

  • Markwon: Android library for rendering markdown as system-native Spannables
  • flexmark-java: Fork that added support for a lot more syntax and flexibility

Contributing

See CONTRIBUTING.md file.

License

Copyright (c) Atlassian and others.

BSD (2-clause) licensed, see LICENSE.txt file.