一.EditorMD编辑器的使用
1.1editor编辑器介绍
- 支持“标准”Markdown / CommonMark和Github风格的语法,也可变身为代码编辑器;
- 支持实时预览、图片(跨域)上传、预格式文本/代码/表格插入、代码折叠、搜索替换、只读模式、自定义样式主题和多语言语法高亮等功能;
- 支持ToC(Table of Contents)、Emoji表情、Task lists、@链接等Markdown扩展语法;
- 支持TeX科学公式(基于KaTeX)、流程图 Flowchart 和 时序图 Sequence Diagram;
- 支持识别和解析HTML标签,并且支持自定义过滤标签解析,具有可靠的安全性和几乎无限的扩展性;
- 支持 AMD / CMD 模块化加载(支持 Require.js & Sea.js),并且支持自定义扩展插件;
- 兼容主流的浏览器(IE8+)和Zepto.js,且支持iPad等平板设备;
1.2.下载editor编辑器
官网:http://pandao.github.io/editor.md/
1.3.下载完成后
这是目录信息,找到examples目录,里面有个simple.html文件,只需要改动这个文件就可以使用
1.4.更改配置
这是笔者下载后修改过后的配置
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="utf-8"/>
<title>Simple example - Editor.md examples</title>
<link rel="stylesheet" href="css/style.css"/>
<link rel="stylesheet" href="../css/editormd.css"/>
<link rel="shortcut icon" href="https://pandao.github.io/editor.md/favicon.ico" type="image/x-icon"/>
</head>
<body>
<div id="layout">
<header>
<h1>Simple example</h1>
</header>
<div id="test-editormd">
<textarea style="display:none;"></textarea>
<textarea class="editor-md-html" name="editor-md-html"></textarea>
</div>
</div>
<script src="js/jquery.min.js"></script>
<script src="../editormd.min.js"></script>
<script type="text/javascript">
var testEditor;
$(function () {
testEditor = editormd("test-editormd", {
width: "70%",//编辑器大小官方默认90%
height: 640,
syncScrolling: "single",
path: "../lib/",//这个编辑器文件的lib路径
saveHTMLToTextarea : true,//注意3:这个配置,textarea可以提交
emoji: true,//emoji表情,默认关闭
/**上传图片相关配置如下*/
imageUpload : true,
imageFormats : ["jpg", "jpeg", "gif", "png", "bmp", "webp"],
imageUploadURL : "/editorMDUpload",//注意你后端的上传图片服务地址
//editorTheme: "pastel-on-dark",//编辑器的主题颜色
theme: "gray",//顶部的主题
previewTheme: "dark"//显示的主题
//editor.md期望得到一个json格式的上传后的返回值,格式是这样的:
/*
{
success : 0 | 1, // 0 表示上传失败,1 表示上传成功
message : "提示的信息,上传成功或上传失败及错误信息等。",
url : "图片地址" // 上传成功时才返回
}
*/
});
/*
// or
testEditor = editormd({
id : "test-editormd",
width : "90%",
height : 640,
path : "../lib/"
});
*/
});
</script>
</body>
</html>
1.5.图片上传
这是图片上传的前端配置,如上代码中的一样
imageUpload : true,
imageFormats : ["jpg", "jpeg", "gif", "png", "bmp", "webp"],
imageUploadURL : "/editorMDUpload",//注意你后端的上传图片服务地址
1.6.SpringMVC文件上传
为了试下动态上传,笔者后台使用的是java SpringMVC框架,以下是修改后的jsp代码
<%--
Created by IntelliJ IDEA.
User: hly
Date: 2018/8/15
Time: 16:17
github :github.com/SiriusHly
blog :blog.csdn.net/Sirius_hly
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<% String path = request.getContextPath();%>
<html lang="zh">
<head>
<meta charset="utf-8"/>
<title>Simple example - Editor.md examples</title>
<link rel="stylesheet" href="<%=path%>/static/html/editor/editor.md-master/examples/css/style.css"/>
<link rel="stylesheet" href="<%=path%>/static/html/editor/editor.md-master/css/editormd.css"/>
<link rel="shortcut icon" href="https://pandao.github.io/editor.md/favicon.ico" type="image/x-icon"/>
</head>
<body>
<div id="layout">
<header>
<h1>Simple example</h1>
</header>
<div id="test-editormd">
<textarea style="display:none;"></textarea>
<textarea class="editor-md-html" name="editor-md-html"></textarea>
</div>
</div>
<script src="<%=path%>/static/html/editor/editor.md-master/examples/js/jquery.min.js"></script>
<script src="<%=path%>/static/html/editor/editor.md-master/editormd.min.js"></script>
<script type="text/javascript">
var testEditor;
$(function () {
testEditor = editormd("test-editormd", {
width: "70%",//编辑器大小官方默认90%
height: 640,
syncScrolling: "single",
path: "<%=path%>/static/html/editor/editor.md-master/lib/",
saveHTMLToTextarea : true,//注意3:这个配置,textarea可以提交
emoji: true,//emoji表情,默认关闭
/**上传图片相关配置如下*/
imageUpload : true,
imageFormats : ["jpg", "jpeg", "gif", "png", "bmp", "webp"],
imageUploadURL : "<%=path%>/fileUpload/editorMDUpload",//注意你后端的上传图片服务地址
onload: function () { //上传成功之后的回调
},
//editorTheme: "pastel-on-dark",//编辑器的主题颜色
theme: "gray",//顶部的主题
previewTheme: "dark"//显示的主题
});
});
</script>
</body>
</html>
1.7.SpringMVC后台
package com.hly.ssm.controller.fileUploadController;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Calendar;
/**
* @author :hly
* @github :github.com/SiriusHly
* @blog :blog.csdn.net/Sirius_hly
* @date :2018/8/15
*/
@Controller
@RequestMapping(value = "/fileUpload" )
public class EditormdFileUploadController {
@RequestMapping(value = "/editorMDUpload" ,method = RequestMethod.POST)
public void editorMD(HttpServletRequest request, HttpServletResponse response,@RequestParam(value = "editormd-image-file", required = false) MultipartFile file) throws IOException {
try {
request.setCharacterEncoding( "utf-8" );
/*这里返回格式是html/txt才能上传*/
response.setHeader( "Content-Type" , "application/json" );
//获得web项目的全路径
String rootPath = request.getSession().getServletContext().getRealPath("/resource/upload/");
//Calendar.getInstance()是获取一个Calendar对象并可以进行时间的计算,时区的指定
Calendar date = Calendar.getInstance();
//获得日期路径,MONTH个值的初始值是0,因此我们要用它来表示正确的月份时就需要加1。
File dateFile = new File(date.get(Calendar.YEAR)+"/"+(date.get(Calendar.MONTH)+1)+"/"+(date.get(Calendar.DATE)));
//获得文件最初的路径
String originalFile = file.getOriginalFilename();
//得到完整路径名
File newFile = new File(rootPath+File.separator+dateFile+File.separator+originalFile);
/*文件不存在就创建*/
if(!newFile.getParentFile().exists()){
newFile.getParentFile().mkdirs();
}
file.transferTo(newFile);
//System.out.println("/resources/upload/"+dateFile+File.separator+originalFile);
System.out.println(dateFile+"/"+file.getOriginalFilename());
/*JSON格式*/
response.getWriter().write("{\"success\":1,\"message\":\"上传成功\",\"url\":\"/resource/upload/"+date.get(Calendar.YEAR)+"/"+(date.get(Calendar.MONTH)+1)+"/"+date.get(Calendar.DATE)+"/"+file.getOriginalFilename()+"\"}");
} catch (Exception e) {
response.getWriter().write("{\"success\":0}");
}
}
@RequestMapping("editorMD")
public ModelAndView editormd(){
ModelAndView mv = new ModelAndView();
mv.setViewName("/editor/simple");
return mv;
}
}
这里有几点需要注意:
@RequestParam(value = "editormd-image-file", required = false)
1.上面的value是特定的,这样才能接收到文件
2.图片被拦截
在上传后,图片无法再前端的预览区显示,是由于mvc拦截了图片,所以需要在web.xml文件中添加
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.css</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.xml</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.swf</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.zip</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.gif</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.jpg</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.png</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.js</url-pattern>
</servlet-mapping>
也可以放在webapp路径下,然后在springMVC中进行配置,如下
<!-- 静态资源映射 -->
<!--路径后有/会认为是目录,没有认为是文件-->
<!--location是工程路径地址,mapping是映射后的访问地址-->
<!--/*所有文件夹不包括子文件夹,/**所有文件夹和里面的子文件夹-->
<mvc:resources mapping="/static/**" location="/static/"/>
3.所传递的json字符串需要正确,如上
//editor.md期望得到一个json格式的上传后的返回值,格式是这样的:
/*
{
success : 0 | 1, // 0 表示上传失败,1 表示上传成功
message : "提示的信息,上传成功或上传失败及错误信息等。",
url : "图片地址" // 上传成功时才返回
}
*/
4.笔者在定义上传文件夹时,使用了日期进行分类,造成了错误,导致图片无法上传成功,研究发现是
File.separator
的问题,json貌似不能传递\(反斜杠),所以我们可以用"/",在创建文件对象时即使用"/",也会被转化为\,所以我们可以在json字符串中再做改动。下面是上传的目录及效果截图。
二.编辑内容获取
1.html代码
这是获取内容的html代码,其他部分都一样
<input type="text" placeholder="请输入标题" id="title" name="title" autocomplete="off">
<input name="my_submit" id="my_submit" value="提交" type="button">
<div id="test-editormd">
<textarea id="editor-md-doc" name="editor-md-doc" style="display:none;"></textarea>
<textarea id="editor-md-html" name="editor-md-html"></textarea>
</div>
2.js代码
JQ实现,获取编辑内容,然后ajax封装上传
<script>
$("#my_submit").click(function () {
alert("正在提交");
submit_atricle();
})
function submit_atricle() {
var title = $("#title").val();
var htmlContent = $("#editor-md-html").val();
var markdownContent = $("#editor-md-doc").val();
$.ajax({
url: "<%=path%>/fileUpload/editorContent",
data: JSON.stringify({title: title, htmlContent: htmlContent, markdownContent: markdownContent}),
type: "POST",
contentType: 'application/json',
success: function () {
alert("发布成功");
},
error: function () {
alert("发布失败");
}
})
}
</script>
3.完整jsp前端代码
<%--
Created by IntelliJ IDEA.
User: hly
Date: 2018/8/15
Time: 16:17
github :github.com/SiriusHly
blog :blog.csdn.net/Sirius_hly
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<% String path = request.getContextPath();%>
<html lang="zh">
<head>
<meta charset="utf-8"/>
<title>Simple example - Editor.md examples</title>
<link rel="stylesheet" href="<%=path%>/static/html/editor/editor.md-master/examples/css/style.css"/>
<link rel="stylesheet" href="<%=path%>/static/html/editor/editor.md-master/css/editormd.css"/>
<link rel="stylesheet" href="<%=path%>/static/assets/js/jquery-3.1.1.js"/>
<link rel="shortcut icon" href="https://pandao.github.io/editor.md/favicon.ico" type="image/x-icon"/>
</head>
<body>
<div id="layout">
<header></header>
<%--页面提交表单内容--%>
<input type="text" placeholder="请输入标题" id="title" name="title" autocomplete="off">
<input name="my_submit" id="my_submit" value="提交" type="button">
<div id="test-editormd">
<textarea id="editor-md-doc" name="editor-md-doc" style="display:none;"></textarea>
<textarea id="editor-md-html" name="editor-md-html"></textarea>
</div>
</div>
<script src="<%=path%>/static/html/editor/editor.md-master/examples/js/jquery.min.js"></script>
<script src="<%=path%>/static/html/editor/editor.md-master/editormd.min.js"></script>
<script>
$("#my_submit").click(function () {
alert("正在提交");
submit_atricle();
})
function submit_atricle() {
var title = $("#title").val();
var htmlContent = $("#editor-md-html").val();
var markdownContent = $("#editor-md-doc").val();
$.ajax({
url: "<%=path%>/fileUpload/editorContent",
data: JSON.stringify({title: title, htmlContent: htmlContent, markdownContent: markdownContent}),
type: "POST",
contentType: 'application/json',
success: function () {
alert("发布成功");
},
error: function () {
alert("发布失败");
}
})
}
</script>
<script type="text/javascript">
var testEditor;
$(function () {
testEditor = editormd("test-editormd", {
/*上面div的值*/
width: "70%",//编辑器大小官方默认90%
height: 640,
syncScrolling: "single",
path: "<%=path%>/static/html/editor/editor.md-master/lib/",
saveHTMLToTextarea: true,//注意3:这个配置,textarea可以提交
emoji: true,//emoji表情,默认关闭
tocm: true, // Using [TOCM]
tex: true, // 开启科学公式TeX语言支持,默认关闭
flowChart: true, // 开启流程图支持,默认关闭
/**上传图片相关配置如下*/
imageUpload: true,
imageFormats: ["jpg", "jpeg", "gif", "png", "bmp", "webp"],
imageUploadURL: "<%=path%>/fileUpload/editorMDUpload",//注意你后端的上传图片服务地址
onload: function () { //上传成功之后的回调
},
//editorTheme: "pastel-on-dark",//编辑器的主题颜色
theme: "gray",//顶部的主题
previewTheme: "dark"//显示的主题
});
});
</script>
</body>
</html>
4.后端获取代码
@RequestMapping(value = "editorContent",method = RequestMethod.POST)
public ModelAndView articleContent(@RequestBody Article article){
System.out.println("MD文本");
System.out.println(article.getMarkdownContent());
System.out.println("HTML文本");
System.out.println(article.getHtmlContent());
ModelAndView mv = new ModelAndView();
mv.addObject("html",article.getHtmlContent());
mv.addObject("md",article.getMarkdownContent());
mv.setViewName("editor/article");
return mv;
}
文章实体类,关于@Requestbody的使用方法,https://blog.csdn.net/Sirius_hly/article/details/80302060 请看笔者者篇文章。
public class Article {
private String title;
private String htmlContent;
private String markdownContent;
}
5.处理获得的文本
后端获得文本后,我们可以先创建一个html,因为传过来的是markdown文本,我们需要把他们转化为html文本。下面是完整代码,需要引入一些js文件和css文件,基本上都在lib下。
<!--@author :hly
@github :github.com/SiriusHly
@blog :blog.csdn.net/Sirius_hly
@date :2018/8/4
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="../../../static/html/editor/editor.md-master/examples/css/style.css"/>
<link rel="stylesheet" href="../../../static/html/editor/css/editormd.css"/>
<link rel="shortcut icon" href="https://pandao.github.io/editor.md/favicon.ico" type="image/x-icon"/>
</head>
<body>
<div id="content">
<textarea style="display:none;">```html
$("#my_submit").click(function () {
alert("正在提交");
submit_atricle();
})
```
## 提交代码</textarea>
</div>
<script src="../../../static/html/editor/editor.md-master/examples/js/jquery.min.js"></script>
<script src="../../../static/html/editor/editor.md-master/editormd.min.js"></script>
<script src="../../../static/html/editor/editor.md-master/lib/flowchart.min.js"></script>
<script src="../../../static/html/editor/editor.md-master/lib/jquery.flowchart.min.js"></script>
<script src="../../../static/html/editor/editor.md-master/lib/marked.min.js"></script>
<script src="../../../static/html/editor/editor.md-master/lib/prettify.min.js"></script>
<script src="../../../static/html/editor/editor.md-master/lib/raphael.min.js"></script>
<script src="../../../static/html/editor/editor.md-master/lib/sequence-diagram.min.js"></script>
<script src="../../../static/html/editor/editor.md-master/lib/underscore.min.js"></script>
<script type="text/javascript">
var testEditor;
$(function () {
testEditor = editormd.markdownToHTML("content", {//注意:这里是上面DIV的id
htmlDecode: "style,script,iframe",
emoji: true,
taskList: true,
tex: true, // 默认不解析
flowChart: true, // 默认不解析
sequenceDiagram: true, // 默认不解析
codeFold: true,
//editorTheme: "pastel-on-dark",//编辑器的主题颜色
theme: "gray",//顶部的主题
previewTheme: "dark"//显示的主题
});});
</script>
</body>
</html>
6.文本显示
运行html,显示的文本是这样的,由于觉得代码样式太丑,笔者修改了一下editormd.css背景和颜色,具体在格式化后的3千多行。
这是修改过后的css代码:https://github.com/SiriusHly/SSM/tree/master/MySSM/src/main/webapp/static/html/editor/css
7.最后附上后端完整代码
package com.hly.ssm.controller.fileUploadController;
import com.hly.ssm.pojo.Article;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Calendar;
/**
* @author :hly
* @github :github.com/SiriusHly
* @blog :blog.csdn.net/Sirius_hly
* @date :2018/8/15
*/
@Controller
@RequestMapping(value = "/fileUpload" )
public class EditormdFileUploadController {
/**
* 边界页面
* @return
*/
@RequestMapping("editorMD")
public ModelAndView editormd(){
ModelAndView mv = new ModelAndView();
mv.setViewName("/editor/simple");
return mv;
}
/**
* 图片上传
* @param request
* @param response
* @param file
* @throws IOException
*/
@RequestMapping(value = "/editorMDUpload" ,method = RequestMethod.POST)
public void editorMD(HttpServletRequest request, HttpServletResponse response,@RequestParam(value = "editormd-image-file", required = false) MultipartFile file) throws IOException {
try {
request.setCharacterEncoding( "utf-8" );
/*这里返回格式是html/txt才能上传*/
response.setHeader( "Content-Type" , "application/json" );
//获得web项目的全路径
String rootPath = request.getSession().getServletContext().getRealPath("/resource/upload/");
//Calendar.getInstance()是获取一个Calendar对象并可以进行时间的计算,时区的指定
Calendar date = Calendar.getInstance();
//获得日期路径,MONTH个值的初始值是0,因此我们要用它来表示正确的月份时就需要加1。
File dateFile = new File(date.get(Calendar.YEAR)+"/"+(date.get(Calendar.MONTH)+1)+"/"+(date.get(Calendar.DATE)));
//获得文件最初的路径
String originalFile = file.getOriginalFilename();
//得到完整路径名
File newFile = new File(rootPath+File.separator+dateFile+File.separator+originalFile);
/*文件不存在就创建*/
if(!newFile.getParentFile().exists()){
newFile.getParentFile().mkdirs();
}
file.transferTo(newFile);
//System.out.println("/resources/upload/"+dateFile+File.separator+originalFile);
System.out.println(dateFile+"/"+file.getOriginalFilename());
/*JSON格式*/
response.getWriter().write("{\"success\":1,\"message\":\"上传成功\",\"url\":\"/resource/upload/"+date.get(Calendar.YEAR)+"/"+(date.get(Calendar.MONTH)+1)+"/"+date.get(Calendar.DATE)+"/"+file.getOriginalFilename()+"\"}");
} catch (Exception e) {
response.getWriter().write("{\"success\":0}");
}
}
/**
* 获取文章内容
*/
@RequestMapping(value = "editorContent",method = RequestMethod.POST)
public ModelAndView articleContent(@RequestBody Article article){
System.out.println("MD文本");
System.out.println(article.getMarkdownContent());
System.out.println("HTML文本");
System.out.println(article.getHtmlContent());
ModelAndView mv = new ModelAndView();
mv.addObject("html",article.getHtmlContent());
mv.addObject("md",article.getMarkdownContent());
mv.setViewName("editor/article");
return mv;
}
}