-
Notifications
You must be signed in to change notification settings - Fork 2
/
04-customization.Rmd
263 lines (194 loc) · 12.9 KB
/
04-customization.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
# 定制化 {#customization}
正如我们在本书的开头中所提到的,你应该对 R Markdown 有一些基本的了解,并且我们一直在重点介绍 **bookdown** 而不是 **rmarkdown** 的特性。事实上,R Markdown 是高度可定制的,你可以使用许多选项来定制输出文档。根据你希望自定义输出文档的程度,你可以在 YAML 元数据中使用一些简单的选项,或者只替换整个 Pandoc 模板。
## YAML 选项 {#yaml-options}
\index{YAML}  对于大多数类型的输出格式来说,你可以使用特定格式的 `highlight` 选项自定义语法高亮样式,可用的样式为 `r knitr::combine_words(rmarkdown:::highlighters(), before='\x60', sep='、', and=" 和 ", oxford_comma=FALSE)`。例如,你可以为 `gitbook` 格式选择 `tango` 样式:
```yaml
---
output:
bookdown::gitbook:
highlight: tango
---
```
对于 HTML\index{HTML} 输出格式,你最有可能使用 `css` 选项来提供自己的 CSS\index{CSS} 样式表,以自定义 HTML 元素的外观。有一个 `includes` 选项能够适用于更多格式,包括 HTML 和 LaTeX。`includes` 选项允许你在输出文档之前和/或之后插入任意自定义的内容。它有三个子选项:`in_header`、`before_body` 和 `after_body`。你需要了解 HTML 或 LaTeX 文档的基本结构才能理解这些选项。HTML 文件源文本如下所示:
```html
<html>
<head>
<!-- 这里放置首部内容,例如 CSS 和 JS -->
</head>
<body>
<!-- 这里放置正文内容 -->
</body>
</html>
```
`in_header` 选项接受一个文件路径然后将文件内容插入到 `<head>` 标签之间。`before_body` 所指文件将会被插入到 `<body>` 标签的正下方,`after_body` 所指文件将会被插入到 `</body>` 标签之前。
一个 LaTeX\index{LaTeX} 源文档有着相似的结构:
```latex
\documentclass{book}
% LaTeX 导言 (preamble)
% 这里插入 in_header
\begin{document}
% 这里插入 before_body
% 这里是正文内容
% 这里插入 after_body
\end{document}
```
`includes` 选项非常有用且使用灵活。对于 HTML 输出,它意味着你能够将任意 HTML 代码插入到输出中。例如,当你在 HTML 输出中通过 MathJax\index{MathJax} 库渲染 LaTeX 数学表达式,并希望方程编号显示在左侧(默认显示在右侧),你可以创建一个包含有以下代码的文本文件:
```html
<script type="text/x-mathjax-config">
MathJax.Hub.Config({
TeX: { TagSide: "left" }
});
</script>
```
让我们假设文件名为 `mathjax-number.html`,并且它位于你的书籍的根目录下(包含有你的全部 Rmd 文件的目录)。你可以通过 `in_header` 选项将该文件插入到 HTML 首部,例如:
```yaml
---
output:
bookdown::gitbook:
includes:
in_header: mathjax-number.html
---
```
另一个例子是在 HTML 页面上启用评论区或讨论区。有这么几种可能的选择,例如:Disqus (https://disqus.com) 或 Hypothesis (https://hypothes.is)。这些服务可以通过 `includes` 选项轻松地嵌入到你的 HTML 书籍中(有关更多详细信息,请参阅第 \@ref(collaboration) 节)。
类似地,如果你熟悉 LaTeX,则可以在导言 (preamble) 中添加任意 LaTeX 代码。这意味着你可以使用任何 LaTeX 软件包,并为书籍设置任何软件包选项。例如,本书通过 `in_header` 选项使用了更多的 LaTeX 软件包,如 **booktabs**(用于更美观的表格)和 **longtable**(用于跨多个页面的表格),并对图形环境中的链接不起作用的 XeLeTeX 问题进行了修复:
> 中文版还使用了 **ctex** 软件包以在 PDF 输出中渲染中文字符。
```latex
\usepackage{booktabs}
\usepackage{longtable}
\ifxetex
\usepackage{letltxmacro}
\setlength{\XeTeXLinkMargin}{1pt}
\LetLtxMacro\SavedIncludeGraphics\includegraphics
\def\includegraphics#1#{% #1 catches optional stuff (star/opt. arg.)
\IncludeGraphicsAux{#1}%
}%
\newcommand*{\IncludeGraphicsAux}[2]{%
\XeTeXLinkBox{%
\SavedIncludeGraphics#1{#2}%
}%
}%
\fi
```
上述 LaTeX 代码保存在文件 `preamble.tex` 中,而书籍的 YAML 元数据如下所示:
```yaml
---
output:
bookdown::pdf_book:
includes:
in_header: preamble.tex
---
```
## 更换主题
有时你可能想要更改输出的整体主题,这通常可以通过上一节叙述的 `in_header` 选项或 `css` 选项(如果输出格式为 HTML)来完成。一些输出格式有它们独特的主题,例如 `gitbook`、`tufte_html_book` 和 `tufte_book2`,而你可能不想过多地自定义这些主题。相比之下,输出格式 `html_book()` 和 `pdf_book` 不受到特定主题的约束,更具有定制性。
如第 \@ref(bootstrap-style) 节所述,`html_book()` 的默认样式是 Bootstrap 样式。Bootstrap 样式实际上有一些可以使用的内置主题,包括 `r knitr::combine_words(rmarkdown:::themes(), before='\x60', sep='、', and=" 和 ", oxford_comma=FALSE)`。你可以通过 `theme` 选项设定主题,例如:
```yaml
---
output:
bookdown::html_book:
theme: united
---
```
如果你不喜欢上述任何一个 Bootstrap 主题,你可以将 `theme` 设置为 `null`,然后通过 `css` 或 `includes` 选项应用你自己的 CSS。
对于 `pdf_book()`,除了上一节提到的 `in_header` 选项,另一个方法是改变文档类 (document calss)。对于书籍来说有许多可用的 LaTeX 类,例如 **memoir** (https://www.ctan.org/pkg/memoir)、**amsbook** (https://www.ctan.org/pkg/amsbook)、KOMA-Script (https://www.ctan.org/pkg/koma-script) 等等。以下是在 YAML 元数据中指定 KOMA-Script 软件包中的 `srcbook` 类的一个简要的示例:
```yaml
---
documentclass: scrbook
output:
bookdown::pdf_book:
template: null
---
```
一些出版商(例如 Springer 和 Chapman & Hall/CRC)有他们自己的 LaTeX 样式或类文件。你可以尝试更改 `documentclass` 选项来使用他们的文档类,尽管通常情况下并非如此简单。你最终可能会使用 `in_header`,甚至设计一个自定义的 Pandoc LaTeX 模板来容纳这些文档类。
请注意,当你更改 `documentclass` 时,你可能会指定一个额外的 Pandoc 参数 `--top-level-division=chapter` 以便 Pandoc 知道应该将第一级标题视为章而不是小节(这是在 `documentclass` 为 `book` 时的默认值),例如:
```yaml
documentclass: krantz
output:
bookdown::pdf_book:
pandoc_args: --top-level-division=chapter
```
## 模板
当 Pandoc 将 Markdown 转换为另一种输出格式时,它在幕后使用模板\index{Pandoc template}。模板是一个纯文本文件,其中包含一些格式为 `$variable$` 的变量。这些变量将由 Pandoc 生成的值替换。下面是一个非常简短的 HTML 输出模板:
```html
<html>
<head>
<title>$title$</title>
</head>
<body>
$body$
</body>
</html>
```
它有两个变量 `title` 和 `body`。`title` 的值来自 YAML 元数据的 `title` 字段,`body` 是从 Markdown 输入文档的正文生成的 HTML 代码。例如,假设我们有一个 Markdown 文档:
```markdown
---
title: 一本好书
---
# 简介
这是一本**优秀的**书!
```
如果我们使用上述文档生成 HTML 文档,其源代码如下:
```html
<html>
<head>
<title>一本好书</title>
</head>
<body>
<h1>简介</h1>
<p>这是一本<strong>优秀的</strong>书!</p>
</body>
</html>
```
实际的 HTML、LaTeX 和 EPUB 模板更加复杂,但其中的核心思想是一样的。你需要知道哪些变量可以使用:有些变量是内置的 Pandoc 变量,有些可以由用户在 YAML 元数据中定义,或者从命令行选项 `-V` 或 `--variable` 传递。某些变量仅在特定的输出格式中有意义,例如,`documentclass` 变量仅用于 LaTeX 输出。请参阅 Pandoc 文档以了解有关这些变量的更多信息,你可以在 GitHub 存储库 <https://github.com/jgm/pandoc-templates> 中找到所有默认的 Pandoc 模板。
请注意,对于 HTML 输出,**bookdown** 需要模板中的一些附加注释标记,我们已经在第 \@ref(bootstrap-style) 节中对它们进行了解释。
## 配置 {#configuration}
我们以尽在第 \@ref(usage) 节中提到了 `rmd_files`,并且你可以在 `_bookdown.yml`\index{\_bookdown.yml} 中为书籍配置更多(可选的)设置。^[对于 [`bs4_book()`](#bs4-book) 格式,`edit`、`history` 和 `view` 字段不会起作用,可以使用输出函数的 [repo](#specifying-the-repository) 参数来指定类似的配置。]:
- `book_filename`: 主 Rmd 文件的文件名,即从所有章节进行合并后的单个 Rmd 文件;默认情况下,它被命名为 `_main.Rmd`。
- `delete_merged_file`: 书籍成功编译后是否删除主 Rmd 文件。
- `before_chapter_script`: 在每个章节之前执行的一个或多个 R 脚本,例如,你可能希望在编译每个章节之前清理工作区,在这种情况下可以在 R 脚本中使用 `rm(list = ls(all = TRUE))`。
- `after_chapter_script`: 与 `before_chapter_script` 类似,不过 R 脚本是在每一个章节编译完成后执行。
- `edit`: 协作者可以单击后直接编辑当前页面 Rmd 源文档的链接;这主要是为 GitHub 存储库设计的,因为在 GitHub 上编辑任意纯文本文件很容易,即使在其他人的存储库中也是如此(如果你没有对存储库的写入权限,GitHub 将自动为其分叉,并允许你在编辑完文件后提交拉取请求 (pull request))。这个链接中应包含 `%s`,它将被每个页面的实际 Rmd 文件名替换。
- `history`: 类似于 `edit`,它是一个指向当前页面编辑/提交历史记录的链接。
- `view`: 类似于 `edit`,它是一个指向当前页面源代码的链接。
- `rmd_subdir`: 是否在子目录中搜索书籍 Rmd 源文件(默认情况下仅搜索根目录)。它可以是一个布尔值(例如,如果设为 `true`,则将在项目目录和所有子目录中搜索书记的 Rmd 源文件),如果要在子目录的子集中搜索书籍的 Rmd 源文件,它也可以是一个路径列表。
- `include_md`: 在搜索数据源文件时包含 `.md` 文件(默认情况下只会包含 `.Rmd` 文件)。
- `output_dir`: 书籍的输出目录(默认为 `_book`);`render_book()` 将会读取并使用这个设置。
- `clean`: `clean_book()` 函数将要清理的文件和目录的向量。
下面是一个简短的 `_bookdown.yml`:
```yaml
book_filename: "my-book.Rmd"
delete_merged_file: true
before_chapter_script: ["script1.R", "script2.R"]
after_chapter_script: "script3.R"
view: https://github.com/rstudio/bookdown-demo/blob/master/%s
edit: https://github.com/rstudio/bookdown-demo/edit/master/%s
output_dir: "book-output"
clean: ["my-book.bbl", "R-packages.bib"]
```
## 国际化 {#internationalization}
如果你的书籍的语言不是英语,那么可能需要将某些英语单词和短语翻译成你使用的语言,例如在 HTML 输出中自动编号数字/表格时的单词“Figure”和“Table”。国际化可能不是 LaTeX 输出的问题,因为一些 LaTeX 软件包可以自动将这些术语翻译成本地语言,例如 **ctexcap** 中文软件包。
对于非 LaTeX 输出,你可以在配置文件 `_bookdown.yml` 中设置 `language` 字段。目前默认的设置为:
```{r echo=FALSE, comment='', results='asis'}
cat('```yaml\n')
cat(yaml::as.yaml(list(language = list(
label = c(bookdown:::label_names, bookdown:::label_names_math2),
ui = bookdown:::ui_names
))
))
cat('```')
```
例如,如果你想要将使用 `FIGURE x.x` 而不是 `Figure x.x`,你可以将 `fig` 更改为 `"FIGURE "`:
```yaml
language:
label:
fig: "FIGURE "
```
`ui` 下的字段用于指定用户界面中的某些术语。`edit` 字段指定在 `_bookdown.yml`(第 \@ref(configuration) 节)中提到的 `edit` 链接相关联的文本。`chapter_name`、`appendix_name`、`fig`、`tab` 和 `eq` 字段可以是要在篇章或引用编号前加入的字符串(例如 `CHAPTER` 或 `FIGURE`),也可以是一个以接受数字(篇章或引用编号)输入并返回一个字符串的 R 函数(例如 `!expr function(i) paste('Chapter', i)`)。以下是匈牙利语的一个例子:
```yaml
language:
label:
fig: !expr function(i) paste(i, 'ábra')
ui:
chapter_name: !expr function(i) paste0(i, '. fejezet')
```
仅仅对于 `chapter_name` 和 `appendix_name`,如果它是长度为 2 的字符向量,则章节标题前缀将为 `paste0(chapter_name[1], i, chapter_name[2])`,其中 `i` 是章节编号。
当你使用使用多字节字符(如中文、日文和韩文 (CJK))的语言编写时会有一个警告:Pandoc 无法从纯 CJK 字符的章节标题中生成标识符,因此你将无法交叉引用章节(它们没有标签),除非你通过将 `{#identifier}` 附加到章节标题来手动为其分配标识符,其中 `identifier` 是你选择的标识符。