一、前言

Markdown是一种用来书写结构化文档的纯文本格式,吸收了很多在电子邮件中已有的纯文本标记的特性。CommonMark主要让Markdown语法更明确。同时CommonMark还提供了一个测试工具spec_tests.py或者SpecTestCase.java对Markdown程序进行测试。

二、引入依赖

1
2
3
4
5
6
7
8
9
10
11
12
        <!-- https://mvnrepository.com/artifact/com.atlassian.commonmark/commonmark -->
<dependency>
<groupId>com.atlassian.commonmark</groupId>
<artifactId>commonmark</artifactId>
<version>0.15.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.atlassian.commonmark/commonmark-ext-gfm-tables -->
<dependency>
<groupId>com.atlassian.commonmark</groupId>
<artifactId>commonmark-ext-gfm-tables</artifactId>
<version>0.15.2</version>
</dependency>

注意:如果需要其他相关插件,可以引入对应的依赖。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
        <!-- https://mvnrepository.com/artifact/com.atlassian.commonmark/commonmark-ext-heading-anchor -->
<dependency>
<groupId>com.atlassian.commonmark</groupId>
<artifactId>commonmark-ext-heading-anchor</artifactId>
<version>0.15.2</version>
</dependency>

<!-- https://mvnrepository.com/artifact/com.atlassian.commonmark/commonmark-ext-gfm-strikethrough -->
<dependency>
<groupId>com.atlassian.commonmark</groupId>
<artifactId>commonmark-ext-gfm-strikethrough</artifactId>
<version>0.15.2</version>
</dependency>
<dependency>
<groupId>com.atlassian.commonmark</groupId>
<artifactId>commonmark-ext-autolink</artifactId>
<version>0.15.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.atlassian.commonmark/commonmark-ext-yaml-front-matter -->
<dependency>
<groupId>com.atlassian.commonmark</groupId>
<artifactId>commonmark-ext-yaml-front-matter</artifactId>
<version>0.15.2</version>
</dependency>

三、使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
public abstract class MarkdownUtil {

public static List<Extension> extensions = Arrays.asList(TablesExtension.create());
private static final Parser parser = Parser.builder().extensions(extensions).build();

/**
* 对已经有的标签进行改造
*
* @param markdown
* @return
*/
private static final HtmlRenderer renderer = HtmlRenderer.builder().extensions(extensions)
.nodeRendererFactory(context -> new NodeRenderer() {

@Override
public Set<Class<? extends Node>> getNodeTypes() {
return Collections.singleton(FencedCodeBlock.class);
}

@Override
public void render(Node node) {
HtmlWriter html = context.getWriter();
FencedCodeBlock codeBlock = (FencedCodeBlock) node;
Map<String, String> attrs = new HashMap<>();
if (!StringUtils.isEmpty(codeBlock.getInfo())) {
attrs.put("class", "language-" + codeBlock.getInfo());
}
html.line();
html.tag("pre");
html.tag("code", attrs);
html.tag("ol");
String data = codeBlock.getLiteral();
String[] split = data.split("\n");
for (String s : split) {
html.tag("li");
html.text(s + "\n");
html.tag("/li");
}
html.tag("/ol");
html.tag("/code");
html.tag("/pre");
html.line();
}
})
.nodeRendererFactory(context -> new NodeRenderer() {

@Override
public Set<Class<? extends Node>> getNodeTypes() {
// TODO Auto-generated method stub
return Collections.singleton(BlockQuote.class);
}

@Override
public void render(Node node) {
// TODO Auto-generated method stub
HtmlWriter html = context.getWriter();
BlockQuote blockQuote = (BlockQuote) node;
Text text = (Text)blockQuote.getFirstChild().getFirstChild();
Map<String, String> attrs = new HashMap<>();
attrs.put("class", "language-json hljs");
Map<String, String> attrs1 = new HashMap<>();
attrs1.put("type", "a");
html.line();
html.tag("pre");
html.tag("code", attrs);
html.tag("ol",attrs1);
getText(html,text);
html.tag("/ol");
html.tag("/code");
html.tag("/pre");
html.line();
}
})
.nodeRendererFactory(context -> new NodeRenderer() {
@Override
public Set<Class<? extends Node>> getNodeTypes() {
return Collections.singleton(Image.class);
}

@Override
public void render(Node node) {
HtmlWriter html = context.getWriter();
Image image = (Image) node;
Map<String, String> attrs = new HashMap<>();
Map<String, String> attrs2 = new HashMap<>();
attrs.put("href", image.getDestination());
attrs2.put("src", image.getDestination());
html.line();
html.tag("a", attrs);
html.tag("image", attrs2);
html.tag("/a");
html.line();
}
})
.attributeProviderFactory(context -> (node, s, map) -> {
if ("p".equals(s) && node.getParent() instanceof ListItem) {
map.put("class", "show-line");
}
})
.softbreak("<br/>") // 这样设置就可以实现回车一次就换行
.build();

/**
** 增加扩展[标题锚点,表格生成] Markdown转换成HTML
*
* @param markdown
* @return
*/
public static String markdownToHtmlExtensions(String markdown) {
// h标题生成id
Set<Extension> headingAnchorExtensions = Collections.singleton(HeadingAnchorExtension.create());
// 转换table的HTML
List<Extension> tableExtension = Arrays.asList(TablesExtension.create());
Parser parser = Parser.builder().extensions(tableExtension).build();
Node document = parser.parse(markdown);
HtmlRenderer renderer = HtmlRenderer.builder().extensions(headingAnchorExtensions).extensions(tableExtension)
.attributeProviderFactory(new AttributeProviderFactory() {
public AttributeProvider create(AttributeProviderContext context) {
return new CustomAttributeProvider();
}
}).build();
return renderer.render(document);
}

/**
* 处理标签的属性
*/
static class CustomAttributeProvider implements AttributeProvider {
@Override
public void setAttributes(Node node, String tagName, Map<String, String> attributes) {
// 改变a标签的target属性为_blank
if (node instanceof Link) {
attributes.put("target", "_blank");
}
if (node instanceof TableBlock) {
attributes.put("class", "ui celled table");
}
if (node instanceof Image) {
attributes.put("style", "width:150px;height:200px;position:relative;left:50%;margin-left:-100px;");
}
}
}
/*
* 通过迭代方式获取某一个节点下所有内容
*/
public static void getText(HtmlWriter html,Text text){
html.tag("li");
html.text(text.getLiteral() + "\n");
html.tag("/li");
if(text.getNext()==null) return;
getText(html,(Text)text.getNext().getNext());
}

/**
* markdown 转 html
*
* @param markdown
* @return
*/
public static String md2html(String markdown) {
Node document = parser.parse(markdown);
String result = renderer.render(document);
return result;
}
}

使用:调用其方法就可以了