当 MarkEditor 遇到中文

写在前面的“免责声明”

本文的内容,本身可能存在争议。

为了尽可能避免争议,先声明我们基本遵循的原则是 (简而言之,怎么适合自己怎么来):
1,Markdown 只是标注,如何呈现各自表述,结构可关乎语义,也可以无关而只在乎实际的视觉呈现;
2,除了正式的工作场合,我们不应该受制于并未广泛接受的规范,其实只有建议而已,包括本文中的一些观点。
3,书写的体验,是自己的。阅读的体验才需要考虑读者,这是后话。

文中提及的大部分底层技术问题,在 MarkEditor 2.0 中都有所对应。
曾经意气风发,觉得只要肯花时间,最终的效果都能达到理想,现实更残酷,一部分考虑性能,一部分考虑技术底层本身的天花板,并不存在 100% 的理想。当然,在我们努力之后,有瑕疵的地方,普通使用者其实是很难感受到的……
所以,文中涉及到的一些竞品,我们认为他们也是可以做到更好一些,但由于各种客观因素,并不认为这是他们的缺点,请悉知。

另外,如果涉及到非常具体的排版规范、美学,我们所知,仅为皮毛,不足以产生给他人的参考。
如果你可以简单、快速获取的排版规范作为这方面的指导,以我们所知,这种指导是不充分,甚至是错误的。
当然,大部分时候,我们并不需要去深入探讨这个问题。

中英混排

诡异的行高

下面 GIF 图是 MacDown 的行高表现,一个比较典型的现象,此时并非真正的行高,而是做了一个行底部的 Margin (LineSpacing)。
我们可以看到:
1,普通行的行高和尾号的行高是不一样的(因为尾行没有可以 Margin 的)
2,文字选中后,当前行的文字实际上是没有居中的。

在中英文混排的时候,这个现象会更加明显,我们认为的 行高, 并非 Mac 上技术底层能直接处理的,一般需要开发者额外对应。
Ulysses、Bear 对这个问题有很好的技术底层对应。但也有比较临时的方案,比如看到过一个国内的 App,也是用 LineSpacing 实现 LineHeight 的逻辑,开发者为了避免尾行的行高偏小的问题,就在尾部添加一个不必要的空行,尽可能避免(又无可避免)使用者将光标聚焦在尾行……

输入抖动的问题

可能会奇怪,为什么讲 中英文排版 的时候,第一个问题说的却是 行高
行高 在 Mac 的原生 GUI 中,几乎是文本编辑时候,中英文混排出问题的元凶。

在 Mac 上,一个 中文输入法抖动 的现象可能我们已经习以为常了,即使苹果的亲儿子 Pages 这类应用也同样有这个问题。

下图是某著名写作 App:

这个是微信 Mac 版:

什么原因造成的?
行高!! 即使相同的字号,不同的字体,特别是中文、英文字体,其实际的行高基准线是不一样的!

有什么解决方案吗?
1,期望开发者在中英混排的时候提供更好的支持;
2,偏好设置中换一个中文的字体 (因为中文字体本身是包含英文字体的)……

其实第一个方案并不实际,因为说了,苹果的亲儿子 App 也有这个问题。
也因此,有不少朋友认为是某些 App 的开发者对中文不够上心。其实,也不尽然吧。确实处置起来非常麻烦,如果作者本身不是真正有切肤之痛,对中英混排这小细节不上心,也是能理解的。(但其实像微信 Mac 端这类简单的文本输入区域,处置起来倒是简单的……)

图文排版

图片,从某种角度上,也可以简单理解为一种语言。如果只是 英文+图片,或者 中文+图片,排版的计算还不算复杂,但是 中文+英文+图片 三种元素同时存在的时候,这个复杂度又上了一个度。

MarkEditor 在处理这基础排版引擎的时候,特别是中英文混排,确实耗费了很多精力。
然后,又遇到 图文混排 的问题,图片的高度不像文字一样,可以推定到一个固定高,也可归结于 行高 的问题吧。一种“才下眉头,却上心头”的绝望感。

