3.1 HTML

编译一本书(使用 bookdown)与编译一个单独的 R Markdown 文档(使用 rmarkdown)为 HTML 格式的主要区别在于,默认情况下一本书籍会生成多个 HTML 页面——通常每章一个 HTML 文件。这使得你在阅读书籍某一章节的时候能够更容易地添加书签或将其 URL 分享给他人,并且可以更快地将书籍加载到 Web 浏览器中。目前,我们为 HTML 输出提供了多种不同地样式:

  • GitBook 样式 (Section 3.1.1),
  • 三列 Bootstrap 样式 (Section 3.1.2),
  • 默认的 Bootstrap 样式 (Section 3.1.3)
  • Tufte 样式 (Section 3.1.4).

3.1.1 GitBook 样式

GitBook 样式来自于 GitBook,这是一个由 Friendcode, Inc 公司发起的项目 (https://www.gitbook.com),它致力于帮助作者使用 Markdown 撰写书籍。它提供了一种漂亮的风格,其布局由左侧显示目录的侧边栏和右侧的书籍主题组成。该设计能够对窗口大小变化做出响应,例如,当窗口足够宽时,导航按钮显示在书籍主体的左侧/右侧,当窗口较窄时,导航按钮折叠到底部,一边给读者更多的水平空间来阅读书籍主体部分。

开始撰写一本新的 gitbook 的最简单的方法就是使用 RStudio Project Wizard(文件 (File) > 新建项目 (New Project) > 新的目录 (New Directory) > 使用 bookdown 的书籍项目 (Book project using bookdown))并在下拉菜单中选择 gitbook(见图 3.3)。

如果你不使用 RStudio 或更喜欢使用函数,则可以从 R console 中使用 bookdown::create_gitbook() 创建相同的项目模板。请参阅 ?bookdown::create_gitbook 以获取帮助。

我们对原始的 GitBook 项目做了一些改进。最重要的一点是,我们将 Markdown 引擎替换为基于 Pandoc 的 R Markdown v2,这样你在写书时可以使用更多的功能:

  • 你可以在 Markdown 中嵌入 R 代码块和内联 R 表达式,这样可以轻松创建可重复的 (reproducible) 文档,并使你不必手动同步计算过程与它的实际输出结果(knitr 将自动处理)。
  • Markdown 语法更加丰富:你可以编写 Pandoc 版本的 Markdown 支持的任何内容,例如 LaTeX 数学表达式和引文。
  • 你可以在书中嵌入交互式内容(仅用于 HTML 输出)。例如 HTML 小组件和 Shiny 应用程序。

我们还在用户界面中添加了一些有用的特性,很快我们将详细介绍它们。bookdown 中 GitBook 样式的输出格式函数为 gitbook()。它的参数如下所示:

gitbook(fig_caption = TRUE, number_sections = TRUE,
  self_contained = FALSE, anchor_sections = TRUE,
  lib_dir = "libs",
  global_numbering = !number_sections,
  pandoc_args = NULL, extra_dependencies = list(), ...,
  template = "default",
  split_by = c("chapter", "chapter+number", "section", "section+number", "rmd", "none"),
  split_bib = TRUE, config = list(), table_css = TRUE,
  code_folding = c("none", "show", "hide"))

大多数参数被传递给 rmarkdown::html_document(),包括 fig_captionlib_dir...。想要了解所有可能参数的完整列表,你可以查阅 rmarkdown::html_document() 的帮助页面。我们强烈推荐你使用 fig_caption = TRUE,原因由两个:1) 使用标题来解释你的图片很重要;2) 启用图片标题意味着当输出为 LaTeX 时,图片将被放置在浮动环境中,否则可能会在某些页面上留下大量空白。图/表编号的格式取决于章节是否编号:如果 number_sections = TRUE,这些编号数字会使用 X.i 的格式,其中 X 是篇章编号而 i 是递增编号;如果章节没有编号,所有的图/表在书籍中将从 1、2、……、N 开始依次编号。请注意,在任何一种情况下,图片和表格的编号都是相互独立的。

