阳光正好,微风不燥。
前言
万事开头难,鬼知道在写这篇文章的时候我踌躇了多久。
在知乎上有一篇帖子在讨论Markdown编辑器做成WYSIWYG(所见即所得)形式有什么弊端。
本文相对而言,更像是开篇总结,实质内容没多少,活脱脱一篇菜鸡踩坑日记。
对于一个程序员来说,我们使用markdown大多是在README.md或者api文档中,样式是我们从不去关心的,因为市面上有很多优秀的markdown编辑器:mdnice、vditor等等。
退而求其次,供我们选择的markdown解析渲染插件也有很多:marked、markdown-it。
再退而求其次(内心OS:对,我就是这么没有底线),vscode、webstrom、py、Go....甚至是文本编辑器,我们都可以去写markdown(至于样式,我都退成这样了,给个活路吧亲)。
言归正传,做一款左右预览的markdown编辑器不算难,从旁观者的角度来看,无非是选个框架,去npm哐哐哐哐install一些插件,接着左边儿跟我一起画个龙(编辑区);在你右边儿画一道彩虹(预览区),在你胸口上比划一个郭富城(菜单栏),至于优化,再说再说。
在写这篇文章的前几个月,我基于React+monaco-editor+markdown-it做了一款左右预览的markdown编辑器,但是(敲黑板),无论多么完善他,总是会有左右滚动不同步的问题,无论使用codemirror还是monaco-editor,他们都是一款成熟的编辑器,但是(再敲黑板),我们在右侧预览的时候,当我们左侧插入图片,右侧将图片显示出来,它和左侧的图片语法不能够完美的对应上,例如:当我们左侧图片链接已经滚出可视区域,而右侧图片因为高度的原因,或多或少都会出现图片还没滚动出可视区域的问题。
为了解决它,我调研了很多成熟的编辑器,做得好的:stackedit vditor HyperMd balaala一大堆。
由此,引出了我长达几个月的踩坑之旅。(朱局长:他平时就这么勇的吗?🐶)
ContentEditable
那时,我们还年轻。总觉得世界应该是我们的
在使用contenteditable="true"的时候踩坑不仅是单行内容在结构嵌套的情况下光标位置的问题,这个问题的解决可以参考vditor的解决方案,动态向内容中插入<wbr />标签,然后实时获取标签位置,将光标移动到这个标签之后删除这个标签。
但是相应也会产生一个问题,因为vditor是使用了自己编写的词法分析器---Luter,所以它不必担心这个wbr标签会对输出的html格式产生什么样的影响,但是,我们如果使用marked或者markdown-it去解析内容的时候,因为有这个标签的存在,可能会存在将加粗解析为两个斜体(因为中间有wbr)
vditor
通过阅读vidtor的源码(对不起,vditor作者,🧎♀️),我知道了,他其实自定义了markdown的词法分析---Luter,在此基础之上完成了vidtor编辑器,我最开始想要尝试使用Luter引擎,但是后来困难战胜了我脆弱的小心灵,同时给我造成了不可磨灭的伤害,不是说Luter不好,相反,他脱离于正则去校验是否输入为markdown特殊语法,在响应速度上会优于很多词法分析器,但是他对我这个菜鸡而言,太难了,我曾经在他的基础上连续开发编辑器半个月左右,后来将这些代码全部放弃,重新去考虑其他的了,因为:
-
我觉得我再写也不会超越vditor(Jay:我感觉我一直活在“夏洛”的影子里)因为单从编辑器这个角度而言,至少是我阅过的源码中顶优秀的存在,像国外的stackflowd 的优秀开源工具stackedit,他的缺点在于使用了vue作为了技术框架,此举不是为了批判vue,因为我也使用vue使用了几年,而vditor是脱离于三大框架之外,更能一套代码多端适配。这才是我推荐的原因,当然,也得说说vditor的左右同步滚动做的不到位呀,还是很不同步的
-
我再怎么写,也是vditor mini,因为luter和vditor人一家产的,在使用luter的时候或多或少还是会使用到vditor的东西,那 和直接对vditor的源码进行删减有甚区别?
-
我是个菜鸡而已,单单一个heading的语法就让我够头疼了,在光标切换到其它行的时候,我们之前行的内容如何展示,我拿到的是text,并不是一个stream流,这让我很头疼,我总不能走一个for循环去解决这个吧
stackedit
这个并不是因为vue就不可取了,想反,他的代码很牛逼,大佬将所有的正则匹配规则都写在了里面,其实说真的,可以借鉴一下,我决定在之后我的这个v1版本完成之后将这块做一下。
小结
当我在使用contenteditable="true"这条路上走了很久之后,我清楚的认识道自己是个菜鸡👎,因为从头去写一个真的是太难了,光标、换行等等的问题接踵而来,如果想要踩坑少,我就不自觉的想要看vditor或者stackedit源码。
难道,我只能做一个面向源码编程的码农?
codemirror
我以为我搭上了通过成功的阶梯
接着,我使用了codemirror这个代码编辑器,相对于monaco-editor,它的又是在于:体积小、文档全,同时他只是提供了输入,至于输出以及结构,全部是我们去自己主宰的,可插拔性极高,由此,引出本次更新日志的重点,当然也算踩坑较多的地方。
直接说结果,也是以失败告终,失败点在于:当我们在写table语法的时候,他会在多行去展示这个语法,以HyperMd demo为例:
他不是在一行去展示,我尝试过当检测到markdown语法的时候自己创建一个table结构,但是这样子光标又会出现问题,因为codemirror是块级光标,当插入在一行的时候光标就会很长。
也有试过我将markdown解析,然后在codemirror中插入html,但是这样表格内容无法编辑,如果在table上加contenteditable又不能直接修改td中的内容,td上加contenteditable又会很小,且不能使用快捷键切换。
slate.js
蓦然回首,那人却在灯火阑珊处
slate 是一款流行的富文本编辑器——不,与其说它是一款编辑器,倒不如说它是一个编辑器框架,在这个框架上,开发者可以通过插件的形式提供丰富的富文本编辑功能。slate 比较知名的用户(包括前用户)有 GitBook 和语雀
钉钉的文档协同团队,在自研文字编辑器之前,就用了很久的slate
其实截止到现在,我仍没有完成自己的markdown编辑器,但是,我目前完成了标题和table表格的语法支持,参考下方GIF图:
结语
本文主要是针对之前做WYSIWYG(所见即所得)的markdown编辑器时所遇到的经历以及采用、放弃的内容进行总结,算是一篇开篇文序,后续将同步更新基于slate.js实现markdown的WYSIWYG(所见即所得)的过程。