在计算排版布局的时候,必须要考虑到图片的存在情况。
还要考虑到 GIF 图片是否允许播放、图片的缩放问题,细节的比如图片与光标保持 1 像素的间隔,这些都与布局的计算有一定关系。

字体

Textview 于 Webview,是两个不同的渲染引擎,一般 Mac 上 Native 的 App,都是 Textview,它的性能自然是远高于 Webview 的。
但在 Textview 中,一个文字的 粗体斜体 实际表达的并不是 效果,而是一个对应的字体。如果一个字体,它不存在粗体、斜体,那么,在 Textview 中,使用这个字体的文本是不会有粗体、斜体的特效的。
所以,我们会看到比如 Ulysses、Bear 会将粗体、斜体的语法,直接呈现出对应的效果,粗体还好,斜体就糟糕了,英文的字体一般是有斜体对应的,但是中文字体没有呀!

在设计 MarkEditor 的时候,我们就避免在 Editor 中呈现这些字体的效果,尽可能使用颜色的高亮进行表达。
重要的是标识,`xx` 类似的是指上是 行内代码 的语法,但是又有什么关系,我们在实际书写的时候,仅仅作为一种不同于加粗、斜体的强调语法,至于最终如何渲染,交于最终的 HTML+CSS 的渲染引擎再调整就好了。

Markdown 中文如何首行缩进?

使用 Markdown 最终渲染的格式,默认是无法做到 首行缩进 的。首行缩进的概念更多是出现在中文排版,而Markdown 默认最终渲染为 HTML,并通过 CSS 的样式来实现视觉的效果。
一般情况下,Markdown 解析为的 HTML,段落、分行是采用 <P> + <BR> 来实现,由于各种历史原因,<BR> 并没有特别的缩进样式 (但也不是完全绝对的,个别浏览器支持,未来的相关协议也有这方面的支持)。
在这个技术前提下,确实也让不少人认为 Markdown 和首行缩进是绝缘的,一样要实现,只能通过全角空格,或者 &nbsp; 的 HTML 转义字符。

我们其实也容易忽略一个事实,Markdown 是 10 多年前出现的,10 多年前的 HTML+CSS 跟现在也是有巨大差别的。
首行缩进可以说是一个历史残留的问题,而不是因为 Markdown 就是如此(原旨主义),或者 Markdown 最初就是为英文设计的。

边界总能被打破,在 MarkEditor 中,不论是书写的内容本身,还是最终的渲染结果,都能实现首行缩进的效果。当然,这个要看使用者的喜好,可以缩进,或者不缩进,或者 1 个 em,或者 2 个 em 皆可。毕竟,在移动端设备上阅读,有时候缩进未必会带来更好的体验。
但 MarkEditor 对于首行缩进的处理,也只是一般的对应。
实际上涉及到排版的技艺,有很多小的细节,Header(标题级)是否需要缩进,在列表中是否缩进,在 Blockquote(引用) 中是否缩进?甚至,这些什么也不都是定论,还要看具体的上下文决定。
如果有更细腻的想法,可以自己再定义 CSS 的样式,MarkEditor 的 HTML 结构提供了比普通 Markdown 解析结果更多的信息,多数排版上想法应该都能实现。

中英文之间的自动空格

在 MarkEditor 中,这是 Pro 版的功能,需要在 写作 -> 中英文间自动空格 勾选才会生效 (建议开启)。
有用户认为这么简单的功能只开放给 Pro 用户,并不合适。呃,我们没有做任何的改变,而是把这个功能,从 Pro 在文案上的 Feature List 上移除。

这并非一个简单的功能。即使 MarkEditor 而言,也没有做到极致。
识别中文、英文,并不困难,而是要针对不同的场景,是否空格的判断,其实还有不少条件的对应。而且,在未来的版本更新中,还需要补充一些额外的规则。

这个功能,其实也有“副作用”。
比如,我们自己在其它地方要处理文字书写的过程中,涉及到中英文同时出现的时候,就会有很大的不适应感,因为空格没有自动添加……

中文的词性分析