... 的所有可能的参数之中,你最可能使用参数 css 提供一个或多个自定义的 CSS 文件来调整默认 CSS 样式。在 gitbook() 中有一些 html_document() 的参数被硬编码,你无法更改它们:toc = TRUE(必须使用目录)、theme = NULL(不使用任何 Bootstrap 主题)和 template(存在一个内部 GitBook 模板)。

请注意,如果将参数修改为 self_contained = TRUE 以更改 HTML 页面为自包含的 HTML 页面,则所有 HTML 文件的总大小都会显著增加,因为每个 HTML 文件中都必须嵌入许多 JS 和 CSS 文件。

除了这些 html_document() 的配置项之外,gitbook() 还有另外三个参数:split_bysplit_bibconfig。参数 split_by 指定了如何将 HTML 输出文件拆分为多个页面,其可能的值为:

  • rmd:使用输入的 Rmd 文件的文件名作为对应 HTML 文件的文件名,例如,chapter3.Rmd 生成的 HTML 文件为 chapter3.html
  • none:不要拆分 HTML 文件(整本书将是一个 HTML 文件)。
  • chapter:按一级标题拆分文件。
  • section:按二级标题拆分文件。
  • chapter+numbersection+number: 与 chaptersection 类似,但是文件将被编号。

对于 chaptersection,HTML 文件名将由标题标识符确定,例如,篇章标题为 # Introduction 的第一章的文件名默认为 introduction.html。对于 chapter+numbersection+number,章/节编号将在 HTML 文件名之前,例如 1-introduction.html2-1-literature.html。默认情况下,标题标识符是从标题文本自动生成的,9你页可以在标题文本后使用语法 {your-custom-id} 手动指定标识符,例如:

# An Introduction {#introduction}

默认标识符是 `an-introduction`
但是我们将其更改为 `introduction`

默认情况下,参考书目会被拆分,相关的引文项目将放在每页的底部,这样读者就不必导航到不同的参考书目页面来查看引文的详细信息。可以使用 split_bib = FALSE 禁用此功能,在这种情况下,所有引文都放在单独的页面上。

你可以使用 config 配置项中的几个子配置项来调整用户界面中的一些细节。回想一下,所有输出格式配置项(不仅仅适用于 bookdown::gitbook)都可以通过使用命令行接口 bookdown::render_book() 传递给格式函数,或直接将其写入 YAML 元数据。我们将 gitbook 格式下 config 的默认子配置项显示为 YAML 元数据并展示如下(请注意,它们的缩进都在 config 配置项下):

bookdown::gitbook:
  config:
    toc:
      collapse: subsection
      scroll_highlight: true
      before: null
      after: null
    toolbar:
      position: fixed
    edit : null
    download: null
    search:
      engine: lunr # or fuse
      # options to control/tune search engine behavior (for
      # fuse.js, refer to https://fusejs.io/api/options.html)
      options: null
    fontsettings:
      theme: white
      family: sans
      size: 2
    sharing:
      facebook: true
      github: false
      twitter: true
      linkedin: false
      weibo: false
      instapaper: false
      vk: false
      whatsapp: false
      all: ['facebook', 'twitter', 'linkedin', 'weibo', 'instapaper']
    info: true

toc 配置项控制目录 (TOC) 的行为。当加载页面时,你可以通过 collapse 配置项先将某些项目折叠。该配置项可能的值为 subsectionsectionnone(或 null)。如果你的目录很长且标题超过三个级别,则这个配置项可能会有所帮助:subsection 表示折叠目录项目中的所有小节 (X.X.X);section 表示折叠目录项目中的所有节 (X.X),因此最初仅显示顶级标题;none 表示不折叠目录中的任何项目。对于那些折叠的目录项目,可以通过单击其上级目录项目来切换其可见性。例如,你可以单击目录中的篇章标题以显示/隐藏该章的小节。

toc 中的 scroll_highlight 配置项控制在滚动书籍正文页面时是否启用目录项目的高亮显示(默认情况下此功能已启用)。当向下/向上滚动时,每当新标题进入当前视口,左侧目录中的相应项目将高亮显示。

由于侧边栏的宽度是固定的,因此当目录中的某个项目由于标题文本太宽而被截断时,可以将光标悬停在侧边栏上以查看显示全部文字的提示条。

