Java Flexmark
last modified July 4, 2026
In this article we show how to work with the Flexmark library which is used to parse and render Markdown in Java. We provide several code examples to work with Markdown in Java.
Markdown is a lightweight markup language with plain text formatting syntax. It is widely used for documentation, readme files, blog posts, and note-taking. Flexmark implements the CommonMark specification, a strongly defined, highly compatible standard that resolves ambiguities found in the original Markdown specification.
Flexmark also supports GitHub-Flavored Markdown (GFM) extensions including tables, task lists, and strikethrough, making it suitable for rendering the same Markdown that developers use on platforms like GitHub.
Flexmark library
Flexmark is a Java library for parsing and rendering Markdown according to the CommonMark specification. It is highly extensible with plugins for tables, task lists, strikethrough, footnotes, and many more features.
<dependencies>
<dependency>
<groupId>com.vladsch.flexmark</groupId>
<artifactId>flexmark</artifactId>
<version>0.64.8</version>
</dependency>
<dependency>
<groupId>com.vladsch.flexmark</groupId>
<artifactId>flexmark-ext-tables</artifactId>
<version>0.64.8</version>
</dependency>
<dependency>
<groupId>com.vladsch.flexmark</groupId>
<artifactId>flexmark-ext-gfm-tasklist</artifactId>
<version>0.64.8</version>
</dependency>
<dependency>
<groupId>com.vladsch.flexmark</groupId>
<artifactId>flexmark-ext-gfm-strikethrough</artifactId>
<version>0.64.8</version>
</dependency>
</dependencies>
These are the Maven dependencies for Flexmark, including the core library and extensions for tables, task lists, and strikethrough.
Parsing Markdown
The first example shows how to parse a Markdown string into an abstract syntax tree (AST).
import com.vladsch.flexmark.parser.Parser;
void main() {
var markdown = """
# Hello, CommonMark!
This is a **Markdown** document with a [link](https://commonmark.org).
""";
var parser = Parser.builder().build();
var document = parser.parse(markdown);
System.out.println(document);
}
The example parses a Markdown string using the default parser and prints the resulting AST.
var markdown = """
# Hello, CommonMark!
This is a **Markdown** document with a [link](https://commonmark.org).
""";
A Markdown string is defined using a Java text block. The string contains a heading, a paragraph with bold text, and a link.
var parser = Parser.builder().build(); var document = parser.parse(markdown);
The Parser is built using the builder pattern. The
parse method converts the Markdown string into a
Document AST node.
$ java -cp "lib/*" Main.java
Document{}
The output is Document{}. The
Document class does not override toString, so it
falls back to the default Object.toString implementation, which
prints the class name and an empty braces pair. The parsed content is not lost
— the Document object contains a full tree of AST nodes
representing the heading, paragraph, bold text, and link.
To actually see the result, you need to pass the document to an
HtmlRenderer or traverse the node tree manually. We cover rendering
to HTML in the next section.
Rendering to HTML
The most common use case is converting Markdown to HTML.
import com.vladsch.flexmark.html.HtmlRenderer;
import com.vladsch.flexmark.parser.Parser;
void main() {
var markdown = """
# Features
Flexmark supports **bold**, *italic*, and `inline code`.
- Item one
- Item two
- Item three
""";
var parser = Parser.builder().build();
var renderer = HtmlRenderer.builder().build();
var document = parser.parse(markdown);
var html = renderer.render(document);
System.out.println(html);
}
The example converts a Markdown string into an HTML string.
var renderer = HtmlRenderer.builder().build();
An HtmlRenderer is built using its builder. It transforms the AST
into an HTML string.
var html = renderer.render(document);
The render method takes the parsed document and produces an HTML
string. The result includes standard HTML tags such as
<h1>, <p>, <strong>,
<em>, <ul>, and <li>.
Shared parser and renderer configuration
Both the parser and renderer can share a single MutableDataSet
configuration object. This ensures that extensions and options are applied
consistently.
import com.vladsch.flexmark.html.HtmlRenderer;
import com.vladsch.flexmark.parser.Parser;
import com.vladsch.flexmark.util.data.MutableDataSet;
void main() {
var options = new MutableDataSet();
var parser = Parser.builder(options).build();
var renderer = HtmlRenderer.builder(options).build();
var markdown = """
## Configuration
Both parser and renderer share the same options.
""";
var html = renderer.render(parser.parse(markdown));
System.out.println(html);
}
A MutableDataSet holds all configuration options. Passing the same
instance to both builders ensures that extensions registered via the options are
available to both the parser and the renderer.
Using extensions
Flexmark provides numerous extensions for GitHub-Flavored Markdown features such as tables, task lists, and strikethrough. The following example demonstrates how to enable them.
import com.vladsch.flexmark.ext.gfm.strikethrough.StrikethroughExtension;
import com.vladsch.flexmark.ext.gfm.tasklist.TaskListExtension;
import com.vladsch.flexmark.ext.tables.TablesExtension;
import com.vladsch.flexmark.html.HtmlRenderer;
import com.vladsch.flexmark.parser.Parser;
import com.vladsch.flexmark.util.data.MutableDataSet;
import java.util.List;
void main() {
var options = new MutableDataSet();
options.set(Parser.EXTENSIONS, List.of(
TablesExtension.create(),
TaskListExtension.create(),
StrikethroughExtension.create()));
var parser = Parser.builder(options).build();
var renderer = HtmlRenderer.builder(options).build();
var markdown = """
## Extensions Demo
| Name | Price |
|-------|-------|
| Book | $12 |
| Pen | $2 |
- [x] Learn Flexmark
- [ ] Write article
- [ ] Publish
This is ~~deprecated~~ updated.
""";
var html = renderer.render(parser.parse(markdown));
System.out.println(html);
}
The example enables table, task list, and strikethrough extensions.
options.set(Parser.EXTENSIONS, List.of(
TablesExtension.create(),
TaskListExtension.create(),
StrikethroughExtension.create()));
Extensions are registered via the Parser.EXTENSIONS key. Each
extension is created with its static factory method and added to a list. These
extensions are then automatically available to both the parser and the renderer.
| Name | Price | |-------|-------| | Book | $12 | | Pen | $2 |
Tables are defined using pipe characters and hyphens. The first row is the header, and the second row defines the column alignment.
- [x] Learn Flexmark - [ ] Write article
Task lists use the [ ] and [x] syntax for unchecked
and checked items respectively.
This is ~~deprecated~~ updated.
Strikethrough text is marked with double tildes ~~.
Customizing rendering options
Flexmark allows customization of HTML output through various options. The following example shows how to configure soft breaks and unsafe HTML rendering.
import com.vladsch.flexmark.html.HtmlRenderer;
import com.vladsch.flexmark.parser.Parser;
import com.vladsch.flexmark.util.data.MutableDataSet;
void main() {
var options = new MutableDataSet();
options.set(HtmlRenderer.SOFT_BREAK, "<br />");
var parser = Parser.builder(options).build();
var renderer = HtmlRenderer.builder(options).build();
var markdown = """
Line one
Line two
Line three
""";
var html = renderer.render(parser.parse(markdown));
System.out.println(html);
}
The SOFT_BREAK option controls how line breaks within a paragraph
are rendered. By setting it to <br />, single line breaks
in the Markdown source become HTML line breaks.
options.set(HtmlRenderer.SOFT_BREAK, "<br />");
The default behaviour translates a soft break into a space. Setting it to
<br /> makes single newlines visible in the rendered HTML.
Wrapping HTML with CSS
When embedding rendered Markdown in a Swing application or web page, it is useful to wrap the HTML body with a full document structure including CSS styling.
import com.vladsch.flexmark.html.HtmlRenderer;
import com.vladsch.flexmark.parser.Parser;
import com.vladsch.flexmark.util.data.MutableDataSet;
void main() {
var options = new MutableDataSet();
options.set(HtmlRenderer.SOFT_BREAK, "<br />");
var parser = Parser.builder(options).build();
var renderer = HtmlRenderer.builder(options).build();
var markdown = """
## Styled Output
This Markdown is rendered with custom CSS styling.
""";
var body = renderer.render(parser.parse(markdown));
var css = """
body {
font-family: "Segoe UI", Roboto, sans-serif;
font-size: 14px;
line-height: 1.6;
padding: 20px;
color: #333;
text-align: left;
}
h2 { color: #2c3e50; }
""";
var fullHtml = """
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>%s</style>
</head>
<body>%s</body>
</html>
""".formatted(css, body);
System.out.println(fullHtml);
}
The example renders Markdown to HTML and wraps the result in a complete HTML
document with embedded CSS styles. This approach is especially useful when
displaying Markdown in JEditorPane or similar Swing components.
var body = renderer.render(parser.parse(markdown));
The Markdown is first parsed and rendered into an HTML body fragment.
var fullHtml = """
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>%s</style>
</head>
<body>%s</body>
</html>
""".formatted(css, body);
The HTML body and CSS are embedded into a full HTML document using a text block
template and the formatted method for string interpolation.
Reading Markdown from a file
In practice, Markdown content is often stored in files. The next example reads a Markdown file and renders it to HTML.
# Sample Document
## Introduction
This is a sample Markdown file with **formatted** text.
### Code Example
```java
record Point(int x, int y) {
Point translate(int dx, int dy) {
return new Point(x + dx, y + dy);
}
}
```
We have a sample Markdown file with a heading, formatted text, and a fenced code block.
import com.vladsch.flexmark.html.HtmlRenderer;
import com.vladsch.flexmark.parser.Parser;
import com.vladsch.flexmark.util.data.MutableDataSet;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
void main() throws IOException {
var filePath = Path.of("src/main/resources/sample.md");
var markdown = Files.readString(filePath);
var options = new MutableDataSet();
var parser = Parser.builder(options).build();
var renderer = HtmlRenderer.builder(options).build();
var html = renderer.render(parser.parse(markdown));
var outputPath = Path.of("sample.html");
Files.writeString(outputPath, html);
System.out.println("HTML written to " + outputPath.toAbsolutePath());
}
The example reads Markdown from a file, renders it to HTML, and writes the output to another file.
var filePath = Path.of("src/main/resources/sample.md");
var markdown = Files.readString(filePath);
The Files.readString method reads the entire Markdown file into a
string. It uses UTF-8 encoding by default.
var outputPath = Path.of("sample.html");
Files.writeString(outputPath, html);
The rendered HTML is written to a file using Files.writeString.
In this article we have worked with the Flexmark library, which implements the CommonMark specification. We have parsed Markdown strings, rendered them to HTML, enabled extensions for GitHub-Flavored Markdown, customized rendering options, and wrapped HTML output with CSS styling.
Source
Author
List all Java tutorials.