Skip to content

Commit

Permalink
feat: new override argument to pass metadata (#52)
Browse files Browse the repository at this point in the history
Co-authored-by: Christophe Dervieux <christophe.dervieux@gmail.com>
  • Loading branch information
mcanouil and cderv committed Oct 12, 2023
1 parent b93ce9e commit 589c937
Show file tree
Hide file tree
Showing 10 changed files with 136 additions and 15 deletions.
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: quarto
Title: R Interface to 'Quarto' Markdown Publishing System
Version: 1.3.1
Version: 1.3.2
Authors@R:
person("JJ", "Allaire", , "jj@rstudio.com", role = c("aut", "cre"),
comment = c(ORCID = "0000-0003-0174-9868"))
Expand Down
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# quarto (development version)

* Add `metadata` and `metadata_file` to `quarto_render()` to pass modify Quarto metadata from calling render. If both are set, `metadata` will be merged over `metadata_file` content. Internally, metadata will be passed as a `--metadata-file` to `quarto render` (thanks, @mcanouil, #52, @maelle, #49).

* Added a `NEWS.md` file to track changes to the package.

* `execute_params` in `quarto_render()` now converts boolean value to `true/false` correctly as expected by `quarto render` (thanks, @marianklose, #124).
33 changes: 26 additions & 7 deletions R/render.R
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,15 @@
#' @param use_freezer Force use of frozen computations for an incremental
#' file render.
#' @param cache Cache execution output (uses knitr cache and jupyter-cache
#' respectively for Rmd and Jupyter input files).
#' respectively for Rmd and Jupyter input files).
#' @param cache_refresh Force refresh of execution cache.
#' @param metadata An optional named list used to override YAML
#' metadata. It will be passed as a YAML file to `--metadata-file` CLI flag.
#' This will be merged over `metadata-file` options if both are
#' specified.
#' @param metadata_file A yaml file passed to `--metadata-file` CLI flags to
#' overrite metadata. This will be merged with `metadata` if both are
#' specified, with low precedence on `metadata` options.
#' @param debug Leave intermediate files in place after render.
#' @param quiet Suppress warning and other messages.
#' @param pandoc_args Additional command line options to pass to pandoc.
Expand All @@ -48,6 +55,9 @@
#'
#' # Render Jupyter Markdown
#' quarto_render("notebook.md")
#'
#' # Override metadata
#' quarto_render("notebook.Rmd", override = list(lang = "fr", echo = "false"))
#' }
#' @export
quarto_render <- function(input = NULL,
Expand All @@ -62,6 +72,8 @@ quarto_render <- function(input = NULL,
use_freezer = FALSE,
cache = NULL,
cache_refresh = FALSE,
metadata = NULL,
metadata_file = NULL,
debug = FALSE,
quiet = FALSE,
pandoc_args = NULL,
Expand Down Expand Up @@ -136,6 +148,19 @@ quarto_render <- function(input = NULL,
if (isTRUE(cache_refresh)) {
args <- c(args, "--cache-refresh")
}
# metadata to pass to quarto render
if (!missing(metadata)) {
# We merge meta if there is metadata_file passed
if (!missing(metadata_file)) {
metadata <- merge_list(yaml::read_yaml(metadata_file, eval.expr = FALSE), metadata)
}
meta_file <- tempfile(pattern = "quarto-meta", fileext = ".yml")
on.exit(unlink(meta_file), add = TRUE)
write_yaml(metadata, meta_file)
args <- c(args, "--metadata-file", meta_file)
} else if (!missing(metadata_file)) {
args <- c(args, "--metadata-file", metadata_file)
}
if (isTRUE(debug)) {
args <- c(args, "--debug")
}
Expand All @@ -152,9 +177,3 @@ quarto_render <- function(input = NULL,
# no return value
invisible(NULL)
}






7 changes: 7 additions & 0 deletions R/utils.R
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,10 @@ write_yaml <- function(x, file) {
})
yaml::write_yaml(x, file, handlers = handlers)
}


# inline knitr:::merge_list()
merge_list <- function(x, y) {
x[names(y)] <- y
x
}
14 changes: 14 additions & 0 deletions man/quarto_render.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions tests/testthat/_snaps/render/metadata-file.test.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Pandoc
Meta
{ unMeta =
fromList [ ( "title" , MetaInlines [ Str "test" ] ) ]
}
[ Para [ Str "content" ] ]
6 changes: 6 additions & 0 deletions tests/testthat/_snaps/render/metadata-merged.test.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Pandoc
Meta
{ unMeta =
fromList [ ( "title" , MetaInlines [ Str "test2" ] ) ]
}
[ Para [ Str "content" ] ]
6 changes: 6 additions & 0 deletions tests/testthat/_snaps/render/metadata.test.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Pandoc
Meta
{ unMeta =
fromList [ ( "title" , MetaInlines [ Str "test" ] ) ]
}
[ Para [ Str "content" ] ]
39 changes: 33 additions & 6 deletions tests/testthat/helper.R
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,49 @@ skip_if_quarto <- function() {
local_qmd_file <- function(..., .env = parent.frame()) {
skip_if_not_installed("xfun")
skip_if_not_installed("withr")
path <- withr::local_tempfile(.local_envir = .env, fileext = ".qmd")
# create a directory to delete for correct cleaning
dir <- withr::local_tempdir("quarto-test", .local_envir = .env)
# create a file in this directory
path <- withr::local_tempfile(tmpdir = dir, fileext = ".qmd", .local_envir = .env)
xfun::write_utf8(c(...), path)
path
}

.render <- function(input, ...) {
.render <- function(input, output_file = NULL, ..., .env = parent.frame()) {
skip_if_no_quarto()
output_file <- xfun::with_ext(basename(input), "test.out")
quarto_render(input, output_file = output_file, quiet = TRUE, ...)
output_file
skip_if_not_installed("withr")
# work inside input directory
withr::local_dir(dirname(input))
if (is.null(output_file)) {
output_file <- basename(withr::local_file(
xfun::with_ext(input, "test.out"),
.local_envir = .env
))
}
quarto_render(basename(input), output_file = output_file, quiet = TRUE, ...)
expect_true(file.exists(output_file))
normalizePath(output_file)
}

.render_and_read <- function(input, ...) {
skip_if_not_installed("xfun")
skip_if_not_installed("withr")
out <- .render(input, ...)
withr::local_dir(dirname(input))
xfun::read_utf8(out)
}

expect_snapshot_qmd_output <- function(name, input, output_file = NULL, ...) {
local_edition(3)
skip_if_not_installed("xfun")
name <- xfun::with_ext(name, ".test.out")

# Announce the file before touching `code`. This way, if `code`
# unexpectedly fails or skips, testthat will not auto-delete the
# corresponding snapshot file.
announce_snapshot_file(name = name)

# render with quarto and snapshot
output_file <- .render(input, output_file, ...)

expect_snapshot_file(output_file, name)
}
36 changes: 35 additions & 1 deletion tests/testthat/test-render.R
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

test_that("An error is reported when Quarto is not installed", {
skip_if_quarto()
expect_error(quarto_render("test.Rmd"))
Expand All @@ -11,3 +10,38 @@ test_that("R Markdown documents can be rendered", {
expect_true(file.exists("test.html"))
unlink("test.html")
})

test_that("metadata argument works in quarto_render", {
skip_if_no_quarto()
qmd <- local_qmd_file(c("content"))
# metadata
expect_snapshot_qmd_output(name = "metadata", input = qmd, output_format = "native", metadata = list(title = "test"))
})

test_that("metadata-file argument works in quarto_render", {
skip_if_no_quarto()
skip_if_not_installed("withr")
qmd <- local_qmd_file(c("content"))
yaml <- withr::local_tempfile(fileext = ".yml")
write_yaml(list(title = "test"), yaml)
expect_snapshot_qmd_output(
name = "metadata-file",
input = qmd,
output_format = "native",
metadata_file = yaml
)
})

test_that("metadata-file and metadata are merged in quarto_render", {
skip_if_no_quarto()
skip_if_not_installed("withr")
qmd <- local_qmd_file(c("content"))
yaml <- withr::local_tempfile(fileext = ".yml")
write_yaml(list(title = "test"), yaml)
expect_snapshot_qmd_output(
name = "metadata-merged",
input = qmd,
output_format = "native",
metadata_file = yaml, metadata = list(title = "test2")
)
})

0 comments on commit 589c937

Please sign in to comment.