基于JavaWeb的MarkDown编辑器editor.md的使用

1、简介

editor.md是国内开发的开源项目,单纯基于前端JavaScript,可以实现markdown编辑器的所有功能。

主要特性

  • 支持通用 Markdown / CommonMark 和 GFM (GitHub Flavored Markdown) 风格的语法,也可变身为代码编辑器;
  • 支持实时预览、图片(跨域)上传、预格式文本/代码/表格插入、代码折叠、跳转到行、搜索替换、只读模式、自定义样式主题和多语言语法高亮等功能;
  • 支持 ToC(Table of Contents)、Emoji表情、Task lists、@链接等 Markdown 扩展语法;
  • 支持 TeX 科学公式(基于 KaTeX)、流程图 Flowchart 和 时序图 Sequence Diagram;
  • 支持识别和解析 HTML 标签,并且支持自定义过滤标签及属性解析,具有可靠的安全性和几乎无限的扩展性;
  • 支持 AMD / CMD 模块化加载(支持 Require.js & Sea.js),并且支持自定义扩展插件;
  • 兼容主流的浏览器(IE8+)和 Zepto.js,且支持 iPad 等平板设备;

官网:https://pandao.github.io/editor.md/,下载解压后的目录如下图所示:
基于JavaWeb的MarkDown编辑器editor.md的使用_第1张图片
说明:

  • css目录中可选择editormd.min.css放在对应的项目css目录中;
  • js可选择editormd.min.js放置在对应项目的js目录中,需要注意的是同时需要引入jQuery,这里使用jquery.min.js;
  • examples文件夹中是一部分核心功能的demo,在使用的过程中用到对应的组件或功能可打开参考;
  • fonts是需要用到字体,可一并引入项目;
  • images是一些加载类的图片;
  • lib是editor.md依赖的第三方js资源,比如流程图的js资源;
  • plugins主要是编辑器上面的操作功能插件,比如图片上传等,可选择使用的进行加载;

在examples文件夹中有一个简单的示例simple.html,源代码为:


<html lang="zh">
    <head>
        <meta charset="utf-8" />
        <title>示例title>
        <link rel="stylesheet" href="../css/editormd.css" />
    head>
    <body>
        <div id="layout">
            <header>
                <h1>Simple exampleh1>
            header>
            <div id="test-editormd">
                <textarea style="display:none;">textarea>
            div>
        div>
        <script src="js/jquery.min.js">script>
        <script src="../editormd.js">script>
        <script type="text/javascript">
			var testEditor;
            $(function() {
                testEditor = editormd("test-editormd", {
                    width   : "90%",  //宽度
                    height  : 640,  //高度
                    syncScrolling : "single",  //
                    path    : "../lib/",
                    autoFocus:false  //页面打开时不自动获取焦点
                });
            });
        script>
    body>
html>

注意

  • 是默认的显示mark文本的区域,默认的name值是test-editormd-markdown-doc,如果想更换名称为content,只需要修改为:即可

2、环境搭建

  • 第一步:创建一个Maven形式的Web项目,然后将editor.md解压后的文件全部拷贝到项目的webapp目录下:
    基于JavaWeb的MarkDown编辑器editor.md的使用_第2张图片

  • 第二步:将editormd/examples下的simple.html的源代码拷贝到index.jsp,然后调整为:

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
    <html>
    <head>
        <meta charset="utf-8" />
        <title>示例title>
        <link rel="stylesheet" href="${pageContext.request.contextPath}/editormd/css/editormd.css" />
    head>
    <body>
    <div id="layout">
        <header>
            <h1>editor.md示例h1>
            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        header>
        <div id="test-editormd">
             <textarea style="display:none;" class="form-control" id="editormd" name="editormd">textarea>
        div>
    div>
    <script src="${pageContext.request.contextPath}/editormd/examples/js/jquery.min.js">script>
    <script src="${pageContext.request.contextPath}/editormd/editormd.js">script>
    <script type="text/javascript">
        var testEditor;
        $(function() {
            testEditor = editormd("test-editormd", {
                width   : "90%",
                height  : 640,
                syncScrolling : "single",
                path    : "${pageContext.request.contextPath}/editormd/lib/",
                //这个配置可以让构造出来的HTML代码直接在第二个隐藏的textarea域中,方便post提交表单。
                saveHTMLToTextarea : true
            });
        });
    script>
    body>
    html>
    

