编写一个markdown文本编辑器工具
文章目录
- 1、UI组件/依赖库选择。
- 1.1、左侧Markdown编辑区UI组件选择。
- 1.2、webview组件选择
- 1.3、markdown转html开源库选择。
- 2、核心技术实现
- 2.1、左侧Markdown编辑区实现
- 2.2、右侧webview预览实现
- 2.3、markdown转html实现
- 3、运行效果
- 3.1、界面展示
1、UI组件/依赖库选择。
编辑器采用左右分割布局,左侧为Markdown编辑区,右侧为实时预览区,相关组件或依赖选择现成的开源库整合实现,减少开发成本。
1.1、左侧Markdown编辑区UI组件选择。
网上找了一下,仅发现RSyntaxTextArea https://github.com/bobbylight/rsyntaxtextarea这个组件比较适合。
RSyntaxTextArea的功能::
- 现成的文本编辑界面
- Markdown语法高亮显示
- 可定制的编辑功能
- 开源免费使用
1.2、webview组件选择
要创建markdown编辑,需要一个webview组件,在java里面可用的webview组件有:
- javafx.scene.web.WebView,开源免费,基于webkit内核
- jcef,开源免费,基于Chromium
- JxBrowser,商业收费,基于Chromium
在考虑免费和整合方便上,选择了javafx.scene.web.WebView。
1.3、markdown转html开源库选择。
-
CommonMark-java
- 基于CommonMark规范实现
- 轻量级,易于集成
- 支持标准Markdown语法
-
Flexmark-java
- 功能丰富的Markdown处理器
- 支持CommonMark和GitHub Flavored Markdown
- 可扩展性强,支持自定义扩展
-
Markdown4j
- 简单易用的Markdown解析器
- 基于JavaScript的markdown.js移植
- 适合基本的Markdown转换需求
-
Txtmark
- 轻量级Markdown处理器
- 性能较好
- 支持基本Markdown语法
Flexmark-java支持最完整,选择了它。
2、核心技术实现
2.1、左侧Markdown编辑区实现
编辑区采用RSyntaxTextArea,初始化代码如下:
// 初始化面板private void initPanel() {textArea = new RSyntaxTextArea();textArea.setCodeFoldingEnabled(true);textArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_MARKDOWN);textArea.setAntiAliasingEnabled(true);textArea.setFont(Config.getFont());textArea.setLineWrap(Config.isIsLineWrap());textArea.addCaretListener(e -> {try{int pos = textArea.getCaretPosition();//获取行数int row = textArea.getLineOfOffset(pos) + 1;//获取列数int col = pos - textArea.getLineStartOffset(row - 1) + 1;rowValueLabel.setText(String.valueOf(row));columnValueLabel.setText(String.valueOf(col));}catch(Exception ex){log.log(Level.SEVERE, " 无法获得当前光标位置 ", ex);}});scrollPane = new RTextScrollPane(textArea);this.add(scrollPane, BorderLayout.CENTER);}
2.2、右侧webview预览实现
预览区采用javafx.scene.web.WebView,初始化代码如下:
private void initWebView(JFXPanel fxPanel){WebView webView = new WebView();webEngine = webView.getEngine();webEngine.setOnAlert((WebEvent<String> wEvent) -> {System.out.println("alert========: " + wEvent.getData());});webEngine.setOnError((WebErrorEvent wEvent) -> {System.out.println("error========: " + wEvent.getMessage());});String body = "";String markdown = textArea.getText();if (!StrUtil.isEmpty(markdown)){body = Markdown2Html.toHtml(markdown);}webEngine.loadContent(getHtml(body), "text/html");Scene scene = new Scene(new StackPane(webView));fxPanel.setScene(scene);}
2.3、markdown转html实现
左侧编辑区增加文本变动监听器,使用flexmark-java将Markdown文本转换为HTML,并通过WebView加载。关键步骤包括:
// 监听文本编辑,如果文本内容有更新,则将markdown转为html,并更新webview。
class MdDocumentListener implements DocumentListener {public void insertUpdate(DocumentEvent e) {}public void removeUpdate(DocumentEvent e) {}public void changedUpdate(DocumentEvent e) {String markdown = editor.getTextArea().getText();String html = Markdown2Html.toHtml(markdown);Platform.runLater(() -> {JSObject obj = (JSObject) webEngine.executeScript("window");obj.setMember("javaContent", html);webEngine.executeScript("addHtml(javaContent)");});}
}
public class Markdown2Html {private static Parser parser = null;private static HtmlRenderer renderer = null;public static String toHtml(String markdown) {MutableDataSet options = new MutableDataSet();options.set(Parser.EXTENSIONS, Arrays.asList(TablesExtension.create(),FootnoteExtension.create(),TaskListExtension.create()));if (parser == null){parser = Parser.builder(options).build();renderer = HtmlRenderer.builder(options).build();}Node document = parser.parse(markdown);return renderer.render(document);}
}
3、运行效果
3.1、界面展示
启动应用后,界面呈现左右分割布局:左侧为支持语法高亮的文本编辑区,底部显示当前光标所在的行和列位置;右侧为实时渲染的预览区。