哈梨尔 发表于 2026-3-12 12:05:05

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 图片

插入图片,格式如下:

![这里写图片描述](https://markdown.com.cn/images/qrcode_for_gh_82cf87d482f0_258.jpg)

支持 jpg、png、gif、svg 等图片格式,**其中 svg 文件仅可在微信公众平台中使用**,svg 文件示例如下:

![](https://markdown.com.cn/images/i-am-svg.svg)

支持图片**拖拽和截图粘贴**到编辑器中。

注:支持图片 ***拖拽和截图粘贴*** 到编辑器中,仅支持 https 的图片,图片粘贴到微信时会自动上传微信服务器。

### 1.9 分割线

可以在一行中用三个以上的减号来建立一个分隔线,同时需要在分隔线的上面空一行。如下:

---

### 1.10 表格

可以使用冒号来定义表格的对齐方式,如下:

| 姓名   | 年龄 |   工作 |
| :----- | :--: | -------: |
| 小可爱 |18| 吃可爱多 |
| 小小勇敢 |20| 爬棵勇敢树 |
| 小小小机智 |22| 看一本机智书 |test.md2.2、引入依赖

<dependency>
    <groupId>org.commonmark</groupId>
    commonmark</artifactId>
    <version>0.26.0</version>
</dependency>

<dependency>
    <groupId>org.commonmark</groupId>
    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();
      }
    }
}CommonmarkCase.java 
 
 
参考:https://github.com/commonmark/commonmark-java。
 

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: Java 操作 Markdown(1)--commonmark-java 使用