editor.md是国内开发的开源项目,单纯基于前端JavaScript,可以实现markdown编辑器的所有功能。
主要特性
官网:https://pandao.github.io/editor.md/,下载解压后的目录如下图所示:
说明:
在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,只需要修改为:
即可第二步:将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>
代码解释:
注意:
无论需要html格式的内容还是markdown格式的内容,都只需要写一个textarea。此处有一个很大的坑。不少其他教程中说需要两个textarea,那么会导致后一个textarea后台获得的数据是一个数组,而不是单纯的HTML内容。
运行
这样就完成了一个最简单的editor.md的编辑器了,可以在打开的页面书写熟悉的Markdown文档,里面可以包含代码,右侧有实时的预览。
后端返回的报文必须json 格式:
{
success : 0 | 1, //0表示上传失败;1表示上传成功
message : "提示的信息",
url : "图片地址" //上传成功时才返回
}
说明:
第一步:页面代码
<%@ 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>
说明:
第二步:后台处理文件上传的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;
}
}
第三步:后台处理图片回显的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();
}
}
}
前端页面:
<%@ 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");
}
}
```
<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>