Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

render_docs(autolink = TRUE) uses downlit #273

Merged
merged 22 commits into from
Apr 8, 2024
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/altdoc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ jobs:
install.packages(".", repos = NULL, type = "source")
install.packages("pkgload")
pkgload::load_all()
altdoc::render_docs(parallel = TRUE, freeze = FALSE)
altdoc::render_docs(parallel = FALSE, freeze = FALSE)
shell: Rscript {0}

- name: Deploy to GitHub pages 🚀
Expand Down
3 changes: 2 additions & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Type: Package
Package: altdoc
Title: Package Documentation Websites with 'Quarto', 'Docsify', 'Docute', or 'MkDocs'
Version: 0.3.0.9002
Version: 0.3.0.9003
Authors@R:
c(person(given = "Etienne",
family = "Bacher",
Expand All @@ -24,6 +24,7 @@ Imports:
cli,
desc,
evaluate,
downlit,
fs,
quarto,
tools,
Expand Down
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
execute:
freeze: auto
```
* `render_docs(autolink = TRUE)` uses the `downlit` package to automatically link function calls to their documentation on the web.

### Other changes

Expand Down
30 changes: 30 additions & 0 deletions R/autolink.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
.autolink <- function(path = ".") {
# everyting wrapped in tryCatch() because especially error prone with weird pandoc memory errors
vincentarelbundock marked this conversation as resolved.
Show resolved Hide resolved
html_files <- c(tryCatch(fs::dir_ls(fs::path_join(c(path, "docs/vignettes")), regexp = "\\.html$"), error = function(e) NULL),
tryCatch(fs::dir_ls(fs::path_join(c(path, "docs/man")), regexp = "\\.html$"), error = function(e) NULL))
vincentarelbundock marked this conversation as resolved.
Show resolved Hide resolved
for (h in html_files) {
tmp <- try(downlit::downlit_html_path(h, h), silent = TRUE)
etiennebacher marked this conversation as resolved.
Show resolved Hide resolved
if (inherits(tmp, "try-error")) {
cli::cli_alert_danger(sprintf("Failed to auto-link: %s", h))
}

}
# h <- fs::path_join(c(path, "docs/index.html"))
# if (fs::file_exists(h)) {
# downlit::downlit_html_path(h, h)
# }
vincentarelbundock marked this conversation as resolved.
Show resolved Hide resolved

md_files <- c(
vincentarelbundock marked this conversation as resolved.
Show resolved Hide resolved
tryCatch(fs::dir_ls(fs::path_join(c(path, "docs/vignettes")), regexp = "\\.md$"), error = function(e) NULL),
tryCatch(fs::dir_ls(fs::path_join(c(path, "docs/man")), regexp = "\\.md$"), error = function(e) NULL))
for (m in md_files) {
tmp <- try(downlit::downlit_md_path(m, m), silent = TRUE)
if (inherits(tmp, "try-error")) {
cli::cli_alert_danger(sprintf("Failed to auto-link: %s", h))
}
}
# m <- fs::path_join(c(path, "docs/README.md"))
# if (fs::file_exists(m)) {
# downlit::downlit_html_path(m, m)
# }
vincentarelbundock marked this conversation as resolved.
Show resolved Hide resolved
}
10 changes: 9 additions & 1 deletion R/render_docs.R
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#' @param verbose Logical. Print Rmarkdown or Quarto rendering output.
#' @param parallel Logical. Render man pages and vignettes in parallel using the `future` framework. In addition to setting this argument to TRUE, users must define the parallelism plan in `future`. See the examples section below.
#' @param freeze Logical. If TRUE and a man page or vignette has not changed since the last call to `render_docs()`, that file is skipped. File hashes are stored in `altdoc/freeze.rds`. If that file is deleted, all man pages and vignettes will be rendered anew.
#' @param autolink Logical. TRUE to link function names and calls to web-based documentation. See the Autolink section below for details.
#' @inheritParams setup_docs
#' @export
#'
Expand All @@ -32,6 +33,7 @@
#' @template altdoc_variables
#' @template altdoc_preambles
#' @template altdoc_freeze
#' @template altdoc_autolink
#'
#' @examples
#' if (interactive()) {
Expand All @@ -44,7 +46,7 @@
#' render_docs(parallel = TRUE)
#'
#' }
render_docs <- function(path = ".", verbose = FALSE, parallel = FALSE, freeze = FALSE) {
render_docs <- function(path = ".", verbose = FALSE, parallel = FALSE, freeze = FALSE, autolink = FALSE) {

path <- .convert_path(path)
tool <- .doc_type(path)
Expand Down Expand Up @@ -92,6 +94,7 @@ render_docs <- function(path = ".", verbose = FALSE, parallel = FALSE, freeze =
cli::cli_h1("Vignettes")
fail_vignettes <- .import_vignettes(src_dir = path, tar_dir = docs_dir, tool = tool, verbose = verbose, parallel = parallel, freeze = freeze)


# Error so that CI fails
if (length(fail_vignettes) > 0 & length(fail_man) > 0) {
cli::cli_abort("There were some failures when rendering vignettes and man pages.")
Expand All @@ -104,6 +107,11 @@ render_docs <- function(path = ".", verbose = FALSE, parallel = FALSE, freeze =
cli::cli_h1("Update HTML")
.import_settings(path = path, tool = tool, verbose = verbose, freeze = freeze)

if (isTRUE(autolink)) {
cli::cli_h1("Auto-Link")
.autolink(path)
}

cli::cli_h1("Complete")
cli::cli_alert_success("Documentation updated.")
}
Expand Down
12 changes: 8 additions & 4 deletions R/settings_docute.R
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,10 @@
tmp <- sprintf("{title: '%s', link: '%s'}", titles, fn_vignettes)
tmp <- paste(tmp, collapse = ", ")
sidebar <- paste(sidebar, collapse = "\n")
sidebar <- gsub("\\$ALTDOC_VIGNETTE_BLOCK", "%s", sidebar)
sidebar <- sprintf(sidebar, tmp)
if (isTRUE(grepl("\\$ALTDOC_VIGNETTE_BLOCK", sidebar))) {
sidebar <- gsub("\\$ALTDOC_VIGNETTE_BLOCK", "%s", sidebar)
sidebar <- sprintf(sidebar, tmp)
}
sidebar <- strsplit(sidebar, "\n")[[1]]
} else {
sidebar <- sidebar[!grepl("\\$ALTDOC_VIGNETTE_BLOCK", sidebar)]
Expand All @@ -81,8 +83,10 @@
tmp <- sprintf("{title: '%s', link: '%s'}", titles, fn_man)
tmp <- paste(tmp, collapse = ", ")
sidebar <- paste(sidebar, collapse = "\n")
sidebar <- gsub("\\$ALTDOC_MAN_BLOCK", "%s", sidebar)
sidebar <- sprintf(sidebar, tmp)
if (isTRUE(grepl("\\$ALTDOC_MAN_BLOCK", sidebar))) {
sidebar <- gsub("\\$ALTDOC_MAN_BLOCK", "%s", sidebar)
sidebar <- sprintf(sidebar, tmp)
}
sidebar <- strsplit(sidebar, "\n")[[1]]
} else {
sidebar <- sidebar[!grepl("\\$ALTDOC_MAN_BLOCK", sidebar)]
Expand Down
1 change: 1 addition & 0 deletions R/setup_docs.R
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ setup_docs <- function(tool, path = ".", overwrite = FALSE) {
.add_rbuildignore("^docs$", path = path)
.add_rbuildignore("^altdoc$", path = path)
.add_gitignore("altdoc/freeze.rds", path = path)
.add_pkgdown(path = path)
if (tool == "quarto_website") {
.add_rbuildignore("^_quarto$", path = path)
.add_gitignore("_quarto/*", path = path)
Expand Down
20 changes: 20 additions & 0 deletions R/utils.R
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,26 @@
}


.add_pkgdown <- function(path = ".") {
if (!isTRUE(.dir_is_package(path))) {
stop(".add_pkgdown() must be run from the root of a package.", call. = FALSE)
}
url <- desc::desc_get_urls()
fn <- fs::path_join(c(path, "altdoc/pkgdown.yml"))
if (!fs::file_exists(fn) && length(url) > 0) {
url <- url[1]
vincentarelbundock marked this conversation as resolved.
Show resolved Hide resolved
vig <- fs::path_join(c(url, "vignettes"))
man <- fs::path_join(c(url, "man"))
content <- c(
"urls:",
paste(" reference:", man),
paste(" article:", vig),
"")
cli::cli_alert_info("Adding altdoc/pkgdown.yml file.")
writeLines(content, fn)
}
}


.add_rbuildignore <- function(x = "^docs$", path = ".") {
if (!isTRUE(.dir_is_package(path))) {
Expand Down
3 changes: 3 additions & 0 deletions altdoc/pkgdown.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
urls:
reference: https://altdoc.etiennebacher.com/man
article: https://altdoc.etiennebacher.com/vignettes
2 changes: 1 addition & 1 deletion inst/gha/altdoc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ jobs:
install.packages(".", repos = NULL, type = "source")
install.packages("pkgload")
pkgload::load_all()
altdoc::render_docs(parallel = FALSE, freeze = FALSE)
altdoc::render_docs(parallel = TRUE, freeze = FALSE)
vincentarelbundock marked this conversation as resolved.
Show resolved Hide resolved
shell: Rscript {0}

- name: Deploy to GitHub pages 🚀
Expand Down
9 changes: 9 additions & 0 deletions man-roxygen/altdoc_autolink.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#' @section Auto-link:
#'
#' When the `autolink` argument is `TRUE`, `altdoc` will use the `downlit` package to replace the function names on the package website by links to web-based package documentation. This works for base R libraries and any package published on CRAN.
#'
#' To allow internal links to functions documented by `altdoc`, we need to include links to correct URLs in the `altdoc/pkgdown.yml` file. By default, this file is populated with links to the first URL in the `DESCRIPTION`. When calling `render_docs(autolink=TRUE)`, the `pkgdown.yml` file is moved to the root of the website.
#'
#' Importantly, `downlit` requires the `pkgdown.yml` to be live on the website to create links. This means that links will generally not be updated when making purely local changes. Also, links may not be updated the first time an `altdoc` website is published to the web.
#'
#' Note that the `autolink` argument works best for Quarto-based websites. `mkdocs` appears to ignore `downlit` annotations altogether. `docute` and `docsify` display `downlit` annotations, but CSS styling and code highlighting sometimes suffer.
2 changes: 1 addition & 1 deletion man-roxygen/altdoc_freeze.R
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#' @section Freeze
#' @section Freeze:
#'
#' When working on a package, running `render_docs()` to preview changes can be a time-consuming road block. The argument `freeze = TRUE` tries to improve the experience by preventing rerendering of files that have not changed since the last time `render_docs()` was ran. Note that changes to package internals will not cause a rerender, so rerendering the entire docs can still be necessary.
#'
Expand Down
36 changes: 35 additions & 1 deletion man/render_docs.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

33 changes: 33 additions & 0 deletions tests/testthat/test-render_docs.R
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,39 @@ test_that("quarto: no error for basic workflow", {
})


test_that("quarto: autolink", {
skip_on_cran()
skip_if(.is_windows() && .on_ci(), "Windows on CI")

### setup: create a temp package using the structure of testpkg.altdoc
path_to_example_pkg <- fs::path_abs(test_path("examples/testpkg.altdoc"))
create_local_project()
fs::dir_delete("R")
fs::dir_copy(path_to_example_pkg, ".")
all_files <- list.files("testpkg.altdoc", full.names = TRUE)
for (i in all_files) {
fs::file_move(i, ".")
}
fs::dir_delete("testpkg.altdoc")

### generate docs
install.packages(".", repos = NULL, type = "source")
fs::file_move("README.Rmd", "README.qmd") # special thing quarto
setup_docs("quarto_website")
expect_no_error(render_docs(verbose = .on_ci(), autolink = TRUE))

### Quarto output changes depending on the version, I don't have a solution for
### now.
vincentarelbundock marked this conversation as resolved.
Show resolved Hide resolved

### test
# expect_snapshot(.readlines("docs/index.html"))
# expect_snapshot(.readlines("docs/NEWS.html"))
# expect_snapshot(.readlines("docs/man/hello_base.html"))
# expect_snapshot(.readlines("docs/man/hello_r6.html"))
# expect_snapshot(.readlines("docs/vignettes/test.html"))
})


# Test failures ------------------------------

test_that("render_docs errors if vignettes fail", {
Expand Down
Loading