我第一次坐在Jacob(@fat)桌子对面时,他直率的问:“你是怎么写一个文字编辑器的?” 我在白板上画了一个树结构,挥舞着手臂,说“这个是如shit一般的编辑界面。“然后我画了一列方框,用箭头指向数组,更多的挥舞手臂,说”这个是一个好的编辑界面。” Jacob扬了一下眉。 这篇文章是我本应该那时说的,如果我有一年的时间去思考的话。 为什么 ContentEditable 这么恐怖: 一个数学上的佐证ContentEditable 是一种在web浏览器上进行富文本编辑的本地原生组件. 它是那样让人…伤感. 我会用一些顺手拈来的数学方法来想你证明,目前的ContentEditable的方法是不好的. 这并不是因为我觉得数学是解释这个论点的一个有说服力的方式。它实际上使得这个论点更加的异类话. 但是我真的觉得文本编辑器导致了太多的模棱两可, 就像“所见即所得 (WYSIWYG) 是啥意思?”还有 “当你选择了这段文本并敲下了Enter会发生什么?”这样不明确的问题。公理化的数学是我所知道的能解决模棱两可的问题并对它们进行明确的最佳工具. 那么所见即所得是什么意思呢?一个好的所见即所得编辑器应该满足下面3个定理: 首先,我会解释这3个定理所表达的意思,并且一个好的编辑器为什么要遵守这些规则。但是我们首先要明白:他们是定理。他们最弱的部分是缺少证明。但是我们假设他们是没问题的除非我们能拿出明显的证据来。
最后,我会讨论浏览器新的特性和库是怎样针对这些问题的,以及我们怎样在普通的编辑器中处理他们的。 DOM空间是我们能在HTML中表述的所有网页页面的集合。所有页面都能够被表示成一个元素树,而这些树把文本节点作为叶子。 可视化空间(“所见即所得”)是所有可视化页面的集合 — 也就是我们在屏幕上看到的浏览器渲染的一个页面。我们常常会把看起来一样的两个页面的可视化空间认为是一样的。 浏览器渲染引擎是一个把DOM空间映射到可视化空间的一个映射。“映射”是指对某个DOM树 x 进行 Render(x)操作产生所有的可视化页面。 当我们说一个映射在编辑器中表现良好时,我们的意思是这个映射保留了所有的编辑操作(见注1)。更准确的说,如果渲染的定义是明确的话,那么
这是一种在“你看到的是什么”之后确定“你得到了什么”的方式。如果两个部分看起来是一样的,而我们对它们进行了相同的编辑,那么两种结果应该看起来是一样的. (请再看看第 1 条) 我已经很惊奇的看到网络上那么多的 “WYSIWYG” 编辑器都打破了这个规则. 这听起来应该是一个理所当然的规则。但是它会导致你陷入有关“相同”是什么意思这个有点怪异的问题,而对这个问题的问题的最好探讨就是示例了. 行为良好的内容看看下面这个例句:
编辑器里面呈现这句话,大致上如下所示.
有许多许多的方式可以用来对最后一个词—— Baggins —— 进行编码. (见注2)
编辑器应该明智的认为这些形式是等价的。你对这篇文章所进行的任何编辑都应该对所有这种形式同等对待。编写一个编辑动作来了解所有这些不同的DOM形式是需要令人极其惊讶的技巧. 对于网上大量的可编辑内容的实现,一些不显眼的字符或者空的span标签可能会进入到HTML中,因此两个可编辑内容的元素的表现完全不同(即使看起来是一样的)。这样的体验会激怒用户,而工程师也很难去调试。 即使我们知道如何编写一个表现良好的编辑动作,但我们怎么检查它呢?如果我们把HTML限制到一些简单的标签,证明两个表单视觉上是相等的将。。。非常复杂。你最好能够在每个字符上迭代,分配一个样式,并比较结果。 在理想世界里,我们对于DOM的“可视编辑”会有一些高级的API。每个操作将保证它的有效性,对于所有视觉上相等的页面做“相同”的操作。这样,只要你的编辑器仅仅使用这些API,你就能保证它的有效性。 有效性选择DOM和可见内容的映射是很丑陋的,但至少是多对一的关系。一个DOM表示有一个准确的可见表示。 选择更加丑陋,因为映射是多对多的关系。 你可以很轻松的看到一个可见的选择可以有很多的DOM表示。如果你有HTML,
那么“Baggins”之前的指针可以在三个DOM位置之一:在 strong开始标签前,在 strong开始标签和 em开始标签中间,以及在 em开始标签之后。如果你把指针放在“Baggins”之前开始输入,你的字符会是粗体,斜体,或者都不是? 更微妙地,一个DOM选择可以有多种可视化表示。比如下面这种情况,“well-to-do”在“to-”之后换行,如上图所展示的。光标在第一行的末尾和在第二行开头拥有同样的DOM位置,但是却拥有不同的可视化位置。就我所知,我们没有办法让浏览器去优先选择哪一个可视化位置。当我们设计编辑器命令的时候,我们会让选择操作表现的和看起来是一样的。但是那太痛苦了,因为这种映射太混乱了。 封闭并且完整的编辑操作几年前的某一天, 我的朋友Julie在Gchat上给我发了一个消息: We can remove Apple Style Span…Oh happy day! Ryosuke Niwa 在WebKit的博客上发表了一个友好的帖子 ,这篇帖子请求移除苹果风格的span(apple-style-span)。如果你之前读过这篇文章的话,那么他提出的许多问题听上去很耳熟。WebKit的ContentEditable 编辑器增加许多“bookkeeping”HTML标签,这种标签不会改变任何的可视化效果,仅仅是使编辑器表现的不同。 他也指出WebKit的ContentEditable的实现必须能够处理由其他任何的CMS或其他任何的浏览器的ContentEditable 的实现创建的HTML。我们的编辑器在这种生态环境下应该是一个好的公民。这意味着我们应该制作易读易懂的HTML。但另一面,我们要意识到我们的编辑器必须处理那些我们不能在编辑器中创建的拷贝内容。 我见过许多种问题,复现这种问题的唯一方式是在Firefox中写文本,然后切换到Chrome中做编辑操作,再然后切回到Firefox中。这对开发者和用户来说是非常令人沮丧的。 |