说起编程语言,大家都知道,C、C++、Java、Python、C#,对编程语言了解的深的,可能还能说出1957年就被发明的Fortran,Fortran语言仍是美国学术界使用的编程语言,至今仍在编程语言排行榜霸榜前十。
但说起标记语言,大家可能就知道一个HTML,在互联网上文章写得多的可能还知道Markdown,我这个网站的文章都是用Markdown写的。由于Markdown不支持内嵌外部代码,这几天找到了Spring也在用的Asciidoc准备作为开源库的文档标记语言。正好了解到标记语言的发展历史,就写篇文章聊聊。
数字出版业的GenCode
可能说出来有人不信,标记语言的历史远比大多数编程语言早————第一门标记语言比C语言还早出生几年。当时的计算机还是稀有物品,出版业就是使用计算机的一大客户。出版业使用一个TYPSET的软件用来做排版,TYPSET编辑器和RUNOFF排版软件一起使用,这可能是历史上最早的文档编辑器了。
一个叫威廉的针对RUNOFF程序,为出版行业制定了最早的文本标记语言的标准GenCode,这个人后来也成了ISO标准委员会的第一任主席。
通用标记语言: XML和HTML的前身
ISO标准委员会,学工科的应该都知道,工业界的大多数国际标准都是这个国际组织制定的。咱计算机领域的OSI七层网络协议就是这个组织制定的。
1986年,ISO组织就基于IBM的通用标记语言GML制定了第一个国际化标记语言的标准SGML。SGML就是众所周知的XML和HTML的前身。
这个GML是IBM研究员查尔斯在1969年发明的,SGML基于GML和GenCode,也是查尔斯进入ISO委员会制定的第一个标准。查尔斯也因此被称为“标记语言之父”、“HTML之祖”。
学术界的标记语言: Tex
大家都知道C语言是贝尔实验室的丹尼斯·里奇发明的,他和肯·汤普森在参与Multics操作系统研发失败后回到了贝尔实验室。肯·汤普森为了用一台废旧的PDP-7小型机玩游戏,开发了Unix操作系统和B语言。丹尼斯·里奇为了改进系统,又开发了C语言重写了Unix系统。
当时的贝尔实验室大拿云集,很多人被Unix操作系统吸引,在它上面开发各种工具,Troff和Nroff就是Unix上的排版软件,你可以把这个软件可以类比为Windows上的Word。
Unix早期还没有受到贝尔公司的重视,没有商业化,除了在贝尔实验室流行开来,还流传到了大学里。加州大学就是其中之一,加州大学伯克利分校在Unix基础上进行了二次开发,随着Unix被各大商业公司拿去搞钱弄成了闭源,伯克利重写了Unix操作系统,现在流行的Unix开源版本Open BSD就是这个学校开发的。
当时大学里很多人要写论文,论文里有很多数学公式,为了解决论文的排版问题,1978年~1989年间在斯坦福大学当教授的唐纳德·克努斯开发了Tex,斯坦福研究所的莱斯利·兰波特认为Tex可以通用起来,就自己开发了Latex并在1986年发布问世。Tex排版系统现在几乎成了学术界标准的排版软件。后来有人把Tex移植到Unix操作系统上取代了Troff和Nroff。
Tex也有几个Web的移植版本,Letex.js、MathJax、KaTex.js。我这个网站上的公式渲染就是用了MathJax。
最近有一款新的标记语言非常火,typst号称要取代Latex。截止2024年5月,这个项目已经有2万多star了,势头很猛。
互联网让HTML风靡起来
1980年,在欧洲核子研究中心任职的物理学家伯纳斯-李为了方便研究中心人员共享文档,发明了HTML和用于传输的HTTP协议,并找了个本科生尼古拉·佩洛写了第一个网络浏览器Line Mode Browser,这个浏览器当时还是在终端运行。
后来的1990年伯纳斯-李开发了第一个Web服务器CERNhttpd。现在还能在欧洲核子研究中心看到世界上第一个网站:http://info.cern.ch/ 和 第一个浏览器line-mode的历史。能翻墙的话也可以到维基百科上看看万维网的历史。
后来就是图形界面浏览器,以及众所周知的网景与微软的IE浏览器大战了。而CERNhttpd逐渐演变为NCSA_HTTPd,1995年演变为著名的Apache httpd,这也是1999年Apache基金会成立时的第一个项目。当然现在大家可能用的都是战斗民族在2004年开发的Nginx,不过由于历史原因Apache仍以31.4%的占有率排名第二。而CERNhttpd的原班人马专注于开发Java的Web服务器Jigsaw。
Java语言是1991年Sun公司开发的,它就是乘着这一波互联网东风流行起来的。1996年IE支持Java Applets本来的想法和今天的微信小程序一样,结果Java在浏览器上没掀起什么波浪,在服务端却大放异彩。1997年IE支持了Ajax,互联网迈入Web2.0时代,Dynamic HTML开始流行。客户端脚本语言Javascript蹭了Java的热度,成了现今浏览器的标准;服务端脚本PHP, Python, Java的JSP 和 后来C#的ASP.NET陆陆续续出现。美国的门户网站雅虎、搜索引擎谷歌,中国的三大门户网易、搜狐、新浪,搜索引擎百度就是这个时候崛起的,腾讯、阿里也是这个时候初创还未成气候。
2000年互联网泡沫破裂,大量互联网公司因为融不到资,最后资金链断裂倒闭。这场风暴后活下来的公司,很多现在都成了世界五百强。很多以前的网页现在只能通过 https://archive.org/ 互联网档案馆这个网站看到。
现在的互联网网站比以前绚烂多彩。浏览器从IE一家独大又变回了百花齐放;HTML已经进化到HTML5标准;CSS已经进化到CSS3,CSS4标准也陆续出台;JS也树立了ECMAScript标准,每年都会有新的规范出台;Web上XML也有了用于公式渲染的MathML 和 矢量图形渲染的SVG等一系列子集。连Office办公套件也在2007版之后使用OpenXML规范了,现在看到的docx、xlsx、pptx都是个xml文件的压缩包。
1980年代的C++、1990年代的Java也在新时代的浪潮下不断推出新版本,但是由于历史包袱太重,2010年后Go、Rust、Swift、Zig等新起之秀也相继出现。继移动互联网后,新一代人工智能浪潮又来了,估计大多数程序员和我一样觉得互联网的变化太快了。
轻量标记语言
随着互联网崛起的HTML,有个缺点就是太重了,这是所有XML的通病。随着XML用途越来越广泛,这个弊端也越来越凸显,因此在各个领域都出现了新的轻量级标记语言:
- 数据存储与传输领域:早期的Ajax使用XML传输数据,微软的IE提供的Ajax接口就叫做
XMLHttpRequest
,就是因为XML太重了,2001年才基于Javascript开发了JSON(JavaScript Object Notation),也叫做JSML(JavaScript Markup Language),现在几乎成了互联网传输数据的标准,最新标准已经到了JSON5。同时为了应对存储,JSON还有一个对应的二进制版本BSON(Binary JSON,最早出现在2009年发布的的MongoDB中。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28{
"first_name": "John",
"last_name": "Smith",
"is_alive": true,
"age": 27,
"address": {
"street_address": "21 2nd Street",
"city": "New York",
"state": "NY",
"postal_code": "10021-3100"
},
"phone_numbers": [
{
"type": "home",
"number": "212 555-1234"
},
{
"type": "office",
"number": "646 555-4567"
}
],
"children": [
"Catherine",
"Thomas",
"Trevor"
],
"spouse": null
} - 配置领域:古早的应用大多是用XML配置的,比如上面提到的Apache Httpd。90年代Java搭着互联网的快车兴起,Java的很多系统都是用XML做配置的,比如程序构建和依赖管理工具Maven。原本为数据传输设计的JSON,用作配置文件有个天生的缺陷是不支持注释,因此出现了很多JSON的变体。比如2004年发布的YAML、微软专门为VSCode设计的JSONC(JSON with Comments)、CSON(CoffeeScript Object Notation)、HOCON(Human-Optimized Config Object Notation)等。另外还出现了新的配置格式,比如2013年Github创始人兼CEO 汤姆·维尔纳基于Windows的INI配置文件扩展的TOML,这个TOML由于简洁、对缩进不敏感而备受Rust、golang、Julia等新兴编程语言青睐,比如Rust的构建和依赖管理工具cargo就是用了TOML作为配置文件。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25# 这是一个TOML文件
title = "ImpalaPay Co."
[database]
server = "192.168.1.1"
ports = [ 8000, 8001, 8002 ]
connection_max = 5000
enabled = true
# 数组内使用换行符也是ok的
hosts = [
"alpha",
"omega"
]
[servers]
# 缩进 (tabs 或 spaces) 都可以, 也可以没有缩进。没有严格要求
[servers.alpha]
ip = "10.0.0.1"
dc = "eqdc10"
[servers.beta]
ip = "10.0.0.2"
dc = "eqdc10" - 渲染领域:在渲染方面HTML也太重,特别是对于非计算机专业的人士来说,HTML太难懂了,所以也发展出了很多轻量级标记语言,下面主要介绍的就是用在渲染领域的标记语言。
用于渲染的轻量级标记语言
渲染领域最终还是要生成HTML,轻量级标记语言的出现只要为了方便排版简化HTML的编写。这些语言有以下几个应用场景:
- BBS社交论坛或社交平台等其他内容管理系统
- 电子邮件的渲染
- 软件文档的渲染
最早的轻量级标记语言,主要是用在论坛发布广告栏,管理员不用懂复杂的HTML嵌套语法,在后台直接基于BBCode或Textile写公告。
还有一个应用场景是渲染电子邮件和软件的文档。约1992年开发的Setext就是用来写邮件和评论帖子的轻量标记语言,2002年开发的ATX是用来写博客的,reStructuredText就是Python用于生成文档的标记语言。
现在依然活跃的Textile是2002年开发的,一些博客或CMS网站上还在用。这种轻量级标记语言语法简单,是个人分分钟就能学会。基于这个轻量级标记语言再渲染成HTML,可以节省很多排版工作。
现在非常流行的Markdown,从名字可以看出和Markup标记语言对应,它是John Gruber受Setext、Textile和reStructuredText影响在2004年开发的。Markdown被Github(GitHub Flavored Markdown)、Stack Exchange、SourceForge等网站采用,并加了很多额外的扩展语法因而逐渐分裂,已经有几十个版本的Markdown解析器实现。所以2012年一群人发起了CommonMark计划对Markdown进行了标准化,在commonmark.org网站可以看到相应的语法规范。
Markdown基本语法还是很简单的,CommonMark标准2024年已经发展到0.31.2
版了,可以看到CommonMark是兼容ATX和Setext语法的。实现了CommonMark语法规范的解析器实现可以在它的wiki上看到。
轻量级标记语言已经有很多种了,截止2024年Wikipedia上已经列出了二十多种轻量级标记语言:
Language | HTML export tool | HTML import tool | Tables | Link titles | class attribute | id attribute | Release date |
---|---|---|---|---|---|---|---|
setext | Yes | Yes | No | Yes | No | No | 1992 |
POD | Yes | ? | No | Yes | ? | ? | 1994 |
BBCode | No | No | Yes | No | No | No | 1998 |
txt2tags | Yes | Yes | Yes | Yes | Yes/No | Yes/No | 2001-07-26 |
MediaWiki | Yes | Yes | Yes | Yes | Yes | Yes | 2002 |
PmWiki | Yes | Yes | Yes | Yes | Yes | Yes | 2002-01 |
reStructuredText | Yes | Yes | Yes | Yes | Yes | auto | 2002-04-02 |
AsciiDoc | Yes | Yes | Yes | Yes | Yes | Yes | 2002-11-25 |
Textile | Yes | No | Yes | Yes | Yes | Yes | 2002-12-26 |
Jira Formatting Notation | Yes | No | Yes | Yes | No | No | 2002+ |
Org-mode | Yes | Yes | Yes | Yes | Yes | Yes | 2003 |
Texy | Yes | Yes | Yes | Yes | Yes | Yes | 2004 |
Markdown | Yes | Yes | No | Yes | Yes/No | Yes/No | 2004-03-19 |
TiddlyWiki | Yes | No | Yes | Yes | Yes | No | 2004-09 |
Creole | No | No | Yes | No | No | No | 2007-07-04 |
MultiMarkdown | Yes | No | Yes | Yes | No | No | 2009-07-13 |
GitHub Flavored Markdown | Yes | No | Yes | Yes | No | No | 2011-04-28+ |
Markdown Extra | Yes | Yes | Yes | Yes | Yes | Yes | 2013-04-11 |
Slack | No | No | No | Yes | No | No | 2013+ |
No | No | No | No | No | No | 2016-03-16 | |
Gemtext | Yes | ? | No | Yes | No | No | 2020 |
Djot | Yes | Yes | Yes | Yes | Yes | Yes | 2022-07-30 |
近十来年,电子邮件为了适应移动端,实现响应式布局,也出现了很多专门用于邮件的标记语言(email markup language):
Language | Github Stars | Release Year |
---|---|---|
mjml | 2015 | |
foundation/inky | 2016 | |
heml | 2017 |
文档的相互转换
大家都知道Markdown可以导出HTML和pdf,实际上有一个pandoc项目,可以在市面上大多数文档软件格式之间进行转换。
项目是用haskell写的:https://github.com/jgm/pandoc 。它甚至支持word、ppt的格式转换。
目前来看,最流行的markdown不仅用在写技术文档,还在知乎等社交论坛网站有应用。除此之外还有针对特定用于的场景也在用Markdown,比如用Markdown写Changelog,这个已经有了一个Common-Changelog标准;用markdown写ppt,这个有一个非常牛逼的库reveal.js。Markdown几乎成了事实上的文档标准了。
不过目前对我来说最大的痛点是Markdown无法include外部文件,这个功能2014年在CommonMark中就有过讨论了,但是一直都没有标准化的实现。所以在技术文档方面asciidoc会更强大一些,最有名的就是Spring,它的所有文档都是基于asciidoc。github也支持渲染asciidoc文档。