quarto R package v1.5.0: Streamlined Workflows for R Users

The quarto R package 1.5.0 brings powerful new features for passing R values to Quarto metadata, inserting Markdown in HTML tables, working with R scripts, building paths from Quarto projects, and automating Quarto CLI from R.

R package
knitr
Releases
Author

Christophe Dervieux

Published

July 28, 2025

The quarto R package version 1.5.0 is here! This release focuses on making Quarto more flexible and powerful for R users with significant workflow improvements.

What’s New

Install the latest version from CRAN:

install.packages("quarto")

Major features in this release include:

Pass R Values to Quarto Metadata

Set metadata dynamically based on R computations with write_yaml_metadata_block(). For example, you could check a parameter value, and conditionally include content based on it:

#| output: asis

write_yaml_metadata_block(
  is_france = params$country == "france"
)

This will write the following (e.g., when quarto render report.qmd -P country:france):

---
is_france: true
---

Then use Quarto’s conditional features:

::: {.content-visible when-meta="is_france"}
## Fun fact about France

In 2025, France is the most visited country in the world, attracting over 89 million tourists annually!

:::

Improved YAML 1.2 Compatibility

The function now correctly handles special edge cases in YAML quoting. Specifically, it automatically quotes octal-like strings that are not supported in YAML 1.1 (like "0888" or "0999"):

# These octal-like values are automatically quoted to prevent errors
write_yaml_metadata_block(
  code1 = "0888",    # Without quoting: YAML 1.2 interprets as 888 (invalid octal ignored)
  code2 = "0999"     # Without quoting: YAML 1.2 interprets as 999 (invalid octal ignored)
)

Without the automatic quoting, these values would be interpreted as decimal numbers (888 and 999) in YAML 1.2, losing the leading zeros. This could break code that expects string values like file permissions or ID codes that must preserve leading zeros.

This change applies to internal functions that write YAML from R object lists, and so this improvement is particularly important when using execute_params with quarto_render(), where parameter values might include such edge cases:

# Parameters with octal-like codes are now handled correctly
quarto_render("report.qmd", 
  execute_params = list(
    site_code = "0888",
    permission = "0755"
  ))

For explicit control over quoting, use yaml_quote_string():

# Force specific values to be quoted in YAML output
metadata <- list(
  code1 = yaml_quote_string("1.0")
)
write_yaml_metadata_block(.list = metadata)

This will mark the string to be double quoted in YAML, preserving the character representation exactly as provided.

See more examples in the dynamic metadata vignette, including how to make parameters available as metadata for conditional content.

Insert Markdown in HTML Tables for Quarto Processing

Quarto can parse Markdown content in HTML tables, enabling rich formatting like math equations, links, and text styling. The new tbl_qmd_*() functions make this powerful Quarto feature easier to use from R:

data.frame(
  Feature = c("Formatting", "Math", "Links"),
  Example = c(
    tbl_qmd_span("**Bold**, *italic*"),
    tbl_qmd_span("$E = mc^2$"),
    tbl_qmd_span("[Quarto docs](https://quarto.org)")
  )
) |>
  knitr::kable(format = "html", escape = FALSE)

These helper functions wrap content in HTML spans with data-qmd-base64 attributes that Quarto recognizes for Markdown processing. They work with any table package that supports raw HTML (knitr, kableExtra, DT). For content that only works in Quarto, use the display argument for graceful fallback. See more examples in the Markdown in HTML tables vignette, including comparisons of Markdown support in HTML tables across different packages.

Apply Light and Dark Themes to Plots and Tables

The theme_colors_flextable(), theme_colors_ggplot2(), theme_colors_gt(), theme_colors_plotly(), theme_colors_thematic() helper functions change the background and foreground colors of six popular plot and table packages. These can be used to produce light and dark renderings to match the plot or table with themes in light and dark mode.

The usage of the the results of these functions depends on the package. See the Theme Helpers article for usage examples of theme_colors_*.

The theme_brand_flextable(), theme_brand_ggplot2(), theme_brand_gt(), theme_brand_plotly(), theme_brand_thematic() helper functions change the background and foreground colors of these packages using corresponding brand.yml colors. See the Light & Dark Renderings Examples for usage examples of theme_brand_*.

Work with R Scripts and Quarto

Extract R Code from Quarto Documents

