InkMark 简介

2021年8月26日 // InkMark 标记语言

上一篇文章中,主要从设计思想、详细规则、可能遇到的特殊问题等方面详细介绍了 InkMark,但该文档是按照由难到易的顺序介绍的,对 InkMark 的初识者来说实在是太复杂且冗长了。为了能更好地让大家认识 InkMark,这里从初学者角度,写一个 InkMark 的学习教程。该教程将按由易到难逐步进阶的方式呈现 InkMark 的全貌。

InkMark 是一个类似于 Markdown 的轻量级标记语言,它通过为简单的标记,为文档添加结构、语义和格式。与 Markdown 不同的是,当遇到复杂的文档表达需求时,InkMark 可以通过内建的扩展规则,使用更多的元素类型,并为元素添加各种属性,从而可无限扩展 InkMark 的功能。

1 入门

InkMark 将文档内容分成一个个元素。通常将那些小型的、出现在段落文本中的元素称为行内元素内联元素;而那些大型的,单独占一行或多行的元素称为块级元素,两者的标记方法有所不同。常见的元素都可以用键盘上出现的英文标点符号标记。

1.1 简单行内元素

先来看看一些简单的行内元素的标记方法及其显示样式,见表 1

表 1 常见的简单行内元素
元素类型 示例 生成的 HTML 显示效果
着重强调 *[示例文本] <strong>示例文本</strong> 示例文本
强调 /[示例文本] <em>示例文本</em> 示例文本
插入 +[示例文本] <ins>示例文本</ins> 示例文本
删除 -[示例文本] <del>示例文本</del> 示例文本
上标 a^[2] a<sup>2</sup> a2
下标 a_[2] a<sub>2</sub> a2
引用 "[示例文本] <cite>呼啸山庄</cite> 呼啸山庄
变量 '[f]_[1] <var>f</var><sub>1</sub> f1
代码 `[func] <code>func</func> func

正如表 1 所示,当标记行内元素时,标记符号后必须紧跟用方括号包括的元素内容。InkMark 为各种常用元素定义了各自的标记符号,你首先需要记住这些标记符号才能撰写文档。为了方便记忆,许多标记符号的选取和元素的语义是关联的。如常使用的 4 个行内元素着重强调、强调、插入和删除的标记符号分别是 */+-,这些符号又可称为乘号、除号、加号和减号。着重强调对应乘号,大多轻量级标记语言都这样用;强调常显示为斜体,因此对应斜线形式的除号;插入文字就是向文本中添加文字,对应的符号就是加号;相反,删除就对应减号。这种理解虽然有点牵强,但确实能帮助记忆。你可以根据自己的理解,为大部分元素的标记符号和语义之间添加辅助记忆关联。

1.2 简单块级元素

再来看看块级元素的标记方法。以下是一个段落,它以英文句点 . 标记:

. 曲曲折折的荷塘上面,弥望的是田田的叶子。叶子出水很高,像亭亭的舞女的裙。

段落元素在文档中是如此常见,以至于我们专门规定可以省略其前方的句点 .,但要求必须和前后的段落用空行分隔。如下所示为两个段落:

曲曲折折的荷塘上面,弥望的是田田的叶子。叶子出水很高,像亭亭的舞女的裙。

层层的叶子中间,零星地点缀着些白花,有袅娜地开着的,有羞涩地打着朵儿的;正如一粒粒的明珠,又如碧天里的星星,又如刚出浴的美人。

InkMark 使用硬换行,对于如下代码,在生成 HTML 时,将自动在每行末尾插入换行符 <br>

远远的街灯明了,
好像闪着无数的明星。
天上的明星现了,
好像点着无数的街灯。

当然,也可以显式地在一行中插入用 ;; 表示的换行符。以下代码与上面的代码是等同的:

远远的街灯明了,;;好像闪着无数的明星。;;天上的明星现了,;;好像点着无数的街灯。

以下是一个块级引用,以双引号 " 标记:

" 学而时习之,不亦说乎?有朋自远方来,不亦乐乎?人不知而不愠,不亦君子乎?

与行内元素不同,块级元素的标记符号后必须加一个或多个水平空白(空格或水平制表符)把标记符号和内容分隔开来。另外当块级内容只占一行时,不需要用方括号包括内容。

当块级元素包含多行内容,或者包含多个块级元素时,应该用方括号对将被标记的内容包括起来。如下的块级引用中就包含了两个段落:

" [
	学而时习之,不亦说乎?有朋自远方来,不亦乐乎?人不知而不愠,不亦君子乎?

	巧言令色,鲜矣仁!
]

代码块则用 ` 标记,如下所示:

