在rstudio/knitr文档中导入通用YAML
我有一些Rmd文件,除了标题之外,所有这些文件都具有相同的YAML frontmatter如何将此frontmatter保存在一个文件中并用于所有文档?它越来越大,我不想每次调整frontmatter时都将每个文件保持同步 我想继续在rstudio/knitr文档中导入通用YAML,r,knitr,r-markdown,R,Knitr,R Markdown,我有一些Rmd文件,除了标题之外,所有这些文件都具有相同的YAML frontmatter如何将此frontmatter保存在一个文件中并用于所有文档?它越来越大,我不想每次调整frontmatter时都将每个文件保持同步 我想继续 使用RStudio中的Knit按钮/Ctrl+Shift+K快捷键进行编译 保持整个设置的可移植性:希望避免编写自定义输出格式或覆盖rstudio.markdownToHTML(因为这也需要我随身携带.Rprofile) 例子 common.yaml: auth
- 使用RStudio中的Knit按钮/Ctrl+Shift+K快捷键进行编译
- 保持整个设置的可移植性:希望避免编写自定义输出格式或覆盖
(因为这也需要我随身携带rstudio.markdownToHTML
).Rprofile
author: me
date: "`r format (Sys.time(), format='%Y-%m-%d %H:%M:%S %z')`"
link-citations: true
reference-section-title: References
# many other options
示例文档
----
title: On the Culinary Preferences of Anthropomorphic Cats
----
I do not like green eggs and ham. I do not like them, Sam I Am!
期望输出:
已编译的示例文档(即HTML或PDF),已使用common.yaml
中插入的元数据进行编译。YAML中的R代码(在本例中为日期)将被编译为额外代码,但这并不是必需的(我只将其用于我并不真正需要的日期)
选择/解决方案?
这些东西我还没有完全做好
- 使用rmarkdown可以创建一个
来放置常见的yaml元数据,但这会将所有元数据放在yaml中的\u output.yaml
下,因此只适用于output:
和html\u文档:
下的选项,而不适用于作者、日期等内容pdf\u文档:
- 编写knitr块以导入YAML,例如
如果我---- title: On the Culinary Preferences of Anthropomorphic Cats ```{r echo=F, results='asis'} cat(readLines('common.yaml'), sep='\n') ``` ---- I do not like green eggs and ham. I do not like them, Sam I Am!
,然后knitr('input.Rmd')
输出,这就行得通,但如果我使用Rstudio中的Knit按钮(我假设它调用pandoc
),则不行,因为这会在运行knitr之前首先解析元数据,直到knitr运行之前元数据的格式都不正确render
- Makefile:如果我足够聪明,我可以编写一个Makefile或其他东西,将
注入common.yaml
,然后运行input.Rmd
,并以某种方式将其连接到Rstudio的Knit按钮,也许可以将这个Rstudio配置保存到rmarkdown::render()
文件中,这样整个东西就可以移植,而无需我也编辑.Rproj
。但我不够聪明.Rprofile
编辑:我尝试了最后一个选项,并将一个生成文件连接到Build命令(Ctrl+Shift+B)。但是,每次我通过Ctrl+Shift+B使用它时,这将构建相同的目标,我希望构建与我当前在编辑器中打开的Rmd文件相对应的目标[对于Ctrl+Shift+K]。找到了两个可移植的选项(即不
。需要定制Rprofile
YAML frontmatter的最小重复):
knit:
属性设置为您自己的函数,以便更好地控制Ctrl+Shift+K时发生的情况common.yaml
:
---
author: me
date: "`r format (Sys.time(), format='%Y-%m-%d %H:%M:%S %z')`"
link-citations: true
reference-section-title: References
---
注意它是完整的,即需要--
然后在文档中,您可以将YAML指定为pandoc的最后一个参数,它将应用YAML(请参阅)
在示例.rmd
中:
---
title: On the Culinary Preferences of Anthropomorphic Cats
output:
html_document:
pandoc_args: './common.yaml'
---
I do not like green eggs and ham. I do not like them, Sam I Am!
---
title: On the Culinary Preferences of Anthropomorphic Cats
knit: (function (...) { source('myknit.r'); myknit(...) })
---
I do not like green eggs and ham. I do not like them, Sam I Am!
您甚至可以将html\u文档:
内容放在\u输出中。yaml
因为rmarkdown
会将其放在该文件夹中所有文档的output:
下。通过这种方式,使用此frontmatter的所有文档之间可以无YAML复制
优点:
- 没有YAML frontmatter的重复
- 非常干净
- 通用YAML没有通过knit,因此上面的日期字段将不会被解析。您将获得文字字符串“r格式(Sys.time(),格式=“%Y-%m-%d%H:%m:%S%z”)作为日期
- 来自同一github问题: 首先看到的元数据定义将保持不变,即使在以后解析冲突数据也是如此
knit
命令
这允许进行更大的控制,尽管有点麻烦/棘手
并在rmarkdown中提到一个未记录的功能:点击Rstudio的“knit”按钮时,将执行YAML的knit:
部分
简言之:
myknit(inputFile,encoding)
,该函数将读取YAML,将其放入RMD并对结果调用render
。保存在自己的文件中myknit.r
example.rmd
的YAML中,添加
knit: (function (...) { source('myknit.r'); myknit(...) })
似乎必须在一条线上。source('myknit.r')
而不是将函数定义放在YAML中的原因是为了可移植性。如果我修改myknit.r
,我就不必修改每个文档的YAML。这样,所有文档必须在其前端重复的唯一常见YAML是knit
行;所有其他通用YAML可以保留在common.YAML
中
可能只是对myknit
的系统调用,如果我有makefile设置的话make
- 注入的YAML将通过
传递,因此被编织,因为它是在调用rmarkdown
之前注入的render
- 预览窗口:只要
生成一条(单个)消息myknit
,文件就会显示在预览窗口中 我发现输出中只能有一条这样的消息,或者没有预览窗口。因此,如果使用Output created:path/to/file.html
(生成一个“Output created:basename.extension”)消息,并且最终生成的文件实际上在别处,那么render
author: me date: "`r format (Sys.time(), format='%Y-%m-%d %H:%M:%S %z')`" link-citations: true reference-section-title: References
myknit <- function (inputFile, encoding, yaml='common.yaml') { # read in the YAML + src file yaml <- readLines(yaml) rmd <- readLines(inputFile) # insert the YAML in after the first --- # I'm assuming all my RMDs have properly-formed YAML and that the first # occurence of --- starts the YAML. You could do proper validation if you wanted. yamlHeader <- grep('^---$', rmd)[1] # put the yaml in rmd <- append(rmd, yaml, after=yamlHeader) # write out to a temp file ofile <- file.path(tempdir(), basename(inputFile)) writeLines(rmd, ofile) # render with rmarkdown. message(ofile) ofile <- rmarkdown::render(ofile, encoding=encoding, envir=new.env()) # copy back to the current directory. file.copy(ofile, file.path(dirname(inputFile), basename(ofile)), overwrite=T) }
title: "Crime and Punishment" author: "Fyodor Dostoevsky"
--- output: html_document: pandoc_args: ["--metadata-file=header.yaml"] ---