The new qmd_to_r_script() Experimental lifecycle function provides an alternative to knitr::purl() that leverages quarto inspect for code extraction:

# Extract R code from a Quarto document
qmd_to_r_script("analysis.qmd")  # Creates "analysis.R"

# Specify custom output
qmd_to_r_script("analysis.qmd", script = "extracted-code.R")

This function uses Quarto’s static document analysis rather than R evaluation, making it faster and safer for simple code extraction. It preserves cells options, commenting cells with eval: false, and ignoring content having purl: false. For documents using advanced knitr features like child= chunks or knitr::read_chunk(), knitr::purl() remains the recommended approach as it handles these through actual document processing.

Prepare R Scripts for Quarto Rendering

Quarto can render R scripts directly, treating specially formatted comments as Markdown. The add_spin_preamble() function helps prepare R scripts for this feature by adding the required YAML metadata:

# Add metadata for rendering
add_spin_preamble("analysis.R", 
                  title = "Analysis Report",
                  preamble = list(author = "Data Team"))

# Now render the script with Quarto
quarto_render("analysis.R")

This function adds a minimal spin-style preamble (using #' comments) that Quarto recognizes:

#' ---
#' title: Analysis Report
#' author: Data Team
#' ---
#'

# Your original R code follows...

The preamble enables Quarto’s engine binding to properly process the script, allowing you to use R scripts as source documents alongside .qmd files. Learn more about working with R scripts in the R scripts vignette.

Build Paths from Quarto Project

Quarto sets environment variables during rendering that identify the project root, but knitr doesn’t have direct access to this information by default. The new project navigation functions bridge this gap:

# Build paths relative to the Quarto project root
data_file <- project_path("data", "analysis.csv")

# Explicitly find the project root (searches for _quarto.yml)
root <- find_project_root()

project_path() Experimental lifecycle intelligently handles different execution contexts:

  • During quarto render, it uses QUARTO_PROJECT_ROOT or QUARTO_PROJECT_DIR environment variables
  • In interactive sessions, it automatically detects the project root by searching for _quarto.yml.
  • Falls back to the current working directory with a warning if no project is found.

This ensures your paths work consistently without hardcoding or manual adjustments. For example, you can read a CSV file relative to your project root:

# In posts/2025/analysis/report.qmd, this resolves to ../../../data/results.csv
results <- read.csv(project_path("data", "results.csv"))

For more explicit control, consider using here::i_am() and here::here() as an alternative approach. Follow r-lib/usethis Issue #128 for improved support in next versions of here.

Automate Quarto CLI from R

The quarto R package has always been designed as a comprehensive wrapper for the Quarto CLI, enabling seamless integration of Quarto into R workflows and pipelines. This release strengthens that foundation with improved wrappers and new helpers.

Extension Management

Programmatically manage Quarto extensions:

# Add an extension
quarto_add_extension("quarto-journals/jss")

# List installed extensions
quarto_list_extensions()

# Remove an extension
quarto_remove_extension("jss")

Project and Version Management

New helpers for common CLI tasks:

# Create projects from templates
quarto_create("article", name = "my-analysis")

# Check if a newer version of Quarto is available
check_newer_version()

Document Inspection

Leverage quarto inspect results to answer questions about documents:

# Check if a document has parameters (uses quarto inspect internally)
if (has_parameters("report.qmd")) {
  quarto_render("report.qmd", execute_params = list(year = 2025))
}

These CLI wrappers enable automation scenarios like CI/CD pipelines, batch processing, and dynamic project management—all from within R. The consistent interface means you can script complex Quarto workflows without leaving your R environment.

Additional Improvements

Familiar Workflows for Blogdown Users

The new_blog_post() function provides a familiar workflow for users transitioning from blogdown:

# Create a new blog post with automatic date prefix and YAML frontmatter
new_blog_post("my-first-quarto-post", dir = "posts")

Similar to blogdown’s new_post(), this function automatically creates a new blog post file with proper YAML frontmatter in the appropriate directory structure for Quarto blogs, making the transition from blogdown to Quarto smoother.

Migration Helper for Bookdown Projects

The detect_bookdown_crossrefs() function helps identify bookdown cross-reference syntax that needs conversion:

# Scan your bookdown project for cross-references
detect_bookdown_crossrefs("my-bookdown-project/")

The function prints detailed guidance to the console, showing:

  • Which cross-reference patterns need manual conversion
  • Which patterns can be automatically converted
  • Specific examples from your files

Example output from the bookdown book sources:

> detect_bookdown_crossrefs("~/Documents/DEV_R/bookdown/inst/examples", verbose = FALSE)
ℹ Scanning for bookdown cross-references in 12 .Rmd files...
! Found 110 bookdown cross-references that should be converted:

01-introduction.Rmd: 3 references
- 3 Sec

02-components.Rmd: 52 references
- 5 Eq
- 7 Fig
- 1 Lem
- 1 Lemma Div
- 7 Numbered Equation
- 17 Sec
- 5 Tab
- 5 Theorem Div
- 4 Thm

03-formats.Rmd: 20 references
- 4 Fig
- 16 Sec

04-customization.Rmd: 5 references
- 5 Sec

05-editing.Rmd: 8 references
- 3 Fig
- 5 Sec

06-publishing.Rmd: 8 references
- 3 Fig
- 5 Sec

08-usage.Rmd: 3 references
- 3 Sec

• index.Rmd: 11 references
- 11 Sec

ℹ Summary of conversion requirements:
5 Eq reference
17 Fig reference
1 Lem reference
1 Lemma Div reference
7 Numbered Equation reference
65 Sec reference
5 Tab reference
5 Theorem Div reference
4 Thm reference

ℹ Manual conversion requirements:
• Section headers: 65 references need manual attention
• Figure labels: 17 references need manual attention
• Table labels: 5 references need manual attention
• Equation structure: 7 references need manual attention
• Theorem blocks: 6 references need manual attention

ℹ For detailed conversion guidance, run: quarto::detect_bookdown_crossrefs("~/Documents/DEV_R/bookdown/inst/examples", verbose = TRUE)

For converting chunk headers from curly brace syntax to Quarto’s YAML style, remember that knitr::convert_chunk_header() is available:

# Convert {r label, option=value} to YAML-style chunk options for a single file
knitr::convert_chunk_header("analysis.Rmd", output = NULL)

# To process multiple files in a directory, you need to iterate:
rmd_files <- list.files("my-bookdown-project/", pattern = "\\.Rmd$", 
                        full.names = TRUE, recursive = TRUE)
lapply(rmd_files, knitr::convert_chunk_header, output = NULL)

Together, these tools address the main syntax differences when migrating from bookdown to Quarto.

Enhanced Workflow

  • quarto_preview() now returns the preview URL for automation
  • Better debugging with QUARTO_R_DEBUG=TRUE environment variable
  • Consistent R version usage in embedded processes

Breaking Changes

Output File Handling

The output_file parameter in quarto_render() now sets the output-file metadata field instead of passing the --output CLI flag to Quarto. This change better aligns with Quarto’s metadata processing and enables support for multiple output formats:

# Sets output-file metadata (like having 'output-file: report.html' in YAML)
quarto_render("doc.qmd", output_file = "report.html")

If you specifically need the old CLI flag behavior, use quarto_args:

# Use CLI flag directly
quarto_render("doc.qmd", quarto_args = c("--output", "report.html"))

Template Usage

quarto_use_template() now requires an empty directory and fails with a clear error message when used in non-empty directories:

# Create an empty directory first
dir.create("my-article")
quarto_use_template("quarto-journals/jss", dir = "my-article")

This change follows a Quarto CLI update that removed interactive prompting for programmatic use. If you need to use templates in existing directories, use quarto use template directly in the terminal for interactive installation.

Learn More

Explore the new features and improvements:

For detailed examples and workflows, check out the new vignettes:

Acknowledgments

Special thanks to all contributors that helped make this release:

@asadow, @caiolivf, @caocloud, @cderv, @coatless, @ColinFay, @cwickham, @davidrsch, @DillonHammill, @eitsupi, @GeorgeBatten, @gordonwoodhull, @jennybc, @jeroen, @joanbadia, @JosephBARBIERDARNAL, @LiNk-NY, @llrs-roche, @milanmlft, @papayoun, @petermacp, @remlapmot, @salim-b, @saudiwin, @smzimbo-bayer, @srvanderplas, and @wjschne.


Happy Quarto-ing with R!

Subscribe

Enjoy this blog? Get notified of new posts by email: