ThinkCMF整合Editor.md编辑器挖坑补坑指南
最近倒腾了一个网站,使用的是ThinkCMF基于ThinkPHP的框架,自带的编辑器是百度的UEditor,这是百度的一个开源的富文本编辑器,前些年的时候界面是很合适的,那个时候用的比较多,随着时间的推移,UEditor的界面显得有些过时了,自从common-fileupload.jar包存在ddos漏洞, php的代码会存在 ssrf 的安全漏洞,外加隔壁MarkDown之风盛行,UEditor用的人也越来越少了,项目也年久失修,存在的问题不少。
ThinkCMF默认使用的就是UEditor,早前ThinkCMF的UEditor也是问题一大堆,比如视频不能二次保存啥的,但是随着不断的更新,问题也越来越少了。
ThinkCMF的编辑器问题以前早已折腾过,很熟悉了,估摸着可以换个好点的,颜值高点的编辑器,问题应该也不大。
于是乎看中了Editor.md,基于JavaScript,能实现Markdown语法,看着好看,就行了。没有这么多要求,谁知道坑一大堆。。。。。怪我。。
1.下载
去项目首页下载就好了,Editor.md,下载最后一个版本,1.5的。可惜已经很多年未维护了。
2.调用css,js文件
从解压的文件中找到,jquery.min.js,但是ThinkCMF中已经有了,我们就不额外调用了,到时候注意一下顺序就好了。
如下:
editormd.min.js或者editormd.js
editormd.min.css或者editormd.css
lib目录(必要)
plugins目录(可选)
我将其上传到了项目路径+public\themes\admin_simpleboot3\public\assets\editormd
,在assets中新建了目录,名称为:editormd。根据你自己的选择全部扔进去。因为我只是将Editor.md编辑器用于后台,前台用的另外的编辑器(为后面埋下了麻烦)。你也可以传到public\static\js\ueditor
,UEditor的目录。
更改public/themes/admin_simpleboot3/portal
中的调用即可。
比如我们修改文章编辑的页面。
原先的UEditor应该注释掉,或者删除。
<script type="text/javascript" src="__STATIC__/js/ueditor/ueditor.config.js"></script>
<script type="text/javascript" src="__STATIC__/js/ueditor/ueditor.all.min.js"></script>
editorcontent = new baidu.editor.ui.Editor();
editorcontent.render('content');
try {
editorcontent.sync();
} catch (err) {
}
<script type="text/plain" id="content" name="post[post_content]">{$post.post_content}</script>
我们要增加Editor.md的调用,你可以:
大于ThinkPHP 5.0.4版本可以直接使用
__ROOT__: 网站根目录,不带/;__WEB_ROOT__: 网站资源根目录,不带/,如果以前版本用__ROOT__来定位网站资源,方便以后cdn切换
__TMPL__: 当前模板根目录,不带/; 如:前台 simpleboot3模板根目录是 public/themes/simpleboot3
后台admin_simpleboot3模板根目录是public/themes/admin_simpleboot3__STATIC__: public/static目录,不带/;
我写的是这样:
<link href="__TMPL__/public/assets/editormd/css/editormd.min.css" rel="stylesheet">
<script src="__TMPL__/public/assets/editormd/js/editormd.min.js"></script>
然后还需要创建Editor.md编辑器,我不太推荐直接写到公共的header中,我将其写到了edit.html的头部中。
<script type="text/javascript">
$(function() {
var testEditor = editormd("test-editormd", {
saveHTMLToTextarea: true,//保存为html(!!!)
syncScrolling : "single",
path : "__TMPL__/public/assets/editormd/lib/",//路径,同上面的路径配置
watch : false,//是否有预览
width : "100%",
height : 640,
htmlDecode: "style,script,iframe|on*"//html过滤
});
});
</script>
里面的是配置信息,酌情选择。
关于是否开启HTML解析,官网是这样写的:
注:虽然此功能能极大地扩展 Markdown 语法,但也面临着安全上的风险,所以默认是不开启的。
Update: 可以通过设置 `settings.htmlDecode =
"style,script,iframe|on*"`来实现过滤指定标签及属性的解析,提高安全性;
test-editormd务必和下面的div中的id相同。
差不多是下面这样:
然后修改下面的调用位置:
<div class="editormd" id="test-editormd">
<textarea class="editormd-markdown-textarea" name="my-editormd-markdown-doc" style="display:none;">{$post.post_content}</textarea>
<textarea class="editormd-html-textarea" name="post[post_content]"></textarea>
</div>
3.图片上传
需要在上面的配置中加入下面的配置:
imageUpload : true,
imageFormats : ["jpg", "jpeg", "gif", "png", "bmp", "webp"],
imageUploadURL : "__TMPL__/public/assets/editormd/upload/"
Editor.md默认提供了简单的PHP上传后端,在editor.md-master\examples\php\
中,有简易上传类和跨域的演示类(cross-domain upload demo),但是作者貌似不太自信,写了这个:
ThinkCMF自己有上传,我们就用ThinkCMF的吧。
直接修改主js。我们直接进入editormd.js
或editormd.min.js
(须格式化),找到image的调用。
image : function()
默认是:this.executePlugin("imageDialog", "image-dialog/image-dialog");
是为了弹出图片上传框。直接注释,让其弹出openUploadDialog
,具体的可以查看手册。
/**
* 打开文件上传对话框
* @param dialog_title 对话框标题
* @param callback 回调方法,参数有(当前dialog对象,选择的文件数组,你设置的extra_params)
* @param extra_params 额外参数,object
* @param multi 是否可以多选
* @param filetype 文件类型,image,video,audio,file
* @param app 应用名,CMF的应用名
*/
function openUploadDialog(dialog_title, callback, extra_params, multi, filetype, app)
我就暴力修改了:
var that = this;
openUploadDialog('图片上传', function (dialog, files) {
$('#test-editormd').attr('src', files[0].preview_url);
var link = files[0].filepath;
var url = files[0].filepath;
var alt = '';
var altAttr = '';
if (link === "" || link === "http://")
{
that.cm.replaceSelection("");
}
else
{
that.cm.replaceSelection("[](" + link + altAttr + ")");
}
}, '', 0, 'image', 'app');
里面有replaceSelection('XX');
,这是Editor.md的自带方法,替换当前光标选中的文本或在当前光标处插入新字符。
至于上面的link,url,alt,altAttr参数根据你自己需求进行修改了。
然后就正常了。
4.saveHTMLToTextarea?到底是一个textarea还是两个?
这里网上的文章有点含糊不清,有说加textarea一个的,有两个的,其实就是看你想不想要直接保存html到数据库,
看下内部代码:
基本上就是,前面的class="editormd-markdown-textarea"
是读取到前台的数据,通过{$post.post_content}
读取到前台,后面的class="editormd-html-textarea"
是解析为HTML的数据,这里的name很重要,是name="post[post_content]"
,这是最终提交到后台的数据,我们这里的意思就是直接提交html到数据库。
5.打开额外的插件功能
如果你没有启用部分插件,在控制台会遇到问题。
将plugins
目录中的插件上传上去即可。
6.MarkDown的前端解析
如果你在前端没有启用saveHTMLToTextarea
,默认为false
,并且你在后端接收的时候没有接收第二个textarea中的HTML,那么,你在数据库中的post_content
字段为markdown的数据。前端在解析的时候也会是makrdown,显然这并不友好。
你可以有两种选择,就是数据库中储存markdown的数据,前端对markdown的数据进行解析。还有就是数据库中同时储存markdown的数据和html的数据(不推荐,但是我是这样做的,原因是我需要Editor.md和UEditor同时使用,不是同一页面)。
如果你是第一种的话,看起来就是下面这样,仅作演示,实际使用的时候务必注意调用路径!
<script src="__TMPL__/public/assets/editormd/lib/marked.min.js"></script>
<script src="__TMPL__/public/assets/editormd/lib/prettify.min.js"></script>
<script src="__TMPL__/public/assets/editormd/lib/raphael.min.js"></script>
<script src="__TMPL__/public/assets/editormd/lib/underscore.min.js"></script>
<script src="__TMPL__/public/assets/editormd/lib/sequence-diagram.min.js"></script>
<script src="__TMPL__/public/assets/editormd/lib/flowchart.min.js"></script>
<script src="__TMPL__/public/assets/editormd/lib/jquery.flowchart.min.js"></script>
<script src="__TMPL__/public/assets/editormd/editormd.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
var testEditor = editormd.markdownToHTML("test-editormd-view", {
htmlDecode : "style,script,iframe"
});
})
</script>
关于第二种,我就不太想说了,你可以通过新建一个数据库字段来完成这个事,有个问题是markdown转html没有任何问题,但是html转markdown就有些问题了。
7.分页
默认的分页是用的UEditor的_ueditor_page_break_tag_
,你知道_XXX_
是在markdown中会转义的,酌情修改即可。
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。