描写

草稿

这份文件仅仅是草案。这些建议不是教条,有可能会更改。

AsciiDoc提供了多种实现相同功能的方法,并且在语法上经常非常宽容。这份指南有助于为你的文档带来一致性,将最大限度地提高效率,改善可读性并减少维护工作。

文件扩展名

AsciiDoc不关心你使用哪种扩展名。GitHub支持扩展名`.asciidoc`、.adoc`和.asc`。

Note
adoc`似乎是最常用的扩展名,也是我们更倾向于使用的。它不会与其他著名应用程序冲突,有辨识度,同时也不像`.asciidoc`那样过长。它还能被读作“a doc(一份文档)”。因此,我们的建议是使用`.adoc`。
我们强烈建议 不要 使用 .asc 扩展名。它与AsciiDoc的关联并不直观,而且在Linux上会错误地被识别为PGP文件。

每行一句话

不要在固定列宽处折行。相反,将每个句子放在单独的一行,这种技术称为_每行一个句子_。这种技术与你编写和组织源代码的方式类似。其结果可能非常出色。

采用每行一句风格的一些优点包括:

  • 它防止了回流(这意味着段落开头的变化不会导致段落中剩余行的重新定位)。

  • 你可以轻松地交换句子。

  • 你可以轻松地分开或连接段落。

  • 你可以对句子进行注释或添加解释。

  • 你可以发现那些过长的句子或者长度变化很大的句子。

  • 你可以在你的写作中发现冗余(因此平庸)的模式。

我们从https://neo4j.com/docs/2.2.8/community-docs.html#_writing[Neo4j文档]的写作指南中获取了这个想法。然而,似乎这个想法可以追溯到1930年代巴克明斯特·富勒的一项发现,他称之为https://vanemden.wordpress.com/2009/01/01/ventilated-prose/[通风散文]。这项技术也在2009年布兰登·罗德斯关于https://rhodesmill.org/brandon/2012/one-sentence-per-line/[语义换行]的博客文章中被推荐。

需要注意的是,这种技术之所以有效,是因为AsciiDoc不会将段落中的换行视为硬换行。至少,它对读者来说不是那样的。连续的文本行之间的换行在渲染后的文档中(也就是读者看到的样子)是不可见的。

Caution
单个换行在输出中不会显示,但连续两个换行会开始一个新的段落(或其他块)。

章节标题

定义节标题有三种方式。这些变体可以分为两种风格,atxsetext(历史名称)。我们建议使用非对称的Atx风格来定义你的节标题。

Atx风格

在Atx风格中,节标题定义在单行上。节标题以一个或多个等号字符(即 =)开始,后跟一个空格和节标题。前导字符的数量代表层级深度。顶级部分是为文档标题保留的,因此文档中的第一节将有两个前导字符。

第一节

这个例子使用了不对称的Atx风格。它需要最少的字符数量,并且因为前导字符的数量代表了标题的层次,所以它直观易懂。

当使用HTML后端时,这个章节标题将被转换成一个h2标题(很可能包裹在一个用于样式的section块中):

<h2>First Section</h2>

对称的Atx样式将章节标题放置在一对匹配的定界符之间。

第一节

虽然这种语法对某些人来说看上去可能更好看,但它需要两倍数量的定界符而没有增加任何额外的语义。因此,我认为这是键入次数的浪费,不推荐使用它。然而,Atx风格的节标题要比Setext风格的好。

Setext

在Setext风格中,节标题是由两行定义的。第二行是一串字符,用来形成节标题下方的下划线。以下是一个用Setext风格定义的节标题的例子。

第一部分

线的长度由节标题中的字符数决定,因此必须引入另一个维度来确定层级。这个维度是用于下划线的字符。使用的字符有(从文档标题到第五级节排序)`=`, `-`, `~`, `^`, 和 `+`。

我强烈建议不要使用Setext风格进行章节标题的排版。保持下划线与标题长度一致是一项不必要的任务,也是浪费时间。更重要的理由是,字符与标题等级之间的映射*非常*难以记忆,对于AsciiDoc的新用户来说并不明显。总而言之,使用Setext章节标题是一个_糟糕的做法_。*不要使用它们!*

TIP: 建议使用不对称的Atx风格作为章节标题。这是写作和在纯文本(源文件)中阅读最简单直观的方法。

=== 文档标题

由于文档标题在一个文档中只出现一次,我认为在这种情况下使用Setext样式是可以接受的(但强烈不建议),只要你*同时*禁用compat-mode属性(否则它会将处理器置于兼容模式)。

Document Title
 ==============
 Author Name <author@example.org>
 :compat-mode!:

IMPORTANT: 在这种情况下,如果您不希望启用兼容性模式,您必须显式地禁用它(即,`compat-mode!`)。当使用Setext风格的文档标题时,兼容性模式会自动启用。详见https://docs.asciidoctor.org/asciidoctor/latest/migrate/asciidoc-py/[迁移指南]。

请确保在文档标题之后立即写上你的名字。

NOTE: AsciiDoc 仅支持在作者行后面跟一个电子邮件地址。它不支持个人网址。Asciidoctor 支持原始 URL 以及内联链接宏。

在作者行之后附加一个修订行也是一个好习惯。

Document Title
 ==============
 Author Name <author@example.org>
 v1.0, 2012-02-10
 :compat-mode!:

版本号是可选的。修订行可能只包含日期。


Document Title
==============
Author Name <author@example.org>
2012-02-10
:compat-mode!:

== 分隔块

限定块包含特殊文本,如代码列表、引用、侧边栏文本、表格等等。你可能已经猜到了,它们被一串定界符所包围。定界符在它们自己的行上定义。内容放在定界符行之间。这里有一个列表的例子:


----
$ asciidoctor -b html5 recommended-practices.adoc
----

分隔块需要四个或更多重复字符自成一行来标记块的边界。唯一的例外是开放块,只需要两个重复的“-”字符。

你可能会想要将线条延伸得更长,无论是延伸到预定的长度,还是与内容的长度相匹配。

-------------------------------------------------
 $ asciidoctor -b html5 recommended-practices.adoc
 -------------------------------------------------

不要这样做!

维持长的分隔符线是一个**巨大的时间浪费**,更不用说它是任意的和容易出错的。我强烈建议你**使用最少的字符数量**来形成一个分割块,然后继续撰写内容。因为这些长串分隔符在输出(HTML、DocBook等)中 anyway 是不会显示的,读者也永远不会看到。

NOTE: AsciiDoc不强制要求开始限定块的行长度与关闭限定块的行长度相匹配,但我认为_应该_如此。Asciidoctor强制执行此要求,因此请确保它们匹配!

== 文档属性(即,变量)

您可以通过利用文档属性来节省大量的打字工作。文档属性将频繁出现的引用和短语提升到文档(或节)的顶部。你可以通过将信息赋值给一个属性来声明一次,然后在整个文档中引用那个属性。从这个意义上说,您可以将属性视为AsciiDoc的变量。

在文档顶部声明的属性中存储信息可以方便地查找信息,并且避免你在多处更新信息(即保持文档的DRY原则)。当你更新属性的值时,该属性在文档中被引用的所有地方的值都会发生变化。

=== 不要重复你自己的URLs

属性的一个常见用途是存储URLs。URLs经常变化,可能相当长,并且经常包含需要转义的特殊字符。通过在属性中声明URLs可以解决这些问题。

您只需将URL分配给一个简短易记的属性:

[source, asciidoc]
----
:url-issues: https://github.com/asciidoctor/asciidoctor/issues
----

那么当你想要在文档中使用这个URL,比如制作一个链接,就可以引用这个属性。

[source, asciidoc]
----
将错误修复和功能请求提交到{url-issues}[问题追踪器]。
----

鉴于你可能会为许多不同的事物定义属性,使用一种系统来保持它们的有序是非常好的。让我们来研究一种这样的系统。

=== 属性组

如果你定义了很多文档属性,文档头部可能会变得杂乱无章。为了保持整洁,一个好主意是:

* 使用共同前缀为相关的名称属性命名(即,给它们一个命名空间)
* 将相关属性归类到一个横幅下。

例如,我们建议在声明包含URL值的属性时,使用前缀`url-`或`uri-`。这样做有几个原因:

. 它传达了属性持有值的类型(例如,`url-issues` 是问题跟踪器的一个URL)。
. 它避免了与用于其他目的的属性发生冲突(例如,使用`org`作为组织URL可能与用于组织名称的`org`发生冲突)。
. 它会导致编辑器中的代码辅助工具(例如文本自动完成)自然地将相关属性进行分组(例如,通过输入`url-`来调出所有URL属性的列表)。

将相关属性分组可以便于看出应添加新属性的位置,从而帮助保持文档头部的整洁。它还为将来将这些组织分离到不同文件中打开了一扇门。在一个组内,你可能会考虑将属性按字母顺序排列。对于这个规则的一个例外是,如果一个属性引用了另一个属性,这种情况下你必须首先定义被引用的属性。

以下是我们推荐用于在文档头部对相关属性进行分组的一些横幅:

* 元数据 - 定义输出文档头部索引信息的属性
* 设置 - 控制内置转换和格式化行为的属性
* 参考属性 - 在内容中被引用的属性,例如URLs;为了使自动完成工作更加顺畅,请为每个属性添加其类型前缀,例如对于URL使用`url-`前缀。

你可以使用任何你觉得自然的附加组。

将这些建议放在一起时,它的样子是这样的:

[source, asciidoc]
----
= 文档标题
Author Name // Metadata: :description: The description of this page. :keywords: writing, documentation, publishing // Settings: :icons: font :idprefix: :idseparator: - // Refs: :url-project: https://asciidoctor.org :url-docs: {url-project}/docs :url-issues: https://github.com/asciidoctor/asciidoctor :img-ci: https://github.com/asciidoctor/asciidoctor/workflows/CI/badge.svg
----

=== 计数器

计数器是由文档属性支持的。因为它们与所有其他文档属性共享相同的全局命名空间,所以给计数器名称加上前缀以避免与其他属性发生冲突是一个好主意。例如:

{计数器:当前值-步长}

=== 文档设置

大多数文档设置是通过属性来控制的。文档设置是通过紧接文档标题后面的属性条目来配置的(中间没有任何空行)。有几个有趣的选项。

.章节编号

你可以通过设置`sectnums`属性(默认关闭)来启用章节编号。

:sectnums:

.文件描述

你可以使用`description`属性来设置文档的描述。描述会包含在文档的头部。

描述:本文档编录了一系列用于AsciiDoc写作的推荐实践。

您可以通过在行尾加上一个空格和一个`\`符号来把任何[属性值分成多行](https://docs.asciidoctor.org/asciidoc/latest/attributes/wrap-values/)。

:description: 该文档编录了一组推荐的实践,用于用AsciiDoc编写文档。

您可以通过将其作为属性引用,在文档的任何地方使用这段文本。

描述

.章节标题ID和ID前缀

默认情况下,每个章节标题都会生成一个ID。这个ID是由章节标题生成的,默认前缀是下划线(即 `_`)。你可以使用`idprefix`属性来改变这个前缀。

:idprefix: id_

如果您想要移除前缀,请将它赋值为空值:

:idprefix:

要禁用自动生成节ID,请取消设置`sectids`属性:

:sectids!:

.目录

将`toc`属性设置为激活,在文档顶部生成一个自动生成的内容目录:

:toc:

== 图片和其他媒体

待办事项

.路径
在每个图像引用中不要包含图片目录。

.块级元素与行内元素

...

== 条件包含

待办事项

如何使用,使用的理由

== 列表

.无序列表标记

AsciiDoc支持使用`*`(一个或多个)和`-`(只有一个)作为顶级列表项的标记。

....
* 第一
* 第二
* 第三
....

或者

....
- 第一
- 第二
- 第三
....

然而,在定义列表项时,破折号标记 _不能_ 重复使用。这可能导致混淆,因为每次AsciiDoc遇到一个 _不同_ 的标记时,它就会增加嵌套级别。例如,在下面的情况中,带有星号标记的项是*嵌套*在第一个项内部的。

....
- 第一
* 嵌套项
- 第二
- 第三
....

这种嵌套规则即使在星号的数量似乎指示层级时也是成立的:

....
*** first
* nested item
*** second
*** third
....

诶,没错,第二个列表项嵌套在第一个列表项里。

如果你坚持遵循约定,星号的数量可以表示嵌套级别:

....
* 第一
** 嵌套项
* 第二
* 第三
....

这可真是直观。

我强烈建议如果你要使用嵌套列表的话,请使用星号标记。

如果你只有顶层的列表项,那么使用这两种标记中的任何一种都是合理的。我甚至可能会建议对于那些不打算拥有嵌套项的列表使用破折号标记,而对于那些确实含有嵌套项的列表则使用星号标记。这样就很容易将它们识别为不同的类型。

.描述列表

他们存在!

.分隔列表

邻近的列表有时候会融合在一起。要强制开始一个新列表,请通过一个空行注释来偏移这两个列表:

....
* 苹果
* 橙子
* 香蕉

//-

胡萝卜
番茄
芹菜
....

== 字面文本

待办事项

反引号对比加号以及通过材料

推荐用于行内代码引用的字符

== 桌子

.堆叠单元

利用它们,使其更易于阅读