你可以使用 HTML 标签 <li> 在目录前后添加更多项目。这些项目将使用水平分隔器与目录分开。你可以使用管道符 |,这样就不需要按照 YAML 语法转义这些项目中的任何字符,例如:

    toc:
      before: |
        <li><a href="...">My Awesome Book</a></li>
        <li><a href="...">John Smith</a></li>
      after: |
        <li><a href="https://github.com/rstudio/bookdown">
        Proudly published with bookdown</a></li>

当你浏览不同的 HTML 页面时,我们将尝试保留目录的滚动位置。通常即使你转到下一页,也会在目录的固定位置上看到滚动条。但是如果当前章/节的目录项目在页面加载时不可见,我们将自动滚动目录以使其对你可见。

The GitBook toolbar.

图 3.1: The GitBook toolbar.

Gitbook 样式在每个页面的顶部都有一个工具栏(图 3.1),允许你动态地改变书籍设置。toolbar 配置项有一个子配置项 position,可以取值为 fixedstatic。默认情况下 (fixed),工具栏将被固定在页面的顶部,所以即使你向下滚动页面,工具栏也仍然在顶部可见。如果它被设置为 static,工具栏将不会随着页面滚动,也就是说,一旦滚动页面,你将无法看到它。

工具栏的第一个按钮可以切换侧边栏的可见性。你也可以敲击键盘上的 S 键来做同样的事。GitBook 样式能够记住侧边栏的可见性状态,例如,如果你关闭了侧边栏,那么下次打开书籍时,侧边栏将保持隐藏状态。事实上,GitBook 样式也能够记住许多其它的设置,例如搜索关键词和字体设置。

工具栏的第二个按钮是搜索按钮。它的键盘快捷键是 F(查找)。点击该按钮后,你会看到侧边栏的顶部出现一个搜索框。当你在框中输入时,目录项将会被过滤,以显示符合搜索关键词的部分。现在你可以使用方向键 Up/Down 来突出显示搜索结果中的上一个或下一个匹配内容。当你再次点击搜索按钮(或在搜索框外敲击 F),搜索关键词将被清空,搜索框将被隐藏。如果要禁用搜索,请在 config 中设置 search: false 配置项。

第三个按钮是用于字体/主题设置。读者可以改变字体大小(更大或更小),字体族(有衬线 (serif) 或无衬线 (sans serif)),以及主题(WhiteSepiaNignt)。你可以通过 fontsettings 配置项设置这些配置项的初始值。字体大小是按 0-4 的比例测量的;初始值可以设置为 1、2(默认)、3 或 4。可以通过设置 fontsettings: null(或 no)将该按钮从工具栏中删除。

# changing the default
    fontsettings:
      theme: night
      family: serif
      size: 3

edit(编辑)配置项与第 4.4 节中提到的配置项相同。如果它不为空,一个编辑按钮将被添加到工具栏中。这是为书籍的潜在贡献者设计的,他们可以在点击该按钮后在 GitHub 上编辑书籍内容并发送 Pull Requests。historyView 配置项的工作方式也是如此。

如果你的书有其它输出格式供读者下载,你可以提供 download 选项,这样就可以在工具栏中添加一个下载按钮。这个配置项可以接受一个字符向量,或者一个字符向量的列表,其中每个向量的长度为 2。当它是一个字符向量时,它应该包含文件名或文件扩展名,例如,以下两种设置都是正确的。

    download: ["book.pdf", "book.epub"]
    download: ["pdf", "epub", "mobi"]

当你只提供文件扩展名时,文件名来自于配置文件 _bookdown.yml(第 4.4 节)中的书籍文件名。当 downloadnull 时,gitbook() 将在书籍输出目录中寻找 PDF、EPUB 和 MOBI 文件,并自动将它们加入 download 配置项中。如果你只是想关闭下载按钮,请使用 download: false。所有供读者下载的文件将显示在一个下拉菜单中,文件扩展名被用作菜单文本。当唯一可供读者下载的格式是 PDF 时,下载按钮将是一个单一的 PDF 按钮而不是一个下拉菜单。

 &esmp;另一种形式的 download 配置项的值是一个长度为 2 的向量构成的列表,例如:

    download: [["book.pdf", "PDF"], ["book.epub", "EPUB"]]

