博客 / 詳情

返回

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.md

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();
        }
    }
}
CommonmarkCase.java

 

 

 

參考:https://github.com/commonmark/commonmark-java。

 

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.