代码解释:

  • path:需要指定到项目中对应的lib的路径,如果设置不对markdown 无法渲染出来。
  • saveHTMLToTextarea设置为true表示,转化为html格式的内容也同样提交到后台。
  • 通过form表单提交时后台可通过request.getParameter(“editormd”)获取到对应的markdown文档内容。

注意

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

  • 运行
    基于JavaWeb的MarkDown编辑器editor.md的使用_第3张图片
    这样就完成了一个最简单的editor.md的编辑器了,可以在打开的页面书写熟悉的Markdown文档,里面可以包含代码,右侧有实时的预览。


3、实现文件上传

3.1、理该基础

后端返回的报文必须json 格式:

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

说明:

  • 0,1 必须是数字;
  • url :就是你图片存在的地址,这个就是返回到弹框中的图片地址。

3.2、示例:

  • 第一步:页面代码

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
    <html>
        <head>
            <meta charset="utf-8" />
            <title>示例title>
            <link rel="stylesheet" href="${pageContext.request.contextPath}/editormd/css/editormd.css" />
        head>
        <body>
        <div id="layout">
            <header>
                <h1>editor.md示例h1>
                <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
            header>
            <div id="test-editormd">
                <textarea style="display:none;" class="form-control" id="editormd" name="editormd">textarea>
            div>
        div>
        <script src="${pageContext.request.contextPath}/editormd/examples/js/jquery.min.js">script>
        <script src="${pageContext.request.contextPath}/editormd/editormd.js">script>
        <script type="text/javascript">
            var testEditor;
            $(function() {//Editor初始化:
                testEditor = editormd("test-editormd", {
                    width   : "90%",
                    height  : 640,
                    syncScrolling : "single",
                   // theme : "dark",
                    path    : "${pageContext.request.contextPath}/editormd/lib/", //依赖lib文件夹路径
                    //这个配置可以让构造出来的HTML代码直接在第二个隐藏的textarea域中,方便post提交表单
                    saveHTMLToTextarea : true,
                    saveHTMLToTextarea : true, // 保存 HTML 到 Textarea,true表示转化为html格式的内容也同样提交到后台
                    toolbarAutoFixed:true,//工具栏自动固定定位的开启与禁用
                    imageUpload : true,
                    imageFormats : ["jpg", "jpeg", "gif", "png", "bmp", "webp"],
                    imageUploadURL : "${pageContext.request.contextPath}/imageUpload",
                });
            });
        script>
        body>
    html>
    

    说明:

    • imageUpload:设置为true表示支持上传,此时需要plugins中的image-dialog.js插件(默认调用,放在指定路径即可)
    • imageFormats:为支持上传的图片类型
    • imageUploadURL:要上传图片的后台服务器路径
  • 第二步:后台处理文件上传的Servlet

    @MultipartConfig    //标识Servlet支持文件上传
    @WebServlet(urlPatterns = "/imageUpload")
    public class ImageUploadServlet extends HttpServlet {
        @Override
        public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            JSONObject res = new JSONObject();
            request.setCharacterEncoding("utf-8");
            response.setCharacterEncoding("utf-8");
            response.setContentType("text/html;charset=utf-8");
    
            String savePath = request.getServletContext().getRealPath("/uploadFile");  //存储路径
            File path = new File(savePath);
            if (!path.exists()) { //如果路径不存在则创建
                path.mkdirs();
            }
    
            Collection<Part> parts = request.getParts(); //获取上传的文件集合
            if (parts != null && parts.size() == 1) {   //上传单个文件
                Part part = request.getPart("editormd-image-file"); //-----① 通过表单file控件()的名字直接获取Part对象
                String header = part.getHeader("content-disposition");//获取请求头
                String fileName = getFileName(header);
                String url = savePath + File.separator + fileName;
                part.write(url);           //把文件写到指定路径
    
                res.put("success", 1);
                res.put("message", "上传成功");
                res.put("url", "http://localhost:8080/EditorMarkDownDemo_war/imageShow?imageFileName=" + fileName);
            } else {
                res.put("success", 0);
                res.put("message", "上传失败");
            }
    
    
            PrintWriter out = response.getWriter();
            out.println(res.toJSONString());
            out.flush();
            out.close();
        }
    
        /**
         * 根据请求头解析出文件名
         * @param header 请求头
         * @return 文件名
         */
        public String getFileName(String header) {
            String[] temp = header.split(";")[2].split("=");
            //获取文件名,兼容各种浏览器的写法
            String fileName = temp[1].substring(temp[1].lastIndexOf("\\") + 1).replaceAll("\"", "");
            return fileName;
        }
    }
    

    编号①处之所以通过editormd-image-file获取Part的原因如下图所示:
    基于JavaWeb的MarkDown编辑器editor.md的使用_第4张图片

  • 第三步:后台处理图片回显的Servlet

    @WebServlet(urlPatterns = "/imageShow")
    public class ImageShowServlet extends HttpServlet {
        @Override
        public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            String imageFileName = request.getParameter("imageFileName");
            response.setContentType("text/html; charset=UTF-8");
            response.setContentType("image/jpeg");
            OutputStream os = response.getOutputStream();
            String savePath = request.getServletContext().getRealPath("/uploadFile");  //存储路径
    
            try (FileImageInputStream input = new FileImageInputStream(new File(savePath + File.separator +imageFileName));
                 ByteArrayOutputStream output = new ByteArrayOutputStream();) {
                byte[] buf = new byte[1024];
                int len = -1;
                while ((len = input.read(buf)) != -1) {
                    output.write(buf, 0, len);
                }
                byte[] data = output.toByteArray();
                os.write(data);
                os.flush();
            } catch (FileNotFoundException ex) {
                ex.printStackTrace();
            }
        }
    }
    
  • 结果:
    基于JavaWeb的MarkDown编辑器editor.md的使用_第5张图片
    基于JavaWeb的MarkDown编辑器editor.md的使用_第6张图片


