章 5 · 篇 II · 工艺
文档格式
Postext解析的Markdown子集,以及编写源文档的规则
Postext读取的是一种有意保持精简的Markdown方言。
解析器是一个手写的分词器,而不是完整的CommonMark实现,因此源格式范围窄、行为可预测。这样做有两个目的:让引擎保持小而快;让文档可以毫不费力地在Postext与其他CommonMark阅读器(Obsidian、Pandoc、VS Code……)之间通用。本页没有列出的写法,要么按纯文本处理,要么从行内文本流中移除。
如果你用程序构建文档,parseMarkdown函数(见配置 › 解析)会给出排版引擎实际使用的块结构。
#前置元数据
文档可以以一个可选的YAML前置元数据(frontmatter)块开头,前后用---标记围住:
---
title: Chapter One
author: Jane Doe
publishDate: 2026-04-15
---
# Chapter One
The story begins here…调用extractFrontmatter(source)可以把前置元数据和正文分开。它返回解析后的元数据对象、其余的Markdown,以及正文起始处的字符偏移量;如果你需要把错误或光标位置映射回原始源文本,这个偏移量就很有用。
前置元数据由gray-matter解析,因此任何结构的YAML都能接受。Postext本身只看title、subtitle、author和publishDate;其他键保留在PostextContent.metadata上,供你自行使用。
YAML会给值赋予类型:1984是数字,2026-04-15是日期,[Ana Gil, Luis Paz]是列表。无论类型如何,Postext都把这四个字段作为文本输出:
- 数字按普通十进制形式输出,布尔值输出为
true或false(title: 1984输出1984)。YAML把数字当作一个值来读,而不是逐位读取:1.50输出1.5,017(八进制)输出15,1:30(六十进制)输出90; - 日期输出为它所在的日历日,用文档的语言书写,即
locale设置,未设置时取断词语言:publishDate: 2026-04-15在英文中输出April 15, 2026,在西班牙文中输出15 de abril de 2026,在德文中输出15. April 2026。带时刻的日期按其UTC时间取日期并舍去时刻:2026-09-24T23:30:00-05:00是25日UTC 04:30,输出September 25, 2026; - 列表输出为用逗号连接的各项(
author: [Ana Gil, Luis Paz]输出Ana Gil, Luis Paz)。
给值加上引号,就会照写的样子原样输出,适用于必须保留每一位数字的数字、必须保留原有日期的日期:publishDate: "15/04/2026"、title: "1984"。这段文本会进入doc.metadata、占位符({title}、{publishDate}……)以及PDF的标题和作者。这四个字段中没有文本形式的值(嵌套映射、空的title:)不会出现在doc.metadata中。extractFrontmatter仍按YAML赋予的类型返回这些值;metadataText(value, locale)给出Postext对某个值输出的文本。
#块结构
Postext识别七种正文块类型,另外还有本页后文介绍的指令和资源嵌入。块总是以空行或另一个块的开始作为结束。
| 结构 | 语法 | 说明 |
|---|---|---|
| 标题 | # Title … ###### H6 | 一到六个#字符,后跟一个空格和标题文本。1–6级直接对应headings.levels配置。 |
| 段落 | 一行或多行纯文本 | 连续的非空、非特殊行用一个空格连接,作为一个段落输出。在两个中文或日文字符(表意文字、假名、全角标点,以及紧挨它们的弯引号、破折号或省略号)之间,换行符则直接去掉,与CSS的做法相同,因此中文段落在源文本中可以在任意位置换行。在两个这样的符号之间(“你好”⏎“再见”、他说……⏎“好”),由符号外侧的字符决定:其中一个是中文或日文时,换行符去掉;“hello”⏎“bye”则保留空格。韩文保留空格。段落内的手动换行不会保留,要开始新段落请用空行。 |
| 引用块 | > quoted text | 引文的每一行都必须以>开头(后面可有一个空格)。连续的引文行合并为一个引用块,连接方式与段落行相同。它按bodyText.blockquote的设置排版:除非你修改,否则为灰色斜体,并带有正文的首行缩进(见配置 › 引用块)。 |
| 无序列表 | - item、* item、+ item | 三种项目符号都可以使用。嵌套时每级恰好两个空格,最大深度为5。 |
| 有序列表 | 1. item、2) item | 数字后跟.或)。起始编号会保留(列表可以从5开始,也可以从0开始)。输出中显示的分隔符来自orderedLists.separator,而不是源文本。 |
| 任务列表(GFM) | - [ ] todo、- [x] done | 带方括号复选框的无序列表项。小写x和大写X均可。用taskCheckboxChar / taskCheckedChar字形渲染。 |
| 行间公式 | $$ … $$ | 单独成块排版的LaTeX公式。在栏内居中渲染,像标题一样对齐基线网格,在PDF输出中保持矢量。单行形式和围栏多行形式见数学公式。 |
两个列表项之间有一个空行是允许的,列表仍保持连续。两个或更多空行则结束列表。
同一深度上可以混用不同类型的列表(可以在中途从无序切换为有序),但引擎在编号时把它们当作各自独立的列表。实际使用中,除非有理由混用,每个深度只用一种类型。
#标题属性
标题行末尾可以带一个花括号属性块,语法与指令使用的key="value"相同:
# The Long Road {author="I. Zango Martín" year=1998}花括号及其内容会从标题文本中移除(上例的标题渲染为The Long Road),并作为attrs存储在标题上。它们以{attr.<key>}占位符的形式提供给设计槽位:标题自身的高级设计槽位,以及页眉和页脚,后者从当前章的H1取值。只有位于行尾、括号配对且内部不含花括号的块才会被识别;它前面须是一个空格,或者紧跟一个中文或日文字符,因为中文标题本来就不加空格(# 回目{style="x"})。只有当下面的属性语法能读完整个块时,才会把它当作属性块:{x, y}、{紅樓|hóng lóu}和单独的{}都留在标题中,紧贴标题且只有标志的块(# 第一回{draft})也一样。属性之间用空格分隔,因此带逗号的块({a="1", b="2"})以及Pandoc的{#id}和{.class}也留在标题中;在postext 1.8及以前,它们会被读取并从标题中移除。用其他文字书写的键会被读取后丢弃并给出警告(见下文),所以# 回目{style="x" 作者=曹雪芹}仍会采用style。见配置 → 页眉与页脚。
设计文本输出的值可以占多行:两个字符\n在该处换行,与元素的overflow无关(to="Firma X\nStrasse 1\n10115 Berlin"输出三行地址)。元素设置了inlineMarks时,值中的行内标记也会生效:authors="Ana Ruiz^1^, Luis Gil^2^"会把单位编号排成上标。这种转义只适用于属性值(以及设计本身的模板):标题文本中的\n字符,比如在代码片段里,会原样输出。
有两个属性有专门的含义。style="<id>"给标题应用一个命名的标题样式,例如前言或作者名单,它有自己的章首页设计、书眉、页面几何和正文排版;样式设为numbered: false时不带章号。toc="false"(或"true")决定该标题是否被:::toc列出:
# Preface {style="front-matter"}
# Contents {style="front-matter" toc="false"}另有两个属性改变标题输出的内容和计数方式。hidden="true"(或"false")覆盖标题所在级别或样式的hidden:隐藏的标题不输出任何内容,也不占空间(在正文流中和:::callout框内都是如此),但仍会开启它所在的页、参与计数,并列入目录、{chapterTitle}书眉和PDF书签。startAt=N(正整数)把该标题所在级别的计数器设为N,而不是递增;其后的标题从这里继续计数,后面的章也一样,下级标题照常在它之下重新计数。如果某个标题样式用字母为附录编号(numberingTemplate: 'Appendix {1:A}'),第一个附录重新开始计数,读作Appendix A,而不是接着各章往下数:
# To my mother {hidden="true" toc="false"}
# Survey instrument {style="appendix" startAt=1}
# Raw data {style="appendix"}#指令
指令是单行控制标记,单独写在一行,形式为:::name或:::name{attrs}。它们不产生可见输出,而是驱动定位和编号流程。
| 语法 | 作用 |
|---|---|
:::pagebreak | 强制下一个块在新页开始。 |
:::pagebreak{parity="odd"} | 同上,并确保新页是奇数页(右页)。必要时插入一个空白补位页。 |
:::pagebreak{parity="even"} | 同上,但目标是偶数页(左页)。 |
:::pagebreak{parity="always-odd"} | 保证在落到奇数页之前至少有一个必需的空白分隔页。这个分隔空白页属于前面的内容;此外的奇偶补位页属于后面的内容。适合每章都必须从新跨页开始的情况。 |
:::pagebreak{parity="always-even"} | 同上,但目标是偶数页。 |
:::numbering{format="decimal" startAt=1} | 在下一个页面边界切换页码序列。两个属性都是可选的:省略format则保留原格式,省略startAt则继续计数。 |
:::columnbreak | 在此结束当前栏:下一个块从同一页的下一栏开始(指令落在最后一栏时则从新页开始)。在空栏中不起作用,因此不会产生空白栏或空白页。被结束的栏保留底部空白,各栏齐底不会拉伸它。 |
:::space | 在此留出一行正文的空白,这是在两个块之间稍加留白的明确方式。:::space{lines=2}留出两行(也可以用0.5这样的小数)。它叠加在块之间的外边距上,在栏顶或页顶会被丢弃。见下文。 |
:::toc | 在此输出目录:所列级别的每个标题一条(标题、编号、页码,可选附上本章作者),每个篇分隔页一行,按toc配置排版。条目跟随文档:重命名、移动章或重新编号,目录都会随之更新。 |
:::index | 在此输出索引:书中用:index标记的每个词条,排序并按字母分组,附上所在页码,按index配置排版。:::index{index="names"}输出一个命名索引。见索引。 |
属性值可以用双引号("…")、单引号('…')或不加引号(startAt=17)。没有=的单独键被视为存在但为空的标志。
目前只有pagebreak、numbering、columnbreak、space、toc和index被识别为单行指令;其他任何不是容器(见下文)的:::name行都按段落解析,并在沙盒中显示未知指令警告。引擎也会记录它,作为文档contentWarnings中的一条unknownDirective(见配置 › 文档中的警告)。
#属性值
同一套key="value"语法用于标题属性、指令和容器的起始行(:::name{…})、行内引用(:ref{…})、行内标签(:chip[…]{…})、色块(:swatch{…})和索引标记(:index[…]{…})。规则如下:
- 键以ASCII字母或
_开头,后面可以是ASCII字母、数字、_或-。=两侧可以有空格;中文输入法打出的全角=与=等效;重复的键取最后一个值;没有=的键是值为空的标志。用其他文字书写的键(作者=曹雪芹)不会被读取,并触发attributeKeyInvalid警告;块中的其他键仍然生效。值可以用任何文字。 - **带引号的值。**双引号值可以包含除
"以外的任何字符,包括单引号;单引号值可以包含除'以外的任何字符。因此含双引号的值要放在单引号里:lead='He said "hi"'。没有转义,反斜杠是普通字符,所以同时需要两种ASCII引号的值要改用印刷引号(“…”、’)。值也可以用中文输入法打出的弯引号“或直角引号「开头,一直延续到对应的”或」,中间可以有空格:title=“甲戌本 眉批”、title=「脂批」。 - 不加引号的值(
startAt=17、year=1998)延续到下一个空格:title=Hello world等于title="Hello"加上一个标志world。 - 不能有花括号。
{和}不能出现在值中。第一个}就结束属性块:值中含花括号的起始行不再是指令,而是段落;在行内,值的剩余部分会溢出到正文中。在标题中,值里的花括号会使整个块留在标题里:# Title {note="a {b"}原样排出。(在postext 1.8及以前,空格后的{会重新开始一个块,b被当作标志读取。) - **美元符号是普通文本。**属性在行内公式之前读取,所以
lead="from $5 to $6"只是文本。 - **只占一行。**属性块从不跨行。
# The Long Road {lead='A "road novel", they said' price="$18"}
:::callout{type="note" title='The "fast" path'}
…
:::::resource{id="…"}更严格:id必须用双引号,且不能有其他属性(见资源)。
#容器
容器用围栏包住一段块:起始行为:::name或:::name{attrs},接着是任意普通内容(段落、标题、列表、引用块、公式,甚至其他指令),结束行只有一个:::。容器可以嵌套;每个结束的:::关闭最内层尚未关闭的容器。
:::callout{type="note"}
Keep the lantern lit **every** night.
- Check the wick.
- Trim it at dusk.
:::
可识别的容器名有三个。各自渲染成什么,由配置中对应的部分设置:
| 语法 | 作用 |
|---|---|
:::callout{…} … ::: | 框内内容:用带边框或底色的框与正文区分开的注释、提示或警告。 |
:::paragraphs{…} … ::: | 一段用命名段落样式(导语、题词、一组小字注释)而不是正文样式排版的段落。 |
:::part{…} … ::: | 篇或部分的开篇页:其中的标题和正文构成一个大分部的开篇页。 |
每种容器接受的属性及其样式设置见配置。属性值的语法与指令相同。:::callout起始行接受type(已配置的标注框样式的id;未知或缺少的类型回退到第一个样式)、title(覆盖样式的默认标题),以及span / placement(column、page或side;here、top、bottom或fixed),用来为这个框覆盖样式的范围和位置:
:::callout{type="objectives" title="What you will learn" span="page" placement="top"}
- Name the parts of the lantern.
- Trim the wick without touching the glass.
:::
标注框按框来排版:可选的标题,接着是用样式自身的正文和列表排版设置排出的内容。默认情况下它保持完整,放不下时整体移到下一栏或下一页(比整栏还高的框同样会拆分,而不是溢出);样式设为keepTogether: false时,框可以在块之间或行之间拆分,切口两侧至少各留splitMinLines行文本,或者一个图、表、行间公式或嵌套框(在段落或列表项内部切开时,切口两侧还至少各留该段落或列表项的layout.boxChildSplitMinLines行:默认两行,splitMinLines更小时取splitMinLines;1.5之前保存、章中含框的书按1读取,即1.4的切法)。第一部分之后的各部分开头不带图标,但文字仍保留图标所占的栏位;也不带标题,除非样式要求重复标题(repeatTitle:“Key points (cont.)”);样式还可以在每个有后续的部分下方加一个“续”标记(continuesMarkerEnabled),见拆分框上的标记。通栏框(span="page")把页面切成若干栏带;span="side"框离开正文流,进入一栏半版式中只放浮动体的侧栏(layout.sideColumnRole: 'floats'),叠放在它所打断的文字旁边,在没有这种侧栏的地方按栏内框排版;placement="fixed"框离开正文流,固定在页面坐标上(比如章末页左下角的自我评估徽标),它所覆盖的栏让出这块区域;浮动框(placement="top" / "bottom")在出现处离开正文流,占据该位置之后第一个空闲的栏带,即本页底部,或下一页的顶部或底部,而它后面的文字填满它离开的那一页。设为floatBarrier: true的样式(通常是章末的“要点”框)使该框成为浮动体屏障:在它之前引用的每个图或表都放在它之前,放在页面的空闲位置,或放在框之前新开的页上,因此不会有浮动体越过本章结尾。未知的:::name起始行不是容器,该行按文本处理,与未知指令完全相同。
:::part起始行接受number(按你希望输出的样子写,如"I"、"IV"、"3";它也会被解析,以便设计重新格式化)和title,两者都是可选的。第三个属性palette="band=#hex"(多个id=#hex对,用逗号分隔)为该篇及其后的各章(直到下一篇)重新着色:所有链接到这些调色板id的设计颜色(书眉、开篇页色带、篇的设计),以及与它们共享基础值的文本流颜色(标题、粗体、引用、项目符号、题注、表格、框、行内标签);见配置 › 篇。这个容器总是独占一页:前面有一个按配置奇偶性的分页,使用parts.margins页边距的单栏正文,整页铺满开篇页设计,结束围栏之后再分一次页。正文通常是该篇所含各章的列表,也可以什么都没有,按parts.bodyStyle排版:
:::part{number="I" title="Foundations"}
1. The lantern and its parts
2. Trimming the wick
:::
# The lantern and its parts
在默认的标题设置下,这会得到经典的顺序:篇页在右页,接着是一个空白左页,章从下一个右页开始。该页报告为role: 'part',所以页眉和页脚可以跳过它;{partTitle} / {partNumber}在其后的每一页都解析为当前的篇。见配置参考中的篇。
围栏前面不需要空行:起始或结束围栏紧贴在段落、列表或引用块下方时,会结束那个块。文档结尾仍未关闭的容器会在那里自动关闭,沙盒会给出指向起始行的容器未关闭警告。没有打开的容器时出现的多余:::会作为可见的段落留在文本中,而不会被悄悄丢弃。
#:::columns
在:::callout内部,:::columns{count=2} … :::组把围栏之间的块排成count个等宽的栏(栏间距为样式的columnGap):在各栏最齐平的地方切开这段内容,可以在块之间,也可以在段落或列表项的行之间,后者的剩余部分在下一栏顶部接着排,不带项目符号;框的高度随最高的一栏增长。组之后的块重新占满整个宽度。在标注框之外,这对围栏会被忽略,块照常排版。breaks属性直接固定各栏的起点,而不做平衡::::columns{count=2 breaks="4"}让第二栏从组内第四个块开始(栏更多时用逗号分隔的列表),不会在段落内部切开,适合文字栏旁边配一栏图的情况。
:::callout{type="summary"}
:::columns{count=2}
- Every element is one kind of atom.
- Electrons live in orbitals.
- A bond shares or transfers electrons.
:::
:::breaks如何计数。breaks按顺序给组内的块编号:段落、列表项(每项一个块)、行间公式、图和表;嵌套的:::callout无论包含多少内容都算一个块。指令不算块:两节诗之间的:::space不会改变计数。小于2、超出组内最后一个块或不在前一个断点之后的数字会被忽略。在组内,:::space像在框内其他地方一样分隔两个块,在组的顶部和各栏的顶部(breaks位置或齐平切口)消失;如果想让组从更低的位置开始,把空白放在:::columns起始行之前。因此,间距相同的两栏会逐节对齐:
:::callout{type="verse"}
:::columns{count=2 breaks="4"}
The lamp is lit at dusk,
and trimmed before the dawn.
:::space
The keeper sleeps by day.
La lámpara se enciende al anochecer,
y se despabila antes del alba.
:::space
El farero duerme de día.
:::
:::这里第四个块“La lámpara…”开启第二栏;两行:::space不计数,在两栏中留出相同的间隙。
:::callout起始行还接受label="…":带label标签的样式在框的顶角输出的文字(:::callout{type="box" label="BOX 1-1" title="The octet rule"})。
嵌在另一个:::callout里的:::callout是一个独立的框,比如装着若干答题框的练习卡片。它使用自己的样式(底色、边框、圆角、内边距、标题、图标),宽度为外框的整个内宽,与外框的其他块依次堆叠;它的span和placement会被忽略,因为嵌套框总是在父框内排版。每个围栏关闭最内层仍未关闭的框:
:::callout{type="card"}
The statement of the exercise.
:::callout{type="answer"}
A white answer box with its own border and padding.
:::
:::callout{type="answer"}
A second answer box.
:::
:::外框跨栏或跨页拆分时(keepTogether: false,或比一栏还高),嵌套框整体移到下一个片段,除非它自己的样式也允许拆分;每个片段重新绘制其中的边框;续排的嵌套框不带图标,也不带标题,除非它的样式要求重复标题(repeatTitle)。
#:::pagebreak
这个指令本身并不强制奇偶,只影响下一个块的版面。可以用它结束前言、让献词独占一页,或者标记一节的结束。如果同一处既要分页又要重置编号,就在:::pagebreak后面接:::numbering:编号切换作用于:::pagebreak刚刚新开的那一页。
在仍为空的页上分页不起作用,因此它不会添加空白页。它也不会取代紧随其后的标题的breakBefore(1级标题默认有):标题仍会应用自己的奇偶设置,这可能在指令新开的那一页之后再加一个空白页。要让标题恰好从那里开始,关掉它的分页(见配置 → 标题样式)。在铺满整页的封面标题之后,分页是可选的:无论单栏还是多栏版式,封面都已占用本页余下的部分,紧接着写一个:::pagebreak也无妨。只有当封面的设计没有延伸到页脚,而正文仍应从下一页开始时,才需要分页(见配置 → 预留高度)。
The old chapter ends here.
:::pagebreak{parity="odd"}
# A new chapter奇偶属性
parity属性接受的五个值与headings.levels[*].breakBefore.parity相同:
'any':默认值,没有奇偶约束,分页只是开一个新页。'odd'/'even':新页从跨页中指定的一侧开始;只有当自然的下一页落在错误的一侧时,才插入一个空白页。'always-odd'/'always-even':保证在前面的内容和新页之间至少有一个必需的空白分隔页,然后再满足奇偶要求。这个分隔空白页属于前一章;此外的奇偶补位页属于后面的内容。
空白页的归属
:::pagebreak(以及breakBefore)可能引入的两类空白页在VDTPage模型中加以区分:
blankForParity: true:为满足奇偶约束而插入。在{chapterTitle}页眉中,这一页显示即将开始的那一章的标题,因为这个空白页只是为了把那一章推到正确的奇偶页上。blankForForce: true:'always-*'模式中必需的前导分隔页。它属于前一章,是有意在章末留出的停顿,而不是为下一章补的奇偶页。
同样这两条规则也让空白页获得带样式部分的书眉和调色板,见配置 › 标题样式。
文档开头的例外
当:::pagebreak是文档中的第一个结构(或者带breakBefore的标题会引入一个分页)时,只要第一页仍为空,就不执行奇偶约束。下一个块照写的那样落在第1页,与要求的奇偶无关,不会在开头多出一个空白页。
#:::numbering
:::numbering用来在文档中途重新开始页码计数。典型的图书示例:
---
title: "A Book With Front Matter"
---
# Preface
…
:::pagebreak{parity="odd"}
:::numbering{format="decimal" startAt=1}
# Chapter 1前言各页的页码为i、ii、iii……;第一章从页码为1的右页开始。
只改格式(不带startAt)时计数器继续累加,这在从lower-alpha切换到upper-alpha而不重置时很有用。
format接受编号格式的任何写法:roman-lower和i与lower-roman等效,arabic与decimal等效(见配置 › 编号格式的写法)。不属于其中任何一种的值会保留原有格式,沙盒会标出它。
#:::space
:::space在两个块之间留出垂直空白:把结尾的一行与上方文字隔开,把题词或署名稍稍往下推,或者在两段文字之间形成空行分隔。Markdown中多余的空行做不到这一点:与任何Markdown一样,连续的空行只是一个段落分隔符,这样编辑器或格式化工具增删空白时,文档的版面不会改变。
The last paragraph of the scene.
:::space
A new scene begins one line lower.
:::space{lines=2}
Two lines lower still.lines:空白的大小,以正文行(基线网格)为单位。默认为1。整数能让每行文字都保持在网格上,页面上各栏仍能对齐;小数(lines=0.5)会精确执行,代价是在下一个对齐网格的块之前失去这种对齐。不是大于0且不超过20的数字时,回退为一行,沙盒会标出它(空白大小无效)。- **它会叠加。**空白加在两个块之间已有的外边距上(标题的上外边距、列表的下外边距),而不是与之合并。连续两行
:::space会加两行。 - 遇到断开处就丢弃,与LaTeX的
\vspace一样:在栏顶或页顶它会消失,所以页面不会以一块空洞开头;在栏底放不下时,它只是结束这一栏,不把剩余部分带到下一栏。 - 其后的段落顶格排。
bodyText.indentAfterHeading关闭时,紧跟在:::space后面的段落不带首行缩进,与标题之后一样,这是空行之后继续正文的通常做法。 - 在标注框内(或
:::columns组内),它以同样的方式分隔框的子块,以框自身的正文行为单位计量。在框的第一个块之前它会被丢弃,与在栏顶一样(内边距已经把内容与边框隔开),但有两种情况例外,此时它会留出相应的空间:紧接在框的标题下方,以及框里没有其他内容时(答题框、以行计量的书写空间)。它在:::columns组的顶部、组内各栏的顶部,以及拆分框续排到下一栏或下一页的部分的顶部,总是会消失。在:::paragraphs容器内,它的作用与正文段落之间相同。 - 与下文同页时会把它计算在内:标题后面跟着
:::space时,如果空白和其后文字的前几行放不下,标题会移到后面。
练习册的答题框就是一个只有空白的框:问题写在标题里,下面留四行空间。
:::callout{type="answer" title="1. Name the three parts of the lantern."}
:::space{lines=4}
:::如果需要固定的断开而不是空白,请用:::columnbreak或:::pagebreak。
#:::toc
:::toc在所在位置输出目录。它展开为普通的块:toc.levels所列级别(默认为1级)的每个标题一个,每个:::part一个,所以目录像其他文字一样跨栏跨页排版,点击条目会跳到指令所在行。条目显示标题的编号(numberingTemplate的输出,没有时为章的序号)、标题、点线前导符和它起始页的页码;启用toc.subtitle时,还有第二行,显示某个标题属性,如本章的{author="…"}。篇有单独的一行,由toc.parts.design设计,用该篇自己的palette着色。样式为numbered: false的标题列出时不带编号;标题上的{toc="false"}会把它排除在外(通常是目录本身的标题)。
# Contents {style="front-matter" toc="false"}
:::toc页码就是文档实际输出的页码。单独排版的文档会用上一遍的页码标签重新排版,直到页码不再变化;如果编号在前置部分之后重新开始(即上面的:::numbering做法),多排一遍就能稳定下来。单独排版的一章(沙盒预览)则从其宿主处接收全书的大纲。见配置参考中的目录。
#:::index
:::index在所在位置输出索引:全书中用:index[…]或:index{term="…"}标记的词条及其页码,页码随文字移动而更新。它与这些标记一起在索引中介绍。
# Index {style="index"}
:::index#标题中的换行
在标题中(或在篇的title属性中)写\\,可以在标题作为标题显示的地方强制换行:栏内标题继续排,在该处显示一个空格,而开篇页设计的{titleText}在该处换行(文本元素的每种overflow模式都是如此)。书眉、{chapterTitle}、{partTitle}和PDF大纲总是把标题渲染为一行。在中文或日文中,这个换行在两个该文字的字符之间读作一个表意空格(对联式标题);如果其中一侧是数字或拉丁文字(关于举办 \\ 2026年…),页面上排出汉字与拉丁文字之间的间距,而PDF书签和文档标题则直接把两半连在一起,与普通中文的写法相同。
# Concepts of health and illness. \\ Community health {author="I. Zango Martín"}#行内格式
行内标记在任何文本块(标题、段落、引用块、列表项)中都能识别。在标题中,它遵循headings.inlineMarks,默认开启:标题里的斜体、粗体、上下标、小型大写字母和链接都按段落中的样子印出,斜体标题中的斜体片段则排成正体。关闭后,标记符号被去掉,标题按标题自身的样式印出;postext 1.4及更早版本保存、标题中带有标记的配置也按这种方式读取(见配置 › 标题)。无论开关如何,标题的版面设计都把{titleText}作为纯文本印出。
| 标记 | 语法 | 说明 |
|---|---|---|
| 粗体 | bold或bold | 以bodyText.boldFontWeight渲染。可选的bodyText.boldColor为粗体片段替换默认正文颜色。 |
| 斜体 | italic或italic | 以当前字体家族的斜体渲染。可选的bodyText.italicColor为斜体片段替换默认正文颜色。与CommonMark一样,下划线只在词边界处表示强调:夹在两个字母或数字之间的下划线(snake_case_name、URL中的SR_AIR_EN.pdf)是普通文本(bold同理);词内强调请用星号(unbelievable)。中文、日文和韩文字符在这里不算字母,因为这些文字不用空格分词:中文_斜体_中文和中文__粗体__中文分别是斜体和粗体。没有构成粗体的__也不会变成斜体:foo__bar__baz仍是文本。 |
| 粗斜体 | both或both | 两种标志叠加。 |
| 上标 | ^text^ | 字号为正文的58%,升高正文字号的三分之一:指数(10^-8^)、离子电荷(Na^+^)。被标记的文本首尾都必须是非空白字符;正文中单独的脱字符保持原样,表情^_^和^o^也一样(n.^o^和1^o^仍是上标)。 |
| 下标 | ~text~ | 字号与上标相同,下降正文字号的0.15,因此不超出下伸部:化学式的下标(H~2~O、pK~a~)。两侧都是数字的波浪号表示范围,保持原样:3~5 days、需要3~5天。夹在两个中文词之间的波浪号也一样,不会开启下标:周一~周五、北京~上海;但下标仍可在中文字符前结束(F~合~等于)。可与粗体和斜体组合(H~2~O)。下标和上标连写、中间没有任何字符时,像公式那样上下叠放:T~0~^2^把2排在0的上方,不论谁先写;此时下标下降正文字号的0.25,以避开上标,这一对占据两者中较宽者的宽度。两者之间有空格或字母时,依次排列;插入词连接符(U+2060)也会依次排列,且中间不显示任何东西。叠放的一对在断行处不会分开:过宽的词会在这一对之前断行。 |
| 小型大写字母 | :smallcaps[text] | 小写字母排成正文字号70%的大写字母:剧本中的人物名、正文里的缩写词。内部和外围都可以带其他标记;见小型大写字母。 |
| 竖排中的文字方向 | :tcy[12]、:upright[GDP]、:sideways[12] | 用于竖排:一个直立的字格(纵中横)、每个字符各占一格直立,或整段横躺。在横排中不起作用;见竖排中的文字方向。 |
| 中文标记 | :dots[不可]、:name[賈寶玉]、:book[石頭記] | 着重号、专名号和书名号(按cjk.bookTitleMark排成《》或波浪线)。文本保持原样;见中文标记、注音和双行夹注。 |
| 注音 | :ruby[紅樓]{rt="hóng lóu"}或{紅樓|hóng|lóu} | 在基字上方(或旁边)标注拼音或注音符号。简写形式要求基字含有汉字、假名或注音符号,因此{x|x>0}仍是文本。 |
| 双行夹注 | :warichu[note]{open="〔" close="〕"} | 在行内以两行半字号排出的注文(双行夹注),可跨行、跨页断开。 |
| 行内代码 | | 去掉反引号,片段按原样以纯文本渲染:其中的、行内标签、公式、链接或强调符号都照字面印出,正文要展示语法时就这样写。独立的代码样式已列入路线图。 |
| 转义 | 、、、、、 | 反斜杠让标记字符本身印出,而不开启一个片段:表注的星号()、字面的脱字符、不开启公式的美元符号。在正文、行内标签、题注、表格单元格和注释中都有效。(postext 1.4及以前,题注、单元格、注释和行内标签会把中的反斜杠也印出来。) |
| 不换行空格 | 直接输入字符本身:U+00A0、U+202F、U+2007 | 把两侧的词粘在一起,使行不会在它们之间断开:数字与单位(37 °C)、页码引用(p. 12)、千位分组(225 000)。不换行空格(U+00A0)、窄不换行空格(U+202F)和数字空格(U+2007)都有粘连作用,在正文、题注、单元格、框和书眉中均如此,并各自保持原有宽度:两端对齐只拉伸词间空格。许多字体没有窄不换行空格或数字空格的字形,这时Canvas、HTML和PDF都按浏览器的方式排:分别为半个词间空格和一个数字的宽度。几乎所有字体都有U+00A0,因此它最稳妥。这样粘连起来、比整行还宽的一组,会在最后一个不换行空格处断开,而不在词内断开。词连接符(U+2060)起粘连作用但不占宽度。请直接输入字符本身:之类的HTML实体会照写法印出。见行不会断开的地方。 |
| 链接 | text | 可见文本留在文字流中,排法与没有链接时完全相同。在HTML和PDF输出中,URL让这些词成为可点击的链接;见链接。 |
| 图片 | | 行内图片的Markdown会从文本中移除。图片必须在PostextContent.resources中声明,排版引擎才能按resourcePlacement规则放置它们。 |
| 行内标签 | :chip[text] | 带框的一段文字,作为一个整体换行:词库、按键、标签。样式由chipStyles设定;见行内标签。 |
| 行内公式 | $…$ | 随周围文本排列的LaTeX公式,例如$e^+1=0$。由MathJax排版,在所有后端都渲染为矢量路径。字面的美元符号写作\$。缩放、独立公式($$ … $$)形式和错误处理见数学公式。 |
#链接
Markdown链接[text](url)把文本留在文字流中,排法与没有链接时完全一样:链接从不改变断行、间距或颜色。它保留URL,供能跟随链接的输出使用:
- HTML(
renderToHtml):链接的词包在<a href="…" rel="noopener noreferrer">中,沿用文本颜色,不加下划线。同一行上每一段连续的链接词对应一个锚点。 - PDF(
postext-pdf):同一行上每一段连续的链接词成为一个可点击的URI链接注释。在带标签的PDF中,它是一个Link元素,其文本就是这些链接词。 - Canvas:作为纯文本绘制,因为Canvas没有可点击的区域。
Read the [configuration guide](https://postext.dev/zh/docs/configuration "Configuration")
or write to [the team](mailto:team@example.com).- 链接目标可以带标题,标题会被忽略(
[text](https://example.com "Title"))。目标也可以用尖括号括起,其中的空格变为%20([text](<https://example.com/a b>))。 - 只保留安全的目标:
http:、https:、mailto:、tel:、ftp:和相对URL(../guide、#top)。其他协议(javascript:、data:、file:……)的文本照排,但不加链接。PDF只链接绝对URL。 - 与CommonMark一样,目标中可以含括号,只要括号配对:
[photo](https://commons.wikimedia.org/wiki/File:Bike_(Unsplash).jpg)链接整个URL。反斜杠可转义字符(\(、\_)。括号不配对时,目标在第一个)处结束,文本照排但不加链接;单独的括号请编码为%28或%29。空格也会结束目标,除非目标用尖括号括起。 - 紧贴链接文本的词共享该链接。在
see [the site](https://example.com).中,句号也属于可点击区域。 - 链接文本可以带强调(
[**bold** words](…)),也可以位于强调之内(**[words](…)**)。 - 链接可用于段落、列表项、引用块、标注框、题注、注释和表格单元格,在
headings.inlineMarks开启(默认)时也可用于标题。由标题生成的书眉、大纲和目录条目只保留文本,:chip[…]的文本也一样。 - 不识别引用式链接(
[text][id])和自动链接(<https://…>)(见不支持的内容)。
在VDT中,目标位于每个链接片段上,即VDTLineSegment.href。解析器把一个片段的链接作为其文本的区间保存在InlineSpan.links中,从不为链接拆分片段,所以链接不会改变版面。
#行内标签
:chip[text]把text排在一个框里,即一个圆角、带底色的“标签”,随行排列:词库或分类练习中的词、键盘按键、标签。:chip[text]{style="key"}从chipStyles中选用一个具名样式(见配置参考);没有style,或所给id没有对应的样式时,行内标签采用第一个样式(配置中没有样式时,采用内置的chip样式;遇到未知id,沙盒会发出警告)。
Classify: :chip[battery] :chip[cable] :chip[switch] :chip[bulb]
Press :chip[Ctrl]{style="key"} + :chip[C]{style="key"} to copy.- **一个整体。**行内标签内部从不断开或断词;行在标签之间、在其两侧的词间空格处断开。比整行还宽的标签会溢出该行,而不是被拆开。
- **宽度。**其步进宽度为文本加上两侧的水平内边距和轮廓线。两端对齐只拉伸词间空格,从不拉伸标签内部。样式的
gap是框与隔着空格的相邻词或标签之间至少保留的距离,空格不够宽时会补足(行首行尾不补,紧贴的标点如:chip[a],也不补)。 - **高度。**框是围绕基线的一条带,以标签字号计,基线以上0.8 em、以下0.25 em,再加上垂直内边距和轮廓线。垂直内边距画在行框之外,从不改变行距,因此基线网格保持不变;比行距还高的框可能碰到上一行或下一行的标签,沙盒会标出不同行上相互重叠的两个标签(“行内标签碰到相邻行”),以便减小内边距、轮廓线或字号。
- **文本。**标签文本可带自身的行内标记(
:chip[**bold** word]、:chip[x^2^]),也可处于外围的强调中(**:chip[a]**);样式可以设定字体家族、字号、颜色、粗体和斜体。内部的字面方括号写作\]。标签内的引用、色块和公式保持字面,\$印出美元符号(postext 1.4及以前会连反斜杠一起印出)。 - **空标签。**只含空格(包括不换行空格)的标签(
:chip[ ])是一个空框,可用作答题空白或结束符:宽度为样式的水平内边距加轮廓线,高度与有文字的标签相同。用样式的paddingX设定空白的宽度(:chip[ ]{style="blank"})。方括号之间什么都没有时,:chip[]保持为字面文本。 - **适用位置。**段落、列表项、引用块、标注框、表格单元格、题注和注释。标题中的
:chip[…]保持为字面文本。 - **输出。**Canvas、HTML和PDF都绘制框,并把文字作为真正的文本排出:在HTML中可以选中,在PDF中可以提取且符合阅读顺序(在带标签的PDF中,框是版式工件,文字属于所在段落)。
#小型大写字母
:smallcaps[text]把text排成小型大写字母,用于剧本中的人物名、正文里的缩写词、章节的开头几个词。小写字母排成正文字号70%的大写字母,大写字母、数字和标点保持原字号,因此:smallcaps[Hamlet]印出一个原字号的H,后接小型大写的AMLET。
Enter :smallcaps[Hamlet] and :smallcaps[Horatio], reading.
The :smallcaps[unesco] report and the :smallcaps[who] guidelines.- **合成。**小型大写字母由字体自身的大写字母生成,在Canvas、HTML和PDF中方式相同,因此文本在各处的度量和断行完全一致。不使用字体真正的小型大写字母(OpenType的
smcp特性);需要时,请通过段落样式把文本设为小型大写字母字体家族(例如名称以“SC”结尾的家族)。 - **标记。**文本可带自身的行内标记(
:smallcaps[**Ophelia**]),也可处于外围的强调中(*:smallcaps[Act I]*);内部的字面方括号写作\]。其中的引用或行内标签也排成小型大写字母,引用在HTML和PDF中仍是一个链接;公式则不受影响。 - **断行。**词照常换行和断词;断词时按每个词原本的大小写读取。
- **适用位置。**段落、列表项、引用块、标注框、表格单元格、题注和注释,以及
headings.inlineMarks开启(默认)时的标题;关闭时,标题中的标记被移除,文本按原样印出。 - 整段。
smallCaps: true的段落样式或标注框正文会把全部文本这样排(见段落样式)。 - **文本。**Canvas、HTML和PDF承载的是画出的字母:复制
:smallcaps[Hamlet]得到“HAMLET”。
#竖排中的文字方向
在竖排(layout.writingMode: 'vertical-rl')中,汉字直立,拉丁词和较长的数字横躺,最多两位的数字在一个字格中直立,除非它位于拉丁语句子中,那时随句中的词排列(见配置 › 竖排中的数字)。有三种标记可手动指定一段文字的方向:
第:tcy[120]回,:upright[GDP]增長:sideways[12]倍。:tcy[…](纵中横,縱中橫)把文本并排放进一个1 em的直立字格,过宽时横向压缩::tcy[120]、:tcy[3.0]、:tcy[A+]。最多约四个字符时效果较好。:upright[…]让每个字符各占一格直立,拉丁字母在格中居中:适合沿栏逐字母阅读的缩写词。行不会在其内部断开。:sideways[…]让整段随行横躺,汉字也一样:适合作者希望横躺的两位数。- 文本保留在纯文本中;这些标记内部可带其他行内标记(
:tcy[**12**])、链接(:sideways[[iPhone](https://…)])以及彼此嵌套,以最内层为准(:tcy[:upright[AB]]让A和B直立);字面方括号写作\]。在横排中它们不起任何作用。 - 标记内的引用、注释标号、公式、行内标签或色块保持各自的排法:
:sideways[iPhone[^1]]让iPhone横躺,注释编号则像所有注释编号一样排;引用的编号像其他短数字一样,按cjk.uprightDigits在一个字格中直立。 inlineMarks: true的设计文本元素竖排时也接受这些标记(见配置 › 竖排文本元素)。- 在断行和两端对齐时,
:tcy字格和:upright的每个字符都按汉字计算,它们旁边不加汉字与拉丁文字之间的间距。
#中文标记、注音和双行夹注
中文书籍用字行之间的标记代替斜体或下划线,为汉字标注读音,并在行内排注文。这由五个指令完成。中文排版解释了它们背后的规范。这些指令保留文本:方括号内的字符留在段落中(搜索、目录、索引锚点和复制的文本都按原样读取),指令内部和外围都可带其他行内标记,包括嵌套的标记。字面方括号写作\]。
此事:dots[不可]輕忽。:name[賈寶玉]與:name[林黛玉]讀:book[西廂記]。
{滿紙|mǎn|zhǐ}荒唐言,:ruby[一把]{rt="yì bǎ"}辛酸淚!:ruby[都]{rt="ㄉㄡ"}云作者痴。
寶玉:warichu[甲戌側批:此是第一首標題詩。]{open="〔" close="〕"}道:……- **
:dots[text]**在横排中于每个字符下方、竖排中于其右侧加着重号,标点和空格不加。style="dot|circle|sesame"(默认dot),fill="open"为空心,pos="over|under"换到另一侧。在cjk.emphasis: 'dots'下(中文文档的默认设置),汉字上的Markdown强调*…*效果相同;同一强调中的拉丁字母仍为斜体。 - **
:name[text]在文本下方(竖排时在左侧)画专名号,:book[text]**加书名号:按cjk.bookTitleMark的设定,在书名两侧加《》(书名中的书名用〈〉),或用古籍和台湾版本的波浪线,或什么都不加(默认在大陆用括号,在台湾和香港用波浪线)。同一份源文件可同时用于现代大陆版本和古籍版本。并排的两个专名或书名,线条彼此分开。 - **
:ruby[base]{rt="…"}**在基字上方标注读音(拼音),或在每个字右侧标注(注音符号读音默认如此)。读音数与字数相同时(以空格或|分隔),每个字各得一个读音,行可在它们之间断开(单字注音);使用group或数量不符时,一个读音居中排在整个基字上方,且不会断开。pos="over|under|right"选择标注的一侧。简写形式{紅樓|hóng|lóu}(每个|后一个读音)或{紅樓|hónglóu}(整个基字一个读音)效果相同,但仅当基字含有汉字、假名或注音符号,且不在公式、代码和属性中时才生效,因此拉丁文正文中的{x|x>0}仍是文本。在花括号或竖线前加反斜杠,可让中文的这类写法保持为文本:\{紅|hóng}和{紅\|hóng}印出{紅|hóng}。位于行首或行尾的基字连同读音一起对齐到该边。 - **
:warichu[note]**在行内以正文一半的字号分两行排注文(双行夹注),先读上行(竖排时为右行)。长注文填满本行剩余部分,再接到下一行、下一栏或下一页。open和close在注文两侧加正文字号的括号;cjk.warichu设定字号、颜色和默认括号。拉丁文字的注文在词间断开。
行距始终不变:标记和读音都放在行间空白中;当段落的行间空白不足以容纳它们时(cjkMarksExceedLeading、rubyExceedsLeading),以及当一行下方的标记与下一行上方的读音放不进共用的空白时(无论在同一段内还是跨两段),构建都会发出警告。请为带注的段落设置行距更大的段落样式。标记、读音和注文在段落、标题、列表项、引用块和框中绘制;在题注、表格单元格和注释中,以及在书眉和版面设计中,文本印出但不带它们。在cjk.bookTitleMark: 'brackets'下,书名的《》属于文本中的标点:题注、单元格、注释、目录条目、书签和索引条目都保留它们。见配置 › 标记、注音和双行夹注。
#脚注
脚注由两部分组成:引用处的标号[^id],以及定义,即本章任意位置以[^id]:开头的独立段落。
The keeper climbed the tower every evening.[^steps] The wind put out his candle,
so he learned to count the steps in the dark.
[^steps]: The cast-iron staircase has 112 steps; the tower was built in 1861.- 标号。
[^id]把脚注编号印成上标,紧贴前面的词(写在标点之后,如上例)。id可包含字母、数字、-、_、.和:。标号可用于段落、列表项、引用块和标注框;在标题、题注和表格单元格中照原样印出。 - **定义。**以
[^id]:开头的段落;其文本一直延续到下一个空行,可带常见的行内标记(粗体、斜体、链接、:ref、公式、行内标签)。定义无论写在哪里都会离开文字流,因此可以放在引用它的段落下方,也可以全部集中在章末。同一id以第一个定义为准。 - **编号。**脚注按首次引用的顺序编号,每章(一级标题,以及书中的每个文档)重新开始;被引用两次的脚注保留第一次的编号,只排一次。
footnotes.numbering: 'document'让编号贯穿全书。 - **脚注的位置。**默认排在引用它的那一行所在栏的底部,上方有一条短线:该行与其脚注总在同一栏,脚注放不下时,该行会随脚注一起移走。单栏版面中就是页面底部。
footnotes.placement: 'chapterEnd'则把一章的所有脚注排在该章最后一个块之后,默认位于它们结束的那一栏的底部。字号、分隔线和间距见配置参考中的脚注。 - **检查。**没有定义的标号(
undefinedFootnote)在空脚注上印出编号;没有标号引用的定义(unusedFootnote)不排。沙盒在检查面板中列出这两种情况。
#索引
书后索引列出书中的术语及其出现的页码。在正文讨论某个术语的地方标记它,再用:::index在需要的位置印出索引,通常放在书末单独的一章。排版完成后,引擎找出每个标记所在的页,因此页码随正文变化:增加一段、移动一章或改变成品尺寸,索引都会印出新的页码。
Iron-deficiency :index[anaemia] is the most common kind.
The pulse is taken at the wrist.:index{term="Pulse!radial" main}
# Index {style="index"}
:::index#索引标记
- **
:index[text]**印出text,并以它本身的词作为条目。内部的行内标记会印出,但不进入条目。方括号后的属性可把它归到别的条目下::index[iron deficiency]{term="Anaemia!iron-deficiency"}。 - **
:index{term="…"}**什么都不印。标记取所在行中紧挨在它前面的词所在的页;若它位于行首,则取它后面的词所在的页。只含标记的行会被删除,因此单独成行的标记从不拆开段落,也不增加空白。 - **适用位置。**段落、标题、列表项、引用块、标注框和脚注定义。在题注、表格单元格和设计元素中,标记照原样印出。在行内代码中以及反斜杠之后(
\:index),它是文本。
| 属性 | 作用 |
|---|---|
term | 条目,各级之间用!分隔:term="Heart!valves!mitral"把该页归在Heart下valves的子条目mitral中。每一级都可以带行内标记(term="*Escherichia coli*"),排序时忽略这些标记。没有term时,:index[text]使用其文本。 |
sub | 加在term之后的一级:term="Heart" sub="valves"等同于term="Heart!valves"。 |
sort | 最后一级的排序键,用于该级应按其他字母排序的情况::index[St Kilda]{sort="Saint Kilda"}、term="20th century" sort="twentieth century"。中文索引按排序器给出的汉字读音排序和分组。多音字若要按另一读音排序,就用只有所需读音的汉字写排序键::index[重阳]{sort="崇阳"}把重阳归在C下,位于程与崔之间,而不是归在Z下。拼音排序键(sort="chong yang")也能归到C,但会排在C下所有中文条目之后,因为排序器把拉丁字母排在汉字之后(见配置 › 索引中的groupBy)。 |
main | 一个标志,表示该术语的主要论述处。其页码排成粗体(index.main)。同时以两种方式标记的页为粗体。 |
range | 同一术语的range="start"和range="end"界定一段跨越数页的论述:条目印出34–37。只有开始没有结束,或只有结束没有开始,则只印它自身所在的一页,并报出indexRangeUnclosed。 |
see | 以参见代替页码::index{term="Cardiac insufficiency" see="Heart failure"}印出Cardiac insufficiency. See Heart failure。目标的各级用!分隔,印出时用冒号连接(See Heart: valves)。目标不是索引中的条目时,报出indexSeeUnknown。 |
seealso | 排在条目页码之后的参见:Heart, 12, 40. See also Circulation。标记自身所在的页与其他标记一样计入,因此一个标记既可以索引一段文字,又可以指向相关条目;see标记则不增加页码。 |
index | 另一个独立索引的名称:index="names"把标记归入:::index{index="names"}印出的索引,而不是主索引。 |
没有术语的标记(单独的:index{}或:index{see="…"})不索引任何内容,并报出indexMarkInvalid。
#印出索引
:::index在所在位置印出主索引,:::index{index="names"}印出具名索引。该指令展开为普通的块,每个条目一块,像正文一样流过各栏和各页:放在标题样式设定了两栏layout的标题之下,就得到常见的两栏索引。点击某个条目会跳到该指令所在的行。
# Index of names {style="index"}
:::index{index="names"}
# Index of subjects {style="index"}
:::index- **顺序。**条目按文档语言(
locale或index.locale)的字母顺序排序:带重音的字母与其基本字母归在一起(Árbol归在A下),西班牙语中ñ排在n之后,自成一组。以符号开头的条目排在最前,其次是以数字开头的,然后是字母。子条目在其条目下以同样方式排序,每深一级缩进一级。 - **分组。**每出现一个新的首字母就开启一组:一个字母标题(
index.groups),其上方空一行(第一组上方不空)。字母标题与该组第一个条目排在同一个块中,因此不会单独留在栏末;没有自身页码的条目(只作为其子条目的上级)出于同样原因与其第一个子条目排在一起。 - **页码。**使用页面上印出的页码标签,包括前置部分的罗马数字页码。条目的页码经过排序且每页只列一次;连续的页合并为范围(
12–14,index.mergeRanges),落在同一条目某个范围内的页并入该范围(其中若有主要页,整个范围排成粗体),index.rangeFormat: 'chicago'会缩短第二个数字(234–37)。粗体(主要)页码单独列出。在PDF中,每个页码都链接到对应的页。 - 参见位于条目末尾:条目没有页码时为Term. See Target,有页码时为Term, 12. See also Target。这些标签随文档语言变化(See、Véase……),可在
index.see中设定。 - **图书。**在逐章排版的书中(沙盒、
buildBundle),印出索引的那一章会收到所有章节的标记及其页码,只有当其中某个标记移动时才重新排版。同时包含标记和索引的文档会反复排版,直到页码稳定,与:::toc相同。
排版样式、缩进和分隔符见配置参考中的索引。
#数学公式
数学公式是文档格式中的一等功能。Postext把$…$解析为行内公式,把$$…$$解析为独立(块级)公式,并通过SVG模式的MathJax渲染。三个后端使用同样的矢量路径,因此Canvas预览、HTML导出和PDF输出逐像素一致,PDF无论放大多少倍都保持矢量。
- 行内:
$…$。在任何文本块(段落、标题、引用块、列表项)中都能识别。它在行中占一个不可分割、不可断开的框;Knuth-Plass把它当作不能拆分的词。若公式的自然高度会撑破行框,就等比缩小,以保持基线网格;很高的表达式应使用独立公式。 - 独立公式:
$$…$$。可以单独占一行($$\int_0^1 x^2\,dx$$),也可以用各自独占一行的$$标记围住多行。公式在栏内居中渲染,并对齐到基线网格,上下外边距可配置(math.marginTop、math.marginBottom),这与标题使用的校正机制完全相同,因此公式后的段落会回到网格上。 - **独立公式周围的文本:**单独占一行的独立公式即使上方没有空行,也会打断段落。公式前的文本是引出它的段落;紧接在结束的
$$下方、中间没有空行的文本,是被打断段落的延续,排版时首行不缩进,就像TeX排独立公式之后的“where …”那样。与上方文本以空行隔开(或位于列表、引文或标题之后)的公式不打断任何段落:其后的文本是新段落,无论有无空行都照常缩进(math.indentAfterDisplay: false让它也顶格)。只有完整的独立公式才会打断段落,即一行只有一个公式,或在下一个空行之前闭合的$$围栏;像$$a$$ and $$b$$这样的行仍是文本。math.keepWithLeadIn让公式与引出它的那一行留在同一栏。(postext 1.4及以前,上方没有空行的$$…$$行被当作段落的一部分,照写法印出。) - 公式编号:
\tag{…}为独立公式编号:公式占满栏宽(或标注框的内宽),公式居中,编号在所在行右对齐;在align中,每个带标签的行都如此。\tag*{…}印出不带括号的标签。只有显式的标签才会编号。 - 转义:
\$是字面的美元符号。题注、表格单元格、注释和行内标签不解析公式,因此其中的$照原样印出;\$在这些地方也印出美元符号,同一个转义字符串在正文和表格中读法相同。未配对的$或$$定界符会在沙盒的检查面板中产生一条unclosedMath记录,并带有可点击定位的源文本锚点。 - **错误:**MathJax拒绝的TeX源码(未定义的宏、语法错误)会以
invalidMath警告的形式报出。该公式被替换为一个红色小占位框,版面几何仍然有效。 - **配置:**配置中的
math部分提供enabled、fontSizeScale(相对于周围文本的字号:为1.0时,公式的一个em等于该字号,对独立公式和正文中的行内公式而言就是正文字号;自postext 1.5起,公式比1.4时约小13%,而1.4保存的文件包和沙盒图书保持原有大小,见公式字号)、color(未设置时沿用正文颜色)以及独立公式的外边距。 - **引擎:**MathJax按需加载。沙盒和排版工作线程会自行启动它;在你自己的代码中,要在
buildDocument之前await initMathEngine(),否则每个公式都会排成一个灰色占位框(见启动数学引擎)。
The Euler identity $e^{i\pi}+1=0$ links the five fundamental constants.
$$
\int_0^{\infty} e^{-x^2}\,dx = \frac{\sqrt{\pi}}{2}
$$句子中间的公式,以及公式之后不缩进、继续下去的句子:
For a pendulum of length $L$ the period is
$$T_0 = 2\pi\sqrt{L/g}$$
where $g$ is the acceleration of free fall.#资源
图片、SVG和表格不直接写在正文里。它们作为资源声明一次(在沙盒的“图表”面板中管理,这个面板负责上传图片和SVG,提供交互式表格编辑器,也用来编辑题注和位置),再通过id与正文关联。引用一个资源就足以把它放进文档:你只需用行内的:ref{id="…"}提到它一次,引擎就会把这幅图或这张表浮动到该引用之后的第一个空位,可能是提到它的那一栏的栏底、下一栏的栏顶,或者下一页的一个横带,和印刷排版师的做法一样。你不需要再摆放它第二次。
下面两种写法都是新增的语法,不与CommonMark冲突,所以用到它们的文档在其他任何Markdown查看器里仍然能当作普通文本阅读。
#行内引用(主要写法)
在正文中用:ref{id="…"}引用资源。第一次引用既会引入这个资源(使它被放到页面上),也会渲染出它经过计算的编号,默认在编号前加上该类型的简称:
As shown in :ref{id="lighthouse-diagram"}, the lantern room sits above the gallery.渲染结果为:As shown in Fig. 1.7, the lantern room sits above the gallery.,而这幅示意图本身会浮动到这句话之后最近的空位(本栏栏底、下一栏栏顶,或者下一页的一个横带),这句话和它后面的文字则不受打断,继续排下去。
正文永远不会在引用处断开。资源落在哪里(第一个空位,还是只接受顶部或底部的空位;限于一栏之内,还是占满全宽),由它的位置决定(见下文的位置),也取决于你在哪里提到它:搜索从引用之后开始。
#块级嵌入(可选,显式的行内放置)
偶尔你会希望资源停在文字流中的某个确切位置,而不是浮动。这时把资源的placement.position设为"here"以取消浮动,并在单独的一行用::resource{id="…"}嵌入它:
Here is the floor plan we discussed.
::resource{id="lighthouse-diagram"}
The keeper's quarters occupy the eastern wing.对浮动资源来说,::resource指令是多余的::ref已经放置了它,同一id多出来的::resource只会被当作又一次引用,而不是第二份副本。只有当资源解析后的位置是"here"时,::resource才会把它以行内方式渲染出来。行内资源上方保留一行的空白(浮动间距),与浮动体一样,除非前面的块要求更多。在正文中,它下方也保留同样的空白;随后,它后面的文字回到基线网格上,这可能再多出最多一行。紧跟在它后面的标题、列表、框或另一个行内资源,会把这段空白与自己上方的空白合并:取两者中较大的一个,而不是两者相加。(在postext 1.4及以前,下方的空白只是对齐网格后剩下的部分,从零到一行不等;layout.inlineResourceGap: 'above'保留这条规则,1.5之前保存的书也按它读取。)在标注框(:::callout)内,资源保留同样的空白:上方是一行框内文字的高度,设为'around'时下方也是;位于框的顶部或底部时,则由内边距把它隔开。(在postext 1.4及以前,它紧贴着框内的文字;layout.inlineResourceGapInBoxes: false保留这种做法,1.5之前保存且框内嵌有资源的书也按它读取。)
id必须与“图表”面板中定义的某个资源对应。引擎渲染资源(位图、SVG或表格),并在下方画出题注,作为图脚或表脚。题注文字由资源类型的captionPrefix、计算出的编号和资源本身的题注组成,例如Figure 1.7. The original lighthouse plan.。题注的排印由配置 › 题注样式控制:标签和说明共用同一种字体和字号,标签单独保留粗体、斜体和颜色设置;题注上方的间距默认为0.75em,对齐方式默认为左对齐。题注也可以放在资源上方(captionStyle.position: 'above',可全局设置,也可按资源类型设置),还可以衬一条色带。资源还可以带一个note:一行简短的来源说明或出处,支持与题注相同的行内格式和:ref标记,以较小的字号排在资源下方(题注在下时排在题注下方,题注在上时排在资源主体下方),样式通过captionStyle.note设置。
**题注和附注中的换行。**题注或附注是按其所在位置的行长排出的一个段落,在其中键入的换行符相当于一个空格。要另起一行,写\\(标题中使用的强制换行),或者在行尾加一个反斜杠,即Markdown的硬换行:¹ Measured at 20 °C. \\ ² Mean of three runs.会把一张宽表的每条脚注各排一行。换行前的那一行保持自然宽度,不会被拉伸到行长;连续两个换行不会产生空行(两者之间加一个不换行空格才会)。在表格单元格中,\\的作用与换行符相同:开始一个新段落;它后面那一行的缩进会保留,所以行首两个空格仍然会把列表项嵌套一级。在正文中,两个反斜杠总是表示换行,没有转义方式:要把它们印出来,就放在行内代码里,那里的反斜杠照原样印出。在链接的目标地址中,它们仍是URL的一部分;在指令的属性中(例如:ref的text),它们是属性值的一部分;在只排一行的行内标签中,换行相当于一个空格。(在postext 1.4及以前,这些反斜杠会被印出来,题注或附注只在行长用尽时才换行。)
表格资源自己画出表格线,样式由配置 › 表格样式控制:表体单元格和表头单元格的排印完全独立;表头背景默认为#f0f0f0,边框默认为0.75pt,cellPadding默认为0.375em;未设置的字段都继承正文的设置。列宽属于表格本身:TableModel.columnWidths为每一列保存一个相对权重([2, 1, 1]让第一列占一半宽度);未设置时各列平分宽度。表格也可以使用某个命名变体:table.styleId从文档的tableStyles中选一个(见配置 › 命名表格样式),其中未设置的字段继承tableStyle;id未知或缺失时沿用tableStyle。
单元格用TableCell.align(left、center、right;列表项始终齐左)和TableCell.verticalAlign(top为默认值,另有middle或bottom)来摆放内容。垂直对齐会在比内容高的单元格里移动整个单元格内容(图片及其下方的文字作为一个整体),比如被更高的相邻单元格撑高的行,或者rowSpan覆盖的多行。它在所有输出中都生效(Canvas、HTML、PDF),也适用于旋转的表格,以及跨页拆分的表格的每一段。两者都可以在沙盒表格编辑器工具栏的对齐按钮中逐个单元格设置。
表格单元格还可以容纳图片。TableCell.image按id指定一个位图或SVG资源({ "resourceId": "fig-arm", "width": 0.7 }):图片画在单元格内,不编号、不浮动、不带题注,按单元格的内宽(或由width给出的比例,默认为1)缩放并保持宽高比,对齐方式与单元格文字相同,单元格中的文字排在它下方。行高会随之增加以容纳图片。在沙盒的表格编辑器中,工具栏的图片按钮为当前单元格选择资源,宽度字段设置比例。id与任何图片资源都不对应时,单元格只显示文字。
单元格可以有自己的填充色。TableCell.background是一个颜色值({ "hex": "#c1dfd6", "model": "hex" },可以用paletteId关联到文档调色板中的某一项),用它代替样式中的表头或表体背景色;兼容性矩阵就是这样把单元格涂成绿、红、黄三色的。沙盒的表格编辑器通过工具栏的填充控件设置它。为了给这些填充色加图例,题注、附注和任何文本块都接受行内色块::swatch{color="#c1dfd6"}(一个十六进制值,或调色板某一项的id,如:swatch{color="table-compatible"})会在基线上排一个小方块,边长为字号的四分之三,用该颜色填充,并以文字颜色描边,所以附注可以写成:swatch{color="ok"}: compatible; :swatch{color="no"}: incompatible。颜色解析不出任何值时,只画一个空的边框。十六进制值可以带alpha通道(#rrggbbaa、#rgba),rgb() / rgba()颜色也可以用,所以半透明的单元格填充色可以有同样半透明的图例(见配置 › 透明度)。
SVG资源还可以通过diagramStyle.singleInk(默认为false)重新着色,以便用单一专色印刷。启用后,SVG示意图中的每一种颜色都会按亮度映射为diagramStyle.inkColor(默认为主调色板颜色#295AA3)的某个色调:白色对应纸色,黑色对应满版油墨。这样文档用单一专色印刷时,图仍能如实再现。见配置 › 示意图样式。
格式错误的嵌入(缺少id或id为空、id没有加引号或用了单引号、带有多余的属性)不会被提升为资源块;它会退回到普通的段落解析,在输出中仍然可见。格式正确、但紧贴在某个段落行下方、中间没有空行的嵌入行也是如此:它会被当作那个段落的一部分。两种情况都会发出malformedEmbed警告,即沙盒“检查”面板中的一条嵌入被排成文字。
行内引用在任何文本块中都能识别,包括段落、标题、引文块和列表项,并且可以与粗体、斜体、行内代码和行内公式并用。
引用选项
:ref指令接受三个可选属性,顺序不限。style选择计算出的标签如何渲染:style="number"只印编号(1.7),style="full"印出类型全称加编号(Figure 1.7),未设置style时使用类型的shortLabel加编号(Fig. 1.7)。case只改变标签部分的大小写,取值为lower、upper或capitalize,编号不受影响。text是原样使用的替换文字,会取代任何计算出的标签,优先级高于style和case。各种渲染选项对照如下:
| 语法 | 渲染结果 | 说明 |
|---|---|---|
:ref{id="…"} | Fig. 1.7 | 默认样式:类型的shortLabel后接编号,两者之间用不换行空格连接,永远不会被拆到两行。 |
:ref{id="…" style="number"} | 1.7 | 只有计算出的编号,不带标签。 |
:ref{id="…" style="full"} | Figure 1.7 | 类型的完整name后接编号。用在句首,或者缩写读起来别扭的地方。 |
:ref{id="…" case="lower"} | fig. 1.7 | 只改变标签的大小写:lower(fig. 1.7)、upper(FIG. 1.7)或capitalize(首字母大写)。可以与style="full"组合(figure 1.7);编号始终不变,无法识别的值会被忽略。 |
:ref{id="…" text="see the plan"} | see the plan | 显式替换。给出的文字原样使用,取代任何计算出的标签,适合写成“前面已经看到”这类行文式的链接。提供text时,它优先于style和case。 |
如果:ref(或::resource)指定的id没有对应的资源,标签会退回为?(设了text=时印出该标签,同样不带编号和链接),沙盒会发出未知资源警告。引擎把它记为文档contentWarnings中的一条unknownResourceId,附上引用的源码范围和页码;正文所用资源的题注、附注或表格单元格中的:ref也同样记录。
#按首次引用编号
资源的编号在它按阅读顺序第一次被提到时分配,不论这第一次是::resource块级嵌入还是行内:ref。此后,对同一id的每一次引用都印出同一个编号。
也就是说,编号遵循读者遇到它们的顺序,而不是资源在面板中创建的顺序:
- 如果你在引言中
:ref了一幅图,两页之后才嵌入它(::resource),它仍然采用引言处的编号,因为引用在先。 - 在文档较前的位置插入一个新引用,其后的所有编号都会自动重排。没有需要手动保持同步的编号。
编号按资源类型分别计数,并遵守每种类型的重置范围和计数格式。模板标记({h1}、{n})、resetOn和counterFormat见配置 › 资源类型。
只有正文引用的资源才会计数:只由版面设计画出的资源(比如章首页的一个图片元素)不编号,计数器保持原样。{h1}会计入每一个样式不是numbered: false的一级标题,即使它的numberingTemplate为空,所以一篇只有标题是H1的文章,默认会把图编为1.1、1.2……。配置 › 哪些内容编号列出了这两条规则,以及把图编为Figure 1、2……的设置。
#位置
每个资源都有一个位置设置,决定它的浮动体落在哪里。解析顺序是:资源自己的placement,然后是其类型的defaultPlacement,最后是内置默认值auto / column:
| 字段 | 取值 | 含义 |
|---|---|---|
position | "auto" · "top" · "bottom" · "here" | "auto"(默认值)占用引用之后的第一个空位,顶部或底部均可;"top" / "bottom"只接受相应类型的空位;"here"取消浮动,在::resource指令处以行内方式嵌入。 |
width, align | 0 < width < 1; "left" · "center" · "right" | 用于比所在位置窄的资源:width是它所占栏宽(或页宽)的比例,align是它在该位置中的摆放方式(在栏中居中的小表格;占满页宽的横带中只跨一栏的图片)。比所在位置窄的图片(比栏窄的位图,或被layout.fitFiguresToPage缩小的图)同样按align摆放,下方的题注仍保持该位置的行长。浮动体和行内::resource嵌入都适用。 |
captionSide | true · false | 在侧栏专供浮动体使用的一栏半版式中(layout.sideColumnRole: 'floats'),带captionSide的"column"浮动体把主体留在主栏,把题注(和附注)排在侧栏,与图的顶边齐平(底部浮动体则与底边齐平);侧栏让出这一段横带。没有这种侧栏的页面,题注仍排在图的下方。 |
span | "column" · "page" | 占一栏,或者打断分栏文字流,横跨所有栏、占满版心宽度。在单栏版式中两者没有区别。 |
rotate | "ccw" · "cw" | 把资源旋转四分之一圈排出,比如竖开本书中的一张横向表格。"ccw"逆时针旋转,资源顶部朝向页面左边缘(读者把书顺时针转过来看),这是通常的惯例;"cw"方向相反。旋转的资源总是独占一页的通栏浮动体:它沿版心的高度排版,高度向下取整到基线网格的整行,再减去一行正文,即每个浮动横带都保留的浮动间距(在14 pt网格上,237 mm高的版心能容纳47行,即232.1 mm,所以资源得到其中46行,即227.2 mm);页边距为对称镜像时它紧贴书脊(否则齐左);一张太宽、一页放不下的表格会在行与行之间切开,在后续页面上继续旋转排出,并重复表头,与比一页还高的直立表格完全一样。旋转的图会缩放到适合页面。对行内("here")嵌入无效。 |
浮动体按阅读顺序进入第一次引用之后的第一个空位:先是引用所在栏的栏底,然后是同一页下一个空栏的栏顶和栏底,再然后是文字流打开的下一页的各个横带(通栏浮动体在每一栏都还有空间容纳它时占用页面底部,否则占用下一页的一个横带)。由行内图或表打开的页面也算在内:等待该页的浮动体,在两者都放得下时占用页首,位于那幅图或那张表的上方;放不下时,那幅图或那张表保留这一页,浮动体等下一页。在postext 1.4及以前,这样的页面会被跳过,即使两者都放得下,浮动体也要等到再下一页。浮动体从不缩小,也从不落在它的引用之前。同一编号序列的浮动体按引用顺序出现:在一页上哪里都放不下的图,会挡住排在它后面的图(等待中的表不会挡住图,反之亦然),所以图12永远不会出现在图11之前。本来要等待的表格会被切开:遇到空栏的栏顶时,它先占用放得下的那些行,然后在下一个空位(旁边的栏或下一页)继续,并重复表头行(见tableStyle.overflow)。
浮动体永远不会越出所在的章:在章首页(带breakBefore或span: 'page'的标题级别)、:::part、带floatBarrier: true的标注框样式(一章末尾的“要点”框)以及文档末尾,所有仍在等待的浮动体都会先被放置,放在该页的空位里,或者放在边界之前新开的页面上。由章首页本身(标题中提到了自己的图的章标题)或:::part之后第一个块首次引用的浮动体,属于新的一章:它和其他浮动体一样,落在那一行之后。要求放在页首的图或表,这时可以占用本章最后一页的底部,位于已齐底的各栏下方,而不必独占一页。:::pagebreak只是把等待中的浮动体送到它后面的那一页。
浮动横带会根据基线网格调整,使周围的文字保持全页统一的垂直节奏。顶部横带把下外边距增加到下一条网格线,让浮动体下方的文字与相邻各栏和对页保持对齐。底部浮动体的定位方式是让其题注的最后一行与其他各栏最后一行文字共用一条基线(没有题注的内容则让底边对齐最后一个网格位置),因此排满的页面在各栏之间、对页之间都结束在同一高度。
在一章(以及整个文档)的最后一页,排在最后一段文字下方的通栏图和表后面再没有内容,所以它们会上移,依次叠放在文字下方一个浮动间距处,而不是在文字与页面底部的图之间留出空白。position: 'bottom'的浮动体也是如此。要让它们像其他页面一样留在页面底部,设置layout.hugClosingFloats: false(见配置 › 版面)。有侧栏的页面从不移动它们。
三个后端,即Canvas预览、HTML查看器和PDF输出,都会渲染资源。在HTML后端中,图片数据不随版面一起传递,所以由宿主通过resourceImageUrl(fileId)解析器选项提供;缺少解析器(或它对某个文件没有返回内容)时,资源会渲染成一个中性的占位框,使版面保持稳定。
浮动体可以落在哪里
“从不落在引用之前”是从引用浮动体的那一行算起的:浮动体要等那一行排好,再按阅读顺序占用它之后的第一个空位;那一行所在页面的页首位于它之前。侧边浮动体(span: 'side',位于一栏半版式中专供浮动体使用的侧栏)是例外:它在侧栏中叠放在引用它的文字旁边,可以比引用行在页面上的位置更高。以第5页引用的一幅图为例:
| 位置 | 在第5页 | 否则 |
|---|---|---|
top, span: 'page' | 不可能:页首的横带在引用行之上。 | 第6页的顶部横带。 |
top, span: 'column' | 后面某个仍为空的栏的栏顶:在两栏中的第一栏引用时,它可以排在第二栏开头。 | 第6页某一栏的栏顶。 |
auto或bottom, span: 'page' | 第5页的底部横带,前提是每一栏都还有空间容纳它。 | 第6页的一个横带。 |
auto或bottom, span: 'column' | 引用所在栏的栏底;然后是后面某个空栏的栏底(两者皆可)或栏顶(仅限auto)。 | 第6页。 |
- 章首页遵循同样的规则:在章首页第一段中引用的通栏
auto或bottom浮动体可以占用该页的底部横带,排在文字下方;top浮动体则排在下一页开头。要让图片出现在引用它的那一页,用auto或bottom,或者把它画成章首页版面设计中的一个图片元素。 - 在同一段中引用的两个栏浮动体占用接下来的两个空位:通常第一个在引用所在栏的栏底,第二个在下一个空栏的栏顶,在页面上并排。
- 在单栏版式中,通栏浮动体就是栏浮动体,规则相同:在某一页引用的
top浮动体落在下一页的页首。 - 从一页延续到下一页的段落,同样从引用行算起。段落从第5页底部开始,而引用落在第6页时(或者因为第5页底部放不下足够多的行,整段移到了第6页),引用就在第6页:
top浮动体排在第7页开头,auto浮动体在有空间时占用第6页底部。同一页的各栏之间也是如此,跨页拆分的框也一样:由框的第二部分引用的图要等到那一部分。 - **postext 1.5中的变化。**在postext 1.4及以前,版面排到引用浮动体的段落时,浮动体就进入等待队列,所以这样的段落延续到(或移到)的那一页,可能以该浮动体开头,排在含有引用的那一行之上。现在这样的图会晚一页出现,或者在它要求
auto时落在该页底部;页数可能随之变化。
#不支持的内容
Postext不识别以下CommonMark功能。它们要么被当作普通文本(因此会原样出现在输出中),要么被悄悄丢弃:
- Setext式标题:即
===/---下划线形式。请使用ATX(#)标题。 - 围栏式或缩进式代码块:即
```或~~~围栏以及4个空格的缩进。其中的行会作为普通Markdown读取,而不是保留为代码清单:彼此之间没有空行的行会合并为一个段落,并丢失行首空格;以#加空格开头的行会变成标题(#!/usr/bin/env仍是文本),以-或1.加空格开头的行会变成列表项,一对$符号会变成公式,围栏行则作为文本印出:```围栏印成一个反引号,开头的那个后面还跟着信息字符串(`bash),~~~围栏印成一个作为下标排出的小~。要排代码清单,把每一行写成单独的段落(行与行之间空一行),放进一个:::paragraphs块,其段落样式设置等宽的fontFamily,并用反引号包住每一行,反引号会让#、$、*等字符照原样保留。行首的普通空格会被丢弃,行内连续的空格会缩成一个,反引号内也是如此,所以要用不换行空格(U+00A0)来缩进和对齐,并把它们放在反引号之内:开头反引号之前的不换行空格同样会被丢弃。行内代码能被识别,但没有代码字体:见行内格式。 - HTML透传:原始的
<tags>不会被解释。MDX式标签也不支持;Postext源文件是纯Markdown。 - 水平线:
---、***、___。 - 表格:管道表格不会被解析。表格作为结构化资源建模,位于
PostextContent.resources中。 - 引用式链接:
[text][id]加上定义块。 - 自动链接:
<https://example.com>。 - 删除线:
~~text~~。删除线渲染器目前保留给已完成的任务项使用。 - 边注:尚未实现;类型定义接受的
PostextContent.notes会被引擎忽略。脚注和章末注用[^id]书写(见脚注);在postext 1.5及以前,它们只能作为文本排出。
这份清单会随时间缩短。在此之前,凡是上文支持部分没有明确列出的内容,都应当视为原样输出的文本。
除语法之外,从右向左书写的文字(阿拉伯文、希伯来文……)目前还不能正确排版:没有双向排版功能。中文可以横排,也可以竖排,并按其所在地区的要求处理断行、标点宽度、字间两端对齐、着重号、注音和割注(见中文排版);日文和韩文使用同一个排版器,按中国大陆的中文规则处理。内置八种语言的断词模式,并为这八种语言和中文提供内置标签。见语言与文字。
#书写约定
有几条约定,决定了文档是能顺利解析,还是会出乎你的意料:
- **块与块之间留一个空行。**用空行隔开的两个段落是两个段落。写在相邻两行的两个段落会变成一个:每一行都并入前面的段落。
- **多余的空行不会增加空白。**三个空行隔开两个块,与一个空行效果完全相同。想在它们之间多留些空间时,写一行
:::space。 - **列表每一级嵌套恰好用两个空格。**一个空格会被解析为第一级列表项。三个或四个空格向下取整为第二级(引擎使用
floor(leading / 2) + 1,最深为5级)。不识别制表符缩进,请把制表符转换为空格。 - **第一个列表项不要缩进。**第一级列表项从第0列开始。项目符号前的空白会隐式提高层级。
- **任务标记必须写在方括号里,中间一个空格。**只能是
[ ]、[x]、[X],不能有变化。[*]或[-]不是任务标记,会作为原样文本渲染。 - **不支持列表中的引文块。**引文块要从第0列开始,写在列表之外。
- **图片和表格放在
resources中。**行内的会被去掉,正是因为行内图片会破坏按栏感知的放置。把每张图片声明为资源并按id引用,引擎再决定它是浮动、打断分栏,还是移到下一页的顶部。 - **不表示公式时,用
\$转义美元符号。**Postext把$…$解释为行内LaTeX,所以正文中单独的$会开始一个公式。价格、shell提示符以及其他带单独美元符号的内容都应写成\$。 - **标记用ASCII字符键入,中文文本中也一样。**中文或日文输入法会给出全角形式:围栏写成
:::,标题写成#,脚注标记写成[^1],属性写成{…},粗体写成**。它们会作为文本印出,构建时会把该行报告为fullwidthMarkup警告,并指出应该键入的ASCII形式。属性值可以使用任何文字,可以用“…”或「…」加引号;键名仍然是ASCII。
#完整示例
一份用到所有受支持结构的短文档:
---
title: The Typesetter's Craft
author: Anon
---
# Opening
A good book reads itself. The **reader** should never notice the
typesetter's work — only the author's voice.
## What makes text readable
Three properties matter most:
1. Line measure — 40 to 75 characters per line.
2. Leading — 1.3 to 1.5 times the font size.
a. Tighter at short measures.
b. Looser at long measures.
3. Contrast between body and headings.
Common failure modes include:
- Lines that stretch across the whole page.
- Headings that float without a following paragraph.
- Orphans and widows at column boundaries.
> Typography is the craft of endowing human language with a durable
> visual form.
> — Robert Bringhurst
### Review checklist
- [x] Column width under 75 characters
- [x] Leading set to 1.5
- [ ] Orphan and widow pass
- [ ] Final proofread
### A note on formulas
Inline math such as $a^2 + b^2 = c^2$ flows with the surrounding text, and
display math sits centred on the baseline grid:
$$
\int_0^1 x^2\,dx = \tfrac{1}{3}
$$同一份文档经排版引擎处理后,会生成一个结构化的VDTDocument,其页面把上述每个块都作为带类型的条目保存。块如何变成几何形状,见架构页面。