/

子文档

当我们提到一个 Quarkdown 文档时,广义上指的是构成某个 Quarkdown 项目的一组资源。

通常,尤其是在知识管理与维基(如本维基)的场景下,页面可以拥有指向其他页面的链接,从而构建起一个相互连通的*子文档(subdocuments)*网络。

在 Quarkdown 中,一个子文档的入口点是一个被另一个子文档所引用的源文件。实际上,当我这样做 时,我就是在引用一个子文档。

每个项目都至少包含一个子文档:称为*根(root)*的主子文档。

注意:不要把子文档与引入 混淆。二者的对比请参阅引入 vs. 子文档

引用子文档

每当一个 Markdown 链接指向一个本地的 .qd.md 文件时,它就被视作对子文档的引用。

[My subdocument](file.qd)

你也可以通过追加锚点,来链接到子文档中的某个特定小节:

[Section A of my subdocument](file.qd#section-a)

等价地,你可以使用 .subdocument {path} {label?} 文档 ↗ 函数:

.subdocument {file.qd} label:{My subdocument}

与链接语法不同,该函数接受动态路径,因此适合更复杂的用例。例如,你可以将它和 .listfiles 结合使用,通过for-each 循环 来自动链接某个目录下的所有文档:

.foreach {.listfiles {pages} sortby:{date} order:{descending}}
    path:
    .subdocument {.path} label:{.path::filename}
List files

Quarkdown 确保每个文件只被求值一次,因此循环与递归引用都能被优雅地处理。

上下文继承

当引用一个子文档时,其内容会像一个独立的 Quarkdown 文档一样被求值。

一个相关的区别在于,子文档会继承引用方的上下文:文档元数据、自定义项、函数、变量,等等。

示例 1

main.qd

.doctype {paged}
.theme {darko}
.pageformat margin:{1cm}

.function {greet}
    Hello!

[Introduction](introduction.qd)

introduction.qd

无需再次设置文档,它已经被继承了!

.greet

.include 不同,上下文是继承而非共享:在子文档中所做的更改不会影响引用方。

示例 2

以下示例会产生错误,因为 greet 并未在引用方的上下文中定义:

main.qd

[Introduction](introduction.qd)

.greet <!-- 错误:未解析 -->

introduction.qd

.function {greet}
    Hello!

工作目录

子文档的工作目录是相对于该子文档自身的入口点,而非引用方:

  • main.qd
  • pages
    • introduction.qd
  • images
    • image.png

虽然 main.qd 可以引用 images/image.png,但 introduction.qd 应该将其引用为 ../images/image.png

媒体存储系统 仍然可以跨子文档存储媒体文件。

子文档图谱

子文档被组织成一个有向图,其中边就是它们之间的链接。

你可以通过 .subdocumentgraph 函数将这张图可视化:

Graph

输出

子文档的导出方式因输出目标而异。

HTML

每个子文档都被导出为与 index.html 位于同一目录下的一个独立子目录。

配置资源(例如主题与运行时脚本)只会生成一次。而媒体 则是按子文档分别存储的。

  • MyDocument
    • media
    • theme
    • script
    • introduction
      • media
      • index.html
    • conclusion
      • media
      • index.html
    • index.html

PDF

每个子文档都被导出为一个独立的 PDF 文件。

  • MyDocument
    • index.pdf
    • introduction.pdf
    • conclusion.pdf

注意:PDF 输出中的子文档链接尚不可导航。

如果只存在根子文档,那么只会生成 MyDocument.pdf,而无需目录。

输出命名

默认情况下,子文档输出文件以其源文件名命名。这一行为可以通过 --subdoc-naming <strategy> 编译器选项进行自定义。这适用于所有输出目标,例如 HTML 与 PDF。

示例 3

getting-started.qdgetting-started.pdf

文档名称

使用 --subdoc-naming document-name 启动编译器时,每个子文档的输出会以自己的 .docname 命名,而非源文件名。如果一个子文档没有设置 .docname,则会回退使用源文件名。请注意,重复的文档名称不会被处理,可能导致名称冲突与文件被覆盖。

示例 4

getting-started.qd 且带有 .docname {Getting Started}Getting-Started.pdf

最小化名称冲突

由于子文档输出文件平铺在同一个目录中,有可能出现两个同名但来自不同目录的子文档发生冲突的情况。

默认情况下,Quarkdown 接受这种易冲突的行为,以生成人类可读的 URL。

如果冲突无法避免,使用 --subdoc-naming collision-proof 启动编译器会为输出文件名追加一个哈希。

示例 5

getting-started.qdgetting-started@12345678.pdf