For Maven, add flexmark-all
as a dependency which includes core and all modules to the following sample:
<dependency> <groupId>com.vladsch.flexmark</groupId> <artifactId>flexmark-all</artifactId> <version>0.64.0</version> </dependency>
compile 'com.vladsch.flexmark:flexmark-all:0.64.0'Building with Android Studio
Additional settings due to duplicate files:
packagingOptions {
exclude 'META-INF/LICENSE-LGPL-2.1.txt'
exclude 'META-INF/LICENSE-LGPL-3.txt'
exclude 'META-INF/LICENSE-W3C-TEST'
}
Please use the code listed here with the understanding that it is probably a bit out of date. Use the links to get the most current version.
Source: ProfileEmulationFamilySamples.java
package com.vladsch.flexmark.samples; import com.vladsch.flexmark.util.ast.Node; import com.vladsch.flexmark.html.HtmlRenderer; import com.vladsch.flexmark.parser.Parser; import com.vladsch.flexmark.parser.ParserEmulationProfile; import com.vladsch.flexmark.util.data.MutableDataHolder; import com.vladsch.flexmark.util.data.MutableDataSet; public class BasicSample { void commonMark() { Parser parser = Parser.builder().build(); Node document = parser.parse("This is *Sparta*"); HtmlRenderer renderer = HtmlRenderer.builder().build(); renderer.render(document); // "<p>This is <em>Sparta</em></p>\n" } void kramdown() { MutableDataSet options = new MutableDataSet(); options.setFrom(ParserEmulationProfile.KRAMDOWN); options.set(Parser.EXTENSIONS, Arrays.asList( AbbreviationExtension.create(), DefinitionExtension.create(), FootnoteExtension.create(), TablesExtension.create(), TypographicExtension.create() )); Parser parser = Parser.builder(options).build(); HtmlRenderer renderer = HtmlRenderer.builder(options).build(); Node document = parser.parse("This is *Sparta*"); renderer.render(document); // "<p>This is <em>Sparta</em></p>\n" } void multiMarkdown() { MutableDataHolder options = new MutableDataSet(); options.setFrom(ParserEmulationProfile.MULTI_MARKDOWN); Parser parser = Parser.builder(options).build(); HtmlRenderer renderer = HtmlRenderer.builder(options).build(); Node document = parser.parse("This is *Sparta*"); renderer.render(document); // "<p>This is <em>Sparta</em></p>\n" } void markdown() { MutableDataHolder options = new MutableDataSet(); options.setFrom(ParserEmulationProfile.MARKDOWN); Parser parser = Parser.builder(options).build(); HtmlRenderer renderer = HtmlRenderer.builder(options).build(); Node document = parser.parse("This is *Sparta*"); renderer.render(document); // "<p>This is <em>Sparta</em></p>\n" } }
This uses the parser and renderer with default options. Both builders have methods for configuring their behavior, e.g. calling escapeHtml(true)
on HtmlRenderer
will escape raw HTML tags and blocks. For all available options, see methods on the builders.
Note that this library does not try to sanitize the resulting HTML; that is the responsibility of the caller.
Despite its name, commonmark is neither a superset nor a subset of other markdown flavors. Rather, it proposes a standard, unambiguous syntax specification for the original, "core" Markdown, thus effectively introducing yet another flavor. While flexmark is by default commonmark compliant, its parser can be tweaked in various ways. The sets of tweaks required to emulate the most commonly used markdown parsers around are available in flexmark as ParserEmulationProfiles.
As the name ParserEmulationProfile
implies, it's only the parser that is adjusted to the specific markdown flavor. Applying the profile does not add features beyond those available in commonmark. If you want to use flexmark to fully emulate another markdown processor's behavior, you have to adjust the parser and configure the flexmark extensions that provide the additional features available in the parser that you want to emulate.
Source: VisitorSample.java
package com.vladsch.flexmark.samples; import com.vladsch.flexmark.ast.Text; import com.vladsch.flexmark.parser.Parser; import com.vladsch.flexmark.util.ast.Node; import com.vladsch.flexmark.util.ast.NodeVisitor; import com.vladsch.flexmark.util.ast.VisitHandler; @SuppressWarnings({ "unchecked", "WeakerAccess" }) public class VisitorSample { int wordCount; // example of visitor for a node or nodes, just add VisitHandlers<> to the list // any node type not handled by the visitor will default to visiting its children NodeVisitor visitor = new NodeVisitor( new VisitHandler<>(Text.class, this::visit) ); public void visit(Text text) { // This is called for all Text nodes. Override other visit handlers for other node types. wordCount += text.getChars().unescape().split("\\W+").length; // Descending into children visitor.visitChildren(text); // Count words (this is just an example, don't actually do it this way for various reasons). } void countWords() { Parser parser = Parser.builder().build(); Node document = parser.parse("Example\n=======\n\nSome more text"); visitor.visit(document); System.out.println(wordCount); // 4 } }Customize HTML attributes via Attribute Provider
Source: AttributeProviderSample.java
package com.vladsch.flexmark.samples; import com.vladsch.flexmark.ast.AutoLink; import com.vladsch.flexmark.util.ast.Node; import com.vladsch.flexmark.ext.autolink.AutolinkExtension; import com.vladsch.flexmark.html.AttributeProvider; import com.vladsch.flexmark.html.AttributeProviderFactory; import com.vladsch.flexmark.html.HtmlRenderer; import com.vladsch.flexmark.html.IndependentAttributeProviderFactory; import com.vladsch.flexmark.html.renderer.AttributablePart; import com.vladsch.flexmark.html.renderer.NodeRendererContext; import com.vladsch.flexmark.parser.Parser; import com.vladsch.flexmark.util.html.Attributes; import com.vladsch.flexmark.util.data.MutableDataHolder; import com.vladsch.flexmark.util.data.MutableDataSet;import org.jetbrains.annotations.NotNull; import java.util.Arrays;import java.util.Collections; public class AttributeProviderSample { static class SampleExtension implements HtmlRenderer.HtmlRendererExtension { @Override public void rendererOptions(@NotNull final MutableDataHolder options) { // add any configuration settings to options you want to apply to everything, here } @Override public void extend(final HtmlRenderer.Builder rendererBuilder, @NotNull final String rendererType) { rendererBuilder.attributeProviderFactory(SampleAttributeProvider.Factory()); } static SampleExtension create() { return new SampleExtension(); } } static class SampleAttributeProvider implements AttributeProvider { @Override public void setAttributes(@NotNull final Node node, @NotNull final AttributablePart part, @NotNull final Attributes attributes) { if (node instanceof AutoLink && part == AttributablePart.LINK) { // Put info in custom attribute instead attributes.replaceValue("class", "my-autolink-class"); } } static AttributeProviderFactory Factory() { return new IndependentAttributeProviderFactory() { @Override public AttributeProvider create(NodeRendererContext context) { //noinspection ReturnOfInnerClass return new SampleAttributeProvider(); } }; } } static String commonMark(String markdown) { MutableDataHolder options = new MutableDataSet(); options.set(Parser.EXTENSIONS, Collections.singletonList(new Extension[] { AutolinkExtension.create(), SampleExtension.create() })); // change soft break to hard break options.set(HtmlRenderer.SOFT_BREAK, "<br/>"); Parser parser = Parser.builder(options).build(); Node document = parser.parse(markdown); HtmlRenderer renderer = HtmlRenderer.builder(options).build(); final String html = renderer.render(document); return html; } public static void main(String[] args) { String html = commonMark("http://github.com/vsch/flexmark-java"); System.out.println(html); // output: <p><a href="http://github.com/vsch/flexmark-java" class="my-autolink-class">http://github.com/vsch/flexmark-java</a></p> html = commonMark("hello\nworld"); System.out.println(html); // output: <p>hello<br/>world</p> } }Include Markdown and HTML File Content
Source: JekyllIncludeFileSample.java
Jekyll tag extension can be used to include content using the {% include file %}
syntax. Although the extension does not actually include the file since this operation is application dependent, it does provide everything necessary to allow your application to easily add this functionality.
In the code below, a hash map is used for file to file content mapping where you would include your own code to resolve the included file name to actual content and determine whether the file requires markdown conversion to HTML or should be included as is.
Markdown include sample is effectively:
Included File test.md
## Included Heading Included paragraph [ref]: http://example.com
Main Document
http://github.com/vsch/flexmark-java [ref] {% include test.md %}
Rendered Html
<p><a href="http://github.com/vsch/flexmark-java">http://github.com/vsch/flexmark-java</a></p> <p><a href="http://example.com">ref</a></p> <h2>Included Heading</h2> <p>Included paragraph</p>
Raw content include sample is effectively:
Included File test.html
Main Document
http://github.com/vsch/flexmark-java [ref] {% include test.html %}
Rendered Html
<p><a href="http://github.com/vsch/flexmark-java">http://github.com/vsch/flexmark-java</a></p> <p>[ref]</p> <p>some text</p>
package com.vladsch.flexmark.samples; import com.vladsch.flexmark.ext.autolink.AutolinkExtension; import com.vladsch.flexmark.ext.jekyll.tag.JekyllTag; import com.vladsch.flexmark.ext.jekyll.tag.JekyllTagExtension; import com.vladsch.flexmark.html.HtmlRenderer; import com.vladsch.flexmark.parser.Parser; import com.vladsch.flexmark.util.ast.Document; import com.vladsch.flexmark.util.data.MutableDataHolder; import com.vladsch.flexmark.util.data.MutableDataSet; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; public class JekyllIncludeFileSample { static String commonMark(String markdown, Map<String, String> included) { MutableDataHolder options = new MutableDataSet(); options.set(Parser.EXTENSIONS, Collections.singletonList(new Extension[] { AutolinkExtension.create(), JekyllTagExtension.create() })); // change soft break to hard break options.set(HtmlRenderer.SOFT_BREAK, "<br/>"); Parser parser = Parser.builder(options).build(); HtmlRenderer renderer = HtmlRenderer.builder(options).build(); Document document = parser.parse(markdown); // see if document has includes Document doc = document; if (doc.contains(JekyllTagExtension.TAG_LIST)) { List<JekyllTag> tagList = JekyllTagExtension.TAG_LIST.get(doc); Map<String, String> includeHtmlMap = new HashMap<String, String>(); for (JekyllTag tag : tagList) { String includeFile = tag.getParameters().toString(); if (tag.getTag().equals("include") && !includeFile.isEmpty() && !includeHtmlMap.containsKey(includeFile)) { // see if it exists if (included.containsKey(includeFile)) { // have the file String text = included.get(includeFile); if (includeFile.endsWith(".md")) { Document includeDoc = parser.parse(text); String includeHtml = renderer.render(includeDoc); includeHtmlMap.put(includeFile, includeHtml); // copy any definition of reference elements from included file to our document parser.transferReferences(doc, includeDoc, null); } else { includeHtmlMap.put(includeFile, text); } } } if (!includeHtmlMap.isEmpty()) { doc.set(JekyllTagExtension.INCLUDED_HTML, includeHtmlMap); } } } String html = renderer.render(document); return html; } public static void main(String[] args) { Map<String, String> included = new HashMap<>(); included.put("test.md", "## Included Heading\n" + "\n" + "Included paragraph\n" + "\n" + "[ref]: http://example.com\n" + ""); included.put("test.html", "<p>some text</p>\n" + ""); String html = commonMark("http://github.com/vsch/flexmark-java\n" + "\n" + "[ref]\n" + "\n" + "{% include test.md %}\n" + "\n" + "", included); System.out.println(html); html = commonMark("http://github.com/vsch/flexmark-java\n" + "\n" + "[ref]\n" + "\n" + "{% include test.html %}\n" + "\n" + "", included); System.out.println(html); } }Render AST as Markdown with Formatting Options
Source: PegdownToCommonMark.java.
The flexmark-formatter
module renders the AST as markdown with various formatting options to clean up and make the source consistent. This also comes with an API to allow extensions to provide formatting options and and handle rendering of markdown for custom nodes.
The Formatter
class is a renderer that outputs markdown and formats it to specified options. Use it in place of HtmlRenderer
to get formatted markdown. It can also be used to convert indentations from one ParserEmulationProfile
to another:
package com.vladsch.flexmark.samples; import com.vladsch.flexmark.util.ast.Node; import com.vladsch.flexmark.formatter.Formatter; import com.vladsch.flexmark.parser.Parser; import com.vladsch.flexmark.profile.pegdown.Extensions; import com.vladsch.flexmark.profile.pegdown.PegdownOptionsAdapter; import com.vladsch.flexmark.util.data.DataHolder; import com.vladsch.flexmark.util.data.MutableDataSet; public class PegdownToCommonMark { final private static DataHolder OPTIONS = PegdownOptionsAdapter.flexmarkOptions( Extensions.ALL ); static final MutableDataSet FORMAT_OPTIONS = new MutableDataSet(); static { // copy extensions from Pegdown compatible to Formatting FORMAT_OPTIONS.set(Parser.EXTENSIONS, Parser.EXTENSIONS.get(OPTIONS)); } static final Parser PARSER = Parser.builder(OPTIONS).build(); static final Formatter RENDERER = Formatter.builder(FORMAT_OPTIONS).build(); // use the PARSER to parse and RENDERER to parse pegdown indentation rules and render CommonMark public static void main(String[] args) { final String pegdown = "#Heading\n" + "-----\n" + "paragraph text \n" + "lazy continuation\n" + "\n" + "* list item\n" + " > block quote\n" + " lazy continuation\n" + "\n" + "~~~info\n" + " with uneven indent\n" + " with uneven indent\n" + " indented code\n" + "~~~ \n" + "\n" + " with uneven indent\n" + " with uneven indent\n" + " indented code\n" + "1. numbered item 1 \n" + "1. numbered item 2 \n" + "1. numbered item 3 \n" + " - bullet item 1 \n" + " - bullet item 2 \n" + " - bullet item 3 \n" + " 1. numbered sub-item 1 \n" + " 1. numbered sub-item 2 \n" + " 1. numbered sub-item 3 \n" + " \n" + " ~~~info\n" + " with uneven indent\n" + " with uneven indent\n" + " indented code\n" + " ~~~ \n" + " \n" + " with uneven indent\n" + " with uneven indent\n" + " indented code\n" + ""; System.out.println("pegdown\n"); System.out.println(pegdown); Node document = PARSER.parse(pegdown); String commonmark = RENDERER.render(document); System.out.println("\n\nCommonMark\n"); System.out.println(commonmark); } }
will convert pegdown 4 space indent to CommonMark list item text column indent.
#Heading
-----
paragraph text
lazy continuation
* list item
> block quote
lazy continuation
~~~info
with uneven indent
with uneven indent
indented code
~~~
with uneven indent
with uneven indent
indented code
1. numbered item 1
1. numbered item 2
1. numbered item 3
- bullet item 1
- bullet item 2
- bullet item 3
1. numbered sub-item 1
1. numbered sub-item 2
1. numbered sub-item 3
~~~info
with uneven indent
with uneven indent
indented code
~~~
with uneven indent
with uneven indent
indented code
Converted to CommonMark indents, ATX heading spaces added, blank lines added, fenced and indented code indents minimized:
# Heading
-----
paragraph text
lazy continuation
* list item
> block quote
> lazy continuation
~~~info
with uneven indent
with uneven indent
indented code
~~~
with uneven indent
with uneven indent
indented code
1. numbered item 1
2. numbered item 2
3. numbered item 3
- bullet item 1
- bullet item 2
- bullet item 3
1. numbered sub-item 1
2. numbered sub-item 2
3. numbered sub-item 3
~~~info
with uneven indent
with uneven indent
indented code
~~~
with uneven indent
with uneven indent
indented code
Source: PdfConverter.java.
The flexmark-pdf-converter
module renders HTML to PDF using Open HTML To PDF
package com.vladsch.flexmark.samples; import com.vladsch.flexmark.util.ast.Node; import com.vladsch.flexmark.html.HtmlRenderer; import com.vladsch.flexmark.parser.Parser; import com.vladsch.flexmark.parent.PdfConverterExtension; import com.vladsch.flexmark.profile.pegdown.Extensions; import com.vladsch.flexmark.profile.pegdown.PegdownOptionsAdapter; import com.vladsch.flexmark.util.data.DataHolder; import org.apache.commons.io.IOUtils; import java.io.IOException; import java.io.InputStream; import java.io.StringWriter; public class PdfConverter { static final DataHolder OPTIONS = PegdownOptionsAdapter.flexmarkOptions( Extensions.ALL & ~(Extensions.ANCHORLINKS | Extensions.EXTANCHORLINKS_WRAP) ).toImmutable(); static String getResourceFileContent(String resourcePath) { StringWriter writer = new StringWriter(); getResourceFileContent(writer, resourcePath); return writer.toString(); } private static void getResourceFileContent(final StringWriter writer, final String resourcePath) { InputStream inputStream = com.vladsch.flexmark.java.samples.PdfConverter.class.getResourceAsStream(resourcePath); try { IOUtils.copy(inputStream, writer, "UTF-8"); inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) { final String pegdown = "#Heading\n" + "-----\n" + "paragraph text \n" + "lazy continuation\n" + "\n" + "* list item\n" + " > block quote\n" + " lazy continuation\n" + "\n" + "~~~info\n" + " with uneven indent\n" + " with uneven indent\n" + "indented code\n" + "~~~ \n" + "\n" + " with uneven indent\n" + " with uneven indent\n" + " indented code\n" + "1. numbered item 1 \n" + "1. numbered item 2 \n" + "1. numbered item 3 \n" + " - bullet item 1 \n" + " - bullet item 2 \n" + " - bullet item 3 \n" + " 1. numbered sub-item 1 \n" + " 1. numbered sub-item 2 \n" + " 1. numbered sub-item 3 \n" + " \n" + " ~~~info\n" + " with uneven indent\n" + " with uneven indent\n" + " indented code\n" + " ~~~ \n" + " \n" + " with uneven indent\n" + " with uneven indent\n" + " indented code\n" + ""; System.out.println("pegdown\n"); System.out.println(pegdown); final Parser PARSER = Parser.builder(OPTIONS).build(); final HtmlRenderer RENDERER = HtmlRenderer.builder(OPTIONS).build(); Node document = PARSER.parse(pegdown); String html = RENDERER.render(document); html = "<!DOCTYPE html><html><head><meta charset=\"UTF-8\">\n" + "\n" + // add your stylesheets, scripts styles etc. "</head><body>" + html + "\n" + "</body></html>"; PdfConverterExtension.exportToPdf("~/flexmark-java.pdf", html,"", OPTIONS); } }
#Heading
-----
paragraph text
lazy continuation
* list item
> block quote
lazy continuation
~~~info
with uneven indent
with uneven indent
indented code
~~~
with uneven indent
with uneven indent
indented code
1. numbered item 1
1. numbered item 2
1. numbered item 3
- bullet item 1
- bullet item 2
- bullet item 3
1. numbered sub-item 1
1. numbered sub-item 2
1. numbered sub-item 3
~~~info
with uneven indent
with uneven indent
indented code
~~~
with uneven indent
with uneven indent
indented code
See PDF Renderer Converter for details on rendering non-latin character sets.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4