Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: new override argument to pass metadata #52

Merged
merged 4 commits into from
Oct 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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")
)
})