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 programmatically based on computed values from knitr engine
- Insert Markdown in HTML tables for Quarto processing - Include Markdown content (equations, links, formatting) in HTML tables
- Apply Light and Dark Themes to Plots and Tables - Change the background and foreground colors of plots and tables based on light & dark themes
- Work with R scripts and Quarto - Extract R code from Quarto documents or prepare R scripts for Quarto rendering
- Build paths from Quarto Project - Build paths relative to Quarto project root within R cells
- Automate Quarto CLI from R - New and improved wrappers around Quarto CLI features for easier automation
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
<- list(
metadata 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)")
)|>
) ::kable(format = "html", escape = FALSE) knitr
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()
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
<- project_path("data", "analysis.csv")
data_file
# Explicitly find the project root (searches for _quarto.yml)
<- find_project_root() root
project_path()
intelligently handles different execution contexts:
- During
quarto render
, it usesQUARTO_PROJECT_ROOT
orQUARTO_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
<- read.csv(project_path("data", "results.csv")) results
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)
for bookdown cross-references in 12 .Rmd files...
ℹ Scanning ! 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
: 11 references
• index.Rmd- 11 Sec
:
ℹ Summary of conversion requirements5 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: 65 references need manual attention
• Section headers: 17 references need manual attention
• Figure labels: 5 references need manual attention
• Table labels: 7 references need manual attention
• Equation structure: 6 references need manual attention
• Theorem blocks
: quarto::detect_bookdown_crossrefs("~/Documents/DEV_R/bookdown/inst/examples", verbose = TRUE) ℹ For detailed conversion guidance, run
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
::convert_chunk_header("analysis.Rmd", output = NULL)
knitr
# To process multiple files in a directory, you need to iterate:
<- list.files("my-bookdown-project/", pattern = "\\.Rmd$",
rmd_files 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:
- Documentation for R package: https://quarto-dev.github.io/quarto-r/
- Full changelog: https://quarto-dev.github.io/quarto-r/news/index.html
- Report issues: https://github.com/quarto-dev/quarto-r/issues
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!