你也可以把它写成这样:

    download:
      - ["book.pdf", "PDF"]
      - ["book.epub", "EPUB"]

列表中的每个向量由文件名和将在菜单中显示的文本组成。与第一种形式相比,这种形式允许你自定义菜单文本,例如,你可能有两份不同的 PDF 供读者下载,因此需要使菜单项目有所差别。

在工具栏的右边有一些按钮,它们可以让你在社会网络网站,如 Twitter、Facebook 和 Linkedin 上分享链接。你可以使用 sharing 配置项来决定启用哪些按钮。如果你想完全摆脱这些按钮,可以使用 sharing: null(或 no)。

工具栏中显示的另一个按钮是信息 (i) 按钮,它列出了可用于导航文档的键盘快捷方式。这个按钮可以通过设置 info: false 来隐藏。

最后,YAML 元数据中还有一些顶级配置项,可以通过 Pandoc 传递给 GitBook HTML 模板。它们可能不会对 HTML 输出产生明显的影响,但当你把 HTML 输出部署为网站时,它们可能会很有用。这些选项包括:

  • description: 一个字符串,它将会被写入 HTML 头部 <meta name="description" content=""> 标签中的 content 属性(如果缺失,将会使用书籍的标题替代)。这对搜索引擎优化 (search engine optimization, SEO) 很有用。请注意,它应该是纯文本,不应该使用任何 Markdown 格式,例如 _italic_**bold**
  • url: 书籍网站的 URL,例如 https\://bookdown.org/yihui/bookdown/10
  • github-repo: user/repo 格式的 GitHub 储存库。
  • cover-image: 书籍封面图片文件的路径。
  • apple-touch-icon: 一个图标文件的路径(例如一个 PNG 图片)。这只适用于 iOS 系统:当网站被添加到主屏幕上时,该链接由这个图标表示。
  • apple-touch-icon-size: 图标文件的大小(默认情况下为 152 x 152 像素)。
  • favicon: favorite icon(收藏夹图标)文件的路径。通常情况下,这个图标显示在浏览器的地址栏中,如果浏览器支持标签,则显示在标签的页面标题前方。

下面我们展示了一下 YAML 元数据的样例(请再次注意这些是 顶级 配置项):

---
title: "An Awesome Book"
author: "John Smith"
description: "This book introduces the ABC theory, and ..."
url: 'https\://bookdown.org/john/awesome/'
github-repo: "john/awesome"
cover-image: "images/cover.png"
apple-touch-icon: "touch-icon.png"
apple-touch-icon-size: 120
favicon: "favicon.ico"
---

设置 descriptioncover-image 的一个很好的效果是,当你在一些社交网站(如 Twitter)上分享你的书籍的链接时,该链接可以自动扩展为一个带有封面图片和书籍描述的卡片。

3.1.2 三列 Bootstrap 样式

bs4_book() 输出格式是使用 Bootstrap (https://getbootstrap.com) 构建的,其功能经过了精心设计,无论你是在手机、平板电脑还是桌面上,都能获得干净的阅读体验。在全尺寸屏幕上,其布局包括散列内容,因此读者能够快速看到左边的所有章节,中间的当前章节,右边的当前篇章中的各个小节。你可以在这里阅读样例书籍:https://mastering-shiny.org

Home page of a book with the three-column Bootstrap style.

图 3.2: Home page of a book with the three-column Bootstrap style.

除了基础的 bookdown 组件(第 2 节),bs4_book 的主要功能包括:

  • 使用 bslib 软件包轻松定制颜色和字体。

  • 内置搜索(按小节细分),帮助读者快速查找所需内容。

  • 包含章节内目录的侧边栏,使得书籍导航更加简单,有助于提供在本章中有关当前位置的上下文。

  • 精心排版,不管设备的大小,都尽可能使得内容易于阅读。在阅读时,一个悬浮标题会妨碍你的阅读,但是如果你需要的话,它很容易被访问。

  • 行内脚注意味着你能够在它们所指文本的旁边阅读旁白。此主题最好与生成脚注的参考样式匹配。

  • 通过 downlit 软件包进行的 R 语法高亮和自动链接,并搭配 Alison Hill 设计的无障碍配色方案。

  • 增强了通过 Twitter、LinkedIn 和 Facebook等平台进行社会分享的元数据,这样,每一个分享的章节都会有一个独特的描述,根据该章节的内容自动生成。

  • 配置指向远程存储库(如 GitHub 或 GitLab)的链接的能力,允许读者轻松查看每个章节的源文件或提供编辑建议。

输出格式函数是 bookdown::bs4_book。以下是它的参数:

bs4_book(theme = bs4_book_theme(), repo = NULL, ...,
  lib_dir = "libs", pandoc_args = NULL,
  extra_dependencies = NULL, template = "default",
  split_bib = FALSE, footnotes_inline = TRUE)

3.1.2.1 创作一本 bs4_book

开始撰写一本新的 bs4_book 的最简单的方法就是使用 RStudio 项目向导 (Project Wizard)(File(文件) > New Project(新的项目) > New Directory(新的目录) > Book project using bookdown(使用 bookdown 的书籍项目)) 并在下拉菜单中选择 bs4_book。(请见图 3.3)。

用于创建新的 bookdown 项目的 RStudio 项目向导的屏幕截图。

图 3.3: 用于创建新的 bookdown 项目的 RStudio 项目向导的屏幕截图。

如果你不使用 RStudio 或者喜欢使用函数来完成,可以在 R Console 中使用 bookdown::create_bs4_book() 创建相同的项目模板。参见 ?bookdown::create_bs4_book在线文档以获得帮助。

这种风格是为每页展示一个章节的书籍设计的。这意味着每章是一个 .Rmd 文件,每个 .Rmd 文件可以包含一个章节。每个文件必须以一级标题开始,例如 # 章节标题,而且必须是文件中唯一的一级标题。

在章节中使用第二级和更低级的标题,如:

#   一章

##  一节

### 一小节

第一级和第二级标题显示在当前章节的侧边栏中,当你向下滚动时,它会粘在页面顶部。当导航到一节时,像 小节 这样的三级子标题将自动展开。

index.Rmd 文件是必需的,并且也是你的书籍的第一章。当你编译书籍时,它将会成为主页面。如果你想将仅应包含在书籍 HTML 版本的内容包括在内,你可能需要将 knitr include 区块配置项与 knitr::is_html_output() 函数相结合,有条件地包含该内容。有关说明请参见 R Markdown Cookbook

index.Rmdbs4_book 的一个 YAML 头部开起来像这样:

---
title: "A Minimal Book Example"
author: "Jane Doe"
date: "2024-12-22"
site: bookdown::bookdown_site
output: bookdown::bs4_book
url: https://bookdown.org/janedoe/bookdown-demo
cover-image: cover.png
description: |
  This is a minimal example of using the bookdown package to write a book.
  The output format for this example is bookdown::bs4_book.
---

3.1.2.2 样式 & 定制化

bs4_book() 格式建立在 Bootstrap CSS 框架 (Version 4)上,这是一个可复用的 HTML、CSS 和 JavaScript 代码块的开源库。Bootstrap 框架允许通过 bslib R 软件包轻松定制颜色和字体。

你可以使用 theme 配置项来添加一个十六进制格式primary 颜色,这将改变你书中所有链接的颜色和页脚的背景颜色。

bookdown::bs4_book:
  theme:
    primary: "#0d6efd"   

对于自定义字体设置,添加 google: 关键字会触发 sass::font_google()的自动导入 Google 字体文件的能力。下面是一个 YAML 的例子,改变了 base_fontheading_fontcode_font

bookdown::bs4_book:
  theme:
    primary: "#0d6efd"   
    base_font: 
      google: Sen
    heading_font:
      google:
        family: Bitter
        wght: 200
    code_font:
      google: 
        # arguments to sass::font_google() 
        family: DM Mono
        local: false

默认情况下,google: 会将字体文件与你的书籍捆绑在一起,所以它会在本地下载、缓存并提供相关的字体文件。这意味着当你与其他人分享书籍时,即使没有互联网连接,字体也能保证呈现出来(local: false 通过 URL 导入文件,而不在本地提供)。

你也可以使用非谷歌字体,使用 sass::font_face() 在本地提供。

3.1.2.3 标注区块

标注区块可以用来使某些部分的内容从你叙述的其他部分中突出出来。bs4_book 样式包括特殊的标注区块,它具有预定义的风格,可以在标注的文本和/或代码周围添加一个彩色的边框。使用下面的语法来创建一个标注区块。

::: {.rmdnote}
`bs4_book` 样式也包含一个像这样的 `.rmdnote` 
标注区块。

```{r collapse=TRUE}`
head(beaver1, n = 5)
```
:::

你可以在区块内使用 Markdown 语法和行内代码。生成书籍时,输出内容看起来和图 3.4 类似。

A special callout block.

图 3.4: A special callout block.

可用的区块有 .rmdnote.rmdcaution.rmdimportant.rmdtip.rmdwarning。使用的颜色将基于 Bootstrap 提供的默认颜色,但也可以在你的 _output.yml 文件中自定义。

bookdown::bs4_book:
  theme:
    primary: "#0d6efd"   # default .rmdnote = blue
    danger:  "#dc3545"   # default .rmdcaution = red
    success: "#198754"   # default .rmdimportant = green
    info:    "#0dcaf0"   # default .rmdtip = cyan
    warning: "#ffc107"   # default .rmdwarning = yellow

对于LaTeX输出,只有这些区块的内容会被显示出来,没有像 HTML 那样的彩色轮廓。用户可以使用自定义环境来定义在 LaTeX 输出时这些区块的外观。参见 R Markdown Cookbook以了解如何操作。

3.1.2.4 HTML 元数据

Bookdown 将根据 Pandoc 在 index.Rmd 中设置的变量生成 HTML <meta> 标签,该部分内容在第 6.4.2 节中进行了描述。此外,bs4_book() 将创建独特的章节描述,这些描述是由章节的内容自动生成的。你可以查阅 bs4_book 的 HTML 模板来了解这些变量的使用细节。

3.1.2.5 行内脚注

bs4_book 使任何脚注显示为在悬停状态下的行内显示,而不是在页面底部的链接项。您可以设置 footnotes_inline = FALSE 来选择取消这种行为,并将脚注放在底部。

bookdown::bs4_book:
  footnotes_inline: false

3.1.2.6 参考文献/书目

将你的引用文献制作为 脚注,可以让读者在引用它们的文本附近阅读脚注内容,因为 bs4_book 默认使脚注在点击时出现在行内。要做到这一点,请下载一个脚注样式的 CSL 文件;我们推荐 https://www.zotero.org/styles/。例如,你可以从 Zotero 下载 chicago-fullnote-bibliography.csl,然后添加到你的 index.Rmd 中。

bibliography: refs.bib
csl: chicago-fullnote-bibliography.csl

如果你不想在书籍的最后有一个参考文献章节,可以选择在你的 index.Rmd 中添加这一行:

suppress-bibliography: true

如果你想使用不支持脚注的引用文献样式,参考文献将不会在行内弹出窗口中显示。在这种情况下,你可能希望在你的 _output.yml 中添加 split_bib 配置项。

bookdown::bs4_book:
  split_bib: true

这样,你的参考书目将被拆分,相关的引用文献项目将被放在每一章的底部,这样读者就不必跳转到不同的参考书目页来查看引用文献的细节。

3.1.2.7 指定储存库

为你的书籍指定一个源码储存库,让你的读者可以轻松查看每一章的源文件或提出编辑建议。

如果你的书籍有一个名为 main 的默认分支,可以使用。

bookdown::bs4_book:
  repo:
    base: https://github.com/hadley/ggplot2-book
    branch: main

进一步,如果你的书籍位于一个名为 “book” 的子目录中,你可以使用:

bookdown::bs4_book:
  repo:
    base: https://github.com/hadley/ggplot2-book
    branch: main
    subdir: book

默认情况下,如果储存库的 URL 包含 “github”,它将获得一个 GitHub Font Awesome 图标,否则它将获得一个 GitLab 图标。要使用其他图标,请用正确的前缀来指定,如 fasfab 等等 (Font Awesome 5)。

bookdown::bs4_book:
  repo:
    base: https://github.com/hadley/ggplot2-book
    branch: main
    subdir: book
    icon: "fas fa-air-freshener"

3.1.3 默认的 Bootstrap 样式

如果你之前使用过 R Markdown,你应该熟悉 Bootstrap 样式 (https://getbootstrap.com),它是 R Markdown 的 HTML 输出格式的默认样式。rmarkdown 中的输出格式函数是 html_document(),并且我们在 bookdown 中也有一个相应的格式 html_book(),它使用 html_document() 作为基础格式。你可以在这里阅读 html_book() 的样例:https://bookdown.org/yihui/bookdown-demo2

事实上,bookdown 中有一个更加通用的格式 html_chapters()html_book() 只是它的特例:

html_chapters(toc = TRUE, number_sections = TRUE,
  fig_caption = TRUE, lib_dir = "libs",
  template = bookdown_file("templates/default.html"),
  global_numbering = !number_sections,
  pandoc_args = NULL, ...,
  base_format = rmarkdown::html_document,
  split_bib = TRUE, page_builder = build_chapter,
  split_by = c("section+number", "section", "chapter+number", "chapter", "rmd", "none"))

请注意它有一个 base_format 参数,接受一个基础输出格式函数,并且 html_book() 基本上就是 html_chapters(base_format = rmarkdown::html_document)html_book() 的所有参数都传递给 html_chapters():

html_book(...)

这意味着你可以使用 rmarkdown::html_document 的大多数参数,例如 toc (是否展示目录), number_sections(是否为章节标题标号)等等。类似地,关于可用配置项的完整列表,请查阅 rmarkdown::html_document 的帮助页面。注意 self_contained 参数在内部硬编码为 FALSE,因此你不能更改这个参数的值。关于 split_by 参数,我们在之前的章节中已经解释过了。

参数 templatepage_builder 是为高级用户准备的,除非你有强烈的定制 HTML 输出的需求,并且 rmarkdown::html_document() 提供的众多选项仍然无法为你提供想要的效果,否则你不需要理解它们。

如果你想将不同的 HTML 模板传递给 template 参数,则模板必须包括三对 HTML 注释,每条注释必须位于单独的行中:

  • <!--bookdown:title:start--><!--bookdown:title:end--> 标记书籍的标题部分。这部分仅放在编译好的书籍的第一页;
  • <!--bookdown:toc:start--><!--bookdown:toc:end--> 标记目录部分,这部分将会被放在所有 HTML 页面上;
  • <!--bookdown:body:start--><!--bookdown:body:end--> 标记书籍的 HTML 主体,HTML 主体内容将会被划分为多个单独的页面。回想一下,我们合并了所有 R Markdown 或 Markdown 文件,然后将其编译为单个 HTML 文件,并将其拆分;

你可以打开默认的 HTML 模板,查看这些注释的插入位置:

bookdown:::bookdown_file('templates/default.html')
# you may use file.edit() to open this file

一旦你知道 bookdown 在内部如何生成多页 HTML 输出,将更容易理解 page_builder 参数。它是一个函数,能够使用从上述注释标志中提取的 HTML 片段来合成每个单独的 HTML 页面。page_builder 的默认值是 bookdown 中的 build_chapter 函数,其源代码相对简单(忽略 button_link() 等内部函数):

build_chapter = function(
  head, toc, chapter, link_prev, link_next, rmd_cur, html_cur, foot
) {
  toc = add_toc_class(toc)
  paste(c(
    head,
    '<div class="row">',
    '<div class="col-sm-12">',
    toc,
    '</div>',
    '</div>',
    '<div class="row">',
    '<div class="col-sm-12">',
    chapter,
    '<p style="text-align: center;">',
    button_link(link_prev, 'Previous'),
    source_link(rmd_cur, type = 'edit'),
    source_link(rmd_cur, type = 'history'),
    source_link(rmd_cur, type = 'view'),
    button_link(link_next, 'Next'),
    '</p>',
    '</div>',
    '</div>',
    foot
  ), collapse = '\n')
}

基本上,这个函数使用许多组件,如 HTML 头部、目录、章节正文等,它将返回一个字符串,该字符串是完整 HTML 页面的 HTML 源代码。你可以使用诸如 gsub()paste() 之类的文本处理函数来操作此函数中的所有组件。

默认的页面生成器所做的是将目录放在第一行,正文放在第二行,导航按钮放在正文底部,并将它们与 HTML 头部和底部连接起来。下面是 HTML 源代码的一个简要示例,可以帮助你理解 build_chapter() 的输出:

<html>
  <head>
    <title>一本好书</title>
  </head>
  <body>
  
    <div class="row">目录</div>
    
    <div class="row">
      章节主体
      <p>
        <button>上一章</button>
        <button>下一章</button>
      </p>
    </div>
  
  </body>
</html>

对于所有 HTML 页面,主要的区别在于章节主体,其它大部分元素是相同的。html_book() 的默认输出将在 <head> 标签中包括 Bootstrap CSS 和 JavaScript 文件。

目录常用于导航。在 GitBook 样式中,目录显示在侧边栏中。对于 Bootstrap 样式,我们没有对它应用特殊样式,因此它显示为普通的无序列表(在 HTML 标签 <ul> 中)。使用某些 CSS 技术可以轻松地将此列表转为导航栏。在这个软件包中我们已经提供了一个 CSS 文件 toc.css,你可以在这里找到它:https://github.com/rstudio/bookdown/blob/master/inst/examples/css/toc.css

你可以复制这个文件导你的书籍的根目录,然后通过 css 配置项应用到 HTML 输出,例如:

---
output:
  bookdown::html_book:
    toc: true
    css: toc.css
---

如果你在网上稍微搜索一下,就能找到许多可能的方法将 <ul> 列表变成导航菜单,你可以选择你喜欢的菜单样式。我们刚才提到的 toc.css 是一种在黑色背景上有白色菜单文本的样式,并且支持子菜单(例如,节标题显示为章标题下的下拉菜单)。

事实上,如果你把 theme 选项设置为 null,就可以在 html_document() 中摆脱 Bootstrap 样式,你可以自由地使用 css 选项在 HTML 输出中应用任意的样式(如果你想在 HTML 头部/底部中包含任意的内容,还可以使用 includes 选项)。

3.1.4 Tufte 样式

和 Bootstrap 样式一样,Tufte 样式由输出格式 tufte_html_book() 提供,这也是 html_chapters() 的一个特例,使用 tufte::tufte_html() 作为基础格式。如果你不熟悉 Tufte 样式,请查阅 tufte 软件包(Xie and Allaire 2023)。你可以在这里阅读一个 tufte_html_book() 的例子:https://bookdown.org/yihui/bookdown-demo3/

基本上,它是一个左边是主栏,右边是边栏的布局。内容主体在主栏中,边栏用来放置脚注 (footnotes)、边注 (margin notes)、参考文献 (references) 和边栏图片 (margin figures) 等。

tufte_html_book() 的所有参数的含义与 html_book() 完全相同,例如,你同样也可以通过 css 配置项定制 CSS。然而,有一些元素是 Tufte 风格所特有的,如边注 (margin notes)、边栏图片 (margin figures) 和全宽图片 (full-width figures)。这些元素需要特殊的语法来生成;请查阅 tufte 软件包的文档。请注意,你不需要对脚注和参考文献做任何特殊处理(只需使用正常的 Markdown 语法 ^[footnote][@citation]),因为它们会被自动放到页边。一个关于 tufte_html_book 格式的简短 YAML 示例如下:

---
output:
  bookdown::tufte_html_book:
    toc: true
    css: toc.css
---

参考文献

Xie, Yihui, and JJ Allaire. 2023. Tufte: Tufte’s Styles for r Markdown Documents. https://github.com/rstudio/tufte.

  1. 要查看有关如何自动生成标识符的更多详细内容,请参阅 Pandoc 文档中 auto_identifiers 扩展相关内容 http://pandoc.org/MANUAL.html#header-identifiers↩︎

  2. : 之前插入的反斜杠是因为一个技术问题:我们要防止 Pandoc 将链接翻译为 HTML 代码 <a href="..."></a>。在 https://github.com/jgm/pandoc/issues/2139 上你能够看到更多细节↩︎