1. maven
<!-- 核心 -->
<dependency>
<groupId>com.atlassian.commonmark</groupId>
<artifactId>commonmark</artifactId>
<version>0.15.0</version>
</dependency>
<!-- 表格-->
<dependency>
<groupId>com.atlassian.commonmark</groupId>
<artifactId>commonmark-ext-gfm-tables</artifactId>
<version>0.15.0</version>
</dependency>
<!-- url格式的文本转成链接-->
<dependency>
<groupId>com.atlassian.commonmark</groupId>
<artifactId>commonmark-ext-autolink</artifactId>
<version>0.15.0</version>
</dependency>
<!-- 删除线插件-->
<dependency>
<groupId>com.atlassian.commonmark</groupId>
<artifactId>commonmark-ext-gfm-strikethrough</artifactId>
<version>0.15.0</version>
</dependency>
<!-- 图片解析插件-->
<dependency>
<groupId>com.atlassian.commonmark</groupId>
<artifactId>commonmark-ext-image-attributes</artifactId>
<version>0.15.0</version>
</dependency>
<!-- 图片解析插件-->
<dependency>
<groupId>com.atlassian.commonmark</groupId>
<artifactId>commonmark-ext-heading-anchor</artifactId>
<version>0.15.0</version>
</dependency>
<!-- 下划线解析插件-->
<dependency>
<groupId>com.atlassian.commonmark</groupId>
<artifactId>commonmark-ext-ins</artifactId>
<version>0.15.0</version>
</dependency>
<!-- 任务列表解析插件-->
<dependency>
<groupId>com.atlassian.commonmark</groupId>
<artifactId>commonmark-ext-task-list-items</artifactId>
<version>0.15.0</version>
</dependency>
<!-- YAML格式数据解析插件-->
<dependency>
<groupId>com.atlassian.commonmark</groupId>
<artifactId>commonmark-ext-yaml-front-matter</artifactId>
<version>0.15.0</version>
</dependency>
2. API
2.1 基础API
类 | 描述 | 方法 | 描述 |
---|---|---|---|
Parser | 用于解析markdown的对象 | builder() | 静态方法,获取Parser构造器对象 |
parse(String input) | 解析字符串为Node对象 | ||
parseReader(Reader input) | 解析流文本为Node对象 | ||
Parser.Builder | Parser对象构造器对象 | extensions(Iterable<? extends Extension> e) | 添加扩展 |
enabledBlockTypes(Set<Class<? extends Block>> t) | 设置启用的块类型 | ||
customBlockParserFactory(BlockParserFactory b) | 添加自定义块解析工厂 | ||
customDelimiterProcessor(DelimiterProcessor d) | 添加自定义边界处理器 | ||
postProcessor(PostProcessor postProcessor) | 添加后处理器 | ||
inlineParserFactory(InlineParserFactory i) | 添加内联解析工厂 | ||
build() | 构建Parser对象 | ||
HtmlRenderer | html渲染对象 | builder() | 静态方法,获取HtmlRenderer构造器对象 |
render(Node node, Appendable output) | 渲染为html代码,可追加 例如:StringBuilder对象 | ||
render(Node node) | 渲染为html代码 | ||
HtmlRenderer.Builder | HtmlRenderer对象构造器对象 | softbreak(String softbreak) | 软中断 |
escapeHtml(boolean escapeHtml) | html是否转移 | ||
sanitizeUrls(boolean sanitizeUrls) | 是否对url进行处理 | ||
urlSanitizer(UrlSanitizer urlSanitizer) | 设置url处理器 | ||
attributeProviderFactory(AttributeProviderFactory a) | 属性提供工厂,可用于添加与修改标签属性 | ||
nodeRendererFactory(HtmlNodeRendererFactory n) | 节点渲染工厂 | ||
percentEncodeUrls(boolean percentEncodeUrls) | 对url是否编码 | ||
extensions(Iterable<? extends Extension> e) | 添加扩展, 必须和Parser配置一致 | ||
build() | 构建HtmlRenderer对象 | ||
TextContentRenderer | 文本内容渲染对象 | builder() | 静态方法,获取TextContentRenderer构造器对象 |
render(Node node, Appendable output) | 渲染文本内容,可追加 例如:StringBuilder对象 | ||
render(Node node) | 渲染为文本内容 | ||
TextContentRenderer.Builder | TextContentRenderer对象构造器对象 | build() | 构建TextContentRenderer对象 |
stripNewlines(boolean stripNewlines) | 是否换行 | ||
nodeRendererFactory(TextContentNodeRendererFactory n) | 节点渲染工厂 | ||
extensions(Iterable<? extends Extension> e) | 添加扩展, 必须和Parser配置一致 | ||
Node | 节点对象 | getFirstChild() | 获取第一个子元素 |
getLastChild() | 获取最后一个子元素 | ||
getParent() | 获取父级元素 | ||
getNext() | 获取同级下一个元素 | ||
getPrevious() | 获取同级上一个元素 | ||
accept(Visitor var1) | |||
appendChild(Node child) | 在最后添加子级元素 | ||
prependChild(Node child) | 在最前添加子级元素 | ||
insertAfter(Node sibling) | 在当前元素后添加元素,根元素不可用 | ||
insertBefore(Node sibling) | 在当前元素前添加元素,根元素不可用 | ||
unlink() |
2.2 扩展API
类 | 描述 |
---|---|
TablesExtension | 表格解析,通过静态方法create()获取对象 |
ImageAttributesExtension | 图片解析,通过静态方法create()获取对象 |
AutolinkExtension | url格式的文本转成链接,通过静态方法create()获取对象 |
StrikethroughExtension | 删除线解析,通过静态方法create()获取对象 |
HeadingAnchorExtension | 航向锚,自动添加biaod通过静态方法create()获取对象 |
InsExtension | 下划线解析通过静态方法create()获取对象 |
YamlFrontMatterExtension | yaml数据解析,通过静态方法create()获取对象 |
TaskListItemsExtension | 任务列表解析,通过静态方法create()获取对象 |
2.3 Node实现类
实现类 | 描述 | markdown语法 | html语法 |
---|---|---|---|
Document | 文档 | ||
Paragraph | 段落 | <p></p> | |
Emphasis | 突出 | *斜体* _斜体_ ***粗斜体*** ___粗斜体___ | <em></em><strong></strong> |
StrongEmphasis | 加粗突出 | **粗体** __粗体__ | <strong></strong> |
Heading | 标题 | # 一级标题 ## 二级标题 ...... | <h1></h1> |
ThematicBreak | 分隔线 | --- ___ *** | <hr/> |
Text | 文本 | ||
Strikethrough | 删除线 | ~~删除线~~ | <del></del> |
ListItem | 列表项 | <li></li> | |
BulletList | 无序列表 | * 无序列表 | <ul></ul> |
OrderedList | 有序列表 | 1. 有序列表 | <ol></ol> |
BlockQuote | 区块 | > 区块 | <blockquote></blockquote> |
Code | 代码块 | `int i = 0;` | <code> </code> |
FencedCodeBlock | 围框代码块 | ````java ```` | <code class="language-java"> </code> |
Link | 超链接 | [百度](www.baidu.com) | <a href="www.baidu.com">百度</a> |
Image | 图片 | ![属性文本](url "可选标题") | <img src="url" alt="属性文本" title="可选标题" /> |
TableBlock | 表格 | | 左对齐 | 右对齐 | 居中对齐 | | :-----| ----: | :----: | | 单元格 | 单元格 | 单元格 | | <table></table> |
TableHead | 表头 | <thead></thead> | |
TableBody | 表格内容 | <tbody></tbody> | |
TableRow | 表格列 | <tr></tr> | |
TableCell | 表格单元格 | <th></th> <td></td> | |
HardLineBreak | |||
HtmlBlock | html块 | <html></html> | |
HtmlInline | html下滑线 | <ins></ins> | |
ImageAttributes | |||
IndentedCodeBlock | |||
Ins | 下划线 | ++you++ | <ins></ins> |
SoftLineBreak | |||
TaskListItemMarker | |||
YamlFrontMatterBlock | |||
YamlFrontMatterNode |
3 示例
@Test
public void testdeom() throws IOException {
List<Extension> extensions = Arrays.asList(
TablesExtension.create(),
ImageAttributesExtension.create(),
AutolinkExtension.create(),
StrikethroughExtension.create(),
HeadingAnchorExtension.create(),
InsExtension.create(),
YamlFrontMatterExtension.create(),
TaskListItemsExtension.create()
);
HashSet enabledBlockTypes = new HashSet(Arrays.asList(
Document.class,Image.class,Link.class,Paragraph.class,Text.class
));
Parser parser = Parser.builder()
// .enabledBlockTypes(enabledBlockTypes)//添加启用块,会报错,暂时不知怎么用
.extensions(extensions)
.postProcessor(new MyPostProcessor())//对解析后的 Node 对象进行处理
.inlineParserFactory(new MyInlineParserFactory())//用于自定义 markdown字符串解析
.customBlockParserFactory(new MyBlockParserFactory())
.customDelimiterProcessor(new MyDelimiterProcessor())
.build();
HtmlRenderer renderer = HtmlRenderer.builder()
.extensions(extensions)//设置扩展
.sanitizeUrls(true)//是否url处理
.urlSanitizer(new MyUrlSanitizer())//设置自定义url处理器
.attributeProviderFactory(new MyAttributeProviderFactory())//设置元素提供工厂
.nodeRendererFactory(new MyHtmlNodeRendererFactory())//设置节点渲染工厂
.escapeHtml(false)//html转码
.softbreak("<br/>")
.percentEncodeUrls(false)//url编码处理
.build();
InputStreamReader inputStreamReader=new InputStreamReader(new FileInputStream("E:\\develop\\DEMO.md"));
Node node = parser.parseReader(inputStreamReader);
String render = renderer.render(node);
System.out.println( render);
}
添加html属性
package com.example.project.demo;
import org.commonmark.renderer.html.AttributeProvider;
import org.commonmark.renderer.html.AttributeProviderContext;
import org.commonmark.renderer.html.AttributeProviderFactory;
/**
* 自定义属性提供工厂
**/
public class MyAttributeProviderFactory implements AttributeProviderFactory {
@Override
public AttributeProvider create(AttributeProviderContext attributeProviderContext) {
return new MyAttributeProvider();
}
}
package com.example.project.demo;
import org.commonmark.node.Image;
import org.commonmark.node.Link;
import org.commonmark.node.Node;
import org.commonmark.renderer.html.AttributeProvider;
import java.util.Map;
/**
* 自定义属性提供类
**/
public class MyAttributeProvider implements AttributeProvider {
@Override
public void setAttributes(Node node, String s, Map<String, String> map) {
if (node instanceof Image) {
map.put("style", "width:150px;height:200px;position:relative;left:50%;margin-left:-100px;");
}
if (node instanceof Link) {
map.put("target", "_blank");
}
}
}
用于修改元素节点
package com.example.project.demo;
import org.commonmark.renderer.NodeRenderer;
import org.commonmark.renderer.html.HtmlNodeRendererContext;
import org.commonmark.renderer.html.HtmlNodeRendererFactory;
/**
* 节点渲染工厂*/
public class MyHtmlNodeRendererFactory implements HtmlNodeRendererFactory {
@Override
public NodeRenderer create(HtmlNodeRendererContext htmlNodeRendererContext) {
return new MyNodeRenderer(htmlNodeRendererContext);
}
}
package com.example.project.demo;
import org.commonmark.node.IndentedCodeBlock;
import org.commonmark.node.Node;
import org.commonmark.renderer.NodeRenderer;
import org.commonmark.renderer.html.HtmlNodeRendererContext;
import org.commonmark.renderer.html.HtmlWriter;
import java.util.Collections;
import java.util.Set;
/**
* 自定义节点渲染
**/
public class MyNodeRenderer implements NodeRenderer {
private final HtmlWriter html;
MyNodeRenderer(HtmlNodeRendererContext context) {
this.html = context.getWriter();
}
@Override
public Set<Class<? extends Node>> getNodeTypes() {
//返回我们要使用此渲染器的节点类型
return Collections.<Class<? extends Node>>singleton(IndentedCodeBlock.class);
}
@Override
public void render(Node node) {
IndentedCodeBlock codeBlock = (IndentedCodeBlock) node;
html.line();
html.tag("pre");
html.text(codeBlock.getLiteral());
html.tag("/pre");
html.line();
}
}
自定义解析
package com.example.project.demo;
import org.commonmark.parser.InlineParser;
import org.commonmark.parser.InlineParserContext;
import org.commonmark.parser.InlineParserFactory;
/**
* 解析工厂
*
**/
public class MyInlineParserFactory implements InlineParserFactory {
@Override
public InlineParser create(InlineParserContext inlineParserContext) {
return new MyInlineParser(inlineParserContext);
}
}
package com.example.project.demo;
import org.commonmark.node.Node;
import org.commonmark.parser.InlineParser;
import org.commonmark.parser.InlineParserContext;
/**
* markdown字符串解析
*
**/
public class MyInlineParser implements InlineParser {
private final InlineParserContext inlineParserContext;
public MyInlineParser(InlineParserContext inlineParserContext) {
this.inlineParserContext = inlineParserContext;
}
@Override
public void parse(String markdown, Node node) {
//TODO 用于把markdown字符串转换为node
}
}
url处理
package com.example.project.demo;
import org.commonmark.renderer.html.UrlSanitizer;
/**
* url处理器
**/
public class MyUrlSanitizer implements UrlSanitizer {
@Override
public String sanitizeLinkUrl(String s) {
return s+"?demo=123456";
}
@Override
public String sanitizeImageUrl(String s) {
return s+"?demo=666666";
}
}
解析markdown后处理
package com.example.project.demo;
import org.commonmark.node.Node;
import org.commonmark.parser.Parser;
import org.commonmark.parser.PostProcessor;
/**
* 解析后处理
**/
public class MyPostProcessor implements PostProcessor {
@Override
public Node process(Node node) {
Parser parser = Parser.builder().build();
node.appendChild(parser.parse("<a>你好</a>"));
return node;
}
}