1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
|
#' Create a vignette or article
#'
#' Creates a new vignette or article in `vignettes/`. Articles are a special
#' type of vignette that appear on pkgdown websites, but are not included
#' in the package itself (because they are added to `.Rbuildignore`
#' automatically).
#'
#' @section General setup:
#' * Adds needed packages to `DESCRIPTION`.
#' * Adds `inst/doc` to `.gitignore` so built vignettes aren't tracked.
#' * Adds `vignettes/*.html` and `vignettes/*.R` to `.gitignore` so
#' you never accidentally track rendered vignettes.
#' * For `*.qmd`, adds Quarto-related patterns to `.gitignore` and
#' `.Rbuildignore`.
#' @param name File name to use for new vignette. Should consist only of
#' numbers, letters, `_` and `-`. Lower case is recommended. Can include the
#' `".Rmd"` or `".qmd"` file extension, which also dictates whether to place
#' an R Markdown or Quarto vignette. R Markdown (`".Rmd"`) is the current
#' default, but it is anticipated that Quarto (`".qmd"`) will become the
#' default in the future.
#' @param title The title of the vignette. If not provided, a title is generated
#' from `name`.
#' @seealso
#' * The [vignettes chapter](https://r-pkgs.org/vignettes.html) of
#' [R Packages](https://r-pkgs.org)
#' * The pkgdown vignette on Quarto:
#' `vignette("quarto", package = "pkgdown")`
#' * The quarto (as in the R package) vignette on HTML vignettes:
#' `vignette("hello", package = "quarto")`
#' @export
#' @examples
#' \dontrun{
#' use_vignette("how-to-do-stuff", "How to do stuff")
#' use_vignette("r-markdown-is-classic.Rmd", "R Markdown is classic")
#' use_vignette("quarto-is-cool.qmd", "Quarto is cool")
#' }
use_vignette <- function(name, title = NULL) {
check_is_package("use_vignette()")
check_required(name)
maybe_name(title)
ext <- get_vignette_extension(name)
if (ext == "qmd") {
check_installed("quarto")
check_installed("pkgdown", version = "2.1.0")
}
name <- path_ext_remove(name)
check_vignette_name(name)
title <- title %||% name
use_dependency("knitr", "Suggests")
use_git_ignore("inst/doc")
if (tolower(ext) == "rmd") {
use_dependency("rmarkdown", "Suggests")
proj_desc_field_update("VignetteBuilder", "knitr", overwrite = TRUE, append = TRUE)
use_vignette_template("vignette.Rmd", name, title)
} else {
use_dependency("quarto", "Suggests")
proj_desc_field_update("VignetteBuilder", "quarto", overwrite = TRUE, append = TRUE)
use_vignette_template("vignette.qmd", name, title)
}
invisible()
}
#' @export
#' @rdname use_vignette
use_article <- function(name, title = NULL) {
check_is_package("use_article()")
check_required(name)
maybe_name(title)
ext <- get_vignette_extension(name)
if (ext == "qmd") {
check_installed("quarto")
check_installed("pkgdown", version = "2.1.0")
}
name <- path_ext_remove(name)
title <- title %||% name
if (tolower(ext) == "rmd") {
proj_desc_field_update("Config/Needs/website", "rmarkdown", overwrite = TRUE, append = TRUE)
use_vignette_template("article.Rmd", name, title, subdir = "articles")
} else {
use_dependency("quarto", "Suggests")
proj_desc_field_update("Config/Needs/website", "quarto", overwrite = TRUE, append = TRUE)
use_vignette_template("article.qmd", name, title, subdir = "articles")
}
use_build_ignore("vignettes/articles")
invisible()
}
use_vignette_template <- function(template, name, title, subdir = NULL) {
check_name(template)
check_name(name)
check_name(title)
maybe_name(subdir)
ext <- get_vignette_extension(template)
if (is.null(subdir)) {
target_dir <- "vignettes"
} else {
target_dir <- path("vignettes", subdir)
}
use_directory(target_dir)
use_git_ignore(c("*.html", "*.R"), directory = target_dir)
if (ext == "qmd") {
use_git_ignore("**/.quarto/")
use_git_ignore("*_files", target_dir)
use_build_ignore(path(target_dir, ".quarto"))
use_build_ignore(path(target_dir, "*_files"))
}
path <- path(target_dir, asciify(name), ext = ext)
data <- list(
Package = project_name(),
vignette_title = title,
braced_vignette_title = glue("{{{title}}}")
)
use_template(template,
save_as = path,
data = data,
open = TRUE
)
path
}
check_vignette_name <- function(name) {
if (!valid_vignette_name(name)) {
ui_abort(c(
"{.val {name}} is not a valid filename for a vignette. It must:",
"Start with a letter.",
"Contain only letters, numbers, '_', and '-'."
))
}
}
# https://cran.r-project.org/doc/manuals/r-release/R-exts.html#Writing-package-vignettes
# "To ensure that they can be accessed from a browser (as an HTML index is
# provided), the file names should start with an ASCII letter and be comprised
# entirely of ASCII letters or digits or hyphen or underscore."
valid_vignette_name <- function(x) {
grepl("^[[:alpha:]][[:alnum:]_-]*$", x)
}
check_vignette_extension <- function(ext) {
# Quietly accept "rmd" here, tho we'll always write ".Rmd" in such a filepath
if (! ext %in% c("Rmd", "rmd", "qmd")) {
valid_exts_cli <- cli::cli_vec(
c("Rmd", "qmd"),
style = list("vec-sep2" = " or ")
)
ui_abort(c(
"Unsupported file extension: {.val {ext}}",
"usethis can only create a vignette or article with one of these
extensions: {.val {valid_exts_cli}}."
))
}
}
get_vignette_extension <- function(name) {
ext <- path_ext(name)
if (nzchar(ext)) {
check_vignette_extension(ext)
} else {
ext <- "Rmd"
}
ext
}
|