poi-tl:1.12.2
poi-tl-ext:0.4.23-poi5
poi-tl-plugin-highlight:1.0.0
根据对应版本实现 poi-tl-ext + HighlightRenderPolicy 编写新插件 让html字符串转word并且代码块高亮(如果存在代码块)
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.plugin.highlight.HighlightRenderData;
import com.deepoove.poi.plugin.highlight.HighlightRenderPolicy;
import com.deepoove.poi.plugin.highlight.HighlightStyle;
import com.deepoove.poi.policy.AbstractRenderPolicy;
import com.deepoove.poi.render.RenderContext;
import com.deepoove.poi.template.run.RunTemplate;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.ddr.poi.html.HtmlRenderPolicy;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
public class HtmlHighlightRenderPolicy extends AbstractRenderPolicy<String> {
private final HtmlRenderPolicy htmlPolicy = new HtmlRenderPolicy();
private final HighlightRenderPolicy highlightPolicy = new HighlightRenderPolicy();
@Override
public void doRender(RenderContext<String> context) {
String html = context.getData();
if (html == null || html.trim().isEmpty()) return;
Document doc = Jsoup.parseBodyFragment(html);
Elements codes = doc.select("pre > code");
// 没有代码块:直接走 HTML
if (codes.isEmpty()) {
htmlPolicy.render(context.getEleTemplate(), html, context.getTemplate());
return;
}
RunTemplate runTemplate = (RunTemplate) context.getEleTemplate();
XWPFParagraph paragraph = runTemplate.getRun().getParagraph();
XWPFTemplate template = context.getTemplate();
// ① 立刻清掉占位符(此后不再使用旧 run)
paragraph.removeRun(paragraph.getRuns().indexOf(runTemplate.getRun()));
// 逐节点处理
for (Element node : doc.body().children()) {
// 代码块
if ("pre".equals(node.tagName()) && node.selectFirst("code") != null) {
Element code = node.selectFirst("code");
String language = parseLanguage(node.className());
String codeText = code.text();
XWPFParagraph codePara = paragraph.getBody().insertNewParagraph(paragraph.getCTP().newCursor());
XWPFRun codeRun = codePara.createRun();
HighlightRenderData data = new HighlightRenderData();
data.setCode(codeText);
data.setLanguage(language);
data.setStyle(HighlightStyle.builder().withShowLine(false).withTheme("zenburn").build());
highlightPolicy.render(
new RunTemplate("",codeRun),
data,
template
);
}
// 普通 HTML
else {
XWPFParagraph htmlPara = paragraph.getBody().insertNewParagraph(paragraph.getCTP().newCursor());
XWPFRun htmlRun = htmlPara.createRun();
htmlPolicy.render(
new RunTemplate("",htmlRun),
node.outerHtml(),
template
);
}
}
}
@Override
protected void afterRender(RenderContext<String> context) {
// 已手动清理,这里不再 clearPlaceholder
}
private String parseLanguage(String className) {
if (className != null && className.startsWith("language-")) {
return className.substring("language-".length());
}
return "text";
}
}