Skip to content

Commit 0de1064

Browse files
authored
Add write_yaml_metadata_block() to add new YAML metadata block to a qmd file (#252)
* Add write_yaml_metadata_block() to add new YAML metadata block to a qmd file * Add to pkgdown * document output: asis constraint * Add a vignette about this new function * Add NEWS * bump version
1 parent 03019b9 commit 0de1064

File tree

11 files changed

+590
-11
lines changed

11 files changed

+590
-11
lines changed

DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Package: quarto
22
Title: R Interface to 'Quarto' Markdown Publishing System
3-
Version: 1.4.4.9014
3+
Version: 1.4.4.9015
44
Authors@R: c(
55
person("JJ", "Allaire", , "[email protected]", role = "aut",
66
comment = c(ORCID = "0000-0003-0174-9868")),

NAMESPACE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export(theme_colors_ggplot2)
3030
export(theme_colors_gt)
3131
export(theme_colors_plotly)
3232
export(theme_colors_thematic)
33+
export(write_yaml_metadata_block)
3334
import(rlang)
3435
importFrom(cli,cli_abort)
3536
importFrom(cli,cli_inform)

NEWS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# quarto (development version)
22

3+
- Added `write_yaml_metadata_block()` function to dynamically set YAML metadata in Quarto documents from R code chunks. This addresses the limitation where Quarto metadata must be static and defined in the document header. The function enables conditional content and metadata-driven document behavior based on R computations (thanks, @kmasiello, #137, #160).
4+
35
- Added debugging logic for quarto vignette engine to help diagnose issues with Quarto vignettes in **pkgdown** and other context (thanks, @hadley, #185).
46
Set `quarto.log.debug = TRUE` to enable debugging messages (or `R_QUARTO_LOG_DEBUG = TRUE` environment variable).
57
Set `quarto.log.file` to change the file path to write to (or `R_QUARTO_LOG_FILE` environment variable). Default will be `./quarto-r-debug.log`

R/blog.R

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,9 @@
1717
#' @return The path to the index file.
1818
#' @export
1919
#' @examples
20-
#' \dontrun{
21-
#' \donttest{
20+
#' \dontrun{\donttest{
2221
#' new_blog_post("making quarto blog posts", categories = c("R"))
23-
#'
24-
#' }
25-
#' }
22+
#' }}
2623
#'
2724
new_blog_post <- function(
2825
title,

R/metadata.R

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
#' Write YAML Metadata Block for Quarto Documents
2+
#'
3+
#' Creates a YAML metadata block that can be dynamically inserted into Quarto
4+
#' documents from R code chunks. This allows setting metadata values based on
5+
#' R computations, which can then be used with Quarto's conditional content
6+
#' features like `when-meta` and `{{< meta >}}` shortcodes.
7+
#'
8+
#' @param ... Named arguments to include in the metadata block. Names become
9+
#' the metadata keys and values become the metadata values. These take
10+
#' precedence over any conflicting keys in `.list`.
11+
#' @param .list Optional list of additional metadata to include. This is useful
12+
#' when you have metadata stored in a list variable. Keys in `.list` are
13+
#' overridden by any matching keys provided in `...`.
14+
#'
15+
#' @return A character string containing the formatted YAML metadata block,
16+
#' wrapped with `knitr::asis_output()` so it renders as raw markdown.
17+
#' Returns `NULL` invisibly if no metadata is provided.
18+
#'
19+
#' @details
20+
#' The function converts R values to YAML format and wraps them in YAML
21+
#' delimiters (`---`). Logical values are converted to lowercase strings
22+
#' ("true"/"false") to ensure compatibility with Quarto's metadata system.
23+
#'
24+
#' When both `...` and `.list` contain the same key, the value from `...`
25+
#' takes precedence and will override the value from `.list`.
26+
#'
27+
#' If no metadata is provided (empty `...` and `NULL` or empty `.list`),
28+
#' the function returns `NULL` without generating any output.
29+
#'
30+
#' **Important**: When using this function in Quarto documents, you must set
31+
#' the chunk option `output: asis` (or `#| output: asis`) for the metadata
32+
#' block to be properly processed by Quarto.
33+
#'
34+
#' This addresses the limitation where Quarto metadata must be static and
35+
#' cannot be set dynamically from R code during document rendering.
36+
#'
37+
#' @examples
38+
#' \dontrun{
39+
#' # In a Quarto document R chunk with `#| output: asis`:
40+
#' admin <- TRUE
41+
#' user_level <- "advanced"
42+
#'
43+
#' # Set metadata dynamically
44+
#' write_yaml_metadata_block(
45+
#' admin = admin,
46+
#' level = user_level,
47+
#' timestamp = Sys.Date()
48+
#' )
49+
#'
50+
#' # Use with .list parameter
51+
#' metadata_list <- list(version = "1.0", debug = FALSE)
52+
#' write_yaml_metadata_block(.list = metadata_list)
53+
#'
54+
#' # Direct arguments override .list values
55+
#' base_config <- list(theme = "dark", debug = TRUE)
56+
#' write_yaml_metadata_block(
57+
#' debug = FALSE, # This overrides debug = TRUE from base_config
58+
#' author = "John",
59+
#' .list = base_config
60+
#' )
61+
#'
62+
#' # Then use in Quarto with conditional content:
63+
#' # ::: {.content-visible when-meta="admin"}
64+
#' # Admin-only content here
65+
#' # :::
66+
#' }
67+
#'
68+
#' @section Quarto Usage:
69+
#' To use this function in a Quarto document, create an R code chunk with
70+
#' the `output: asis` option:
71+
#'
72+
#' ```
73+
#' ```{r}
74+
#' #| output: asis
75+
#' write_yaml_metadata_block(admin = TRUE, version = "1.0")
76+
#' ```
77+
#' ```
78+
#'
79+
#' Without the `output: asis` option, the YAML metadata block will be
80+
#' displayed as text rather than processed as metadata by Quarto.
81+
#'
82+
#'
83+
#' @export
84+
write_yaml_metadata_block <- function(..., .list = NULL) {
85+
meta <- list(...)
86+
if (!is.null(.list)) {
87+
meta <- merge_list(.list, list(...))
88+
}
89+
if (length(meta) == 0) {
90+
return()
91+
}
92+
res <- as_yaml(meta)
93+
yaml_block <- paste0("---\n", res, "---\n")
94+
knitr::asis_output(yaml_block)
95+
}

_pkgdown.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,9 @@ reference:
5555
contents:
5656
- starts_with("theme_colors")
5757
- starts_with("theme_brand")
58+
59+
- title: "Miscellaneous"
60+
desc: >
61+
These functions are used to help with Quarto documents and projects:
62+
contents:
63+
- write_yaml_metadata_block

man/new_blog_post.Rd

Lines changed: 2 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/write_yaml_metadata_block.Rd

Lines changed: 95 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/_snaps/metadata.md

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# write_yaml_metadata_block handles complex data types
2+
3+
Code
4+
cat(write_yaml_metadata_block(title = "Complex Test", date = current_date,
5+
count = 42L, rate = 3.14, tags = c("r", "quarto", "test")))
6+
Output
7+
---
8+
title: Complex Test
9+
date: 20262.0
10+
count: 42
11+
rate: 3.14
12+
tags:
13+
- r
14+
- quarto
15+
- test
16+
---
17+
18+
# write_yaml_metadata_block handles nested lists
19+
20+
Code
21+
cat(write_yaml_metadata_block(format = list(html = list(toc = TRUE, theme = "bootstrap"),
22+
pdf = list(documentclass = "article"))))
23+
Output
24+
---
25+
format:
26+
html:
27+
toc: true
28+
theme: bootstrap
29+
pdf:
30+
documentclass: article
31+
---
32+
33+
# write_yaml_metadata_block overrides .list with direct arguments
34+
35+
Code
36+
cat(write_yaml_metadata_block(title = "Direct Argument", author = "John",
37+
.list = meta_list))
38+
Output
39+
---
40+
title: Direct Argument
41+
debug: true
42+
author: John
43+
---
44+
45+
# write_yaml_metadata_block handles special characters in values
46+
47+
Code
48+
cat(write_yaml_metadata_block(title = "Test: A Study of R & Quarto",
49+
description = "This is a \"quoted\" string with 'mixed' quotes", path = "C:\\Users\\test\\file.txt"))
50+
Output
51+
---
52+
title: 'Test: A Study of R & Quarto'
53+
description: This is a "quoted" string with 'mixed' quotes
54+
path: C:\Users\test\file.txt
55+
---
56+
57+
# write_yaml_metadata_block handles empty lists and vectors
58+
59+
Code
60+
cat(write_yaml_metadata_block(title = "Test", empty_list = list(),
61+
empty_vector = character(0), empty_numeric = numeric(0)))
62+
Output
63+
---
64+
title: Test
65+
empty_list: []
66+
empty_vector: []
67+
empty_numeric: []
68+
---
69+

0 commit comments

Comments
 (0)