reStructuredText 九个实用语法

Kaffa 发布于 最后修改

分类: 编程 标签: reStructuredText

reStructuredText 是什么

reStructuredText 是一种轻量级的文本标记语言,是 Python 中 Docutils 项目的一部分。其文件以 .rst 为后缀,也常被简写为 rst 或 reST。它可以被转化成 PDF、HTML 等多种格式,也可以由 Sphinx 转化为 LaTex、man 等格式,现被广泛的用于开源程序文档的撰写。

本文记录了其常用语法,整体来说,语法更统一严谨一些,很适合用来写技术笔记,学起来也简单。在计算机上写作的人,如果不满意 Markdown 的缺点,也可使用它来替代。

rst 语法指南

官方参考细致繁复,对初学者不够友好。若要拿着 reStructuredText 写文章,仅需先知晓写文章的简单实用语法,本文已列出最常用的九个语法。

可参看官方参考:https://docutils.sourceforge.io/rst.html

一、文本样式

rst 标记 显示
*斜体*

**粗体**

``段内标记``

斜体

粗体

段内标记

二、标题

rst 的主场是写书和写文档,可参用 #*=-^" 符号

  • #, parts,部分,比如一本书的“第一部分”
  • *, chapters,章,比如“第一章”
  • =, sections,节,比如“第一节”
  • -, subsections,小节,比如“第一小节”
  • ^, subsubsections,小小节,中文书少用。
  • ", paragraphs,段落。
rst 标记 显示
第 1 章 标题
======================

第 1.1 节 标题
--------------------

第 1.1.1 小节 标题
^^^^^^^^^^^^^^^^^^^^^^

第 1.1.2 小节 标题
^^^^^^^^^^^^^^^^^^^^^^

第 1.2 节 标题
--------------------

第 2 章 标题
======================

第 2.1 节 标题
--------------------

第 2.1.1 小节 标题
^^^^^^^^^^^^^^^^^^^^^^

第 2.1.2 小节 标题
^^^^^^^^^^^^^^^^^^^^^^

第 2.2 节 标题
--------------------

第 1 章 标题

第 1.1 节 标题

第 1.1.1 小节 标题

第 1.1.2 小节 标题

第 1.2 节 标题

第 2 章 标题

第 2.1 节 标题

第 2.1.1 小节 标题

第 2.1.2 小节 标题

第 2.2 节 标题

注意:rst 输出网页中只允许有一个一级标题,且标题的层次不能前后矛盾,否则输出时会报错:Title level inconsistent
如果在 VSCode 中预览标题遇到问题,可参阅我另一篇 用 VSCode 预览 reStructuredText 文件

三、段落

rst 标记 显示
段落是由空行分割的文字。

这是另一个段落。

段落是由空行分割的文字。

这是另一个段落

四、列表和术语表

  1. 无序列表
rst 标记 显示
* 这是一个无序列表
* 它含有两项,第二
  项占两行
  • 这是一个无序列表
  • 它含有两项,第二 项占两行
  1. 有序列表
rst 标记 显示
1. 这是一个有序列表
2. 它也有两项
  1. 这是一个有序列表
  2. 它也有两项
  1. 多级列表
此特性可让 reStructuredText 持续嘲讽 Markdown
rst 标记 显示
* 这是
* 一个多级列表

  * 含一个缩进子列表
  * 这是子列表另一个子项
* 这里是父级的继续
  • 这是
  • 一个多级列表
    • 含一个缩进子列表
    • 这是子列表另一个子项
  • 这里是父级的继续
rst 标记 显示
* 这是更复杂的情况
* 一个含无序列表和有序列表的多级列表
* 混合无序列表和有序列表

    1. 含一个缩进列表子项
    2. 和另一个子项

      * 及另一个第一子项
      * 和第二子项
* 这里是父级的继续
  • 这是更复杂的情况
  • 一个含无序列表和有序列表的多级列表
  • 混合无序列表和有序列表
    1. 含一个缩进列表子项
    2. 和另一个子项
      • 及子项的第一子项
      • 和第二子项
  • 这里是父级的继续
  1. 术语表
rst 标记 显示
术语一
    术语解释,需要缩进。

    甚至可以有多个段落。

术语二
    描述
术语一

术语解释,需要缩进

甚至可以有多个段落

术语二
描述

五、代码

双冒号换行两次后缩进就是代码。

rst 标记 显示
::

    # PEP 20 -- The Zen of Python
    import this
# PEP 20 -- The Zen of Python
import this

六、表格

简易写法:

=====  =====  =======
A      B      A and B
=====  =====  =======
False  False  False
True   False  False
False  True   False
True   True   True
=====  =====  =======

显示为:

A B A and B
False False False
True False False
False True False
True True True

