package com.abc.md;
import com.vladsch.flexmark.ast.*;
import com.vladsch.flexmark.ext.gfm.strikethrough.Strikethrough;
import com.vladsch.flexmark.ext.gfm.strikethrough.StrikethroughExtension;
import com.vladsch.flexmark.ext.tables.*;
import com.vladsch.flexmark.html.HtmlRenderer;
import com.vladsch.flexmark.html2md.converter.FlexmarkHtmlConverter;
import com.vladsch.flexmark.parser.Parser;
import com.vladsch.flexmark.util.ast.Document;
import com.vladsch.flexmark.util.ast.Node;
import com.vladsch.flexmark.util.collection.iteration.ReversiblePeekingIterator;
import com.vladsch.flexmark.util.data.MutableDataSet;
import com.vladsch.flexmark.util.sequence.BasedSequence;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
public class FlexmarkCase {
@Test
public void serialize() {
Document document = new Document(null, BasedSequence.EMPTY);
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("不同数量的"));
Code code = new Code();
code.setText(BasedSequence.of("#"));
paragraph.appendChild(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);
Strikethrough strikethrough = new Strikethrough();
strikethrough.appendChild(new Text("这里是删除线"));
paragraph = new Paragraph();
paragraph.appendChild(strikethrough);
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("无序列表的使用,在符号"));
code = new Code();
code.setText(BasedSequence.of("-"));
paragraph.appendChild(code);
paragraph.appendChild(new Text("后加空格使用。如下:"));
document.appendChild(paragraph);
BulletList bulletList = new BulletList();
BulletListItem bulletListItem = new BulletListItem();
bulletListItem.appendChild(new Text("无序列表 1"));
bulletList.appendChild(bulletListItem);
bulletListItem = new BulletListItem();
bulletListItem.appendChild(new Text("无序列表 2"));
bulletList.appendChild(bulletListItem);
bulletListItem = new BulletListItem();
bulletListItem.appendChild(new Text("无序列表 3"));
bulletList.appendChild(bulletListItem);
document.appendChild(bulletList);
paragraph = new Paragraph();
paragraph.appendChild(new Text("如果要控制列表的层级,则需要在符号"));
code = new Code();
code.setText(BasedSequence.of("-"));
paragraph.appendChild(code);
paragraph.appendChild(new Text("前使用空格。如下:"));
document.appendChild(paragraph);
bulletList = new BulletList();
bulletListItem = new BulletListItem();
bulletListItem.appendChild(new Text("无序列表 1"));
bulletList.appendChild(bulletListItem);
bulletListItem = new BulletListItem();
bulletListItem.appendChild(new Text("无序列表 2"));
bulletList.appendChild(bulletListItem);
BulletList bulletList2 = new BulletList();
bulletListItem = new BulletListItem();
bulletListItem.appendChild(new Text("无序列表 2.1"));
bulletList2.appendChild(bulletListItem);
bulletListItem = new BulletListItem();
bulletListItem.appendChild(new Text("无序列表 2.2"));
bulletList2.appendChild(bulletListItem);
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("有序列表的使用,在数字及符号"));
code = new Code();
code.setText(BasedSequence.of("."));
paragraph.appendChild(code);
paragraph.appendChild(new Text("后加空格后输入内容,如下:"));
document.appendChild(paragraph);
OrderedList orderedList = new OrderedList();
orderedList.setStartNumber(1);
OrderedListItem orderedListItem = new OrderedListItem();
orderedListItem.appendChild(new Text("有序列表 1"));
orderedList.appendChild(orderedListItem);
orderedListItem = new OrderedListItem();
orderedListItem.appendChild(new Text("有序列表 2"));
orderedList.appendChild(orderedListItem);
orderedListItem = new OrderedListItem();
orderedListItem.appendChild(new Text("有序列表 3"));
orderedList.appendChild(orderedListItem);
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("引用的格式是在符号"));
code = new Code();
code.setText(BasedSequence.of(">"));
paragraph.appendChild(code);
paragraph.appendChild(new Text("后面书写文字。如下:"));
document.appendChild(paragraph);
paragraph = new Paragraph();
paragraph.appendChild(new Text(" "));
document.appendChild(paragraph);
BlockQuote blockQuote = new BlockQuote();
paragraph = new Paragraph();
paragraph.appendChild(new Text("读一本好书,就是在和高尚的人谈话。 ——歌德"));
blockQuote.appendChild(paragraph);
document.appendChild(blockQuote);
paragraph = new Paragraph();
paragraph.appendChild(new Text(" "));
document.appendChild(paragraph);
blockQuote = new BlockQuote();
paragraph = new Paragraph();
paragraph.appendChild(new Text("雇用制度对工人不利,但工人根本无力摆脱这个制度。 ——阮一峰"));
blockQuote.appendChild(paragraph);
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("微信公众号仅支持公众号文章链接,即域名为"));
code = new Code();
code.setText(BasedSequence.of("https://mp.weixin.qq.com/"));
paragraph.appendChild(code);
paragraph.appendChild(new Text("的合法链接。使用方法如下所示:"));
document.appendChild(paragraph);
paragraph = new Paragraph();
Link link = new Link();
link.setUrl(BasedSequence.of("https://mp.weixin.qq.com/s/s5IhxV2ooX3JN_X416nidA"));
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();
image.setUrl(BasedSequence.of("https://markdown.com.cn/images/qrcode_for_gh_82cf87d482f0_258.jpg"));
image.appendChild(new Text("这里写图片描述"));
paragraph.appendChild(image);
document.appendChild(paragraph);
paragraph = new Paragraph();
paragraph.appendChild(new Text("支持 jpg、png、gif、svg 等图片格式,"));
strongEmphasis = new StrongEmphasis();
strongEmphasis.appendChild(new Text("其中 svg 文件仅可在微信公众平台中使用"));
paragraph.appendChild(strongEmphasis);
paragraph.appendChild(new Text(",svg 文件示例如下:"));
document.appendChild(paragraph);
paragraph = new Paragraph();
image = new Image();
image.setUrl(BasedSequence.of("https://markdown.com.cn/images/i-am-svg.svg"));
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();
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);
MutableDataSet options = new MutableDataSet();
options.set(Parser.EXTENSIONS, Arrays.asList(
StrikethroughExtension.create(), //删除线扩展
TablesExtension.create() //表格扩展
));
HtmlRenderer htmlRenderer = HtmlRenderer.builder(options).build();
String html = htmlRenderer.render(document);
System.out.println(html);
MutableDataSet options2 = new MutableDataSet();
options2.set(FlexmarkHtmlConverter.SETEXT_HEADINGS, false);//标题是否使用下划线格式
options2.set(FlexmarkHtmlConverter.SKIP_CHAR_ESCAPE, true);//是否跳过转义符
options2.set(FlexmarkHtmlConverter.UNORDERED_LIST_DELIMITER, '-');//无序列表的符号
options2.set(FlexmarkHtmlConverter.TYPOGRAPHIC_SMARTS, false);//是否启用智能排版,它会处理文本中的一些常见的标点符号,并将其转换为更符合排版习惯的字符
options2.set(FlexmarkHtmlConverter.THEMATIC_BREAK, "---");
String markdown = FlexmarkHtmlConverter.builder(options2).build().convert(html);
System.out.println(markdown);
}
@Test
public void deserialize() throws IOException {
MutableDataSet options = new MutableDataSet();
options.set(Parser.EXTENSIONS, Arrays.asList(
StrikethroughExtension.create(), //删除线扩展
TablesExtension.create() //表格扩展
));
Parser parser = Parser.builder(options).build();
InputStreamReader reader = new InputStreamReader(FlexmarkCase.class.getClassLoader().getResourceAsStream("test.md"));
Document document = parser.parseReader(reader);
ReversiblePeekingIterator<Node> iterator = document.getChildIterator();
while (iterator.hasNext()) {
Node node = iterator.next();
if (node.getClass().equals(Heading.class)) {
Heading heading = (Heading) node;
System.out.println(heading.getText());
} else if (node.getClass().equals(BulletList.class)) {
BulletList bulletList = (BulletList) node;
ReversiblePeekingIterator<Node> iterator2 = bulletList.getChildIterator();
while (iterator2.hasNext()) {
Node node2 = iterator2.next();
BulletListItem bulletListItem = (BulletListItem) node2;
ReversiblePeekingIterator<Node> iterator3 = bulletListItem.getChildIterator();
while (iterator3.hasNext()) {
Node node3 = iterator3.next();
if (node3.getClass().equals(BulletList.class)) {
System.out.println("二级无序列表");
//TODO: 继续解析
} else {
System.out.println(node3.getChars());
}
}
}
} else if (node.getClass().equals(ThematicBreak.class)) {
System.out.println(node.getChars());
}
//else if ...
}
}
}