基于Java和Bytemd用120行代码实现一个桌面版Markdown编辑器

简介: 想到之前业余的时候做过一些Swing或者JavaFx的Demo,记得JavaFx中有一个组件WebView已经支持Html5、CSS3和ES5,这个组件作为一个嵌入式浏览器,可以轻松地渲染一个URL里面的文本内容或者直接渲染一个原始的Html字符串。另外,由于原生的JavaFx的视觉效果比较丑,可以考虑引入Swing配合IntelliJ IDEA的主题提供更好的视觉效果。本文的代码基于JDK11开发。


微信截图_20220513211319.png


这是我参与8月更文挑战的第2天,活动详情查看:8月更文挑战


前提



某一天点开掘金的写作界面的时候,发现了内置Markdown编辑器有一个Github的图标,点进去就是一个开源的Markdown编辑器项目bytemdhttps://github.com/bytedance/bytemd):

微信截图_20220513211328.png


这是一个NodeJs项目,由字节跳动提供。联想到之前业余的时候做过一些Swing或者JavaFxDemo,记得JavaFx中有一个组件WebView已经支持Html5CSS3ES5,这个组件作为一个嵌入式浏览器,可以轻松地渲染一个URL里面的文本内容或者直接渲染一个原始的Html字符串。另外,由于原生的JavaFx的视觉效果比较丑,可以考虑引入Swing配合IntelliJ IDEA的主题提供更好的视觉效果。本文的代码基于JDK11开发。


引入依赖



很多人吐槽过Swing组件的视觉效果比较差,原因有几个:

  • 技术小众,现在有更好的组件进行混合开发和跨平台开发
  • 基于上一点原因,导致很少人会去开发Swing组件的UI,其实Swing的每个组件都可以重新实现UI的表现效果
  • compose-jbJetBrains)组件很晚才发布出来,刚好碰上Swing官方停止维护,后面应该更加少人会使用SwingGUI开发


