一款好用的Markdown编辑器及使用过程中的坑

简介: 一款好用的Markdown编辑器及使用过程中的坑

Markdown在技术圈越来越受欢迎,今天为大家带来一款国内开源的比较好用的Markdown编辑器——editor.md。同时也聊聊在使用过程中遇到的坑。


editor.md简介



需要预览效果可直接访问url:https://pandao.github.io/editor.md/index.html ,这里是官方网站的一个demo。同时提供了全套的下载安装教程。github开源地址:https://github.com/pandao/editor.md/blob/master/examples/image-upload.html


无论发布含有代码的文章、画流程图、展示数学公式等都有完备的支持。而且此编辑器与后端代码无关,纯前端js实现。


editor.md目录介绍

本文介绍的版本为v1.5.0,在首页下载完成,解压editor.md-master.zip文件,可以看到如下图的目录结构:



图中红色框内是我们要引用到项目的文件和目录。

- css目录中可选择editormd.min.css放在对应的项目css目录中;

- js可选择editormd.min.js放置在对应项目的js目录中,需要注意的是同时需要引入jQuery,这里使用jquery.min.js;

- examples文件夹中是一部分核心功能的demo,在使用的过程中用到对应的组件或功能可打开参考;

- fonts是需要用到字体,可一并引入项目;

- images是一些加载类的图片;

- lib是editor.md依赖的第三方js资源,比如流程图的js资源;

- plugins主要是编辑器上面的操作功能插件,比如图片上传等,可选择使用的进行加载;


editor.md整合使用

在上面提到对应的文件根据项目的需要拷贝至项目中,需要注意的是最好文件夹的名字在项目中一一对照。特别是plugins这个文件夹的名称,在使用插件时editormd.min.js会默认找对应plugins路径下的插件。


引入css和js

在使用到editor.md的页面引入css和js:


<link rel="stylesheet" href="/css/editormd.css"/>

<#--js可在jsp或其他类型选择页面的底部引入-->

<script src="/js/jquery.min.js"></script>

<script src="/js/editormd.min.js"></script>

页面中添加div

在需要添加editor.md编辑器的地方输入以下div:


<div id="content-editormd" class="form-group">

   <textarea style="display:none;" class="form-control" id="content-editormd-markdown-doc" name="content-editormd-markdown-doc"></textarea>

</div>

div的id为content-editormd,后面的js代码中需要用到。textarea就是我们编写markdown文件的地方,editor.md会将此textarea渲染成在第一种图中看到的效果。默认的textarea的内容为markdown文档的内容,通过form表单提交时后台可通过content-editormd-markdown-doc获取到对应的markdown文档内容。比如Java中可通过request.getParameter(“content-editormd-markdown-doc”)获得。


注意:此处需要注意的是,无论需要html格式的内容还是markdown格式的内容,都只需要写一个textarea。此处有一个很大的坑。不少其他教程中说需要两个textarea,那么会导致后一个textarea后台获得的数据是一个数组,而不是单纯的HTML内容。


页面添加js代码

js代码用来将上面的textarea进行渲染:

<script type="text/javascript">
    $(function() {
        editormd("content-editormd", {
            width   : "100%",
            height  : 1000,
            syncScrolling : "single",
            path    : "/lib/",
            saveHTMLToTextarea : true, // 保存HTML到Textarea
        });
    });
</script>

此段js代码中的content-editormd就是上面div的id。其中path路径需要指定到项目中对应的lib的路径。saveHTMLToTextarea设置为true表示,转化为html格式的内容也同样提交到后台。


此时如果用浏览器查看页面元素会发现,不仅有name为content-editormd-markdown-doc的textarea,editor.md还会生成一个name为content-editormd-html-code的textarea。也就是说当saveHTMLToTextarea设置为true时,编辑器会自动生成这么一个textarea,后台只需要根据name获取即可,不需要在前台再次自定义一个textarea。



后台接收请求本文采用Springmvc,代码如下:


@RequestMapping("/publish")
public String publish(HttpSession session,@RequestParam("content-editormd-html-code") String contentHtml,@RequestParam("content-editormd-markdown-doc") String content) {
    return null;
}

其中content-editormd-html-code对应的html格式的内容,content-editormd-markdown-doc对应的是markdown格式的内容。如果发现无法接收到参数,可采用上面的方法查看一下页面元素。


上传图片

editor.md的上传图片功能实现起来比较简单,只需要在上段代码中再添加一些配置即可。


<script type="text/javascript">
    $(function() {
        editormd("content-editormd", {
            width   : "100%",
            height  : 1000,
            syncScrolling : "single",
            path    : "/lib/",
            saveHTMLToTextarea : true, // 保存 HTML 到 Textarea
            // 图片上传
            imageUpload : true,
            imageFormats: ["jpg","jpeg","gif","png","bmp","webp"],
            imageUploadURL: "/file/upload",
        });
    });
