blog开发:属于我的markdown编辑器

codemirror


发表于 2018-12-28 12:05


刚开始的时候,我的编辑器是这样的:

base64_3f0836f763af4c739bdb47cdbaa10356.png

勉勉强强能够写篇文章,由于体验实在是不好,所以后来改成了这样(我照搬了http://jbt.github.io/markdown-editor/ 的样式 ):

base64_7d43fc49530349f1893a0d7d1d369b10.png

但这其中有一个问题是如何保markdown证前端渲染能和后端渲染做到一致,我后台解析用的是commonmark-java,如果前台采用js来渲染,由于采用的解析器不一样,很有可能就导致了预览效果和最终效果不一样,也正是因为这个顾虑,我改为了将markdown文本发送到后台,渲染完毕之后将html文本返回,这样做虽然可以保证前后端渲染效果一致,但每次渲染都涉及到前后端的交互,性能低下,扩展性差。

这个问题一直到我看到了后台利用和nodejs服务交互解析markdown的思路才得以解决,对于nodejs,我完全就是新手级的,但好在我所需要的部分实现还算容易,具体请见process-markdown-with-nodejs,虽然要开启一个额外的服务程序,但是很值得。

接下来是一个写作部分与预览部分同步滚动的问题,我看过了很多的在线编辑器,Stackedit、马克飞象、小书匠以及Cmd Markdown等等,它们都工作的很好,哪怕预览内容中存在大量的图片时,它们也能滚动到对应的位置,我不知道它们采用了什么算法,所以这个功能一直搁置下来,直到我看到了 markdown-it的demo。

我看了它的源码后发现,它会在生成的html文本中添加对应的源码所在的行数,然后根据这个行数滚动到对应的位置:

function injectLineNumbers(tokens, idx, options, env, slf) {
    var line;
    if (tokens[idx].map && tokens[idx].level === 0) {
      line = tokens[idx].map[0];
      tokens[idx].attrJoin('class', 'line');
      tokens[idx].attrSet('data-line', String(line));
    }
    return slf.renderToken(tokens, idx, options, env, slf);
  }

  mdHtml.renderer.rules.paragraph_open = mdHtml.renderer.rules.heading_open = injectLineNumbers;

虽然最后的实现还是有点复杂,但好在在我的孜孜不倦的搬运之下,也能够在我的编辑器上正常的工作了。

最后来到手机端,codemirror对手机的支持有限,甚至于存在无法在ios上利用原生键盘输入中文的bug,请见codemirror-ios-input-chinese-bug

如果能够正确输入了中文,那么在利用ios原生键盘录入的时候,还会碰到这样的问题,请见 https://www.qyh.me/space/web/article/584

我花费了很多时间让这个在线编辑器能够在手机端上工作(仍然不是很顺利,缺乏调试工具),但同时我也认为手机端并没有这么强烈的写作需求,并且手机端也有很多markdown app,它们的体验更好,功能也更强大。

最后附上在线调试测试地址: markdown-editor


搜索