使用Swing并且成功了的方案最知名的就是JetBrains全家桶。目前来看,为了解决这个"丑"的问题,现在有比较简单的处理方案:


  • 方案一:使用compose-jb(名字有点不好听,官方仓库为https://github.com/JetBrains/compose-jb)开发,这个是JetBrains系列的通用组件,基于Swing做二次封装,不过必须使用语言Kotlin,有点强买强卖的嫌疑,这列贴两个官方的图参考一下:

微信截图_20220513211337.png

微信截图_20220513211344.png


  • 方案二:FormDev(之前推出过Swing布局器的开发商,官网https://www.formdev.com/flatlaf)提供的FlatLafFlat Look and Feel),提供了Light Dark IntelliJ and Darcula themes,而且依赖少,使用起来十分简单,个人认为当前这个是Swing UI组件视觉效果首选

微信截图_20220513211350.png


引入FlatLafOpenFx的依赖:


<dependency>
    <groupId>com.formdev</groupId>
    <artifactId>flatlaf</artifactId>
    <version>1.5</version>
</dependency>
<dependency>
    <groupId>com.formdev</groupId>
    <artifactId>flatlaf-intellij-themes</artifactId>
    <version>1.5</version>
</dependency>
<dependency>
    <groupId>org.openjfx</groupId>
    <artifactId>javafx-media</artifactId>
    <version>11.0.2</version>
</dependency>
<dependency>
    <groupId>org.openjfx</groupId>
    <artifactId>javafx-swing</artifactId>
    <version>11.0.2</version>
</dependency>
<dependency>
    <groupId>org.openjfx</groupId>
    <artifactId>javafx-web</artifactId>
    <version>11.0.2</version>
</dependency>
<dependency>
    <groupId>org.openjfx</groupId>
    <artifactId>javafx-base</artifactId>
    <version>11.0.2</version>
</dependency>
<dependency>
    <groupId>org.openjfx</groupId>
    <artifactId>javafx-graphics</artifactId>
    <version>11.0.2</version>
</dependency>
<dependency>
    <groupId>org.openjfx</groupId>
    <artifactId>javafx-controls</artifactId>
    <version>11.0.2</version>
</dependency>
复制代码


布局和实现



布局的实现比较简单:

微信截图_20220513211357.png


最终的H5文本渲染在WebView组件中(JFXPanelJavaFx => Swing的适配器,WebViewJavaFx的组件,但是这里使用的外层容器都是Swing组件),具体的编码实现如下:


public class MarkdownEditor {
    private static final int W = 1200;
    private static final int H = 1000;
    private static final String TITLE = "markdown editor";
    public static String CONTENT = "<!DOCTYPE html>\n" +
            "<html lang=\"en\">\n" +
            "<head>\n" +
            "    <meta charset=\"UTF-8\"/>\n" +
            "    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"/>\n" +
            "    <title>ByteMD example</title>\n" +
            "    <link rel=\"stylesheet\" href=\"https://unpkg.com/bytemd/dist/index.min.css\"/>\n" +
            "    <link rel=\"stylesheet\" href=\"https://unpkg.com/github-markdown-css\"/>\n" +
            "    <script src=\"https://unpkg.com/bytemd\"></script>\n" +
            "    <script src=\"https://unpkg.com/@bytemd/plugin-gfm\"></script>\n" +
            "    <script src=\"https://unpkg.com/@bytemd/plugin-highlight\"></script>\n" +
            "    <style>\n" +
            "        .bytemd {\n" +
            "            height: calc(100vh - 50px);\n" +
            "        }\n" +
            "\n" +
            "        .footer {\n" +
            "            width: 100%;\n" +
            "            height: 30px;\n" +
            "            left: 0;\n" +
            "            position: absolute;\n" +
            "            bottom: 0;\n" +
            "            text-align: center;\n" +
            "        }\n" +
            "    </style>\n" +
            "</head>\n" +
            "<body>\n" +
            "<div class=\"footer\">\n" +
            "    <a href=\"https://github.com/bytedance/bytemd\">bytemd</a>\n" +
            "</div>\n" +
            "<script>\n" +
            "    const plugins = [bytemdPluginGfm(), bytemdPluginHighlight()];\n" +
            "    const editor = new bytemd.Editor({\n" +
            "        target: document.body,\n" +
            "        props: {\n" +
            "            value: '# heading\\n\\nparagraph\\n\\n> blockquote',\n" +
            "            plugins,\n" +
            "        },\n" +
            "    });\n" +
            "    editor.$on('change', (e) => {\n" +
            "        editor.$set({value: e.detail.value});\n" +
            "    });\n" +
            "</script>\n" +
            "</body>\n" +
            "</html>";
    static {
        // 初始化主题
        try {
            UIManager.setLookAndFeel(FlatIntelliJLaf.class.getName());
        } catch (Exception e) {
            throw new IllegalStateException("theme init error", e);
        }
    }
    private static JFrame buildFrame(int w, int h, LayoutManager layoutManager) {
        JFrame frame = new JFrame();
        frame.setLayout(layoutManager);
        frame.setTitle(TITLE);
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setSize(w, h);
        Toolkit toolkit = Toolkit.getDefaultToolkit();
        int x = (int) (toolkit.getScreenSize().getWidth() - frame.getWidth()) / 2;
        int y = (int) (toolkit.getScreenSize().getHeight() - frame.getHeight()) / 2;
        frame.setLocation(x, y);
        return frame;
    }
    private static void initAndDisplay() {
        // 构建窗体
        JFrame frame = buildFrame(W, H, new BorderLayout());
        JFXPanel panel = new JFXPanel();
        Platform.runLater(() -> {
            panel.setSize(W, H);
            initWebView(panel, CONTENT);
            frame.getContentPane().add(panel);
        });
        frame.setVisible(true);
    }
    public static void main(String[] args) {
        SwingUtilities.invokeLater(MarkdownEditor::initAndDisplay);
    }
    private static void initWebView(JFXPanel fxPanel, String content) {
        StackPane root = new StackPane();
        Scene scene = new Scene(root);
        WebView webView = new WebView();
        WebEngine webEngine = webView.getEngine();
        webEngine.setJavaScriptEnabled(true);
        webEngine.loadContent(content);
        root.getChildren().add(webView);
        fxPanel.setScene(scene);
    }
}
复制代码


H5文本来源于bytemd的原生JS实现例子:

微信截图_20220513211407.png


所有代码加上注释大概120多行。使用JDK11运行,结果如下:

微信截图_20220513211415.png


目前有2个没有解决的问题(也有可能是):

  • JS的动作触发有轻微延迟
  • WebView组件初始化比较慢


小结



Oracle JDK官方已经宣布不再维护Swing项目,按照一般的尿性后面有可能从JDK中移除,也许是因为它体现不了自身的价值(低情商:不赚钱)。Swing的开发中布局是比较反人类的,一般可能一个Swing项目布局会耗费90%以上的时间,原生组件的UI设计看上去比较"丑",没有丰富的扩展组件和活跃的社区,加上现在有其他更好的跨平台开发方案如QtReact NativeFlutter等等,Swing被遗忘是一个既定的结局。往后除了一枝独秀的JetBrainsSwing的结局就是成为少数人业务的爱好,成为JDK GUI编程爱好者的收藏品。


Demo源码:


(本文完 e-a-20210815 c-1-d)

相关文章
|
16天前
|
Linux UED C++
MarkEdit:相信做技术的同学都会喜欢这个编辑器的,MarkEdit编辑器,让Markdown编辑变得简单而强大,超赞~~~
嗨,大家好,我是小华同学。MarkEdit是一款跨平台的Markdown编辑器,支持Windows、macOS和Linux,提供实时预览、快捷键、自定义主题和插件系统等核心功能。它适用于日常笔记、技术文档、博客写作、学术论文和电子书制作等多种场景。
109 31
|
3月前
|
人工智能 移动开发 前端开发
Markdown-to-Image:开源的在线 Markdown 转海报编辑器
Markdown-to-Image 是一款开源的在线 Markdown 转海报编辑器,能够将 Markdown 文本内容转换为图像,适用于创建社交媒体帖子、海报和其他视觉内容。该工具支持多种输出格式,并允许用户自定义样式,适用于多种应用场景。
175 4
Markdown-to-Image:开源的在线 Markdown 转海报编辑器
|
3月前
|
运维 自然语言处理 供应链
Java云HIS医院管理系统源码 病案管理、医保业务、门诊、住院、电子病历编辑器
通过门诊的申请,或者直接住院登记,通过”护士工作站“分配患者,完成后,进入医生患者列表,医生对应开具”长期医嘱“和”临时医嘱“,并在电子病历中,记录病情。病人出院时,停止长期医嘱,开具出院医嘱。进入出院审核,审核医嘱与住院通过后,病人结清缴费,完成出院。
198 4
|
4月前
|
运维 Java Linux
【运维基础知识】掌握VI编辑器:提升你的Java开发效率
本文详细介绍了VI编辑器的常用命令,包括模式切换、文本编辑、搜索替换及退出操作,帮助Java开发者提高在Linux环境下的编码效率。掌握这些命令,将使你在开发过程中更加得心应手。
54 2
|
4月前
|
Ubuntu Linux 测试技术
Linux系统之部署轻量级Markdown文本编辑器
【10月更文挑战第6天】Linux系统之部署轻量级Markdown文本编辑器
215 1
Linux系统之部署轻量级Markdown文本编辑器
|
4月前
|
安全 Linux iOS开发
ONLYOFFICE 桌面编辑器8.1---一个高效且强大的办公软件
ONLYOFFICE 桌面编辑器8.1---一个高效且强大的办公软件
89 2
|
4月前
|
存储 安全 数据管理
深入测评:ONLYOFFICE 8.1 桌面编辑器究竟有多强大?
深入测评:ONLYOFFICE 8.1 桌面编辑器究竟有多强大?
106 1
|
5月前
|
JavaScript 前端开发 API
vue3 v-md-editor markdown编辑器(VMdEditor)和预览组件(VMdPreview )的使用
本文介绍了如何在Vue 3项目中使用v-md-editor组件库来创建markdown编辑器和预览组件。文章提供了安装步骤、如何在main.js中进行全局配置、以及如何在页面中使用VMdEditor和VMdPreview组件的示例代码。此外,还提供了一个完整示例的链接,包括编辑器和预览组件的使用效果和代码。
vue3 v-md-editor markdown编辑器(VMdEditor)和预览组件(VMdPreview )的使用
|
6月前
|
前端开发 Python
60行Python代码开发在线markdown编辑器
60行Python代码开发在线markdown编辑器
88 2
|
6月前
|
存储 安全 数据安全/隐私保护
Django 后端架构开发:富文本编辑器权限管理与 UEditor 、Wiki接入,实现 Markdown 文本编辑器
Django 后端架构开发:富文本编辑器权限管理与 UEditor 、Wiki接入,实现 Markdown 文本编辑器
233 0

热门文章

最新文章