单元格也支持格式:

+--------------------+--------------------+
| rst 代码           | 显示               |
+====================+====================+
|::                  |                    |
|                    |                    |
| *斜体*             |*斜体*              |
| **粗体**           |**粗体**            |
| ``段内标记``       |``段内标记``        |
|                    |                    |
+--------------------+--------------------+

显示为:

rst 代码 显示
*斜体*
**粗体**
``段内标记``
斜体 粗体 段内标记

合并单元格也支持:

+--------------------+--------------------+--------------------+
| 标题1              | 标题2              | 标题3              |
+====================+====================+====================+
| 行1列1             |            行1列2 与 行1列3 合并        |
+--------------------+--------------------+--------------------+
| 行2列1             | 行2列2             | 行2列3             |
+--------------------+ 与                 +--------------------+
| 行3列1             | 行3列2 合并        | 行3列3             |
+--------------------+--------------------+--------------------+
| 行4列1             | 行4列2             | 行4列3             |
|                    |                    |                    |
+--------------------+--------------------+--------------------+

显示为:

标题1 标题2 标题3
行1列1 行1列2 与 行1列3 合并
行2列1 行2列2 与 行3列2 合并 行2列3
行3列1 行3列3
行4列1 行4列2 行4列3

甚至可给单元格加上 class:

.. class:: table is-bordered

    +--------------------+-----------------------------------------+----------------------+
    | 标题1              | 标题2                                   | 标题3                |
    +====================+=========================================+======================+
    |                    |.. class:: highlight-cell-1                                     |
    |                    |                                                                |
    | 行1列1             | **行1列2 与 行1列3 合并**                                      |
    |                    |                                                                |
    +--------------------+-----------------------------------------+----------------------+
    |                    |.. class:: highlight-cell-2              |                      |
    |                    |                                         |                      |
    | 行2列1             | 行2列2                                  | 行2列3               |
    +--------------------+ 与                                      +----------------------+
    | 行3列1             | 行3列2 合并                             | 行3列3               |
    +--------------------+-----------------------------------------+----------------------+
    | 行4列1             | 行4列2                                  | 行4列3               |
    |                    |                                         |                      |
    +--------------------+-----------------------------------------+----------------------+

.. raw:: html

   <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
   <script>
       $(function() {
           $('.highlight-cell-1').parent().addClass('has-background-success-light');
           $('.highlight-cell-2').parent().addClass('has-background-danger-light');
       });
   </script>

显示为:

标题1 标题2 标题3
行1列1

行1列2 与 行1列3 合并

行2列1

行2列2 与 行3列2 合并

行2列3
行3列1 行3列3
行4列1 行4列2 行4列3
reStructuredText 可谓极大做到了代码和显示都能看。

七、注释

rst 标记 显示
注释例子
..
    这个缩进
    是一个注释。

    同级依然是注释

注释例子

上方表格右侧单元格的 HTML 源代码中会含有以下注释
        <!-- 这个缩进
        是一个注释。

        同级依然是注释 -->
    

八、超链接

嵌入式链接

rst 标记 显示
`链接 <https://kaffa.im/>`_
链接

引用式链接

rst 标记 显示
这段含有一个 `链接`_。

这段也含有这个 `链接`_。

.. _`链接`: https://kaffa.im/

这段含有一个 链接

这段也含有这个 链接

链接的定义行,如「 .. _`链接`: https://kaffa.im/ 」可放在文档任意位置,习惯上,统一放在文末便于管理。
在实际的使用中,使用引用式链接中文的链接左右各需要有一个空格。

九、图片

rst 标记 显示
.. image:: https://kaffa.im/static/img/reward.png
    :alt: 打赏用我,感谢阅读。
打赏用我,感谢阅读。

补充技巧

  1. 带删除线的文字

删除的 文字

  1. 不留白的写法

不留白的删除的文字

  1. 上下标

水的分子式: H2O 质能转化方程:E = mc2

附录:我用过文本标记语言

互联网写作的河流中,流过许多标记语言,很难说哪些标记语言有压倒性的优势。

它们主要是创作者们为解决书写和排版格式的差异问题,这里的努力集中在——写作者们希望,用最小的代码实现源码和输出格式兼具可读性。

除开我们熟悉 HTML 和 XML,我使用的几种轻量级的主流都是在 2000 年后成熟或出现的:

  • Org Mode: in 2003 by Carsten Dominik
  • AsciiDoc: in 2002 by Stuart Rackham
  • Textile: in 2002 by Dean Allen
  • reStructuredText: in 2001 by David Goodger
  • Markdown: in 2004 by John Gruber