MarkEditor 有一个非常硬核的功能,就是词性分析,支持中文,也支持英文。
我们也发现一个有趣的现象: 如果一个逻辑陈述的段落中,使用的连词、代词过多,说明表达本身是有问题的,且不容易被读者理解。

词性分析也有其特定的应用场景,如果一篇文章被当做产品去完成,或者本身作为一个供稿人对文稿基础质量有要求的,那么这个词性分析就很有价值。
反之,则会被其束缚了手脚。毕竟,多数时候,快速而正确的表达,远比 推敲而精准 的表达更有价值。

连词+代词标注的状态:

全部词性标注的状态:

通过标点符号,找到上下文语义

词性的分析基础语义,除了文字之外,标点符号,也会很大程度上影响段落的意思。

MarkEditor 在解构 Markdown 规则的时候,考虑到兼容性的同时,还会在一些小的地方,探索更多的可能性。
在 Markdown 中,解析是逐行分析,比如下面的样式文章,实际上会被拆解为两部分: 普通段落+List,这两部分是相互独立的。

比如这有这些好处:
- 这是第一条
- 这是第二条

实际上,作为写作者本身,是期望这两部分建立逻辑关系的,通过 冒号 就可以判断出来。
所以,MarkEditor 在解析 Markdown 的时候,会进一步去寻找此类的上下文关系,并最终体现在 HTML 的结构中。
所以,MarkEditor 中,上面的示例文字,虽然最终解析为两个独立的部分,但通过 ME 特别的 HTML 结构产生了关联,默认的 CSS 样式,使其的视觉看起来是一体,而不是割裂的。

让键盘更理解中文

不断切换的中英文输入法?

由于 Markdown 使用的一些标记字符,本身也对应了中文中的一些标点符号,比如<>() 对应到了《》()
有人在中文输入法中,指定所有的标点符号为英文状态的,但有时候还是要用到中文标点符号就有些麻烦了。
也有人认为这么小的代价为什么也不能接受呢?不就是 Shift 键多按几下吗?呃,这个解决问题的思路似乎并不恰当……

在 MarkEditor 中,我们自己一般是会勾选 写作 -> Markdown标记符使用引文 -> 左Shifit 按下时,如此一来,基本上不用在书写的时候,考虑中英文状态的切换了:
1,如果侧 Shift 键按下的时候,都会输入英文状态下的符号;
2,如果侧 Shift 键按下的时候,则会命中中文状态下的标点符号。

Tab 键的小贴士

由于中文的一些标点符号是成对出现的,书名号、括号,一些中文输入法,也会自动完成标点符号的补全,比如 《》,输入第一个 的时候,会自动补全 ,并将光标自动前移一位方便输入。
为了方便在这些标点符号间更快的移动,MarkEditor 有一个很小的对应,就是光标在成对出现的标点符号前,按下 Tab 键,就会自动后移一位,从而减少键盘上的移动路径,以提高写作的体验。

One More Thing

Markdown 语法应该是简单的,但终归是 10 多年前被创造出来的,有些语法本身对于新的使用者来说,是很容易混淆的。

常见的比如下面两例 (在 MarkEditor 中已经禁用了这类容易混淆的语法解析):

> 这是引用的内容
这还是引用的内容
我是正常的内容

    因为有缩进,我已经不是正常的内容,而是变成了代码块……

恰是 Markdown 的简洁性,MarkEditor 才会将其作为一个基本的书写语法。
但这种简洁,应该是不容易产生误解的。
为了避免这种误解,MarkEditor 会努力寻找其中的一个平衡点,比如我们在中文相关的支持上做的探索。这些探索本身,可以说是有悖于多数人对 Markdown 的认识的,“呀,Markdown 难道也可以这样子?”

我们认为这些固有的边界,如果站在书写的体验、最终的效果的角度,都是可以去重新探讨的。
甚至于,大家几乎接受了 Markdown 中多余的空行是无效的 这样一个定论的时候。我们觉得也是可以再探讨的。
我们应该去推动一个工具不断适用于使用者,而不是被某种并不实际的原旨主义,束缚了手脚。

2018-08-01 15:30
Comments
Write a Comment
  • 那个语义分析会不会下放到windows?