Skip to content

Commit

Permalink
fix #405 and fix #852: execute R scripts specified in before_chapter_…
Browse files Browse the repository at this point in the history
…script and after_chapter_scripts separately, instead of writing them into the Rmd files as code chunks
  • Loading branch information
yihui committed Jan 16, 2020
1 parent 2db085b commit 581bb63
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 23 deletions.
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Package: bookdown
Type: Package
Title: Authoring Books and Technical Documents with R Markdown
Version: 0.17.1
Version: 0.17.2
Authors@R: c(
person("Yihui", "Xie", role = c("aut", "cre"), email = "xie@yihui.name", comment = c(ORCID = "0000-0003-0645-5666")),
person("JJ", "Allaire", role = "ctb"),
Expand Down
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

- Cross-referencing works correctly now with `gitbook` when using `split_by: section` or `split_by: section+number` (thanks, @ThierryO, @cderv, #787)

- When using the Knit-and-Merge approach to compile a book (`new_session: true` in `_bookdown.yml`) and the fields `before_chapter_script` and/or `after_chapter_script` are configured in `_bookdown.yml`, the original Rmd files are no longer touched (thanks, @clauswilke #405 and @bob-carpenter https://stackoverflow.com/q/50554196/559676), and the scripts specified in `before/after_chapter_script` are no longer inserted into the Rmd files (they are read and evaluated separately), so the line numbers will be correct in case of **knitr** errors (thanks, @arencambre, #852).

# CHANGES IN bookdown VERSION 0.17

## NEW FEATURES
Expand Down
24 changes: 5 additions & 19 deletions R/render.R
Original file line number Diff line number Diff line change
Expand Up @@ -169,26 +169,12 @@ render_new_session = function(files, main, config, output_format, clean, envir,
# if input is index.Rmd or not preview mode, compile all Rmd's
rerun = !opts$get('preview') || identical(opts$get('input_rmd'), 'index.Rmd')
if (!rerun) rerun = files %in% opts$get('input_rmd')
add1 = insert_chapter_script(config, 'before')
add2 = insert_chapter_script(config, 'after')
add1 = merge_chapter_script(config, 'before')
add2 = merge_chapter_script(config, 'after')
on.exit(unlink(c(add1, add2)), add = TRUE)
# compile chapters in separate R sessions
for (f in files[rerun]) {
if (length(add1) + length(add2) == 0) {
Rscript_render(f, render_args, render_meta)
next
}
# first backup the original Rmd to a tempfile
f2 = tempfile('bookdown', '.', fileext = '.bak')
file.copy(f, f2, overwrite = TRUE)
# write add1/add2 to the original Rmd, compile it, and restore it
tryCatch({
txt = c(add1, read_utf8(f), add2)
write_utf8(txt, f)
Rscript_render(f, render_args, render_meta)
}, finally = {
if (file.copy(f2, f, overwrite = TRUE)) file.remove(f2)
})
}
for (f in files[rerun]) Rscript_render(f, render_args, render_meta, add1, add2)

if (!all(dirname(files_md) == '.'))
file.copy(files_md[!rerun], basename(files_md[!rerun]), overwrite = TRUE)

Expand Down
22 changes: 20 additions & 2 deletions R/utils.R
Original file line number Diff line number Diff line change
Expand Up @@ -163,12 +163,25 @@ insert_code_chunk = function(x, before, after) {
}

insert_chapter_script = function(config, where = 'before') {
script = config[[sprintf('%s_chapter_script', where)]]
script = get_chapter_script(config, where)
if (is.character(script)) {
c('```{r include=FALSE, cache=FALSE}', unlist(lapply(script, read_utf8)), '```')
c('```{r include=FALSE, cache=FALSE}', script, '```')
}
}

get_chapter_script = function(config, where) {
script = config[[sprintf('%s_chapter_script', where)]]
unlist(lapply(script, read_utf8))
}

merge_chapter_script = function(config, where) {
if (!is.character(script <- get_chapter_script(config, where)) || length(script) == 0)
return('')
f = tempfile(fileext = '.R')
write_utf8(script, f)
f
}

check_special_chars = function(filename) {
reg = rmarkdown:::.shell_chars_regex
for (i in grep(reg, filename)) warning(
Expand All @@ -186,6 +199,11 @@ Rscript_render = function(file, ...) {
if (Rscript(args) != 0) stop('Failed to compile ', file)
}

source_utf8 = function(file) {
if (file == '') return()
eval(xfun::parse_only(read_utf8(file)), envir = globalenv())
}

clean_meta = function(meta_file, files) {
meta = readRDS(meta_file)
for (i in setdiff(names(meta), files)) meta[[i]] = NULL
Expand Down
7 changes: 6 additions & 1 deletion inst/scripts/render_one.R
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
# compile an Rmd file without running Pandoc; arguments are passed from Rscript;
# the three arguments are 1) the Rmd filename; 2) the render arguments; 3) the
# filename to save the returned value of render()
# filename to save the returned value of render(); 4) before_chapter_script; 5)
# after_chapter_script
library(methods)
local({
args = commandArgs(TRUE)

bookdown:::source_utf8(args[4])
out = do.call(
rmarkdown::render, c(args[1], readRDS(args[2]), list(run_pandoc = FALSE, encoding = 'UTF-8'))
)
bookdown:::source_utf8(args[5])

out_expected = xfun::with_ext(args[1], '.md')
if (out != out_expected) {
file.rename(out, out_expected)
Expand Down

0 comments on commit 581bb63

Please sign in to comment.