Org Mode 是文本生活倡导者首选,也是 Emacs [1] 忠实爱好者的选择;AsciiDoc 想的是“人类可读”还可以发布为文档格式;Textile 的缺点和优势是可以混入简单的样式,它使用 PHP 实现,伴有一个设计精巧的 TextPattern CMS,源码有充分的单元测试,但其社区不大;而 reStructuredText 更宏大不断演化而来,吸收了 Zope、Setext、Javadoc 的设计,是这些文档格式中最严谨和包容并蓄的,被广大开源社区偏爱;但从使用广泛来说,这些都在近十年都被 Markdown 超越了。

Markdown 这种标记语言的语法,最早是一名科技作家 John Gruber 设计的,他的设计初衷是使人们能使用易于阅读和编写的纯文本格式进行编写,还可以选择将其转换为结构有效的 HTML,于是他在 BBEdit 编辑器中实现了它。

但说 Markdown 的走红,背后还有参与其中的天才 Aaron Swartz 的原因,一位不策划社会政治活动的企业家黑客不是好的程序员 可以较准确的描述 Aaron,他为今天的 Web 写作行为提供了许多的核心工具,比如 RSS 标准,更好的订阅、分享和推送内容,CC 协议,中文写作者熟悉的《创作者共用》协议,确保了内容的创作共享,web.py 诠释了 Python 的 KISS 哲学。我也读过 Aaron 不少文章,其逻辑清晰,表示准确简洁,易于传播,等今后有空会写一篇他做过的传奇事迹的笔记。

Markdown 的槽点

如果我们将这些标记语言的演化看成是公司的发展,则可以思考它们都做对了什么和哪里做的不够。Markdown 发布了二十多年,目前,对于绝大多数人写作的常规需求来说,Markdown 够用,但如果你没有使用以下功能的话:

  • 列表嵌套
  • 代码渲染
  • 文档元数据
  • 书籍写作

在 Markdown 中,至少上述功能各方实现常不一致。尤其是第一点。

例如,如下无序列表中含有有序列表。

一、“文本形式”说:我所见即所得:

* 年
* 月
* 周
  1. 星期一
  2. 星期二
  3. 星期三
  4. 星期四
  5. 星期五
  6. 星期六
  7. 星期日
* 日

二、“HTML”说:这有啥特别的吗?

    1. 星期一
    2. 星期二
    3. 星期三
    4. 星期四
    5. 星期五
    6. 星期六
    7. 星期日

其代码是在 HTML 中用 ol 包含 ul 实现:

<ol>
    <li>年</li>
    <li>月</li>
    <li>周</li>
    <ul>
        <li>星期一</li>
        <li>星期二</li>
        <li>星期三</li>
        <li>星期四</li>
        <li>星期五</li>
        <li>星期六</li>
        <li>星期日</li>
    </ul>
    <li>日</li>
</ol>

三、“reStructuredText”说:支持列表嵌套是我的特性之一,轻松实现,其代码是:

* 年
* 月
* 周
  1. 星期一
  2. 星期二
  3. 星期三
  4. 星期四
  5. 星期五
  6. 星期六
  7. 星期日
* 日

四、“Org mode” 更是说:我轻松支持 + - * 三级列表呢:

+ 年
+ 月
+ 周
  1. 星期一
  2. 星期二
  3. 星期三
  4. 星期四
  5. 星期五
  6. 星期六
  7. 星期日
+ 日

五、Textile 表示,这是我的基本操作:

* 年
* 月
* 周
## 星期一
## 星期二
## 星期三
## 星期四
## 星期五
## 星期六
## 星期日
* 日

六、Markdown 写下如下代码,但输出却搞砸了。它沉默了一会说:等等,我得看看代码……

* 年
* 月
* 周

  1. 星期一
  2. 星期二
  3. 星期三
  4. 星期四
  5. 星期五
  6. 星期六
  7. 星期日

* 日

所以这里的槽点就是,很多使用很久东西从设计之初就决定了走向。当调整 Markdown 格式的细节,常费时费力,有一种梦回 2000 年旧时代的感觉,我与含有缺陷的排版软件相处的日子,比如用内置模板错乱的 Word 写文档时的感觉,累觉无爱。

相比来说我选择退回到 reStructuredText,它虽然更复杂,但却严谨丰富,作为 Python 世界的主格式,Pelican 引擎的动力之一,我对 reStructuredText 的基本态度是“一直能打”,综合比较,我放弃了 md 转回了 rst。

😁 补充 rst 图片的语法

可以给图片加上属性:

.. image:: https://kaffa.im/static/img/reward.png
    :height: 200
    :width: 200
    :scale: 50
    :alt: 打赏专用,感谢阅读。

显示效果如图

打赏专用,感谢阅读。

脚注

[1]Emacs:等有空,会完成 Emacs 专辑给大家讲解...