关于for-editor的扩展开发及markedjs语法扩展的心得

关于for-editor

开始接触for-editor是由于想本身写一个基于Git的支持markdown的笔记本PC应用,经常使用开发框架是React、在PC端的开发工具的选择上选择了吃内存狂魔electron,就这样抱着能不造轮子就不造轮子的原则开始使用了for-editor(虽然以后没有打算继续开发)。for-editor若是对于语法的支持没有过高的要求的话,是一个很是优秀、简洁的编辑器组件。支持Tex渲染插入、mermaid流程图的支持、高级markdown或者扩展的markdown语法,随着需求的提高就准备了开始本身扩展语法之路,固然其中发现了不少须要优化和修改的地方。html

开发之路

通读源码

源码能够从for-editor中查看。webpack

首先,阅读package.jsonpackage.json是全部React组件开发必不可少的环节,在此以前仍是须要足够了解工程的README.md的。在package.json里,源工程对于markdown解析所用的引擎为marked.jshighlight.js。在以前了解markdown --> HTML的渲染学习的时候所用的是marked.js,好处是足够简洁,坏处是语法不多而且扩展要求并不低。git

其次,对于源码结构的解读。dist为生成产物,doc为相关文档,example为演示文档,src为源码目录,webpack为配置项。在src下有componentslibindex.tsxcomponents为工具栏的组件,lib是开发的依赖和功能源码,index.tsx为总体的页面结构。github

发现的问题

这里提到的问题其实有一些是尚未彻底修复的,有些问题真的存在了不少年了,至今我也没能想到比较好的解决办法。

响应式布局

在现代web开发中,响应式布局对于用户体验来讲是很是好的,可是在访问速度上相比加载速度会稍微慢一些。针对于高标准的用户体验,我选择了牺牲掉一些访问速度,固然对于纯的经过CSS实现响应式布局在某些时候根本达不到好的效果,是须要JavaScript来加buff的,这也为以后的开发其实还挖了一个坑,对此我不得不作出妥协,彻底的响应式目前看来是作不到的。在下面,我也会阐述具体的坑究竟是什么。web

响应式布局方面我作出的优化是针对900px这个标准进行的分割,随着工具栏功能的拓展,本来工具栏的布局会溢出。所以对于没有二级菜单的工具栏button,我选择写在了more里,而且另开了for-mobilefor-pc,使用了flex布局来处理宽度不够换行处理的优化措施。在下一个坑没有遇到以前,这个方案我以为解决的还算不错。(固然开了新得分支,仍是被提了issue,主要是他遇到的浏览器尺寸在我测试的时候真的没有发现任何问题,很迷惑)正则表达式

mermaid的引入

这是我几个月都没有解决的问题,多是打开方式不太对吧。。。参考了mermaidAPI和与mermaid开发者交流提了issue可是始终没有解决。难道mermaid真的是只能用已存在DOM节点来作渲染的吗?但愿能有大佬带我深刻了解一下。mermaid的渲染要写在主组件的生命周期里面,可是就我刚刚说的,若是已知存在,在何时插进去来触发渲染?最后我选择了原样插入,而后再触发渲染的方式,当我满心欢喜以为一切都能如愿的时候。我发现真的能不能渲染出来都是薛定谔的猫:(而后不得不放弃,想一想也真的可能跟后面那个深坑有关系,总有办法能解决这个问题,而后参考过CSDN的HTML代码,也就是我后来的考虑的深坑。对此,我移除了mermaid的渲染支持。json

修复js对于二级菜单的控制

感谢@ivanandonov的issue,以前我并不太以为点击关掉二级菜单很重要,其实也就是添加个关掉二级菜单的事件,问题不大。浏览器

拓展marked.js的语法

这是本部分最核心的内容了。如何去扩展marked.js的语法???我看到网上有不少小伙伴尝试去扩展语法,可是也有很多选择了放弃。markdown

若是你想尝试去扩展语法,熟读marked.js使用指南marked.js源码和实现逻辑,固然还须要写正则表达式:)框架

