Java 操作 Markdown(1)--commonmark-java 使用
commonmark-java 是一个用于解析和渲染 Markdown 文本的 Java 库;本文主要介绍其基本使用,文中所使用到的软件版本:Java 17.0.5、commonmark-java 0.25.1。
1、简介
commonmark-java 可以用来解析抽象语法树(AST),访问和操作其节点,以及生成 HTML 或 Markdown。它最初是 commonmark.js 的移植版,但后来发展成为一个可扩展的库,具备以下特点:
- 小巧(核心没有依赖,扩展以独立的组件形式提供)
- 快速(比曾经流行的 Markdown 库
pegdown快 10 到 20 倍) - 灵活(解析后可操作 AST,定制 HTML 渲染)
- 可扩展(支持表格、删除线、自动链接等)
commonmark-java 需要使用 Java 11 及以上版本。
2、commonmark-java 使用
2.1、样例文件
解析 Markdown 时使用该样例文件。
## 1 Markdown语法教程 ### 1.1 标题 不同数量的`#`可以完成不同的标题,如下: # 一级标题 ## 二级标题 ### 三级标题 ### 1.2 字体 粗体、斜体、粗体和斜体,删除线,需要在文字前后加不同的标记符号。如下: **这个是粗体** *这个是斜体* ***这个是粗体加斜体*** ~~这里是删除线~~ 注:如果想给字体换颜色、字体或者居中显示,需要使用内嵌HTML来实现。 ### 1.3 无序列表 无序列表的使用,在符号`-`后加空格使用。如下: - 无序列表 1 - 无序列表 2 - 无序列表 3 如果要控制列表的层级,则需要在符号`-`前使用空格。如下: - 无序列表 1 - 无序列表 2 - 无序列表 2.1 - 无序列表 2.2 ### 1.4 有序列表 有序列表的使用,在数字及符号`.`后加空格后输入内容,如下: 1. 有序列表 1 2. 有序列表 2 3. 有序列表 3 ### 1.5 引用 引用的格式是在符号`>`后面书写文字。如下: > 读一本好书,就是在和高尚的人谈话。 ——歌德 > 雇用制度对工人不利,但工人根本无力摆脱这个制度。 ——阮一峰 ### 1.7 链接 微信公众号仅支持公众号文章链接,即域名为`https://mp.weixin.qq.com/`的合法链接。使用方法如下所示: 对于该论述,欢迎读者查阅之前发过的文章,[你是《未来世界的幸存者》么?](https://mp.weixin.qq.com/s/s5IhxV2ooX3JN_X416nidA) ### 1.8 图片 插入图片,格式如下:  支持 jpg、png、gif、svg 等图片格式,**其中 svg 文件仅可在微信公众平台中使用**,svg 文件示例如下:  支持图片**拖拽和截图粘贴**到编辑器中。 注:支持图片 ***拖拽和截图粘贴*** 到编辑器中,仅支持 https 的图片,图片粘贴到微信时会自动上传微信服务器。 ### 1.9 分割线 可以在一行中用三个以上的减号来建立一个分隔线,同时需要在分隔线的上面空一行。如下: --- ### 1.10 表格 可以使用冒号来定义表格的对齐方式,如下: | 姓名 | 年龄 | 工作 | | :----- | :--: | -------: | | 小可爱 | 18 | 吃可爱多 | | 小小勇敢 | 20 | 爬棵勇敢树 | | 小小小机智 | 22 | 看一本机智书 |
2.2、引入依赖
<dependency> <groupId>org.commonmark</groupId> <artifactId>commonmark</artifactId> <version>0.26.0</version> </dependency> <dependency> <groupId>org.commonmark</groupId> <artifactId>commonmark-ext-gfm-tables</artifactId> <version>0.26.0</version> </dependency>
2.3、API 方式生成 HTML 或 Markdown 文档
@Test public void serialize() { Document document = new Document(); Heading heading = new Heading(); heading.setLevel(2); heading.appendChild(new Text("1 Markdown语法教程")); document.appendChild(heading); heading = new Heading(); heading.setLevel(3); heading.appendChild(new Text("1.1 标题")); document.appendChild(heading); Paragraph paragraph = new Paragraph(); paragraph.appendChild(new Text("不同数量的")); paragraph.appendChild(new Code("#")); paragraph.appendChild(new Text("可以完成不同的标题,如下:")); document.appendChild(paragraph); heading = new Heading(); heading.setLevel(1); heading.appendChild(new Text("一级标题")); document.appendChild(heading); heading = new Heading(); heading.setLevel(2); heading.appendChild(new Text("二级标题")); document.appendChild(heading); heading = new Heading(); heading.setLevel(3); heading.appendChild(new Text("三级标题")); document.appendChild(heading); heading = new Heading(); heading.setLevel(3); heading.appendChild(new Text("1.2 字体")); document.appendChild(heading); paragraph = new Paragraph(); paragraph.appendChild(new Text("粗体、斜体、粗体和斜体,删除线,需要在文字前后加不同的标记符号。如下:")); document.appendChild(paragraph); paragraph = new Paragraph(); StrongEmphasis strongEmphasis = new StrongEmphasis(); strongEmphasis.appendChild(new Text("这个是粗体")); paragraph.appendChild(strongEmphasis); document.appendChild(paragraph); paragraph = new Paragraph(); Emphasis emphasis = new Emphasis("*"); emphasis.appendChild(new Text("这个是斜体")); paragraph.appendChild(emphasis); document.appendChild(paragraph); paragraph = new Paragraph(); strongEmphasis = new StrongEmphasis(); emphasis = new Emphasis("*"); emphasis.appendChild(new Text("这个是粗体加斜体")); strongEmphasis.appendChild(emphasis); paragraph.appendChild(strongEmphasis); document.appendChild(paragraph); paragraph = new Paragraph(); paragraph.appendChild(new Text("~~这里是删除线~~")); document.appendChild(paragraph); paragraph = new Paragraph(); paragraph.appendChild(new Text("注:如果想给字体换颜色、字体或者居中显示,需要使用内嵌HTML来实现。")); document.appendChild(paragraph); heading = new Heading(); heading.setLevel(3); heading.appendChild(new Text("1.3 无序列表")); document.appendChild(heading); paragraph = new Paragraph(); paragraph.appendChild(new Text("无序列表的使用,在符号")); paragraph.appendChild(new Code("-")); paragraph.appendChild(new Text("后加空格使用。如下:")); document.appendChild(paragraph); BulletList bulletList = new BulletList(); ListItem listItem = new ListItem(); listItem.appendChild(new Text("无序列表 1")); bulletList.appendChild(listItem); bulletList.appendChild(new SoftLineBreak()); listItem = new ListItem(); listItem.appendChild(new Text("无序列表 2")); bulletList.appendChild(listItem); bulletList.appendChild(new SoftLineBreak()); listItem = new ListItem(); listItem.appendChild(new Text("无序列表 3")); bulletList.appendChild(listItem); document.appendChild(bulletList); paragraph = new Paragraph(); paragraph.appendChild(new Text("如果要控制列表的层级,则需要在符号")); paragraph.appendChild(new Code("-")); paragraph.appendChild(new Text("前使用空格。如下:")); document.appendChild(paragraph); bulletList = new BulletList(); listItem = new ListItem(); listItem.appendChild(new Text("无序列表 1")); bulletList.appendChild(listItem); bulletList.appendChild(new SoftLineBreak()); listItem = new ListItem(); listItem.appendChild(new Text("无序列表 2")); bulletList.appendChild(listItem); bulletList.appendChild(new SoftLineBreak()); BulletList bulletList2 = new BulletList(); listItem = new ListItem(); listItem.setMarkerIndent(2); listItem.appendChild(new Text("无序列表 2.1")); bulletList2.appendChild(listItem); bulletList2.appendChild(new SoftLineBreak()); listItem = new ListItem(); listItem.setMarkerIndent(2); listItem.appendChild(new Text("无序列表 2.2")); bulletList2.appendChild(listItem); bulletList.appendChild(bulletList2); document.appendChild(bulletList); heading = new Heading(); heading.setLevel(3); heading.appendChild(new Text("1.4 有序列表")); document.appendChild(heading); paragraph = new Paragraph(); paragraph.appendChild(new Text("有序列表的使用,在数字及符号")); paragraph.appendChild(new Code(".")); paragraph.appendChild(new Text("后加空格后输入内容,如下:")); document.appendChild(paragraph); OrderedList orderedList = new OrderedList(); listItem = new ListItem(); listItem.appendChild(new Text("有序列表 1")); orderedList.appendChild(listItem); orderedList.appendChild(new SoftLineBreak()); listItem = new ListItem(); listItem.appendChild(new Text("有序列表 2")); orderedList.appendChild(listItem); orderedList.appendChild(new SoftLineBreak()); listItem = new ListItem(); listItem.appendChild(new Text("有序列表 3")); orderedList.appendChild(listItem); document.appendChild(orderedList); heading = new Heading(); heading.setLevel(3); heading.appendChild(new Text("1.5 引用")); document.appendChild(heading); paragraph = new Paragraph(); paragraph.appendChild(new Text("引用的格式是在符号")); paragraph.appendChild(new Code(">")); paragraph.appendChild(new Text("后面书写文字。如下:")); document.appendChild(paragraph); BlockQuote blockQuote = new BlockQuote(); blockQuote.appendChild(new Text("读一本好书,就是在和高尚的人谈话。 ——歌德")); document.appendChild(blockQuote); blockQuote = new BlockQuote(); blockQuote.appendChild(new Text("雇用制度对工人不利,但工人根本无力摆脱这个制度。 ——阮一峰")); document.appendChild(blockQuote); heading = new Heading(); heading.setLevel(3); heading.appendChild(new Text("1.7 链接")); document.appendChild(heading); paragraph = new Paragraph(); paragraph.appendChild(new Text("微信公众号仅支持公众号文章链接,即域名为")); paragraph.appendChild(new Code("https://mp.weixin.qq.com/")); paragraph.appendChild(new Text("的合法链接。使用方法如下所示:")); document.appendChild(paragraph); paragraph = new Paragraph(); Link link = new Link("https://mp.weixin.qq.com/s/s5IhxV2ooX3JN_X416nidA", null); link.appendChild(new Text("你是《未来世界的幸存者》么?")); paragraph.appendChild(new Text("对于该论述,欢迎读者查阅之前发过的文章,")); paragraph.appendChild(link); document.appendChild(paragraph); heading = new Heading(); heading.setLevel(3); heading.appendChild(new Text("1.8 图片")); document.appendChild(heading); paragraph = new Paragraph(); paragraph.appendChild(new Text("插入图片,格式如下:")); document.appendChild(paragraph); paragraph = new Paragraph(); Image image = new Image("https://markdown.com.cn/images/qrcode_for_gh_82cf87d482f0_258.jpg", null); image.appendChild(new Text("这里写图片描述")); paragraph.appendChild(image); document.appendChild(paragraph); paragraph = new Paragraph(); paragraph.appendChild(new Text("支持 jpg、png、gif、svg 等图片格式,")); emphasis = new Emphasis("**"); emphasis.appendChild(new Text("其中 svg 文件仅可在微信公众平台中使用")); paragraph.appendChild(emphasis); paragraph.appendChild(new Text(",svg 文件示例如下:")); document.appendChild(paragraph); paragraph = new Paragraph(); image = new Image("https://markdown.com.cn/images/i-am-svg.svg", null); paragraph.appendChild(image); document.appendChild(paragraph); paragraph = new Paragraph(); paragraph.appendChild(new Text("支持图片")); strongEmphasis = new StrongEmphasis(); strongEmphasis.appendChild(new Text("拖拽和截图粘贴")); paragraph.appendChild(strongEmphasis); paragraph.appendChild(new Text("到编辑器中。")); document.appendChild(paragraph); paragraph = new Paragraph(); paragraph.appendChild(new Text("注:支持图片 ")); strongEmphasis = new StrongEmphasis(); emphasis = new Emphasis("*"); emphasis.appendChild(new Text("拖拽和截图粘贴")); strongEmphasis.appendChild(emphasis); paragraph.appendChild(strongEmphasis); paragraph.appendChild(new Text(" 到编辑器中,仅支持 https 的图片,图片粘贴到微信时会自动上传微信服务器。")); document.appendChild(paragraph); heading = new Heading(); heading.setLevel(3); heading.appendChild(new Text("1.9 分割线")); document.appendChild(heading); paragraph = new Paragraph(); paragraph.appendChild(new Text("可以在一行中用三个以上的减号来建立一个分隔线,同时需要在分隔线的上面空一行。如下:")); document.appendChild(paragraph); ThematicBreak thematicBreak = new ThematicBreak(); thematicBreak.setLiteral("---"); document.appendChild(thematicBreak); heading = new Heading(); heading.setLevel(3); heading.appendChild(new Text("1.10 表格")); document.appendChild(heading); paragraph = new Paragraph(); paragraph.appendChild(new Text("可以使用冒号来定义表格的对齐方式,如下:")); document.appendChild(paragraph); TableBlock tableBlock = new TableBlock(); TableHead tableHead = new TableHead(); TableRow tableRow = new TableRow(); TableCell tableCell = new TableCell(); tableCell.appendChild(new Text("姓名")); tableCell.setAlignment(TableCell.Alignment.LEFT); tableRow.appendChild(tableCell); tableCell = new TableCell(); tableCell.appendChild(new Text("年龄")); tableCell.setAlignment(TableCell.Alignment.CENTER); tableRow.appendChild(tableCell); tableCell = new TableCell(); tableCell.appendChild(new Text("工作")); tableCell.setAlignment(TableCell.Alignment.RIGHT); tableRow.appendChild(tableCell); tableHead.appendChild(tableRow); TableBody tableBody = new TableBody(); tableRow = new TableRow(); tableCell = new TableCell(); tableCell.appendChild(new Text("小可爱")); tableRow.appendChild(tableCell); tableCell = new TableCell(); tableCell.appendChild(new Text("18")); tableRow.appendChild(tableCell); tableCell = new TableCell(); tableCell.appendChild(new Text("吃可爱多")); tableRow.appendChild(tableCell); tableBody.appendChild(tableRow); tableRow = new TableRow(); tableCell = new TableCell(); tableCell.appendChild(new Text("小小勇敢")); tableRow.appendChild(tableCell); tableCell = new TableCell(); tableCell.appendChild(new Text("20")); tableRow.appendChild(tableCell); tableCell = new TableCell(); tableCell.appendChild(new Text("爬棵勇敢树")); tableRow.appendChild(tableCell); tableBody.appendChild(tableRow); tableRow = new TableRow(); tableCell = new TableCell(); tableCell.appendChild(new Text("小小小机智")); tableRow.appendChild(tableCell); tableCell = new TableCell(); tableCell.appendChild(new Text("22")); tableRow.appendChild(tableCell); tableCell = new TableCell(); tableCell.appendChild(new Text("看一本机智书")); tableRow.appendChild(tableCell); tableBody.appendChild(tableRow); tableBlock.appendChild(tableHead); tableBlock.appendChild(tableBody); document.appendChild(tableBlock); List<Extension> extensions = List.of(TablesExtension.create()); MarkdownRenderer markdownRenderer = MarkdownRenderer.builder().extensions(extensions).build(); //转成markdown格式 String md = markdownRenderer.render(document); System.out.println(md); HtmlRenderer htmlRenderer = HtmlRenderer.builder().extensions(extensions).build(); //转成html String html = htmlRenderer.render(document); System.out.println(html); }
2.4、解析 Markdown 文档
@Test public void deserialize() throws IOException { List<Extension> extensions = List.of(TablesExtension.create()); Parser parser = Parser.builder().extensions(extensions).build(); InputStreamReader reader = new InputStreamReader(CommonmarkCase.class.getClassLoader().getResourceAsStream("test.md")); Node document = parser.parseReader(reader); Node node = document.getFirstChild(); while (node != null) { System.out.println(node.getClass()); if (node.getClass().equals(Heading.class)) {//处理标题 Heading heading = (Heading) node; Text text = (Text)heading.getFirstChild(); System.out.println(text.getLiteral()); } else if (node.getClass().equals(BulletList.class)) {//处理无序列表 BulletList bulletList = (BulletList) node; Node node2 = bulletList.getFirstChild(); while (node2 != null) { if (node2.getClass().equals(ListItem.class)) { Node node3 = node2.getFirstChild(); if (node3.getClass().equals(Paragraph.class)) { Text text = (Text)node3.getFirstChild(); System.out.println(text.getLiteral()); } if (node3.getNext() != null && node3.getNext().getClass().equals(BulletList.class)) { System.out.println("二级无序列表"); //TODO: 继续解析 } } node2 = node2.getNext(); } } //else if ... node = node.getNext(); } }
2.5、完整代码
package com.abc.md; import lombok.extern.slf4j.Slf4j; import org.commonmark.Extension; import org.commonmark.ext.gfm.tables.*; import org.commonmark.node.*; import org.commonmark.parser.Parser; import org.commonmark.renderer.html.HtmlRenderer; import org.commonmark.renderer.markdown.MarkdownRenderer; import org.junit.Test; import java.io.IOException; import java.io.InputStreamReader; import java.util.List; @Slf4j public class CommonmarkCase { @Test public void serialize() { Document document = new Document(); Heading heading = new Heading(); heading.setLevel(2); heading.appendChild(new Text("1 Markdown语法教程")); document.appendChild(heading); heading = new Heading(); heading.setLevel(3); heading.appendChild(new Text("1.1 标题")); document.appendChild(heading); Paragraph paragraph = new Paragraph(); paragraph.appendChild(new Text("不同数量的")); paragraph.appendChild(new Code("#")); paragraph.appendChild(new Text("可以完成不同的标题,如下:")); document.appendChild(paragraph); heading = new Heading(); heading.setLevel(1); heading.appendChild(new Text("一级标题")); document.appendChild(heading); heading = new Heading(); heading.setLevel(2); heading.appendChild(new Text("二级标题")); document.appendChild(heading); heading = new Heading(); heading.setLevel(3); heading.appendChild(new Text("三级标题")); document.appendChild(heading); heading = new Heading(); heading.setLevel(3); heading.appendChild(new Text("1.2 字体")); document.appendChild(heading); paragraph = new Paragraph(); paragraph.appendChild(new Text("粗体、斜体、粗体和斜体,删除线,需要在文字前后加不同的标记符号。如下:")); document.appendChild(paragraph); paragraph = new Paragraph(); StrongEmphasis strongEmphasis = new StrongEmphasis(); strongEmphasis.appendChild(new Text("这个是粗体")); paragraph.appendChild(strongEmphasis); document.appendChild(paragraph); paragraph = new Paragraph(); Emphasis emphasis = new Emphasis("*"); emphasis.appendChild(new Text("这个是斜体")); paragraph.appendChild(emphasis); document.appendChild(paragraph); paragraph = new Paragraph(); strongEmphasis = new StrongEmphasis(); emphasis = new Emphasis("*"); emphasis.appendChild(new Text("这个是粗体加斜体")); strongEmphasis.appendChild(emphasis); paragraph.appendChild(strongEmphasis); document.appendChild(paragraph); paragraph = new Paragraph(); paragraph.appendChild(new Text("~~这里是删除线~~")); document.appendChild(paragraph); paragraph = new Paragraph(); paragraph.appendChild(new Text("注:如果想给字体换颜色、字体或者居中显示,需要使用内嵌HTML来实现。")); document.appendChild(paragraph); heading = new Heading(); heading.setLevel(3); heading.appendChild(new Text("1.3 无序列表")); document.appendChild(heading); paragraph = new Paragraph(); paragraph.appendChild(new Text("无序列表的使用,在符号")); paragraph.appendChild(new Code("-")); paragraph.appendChild(new Text("后加空格使用。如下:")); document.appendChild(paragraph); BulletList bulletList = new BulletList(); ListItem listItem = new ListItem(); listItem.appendChild(new Text("无序列表 1")); bulletList.appendChild(listItem); bulletList.appendChild(new SoftLineBreak()); listItem = new ListItem(); listItem.appendChild(new Text("无序列表 2")); bulletList.appendChild(listItem); bulletList.appendChild(new SoftLineBreak()); listItem = new ListItem(); listItem.appendChild(new Text("无序列表 3")); bulletList.appendChild(listItem); document.appendChild(bulletList); paragraph = new Paragraph(); paragraph.appendChild(new Text("如果要控制列表的层级,则需要在符号")); paragraph.appendChild(new Code("-")); paragraph.appendChild(new Text("前使用空格。如下:")); document.appendChild(paragraph); bulletList = new BulletList(); listItem = new ListItem(); listItem.appendChild(new Text("无序列表 1")); bulletList.appendChild(listItem); bulletList.appendChild(new SoftLineBreak()); listItem = new ListItem(); listItem.appendChild(new Text("无序列表 2")); bulletList.appendChild(listItem); bulletList.appendChild(new SoftLineBreak()); BulletList bulletList2 = new BulletList(); listItem = new ListItem(); listItem.setMarkerIndent(2); listItem.appendChild(new Text("无序列表 2.1")); bulletList2.appendChild(listItem); bulletList2.appendChild(new SoftLineBreak()); listItem = new ListItem(); listItem.setMarkerIndent(2); listItem.appendChild(new Text("无序列表 2.2")); bulletList2.appendChild(listItem); bulletList.appendChild(bulletList2); document.appendChild(bulletList); heading = new Heading(); heading.setLevel(3); heading.appendChild(new Text("1.4 有序列表")); document.appendChild(heading); paragraph = new Paragraph(); paragraph.appendChild(new Text("有序列表的使用,在数字及符号")); paragraph.appendChild(new Code(".")); paragraph.appendChild(new Text("后加空格后输入内容,如下:")); document.appendChild(paragraph); OrderedList orderedList = new OrderedList(); listItem = new ListItem(); listItem.appendChild(new Text("有序列表 1")); orderedList.appendChild(listItem); orderedList.appendChild(new SoftLineBreak()); listItem = new ListItem(); listItem.appendChild(new Text("有序列表 2")); orderedList.appendChild(listItem); orderedList.appendChild(new SoftLineBreak()); listItem = new ListItem(); listItem.appendChild(new Text("有序列表 3")); orderedList.appendChild(listItem); document.appendChild(orderedList); heading = new Heading(); heading.setLevel(3); heading.appendChild(new Text("1.5 引用")); document.appendChild(heading); paragraph = new Paragraph(); paragraph.appendChild(new Text("引用的格式是在符号")); paragraph.appendChild(new Code(">")); paragraph.appendChild(new Text("后面书写文字。如下:")); document.appendChild(paragraph); BlockQuote blockQuote = new BlockQuote(); blockQuote.appendChild(new Text("读一本好书,就是在和高尚的人谈话。 ——歌德")); document.appendChild(blockQuote); blockQuote = new BlockQuote(); blockQuote.appendChild(new Text("雇用制度对工人不利,但工人根本无力摆脱这个制度。 ——阮一峰")); document.appendChild(blockQuote); heading = new Heading(); heading.setLevel(3); heading.appendChild(new Text("1.7 链接")); document.appendChild(heading); paragraph = new Paragraph(); paragraph.appendChild(new Text("微信公众号仅支持公众号文章链接,即域名为")); paragraph.appendChild(new Code("https://mp.weixin.qq.com/")); paragraph.appendChild(new Text("的合法链接。使用方法如下所示:")); document.appendChild(paragraph); paragraph = new Paragraph(); Link link = new Link("https://mp.weixin.qq.com/s/s5IhxV2ooX3JN_X416nidA", null); link.appendChild(new Text("你是《未来世界的幸存者》么?")); paragraph.appendChild(new Text("对于该论述,欢迎读者查阅之前发过的文章,")); paragraph.appendChild(link); document.appendChild(paragraph); heading = new Heading(); heading.setLevel(3); heading.appendChild(new Text("1.8 图片")); document.appendChild(heading); paragraph = new Paragraph(); paragraph.appendChild(new Text("插入图片,格式如下:")); document.appendChild(paragraph); paragraph = new Paragraph(); Image image = new Image("https://markdown.com.cn/images/qrcode_for_gh_82cf87d482f0_258.jpg", null); image.appendChild(new Text("这里写图片描述")); paragraph.appendChild(image); document.appendChild(paragraph); paragraph = new Paragraph(); paragraph.appendChild(new Text("支持 jpg、png、gif、svg 等图片格式,")); emphasis = new Emphasis("**"); emphasis.appendChild(new Text("其中 svg 文件仅可在微信公众平台中使用")); paragraph.appendChild(emphasis); paragraph.appendChild(new Text(",svg 文件示例如下:")); document.appendChild(paragraph); paragraph = new Paragraph(); image = new Image("https://markdown.com.cn/images/i-am-svg.svg", null); paragraph.appendChild(image); document.appendChild(paragraph); paragraph = new Paragraph(); paragraph.appendChild(new Text("支持图片")); strongEmphasis = new StrongEmphasis(); strongEmphasis.appendChild(new Text("拖拽和截图粘贴")); paragraph.appendChild(strongEmphasis); paragraph.appendChild(new Text("到编辑器中。")); document.appendChild(paragraph); paragraph = new Paragraph(); paragraph.appendChild(new Text("注:支持图片 ")); strongEmphasis = new StrongEmphasis(); emphasis = new Emphasis("*"); emphasis.appendChild(new Text("拖拽和截图粘贴")); strongEmphasis.appendChild(emphasis); paragraph.appendChild(strongEmphasis); paragraph.appendChild(new Text(" 到编辑器中,仅支持 https 的图片,图片粘贴到微信时会自动上传微信服务器。")); document.appendChild(paragraph); heading = new Heading(); heading.setLevel(3); heading.appendChild(new Text("1.9 分割线")); document.appendChild(heading); paragraph = new Paragraph(); paragraph.appendChild(new Text("可以在一行中用三个以上的减号来建立一个分隔线,同时需要在分隔线的上面空一行。如下:")); document.appendChild(paragraph); ThematicBreak thematicBreak = new ThematicBreak(); thematicBreak.setLiteral("---"); document.appendChild(thematicBreak); heading = new Heading(); heading.setLevel(3); heading.appendChild(new Text("1.10 表格")); document.appendChild(heading); paragraph = new Paragraph(); paragraph.appendChild(new Text("可以使用冒号来定义表格的对齐方式,如下:")); document.appendChild(paragraph); TableBlock tableBlock = new TableBlock(); TableHead tableHead = new TableHead(); TableRow tableRow = new TableRow(); TableCell tableCell = new TableCell(); tableCell.appendChild(new Text("姓名")); tableCell.setAlignment(TableCell.Alignment.LEFT); tableRow.appendChild(tableCell); tableCell = new TableCell(); tableCell.appendChild(new Text("年龄")); tableCell.setAlignment(TableCell.Alignment.CENTER); tableRow.appendChild(tableCell); tableCell = new TableCell(); tableCell.appendChild(new Text("工作")); tableCell.setAlignment(TableCell.Alignment.RIGHT); tableRow.appendChild(tableCell); tableHead.appendChild(tableRow); TableBody tableBody = new TableBody(); tableRow = new TableRow(); tableCell = new TableCell(); tableCell.appendChild(new Text("小可爱")); tableRow.appendChild(tableCell); tableCell = new TableCell(); tableCell.appendChild(new Text("18")); tableRow.appendChild(tableCell); tableCell = new TableCell(); tableCell.appendChild(new Text("吃可爱多")); tableRow.appendChild(tableCell); tableBody.appendChild(tableRow); tableRow = new TableRow(); tableCell = new TableCell(); tableCell.appendChild(new Text("小小勇敢")); tableRow.appendChild(tableCell); tableCell = new TableCell(); tableCell.appendChild(new Text("20")); tableRow.appendChild(tableCell); tableCell = new TableCell(); tableCell.appendChild(new Text("爬棵勇敢树")); tableRow.appendChild(tableCell); tableBody.appendChild(tableRow); tableRow = new TableRow(); tableCell = new TableCell(); tableCell.appendChild(new Text("小小小机智")); tableRow.appendChild(tableCell); tableCell = new TableCell(); tableCell.appendChild(new Text("22")); tableRow.appendChild(tableCell); tableCell = new TableCell(); tableCell.appendChild(new Text("看一本机智书")); tableRow.appendChild(tableCell); tableBody.appendChild(tableRow); tableBlock.appendChild(tableHead); tableBlock.appendChild(tableBody); document.appendChild(tableBlock); List<Extension> extensions = List.of(TablesExtension.create()); MarkdownRenderer markdownRenderer = MarkdownRenderer.builder().extensions(extensions).build(); //转成markdown格式 String md = markdownRenderer.render(document); System.out.println(md); HtmlRenderer htmlRenderer = HtmlRenderer.builder().extensions(extensions).build(); //转成html String html = htmlRenderer.render(document); System.out.println(html); } @Test public void deserialize() throws IOException { List<Extension> extensions = List.of(TablesExtension.create()); Parser parser = Parser.builder().extensions(extensions).build(); InputStreamReader reader = new InputStreamReader(CommonmarkCase.class.getClassLoader().getResourceAsStream("test.md")); Node document = parser.parseReader(reader); Node node = document.getFirstChild(); while (node != null) { System.out.println(node.getClass()); if (node.getClass().equals(Heading.class)) {//处理标题 Heading heading = (Heading) node; Text text = (Text)heading.getFirstChild(); System.out.println(text.getLiteral()); } else if (node.getClass().equals(BulletList.class)) {//处理无序列表 BulletList bulletList = (BulletList) node; Node node2 = bulletList.getFirstChild(); while (node2 != null) { if (node2.getClass().equals(ListItem.class)) { Node node3 = node2.getFirstChild(); if (node3.getClass().equals(Paragraph.class)) { Text text = (Text)node3.getFirstChild(); System.out.println(text.getLiteral()); } if (node3.getNext() != null && node3.getNext().getClass().equals(BulletList.class)) { System.out.println("二级无序列表"); //TODO: 继续解析 } } node2 = node2.getNext(); } } //else if ... node = node.getNext(); } } }
参考:https://github.com/commonmark/commonmark-java。
浙公网安备 33010602011771号