From b9c3ff06027e8145928a84b142ea748a3c399484 Mon Sep 17 00:00:00 2001 From: VisruthSK <67435125+VisruthSK@users.noreply.github.com> Date: Fri, 19 Sep 2025 09:15:46 -0700 Subject: [PATCH 1/6] Drafted an initial version of Quarto readme. --- R/readme.R | 44 +++++++++++++++++++++++++ inst/templates/package-README | 15 +++++++++ inst/templates/project-README | 16 ++++++++- inst/templates/readme-rmd-pre-commit.sh | 6 ++-- 4 files changed, 77 insertions(+), 4 deletions(-) diff --git a/R/readme.R b/R/readme.R index cf1a3651c..f4ffef669 100644 --- a/R/readme.R +++ b/R/readme.R @@ -104,3 +104,47 @@ use_readme_md <- function(open = rlang::is_interactive()) { invisible(new) } + +#' @export +#' @rdname use_readme_rmd +use_readme_qmd <- function(open = rlang::is_interactive()) { + check_is_project() + check_installed("quarto") + # TODO: fail if README.RMD exists + + is_pkg <- is_package() + repo_spec <- tryCatch(target_repo_spec(ask = FALSE), error = function(e) NULL) + nm <- if (is_pkg) "Package" else "Project" + data <- list2( + !!nm := project_name(), + quarto = TRUE, + on_github = !is.null(repo_spec), + github_spec = repo_spec + ) + + new <- use_template( + if (is_pkg) "package-README" else "project-README", + "README.qmd", + data = data, + ignore = is_pkg, + open = open + ) + if (!new) { + return(invisible(FALSE)) + } + + if (is_pkg && !data$on_github) { + ui_bullets(c( + "_" = "Update {.path {pth('README.qmd')}} to include installation instructions." + )) + } + + if (uses_git()) { + use_git_hook( + "pre-commit", + render_template("readme-rmd-pre-commit.sh") + ) + } + + invisible(TRUE) +} diff --git a/inst/templates/package-README b/inst/templates/package-README index cde93f606..548bb45b9 100644 --- a/inst/templates/package-README +++ b/inst/templates/package-README @@ -14,8 +14,23 @@ knitr::opts_chunk$set( ) ``` {{/Rmd}} +{{#quarto}} +--- +title: {{{ Package }}} +knitr: + opts_chunk: + collapse: true + comment: '#>' + fig.path: "man/figures/README-" + out.width: "100%" +format: gfm +--- + +{{/quarto}} +{{^quarto}} # {{{ Package }}} +{{/quarto}} diff --git a/inst/templates/project-README b/inst/templates/project-README index 955d05f3d..e7243b1e4 100644 --- a/inst/templates/project-README +++ b/inst/templates/project-README @@ -12,9 +12,23 @@ knitr::opts_chunk$set( ) ``` {{/Rmd}} +{{#quarto}} +--- +title: {{{ Project }}} +knitr: + opts_chunk: + collapse: true + comment: '#>' + fig.path: "man/figures/README-" + out.width: "100%" +format: gfm +--- + +{{/quarto}} +{{^quarto}} # {{{ Project }}} - +{{/quarto}} diff --git a/inst/templates/readme-rmd-pre-commit.sh b/inst/templates/readme-rmd-pre-commit.sh index d56327f36..46febb345 100644 --- a/inst/templates/readme-rmd-pre-commit.sh +++ b/inst/templates/readme-rmd-pre-commit.sh @@ -1,13 +1,13 @@ #!/bin/bash -README=($(git diff --cached --name-only | grep -Ei '^README\.[R]?md$')) +README=($(git diff --cached --name-only | grep -Ei '^README\.([R,q]?md)$')) MSG="use 'git commit --no-verify' to override this check" if [[ ${#README[@]} == 0 ]]; then exit 0 fi -if [[ README.Rmd -nt README.md ]]; then - echo -e "README.md is out of date; please re-knit README.Rmd\n$MSG" +if [[ README.Rmd -nt README.md || README.qmd -nt README.md ]]; then + echo -e "README.md is out of date; please re-knit README.Rmd or README.qmd\n$MSG" exit 1 elif [[ ${#README[@]} -lt 2 ]]; then echo -e "README.Rmd and README.md should be both staged\n$MSG" From 1f49ba690282f637af97dd7ce5cf676a04fd587d Mon Sep 17 00:00:00 2001 From: VisruthSK <67435125+VisruthSK@users.noreply.github.com> Date: Fri, 19 Sep 2025 09:45:22 -0700 Subject: [PATCH 2/6] Deduplicated code. Changed templates to reflect Quarto's execution --- R/readme.R | 125 +++++++++++++--------------------- inst/templates/package-README | 16 ++--- inst/templates/project-README | 4 +- 3 files changed, 56 insertions(+), 89 deletions(-) diff --git a/R/readme.R b/R/readme.R index f4ffef669..a033c0483 100644 --- a/R/readme.R +++ b/R/readme.R @@ -6,7 +6,7 @@ #' * R code to install from GitHub, if GitHub usage detected #' * a basic example #' -#' Use `Rmd` if you want a rich intermingling of code and output. Use `md` for a +#' Use `Quarto` or `Rmd` if you want a rich intermingling of code and output. Use `md` for a #' basic README. `README.Rmd` will be automatically added to `.Rbuildignore`. #' The resulting README is populated with default YAML frontmatter and R fenced #' code blocks (`md`) or chunks (`Rmd`). @@ -35,116 +35,83 @@ #' use_readme_md() #' } use_readme_rmd <- function(open = rlang::is_interactive()) { - check_is_project() - check_installed("rmarkdown") - - is_pkg <- is_package() - repo_spec <- tryCatch(target_repo_spec(ask = FALSE), error = function(e) NULL) - nm <- if (is_pkg) "Package" else "Project" - data <- list2( - !!nm := project_name(), - Rmd = TRUE, - on_github = !is.null(repo_spec), - github_spec = repo_spec - ) - - new <- use_template( - if (is_pkg) "package-README" else "project-README", - "README.Rmd", - data = data, - ignore = is_pkg, - open = open - ) - if (!new) { - return(invisible(FALSE)) - } - - if (is_pkg && !data$on_github) { - ui_bullets(c( - "_" = "Update {.path {pth('README.Rmd')}} to include installation instructions." - )) - } - - if (uses_git()) { - use_git_hook( - "pre-commit", - render_template("readme-rmd-pre-commit.sh") - ) - } - - invisible(TRUE) + use_readme("Rmd", open = open) } #' @export #' @rdname use_readme_rmd use_readme_md <- function(open = rlang::is_interactive()) { - check_is_project() - is_pkg <- is_package() - repo_spec <- tryCatch(target_repo_spec(ask = FALSE), error = function(e) NULL) - nm <- if (is_pkg) "Package" else "Project" - data <- list2( - !!nm := project_name(), - Rmd = FALSE, - on_github = !is.null(repo_spec), - github_spec = repo_spec - ) - - new <- use_template( - if (is_pkg) "package-README" else "project-README", - "README.md", - data = data, - open = open - ) - - if (is_pkg && !data$on_github) { - ui_bullets(c( - "_" = "Update {.path {pth('README.md')}} to include installation instructions." - )) - } - - invisible(new) + use_readme("md", open = open) } #' @export #' @rdname use_readme_rmd use_readme_qmd <- function(open = rlang::is_interactive()) { - check_is_project() - check_installed("quarto") # TODO: fail if README.RMD exists + # cli::cli_abort("Can't have both {.file README.Rmd} and {.file README.qmd}.") + use_readme("qmd", open = open) +} + +#' @noRd +use_readme <- function( + fmt = c("Rmd", "md", "qmd"), + open = rlang::is_interactive() +) { + check_is_project() + fmt <- rlang::arg_match(fmt) + if (fmt == "Rmd") { + check_installed("rmarkdown") + } + if (fmt == "qmd") { + check_installed("quarto") + } is_pkg <- is_package() repo_spec <- tryCatch(target_repo_spec(ask = FALSE), error = function(e) NULL) nm <- if (is_pkg) "Package" else "Project" + + args <- switch( + fmt, + Rmd = list(Rmd = TRUE, needs_render = TRUE), + md = list(needs_render = FALSE), + qmd = list(quarto = TRUE, needs_render = TRUE) + ) data <- list2( !!nm := project_name(), - quarto = TRUE, on_github = !is.null(repo_spec), - github_spec = repo_spec + github_spec = repo_spec, + !!!args ) new <- use_template( if (is_pkg) "package-README" else "project-README", - "README.qmd", + glue::glue("README.", fmt), data = data, - ignore = is_pkg, + ignore = if (fmt %in% c("rmd", "qmd")) is_pkg else FALSE, open = open ) - if (!new) { - return(invisible(FALSE)) - } if (is_pkg && !data$on_github) { - ui_bullets(c( - "_" = "Update {.path {pth('README.qmd')}} to include installation instructions." - )) + msg <- switch( + fmt, + rmd = "Update {.path {pth('README.Rmd')}} to include installation instructions.", + md = "Update {.path {pth('README.md')}} to include installation instructions.", + qmd = "Update {.path {pth('README.qmd')}} to include installation instructions." + ) + ui_bullets(c("_" = msg)) } - if (uses_git()) { + if (fmt %in% c("rmd", "qmd") && uses_git()) { + if (!new) { + return(invisible(FALSE)) + } + use_git_hook( "pre-commit", render_template("readme-rmd-pre-commit.sh") ) + invisible(TRUE) + } else { + invisible(new) } - - invisible(TRUE) } diff --git a/inst/templates/package-README b/inst/templates/package-README index 548bb45b9..cfe6cdbb8 100644 --- a/inst/templates/package-README +++ b/inst/templates/package-README @@ -59,23 +59,23 @@ You can install the development version of {{{ Package }}} like so: This is a basic example which shows you how to solve a common problem: -{{#Rmd}} +{{#needs_render}} ```{r example} -{{/Rmd}} -{{^Rmd}}``` r -{{/Rmd}} +{{/needs_render}} +{{^needs_render}}``` r +{{/needs_render}} library({{Package}}) ## basic example code ``` -{{#Rmd}} -What is special about using `README.Rmd` instead of just `README.md`? You can include R chunks like so: +{{#needs_render}} +What is special about using `README.Rmd` or `README.qmd` instead of just `README.md`? You can include R chunks like so: ```{r cars} summary(cars) ``` -You'll still need to render `README.Rmd` regularly, to keep `README.md` up-to-date. `devtools::build_readme()` is handy for this. +You'll still need to render `README.Rmd`/`README.qmd` regularly, to keep `README.md` up-to-date. `devtools::build_readme()` is handy for this. You can also embed plots, for example: @@ -84,4 +84,4 @@ plot(pressure) ``` In that case, don't forget to commit and push the resulting figure files, so they display on GitHub and CRAN. -{{/Rmd}} +{{/needs_render}} diff --git a/inst/templates/project-README b/inst/templates/project-README index e7243b1e4..17a5f7a03 100644 --- a/inst/templates/project-README +++ b/inst/templates/project-README @@ -34,7 +34,7 @@ format: gfm The goal of {{{ Project }}} is to ... -{{#Rmd}} +{{#needs_render}} What is special about using `README.Rmd` instead of just `README.md`? You can include R chunks like so: ```{r cars} @@ -50,4 +50,4 @@ plot(pressure) ``` In that case, don't forget to commit and push the resulting figure files, so they display on GitHub. -{{/Rmd}} +{{/needs_render}} From b33900b1a1d76e16e5091bebead3b83ab8090d2c Mon Sep 17 00:00:00 2001 From: VisruthSK <67435125+VisruthSK@users.noreply.github.com> Date: Fri, 19 Sep 2025 10:11:15 -0700 Subject: [PATCH 3/6] Fixed typos and adjusted template to write either .Rmd or .qmd --- NAMESPACE | 1 + R/readme.R | 9 +++++---- inst/templates/package-README | 5 +++-- inst/templates/project-README | 4 ++-- man/use_readme_rmd.Rd | 5 ++++- 5 files changed, 15 insertions(+), 9 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index 91a15d28e..87c0e2d9b 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -158,6 +158,7 @@ export(use_rcpp) export(use_rcpp_armadillo) export(use_rcpp_eigen) export(use_readme_md) +export(use_readme_qmd) export(use_readme_rmd) export(use_release_issue) export(use_reprex) diff --git a/R/readme.R b/R/readme.R index a033c0483..9a3b74f7b 100644 --- a/R/readme.R +++ b/R/readme.R @@ -72,9 +72,9 @@ use_readme <- function( args <- switch( fmt, - Rmd = list(Rmd = TRUE, needs_render = TRUE), + Rmd = list(Rmd = TRUE, filename = "README.Rmd", needs_render = TRUE), md = list(needs_render = FALSE), - qmd = list(quarto = TRUE, needs_render = TRUE) + qmd = list(quarto = TRUE, filename = "README.qmd", needs_render = TRUE) ) data <- list2( !!nm := project_name(), @@ -87,7 +87,7 @@ use_readme <- function( if (is_pkg) "package-README" else "project-README", glue::glue("README.", fmt), data = data, - ignore = if (fmt %in% c("rmd", "qmd")) is_pkg else FALSE, + ignore = if (fmt %in% c("Rmd", "qmd")) is_pkg else FALSE, open = open ) @@ -101,7 +101,7 @@ use_readme <- function( ui_bullets(c("_" = msg)) } - if (fmt %in% c("rmd", "qmd") && uses_git()) { + if (fmt %in% c("Rmd", "qmd") && uses_git()) { if (!new) { return(invisible(FALSE)) } @@ -110,6 +110,7 @@ use_readme <- function( "pre-commit", render_template("readme-rmd-pre-commit.sh") ) + invisible(TRUE) } else { invisible(new) diff --git a/inst/templates/package-README b/inst/templates/package-README index cfe6cdbb8..37dbd360f 100644 --- a/inst/templates/package-README +++ b/inst/templates/package-README @@ -14,6 +14,7 @@ knitr::opts_chunk$set( ) ``` {{/Rmd}} + {{#quarto}} --- title: {{{ Package }}} @@ -69,13 +70,13 @@ library({{Package}}) ``` {{#needs_render}} -What is special about using `README.Rmd` or `README.qmd` instead of just `README.md`? You can include R chunks like so: +What is special about using `{{{ filename }}}` instead of just `README.md`? You can include R chunks like so: ```{r cars} summary(cars) ``` -You'll still need to render `README.Rmd`/`README.qmd` regularly, to keep `README.md` up-to-date. `devtools::build_readme()` is handy for this. +You'll still need to render `{{{ filename }}}` regularly, to keep `README.md` up-to-date. `devtools::build_readme()` is handy for this. You can also embed plots, for example: diff --git a/inst/templates/project-README b/inst/templates/project-README index 17a5f7a03..ed606c8e0 100644 --- a/inst/templates/project-README +++ b/inst/templates/project-README @@ -35,13 +35,13 @@ format: gfm The goal of {{{ Project }}} is to ... {{#needs_render}} -What is special about using `README.Rmd` instead of just `README.md`? You can include R chunks like so: +What is special about using `{{{ filename }}}` instead of just `README.md`? You can include R chunks like so: ```{r cars} summary(cars) ``` -You'll still need to render `README.Rmd` regularly, to keep `README.md` up-to-date. +You'll still need to render `{{{ filename }}}` regularly, to keep `README.md` up-to-date. You can also embed plots, for example: diff --git a/man/use_readme_rmd.Rd b/man/use_readme_rmd.Rd index a7d8e0570..d3051058d 100644 --- a/man/use_readme_rmd.Rd +++ b/man/use_readme_rmd.Rd @@ -3,11 +3,14 @@ \name{use_readme_rmd} \alias{use_readme_rmd} \alias{use_readme_md} +\alias{use_readme_qmd} \title{Create README files} \usage{ use_readme_rmd(open = rlang::is_interactive()) use_readme_md(open = rlang::is_interactive()) + +use_readme_qmd(open = rlang::is_interactive()) } \arguments{ \item{open}{Open the newly created file for editing? Happens in RStudio, if @@ -21,7 +24,7 @@ Creates skeleton README files with possible stubs for \item a basic example } -Use \code{Rmd} if you want a rich intermingling of code and output. Use \code{md} for a +Use \code{Quarto} or \code{Rmd} (hereafter just \code{Rmd}) if you want a rich intermingling of code and output. Use \code{md} for a basic README. \code{README.Rmd} will be automatically added to \code{.Rbuildignore}. The resulting README is populated with default YAML frontmatter and R fenced code blocks (\code{md}) or chunks (\code{Rmd}). From a20439c89b42d6bf1fa0296d8caf9106ad30dc23 Mon Sep 17 00:00:00 2001 From: VisruthSK <67435125+VisruthSK@users.noreply.github.com> Date: Fri, 19 Sep 2025 11:15:51 -0700 Subject: [PATCH 4/6] Added tests, updated documentation --- R/readme.R | 53 +++++++++++++++++++++++++----------- man/use_readme_rmd.Rd | 23 ++++++++-------- tests/testthat/test-readme.R | 24 ++++++++++++++++ 3 files changed, 73 insertions(+), 27 deletions(-) diff --git a/R/readme.R b/R/readme.R index 9a3b74f7b..b42fafbd7 100644 --- a/R/readme.R +++ b/R/readme.R @@ -6,21 +6,21 @@ #' * R code to install from GitHub, if GitHub usage detected #' * a basic example #' -#' Use `Quarto` or `Rmd` if you want a rich intermingling of code and output. Use `md` for a -#' basic README. `README.Rmd` will be automatically added to `.Rbuildignore`. +#' Use `qmd` or `Rmd` if you want a rich intermingling of code and output. Use `md` for a +#' basic README. `README.[R,q]md` will be automatically added to `.Rbuildignore`. #' The resulting README is populated with default YAML frontmatter and R fenced -#' code blocks (`md`) or chunks (`Rmd`). +#' code blocks (`md`) or chunks (`Rmd`/`qmd`). #' -#' If you use `Rmd`, you'll still need to render it regularly, to keep +#' If you use `[R,q]md`, you'll still need to render it regularly, to keep #' `README.md` up-to-date. `devtools::build_readme()` is handy for this. You -#' could also use GitHub Actions to re-render `README.Rmd` every time you push. +#' could also use GitHub Actions to re-render `README.[R,q]md` every time you push. #' An example workflow can be found in the `examples/` directory here: #' . #' -#' If the current project is a Git repo, then `use_readme_rmd()` automatically -#' configures a pre-commit hook that helps keep `README.Rmd` and `README.md`, +#' If the current project is a Git repo, then `use_readme_[r,q]md()` automatically +#' configures a pre-commit hook that helps keep `README.[R,q]md` and `README.md`, #' synchronized. The hook creates friction if you try to commit when -#' `README.Rmd` has been edited more recently than `README.md`. If this hook +#' `README.[R,q]md` has been edited more recently than `README.md`. If this hook #' causes more problems than it solves for you, it is implemented in #' `.git/hooks/pre-commit`, which you can modify or even delete. #' @@ -32,6 +32,7 @@ #' @examples #' \dontrun{ #' use_readme_rmd() +#' use_readme_qmd() #' use_readme_md() #' } use_readme_rmd <- function(open = rlang::is_interactive()) { @@ -40,18 +41,22 @@ use_readme_rmd <- function(open = rlang::is_interactive()) { #' @export #' @rdname use_readme_rmd -use_readme_md <- function(open = rlang::is_interactive()) { - use_readme("md", open = open) +use_readme_qmd <- function(open = rlang::is_interactive()) { + use_readme("qmd", open = open) } #' @export #' @rdname use_readme_rmd -use_readme_qmd <- function(open = rlang::is_interactive()) { - # TODO: fail if README.RMD exists - # cli::cli_abort("Can't have both {.file README.Rmd} and {.file README.qmd}.") - use_readme("qmd", open = open) +use_readme_md <- function(open = rlang::is_interactive()) { + use_readme("md", open = open) } +#' Helper to create README files +#' +#' @description +#' This function switches between the three file formats supported for READMEs, +#' and neatly handles file creation for all of them. +#' #' @noRd use_readme <- function( fmt = c("Rmd", "md", "qmd"), @@ -59,17 +64,30 @@ use_readme <- function( ) { check_is_project() fmt <- rlang::arg_match(fmt) + + # Check dependencies and conflicts. if (fmt == "Rmd") { check_installed("rmarkdown") - } - if (fmt == "qmd") { + if (fs::file_exists(proj_path("README.qmd"))) { + cli::cli_abort( + "Can't have both {.file README.Rmd} and {.file README.qmd}. Delete {.file README.qmd} if you want to generate {.file README.Rmd}." + ) + } + } else if (fmt == "qmd") { check_installed("quarto") + if (fs::file_exists(proj_path("README.Rmd"))) { + cli::cli_abort( + "Can't have both {.file README.Rmd} and {.file README.qmd}. Delete {.file README.Rmd} if you want to generate {.file README.qmd}." + ) + } } + # Get some info about the package/project function was called from is_pkg <- is_package() repo_spec <- tryCatch(target_repo_spec(ask = FALSE), error = function(e) NULL) nm <- if (is_pkg) "Package" else "Project" + # build out arguments for creating template args <- switch( fmt, Rmd = list(Rmd = TRUE, filename = "README.Rmd", needs_render = TRUE), @@ -83,6 +101,7 @@ use_readme <- function( !!!args ) + # Create the template, interpolating values from `data` as specified new <- use_template( if (is_pkg) "package-README" else "project-README", glue::glue("README.", fmt), @@ -91,6 +110,7 @@ use_readme <- function( open = open ) + # Make some checks if (is_pkg && !data$on_github) { msg <- switch( fmt, @@ -101,6 +121,7 @@ use_readme <- function( ui_bullets(c("_" = msg)) } + # More checks, specific to renderable README if (fmt %in% c("Rmd", "qmd") && uses_git()) { if (!new) { return(invisible(FALSE)) diff --git a/man/use_readme_rmd.Rd b/man/use_readme_rmd.Rd index d3051058d..591f45e7b 100644 --- a/man/use_readme_rmd.Rd +++ b/man/use_readme_rmd.Rd @@ -2,15 +2,15 @@ % Please edit documentation in R/readme.R \name{use_readme_rmd} \alias{use_readme_rmd} -\alias{use_readme_md} \alias{use_readme_qmd} +\alias{use_readme_md} \title{Create README files} \usage{ use_readme_rmd(open = rlang::is_interactive()) -use_readme_md(open = rlang::is_interactive()) - use_readme_qmd(open = rlang::is_interactive()) + +use_readme_md(open = rlang::is_interactive()) } \arguments{ \item{open}{Open the newly created file for editing? Happens in RStudio, if @@ -24,27 +24,28 @@ Creates skeleton README files with possible stubs for \item a basic example } -Use \code{Quarto} or \code{Rmd} (hereafter just \code{Rmd}) if you want a rich intermingling of code and output. Use \code{md} for a -basic README. \code{README.Rmd} will be automatically added to \code{.Rbuildignore}. +Use \code{qmd} or \code{Rmd} if you want a rich intermingling of code and output. Use \code{md} for a +basic README. \verb{README.[R,q]md} will be automatically added to \code{.Rbuildignore}. The resulting README is populated with default YAML frontmatter and R fenced -code blocks (\code{md}) or chunks (\code{Rmd}). +code blocks (\code{md}) or chunks (\code{Rmd}/\code{qmd}). -If you use \code{Rmd}, you'll still need to render it regularly, to keep +If you use \verb{[R,q]md}, you'll still need to render it regularly, to keep \code{README.md} up-to-date. \code{devtools::build_readme()} is handy for this. You -could also use GitHub Actions to re-render \code{README.Rmd} every time you push. +could also use GitHub Actions to re-render \verb{README.[R,q]md} every time you push. An example workflow can be found in the \verb{examples/} directory here: \url{https://github.com/r-lib/actions/}. -If the current project is a Git repo, then \code{use_readme_rmd()} automatically -configures a pre-commit hook that helps keep \code{README.Rmd} and \code{README.md}, +If the current project is a Git repo, then \verb{use_readme_[r,q]md()} automatically +configures a pre-commit hook that helps keep \verb{README.[R,q]md} and \code{README.md}, synchronized. The hook creates friction if you try to commit when -\code{README.Rmd} has been edited more recently than \code{README.md}. If this hook +\verb{README.[R,q]md} has been edited more recently than \code{README.md}. If this hook causes more problems than it solves for you, it is implemented in \code{.git/hooks/pre-commit}, which you can modify or even delete. } \examples{ \dontrun{ use_readme_rmd() +use_readme_qmd() use_readme_md() } } diff --git a/tests/testthat/test-readme.R b/tests/testthat/test-readme.R index f2c8a0f4d..e9f91c09a 100644 --- a/tests/testthat/test-readme.R +++ b/tests/testthat/test-readme.R @@ -12,6 +12,14 @@ test_that("use_readme_rmd() creates README.Rmd", { expect_proj_file("README.Rmd") }) +test_that("use_readme_qmd() creates README.qmd", { + skip_if_not_installed("quarto") + + create_local_package() + use_readme_qmd() + expect_proj_file("README.qmd") +}) + test_that("use_readme_rmd() sets up git pre-commit hook if pkg uses git", { skip_if_no_git_user() skip_if_not_installed("rmarkdown") @@ -65,3 +73,19 @@ test_that("use_readme_rmd() has expected form for a GitHub package", { transform = scrub_testpkg ) }) + +test_that("Disallow creation of README.Rmd if README.qmd exists", { + skip_if_not_installed("quarto") + create_local_package() + use_readme_qmd() + expect_proj_file("README.qmd") + expect_error(use_readme_rmd()) +}) + +test_that("Disallow creation of README.qmd if README.Rmd exists", { + skip_if_not_installed("rmarkdown") + create_local_package() + use_readme_rmd() + expect_proj_file("README.Rmd") + expect_error(use_readme_qmd()) +}) From d15fd70923cba888dd694e98213b3706c9de5ef5 Mon Sep 17 00:00:00 2001 From: VisruthSK <67435125+VisruthSK@users.noreply.github.com> Date: Sat, 20 Dec 2025 22:26:06 -0800 Subject: [PATCH 5/6] Support Quarto readme across package --- R/badge.R | 8 ++++---- R/release.R | 3 ++- R/upkeep.R | 5 ++++- man/badges.Rd | 4 ++-- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/R/badge.R b/R/badge.R index 7dcf84464..18f794fe5 100644 --- a/R/badge.R +++ b/R/badge.R @@ -5,8 +5,8 @@ #' and link out to relevant external resources. To allow badges to be added #' automatically, ensure your badge block starts with a line containing only #' `` and ends with a line containing only -#' ``. The templates used by [use_readme_md()] and -#' [use_readme_rmd()] include this block. +#' ``. The templates used by [use_readme_md()], +#' [use_readme_rmd()], and [use_readme_qmd()] include this block. #' #' @details #' @@ -66,7 +66,7 @@ use_badge <- function(badge_name, href, src) { block_end = badge_end ) - if (changed && path_ext(path) == "Rmd") { + if (changed && path_ext(path) %in% c("Rmd", "qmd")) { ui_bullets(c( "_" = "Re-knit {.path {pth(path)}} with {.run devtools::build_readme()}." )) @@ -224,5 +224,5 @@ badge_start <- "" badge_end <- "" find_readme <- function() { - path_first_existing(proj_path(c("README.Rmd", "README.md"))) + path_first_existing(proj_path(c("README.Rmd", "README.qmd", "README.md"))) } diff --git a/R/release.R b/R/release.R index 89722e90e..e56f3154f 100644 --- a/R/release.R +++ b/R/release.R @@ -75,7 +75,8 @@ release_checklist <- function(version, on_cran, target_repo = NULL) { has_news <- file_exists(proj_path("NEWS.md")) has_pkgdown <- uses_pkgdown() has_lifecycle <- proj_desc()$has_dep("lifecycle") - has_readme <- file_exists(proj_path("README.Rmd")) + has_readme <- file_exists(proj_path("README.Rmd")) || + file_exists(proj_path("README.qmd")) has_github_links <- has_github_links(target_repo) is_posit_pkg <- is_posit_pkg() milestone_num <- gh_milestone_number(target_repo, version) diff --git a/R/upkeep.R b/R/upkeep.R index 0beb7485a..fc152405a 100644 --- a/R/upkeep.R +++ b/R/upkeep.R @@ -62,7 +62,10 @@ upkeep_checklist <- function(target_repo = NULL) { has_github_links <- has_github_links(target_repo) bullets <- c( - todo("`usethis::use_readme_rmd()`", !file_exists(proj_path("README.Rmd"))), + todo( + "`usethis::use_readme_rmd()`", + !file_exists(proj_path("README.Rmd")) && !file_exists(proj_path("README.qmd")) + ), todo("`usethis::use_roxygen_md()`", !is_true(uses_roxygen_md())), todo("`usethis::use_github_links()`", !has_github_links), todo("`usethis::use_pkgdown_github_pages()`", !uses_pkgdown()), diff --git a/man/badges.Rd b/man/badges.Rd index 8dcafbf09..c21b648ec 100644 --- a/man/badges.Rd +++ b/man/badges.Rd @@ -52,8 +52,8 @@ badges that report information, such as the CRAN version or test coverage, and link out to relevant external resources. To allow badges to be added automatically, ensure your badge block starts with a line containing only \verb{} and ends with a line containing only -\verb{}. The templates used by \code{\link[=use_readme_md]{use_readme_md()}} and -\code{\link[=use_readme_rmd]{use_readme_rmd()}} include this block. +\verb{}. The templates used by \code{\link[=use_readme_md]{use_readme_md()}}, +\code{\link[=use_readme_rmd]{use_readme_rmd()}}, and \code{\link[=use_readme_qmd]{use_readme_qmd()}} include this block. } \details{ \itemize{ From 9d45ea852a5dc565d33d135b82b46112d9ea5e39 Mon Sep 17 00:00:00 2001 From: Visruth <67435125+VisruthSK@users.noreply.github.com> Date: Sat, 20 Dec 2025 22:52:35 -0800 Subject: [PATCH 6/6] Update R/upkeep.R Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- R/upkeep.R | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/R/upkeep.R b/R/upkeep.R index fc152405a..ba9e68d0f 100644 --- a/R/upkeep.R +++ b/R/upkeep.R @@ -64,7 +64,8 @@ upkeep_checklist <- function(target_repo = NULL) { bullets <- c( todo( "`usethis::use_readme_rmd()`", - !file_exists(proj_path("README.Rmd")) && !file_exists(proj_path("README.qmd")) + !file_exists(proj_path("README.Rmd")) && + !file_exists(proj_path("README.qmd")) ), todo("`usethis::use_roxygen_md()`", !is_true(uses_roxygen_md())), todo("`usethis::use_github_links()`", !has_github_links),