持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第3天,点击查看活动详情
Flexmark简介
Flexmark是作者基于commonmark-java开发的markdown转换工具。主要作用是依据markdown源文件生成标准的html页面,转换pdf是基于另一个工具包openhtmltopdf完成。
相比于commonmark-java,Flexmark性能上没有那么好,作者的初衷是替换JetBrains的markdown渲染器,但是文档和示例代码比较全,下面的例子是基于官方示例增加了中文乱码问题处理的代码。
示例
import com.vladsch.flexmark.ext.toc.TocExtension;
import com.vladsch.flexmark.html.HtmlRenderer;
import com.vladsch.flexmark.parser.Parser;
import com.vladsch.flexmark.pdf.converter.PdfConverterExtension;
import com.vladsch.flexmark.profile.pegdown.Extensions;
import com.vladsch.flexmark.profile.pegdown.PegdownOptionsAdapter;
import com.vladsch.flexmark.util.ast.Node;
import com.vladsch.flexmark.util.data.MutableDataHolder;
import org.apache.pdfbox.pdmodel.encryption.AccessPermission;
import org.apache.pdfbox.pdmodel.encryption.StandardProtectionPolicy;
public class PdfConverter {
static final MutableDataHolder OPTIONS = PegdownOptionsAdapter.flexmarkOptions(Extensions.ALL & ~(Extensions.ANCHORLINKS | Extensions.EXTANCHORLINKS_WRAP), TocExtension.create()).toMutable();
static final Parser PARSER = Parser.builder(OPTIONS).build();
static final HtmlRenderer RENDERER = HtmlRenderer.builder(OPTIONS).build();
public static void main(String[] args) throws Exception {
String path = PdfConverter.class.getClassLoader().getResource("HanYiQiHei-55Jian-Regular-2.ttf").getPath();
String markdown = "" +
"# Heading\n\n" +
"=======\n" +
"\n" +
"*** ** * ** ***\n" +
"\n" +
"paragraph text lazy continuation\n" +
"\n" +
"* list itemblock quote lazy continuation\n" +
"\n" +
"\~\~\~info with uneven indent with uneven indent indented code \~\~\~\n" +
"\n" +
" with uneven indent\n" +
" with uneven indent\n" +
" indented code\n" +
"\n" +
"1. numbered item 1\n" +
"2. numbered item 2\n" +
"3. numbered item 3\n" +
" * bullet item 1\n" +
" * bullet item 2\n" +
" * bullet item 3\n" +
" 1. numbered sub-item 1\n" +
" 2. numbered sub-item 2\n" +
" 3. numbered sub-item 3\n" +
"\n" +
" \~\~\~info with uneven indent with uneven indent indented code \~\~\~\n" +
"```java \n" +
" System.out.println("test print");\n" +
"``` \n\n" +
"## 中文测试\n\n" +
"| 字符 | 说明 | \n" +
"| --- | --- | \n" +
"| var 变量名称 | 申明变量,弱类型 |";
Node document = PARSER.parse(markdown);
String html = RENDERER.render(document);
System.out.println(html);
html = "<!DOCTYPE html><html><head>\n" +
"</head><body>" + html + "\n" +
"</body></html>";
String css = "@font-face {\n" +
" font-family: 'cnFont';\n" +
" src: url('file:" + path + "');\n" +
" font-weight: normal;\n" +
" font-style: normal;\n" +
"}\n" +
"* {\n" +
" font-family: 'cnFont';\n" +
"}\n";
html = PdfConverterExtension.embedCss(html, css);
OPTIONS.set(PdfConverterExtension.PROTECTION_POLICY, new StandardProtectionPolicy("123", "123", new AccessPermission()));
PdfConverterExtension.exportToPdf("flexmark-java-landscape.pdf", html, "", OPTIONS);
}
}
关键点说明
- 中文问题:产出html时对中文并没有什么问题,但是将html转换为pdf时会发现中文都显示为乱码,原因是pdf转换使用的是非中文的字体,使用css定义一个中文字体即可。
- 字体使用getClassLoader获取是由于之前使用相对路径一直没找到位置,有了解url file定位规则的同学麻烦告知。
- OPTIONS中屏蔽掉了链接相关配置,需要的话去掉即可
- PROTECTION_POLICY:为pdf密码设置,可生成带密码的pdf。
- 生成过程是先产出html,再转换为pdf,默认生成的html页面并没有携带很多样式,可自行增加。