3、页面保存

  • 前端页面:

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
    <html>
        <head>
            <meta charset="utf-8" />
            <title>示例title>
            <link rel="stylesheet" href="${pageContext.request.contextPath}/editormd/css/editormd.css" />
        head>
        <body>
        <div id="layout">
            <header>
                <h1>editor.md示例h1>
                <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
            header>
            <div id="test-editormd">
                <textarea style="display:none;" class="form-control" id="editormd" name="editormd">textarea>
                <textarea class="editormd-html-textarea" name="text" id="editormdData">textarea>
            div>
        div>
        <script src="${pageContext.request.contextPath}/editormd/examples/js/jquery.min.js">script>
        <script src="${pageContext.request.contextPath}/editormd/editormd.js">script>
        <script type="text/javascript">
            var testEditor;
            $(function() {//Editor初始化:
                testEditor = editormd("test-editormd", {
                    width   : "90%",
                    height  : 640,
                    syncScrolling : "single",
                   // theme : "dark",
                    path    : "${pageContext.request.contextPath}/editormd/lib/", //依赖lib文件夹路径
                    //这个配置可以让构造出来的HTML代码直接在第二个隐藏的textarea域中,方便post提交表单
                   // saveHTMLToTextarea : true, // 保存 HTML 到 Textarea,true表示转化为html格式的内容也同样提交到后台
                    toolbarAutoFixed:true,//工具栏自动固定定位的开启与禁用
                    imageUpload : true,
                    imageFormats : ["jpg", "jpeg", "gif", "png", "bmp", "webp"],
                    imageUploadURL : "${pageContext.request.contextPath}/imageUpload",
                });
                $("#saveBtn").click(function () {
                    var data = $("#editormdData").val();
                    //alert(html);
                    $.ajax({
                        data:{'data':data},
                        dataType:'text',
                        type:'post',
                        url:'${pageContext.request.contextPath}/saveData',
                        success:function (msg) {
                            alert(msg);
                        }
                    })
                });
            });
        script>
        <button id="saveBtn">保存代码button>
        body>
    html>
    

-后台Servlet:

```java
@WebServlet(urlPatterns = "/saveData")
public class SaveDataServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String data = request.getParameter("data");
        System.out.println(data);
        String savePath = request.getServletContext().getRealPath("/md");  //存储路径
        File file = new File(savePath);
        if(!file.exists()){
            file.mkdirs();
        }
        FileWriter out = new FileWriter(savePath+"/demo.md");
        out.write(data);
        out.flush();
        out.close();
        response.getWriter().write("success");
    }
}
```
  • 运行,单击保存按钮,在指定的目录下会找到保存好的文件

4、markdown回显,转HTML


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


<script src="js/jquery-1.8.3.min.js">script>
 <script src="Editor/js/editormd.min.js">script>
<script src="Editor/lib/marked.min.js">script>
<script src="Editor/lib/prettify.min.js">script>



<div class="content editormd-preview-theme" id="content">
     <textarea style="display:none;" >${content}textarea>      
div>


<script>
	editormd.markdownToHTML("content",{emoji:true});
script>

你可能感兴趣的:(JavaWeb)