commonmark-java_CommonMark的Java实现,一种Markdown格式的规范

commonmark-java

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

68747470733a2f2f696d672e736869656c64732e696f2f6d6176656e2d63656e7472616c2f762f636f6d2e61746c61737369616e2e636f6d6d6f6e6d61726b2f636f6d6d6f6e6d61726b2e73766768747470733a2f2f7777772e6a617661646f632e696f2f62616467652f636f6d2e61746c61737369616e2e636f6d6d6f6e6d61726b2f636f6d6d6f6e6d61726b2e7376673f636f6c6f723d626c756568747470733a2f2f7472617669732d63692e6f72672f61746c61737369616e2f636f6d6d6f6e6d61726b2d6a6176612e7376673f6272616e63683d6d617374657268747470733a2f2f636f6465636f762e696f2f67682f61746c61737369616e2f636f6d6d6f6e6d61726b2d6a6176612f6272616e63682f6d61737465722f67726170682f62616467652e73766768747470733a2f2f736f757263657370792e636f6d2f736869656c642e737667

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:

Small (core has no dependencies, extensions in separate artifacts)

Fast (10-20 times faster than pegdown, 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 8 and Java 9. It should work on Java 7 and Android too, but that is on a best-effort basis, please report problems. For Android the minimum API level is 15, see the commonmark-android-test directory.

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

com.atlassian.commonmark

commonmark

0.15.0

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.

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.

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 *Sparta*");

HtmlRenderer renderer = HtmlRenderer.builder().build();

renderer.render(document); // "

This is Sparta

\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 and 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.

For rendering to plain text, there's also a TextContentRenderer with a very similar API.

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

// "

\"text\"

\n"

class ImageAttributeProvider implements AttributeProvider {

@Override

public void setAttributes(Node node, String tagName, Map 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);

// "

Example:

\n
code\n
\n"

class IndentedCodeBlockNodeRenderer implements NodeRenderer {

private final HtmlWriter html;

IndentedCodeBlockNodeRenderer(HtmlNodeRendererContext context) {

this.html = context.getWriter();

}

@Override

public Set> getNodeTypes() {

// Return the node types we want to use this renderer for.

return Collections.>singleton(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.

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

com.atlassian.commonmark

commonmark-ext-gfm-tables

0.15.0

Then, configure the extension on the builders:

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

List extensions = Arrays.asList(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:

Heading

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

text

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:

  • task #1
  • task #2

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

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

License

Copyright (c) 2015-2019 Atlassian and others.

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值