Skip to content

Markdown在线预览

Published: at 07:18 AM | 3 min read

Markdown在线预览上线了,拖动文件或者点击上传markdown文件就可以预览了。
服务器不保存文件副本,只是将上传的文件内容转换为html格式显示在网页上。

点击地址访问:3inns.cn/mdviewer

Markdown viewer

前端实现

支持拖拽和点击打开文件夹选择文件的方式

html代码

<div id="content">
    <div id="dropbox">
      <h1>Drop file here or click to upload</h1>
      <h3>(The server does not keep a copy)</h3>
      <h4 id="tips"></h4>
    </div>
    <div id="result"></div>
    <input type="file" id="inputfile" name="file" style="display:none"/> 
</div>

js代码

<script>
      var dropbox = document.getElementById("dropbox");    
      dropbox.addEventListener("click", openfile, false);
      dropbox.addEventListener("dragenter", dragenter, false);    
      dropbox.addEventListener("dragover", dragover, false);    
      dropbox.addEventListener("drop", drop, false);  

      $('#inputfile').change(function() { upload($('#inputfile').get(0).files); })
      function openfile(e) { $('#inputfile').click(); }
      function dragenter(e) { e.stopPropagation(); e.preventDefault(); }
      function dragover(e) { e.stopPropagation(); e.preventDefault(); }
      function drop(e) { e.stopPropagation(); e.preventDefault(); upload(e.dataTransfer.files); }

      var tips = $('#tips');
      function upload(files) {
        if (files === undefined) {
          return;
        }
        if (files.length !== 1) {
          tips.text('Tips:Only one file can be uploaded.');
          return;
        }

        var fileObj = files[0];
        if (fileObj.size > 5 * 1024 * 1024) {
          tips.text('Tips:No more than 5M.');
          return;
        }

        var FileController = "../mdfile"; // 接收上传文件的后台地址 
        var form = new FormData();
        form.append("author", "3inns.cn");
        form.append("file", fileObj); // 文件对象

        var xhr = new XMLHttpRequest();
        xhr.open("post", FileController, true);
        xhr.onload = function (e) {
            console.log('over');
        };
        xhr.onreadystatechange = function() {
          $('#dropbox').hide();
          $('#result').html(xhr.responseText);
        }
        xhr.upload.addEventListener("progress", function(evt) {
          if (evt.lengthComputable) {
            var percentComplete = Math.round(evt.loaded * 100 / evt.total);
            console.log(percentComplete);
            tips.text('Tips:' + percentComplete + '%');
          } else {
            tips.text('Upload failed!');
          }
        }, false);
        xhr.send(form);
      }
    </script>

后台实现

使用的是koa2

引入koaBody模块

const koaBody = require('koa-body');
...
app.use(koaBody({ multipart: true }))

路由以及实现

使用marked模块转换markdown文本为html格式

app.use(route.get('/mdviewer', Extends.mdviewer))
app.use(route.post('/mdfile', Extends.mdfile))

// Extends对象
module.exports.mdviewer = async function(ctx) {
    ctx.body = await ctx.render('md_viewer');
}

const readFilePromise = (path) => {
    return new Promise((resolve, reject) => {
        fs.readFile(path, 'utf8', (err, data) => {
            if (err) {
                return reject();
            }
            return resolve(data);
        })
    })
}

module.exports.mdfile = async function(ctx, next) {
  if ('POST' != ctx.method) {
      return await next();
  }

  if (ctx.request.body.files && ctx.request.body.files.file) {
    const author = ctx.request.body.fields.author;
    const file = ctx.request.body.files.file;
    const content = await readFilePromise(file.path);
    if (content && content.length) {
        const html = marked(content);
        ctx.body = html;
    } else {
        return await next();
    }
  } else {
      return await next();
  }
}

代码不多实现起来也不复杂,暂时没考虑各浏览器的兼容性问题,相信大家用的都是新版浏览器。