marked.js最牛逼的部分就在于正则表达式,就不重复匹配的问题,如何去用正则表达式去表示?所以重写renderer的时候我参考了不少源码部分的内容,这里就不针对marked.js详细展开介绍了,我只写一写我到底作了哪些事。

  • 抽离highlight.js。在原项目发现的问题之一就是——我如何去让使用者自行决定高亮的代码类型?我总不能把全部的语言都注册一遍吧?!不但增长了代码量,还需求不是很大,因此我选择了把highlight.js依赖给移除掉。让使用者传入Hljs.highlightAuto这个函数,其余的本身引入highlight.js而后本身注册就完事了。
  • 引入emojiTexdiff语法、mark作行内高亮。这就涉及了很多的正则表达式,尤为是在mark这个渲染上,你总不能把每一句都拿正则循环跑吧,根本不实际。因此得先把高亮块抽离出来而后再排回去,而且不能涉及须要使用的非特殊字符。感兴趣的小伙伴能够参考marked.ts这个部分的源码。对于相似```这种就是对于code块的解析,若是是行内嵌入或者自定义渲染块呢就在paragraph的部分进行重写renderer就行了,可是记得必定要看源码对应的html的标签。

扩展渲染的锚点和大纲

渲染的锚点就是重写heading部分的HTML,不赘述了就是添加一个a标签就能解决的事情。大纲、目录、TOC,一个东西须要用到marked.js提供的解析器lexer,提取heading部分和深度,而后来写样式部分。

深坑——如何去调整textarea的高度

这一切的问题仍是来源于,当我使用分栏的功能。我发现记行号并不正确,而且textarea的部分并不能很好的解决高度问题,由于高度不足以显示所有的内容。为何overflow: hidden其实我在不断优化这个问题的时候也能体会到,由于外部的滚动条须要与行号对齐。

  • 修改一:换掉计算行号的方式。源代码的计算方式是经过计算\n来实现的,貌似vscode的markdown也是这么实现的,可是就优化而言textarea对于行号样式能有vscode这样的调整我是没有发现能有什么办法能够作到的。所以我也考虑了不少办法去优化这个问题,甚至重构编辑器。在目前2.x.x的版本中,我已经换成了根据textarea的高度来计算行号了。
  • 修改二:自适应调整textarea的高度。认真地说,这个坑都坑了多少年了,不知道坑过多少人,知乎还有不少的讨论。其实改起来也不算难,就是把height: auto,而后动态调整高度等于scrollHeight。而后我选择了把计算行号在从新计算高度的函数中进行了调用。看起来,everything is ok了是吧?:)惊喜的是当分栏激活的时候scrollHeight并非会增大,是会减少的,没想到吧。而后我只能选择目前来讲我能提供的最优的解决方案,仅当分栏关掉的时候计算高度,而后经过修改值就能够作到精确计算。原做者还提供了fontSize这个可选项,为此我去了解了line-heightfont-size之间的关系,具体的源码请参考index.tsxreHeight部分的源码。其实我还考虑过,根据上一时刻的面积除当前时刻的宽度来计算高度的,听起来是真的很美好。实际状况是,当你切换过快的时候,读取到的面积并不许确,所以这个方法就是理想很丰满,现实很骨感的问题。
  • 为何不考虑去用可编辑div重写?下次必定,我是准备在3.x.x的版本重构的,可是我目前没有这么多时间去考虑这个问题了,是真的很麻烦。

心得感悟

小小的富文本编辑器居然如此复杂,我忽然发现我是想慢慢尝试去实现word的最基础的功能。在拓展for-editor的过程当中我学到了不少根据教程根本是不可能学到的实际开发问题,为此我付出了很长的事件去研究源码,固然也去开始适应TypeScript来作开发。使用开源项目不是减小工做量,很大程度上其实增长了很多学习成本。

若是喜欢for-editor-herb我这个分支呢,请给原项目一个star。

相关文章
相关标签/搜索