对于现在各种文档系统的吐槽
作为强迫症患者,选择合适的文档工具是个特别纠结的问题。过程中涉及到的两种主要需求是
-
存档需求,要求文档包含足够的结构信息。比如 ConTeXt 里有个宏
\quotation,用来排行间引用,就比直接写引号要包含更多的结构信息。 -
展示需求,要求工具有足够的设施用来实现各种排版效果。
同时满足这两个需求的工具才是好工具。
HTML + CSS
HTML 作为文档格式最大的问题就是结构上的表达能力太弱,简单地说就是 tag 的种类太少。比如你想写一段引文,只有一个 blockquote 可用,没有特殊的 tag 来表示引文出处之类的结构。原则上你可以写个 <div class="source"> 这样的 tag 来自己定义任何结构,而且在设计网页的时候这是个标准操作,但是用来存档的话就很弱鸡了,不如使用 XML,写起来差不多复杂。
HTML 5 加入了几个重要的结构标签,比如 article 和 section,但有个很严重的问题,就是 HTML 5 没有 schema⋯⋯(是的,HTML 4 居然是有 DTD 的⋯⋯)这就是说 HTML 5 不能使用 XML 工具(包括 XSLT)来处理,只能使用专门的解释器。
HTML 的另一个问题是历史包袱太重,标准中充满了诸如 <font>, <i> 这种纯粹用于展示用途的标签。当然你可以选择不用,但是你不能保证别人不用,也不能保证你不需要处理包含这些标签的文档⋯⋯ (眼睛看向 LaTeX。)
EPUB 和其他电子书格式
这些电子书格式一般都是编译结果,也就是单纯用于展示。这些格式问题是它们都是打包的 HTML,一般是由设备内嵌的浏览器渲染,所以几乎一定特别难看⋯⋯ 这里的难看并不是指字体不好,或者行间距太小之类的,而是不使用高级的排版算法(比如断行和各种 micro-typography)。当然表面上来讲这不是电子书的锅,而是 HTML 和浏览器的锅,但是 HTML 是用来写网页的啊,浏览器是用来看网页的啊,好的排版算法只是网页渲染里一个非常微不足道的需求,高效地实现各种交互和动态效果远比排版算法重要的多,也是浏览器厂商关注的重点。然而电子书是本书啊!丫的是书啊!书!一本排版难看的书,不扔难道留着过年⋯⋯?所以电子书使用浏览器渲染,阅读器厂商这种懒惰的行为造就了电子书「难看」的印象。
一般来说我拿到 ePUB 之后会解包转成 TeX 重排一遍⋯⋯
Markdown 和其他简化 markup
我觉得所有这些格式里,Markdown 是最弱鸡但同时也是最无辜的一个。Markdown 的功能特别少,因为发明者 John Gruber 在设计 Markdown 的时候从来就没有想过要用它处理复杂的格式,Gruber 只是为了能方便地写 blog 而已。你去看看他的 blog 就知道 Markdown 为何如此简单了。
然而在懒惰的开源社区开始动歪脑筋以后,一切都改变了⋯⋯ Markdown 有了各种各样的扩展,巨硬甚至有人闲得没事搞了扩展用来写学术文档⋯⋯ 但是 TeX 已经存在了啊,有这个功夫还不如自己搞一套宏包⋯⋯
这就好像你想去赛车,本来你车库里就有辆 Nissian GTR, 调一调悬挂可以直接上,你却非要翻新一辆报废的夏利然后换台发动机⋯⋯
这种事也只有开源社区能干的出来⋯⋯
如果你执意要用 Markdown 处理复杂文档,你最终一定会遇到这些问题:
-
基本控制符不分左右,无法处理复杂格式。Gruber 最初的 Markdown 处理器是一个基于正则表达式的 Perl 程序,大家都知道标准的正则表达式是不能处理任意层数的嵌套的(比如 HTML 里的嵌套
div),所以 Markdown 里的控制符没有必要分左右(因为反正不能嵌套⋯⋯)。另外由于同样的原因,很多 Markdown 处理器都不能可靠地处理这种情况:_aa*a$2*x_0$b*bb_(假设$是行间公式)。 -
Markdown 标准并不是非常详细,很多行为都是未定义的,所以处理器之间存在兼容问题。比如
some_long_name这样的表达,有些处理器会认为 “long” 应该加强(一般是斜体),有些会直接把下划线排出来(因为两边没有空格),还有一些有开关可以切换。 -
处理中文文档不方便,这主要是上一条的特殊情况。由于中文字之间不空格,有些处理器会忽略中间的控制字符。
-
没有扩展性,官方没有宏语法,你为一种处理器写的宏不能保证在其他支持宏的处理器都能用。
总之使用 Markdown 写复杂文档是件特别蛋疼的事。
AsciiDoc
表面上看起来,AsciiDoc 是一套和 Markdown 长得差不多的简单语法,实际上它的设计目标和 Markdown 完全不同。AsciiDoc 使用 DocBook 作为中间格式(而不像 Markdown 和其他语法是为输出 HTML 优化),从一开始就是为了给复杂文档提供一套简单且完备的语法。举几个高级功能的例子:
-
区分 article 和 book 类型。在 book 文档类里有 frontmatter 和 backmatter,附记、摘要、引用、索引应有尽有。
-
所有的元素都可以附加属性,AsciiDoc 自己不用的属性会带到输出文档里。
-
基本控制符有两套,用来区分周围有没有空格的情况。
-
所有的 block 元素都可以加标题,都可以带 id 用来交叉引用。
-
记得我之前说 HTML tag 不够丰富么?AsciiDoc 里的引文有特殊的属性用来标记出处。
-
解决 block 元素之间从属关系的歧义。比如你在一个列表后面写了一个段落,你如何告诉处理器这个段落是列表的一部分,而不在列表之外?AsciiDoc 有特殊语法解决这个问题。随之而来的另一个问题如果你有一个一级列表,里面有个二级列表,后面有个段落,你怎么告诉处理器这个段落属于一级列表而不属于二级列表?AsciiDoc 把这个问题也解决了。
AsciiDoc 是我非常常用的语法,它有足够丰富的设施用来实现一般文档可能碰到的所有需求,同时源码写出来简单易读。我以前的 blog 引擎使用 Flask-FlatPages 渲染文章,默认使用 Markdown 语法。我为了用 AsciiDoc,最近重写了 blog 引擎,加入了自定义后端支持。这篇文章就是用 AsciiDoctor(一个 Ruby 写的 AsciiDoc 处理器)渲染的。
*TeX
在这些所有的工具里,TeX 有特殊地位。首先,TeX 是一个真正的排版工具,它自己决定每一个字、每一个标点符号的位置(而不依靠像浏览器这样的前端),相比之下像...
剩余内容已隐藏
对于现在各种文档系统的吐槽
作为强迫症患者,选择合适的文档工具是个特别纠结的问题。过程中涉及到的两种主要需求是
-
存档需求,要求文档包含足够的结构信息。比如 ConTeXt 里有个宏
\quotation,用来排行间引用,就比直接写引号要包含更多的结构信息。 -
展示需求,要求工具有足够的设施用来实现各种排版效果。
同时满足这两个需求的工具才是好工具。
HTML + CSS
HTML 作为文档格式最大的问题就是结构上的表达能力太弱,简单地说就是 tag 的种类太少。比如你想写一段引文,只有一个 blockquote 可用,没有特殊的 tag 来表示引文出处之类的结构。原则上你可以写个 <div class="source"> 这样的 tag 来自己定义任何结构,而且在设计网页的时候这是个标准操作,但是用来存档的话就很弱鸡了,不如使用 XML,写起来差不多复杂。
HTML 5 加入了几个重要的结构标签,比如 article 和 section,但有个很严重的问题,就是 HTML 5 没有 schema⋯⋯(是的,HTML 4 居然是有 DTD 的⋯⋯)这就是说 HTML 5 不能使用 XML 工具(包括 XSLT)来处理,只能使用专门的解释器。
HTML 的另一个问题是历史包袱太重,标准中充满了诸如 <font>, <i> 这种纯粹用于展示用途的标签。当然你可以选择不用,但是你不能保证别人不用,也不能保证你不需要处理包含这些标签的文档⋯⋯ (眼睛看向 LaTeX。)
EPUB 和其他电子书格式
这些电子书格式一般都是编译结果,也就是单纯用于展示。这些格式问题是它们都是打包的 HTML,一般是由设备内嵌的浏览器渲染,所以几乎一定特别难看⋯⋯ 这里的难看并不是指字体不好,或者行间距太小之类的,而是不使用高级的排版算法(比如断行和各种 micro-typography)。当然表面上来讲这不是电子书的锅,而是 HTML 和浏览器的锅,但是 HTML 是用来写网页的啊,浏览器是用来看网页的啊,好的排版算法只是网页渲染里一个非常微不足道的需求,高效地实现各种交互和动态效果远比排版算法重要的多,也是浏览器厂商关注的重点。然而电子书是本书啊!丫的是书啊!书!一本排版难看的书,不扔难道留着过年⋯⋯?所以电子书使用浏览器渲染,阅读器厂商这种懒惰的行为造就了电子书「难看」的印象。
一般来说我拿到 ePUB 之后会解包转成 TeX 重排一遍⋯⋯
Markdown 和其他简化 markup
我觉得所有这些格式里,Markdown 是最弱鸡但同时也是最无辜的一个。Markdown 的功能特别少,因为发明者 John Gruber 在设计 Markdown 的时候从来就没有想过要用它处理复杂的格式,Gruber 只是为了能方便地写 blog 而已。你去看看他的 blog 就知道 Markdown 为何如此简单了。
然而在懒惰的开源社区开始动歪脑筋以后,一切都改变了⋯⋯ Markdown 有了各种各样的扩展,巨硬甚至有人闲得没事搞了扩展用来写学术文档⋯⋯ 但是 TeX 已经存在了啊,有这个功夫还不如自己搞一套宏包⋯⋯
这就好像你想去赛车,本来你车库里就有辆 Nissian GTR, 调一调悬挂可以直接上,你却非要翻新一辆报废的夏利然后换台发动机⋯⋯
这种事也只有开源社区能干的出来⋯⋯
如果你执意要用 Markdown 处理复杂文档,你最终一定会遇到这些问题:
-
基本控制符不分左右,无法处理复杂格式。Gruber 最初的 Markdown 处理器是一个基于正则表达式的 Perl 程序,大家都知道标准的正则表达式是不能处理任意层数的嵌套的(比如 HTML 里的嵌套
div),所以 Markdown 里的控制符没有必要分左右(因为反正不能嵌套⋯⋯)。另外由于同样的原因,很多 Markdown 处理器都不能可靠地处理这种情况:_aa*a$2*x_0$b*bb_(假设$是行间公式)。 -
Markdown 标准并不是非常详细,很多行为都是未定义的,所以处理器之间存在兼容问题。比如
some_long_name这样的表达,有些处理器会认为 “long” 应该加强(一般是斜体),有些会直接把下划线排出来(因为两边没有空格),还有一些有开关可以切换。 -
处理中文文档不方便,这主要是上一条的特殊情况。由于中文字之间不空格,有些处理器会忽略中间的控制字符。
-
没有扩展性,官方没有宏语法,你为一种处理器写的宏不能保证在其他支持宏的处理器都能用。
总之使用 Markdown 写复杂文档是件特别蛋疼的事。
AsciiDoc
表面上看起来,AsciiDoc 是一套和 Markdown 长得差不多的简单语法,实际上它的设计目标和 Markdown 完全不同。AsciiDoc 使用 DocBook 作为中间格式(而不像 Markdown 和其他语法是为输出 HTML 优化),从一开始就是为了给复杂文档提供一套简单且完备的语法。举几个高级功能的例子:
-
区分 article 和 book 类型。在 book 文档类里有 frontmatter 和 backmatter,附记、摘要、引用、索引应有尽有。
-
所有的元素都可以附加属性,AsciiDoc 自己不用的属性会带到输出文档里。
-
基本控制符有两套,用来区分周围有没有空格的情况。
-
所有的 block 元素都可以加标题,都可以带 id 用来交叉引用。
-
记得我之前说 HTML tag 不够丰富么?AsciiDoc 里的引文有特殊的属性用来标记出处。
-
解决 block 元素之间从属关系的歧义。比如你在一个列表后面写了一个段落,你如何告诉处理器这个段落是列表的一部分,而不在列表之外?AsciiDoc 有特殊语法解决这个问题。随之而来的另一个问题如果你有一个一级列表,里面有个二级列表,后面有个段落,你怎么告诉处理器这个段落属于一级列表而不属于二级列表?AsciiDoc 把这个问题也解决了。
AsciiDoc 是我非常常用的语法,它有足够丰富的设施用来实现一般文档可能碰到的所有需求,同时源码写出来简单易读。我以前的 blog 引擎使用 Flask-FlatPages 渲染文章,默认使用 Markdown 语法。我为了用 AsciiDoc,最近重写了 blog 引擎,加入了自定义后端支持。这篇文章就是用 AsciiDoctor(一个 Ruby 写的 AsciiDoc 处理器)渲染的。
*TeX
在这些所有的工具里,TeX 有特殊地位。首先,TeX 是一个真正的排版工具,它自己决定每一个字、每一个标点符号的位置(而不依靠像浏览器这样的前端),相比之下像...
剩余内容已隐藏