</script>

imageUpload设置为true表示支持上传,此时需要plugins中的image-dialog.js插件(默认调用,放在指定路径即可)。

imageFormats为支持上传的图片类型。

imageUploadURL要上传图片的后台服务器路径。

注意:此处需要注意的是服务器后台返回结果的格式必须json格式,且内容如下:


{
    success : 0 | 1, //0表示上传失败;1表示上传成功
    message : "提示的信息",
    url     : "图片地址" //上传成功时才返回
}

此处有一个大坑,返回的参数success的值不是字符串“0”和“1”,而是数字0和1,后台返回的时候一定要注意,否则会出现图片上传成功之后,返回结果中的图片地址无法填充。


其中message为上传成功或失败之后alert出来提示用户的信息。url为上传成功之后服务器返回的图片地址。


后台接收上传代码如下:


@Controller
@RequestMapping("/file")
public class FileUploadController {
    private static final Logger LOGGER = LoggerFactory.getLogger(FileUploadController.class);
    private static final String SUCCESS = "success";
    @ResponseBody
    @RequestMapping("/upload")
    public String upload(HttpSession session, @RequestParam(value = "editormd-image-file") MultipartFile file) {
        JSONObject res = new JSONObject();
        try {
            Map<String, String> uploadMap = QiniuUtils.upload(file.getInputStream());
            String code = uploadMap.get("code");
            if (SUCCESS.equals(code)) {
                res.put("success", 1);
                res.put("message", "上传成功");
                res.put("url", uploadMap.get("url"));
            } else {
                res.put("success", 0);
                res.put("message", "上传失败" + uploadMap.get("error"));
            }
        } catch (IOException e) {
            LOGGER.error("上传图片异常", e);
            res.put("success", 0);
            res.put("message", "上传异常");
        }
        LOGGER.info("上传图片返回结果:{}", res);
        return res.toString();
    }
}

本代码中采用了云存储,大家在使用的过程中可针对自己的情况改写为服务器路径或其他云存储路径。


注意:此处有一坑:服务接收file文件时,对应的参数为editormd-image-file,如果接收不到可采用上面的方式查看页面元素。


上传效果如下图:



markdown页面展示

通过上面的步骤,已经将html格式和markdown格式的内容都上传到服务器了。如果需要编辑则加载markdown的内容,此时只需将服务器存储的内容赋值给上面的textarea即可。


展示内容有两种方式,一种方式是直接展示html格式的内容,第二种方式是页面加载markdown格式内容,然后通过editor.md再次渲染成html格式。


首先看一下直接展示html页面需要做什么。


<link rel="stylesheet" href="/css/editormd.min.css"/>
<div id="content-editormd">
    ${contentHtml}
</div>
<script src="/js/jquery.min.js"></script>
<script src="/js/editormd.min.js"></script>
<script src="/lib/marked.min.js"></script>
<script src="/lib/prettify.min.js"></script>
<script type="text/javascript">
    $(function () {
        editormd.markdownToHTML("content-editormd");
    })
</script>

其中${contentHtml}为获取后台的html格式内容。

如果使用markdown内容前端渲染,则前端代码如下:

<link rel="stylesheet" href="/css/editormd.min.css"/>
<div id="content-editormd">
    <textarea style="display:none;">${content}</textarea>
</div>
<script src="/js/jquery.min.js"></script>
<script src="/js/editormd.min.js"></script>
<script src="/lib/marked.min.js"></script>
<script src="/lib/prettify.min.js"></script>
<script src="/lib/raphael.min.js"></script>
<script src="/lib/underscore.min.js"></script>
<script src="/lib/sequence-diagram.min.js"></script>
<script src="/lib/flowchart.min.js"></script>
<script src="/lib/jquery.flowchart.min.js"></script>
<script type="text/javascript">
    $(function () {     
        editormd.markdownToHTML("content-editormd", {
            htmlDecode: "style,script,iframe", //可以过滤标签解码
            emoji: true,
            taskList: true,
            tex: true,               // 默认不解析
            flowChart: true,         // 默认不解析
            sequenceDiagram: true, // 默认不解析
            codeFold: true
        });
    })
</script>

editor.md的更多配置项

可参看example中的full.html。

$.get('test.md', function(md){
    testEditor = editormd("test-editormd", {
        width: "90%",
        height: 740,
        path : '../lib/',
        theme : "dark",
        previewTheme : "dark",
        editorTheme : "pastel-on-dark",
        markdown : md,
        codeFold : true,
        //syncScrolling : false,
        saveHTMLToTextarea : true,    // 保存 HTML 到 Textarea
        searchReplace : true,
        //watch : false,                // 关闭实时预览
        htmlDecode : "style,script,iframe|on*",            // 开启 HTML 标签解析,为了安全性,默认不开启    
        //toolbar  : false,             //关闭工具栏
        //previewCodeHighlight : false, // 关闭预览 HTML 的代码块高亮,默认开启
        emoji : true,
        taskList : true,
        tocm            : true,         // Using [TOCM]
        tex : true,                   // 开启科学公式TeX语言支持,默认关闭
        flowChart : true,             // 开启流程图支持,默认关闭
        sequenceDiagram : true,       // 开启时序/序列图支持,默认关闭,
        //dialogLockScreen : false,   // 设置弹出层对话框不锁屏,全局通用,默认为true
        //dialogShowMask : false,     // 设置弹出层对话框显示透明遮罩层,全局通用,默认为true
        //dialogDraggable : false,    // 设置弹出层对话框不可拖动,全局通用,默认为true
        //dialogMaskOpacity : 0.4,    // 设置透明遮罩层的透明度,全局通用,默认值为0.1
        //dialogMaskBgColor : "#000", // 设置透明遮罩层的背景颜色,全局通用,默认为#fff
        imageUpload : true,
        imageFormats : ["jpg", "jpeg", "gif", "png", "bmp", "webp"],
        imageUploadURL : "./php/upload.php",
        onload : function() {
            console.log('onload', this);
            //this.fullscreen();
            //this.unwatch();
            //this.watch().fullscreen();
            //this.setMarkdown("#PHP");
            //this.width("100%");
            //this.height(480);
            //this.resize("100%", 640);
        }
    });
});
目录
相关文章
|
存储 JavaScript API
Nuxt.js:用 Vue.js 打造服务端渲染应用程序(三)
Nuxt.js:用 Vue.js 打造服务端渲染应用程序
|
Kubernetes API 调度
k8s中节点无法启动Pod
【10月更文挑战第3天】
428 6
|
前端开发 JavaScript 编译器
对比 React,用10个例子快速上手 Svelte
文章用十个例子比较了 React 和 Svelte 两个框架,包括属性传递、状态管理、条件渲染、异步渲染等。通过阅读这篇文章,你可以了解 Svelte 的基本用法和渲染原理。
465 0
对比 React,用10个例子快速上手 Svelte
|
10月前
|
自然语言处理 资源调度 并行计算
从本地部署到企业级服务:十种主流LLM推理框架的技术介绍与对比
本文深入探讨了十种主流的大语言模型(LLM)服务引擎和工具,涵盖从轻量级本地部署到高性能企业级解决方案,详细分析了它们的技术特点、优势及局限性,旨在为研究人员和工程团队提供适合不同应用场景的技术方案。内容涉及WebLLM、LM Studio、Ollama、vLLM、LightLLM、OpenLLM、HuggingFace TGI、GPT4ALL、llama.cpp及Triton Inference Server与TensorRT-LLM等。
1396 7
|
存储 机器学习/深度学习 XML
PyMuPDF 1.24.4 中文文档(二)(4)
PyMuPDF 1.24.4 中文文档(二)
383 0
|
存储 小程序 数据库
阿里云学生服务器申请流程_学生党免费领7个月学生机
阿里云2024年推出学生优惠,大陆在籍学生可免费申领7个月学生服务器,配置为2核2G,无限流量,含独立IP。学生需注册账号、完成实名及学生认证,首月免费,完成任务可续费6个月。此外,还有300元无门槛优惠券可在阿里云高校计划中领取,适用于多种云产品。申请及优惠详情见官方链接。
7426 4
阿里云学生服务器申请流程_学生党免费领7个月学生机
element el-table 设置fixed导致行错乱问题
文章讨论了在使用Element UI的`el-table`组件时,设置固定列(`fixed`)导致行错乱的问题,并提供了解决方案。问题产生的原因是当表格底部有滚动条而固定列底部没有滚动条时,行无法对齐。解决办法是在表格中设置`padding-bottom`的内边距与滚动条高度相等,确保固定列和非固定列的行能够对齐。
3280 0
|
定位技术
echarts引入百度地图通过脚本bmap.min.js解决关闭底图可点功能的底层解决方案
echarts引入百度地图通过脚本bmap.min.js解决关闭底图可点功能的底层解决方案
304 0
|
Java 编译器 数据库连接
Element UI 上传文件 el-upload —— 手动上传文件,限制上传文件数量,文件类型校验等
Element UI 上传文件 el-upload —— 手动上传文件,限制上传文件数量,文件类型校验等
3651 0