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 180 181 182 183 184 185 186 187
|
#' Use pkgdown
#'
#' @description
#' [pkgdown](https://pkgdown.r-lib.org) makes it easy to turn your package into
#' a beautiful website. usethis provides two functions to help you use pkgdown:
#'
#' * `use_pkgdown()`: creates a pkgdown config file and adds relevant files or
#' directories to `.Rbuildignore` and `.gitignore`.
#'
#' * `use_pkgdown_github_pages()`: implements the GitHub setup needed to
#' automatically publish your pkgdown site to GitHub pages:
#'
#' - (first, it calls `use_pkgdown()`)
#' - [use_github_pages()] prepares to publish the pkgdown site from the
#' `gh-pages` branch
#' - [`use_github_action("pkgdown")`][use_github_action()] configures a
#' GitHub Action to automatically build the pkgdown site and deploy it via
#' GitHub Pages
#' - The pkgdown site's URL is added to the pkgdown configuration file,
#' to the URL field of DESCRIPTION, and to the GitHub repo.
#' - Packages owned by certain GitHub organizations (tidyverse, r-lib, and
#' tidymodels) get some special treatment, in terms of anticipating the
#' (eventual) site URL and the use of a pkgdown template.
#'
#' @seealso <https://pkgdown.r-lib.org/articles/pkgdown.html#configuration>
#' @param config_file Path to the pkgdown yaml config file, relative to the
#' project.
#' @param destdir Target directory for pkgdown docs.
#' @export
use_pkgdown <- function(config_file = "_pkgdown.yml", destdir = "docs") {
check_is_package("use_pkgdown()")
check_installed("pkgdown")
use_build_ignore(c(config_file, destdir, "pkgdown"))
use_git_ignore(destdir)
config <- pkgdown_config(destdir)
config_path <- proj_path(config_file)
write_over(config_path, yaml::as.yaml(config))
edit_file(config_path)
invisible(TRUE)
}
pkgdown_config <- function(destdir) {
config <- list(
url = NULL
)
if (pkgdown_version() >= "1.9000") {
config$template <- list(bootstrap = 5L)
}
if (!identical(destdir, "docs")) {
config$destination <- destdir
}
config
}
# wrapping because I need to be able to mock this in tests
pkgdown_version <- function() {
utils::packageVersion("pkgdown")
}
#' @rdname use_pkgdown
#' @export
use_pkgdown_github_pages <- function() {
tr <- target_repo(github_get = TRUE, ok_configs = c("ours", "fork"))
check_can_push(tr = tr, "to turn on GitHub Pages")
use_pkgdown()
site <- use_github_pages()
use_github_action("pkgdown")
site_url <- tidyverse_url(url = site$html_url, tr = tr)
use_pkgdown_url(url = site_url, tr = tr)
if (is_posit_pkg()) {
proj_desc_field_update("Config/Needs/website", "tidyverse/tidytemplate", append = TRUE)
}
}
# helpers ----------------------------------------------------------------------
use_pkgdown_url <- function(url, tr = NULL) {
tr <- tr %||% target_repo(github_get = TRUE)
config_path <- pkgdown_config_path()
ui_bullets(c(
"v" = "Recording {.url {url}} as site's {.field url} in
{.path {pth(config_path)}}."
))
config <- pkgdown_config_meta()
if (has_name(config, "url")) {
config$url <- url
} else {
config <- c(url = url, config)
}
write_utf8(config_path, yaml::as.yaml(config))
proj_desc_field_update("URL", url, append = TRUE)
if (has_package_doc()) {
ui_bullets(c(
"_" = "Run {.run devtools::document()} to update package-level documentation."
))
}
gh <- gh_tr(tr)
homepage <- gh("GET /repos/{owner}/{repo}")[["homepage"]]
if (is.null(homepage) || homepage != url) {
ui_bullets(c(
"v" = "Setting {.url {url}} as homepage of GitHub repo {.val {tr$repo_spec}}."
))
gh("PATCH /repos/{owner}/{repo}", homepage = url)
}
invisible()
}
tidyverse_url <- function(url, tr = NULL) {
tr <- tr %||% target_repo(github_get = TRUE)
if (!is_interactive() ||
!tr$repo_owner %in% c("tidyverse", "r-lib", "tidymodels")) {
return(url)
}
custom_url <- glue("https://{tr$repo_name}.{tr$repo_owner}.org")
if (grepl(glue("{custom_url}/?"), url)) {
return(url)
}
if (ui_yep(c(
"i" = "{.val {tr$repo_name}} is owned by the {.val {tr$repo_owner}} GitHub
organization.",
" " = "Shall we configure {.val {custom_url}} as the (eventual) pkgdown URL?"
))) {
custom_url
} else {
url
}
}
pkgdown_config_path <- function() {
path_first_existing(
proj_path(
c(
"_pkgdown.yml",
"_pkgdown.yaml",
"pkgdown/_pkgdown.yml",
"pkgdown/_pkgdown.yaml",
"inst/_pkgdown.yml",
"inst/_pkgdown.yaml"
)
)
)
}
uses_pkgdown <- function() {
!is.null(pkgdown_config_path())
}
pkgdown_config_meta <- function() {
if (!uses_pkgdown()) {
return(list())
}
path <- pkgdown_config_path()
yaml::read_yaml(path) %||% list()
}
pkgdown_url <- function(pedantic = FALSE) {
if (!uses_pkgdown()) {
return(NULL)
}
meta <- pkgdown_config_meta()
url <- meta$url
if (!is.null(url)) {
return(url)
}
if (pedantic) {
ui_bullets(c(
"!" = "{.pkg pkgdown} config does not specify the site's {.field url},
which is optional but recommended."
))
}
NULL
}
|