跳转至

markdown在线编辑器 editor.md 二次开发

需求

经常需要在网络论坛发布文章进行宣传,但每个论坛的编写格式存在差异,给发布带来了很大的障碍。

最近markdown格式的兴起,给广大发布者带来了福音,一种文档格式大部分网站都支持,一次编写即可在多个论坛上发布。

如何在线编写markdown就成为一种需求。

markdown编辑器调研

经过查找和对比,发现editor.md是一款开源的markdown编辑器,非常的不错,实例丰富,使用比较简单。

editor.md 经过实际测试,发现几个小需求:

  • 自定义工具栏
    添加自己需要的内容非常有帮助
  • 无法快速移动光标到文档尾
    如果文档比较大,想要移动到文档尾部,比较麻烦
  • 无法上传图片
    需要配置服务端php才能支持
  • 无法复制粘贴图片进行上传
    这个功能非常的有用
  • 定期保存内容到浏览器
    一旦电脑崩溃了,编写的内容就全没了

打造在线markdown编辑器

自定义工具栏

index.html文件 增加如下三个配置,即可在工具栏增加html代码

toolbarIcons : function() {
      var toolBarIconArray=editormd.toolbarModes["full"];
    toolBarIconArray.push("aboutus");
    return toolBarIconArray;
        },

自定义html代码

toolbarCustomIcons : {
            aboutus   :"<a href=\"http://u.720life.cn/s/75244496\" target=\"_blank\"  onclick=\"window.location.href='http://u.720life.cn/s/75244496'\">交流Q群:1142802013 </a>" 
        },

editor.md 快速移动光标

在研究editor.md功能后,发现有移动光标功能,可以指定移动光标到多少行,使用起来稍微复杂一些,需要用户自己输入

1.editormd.js 中增加gfirst,glast

  full: [
          "undo",
          "redo",
          "|",
          "gfirst", //新添加
          "glast",  //新添加
          "|",

2.添加描述信息,鼠标放上去时的说明

     toolbar: {
            undo: "撤销(Ctrl+Z)",
            redo: "重做(Ctrl+Y)",
            gfirst: "回到顶端",
            glast: "到底端",
            bold: "粗体",

3.图标的定义

    toolbarIconsClass: {
          undo: "fa-undo",
          redo: "fa-repeat",
          gfirst: "fa-arrow-up",
          glast: "fa-arrow-down",
          bold: "fa-bold",

4.具体实现功能代码

     editormd.toolbarHandlers = {
        undo: function() {
          this.cm.undo()
        },
        redo: function() {
          this.cm.redo()
        },
        gfirst: function() {
              this.gotoLine("first")
        },
        glast: function() {
              this.gotoLine("last")
        },

注意: 最开始以为 gotoLine是 this.cm.gotoLine的函数,但这样总报错,最终发现cm下的函数应该是 \lib\codemirror\lib\codemirror.js 下面的,因此直接写this.gotoLine即可

文件上传功能修改

  • 支持绝对路径返回 php/upload.php
    $path     = getcwd() . DIRECTORY_SEPARATOR;
    //$url      = dirname($_SERVER['PHP_SELF']) . '/';
    $url = $_SERVER["REQUEST_SCHEME"] .'://'.$_SERVER['HTTP_HOST'] . '/';
    //按照月份进行记录
    $_time = date('Ym');
    //用户是否是免费用户 免费用户free 付费用户pay_token
    $savePath = $path . '../../uploads/free/';
    // 创建images 目录
    if (!file_exists($savePath)) mkdir($savePath);
    $savePath = $savePath . $_time.DIRECTORY_SEPARATOR;

    // 创建月份 目录
    if (!file_exists($savePath)) mkdir($savePath);

    $saveURL  = $url . 'uploads/free/'.$_time.DIRECTORY_SEPARATOR;
  • 保存文件路径失败的修改 php/upload.php
$imageUploader = new EditorMdUploader($savePath, $saveURL, $formats['image'],  1, 'H_i_s');

浏览器js读取剪切板图片 上传到服务器

document.addEventListener("paste", function (e) {
    var cbd = e.clipboardData;
    var ua = window.navigator.userAgent;

    // 如果是 Safari 直接 return
    if ( !(e.clipboardData && e.clipboardData.items) ) {
        return;
    }

    // Mac平台下Chrome49版本以下 复制Finder中的文件的Bug Hack掉
    if(cbd.items && cbd.items.length === 2 && cbd.items[0].kind === "string" && cbd.items[1].kind === "file" &&
        cbd.types && cbd.types.length === 2 && cbd.types[0] === "text/plain" && cbd.types[1] === "Files" &&
        ua.match(/Macintosh/i) && Number(ua.match(/Chrome\/(\d{2})/i)[1]) < 49){
        return;
    }

    for(var i = 0; i < cbd.items.length; i++) {
        var item = cbd.items[i];
        if(item.kind == "file"){
            var blob = item.getAsFile();
            if (blob.size === 0) {
                return;
            }

            // blob 就是从剪切板获得的文件 可以进行上传或其他操作

            var data = new FormData();
            data.append("blob", blob);
            $.ajax({
                url : "php/blob_upload.php",
                type : 'POST',
                cache : false,
                data : data,
                processData : false,
                contentType : false,
                success : function(result){

                var   json = (typeof JSON.parse !== "undefined") ? JSON.parse(result) : eval("(" + result + ")");
                    if(json.success == 1){
                       //上传成功

                       testEditor.cm.replaceSelection("![](" + json.url + ")");

                    }
                }
            });


        }
    }
}, false);      

将代码放入到html页面 即可实现功能,目前确认chrome和火狐是可以支持的,可以使用微信、QQ、win7 自带截图 进行截图复制,在页面上直接粘贴

每30秒保存当前文档到本地

index.html设置一个30秒的定时器,将当前内容保存到本地localstorge,代码如下:

function save_content(){
       
    if (localStorage) {
        localStorage["content"] =$(".editormd-markdown-textarea").val();
    }
}
setInterval("save_content()",30000);  // 30s执行一次 

打开网页时,首先判断是否有localStorage,代码如下:

 $(document).ready(function(){


            var isHave = false;

            if (localStorage) {
              if(localStorage.content && localStorage.content.length > 0) {
                 md = localStorage.content;
                 isHave = true;
              }
            }
            if(!isHave){                 
                $.ajax({
                    url : 'test.md',
                    cache : false,
                    async : false,
                    type : "GET",
                    dataType : 'html',
                    success : function (result){
                       md = result;
                    }
                });
            } // endif isHave

部署方案

由于本项目大部分都是静态资源,只有3个API接口,因此建议将3个API接口独立出来,静态文档托管到云上

可以放到七牛云或gitee等托管仓库

markdown在线文档编辑器

在线markdown文档编辑器

工具适合人群

目前使用该工具的几个场景:

  • 临时在线编写markdown格式记录表
    比如编写本周工作计划,执行完一条删除一条,非常方便, 没30秒自动保存
  • 编写一篇markdown推广文章,进行效果预览

官方QQ交流

如大家有问题,欢迎加入官方交流Q群讨论

官方交流Q群:1142802013

致谢

感谢editor.md 项目,非常的优秀

TODO

  • 首次打开页面时,随机显示一篇markdown文档
  • 加快加载速度