` [
	package main

	import "fmt"

	func main() {
		fmt.Printf("Hello, 世界!\n")
	}
]

对于单行代码,也可用如下方法标记:

` fmt.Printf("Hello, 世界!\n")

当标记块级元素时,为了使元素更加醒目,可以重复书写其标记符号,但标记符号之间不能用空白,如下所示:

""""""" 学而时习之,不亦说乎?有朋自远方来,不亦乐乎?人不知而不愠,不亦君子乎?

当要分割文档内容时,可以插入主题转换元素,它将显示为一个水平线。该元素以单独占一行的 2 个及 2 个以上的连续短线 - 表示:

---

不同于 Markdown,各个 - 之间不能有水平空白,其标记前后不能有任何其他非空白字符,这样要求是为了符合 InkMark 整体的标记规则。

1.3 链接

链接是网页文档中常用的元素,其常见标记方法是:

@[示例标题][http://example.com/]
@[示例标题][https://example.com/]
@[链接到相对地址][example.html]
@[链接到相对地址][./example.html]
@[链接到相对地址][../example.html]
@[链接到本页面中的一个锚点][#本页面中的一个锚点]
@[链接到其他网页中的一个锚点][https://example.com/example-page.html#该网页中的一个锚点]
@[链接到邮箱][myname@gmail.com]
@[链接到邮箱][mailto:myname@gmail.com]
@[链接到图像][https://example.com/images/avatar.png]

其中 @ 是标记符号,其后第一个方括号项内包含链接显示的文本内容,第二个方括号内包含用于给出链接指向的 URL 或 URL 片段。

链接内也可以包含块级内容,如下所示:

@ [
	第一个段落。

	第二个段落。
][https://example.com/]

InkMark 还支持为任意元素添加链接,其方法是为这些元素添加 href 属性(有关属性的介绍,请见下一节)。如下示例将为段落内容添加一个链接:

这是一个段落。 [href="https://example.com/"]

其所生成的 HTML 代码为:

<p><a href="https://example.com/">这是一个段落。</a></p>

1.4 标题

InkMark 可以标记 1 至 6 级的标题,主要依靠各级标题表示文档的结构,以及生成文档的大纲。所有这 6 级标题对应的标记符号都是等号 =,不过在书写时,要通过符号的个数来判断标题的级别。其形式如下:

= 一级标题
== 二级标题
=== 三级标题
==== 四级标题
===== 五级标题
====== 六级标题

这将生成如下 HTML 代码:

<h1 id="一级标题">一级标题</h1>
<h2 id="二级标题">二级标题</h2>
<h3 id="三级标题">三级标题</h3>
<h4 id="四级标题">四级标题</h4>
<h5 id="五级标题">五级标题</h5>
<h6 id="六级标题">六级标题</h6>

1.5 列表

列表包括无序列表有序列表定义列表

以下是一个多级无序列表。其中各个列表项前面的空白并不起标记作用,而只是为了美化排版。

* 列表项 1
* 列表项 2
	** 列表项 2-1
	** 列表项 2-2
	** 列表项 2-3
		*** 列表项 2-3-1
		*** 列表项 2-3-2
	** 列表项 2-4
* 列表项 3

如果要使无序列表的每个列表项内部包含一个段落而不是直接包含文本字面,可通过在 * 后面添加一个句点 . 实现。如下所示:

*. 列表项 1
*. 列表项 2
*. 列表项 3

该列表将被转换为如下 HTML 代码:

<ul>
	<li><p>列表项 1</p></li>
	<li><p>列表项 2</p></li>
	<li><p>列表项 3</p></li>
</ul>

只要有一个列表项中包含段落元素,考虑到各个列表项是并列的,则同级的其他不显式指定块级标记的列表项内容也将是段落。以下代码与上面的 InkMark 代码是等同的:

* 列表项 1
* 列表项 2
*. 列表项 3

标记有序列表时,用 # 代替 *,其他与无序列表的标注相同。

当列表项包含多个块级元素时,可通过如下两个方法实现:

* 列表项 1
* [
列表项 2 中的第一个段落。

列表项 2 中的第二个段落。

列表项 2 中的第三个段落。
]
* 列表项 3
* 列表项 1
* 列表项 2 中的第一个段落。
/ 列表项 2 中的第二个段落。
/ 列表项 2 中的第三个段落。
* 列表项 3

以上两段代码生成的 HTML 是相同的:

<ul>
	<li>
		<p>列表项 1</p>
	</li>
	<li>
		<p>列表项 2 中的第一个段落。</p>
		<p>列表项 2 中的第二个段落。</p>
		<p>列表项 2 中的第三个段落。</p>
	</li>
	<li>列表项 3</li>
</ul>

我们将列表项前面的斜线 / 称为接力棒,它表示其中的内容与前一个块级元素的内容是同级同类型内容(一般为段落),就相当于用一对方括号将所有这些内容同时包括起来,并且之间用空行分隔开来。之所以设计接力棒这种标记法,是因为 InkMark 规定不以行首的水平空白作为标记符号,因此不能像 Markdown 那样通过缩进对这种场景进行标记,而用这种接力棒形式的标记要比方括号形式的标记更加整齐美观。

定义列表中包含两类元素,分别是术语 术语的描述,他们分别用 ;: 标记,如下所示:

; HTML
: 超文本标记语言,延伸自 SGML。
; XHTML
: 可扩展超文本标记语言,是 HTML 4.0 的重写,符合XML规则。
; HTML5
: HTML 标准的最新版本。

1.6 图像

要在文档中插入图像,请使用如下方法:

&[https://example.com/path/to/picture.png][替换文字]

其中 & 是图像的标识符,其后第一项方括号内包含图像的源 src 链接,第二项方括号内是当未找到图像时,替换显示的文字内容。以上图像元素将生成如下 HTML:

<img src="https://example.com/path/to/picture.png" alt="替换文字">

要指定图像的尺寸,就需要用到我们还没有介绍的属性了,见如下示例:

&[https://example.com/path/to/picture.png][替换文字][width="400px"]

&[https://example.com/path/to/picture.png][替换文字][width="400px" height="300px"]

&[https://example.com/path/to/picture.png][替换文字][width="50%" height="50%"]

&[https://example.com/path/to/picture.png][替换文字][width="50%" height="250px"]

InkMark 还支持图像框功能,即生成浮动显示的图像框,图像框内只包含一个图像,一个标题以及一段描述文字,这同样要用到属性进行标记,如下所示:

& [src="https://inkmark.org/path/to/picture.png"][caption="图像标题"][description="用一个段落对图像信息进行描述。"]

因为图像框是一个块级元素,因此以上代码的 & 后面必须有一个空格,以表示和前面行内的图像元素的区别。

2 为元素添加属性

InkMark 可以像 HTML 那样,为元素添加属性,从而大大提高其表达能力,但同时也增加了其复杂度。其实我们在前面已经涉及到好多属性了。

属性放置在内容项之后,也用方括号包括,称为属性项。属性项常使用 属性名称=属性值 的形式标注,其属性名称和值的要求与 HTML 语法完全相同。属性值通常用一对单引号 ' 或一对双引号 " 包括起来的字符串。当属性值中不包括空白时,可以省略这些引号。另外,InkMark 规定,当元素有多个属性时,各个属性可以放在一个方括号对中,中间用一个或多个水平空白分隔;或者将不同的属性分别放在不同的方括号对中。如下所示为链接元素的标注方法:

@[维基百科][href="https://wikipedia.org/"]

其中 href 是元素的属性。然而,我们在前面写链接的时候,似乎都没有写 href,这是因为 InkMark 规定对一些常用元素的常用属性,可以省略其属性名称,但这些省略属性名称的属性必须放置在一个单独的方括号内,并且该属性项必须紧跟内容项放置(当没有内容项时,必须尽管标签项放置)。因此,以上链接也可以表示为:

@[维基百科][https://wikipedia.org/]

当使用一些不常用属性时,就不能省略属性名称了,如要链接元素的 target 属性,就应写作:

@[维基百科][https://wikipedia.org/][target="_blank"]

同样,以下两个图像元素是完全等同的,后者只是省略了属性名称而已。由于后者同时省略了 srcalt 属性名称,规定 src 必须放置在 alt 之前,以对他们进行区别:

&[src="https://example.com/path/to/picture.png"][alt="替换文字"]

&[https://example.com/path/to/picture.png][替换文字]

理论上来说,InkMark 中的元素可以使用所有的 HTML 元素属性。但应尽量有节制地使用各种属性,以降低文档的复杂度,提高安全性。甚至建议解析器主动设置可用属性的白名单或黑名单,以避免属性被滥用。例如,全局属性 style 可直接包含应用于元素的 CSS 样式声明,为了使文档内容和样式分离,可以考虑禁止使用此属性。

在所有属性中,classid 是最常见的全局属性。InkMark 专门为这两种属性定义了简化的定义方法。规定 class 属性可在属性项中以 .class-name-1.class-name-2 的方式给出,即在每个类名称前面添加句点 . 表示这是一个 class。又规定 id 属性可在属性项中以 #id-name 的方式给出,即在 ID 名称前面添加井号 # 表示这是一个 id。其方法与 CSS 中类或 ID 选择器的描述方法一样。因此,以上段落元素又可表示为:

一段包含重要内容的段落。 [.important.highlight#paragraph1]

3 自动编号

学术文档中经常包含大量的图像、表格、公式和参考文献,需要对这些内容分别标注自动编号的标题,然后在文档其他位置进行交叉引用和索引。为了实现这些功能,InkMark 专门定义了自动编号内容元素,以及对自动编号内容元素的引用和索引。自动编号内容元素用井号 # 标记,它是一个行内元素(# 也用于标记有序列表项,但它是块级元素,因此两者是有区分的)。以下是一个自动编号内容元素:

#[图的标题文本][图]

这将生成如下 HTML:

<span id="图_图的标题文本" label="图">图 1 图的标题文本</span>

其中的 1 也可能是 2、3、4 等其他数字。

以上的自动编号内容元素实际上省略了 label 属性名。当不省略属性名称时,应该写作:

#[图的标题文本][label="图"]

对于不同的标签 label 属性值,分别有各自独立的编号序列。因此,对于表格的标题,也可以使用如下的编号形式:

#[表的标题][表]

实际在书写学术文档时,对自动编号的要求往往是各种各样的。例如,我们往往使用形如 “图 2.1” 形式的标号,其中的 2 表示章编号,1 表示本章内的编号标签 label 为 “图” 的编号项在本章内的排序,这时可以通过给定另外一个属性 number 来定制编号,如下所示:

#[图的标题文本][图][number="图 {{=}}.{{#}}"]

number 属性的值是一个模板字符串,其中 {{=}}{{#}} 都是模板变量。前者表示编号元素所在章的编号数值,后者表示本章内该标签的编号数值。以上编号元素将生成如下 HTML 代码:

<span id="图_图的标题文本" label="图">图 2.1 图的标题文本</span>

如果不想使用阿拉伯数字作为编号,还可以在 {{=}}{{#}}=# 的后面添加一个序号字符来显式指定编号序列类型,如 {{=A}}{{=一}}。能添加的序号字符应是各种编号类型序列中的第一个编号,其具体值可以是 1、ⅰ、Ⅰ、①、❶、a、A、⑴、㈠、㊀、一、壹、甲等,而 {{=2}}{{=C}}=六 这些值将不被识别为模板变量。

例如,我国的许多法规文档,一般使用“第一百八十三条”这样的中文编号标记各个法条,可以通过如下方式定义这种编号:

#[][法条][number="第{{#一}}条"]

该编号项的内容部分为空,这是因为法条内容往往较多,甚至还包含多个段落,因而没必要将内容包括进来,不然生成的 id 属性值太长了。当只是简单地生成一个编号,而不打算引用该编号内容,或生成编号内容的索引时,可以使用这种方法。

number 属性只需要在该编号标签的自动编号内容元素第一次出现时定义一次,其后的同类自动编号内容元素默认具有相同的 number 属性。

有了自动编号,还可以通过引用编号项元素,引用自动编号。如下所示:

#[label="图"][ref="图的标题文本"]

该元素似乎和以上的自动编号内容元素相同,他们都是用 # 标记。但不同的是前面的自动编号内容元素为容器元素,# 后面紧跟内容项(该项没有属性名称),而这里的引用编号项元素为空元素,其后面没有内容项,且必须具有 label 属性,所有属性名称不可省略。另外,自动编号引用元素还有一个 ref 属性,其值就是被引用的自动编号内容元素的内容。以上元素将生成一个引用链接:

<a href="#图_图的标题文本">图 1 图的标题文本</a>

要生成自动编号内容元素的索引,请使用如下方法:

[=loanc][label="图"]

其中 loanc 为具名形式的元素标签,没有专门为该元素定义标记符号,将在 使用更多元素类型 一节介绍这种用法。

另外,我们还能通过 template 属性,分别自定义自动编号内容元素、引用编号项元素、自动编号内容索引元素生成的元素内容。如只显示元素编号,只显示元素内容,或是同时显示元素编号和元素内容。这里就先不介绍了,有点复杂,不然屏幕前的你可能就会厌倦了。

相对于 Markdown 中集中在文末列出脚注的方法,InkMark 更倾向于将自动编号内容元素和正文混合在一起,就如同 MediaWiki 那样,这可以提高各部分正文内容的独立性。总之,InkMark 自动编号功能非常强大,基于此能实现许多意想不到的效果。当然,其格式也较复杂,你需要慢慢地了解它。

4 复杂元素

以下将介绍一些复杂的元素,分别是图像、表、公式和参考文献,这些都是书写学术文档必备的功能。这些元素的共同特点是可以和以上介绍的自动编号功能相结合,从而实现生成自动编号标题、交叉引用、生成索引功能。

4.1 图像框

前面已经介绍过图像和图像框了,这里只是进一步介绍如何为图像框添加自动编号的标题。通过为图像框元素附加 label 属性,相当于将上述的自动编号元素和该图像框元素相结合,将图像框的标题变为自动编号内容元素,如下所示:

& [src="https://inkmark.org/path/to/picture.png"][caption="图像标题"][label="图"][description="用一个段落对图像信息进行描述。"]

这将生成如下 HTML 代码:

<figure>
	<img src="https://inkmark.org/path/to/picture.png" alt="图像标题">
	<figcaption><span id="图_图像标题" label="图">图 1 图像标题</span></figcaption>
	<p class="description">用一个段落对图像信息进行描述。</p>
</figure>

当然,除了为图像框元素添加 label 属性外,还可以为其添加其他自动编号内容元素的属性,如 number 属性。示例如下:

& [src="https://inkmark.org/path/to/picture.png"][caption="图像标题"][label="图"][number="图 {{=}}.{{#}}"]

4.2 表格

InkMark 几乎包含对 HTML 表格功能的完整支持,但这里只介绍简单的表格表示法。请看示例:

++ [
-! 第 1 行第 1 列 ! 第 1 行第 2 列 ! 第 1 行第 3 列
-! 第 2 行第 1 列 | 第 2 行第 2 列 | 第 2 行第 3 列
-! 第 3 行第 1 列 | 第 3 行第 2 列 | 第 3 行第 3 列
]

其中加号 + 用于标记表格,短线 - 用于标记表格主体内的表格行,竖线 | 用于标记普通单元格,感叹号 ! 用于标记标题单元格。虽然表格单元格是块级元素,但为了美观,我们规定可以在一个表格行中书写多个单元格,这在块级元素表示法中是个特例;当然,你仍然可以每行书写一个单元格;甚至当一个单元格内包含多个块级内容时,仍然可以通过用方括号包括这些内容来适应这种复杂的情况。

我们同样可以为表格指定标题,并通过 label 为标题指定编号,如下所示:

++ [
-! 第 1 行第 1 列 ! 第 1 行第 2 列 ! 第 1 行第 3 列
-! 第 2 行第 1 列 | 第 2 行第 2 列 | 第 2 行第 3 列
-! 第 3 行第 1 列 | 第 3 行第 2 列 | 第 3 行第 3 列
][表格标题][label="table"][number="表 {{=}}.{{#}}"]

以上代码将生成如下 HTML:

<table>
	<caption label="table" id="table_表格标题">表 16.1 表格标题</caption>
	<tbody>
		<tr>
			<th>第 1 行第 1 列</th>
			<th>第 1 行第 2 列</th>
			<th>第 1 行第 3 列</th>
		</tr>
		<tr>
			<th>第 2 行第 1 列</th>
			<td>第 2 行第 2 列</td>
			<td>第 2 行第 3 列</td>
		</tr>
		<tr>
			<th>第 3 行第 1 列</th>
			<td>第 3 行第 2 列</td>
			<td>第 3 行第 3 列</td>
		</tr>
	</tbody>
</table>

InkMark 还可以通过在单元格中插入 <<^^ 符号,分别使该单元格合并到左侧或上方相邻单元格。如下所示:

++ [
-! 第 1 行第 1 列 ! 第 1 行第 2 列 ! 第 1 行第 3 列 ! 第 1 行第 4 列
-! 第 2 行第 1 列 | 第 2 行第 2 列 | <<      | <<
-! ^^            | 第 3 行第 2 列 | 第 3 行第 3 列 | 第 3 行第 4 列
]

该表格的显示效果为:

第 1 行第 1 列 第 1 行第 2 列 第 1 行第 3 列 第 1 行第 4 列
第 2 行第 1 列 第 2 行第 2 列
第 2 行第 2 列 第 2 行第 3 列 第 2 行第 4 列

InkMark 中的表格还有一些复杂的标记法,将不在这里讲述。

4.3 公式

以往在浏览器中,可以通过多种方法显示公式。如对于简单的公式,可以直接用 HTML 文本显示;对于复杂的公式,可以用以下方法显示:位图图像,SVG 图像,用 MathJax 或 KaTeX 渲染的 LaTeX 公式,MathML 公式,等等。InkMark 并不规定应该用什么方式显示公式,而只是用 $ 标记分别显示行内公式和块级公式。

另外,你可能已经注意到,在前面表 1 中介绍简单行内元素时,其中有一个用单引号 ' 标记的变量元素用于标记变量。因此,如果只是简单地用 InkMark 文本标记公式,则推荐以该元素标记公式中的变量,而不是以强调元素标记。可以通过 CSS,使该元素显示为斜体,并用为其指定合适的字体(通常为衬线字体)。

因此,对于用 InkMark 文本标记的行内公式:

$['[y] = '[a] '[x] ^[2] + '[b] '[x] + '[c]]

其所生成的 HTML 代码为:

<span class="formula"><var>y</var> = <var>a</var> <var>x</var><sup>2</sup> + <var>b</var> <var>x</var> + <var>c</var></span>

其显示效果为:y = a x2 + b x + c

块级公式仍然用 $ 标记,但必须单独占一行或多行,且该符号后面必须有一个或多个水平空白。如下所示:

$ '[y] = '[a] '[x] ^[2] + '[b] '[x] + '[c]

将生成 HTML:

<p class="blockformula">
	<span class="formula"><var>y</var> = <var>a</var> <var>x</var><sup>2</sup> + <var>b</var> <var>x</var> + <var>c</var></span>
</p>

其显示效果为:

y = a x2 + b x + c

同样可以为该公式附加 captionlabelnumber 属性来定义公式的标题以及标题编号。如下所示:

$ [
	'[y] = '[a] '[x] ^[2] + '[b] '[x] + '[c]
][label="formula"][caption="抛物线公式1"][number="({{#}})"][template="{{#}}"]

这里的 template 属性规定只显示公式的编号,而不显示其标题。这将生成如下 HTML:

<p class="blockformula">
	<span class="formula"><var>y</var> = <var>a</var> <var>x</var><sup>2</sup> + <var>b</var> <var>x</var> + <var>c</var></span>
	<span class="number" id="formula_抛物线公式1" label="formula">(1)</span>
</p>

通过设置 CSS,以上 HTML 代码可按如下方式显示:

y = a x2 + b x + c (1)

使用相似的方法,可以在公式元素中包含图片格式的公式。如下所示:

$ [
	&[./parabolic-formula.png]
][label="formula"][caption="抛物线公式2"]

其显示效果为:

抛物线公式2 (2)

或者是 LaTeX 公式:

$ [
	$$x=\frac{-b \pm \sqrt{b^2 - 4ac}}{2a}$$
][label="formula"][caption="一元二次方程的根"]

其显示效果为:

$$x=\frac{-b \pm \sqrt{b^2 - 4ac}}{2a}$$ (3)

4.4 参考文献

InkMark 完全依靠自动编号内容元素实现对参考文献的支持。如在文本流中插入:

#[赵六, 公孙七, 慕容八, 等. 书籍标题 [M]. 北京: 清华大学出版社, 2021.][reference][number="[{{#}}]"][template="^[ {{#}} ]"]

以上代码将在文本流中显示一个 [2] 形式的上标数字。其对应的 HTML 代码为:

<span id="reference_赵六,_公孙七,_慕容八,_等._书籍标题_[M]._北京:_清华大学出版社,_2021." label="reference"><sup>[2]</sup></span>

对带编号的图像框、表格、块级公式和参考文献的引用、索引都像操作基本的自动编号内容的引用、索引一样,不再赘述。

5 使用更多元素类型

以上在进行元素标记时,都采用标点符号标记元素的类型。但标点符号毕竟有限,有时需要用到更多的元素,就只能使用元素的标签 tag 名称进行标记了。其实 InkMark 中的所有元素都有一个唯一的标签名称,我们完全可以使用 [=tagName] 的标签项代替前面用于标记的标点符号。例如,以下代码块中上下相邻的两行元素是两两等价的:

*[着重强调]
[=strong][着重强调]

@[示例标题][http://example.com/]
[=a][示例标题][http://example.com/]

一个段落。
[=p] 一个段落。

又如,要在文档中的某处插入文档目录,可以通过在单独一行插入如下文字实现:

[=toc]

toc 是 InkMark 中的自定义元素,它因为不太常用,没有对应的标记符号,只能通过这种直接给出标签名称的形式使用了。这与前面用于编号索引的元素 loanc 使用场景是相似的。

通过这种方法,使 InkMark 在理论上几乎可以使用 HTML 中 body 元素内的所有流式内容元素,这大大扩展了 InkMark 的表达能力,配合对属性的支持,使 InkMark 几乎具备与 HTML 相匹配的表达能力。

不过,事物往往具有两面性,功能强大的同时,也会带来复杂性的攀升,以及美观性的降低。好在当不需要复杂功能时,InkMark 的标记方法相对较简单。另外 InkMark 的标记规则相对固定,比较容易学习。

已经到结尾了,你已经了解 InkMark 的精髓了,谢谢你!要是还有兴趣,就请鼓足勇气,以更大的耐心看看上一篇的 InkMark 设计文档吧,再次感谢!